Language

接口参考 · Reference

后端 API 参考Backend API reference

下列接口覆盖 src/server 下的全部端点,并就地给出每个端点的参数、响应与调用示例。只描述当前接口,不含历史或兼容别名。 The endpoints below cover everything under src/server, and each one lists its parameters, response, and a call example inline. They describe the current API only, with no legacy or compatibility aliases.

通用约定Common conventions

  • 基地址:默认 http://127.0.0.1:8000,端口可用环境变量 PURRCAT_API_PORT 或 main.py --api-port 指定。 Base URL: http://127.0.0.1:8000 by default; override with PURRCAT_API_PORT or main.py --api-port.
  • 数据格式:除文件上传(multipart/form-data)与静态托管外,请求与响应均为 application/json。 Format: JSON in and out, except file uploads (multipart/form-data) and static hosting.
  • 鉴权:仅 ACP 网关(/acp/*)需要,通过请求头 X-PurrCat-Token 携带 ~/.purrcat/acp_token 的内容;其余接口无鉴权(本地优先)。 Auth: only the ACP gateway (/acp/*) needs it, via the X-PurrCat-Token header carrying the contents of ~/.purrcat/acp_token. Everything else is unauthenticated, local-first.
  • 错误:HTTP 状态码 + { "detail": "<reason>" }(FastAPI 默认错误体)。 Errors: an HTTP status plus { "detail": "<reason>" }, FastAPI's default body.
  • 异步语义:/api/chat、/api/chat/batch、/api/chat/compress-memory、/api/config/deploy/{item} 等为后台异步接口,立即返回受理态,实际进度走对应的轮询 / SSE 接口。 Async semantics: /api/chat, /api/chat/batch, /api/chat/compress-memory, and /api/config/deploy/{item} accept and return immediately; poll the matching status or SSE endpoint for progress.

/api/webmin · Minimal-mode plugin system

极简模式插件系统Minimal-mode plugin system/api/webmin

源码:src/server/api/webmin.py | 前缀:/api/webmin | 端点:9 个

极简模式(web-minimal)宿主为纯静态页面(ui/web-minimal),通过本路由获取插件清单、按需读取插件静态文件(热插拔)、持久化宿主配置,并转发插件自带后端的 RPC 调用。宿主专用,插件一般经 callAction 间接使用(见文末「极简宿主与插件的接入方式」)。

约定Conventions

  • 插件来源与优先级:用户插件(~/.purrcat/webmin-plugins,优先级最高)> 沙盒插件({AGENT_VM_DIR}/ui-plugin)> 内置插件(ui/web-minimal/plugins/builtin,只读)。同名 id 先命中者生效。
  • 宿主配置持久化于 ~/.purrcat/settings.json 的 webminConfig,结构为 { "plugins": { plugin_id: config }, "rail": {...}, "active": {...} }。
  • 本文件只新增路由,不修改任何现有 /api/* 路由行为。
  • 所有 /api/webmin 响应经中间件附加 Cache-Control: no-store(便于热插拔与调试)。
GET /api/webmin/manifest 极简宿主清单(面板 / 插件定义)Minimal-host manifest (panels, plugin definitions)

返回当前已扫描到的全部插件列表。新增插件后无需重启,刷新页面即可感知。

请求Request

无请求参数。

响应Response

{
  "plugins": [
    {
      "id": "builtin-history",
      "name": "历史",
      "icon": "history",
      "slot": "panel",
      "slotDef": { "type": "panel", "area": "panel" },
      "entry": "index.html",
      "configSchema": [],
      "config": {},
      "builtin": true,
      "backend": { "kind": "npm" },
      "root": "builtin",
      "origin": "builtin",
      "rootOk": true,
      "dependency": [{ "type": "skill", "id": "xxx" }]
    }
  ],
  "rail": { "stage": 0, "hidden": {}, "opacity": 1 },
  "panelContainer": {},
  "active": { "panel": "builtin-history" }
}

每条插件附:configSchema(插件自声明)与 config(webminConfig 中已存值,有效配置 = schema 默认值 ∪ config 覆盖)、builtin(是否位于内置根)、backend(是否自带后端,有 server/server.js 则为 { "kind": "npm" },否则 null);root(声明的期望位置)、origin(后端回填的实际所在根)、rootOk(两者是否一致);dependency 归一化为 [{ "type", "id" }](类型限定白名单:skill / plugin / mcp / agentloop / sensor / graph);slot 归一化为字符串 id,完整语义见 slotDef。

顶层另返回 rail(最左图标栏状态:stage、hidden、opacity)、panelContainer(宿主中栏容器配置)、active(单例槽当前选中的插件 id)。

示例Example

curl 'http://127.0.0.1:8000/api/webmin/manifest'
POST /api/webmin/plugin-rpc/{plugin_id}/{handler} 调用插件后端处理函数Invoke a plugin's backend handler

调用插件自带后端子进程(server/server.js)的 handler。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
plugin_idpathPathstring是Yes插件 id(不得含 /、\、..)
handlerpathPathstring是Yes后端 handler 名
payloadbodyBodyobject否No传给 handler 的参数,默认 {}
timeoutbodyBodynumber否No超时秒数,默认 30.0

响应Response

{ "status": "ok", "result": {} }

plugin_id 缺失或含非法字符返回 400;插件不存在返回 404 与 { "detail": "插件 <plugin_id> 不存在" };插件进程执行异常(PluginProcessError)返回 502,detail 为异常信息。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/webmin/plugin-rpc/my-plugin/echo' \
  -H 'Content-Type: application/json' \
  -d '{"payload": {"msg": "hi"}, "timeout": 30}'
GET /api/webmin/config 读取极简模式配置Read minimal-mode config

读取插件配置。

请求Request

无请求参数。

响应Response

{ "plugins": { "my-plugin": { "key": "value" } } }

返回 webminConfig 中的插件配置分节;缺失时返回 { "plugins": {} }。

示例Example

curl 'http://127.0.0.1:8000/api/webmin/config'
PUT /api/webmin/config 保存极简模式配置Save minimal-mode config

按分节更新宿主配置(plugins / rail / active),未提供的分节保持原值。前端每次只提交自己修改的分节(例如滑块只提交 plugins),避免局部保存把其他分节意外清空。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pluginsbodyBodyobject否No{ plugin_id: config },整体替换 plugins 分节
railbodyBodyobject否No{ stage, opacity, hidden };stage 归一化到 0–1(越界取 0),opacity 收敛到 0.0–1.0
activebodyBodyobject否No{ area: plugin_id },值归一化为字符串,空值项丢弃

响应Response

{ "status": "ok" }

请求体非 JSON 对象时返回 400 与 { "detail": "请求体必须是 JSON 对象" }。

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/webmin/config' \
  -H 'Content-Type: application/json' \
  -d '{"rail": {"stage": 1, "opacity": 0.9, "hidden": {}}, "active": {"panel": "builtin-history"}}'
POST /api/webmin/plugin/{plugin_id}/delete 删除插件Delete a plugin

删除插件。用户/沙盒插件被移动为各自根目录下的 <id>.trash(可恢复),删除前先停掉其后端子进程;内置插件拒绝删除。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
plugin_idpathPathstring是Yes插件 id(不得含 /、\、..)

响应Response

{ "status": "ok", "deleted": "my-plugin" }

plugin_id 缺失或含非法字符返回 400;位于内置根的插件返回 403 与 { "detail": "内置插件不可删除" };用户/沙盒根下均不存在该插件返回 404 与 { "detail": "插件 <plugin_id> 不存在" }。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/webmin/plugin/my-plugin/delete'
POST /api/webmin/wallpaper 上传壁纸Upload a wallpaper

把用户选择的本地壁纸复制进托管目录 ~/.purrcat/webmin-wallpapers(内容未变则复用已有文件),返回可访问的 URL。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathbodyBodystring是Yes本地壁纸的绝对路径

响应Response

{
  "status": "ok",
  "filename": "wallpaper_a1b2c3d4e5f6.png",
  "url": "/api/webmin/wallpaper/wallpaper_a1b2c3d4e5f6.png"
}

文件不存在返回 404 与 { "detail": "壁纸文件不存在" };扩展名不在允许集合(png/jpg/jpeg/gif/webp/bmp/mp4/webm/mov)返回 400 与 { "detail": "不支持的壁纸格式: <ext>" }。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/webmin/wallpaper' \
  -H 'Content-Type: application/json' \
  -d '{"path": "C:/Users/me/Pictures/wall.png"}'
GET /api/webmin/wallpaper/{filename} 读取壁纸文件Fetch a wallpaper file

静态托管已导入的壁纸文件,做路径穿越校验(filename 不得含 /、\、..)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
filenamepathPathstring是Yes托管目录内的壁纸文件名

响应Response

直接返回文件流(FileResponse)。文件名非法返回 400 与 { "detail": "非法的文件名" };文件不存在返回 404 与 { "detail": "壁纸不存在" }。

示例Example

curl -OJ 'http://127.0.0.1:8000/api/webmin/wallpaper/wallpaper_a1b2c3d4e5f6.png'
GET /api/webmin/plugin/{plugin_id}/{path} 读取插件静态资源Serve plugin static assets

按路径读取插件目录内的静态文件(热插拔核心)。path 省略或未命中文件时,回退到该插件 descriptor 声明的 entry(默认 index.html)。定位在用户/沙盒/内置插件根中依次查找,并做路径穿越校验。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
plugin_idpathPathstring是Yes插件 id
pathpathPathstring否No插件目录内的相对文件路径;省略时回退到 entry

响应Response

直接返回文件流(FileResponse),MIME 由文件扩展名推断。

未命中任何文件(含回退 entry 失败)返回 404 与 { "detail": "插件 <plugin_id> 资源不存在" }。路径穿越(越出插件目录)一律视为未命中。

示例Example

curl 'http://127.0.0.1:8000/api/webmin/plugin/builtin-history/index.html'
GET /api/webmin/plugin-dir/{plugin_id}/{path} 读取插件目录文件Serve files from the plugin directory

列出插件目录内某一层的子项(仅名字与是否为目录),供插件自动扫描自身数据目录。只返回一层、不含文件内容,并做路径穿越校验。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
plugin_idpathPathstring是Yes插件 id
pathpathPathstring否No插件目录内的相对子目录路径;省略时列出插件根目录

响应Response

{
  "path": "data",
  "entries": [
    { "name": "a.json", "isDir": false },
    { "name": "sub", "isDir": true }
  ]
}

以 . 开头的条目被跳过。目录不存在(越界或未定位到)返回 404 与 { "detail": "插件 <plugin_id> 目录不存在" };列目录异常返回 500 与 { "detail": "读取目录失败: <err>" }。

示例Example

curl 'http://127.0.0.1:8000/api/webmin/plugin-dir/my-plugin/data'

极简宿主与插件的接入方式

两条通道

通道适用说明Description
A. callAction 动作总线插件 → 宿主(推荐)经 postMessage 封装,宿主统一收口(原生能力、坐标换算、配置注入)。见下
B. 同源 fetch('/api/...')插件直连后端(高级)插件 iframe 与宿主同源,可直接调用任意 /api/* 接口,稳定性自担

callAction 协议

插件侧(iframe)唯一通道是 postMessage,向后端发送动作请求:

var id = ++seq;
window.parent.postMessage(
  { type: 'callAction', id: id, actionId: 'state.get', payload: {} }, '*'
);

宿主 → 插件(插件侧 window.addEventListener('message', ...) 接收):

消息含义Meaning
`{ type: 'callActionResult', id, ok, data \error }`
{ type: 'configApply', config }用户在设置面板改了配置 → 实时下发全量 config
{ type: 'event', event, data }宿主广播:host.unmount、host.nativeCover({covered})、layout.empty({empty})、session.switched、branch.switched、config.updated

actionId 清单

(完整 payload → data 契约见 ../plugins/ui-plugin.md;实现以宿主 ui/web-minimal/assets/host.js 的 dispatch 为准)

分类actionId
会话/对话chat.send、chat.sendBatch、chat.interrupt、chat.traceToSkill、sessions.list、sessions.new、session.switch、session.rename、session.delete、session.branch、requests.list、requests.resolve
配置config.get(payload {plugin_id})、config.set、settings.meta、settings.open、settings.close
文件/数据dialog.files、dialog.folder、dialog.resolveFiles、dialog.pickWallpaper、ref.graphs
容器(float/modal 插件)slot.move、slot.close、slot.hide
插件自身plugin.delete、plugin.rpc({plugin_id, handler, payload})
内置浏览器(仅 Electron 主窗口)browser.available、browser.newTab、browser.closeTab、browser.navigate、browser.reload、browser.goBack、browser.goForward、browser.bounds、browser.hide、browser.locate、browser.pickStart、browser.pickEnd、browser.pickElement、browser.openExternal、browser.openUrl
其它state.get、session.setDraftParadigm、branch.select

约束

  • 插件只能引用插件目录内的文件;宿主的静态路由做了路径穿越校验。
  • 插件 id 冲突按 用户 > 沙盒 > 内置 生效;想改造内置插件请另起 id。
  • 宿主 CSS 变量不跨 iframe 继承,插件用 var(--wm-*, fallback) 自带兜底。
  • 新增插件或改动 plugin.json 后,用户按 Ctrl+R 刷新即可生效(无需重启应用)。

/api · Sessions & chat

会话与对话Sessions & chat/api

源码:src/server/api/chat.py | 前缀:/api | 端点:17 个

涵盖会话管理(/api/sessions*)、对话受理(/api/chat*)与 Agent Token 用量(/api/agent/token)。其中发送消息、批量发送、记忆压缩、记忆打断等为后台异步接口,立即返回受理态,实际进度走 /api/sessions/{session_id}/status 轮询。会话支持主体 + 子分支结构:main 为主干,其它 branch_id 为隔离子分支,历史读取与删除均按分支区分。

GET /api/sessions 列出会话List sessions

返回全部会话列表,按 updated_at 倒序排列。

响应Response

[
  {
    "id": "session_xxx",
    "alias": "New Session",
    "messages_count": 12,
    "updated_at": "2026-10-14T10:00:00"
  }
]

示例Example

curl 'http://127.0.0.1:8000/api/sessions'
POST /api/sessions/new 新建会话Create a session

新建一个会话,可选指定别名与 Agent Loop(paradigm)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
aliasbodyBodystring否No会话别名,默认 New Session
paradigmbodyBodystring否Noparadigms/ 下的文件名(不带 .yaml);为空则用默认 PARADIGM.yaml

响应Response

{ "id": "session_xxx", "alias": "New Session" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/sessions/new' -H 'Content-Type: application/json' -d '{"alias":"我的会话"}'
GET /api/sessions/{session_id} 读取会话内容Read a session

读取指定会话某分支的聊天历史(过滤掉 system 角色消息)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id
branch_idqueryQuerystring否No分支 id,默认 main

响应Response

返回消息对象数组(role / content 等字段)。当 branch_id 为 main 且为 Agent 当前活跃会话时,取内存最新历史;否则按 branch_id 从磁盘加载对应隔离子分支历史。

示例Example

curl 'http://127.0.0.1:8000/api/sessions/session_xxx?branch_id=main'
GET /api/sessions/{session_id}/branches 列出分支List branches

返回该会话下全部活跃或已完成的子分支元数据。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id

响应Response

{ "main": { "status": "active" } }

分支 id 为键、元数据(含 status)为值;会话不存在或读取异常时回退为 {"main": {"status": "active"}}。

示例Example

curl 'http://127.0.0.1:8000/api/sessions/session_xxx/branches'
GET /api/sessions/{session_id}/status 会话运行状态Session status

轻量级轮询接口:检查该会话的后台 Agent 是否仍活跃运行。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id

响应Response

{
  "is_thinking": true,
  "state": "running",
  "compressing": false,
  "live_reasoning": "",
  "phase": "thinking"
}

phase 取值:thinking(模型推理中)/ processing(工具执行中)/ aborting(打断等待收尾)/ idle(空闲)。当查询的会话不是 Agent 当前挂载会话时,is_thinking 为 false、state 为 idle。

示例Example

curl 'http://127.0.0.1:8000/api/sessions/session_xxx/status'
PUT /api/sessions/{session_id}/rename 重命名会话Rename a session

重命名会话,同步更新会话索引与元数据中的 alias。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id
aliasbodyBodystring是Yes新的会话别名

响应Response

{ "status": "ok" }

失败时返回 500 与 { "detail": "<reason>" }。

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/sessions/session_xxx/rename' -H 'Content-Type: application/json' -d '{"alias":"新名字"}'
POST /api/sessions/{session_id}/checkout 切换分支Check out a branch

检出/切换到指定会话。session_id 必须以 session_ 开头,否则返回 400。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id(须以 session_ 开头)

响应Response

{ "status": "ok" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/sessions/session_xxx/checkout'
POST /api/sessions/{session_id}/branch 创建分支Create a branch

以指定会话为起点新建一个子分支。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes源会话 id
aliasbodyBodystring否No子分支别名,默认 Branch Session

响应Response

{ "id": "session_xxx", "alias": "Branch Session" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/sessions/session_xxx/branch' -H 'Content-Type: application/json' -d '{"alias":"试验分支"}'
GET /api/sessions/{session_id}/paradigm 读取当前范式Current paradigm

读取某会话当前绑定的 Agent Loop(paradigm);空串表示使用默认 PARADIGM.yaml。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id(含 /、\、.. 时返回 400)

响应Response

{ "paradigm": "" }

示例Example

curl 'http://127.0.0.1:8000/api/sessions/session_xxx/paradigm'
POST /api/sessions/{session_id}/paradigm 热切换范式Hot-swap the paradigm

会话暂停时热切换 Agent Loop:只更换循环逻辑,不动系统提示词,保留 KV Cache。paradigm 非法时返回 400。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id
paradigmbodyBodystring否No目标 paradigm 名;为空表示恢复默认 PARADIGM.yaml

响应Response

{ "ok": true, "paradigm": null, "paradigm_path": "..." }

paradigm 为切换后的目标名(为空时返回 null),paradigm_path 为对应 YAML 的落盘路径。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/sessions/session_xxx/paradigm' -H 'Content-Type: application/json' -d '{"paradigm":"MY_LOOP"}'
DELETE /api/sessions/{session_id} 删除会话Delete a session

删除指定会话。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id

响应Response

{ "status": "ok" }

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/sessions/session_xxx'
DELETE /api/sessions/{session_id}/branches/{branch_id} 删除分支Delete a branch

删除指定子分支。先斩断后台任务并等待收敛,再删除分支文件(避免运行中协程再次落盘复活分支);主干分支禁止删除。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idpathPathstring是Yes会话 id
branch_idpathPathstring是Yes分支 id(main 等主干禁止删除)

响应Response

{ "status": "ok" }

分支不存在或禁止删除时返回 400。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/sessions/session_xxx/branches/session_yyy'
POST /api/chat 发送消息(异步)Send a message (async)

向指定会话推送一条用户消息,交由后台 Agent 异步处理。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idbodyBodystring是Yes目标会话 id
messagebodyBodystring是Yes用户消息正文

响应Response

{ "status": "processing", "message": "Message pushed to agent" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/chat' -H 'Content-Type: application/json' -d '{"session_id":"session_xxx","message":"你好"}'
POST /api/chat/batch 批量发送消息Send messages in batch

批量推送多条事件到指定会话。session_id 为空时自动路由到当前活跃会话(供 ChatPage 之外的页面触发)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idbodyBodystring否No目标会话 id;为空时路由到当前活跃会话
eventsbodyBodyarray是Yes事件对象数组(含 type、content 等字段)

响应Response

{
  "status": "processing",
  "processed_events": [
    { "type": "user", "content": "你好" }
  ]
}

processed_events 为做过超长输入缓冲替换(与 force_push_batch 保持一致)后的事件副本。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/chat/batch' -H 'Content-Type: application/json' -d '{"session_id":"session_xxx","events":[{"type":"user","content":"你好"}]}'
POST /api/chat/interrupt 中断当前生成Interrupt generation

人类强制打断:物理掐断 Agent 正在执行的工具(子进程 terminate),隔离旧响应并注入打断提示,Agent 立即回到 idle。

响应Response

{ "status": "ok", "interrupted": true }

status 为 ok(成功打断)或 no_agent(无 Agent 实例);interrupted 为布尔结果。异常时返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/chat/interrupt'
POST /api/chat/compress-memory 压缩记忆(异步)Compress memory (async)

手动触发 Agent 记忆压缩:全局大总结并截断历史上下文。内部需调用 LLM 生成摘要,耗时较长,故放后台任务避免 HTTP 超时。

响应Response

{ "status": "processing" }

异常时返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/chat/compress-memory'
GET /api/agent/token Agent token 用量Agent token usage

获取上下文 Token 使用进度与本会话累计消耗。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
session_idqueryQuerystring否No前端“正在查看”的会话 id;传入且非 Agent 当前挂载会话时返回落盘用量

响应Response

{
  "window_token": 12345,
  "max_token": 500000,
  "consumed_main": 0,
  "consumed_sub": 0,
  "consumed_total": 0
}

window_token 为上下文窗口长度,max_token 为当前模型上限;consumed_* 为本会话累计消耗(含子代理):活跃会话主干取内存实时值,子代理取落盘聚合值,非活跃会话整体取落盘聚合值。异常时回退为 window_token: 0、max_token: 1000000、其余为 0。

示例Example

curl 'http://127.0.0.1:8000/api/agent/token?session_id=session_xxx'

/api/config · Config

配置Config/api/config

源码:src/server/api/config.py | 前缀:/api/config | 端点:29 个

配置文件均落盘在 ~/.purrcat 下(settings.json 为内部全局设置,其余为各模块 JSON)。除 ACP 令牌重置、数据根目录迁移等接口外,均为无鉴权本地接口。

GET /api/config/model 读取模型配置Read model config

读取模型配置(~/.purrcat/model.json)。

请求Request

无参数。

响应Response

{
  "main": {
    "openai:deepseek-flash": {
      "api_keys": [""],
      "base_url": "https://api.deepseek.com",
      "max_token": 500000
    }
  },
  "task": {},
  "vision": {}
}

示例Example

curl 'http://127.0.0.1:8000/api/config/model'
PUT /api/config/model 保存模型配置Save model config

更新模型配置(~/.purrcat/model.json),整体覆盖写入后立即热重载内存中的 Agent。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整模型配置对象,整体覆盖写入,含 main / task / vision 等分段

响应Response

{ "status": "ok", "message": "Model config updated and reloaded successfully" }

保存失败返回 500:{ "detail": "Failed to save model config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/model' \
  -H 'Content-Type: application/json' \
  -d '{"main":{"openai:deepseek-v4-flash":{"base_url":"https://api.deepseek.com","max_token":500000}}}'
GET /api/config/sensor 读取 Sensor 配置Read sensor config

读取传感器配置(~/.purrcat/activate_sensor.json)。结构为「Sensor 名称 → 配置对象」,enabled=false 的项不会拉起。

请求Request

无参数。

响应Response

{
  "my_sensor": { "enabled": true }
}

示例Example

curl 'http://127.0.0.1:8000/api/config/sensor'
PUT /api/config/sensor 保存 Sensor 配置Save sensor config

更新传感器配置(~/.purrcat/activate_sensor.json),整体覆盖写入。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整传感器配置对象,整体覆盖写入

响应Response

{ "status": "ok", "message": "Sensor config updated successfully" }

保存失败返回 500:{ "detail": "Failed to save sensor config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/sensor' \
  -H 'Content-Type: application/json' \
  -d '{"my_sensor":{"enabled":true}}'
POST /api/config/sensor/reload 重载 SensorReload sensors

停止所有运行中的 Sensor 进程,并按 activate_sensor.json 重新拉起启用项(热重启)。

请求Request

无参数。

响应Response

{ "status": "ok", "message": "Sensors reloaded successfully" }

失败返回 500:{ "detail": "热重启失败: <原因>" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/sensor/reload'
GET /api/config/file 读取文件型配置Read file-based config

读取文件权限配置(~/.purrcat/file.json),定义 blocked / readonly / writable 三类路径规则与默认权限。

请求Request

无参数。

响应Response

{
  "default_permission": "readonly",
  "permissions": {
    "blocked": [".git", "src", "node_modules", "miniconda3", ".env"],
    "readonly": [],
    "writable": []
  }
}

示例Example

curl 'http://127.0.0.1:8000/api/config/file'
PUT /api/config/file 保存文件型配置Save file-based config

更新文件权限配置(~/.purrcat/file.json),整体覆盖写入。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整文件配置对象,整体覆盖写入

响应Response

{ "status": "ok", "message": "File config updated successfully" }

保存失败返回 500:{ "detail": "Failed to save file config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/file' \
  -H 'Content-Type: application/json' \
  -d '{"default_permission":"readonly","permissions":{"blocked":[".git"],"readonly":[],"writable":[]}}'
GET /api/config/mcp 读取 MCP 配置Read MCP config

读取 MCP 配置(~/.purrcat/mcp_config.json),标准 mcpServers 结构。

请求Request

无参数。

响应Response

{ "mcpServers": {} }

示例Example

curl 'http://127.0.0.1:8000/api/config/mcp'
PUT /api/config/mcp 保存 MCP 配置Save MCP config

更新 MCP 配置(~/.purrcat/mcp_config.json),整体覆盖写入;改配置后需调用 /mcp/reload 使其生效。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整 MCP 配置对象,整体覆盖写入

响应Response

{ "status": "ok", "message": "MCP config updated successfully" }

保存失败返回 500:{ "detail": "Failed to save MCP config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/mcp' \
  -H 'Content-Type: application/json' \
  -d '{"mcpServers":{}}'
POST /api/config/mcp/reload 重载 MCPReload MCP

重新握手所有 MCP Server(新增项即时拉起、改配置的自动重启子进程),重建 schema 缓存并热更新内存检索树。

请求Request

无参数。

响应Response

{ "status": "ok", "message": "MCP 已重载到内存:检索树已热更新,共 12 个工具" }

失败返回 500:{ "detail": "MCP 重载失败: <原因>" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/mcp/reload'
GET /api/config/app 读取应用配置Read app config

读取应用白名单配置(~/.purrcat/app_config.json)。

请求Request

无参数。

响应Response

{ "GitHub": "https://github.com" }

示例Example

curl 'http://127.0.0.1:8000/api/config/app'
PUT /api/config/app 保存应用配置Save app config

更新应用白名单配置(~/.purrcat/app_config.json),整体覆盖写入。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整应用配置对象,整体覆盖写入

响应Response

{ "status": "ok", "message": "App config updated successfully" }

保存失败返回 500:{ "detail": "Failed to save app config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/app' \
  -H 'Content-Type: application/json' \
  -d '{"GitHub":"https://github.com"}'
GET /api/config/acp 读取 ACP 配置Read ACP config

读取 ACP 接入状态:relay 部署情况、端口与 uv 可用性。

port 是 settings.json 里的用户期望端口;actual_port 是本次运行后端真实 bind 的端口(写在 ~/.purrcat/runtime.json)。后端端口自动 fallback 时两者会不一致,此时 ACP relay按 actual_port 连接,port_mismatch 为 true。

请求Request

无参数。

响应Response

{
  "relay_path": "C:\\Users\\<user>\\.purrcat\\bin\\acp_relay.py",
  "relay_deployed": true,
  "relay_source_found": true,
  "relay_matches_source": true,
  "port": 8000,
  "actual_port": 8001,
  "port_mismatch": true,
  "uv_found": true
}
字段Field类型Type说明Description
portint用户期望端口(settings.json 的 acp_port,未设置时 8000)
actual_portint \null
port_mismatchbool期望端口与实际端口不一致(actual_port 为 null 时为 false)

示例Example

curl 'http://127.0.0.1:8000/api/config/acp'
PUT /api/config/acp 保存 ACP 配置Save ACP config

更新 ACP 接入设置(目前仅后端端口,写入 settings.json 的 acp_port)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
portbodyBodyint否No后端端口,取值 1–65536;缺省则不修改。非法端口返回 400

响应Response

{ "status": "ok", "message": "ACP settings updated" }

保存失败返回 500:{ "detail": "保存 acp_port 失败" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/acp' \
  -H 'Content-Type: application/json' \
  -d '{"port":8000}'
POST /api/config/acp/redeploy 重新部署 ACPRedeploy ACP

重新部署 relay 脚本(文件被误删 / 版本落后时的一键修复,强制覆盖写入 ~/.purrcat/bin/acp_relay.py)。

请求Request

无参数。

响应Response

返回当前 ACP 状态并附加 status:

{
  "relay_path": "C:\\Users\\<user>\\.purrcat\\bin\\acp_relay.py",
  "relay_deployed": true,
  "relay_source_found": true,
  "relay_matches_source": true,
  "port": 8000,
  "uv_found": true,
  "status": "ok"
}

失败返回 500:{ "detail": "部署失败:内置源缺失或写入错误" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/acp/redeploy'
POST /api/config/acp/reset-token 重置 ACP tokenReset the ACP token

重置 ACP 网关 token:删除 ~/.purrcat/acp_token 并立即重新生成。

> ⚠️ 副作用:旧令牌立即失效,客户端侧 relay 需重启后才能用新令牌重连。

请求Request

无参数。

响应Response

{ "status": "ok" }

失败返回 500:{ "detail": "token 重置失败: <原因>" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/acp/reset-token'
GET /api/config/deploy 部署状态总览Deployment overview

获取各依赖项就绪状态 + 部署任务进度与日志,供前端轮询。

请求Request

无参数。

响应Response

{
  "items": {
    "uv": { "ready": true, "detail": "uv x.y.z (C:\\...\\uv.exe)" },
    "node": { "ready": false, "detail": "未检测到 node 命令" },
    "sandbox": { "ready": true, "detail": "..." },
    "embedding": { "ready": false, "detail": "嵌入模型未下载(约 120MB)" }
  },
  "tasks": {
    "uv": { "state": "idle", "log": [], "finished_at": null }
  }
}

示例Example

curl 'http://127.0.0.1:8000/api/config/deploy'
POST /api/config/deploy/{item} 部署某一项(异步)Deploy one item (async)

一键部署指定依赖项,后台线程执行,进度通过 GET /api/config/deploy 轮询。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
itempathPathstring是Yes依赖项标识,取值 uv / node / sandbox / embedding

响应Response

{ "status": "ok", "message": "已开始部署 uv" }

未知项或已在部署中返回 409:{ "detail": "<reason>" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/deploy/uv'
GET /api/config/sandbox-registry 读取沙箱镜像源Read sandbox registry

读取沙箱镜像 registry 前缀(settings.json 的 sandbox_registry)。

请求Request

无参数。

响应Response

{ "sandbox_registry": "" }

示例Example

curl 'http://127.0.0.1:8000/api/config/sandbox-registry'
PUT /api/config/sandbox-registry 保存沙箱镜像源Save sandbox registry

更新沙箱镜像 registry 前缀(写入 settings.json 的 sandbox_registry)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
sandbox_registrybodyBodystring否Noregistry 前缀,如 ghcr.m.daocloud.io;留空 = 自动依次尝试官方与公共源

响应Response

{ "status": "ok" }

保存失败返回 500:{ "detail": "保存 sandbox_registry 失败" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/sandbox-registry' \
  -H 'Content-Type: application/json' \
  -d '{"sandbox_registry":"ghcr.m.daocloud.io"}'
GET /api/config/markdown/{filename} 读取提示词类 markdownRead a markdown profile

读取 ~/.purrcat/core/ 下的 SOUL.md 或 GOAL.md。filename 仅允许 SOUL、GOAL,其余返回 400(防路径穿越);文件不存在时返回空内容。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
filenamepathPathstring是Yes仅允许 SOUL 或 GOAL

响应Response

{ "content": "## 性格\n\n你是一个内向的程序员……" }

示例Example

curl 'http://127.0.0.1:8000/api/config/markdown/SOUL'
PUT /api/config/markdown/{filename} 保存提示词类 markdownSave a markdown profile

保存 ~/.purrcat/core/ 下的 SOUL.md 或 GOAL.md。filename 仅允许 SOUL、GOAL,其余返回 400。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
filenamepathPathstring是Yes仅允许 SOUL 或 GOAL
contentbodyBodystring否NoMarkdown 全文内容,缺省为空串

响应Response

{ "status": "ok", "message": "SOUL.md saved successfully" }

写入失败返回 500:{ "detail": "Failed to save SOUL.md" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/markdown/SOUL' \
  -H 'Content-Type: application/json' \
  -d '{"content":"## 性格\n\n你是一个内向的程序员……"}'
GET /api/config/info 配置信息Config info

读取 ~/.purrcat/core/info.json,提供 skills 与 workshops 列表(文件缺失或解析失败时均返回空列表)。

请求Request

无参数。

响应Response

{ "skills": [], "workshops": [] }

示例Example

curl 'http://127.0.0.1:8000/api/config/info'
GET /api/config/setup-status 初始化状态Setup status

首次启动引导用:数据盘是否已配置(配置过就不再弹引导)。

请求Request

无参数。

响应Response

未配置时:

{ "configured": false, "data_root": "" }

已配置时:

{ "configured": true, "data_root": "D:\\purrcat_data" }

示例Example

curl 'http://127.0.0.1:8000/api/config/setup-status'
POST /api/config/setup-data-root 设定数据根目录Set the data root

首次启动设置数据盘(仅首启引导使用;后续变更走 /change-data-root)。写入 settings.json 的 data_root,重启后生效。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
data_rootbodyBodystring是Yes绝对路径,且不能是磁盘根目录;为空 / 相对路径 / 盘符根均返回 400

响应Response

{ "status": "ok", "data_root": "D:\\purrcat_data", "message": "数据盘设置成功,重启后生效" }

已配置过返回 409:{ "detail": "数据盘已配置,变更请使用配置中心的数据根目录入口" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/setup-data-root' \
  -H 'Content-Type: application/json' \
  -d '{"data_root":"D:\\purrcat_data"}'
POST /api/config/change-data-root 迁移数据根目录Migrate the data root

随时更改数据根目录:搬迁可迁移的大型数据子目录到新位置、落盘 settings.json、销毁旧沙盒容器;前端随后重启生效。

> ⚠️ 副作用:embedding 等大型子目录被整体搬迁;agent_vm 不搬迁(旧盘数据保留在旧位置由用户处置,新位置创建全新空目录);旧沙盒容器 agent_computer 会被销毁(容器内系统变更随之丢失),重启后按新根重建。搬迁中途失败会回滚已移动目录。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
data_rootbodyBodystring是Yes新的绝对路径;需与当前根不同、且两者不能互为父子目录,否则返回 400

响应Response

{
  "status": "ok",
  "data_root": "E:\\purrcat_data",
  "moved": ["embedding"],
  "message": "数据已就绪(agent_vm 已在新位置全新初始化,沙盒容器已销毁,重启后自动重建)"
}

目标位置已存在同名子目录返回 409;搬迁或落盘失败返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/config/change-data-root' \
  -H 'Content-Type: application/json' \
  -d '{"data_root":"E:\\purrcat_data"}'
GET /api/config/cron 读取定时任务配置Read cron config

读取定时任务配置(~/.purrcat/core/cron.json)。文件缺失或解析失败时返回空任务列表。

请求Request

无参数。

响应Response

{ "jobs": [] }

示例Example

curl 'http://127.0.0.1:8000/api/config/cron'
PUT /api/config/cron 保存定时任务配置Save cron config

更新定时任务配置(~/.purrcat/core/cron.json),整体覆盖写入。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
configbodyBodyobject是Yes完整定时配置对象,整体覆盖写入

响应Response

{ "status": "ok", "message": "Cron config updated successfully" }

保存失败返回 500:{ "detail": "Failed to save cron config" }

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/config/cron' \
  -H 'Content-Type: application/json' \
  -d '{"jobs":[]}'
GET /api/config/meta 配置元信息(字段 schema)Config metadata (field schema)

返回当前正在生效的路径常量,便于前端展示给用户参考。

请求Request

无参数。

响应Response

{
  "PURRCAT_DIR": "C:\\Users\\<user>\\.purrcat",
  "DATA_ROOT": "D:\\purrcat_data",
  "BASE_DIR": "D:\\cat-in-cup",
  "settings_path": "C:\\Users\\<user>\\.purrcat\\settings.json",
  "cron_path": "C:\\Users\\<user>\\.purrcat\\core\\cron.json"
}

示例Example

curl 'http://127.0.0.1:8000/api/config/meta'

/api/tools · Tools

工具Tools/api/tools

源码:src/server/api/tools.py | 前缀:/api/tools | 端点:31 个

覆盖 Skill、MCP、Cron、心跳(HEARTBEAT)以及市场(sensors / graphs / ui-plugins / agentloops)等接口。市场类接口统一遵循 registry(拉取官方注册表)、installed(本地已安装列表)、install(安装)、uninstall(卸载)四类命名。

GET /api/tools/skills 列出已安装技能List installed skills

获取内存里已加载的 Skill 名称与描述。

请求Request

无参数。

响应Response

[
  { "name": "示例技能", "description": "技能描述", "dir_name": "example-skill" }
]

示例Example

curl 'http://127.0.0.1:8000/api/tools/skills'
POST /api/tools/skills/install 安装技能Install a skill

根据 GitHub URL 下载第三方 Skill 到本地并热更新内存索引。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
urlbodyBodystring是YesSkill 所在 GitHub tree / blob 地址,如 https://github.com/owner/repo/tree/main/path/to/skill;目标目录内必须包含 SKILL.md,否则报错。链接若直接指向 SKILL.md 等文件,则自动取其所在文件夹

响应Response

{ "status": "success", "message": "Skill 'xxx' 下载成功并已热加载入内存!" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/skills/install' -H 'Content-Type: application/json' -d '{"url":"https://github.com/owner/repo/tree/main/path/to/skill"}'
POST /api/tools/skills/install-batch 批量安装技能Install skills in batch

批量下载多个第三方 Skill 并一次性热更新内存(同一仓库的 zip 只下载一次)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
urlsbodyBodyarray&lt;string&gt;是Yes多个 Skill 的 GitHub tree / blob 地址(规则同 /skills/install,每个目录需含 SKILL.md)

响应Response

{
  "status": "success",
  "installed": ["skill-a", "skill-b"],
  "failed": [{ "path": "path/to/skill", "error": "仓库下载失败: ..." }],
  "message": "批量安装完成:成功 2 个,失败 1 个"
}

status 在有失败项时为 partial,全部成功时为 success。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/skills/install-batch' -H 'Content-Type: application/json' -d '{"urls":["https://github.com/owner/repo/tree/main/skills/a","https://github.com/owner/repo/tree/main/skills/b"]}'
POST /api/tools/skills/uninstall 卸载技能Uninstall a skill

删除本地已安装的 Skill(按目录名或 SKILL.md 的 name 匹配),并热更新内存。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesSkill 目录名或 SKILL.md 中声明的名称

响应Response

{ "status": "success", "message": "Skill 'xxx' 已删除" }

未找到该 Skill 时返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/skills/uninstall' -H 'Content-Type: application/json' -d '{"name":"example-skill"}'
POST /api/tools/skills/refresh 刷新技能索引Refresh the skill index

手动扫描本地 Skill 文件夹并更新内存检索树(并后台重建向量矩阵)。刷新进行中时直接返回受理态。

请求Request

无参数。

响应Response

{ "status": "success", "message": "Skill 已刷新,共加载 12 个技能" }

刷新进行中时:

{ "status": "refreshing", "message": "Skill 正在刷新中,请稍候…" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/skills/refresh'
GET /api/tools/mcp MCP 总览MCP overview

获取内存/缓存里的 MCP 服务器及其包含的工具名称和描述。

请求Request

无参数。

响应Response

以服务器名为键、工具数组为值:

{
  "server_name": [
    { "name": "tool_name", "description": "工具描述" }
  ]
}

示例Example

curl 'http://127.0.0.1:8000/api/tools/mcp'
GET /api/tools/mcp/list 列出 MCP 服务List MCP servers

返回 mcp_config.json 中已配置的 MCP Server 名称列表(供市场“已安装”检测用)。

请求Request

无参数。

响应Response

["server-a", "server-b"]

示例Example

curl 'http://127.0.0.1:8000/api/tools/mcp/list'
POST /api/tools/mcp/install 安装 MCP 服务Install an MCP server

解析并合并用户传入的 MCP Server JSON 配置,落盘到 mcp_config.json 后刷新 Schema 并热更新检索树;官方仓库(PurrPod/mcps)会额外下载源码。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
config_jsonbodyBodystring是Yes合法的 JSON 字符串,顶层键必须为 mcpServers
repobodyBodystring否No源码仓库地址;为官方仓库 PurrPod/mcps 时额外下载对应源码

响应Response

{ "status": "success", "message": "MCP 配置已合并并热加载成功!当前系统共载入 30 个工具。" }

JSON 非法或缺少 mcpServers 顶层键时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/mcp/install' -H 'Content-Type: application/json' -d '{"config_json":"{\"mcpServers\":{\"demo\":{\"command\":\"npx\",\"args\":[\"-y\",\"demo-mcp\"]}}}","repo":""}'
POST /api/tools/mcp/uninstall 卸载 MCP 服务Uninstall an MCP server

从 mcp_config.json 移除该 Server,清理本地源码目录并热更新 Schema。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是Yes要移除的 MCP Server 名称

响应Response

{ "status": "success", "message": "MCP Server 'demo' 已删除" }

未配置该 Server 时返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/mcp/uninstall' -H 'Content-Type: application/json' -d '{"name":"demo"}'
POST /api/tools/mcp/refresh 刷新 MCPRefresh MCP

手动刷新 MCP Schema 并更新内存检索树(并后台重建向量矩阵)。刷新进行中时直接返回受理态。

请求Request

无参数。

响应Response

{ "status": "success", "message": "MCP 缓存已刷新,共加载 30 个工具" }

刷新进行中时:

{ "status": "refreshing", "message": "MCP 正在刷新中,请稍候…" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/mcp/refresh'
GET /api/tools/cron 列出定时任务List cron jobs

读取 cron.json 返回现有闹钟列表。

请求Request

无参数。

响应Response

返回闹钟列表(结构由 list_crons() 决定),形如:

[
  { "id": "xxxx", "title": "喝水提醒", "trigger_time": "2026-10-14 09:00", "repeat_rule": "none", "task_hook": "Agent" }
]

示例Example

curl 'http://127.0.0.1:8000/api/tools/cron'
POST /api/tools/cron 新增 / 更新定时任务Create or update a cron job

添加一个闹钟。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
titlebodyBodystring是Yes闹钟标题
trigger_timebodyBodystring是Yes触发时间
repeat_rulebodyBodystring否No重复规则,默认 none
task_hookbodyBodystring否No到点触发的任务钩子,默认 Agent
task_inputsbodyBodyobject否No传给任务钩子的参数,默认 {}

响应Response

{ "status": "success", "data": { "id": "xxxx" } }

添加失败时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/cron' -H 'Content-Type: application/json' -d '{"title":"喝水提醒","trigger_time":"2026-10-14 09:00","repeat_rule":"none","task_hook":"Agent","task_inputs":{}}'
DELETE /api/tools/cron/{identifier} 删除定时任务Delete a cron job

删除闹钟,identifier 支持传 id 或 title。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
identifierpathPathstring是Yes闹钟的 id 或 title

响应Response

{ "status": "success", "data": { "id": "xxxx" } }

删除失败时返回 400。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/tools/cron/喝水提醒'
GET / POST /api/tools/heartbeat 读取 / 写入心跳配置Read or write heartbeat config

GET:获取心跳配置与 GOAL.md 当前内容;POST:保存心跳配置(开启心跳时必须提交非空 GOAL.md)。

请求Request

GET 无参数。POST:

参数Parameter位置Location类型Type必填Required说明Description
intervalbodyBodyinteger是Yes心跳间隔(秒),最短 60,实际落盘取 max(60, interval)
activebodyBodyboolean是Yes是否开启心跳
goalbodyBodystring否NoGOAL.md 内容;active=true 时必须非空

响应Response

GET:

{ "interval": 300, "active": true, "goal": "# 目标\n..." }

POST:

{ "status": "success", "data": { "interval": 300, "active": true } }

active=true 且 goal 为空时返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/tools/heartbeat'
curl -X POST 'http://127.0.0.1:8000/api/tools/heartbeat' -H 'Content-Type: application/json' -d '{"interval":300,"active":true,"goal":"# 目标\n持续优化项目"}'
GET /api/tools/market/sensors Sensor 市场列表Sensor market list

从官方 PurrPod/sensors 仓库拉取 registry.json 返回给前端市场。

请求Request

无参数。

响应Response

{ "version": "1.0.0", "repository": "PurrPod/sensors", "sensors": [{ "name": "feishu-bot", "description": "..." }] }

拉取失败时返回 502。

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/sensors'
GET /api/tools/market/sensors/installed 已安装 SensorInstalled sensors

返回 activate_sensor.json 中已配置(不论是否 enabled)的传感器列表。

请求Request

无参数。

响应Response

[
  { "name": "feishu-bot", "enabled": true, "has_code": true }
]

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/sensors/installed'
POST /api/tools/market/sensors/install 安装 SensorInstall a sensor

安装 Sensor(支持覆盖式重新下载):合并配置写入 activate_sensor.json(按 name 覆盖,保留用户已填 env),并下载对应代码文件到本地。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
sensorbodyBodyobject是Yesregistry 中的单条 sensor 对象,必须含 name 字段

响应Response

成功:

{ "status": "success", "message": "Sensor 'feishu-bot' 配置已合并,代码已下载到 ...。", "code_downloaded": true }

配置写入成功但代码下载失败时返回 partial,code_downloaded 为 false。缺少 name 时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/sensors/install' -H 'Content-Type: application/json' -d '{"sensor":{"name":"feishu-bot","description":"..."}}'
POST /api/tools/market/sensors/uninstall 卸载 SensorUninstall a sensor

从 activate_sensor.json 移除该 Sensor,并删除本地代码文件。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是Yes要移除的 Sensor 名称

响应Response

{ "status": "success", "message": "Sensor 'feishu-bot' 已删除" }

未配置该 Sensor 时返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/sensors/uninstall' -H 'Content-Type: application/json' -d '{"name":"feishu-bot"}'
GET /api/tools/market/graphs Graph 市场列表Graph market list

从官方 PurrPod/graphs 仓库拉取 registry.json 返回给前端市场。

请求Request

无参数。

响应Response

{ "version": "1.0.0", "repository": "PurrPod/graphs", "graphs": [{ "name": "demo", "files": ["graph.json"] }] }

拉取失败时返回 502。

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/graphs'
GET /api/tools/market/graphs/installed 已安装 GraphInstalled graphs

返回本地 graph 目录下已安装的 Graph(文件夹结构)名字列表。

请求Request

无参数。

响应Response

["demo", "writer"]

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/graphs/installed'
POST /api/tools/market/graphs/install 安装 GraphInstall a graph

安装 Graph(文件夹结构):从 registry 取文件清单逐文件下载落盘;安装前会检查 graph.json 声明的 mcp/skill 依赖,本地缺失的先从市场安装,市场也缺失时跳过。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesGraph 名称

响应Response

{ "status": "success", "message": "Graph 'demo' 已安装到 ...(3 个文件)。已从市场自动安装 MCP 依赖: xxx" }

注册表缺失该 Graph 时返回 404,拉取/下载失败时返回 502。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/graphs/install' -H 'Content-Type: application/json' -d '{"name":"demo"}'
POST /api/tools/market/graphs/uninstall 卸载 GraphUninstall a graph

删除 {GRAPHS_DIR}/{name} 文件夹。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是Yes要删除的 Graph 名称

响应Response

{ "status": "success", "message": "Graph 'demo' 已删除" }

未安装该 Graph 时返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/graphs/uninstall' -H 'Content-Type: application/json' -d '{"name":"demo"}'
GET /api/tools/market/ui-plugins UI 插件市场列表UI-plugin market list

从官方 PurrPod/ui-plugins 仓库拉取 registry.json 返回给前端市场。

请求Request

无参数。

响应Response

{ "version": "1.0.0", "repository": "PurrPod/ui-plugins", "plugins": [{ "name": "hello", "root": "user" }] }

拉取失败时返回 502。

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/ui-plugins'
GET /api/tools/market/ui-plugins/installed 已安装 UI 插件Installed UI plugins

返回已安装的 UI 插件名字列表(用户根 + 沙盒根两个可写根合并去重)。

请求Request

无参数。

响应Response

["hello", "dashboard"]

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/ui-plugins/installed'
POST /api/tools/market/ui-plugins/install 安装 UI 插件Install a UI plugin

安装 UI 插件到其注册表条目声明的 root(user → 用户根、sandbox → 沙盒根),逐文件从官方仓库下载落盘,并按插件声明的 dependency 逐一补齐 skill / mcp / sensor / graph / agentloop / plugin 依赖;依赖缺失或失败只记录说明,不阻断插件本体安装。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesUI 插件名称

响应Response

{ "status": "success", "message": "UI 插件 'hello' 已安装到 ...(4 个文件)。..." }

注册表缺失该插件时返回 404;root 为 builtin(内置插件)时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/ui-plugins/install' -H 'Content-Type: application/json' -d '{"name":"hello"}'
POST /api/tools/market/ui-plugins/uninstall 卸载 UI 插件Uninstall a UI plugin

卸载 UI 插件:在用户根 / 沙盒根中找到该插件目录,移为同根下的 <name>.trash(可恢复)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesUI 插件名称

响应Response

{ "status": "success", "message": "UI 插件 'hello' 已删除" }

未安装该插件时返回 404;名称含 /、\ 或 .. 时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/ui-plugins/uninstall' -H 'Content-Type: application/json' -d '{"name":"hello"}'
GET /api/tools/market/agentloops AgentLoop 市场列表AgentLoop market list

从官方 PurrPod/agentloops 仓库拉取 registry.json 返回给前端市场。

请求Request

无参数。

响应Response

{ "version": "1.0.0", "repository": "PurrPod/agentloops", "agentloops": [{ "name": "demo", "files": ["demo.yaml"] }] }

拉取失败时返回 502。

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/agentloops'
GET /api/tools/market/agentloops/installed 已安装 AgentLoopInstalled agentloops

返回 paradigms 目录下已安装的 AgentLoop 名字列表。

请求Request

无参数。

响应Response

["demo", "writer"]

示例Example

curl 'http://127.0.0.1:8000/api/tools/market/agentloops/installed'
POST /api/tools/market/agentloops/install 安装 AgentLoopInstall an agentloop

安装 AgentLoop(范式 YAML)到 paradigms 目录:从注册表取文件清单逐文件下载落盘,落盘后解析 YAML 校验 hooks;缺失或校验失败会报错。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesAgentLoop 名称

响应Response

{ "status": "success", "message": "AgentLoop 'demo' 已安装到 ...(1 个文件)" }

注册表缺失该 AgentLoop 时返回 404;下载或 YAML 校验失败时返回 502。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/agentloops/install' -H 'Content-Type: application/json' -d '{"name":"demo"}'
POST /api/tools/market/agentloops/uninstall 卸载 AgentLoopUninstall an agentloop

卸载 AgentLoop:删除 paradigms 目录下对应的 YAML(默认 PARADIGM 除外)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namebodyBodystring是YesAgentLoop 名称

响应Response

{ "status": "success", "message": "AgentLoop 'demo' 已删除" }

未安装该 AgentLoop 时返回 404;名称为 PARADIGM(大小写不敏感)或含 /、\、.. 时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tools/market/agentloops/uninstall' -H 'Content-Type: application/json' -d '{"name":"demo"}'

/api/filesystem · Filesystem

文件系统Filesystem/api/filesystem

源码:src/server/api/filesystem.py | 前缀:/api/filesystem | 端点:12 个

面向 IDE Panel / 前端 UI 的文件直连操作(浏览器端降级用)。路径以 /agent_vm 沙盒路径为主,服务端会通过 convert_sandbox_path 自动映射为宿主真实绝对路径,并含沙盒层缺失时的回退查找。文件改动以备份快照(backup_id)+ 未确认变更(diff)为核心:undo 回滚、ack/ack_all 确认清理备份。

GET /api/filesystem/list 列出目录List a directory

列出目录内容,跳过以 . 开头的隐藏项。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathqueryQuerystring是Yes目标目录路径(可为沙盒路径)

响应Response

[
  { "name": "src", "isDir": true, "path": "/agent_vm/src" },
  { "name": "main.py", "isDir": false, "path": "/agent_vm/main.py" }
]

按“目录优先、名称不区分大小写”排序。异常时返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/list?path=/agent_vm'
GET /api/filesystem/read 读取文件Read a file

读取文件文本内容(/agent_vm 沙盒路径自动转换,含 agent_vm 层缺失回退)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathqueryQuerystring是Yes目标文件路径

响应Response

{ "content": "文件文本内容" }

异常时返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/read?path=/agent_vm/README.md'
GET /api/filesystem/stat 路径信息Stat a path

返回文件元信息(大小),供 IDE 做超大文件拦截。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathqueryQuerystring是Yes目标文件路径

响应Response

{ "size": 2048 }

异常时返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/stat?path=/agent_vm/main.py'
POST /api/filesystem/write 写入文件Write a file

写入文件文本内容(自动创建父目录,/agent_vm 沙盒路径自动转换)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathbodyBodystring是Yes目标文件路径
contentbodyBodystring是Yes要写入的文本内容

响应Response

{ "status": "success" }

异常时返回 400。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/filesystem/write' -H 'Content-Type: application/json' -d '{"path":"/agent_vm/notes.txt","content":"hello"}'
GET /api/filesystem/history_list 变更历史Change history

直接读取 .agent_history 目录,返回真实存在的备份文件列表(跳过 .empty 占位文件)。

响应Response

[
  {
    "id": "safe_path@backup_id",
    "path": "/sandbox/path",
    "backup_id": "backup_id",
    "time": ""
  }
]

id 为完整文件名(safe_path@backup_id),path 由安全路径还原为 / 前缀的沙盒路径;time 当前为空串,需前端自行转换。目录不存在时返回空数组。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/history_list'
GET /api/filesystem/backups 备份列表List backups

提供给前端:校验哪些快照仍在硬盘上存活。

响应Response

{ "status": "success", "valid_ids": ["backup_id_1", "backup_id_2"] }

读取异常时返回 { "status": "error", "valid_ids": [] }。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/backups'
POST /api/filesystem/undo 撤销一次变更Undo a change

提供给前端 UI 的一键回滚(最高权限):按 backup_id 将文件还原到指定快照。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathbodyBodystring是Yes目标文件路径
backup_idbodyBodystring是Yes要回滚到的备份快照 id

响应Response

{ "status": "success", "message": "<回滚结果描述>" }

message 为回滚操作的文字结果。失败时返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/filesystem/undo' -H 'Content-Type: application/json' -d '{"path":"/agent_vm/notes.txt","backup_id":"backup_id_1"}'
POST /api/filesystem/ack 确认单条变更Ack one change

用户确认更改:删除该文件在磁盘上的备份,解决空间膨胀。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathbodyBodystring是Yes目标文件路径
backup_idbodyBodystring是Yes要确认的备份快照 id

响应Response

{ "status": "success" }

若当前沙盒解析不到任何备份(文件可能已被外部迁移或销毁),会直接清掉该改动记录并返回:

{ "status": "success", "purged_stale": true }

失败时返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/filesystem/ack' -H 'Content-Type: application/json' -d '{"path":"/agent_vm/notes.txt","backup_id":"backup_id_1"}'
POST /api/filesystem/ack_all 确认全部变更Ack all changes

一键接受全部更改:对所有未确认变更执行 ack,清理全部备份(无请求体)。

响应Response

{ "status": "success", "total": 3, "purged_stale": 0 }

total 为处理的变更总数,purged_stale 为其中被直接清掉记录的陈旧变更数。若存在处理失败项则返回:

{ "status": "partial", "failed": 1, "total": 3 }

失败时返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/filesystem/ack_all'
GET /api/filesystem/diffs 查看文件差异View diffs

提供给前端全局读取所有未确认的代码变更(DiffView)。

响应Response

{ "status": "success", "diffs": [] }

异常时返回 { "status": "error", "diffs": [], "message": "<错误详情>" }。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/diffs'
GET /api/filesystem/resolve 处理冲突Resolve conflicts

返回沙盒/相对路径对应的宿主机真实绝对路径,供前端构造 file:// URL 在内置浏览器中打开本地文件。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathqueryQuerystring是Yes沙盒/相对路径

响应Response

{ "real_path": "D:\\cat-in-cup\\agent_vm\\index.html" }

目标不是文件时返回 404;其它异常返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/resolve?path=/agent_vm/index.html'
GET /api/filesystem/preview 预览文件Preview a file

接收路径并返回文件流供前端预览,绕过浏览器对 file:// 协议的同源与安全限制。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
pathqueryQuerystring是Yes文件路径(绝对路径或沙盒路径)

响应Response

返回 FileResponse 文件流,Content-Type 由 mimetypes 依据文件名推断(无法推断时为 application/octet-stream)。

示例Example

curl 'http://127.0.0.1:8000/api/filesystem/preview?path=/agent_vm/index.html' -o preview.html

/api/evolve · Evolve factory

进化工厂Evolve factory/api/evolve

源码:src/server/api/evolve.py | 前缀:/api/evolve | 端点:12 个

进化工厂(Evolution Factory)管理接口。type 指定加工厂类型:skill(默认)、mcp、sensor、agentloop、graph。每个沙盒按 workplace_id 组织,位于 AGENT_VM_DIR/{type}_workplace/{workplace_id}/ 下。

约定Conventions

  • type 取值:skill | mcp | sensor | agentloop | graph(缺省 "skill")。
  • skill/mcp 的「本体」为 workplace 下同名子目录;sensor 的本体为 workplace 根目录下的单个 <name>.py;agentloop 的本体为 workplace 根目录下的单个 <name>.yaml;graph 的本体为 workplace 下的同名目录(含 graph.json)。
  • POST /api/evolve/test/run 为后台异步接口,立即返回受理态,进度经 /api/evolve/test/iterations、/api/evolve/test/report 轮询。
GET /api/evolve/list 列出进化工作区List evolve workplaces

扫描指定加工厂的沙盒列表。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
typequeryQuerystring否No加工厂类型,默认 skill

响应Response

[
  { "workplace_id": "wp-001", "name": "my-skill", "status": "processing" }
]

返回沙盒数组;无有效本体(未知名称)的沙盒会被跳过。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/list?type=skill'
POST /api/evolve/init 初始化工作区Initialize a workplace

初始化沙盒并分配 workplace。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
typebodyBodystring否No加工厂类型,默认 skill
namebodyBodystring是Yes模块名称
is_upgradebodyBodyboolean是Yes是否为升级(false 为改进)
goalbodyBodystring否No本次构建目标(写入 GOAL.md 并嵌入 GUIDE.md),默认空串
tracebodyBodyboolean否Notrace2skill 入口:为 true 时快照来源会话 Token 到沙盒 trace_meta.json,默认 false
session_idbodyBodystring否No来源会话 ID,配合 trace 使用

响应Response

{
  "status": "success",
  "workplace_id": "wp-001",
  "message": "初始化完成"
}

分配失败(无 workplace_id)返回 400;内部异常返回 500。

当 trace=true 且 type=skill 且有 session_id 时,会把该会话的累计 Token 快照写入 skill_workplace/<workplace_id>/trace_meta.json,随后盲测报告据此对比展示「该技能让后台盲测任务少花了多少 token」。快照失败不影响建厂。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/evolve/init' \
  -H 'Content-Type: application/json' \
  -d '{"type": "skill", "name": "my-skill", "is_upgrade": false, "goal": "补全文档", "trace": true, "session_id": "main"}'
GET /api/evolve/file 读取工作区文件Read a workplace file

读取沙盒内文件;不传 filename 时返回文件树。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
namequeryQuerystring是Yes模块名称
typequeryQuerystring否No加工厂类型,默认 skill
filenamequeryQuerystring否No相对文件名;为空则返回文件列表,默认空串

响应Response

{ "content": "", "attachments": ["SKILL.md", "main.py"] }

filename 为空时返回 attachments(排除 __pycache__ / .venv / node_modules / iteration-* / trigger-* 目录及 .pyc / .png / .jpg 文件,已排序);否则返回 { "content": "<文件文本>" }。工作区或文件不存在返回 404。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/file?workplace_id=wp-001&name=my-skill'
curl 'http://127.0.0.1:8000/api/evolve/file?workplace_id=wp-001&name=my-skill&filename=SKILL.md'
PUT /api/evolve/file 写入工作区文件Write a workplace file

写入沙盒内文件。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
namequeryQuerystring是Yes模块名称
filenamequeryQuerystring是Yes相对文件名
typequeryQuerystring否No加工厂类型,默认 skill
contentbodyBodystring是Yes要写入的文件内容

响应Response

{ "status": "success", "message": "保存成功" }

写入前会自动创建父目录;异常返回 500。

示例Example

curl -X PUT 'http://127.0.0.1:8000/api/evolve/file?workplace_id=wp-001&name=my-skill&filename=SKILL.md' \
  -H 'Content-Type: application/json' \
  -d '{"content": "# My Skill"}'
POST /api/evolve/test/run 运行测试Run tests

启动盲测 / 评测(后台异步)。

每次调用都会新开一代(iteration-N)。skill 类型会把 Trigger 激发测试与盲测一并跑进这一代,不复用最近一代;mcp / sensor 本就按新代归档。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
typebodyBodystring否No加工厂类型,默认 skill
workplace_idbodyBodystring是Yes沙盒工作区 ID
namebodyBodystring是Yes模块名称
session_idbodyBodystring否No会话 ID,默认 main

响应Response

{ "status": "success", "message": "盲测已启动" }

启动异常返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/evolve/test/run' \
  -H 'Content-Type: application/json' \
  -d '{"type": "skill", "workplace_id": "wp-001", "name": "my-skill", "session_id": "main"}'
GET /api/evolve/test/iterations 迭代记录Test iterations

列出评测轮次。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
typequeryQuerystring否No加工厂类型,默认 skill

响应Response

[1, 2, 3]

扫描 iteration-<n> 目录并返回升序轮次编号数组。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/test/iterations?workplace_id=wp-001&type=skill'
GET /api/evolve/test/report 测试报告Test report

读取某轮评测的 HTML 报告页。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
namequeryQuerystring是Yes模块名称
typequeryQuerystring否No加工厂类型,默认 skill
iterationqueryQueryinteger否No轮次;缺省取最新轮次

响应Response

{ "report_html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">...</html>" }

报告统一以自包含的瑞士国际主义风格 HTML 页面输出,各类型同取该轮次目录下的 report.html(skill 为 Trigger + 盲测合并的单一页面)。页面零外部依赖,前端以 iframe 直接承载,故接口不再返回文件清单或 Markdown。无报告时返回 { "report_html": "" }。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/test/report?workplace_id=wp-001&name=my-skill&type=skill'
GET /api/evolve/test/benchmark 基准数据Benchmarks

读取某轮体检的结构化结论(benchmark.json),供前端展示逐条判据与未覆盖项。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
typequeryQuerystring否No加工厂类型,默认 sensor
iterationqueryQueryinteger否No轮次;缺省取最新轮次

响应Response

{ "benchmark": { "criteria": [], "coverage": {} } }

读取 iteration-<n>/benchmark.json;轮次不存在、文件缺失或解析失败均返回 { "benchmark": null }。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/test/benchmark?workplace_id=wp-001&type=sensor'
GET /api/evolve/diff 版本差异Version diff

生成沙盒与正式库的差异(Diff)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idqueryQuerystring是Yes沙盒工作区 ID
namequeryQuerystring是Yes模块名称
typequeryQuerystring否No加工厂类型,默认 skill

响应Response

{ "diff_content": "diff --git ..." }

对比正式库与沙盒:skill 对比 SKILL_DIR/{name},mcp 对比 ./mcps/{name},sensor 对比 {name}.py,agentloop 对比 PARADIGMS_DIR/{name}.yaml,graph 对比 GRAPHS_DIR/{name}。全新模块返回文字说明,无变化返回提示语。异常返回 500。

示例Example

curl 'http://127.0.0.1:8000/api/evolve/diff?workplace_id=wp-001&name=my-skill&type=skill'
POST /api/evolve/handle 处理进化结果Handle an evolve result

处理进化合并请求(人工审批)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
typebodyBodystring否No加工厂类型,默认 skill
workplace_idbodyBodystring是Yes沙盒工作区 ID
namebodyBodystring是Yes模块名称
is_approvedbodyBodyboolean是Yes是否批准
reject_reasonbodyBodystring否No拒绝原因,默认空串

响应Response

{ "status": "success", "message": "合并完成" }

拒绝时(is_approved = false)将拒绝意见写入 REJECT_REASON.md 并返回:

{ "status": "rejected", "message": "已将拒绝意见抛回沙盒,Agent可读取并继续调整。" }

异常返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/evolve/handle' \
  -H 'Content-Type: application/json' \
  -d '{"type": "skill", "workplace_id": "wp-001", "name": "my-skill", "is_approved": true}'
POST /api/evolve/rollback 回滚Roll back

回滚指定模块至上一个 Git 版本。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
typebodyBodystring否No加工厂类型,默认 skill
namebodyBodystring是Yes模块名称

响应Response

{ "status": "success", "message": "回滚成功!'my-skill' 已恢复至上一个版本,并生成了 Rollback Commit。" }

回滚失败或无 Git 历史时返回 400;异常返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/evolve/rollback' \
  -H 'Content-Type: application/json' \
  -d '{"type": "skill", "name": "my-skill"}'
DELETE /api/evolve/workplace/{workplace_id} 删除工作区Delete a workplace

前端手动彻底删除工厂沙盒。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
workplace_idpathPathstring是Yes沙盒工作区 ID
typequeryQuerystring否No加工厂类型,默认 skill

响应Response

{ "status": "success", "message": "沙盒已彻底清理" }

递归删除 workplace 目录(只读文件会先改权限)。沙盒不存在返回 404;异常返回 500。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/evolve/workplace/wp-001?type=skill'

/api/system · System

系统System/api/system

源码:src/server/api/system.py | 前缀:/api/system | 端点:10 个

运行环境探测、容器引擎/镜像状态、环境安装进度、文件上传与 Agent 使用统计。

GET /api/system/env/detect 探测本机环境Detect the local environment

探测运行环境:返回操作系统、已安装的容器引擎及推荐引擎与原因。

请求Request

无请求参数。

响应Response

{
  "os": "Windows",
  "installed": { "docker": true },
  "recommend": "docker",
  "recommend_reason": "检测到已安装 Docker。"
}

示例Example

curl 'http://127.0.0.1:8000/api/system/env/detect'
GET /api/system/env-status 环境状态Environment status

环境状态(完整):检查容器引擎版本并确认 daemon 是否运行,返回是否就绪及错误信息。

请求Request

无请求参数。

响应Response

{
  "is_ready": true,
  "engine": "docker",
  "engine_version": "Docker version 27.x.x, build xxxxx",
  "error": null
}

未就绪时 is_ready 为 false,error 携带原因(如 daemon 未启动)。

示例Example

curl 'http://127.0.0.1:8000/api/system/env-status'
GET /api/system/env/status 环境状态(别名路径)Environment status (alias path)

环境状态(简化):仅按可执行文件是否存在判断。

请求Request

无请求参数。

响应Response

{ "ready": true, "engine": "docker", "has_docker": true }

未检测到 docker 时 ready 为 false、engine 为 null。

示例Example

curl 'http://127.0.0.1:8000/api/system/env/status'
GET /api/system/image-status 镜像状态Image status

查询容器镜像是否已存在。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
image_namequeryQuerystring否No镜像名,默认 my_agent_env:latest

响应Response

{ "exists": true, "image_name": "my_agent_env:latest", "error": null }

镜像不存在时 exists 为 false;docker 缺失或连接失败时 error 携带原因。

示例Example

curl 'http://127.0.0.1:8000/api/system/image-status?image_name=my_agent_env:latest'
POST /api/system/image/pull 拉取镜像Pull an image

后台拉取镜像:立即返回已受理,实际进度通过环境安装进度接口查看。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
image_namebodyBodystring是Yes要拉取的镜像名

响应Response

{ "status": "started", "message": "已开始后台拉取镜像 my_agent_env:latest,请稍候..." }

docker 缺失或连接失败返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/system/image/pull' \
  -H 'Content-Type: application/json' \
  -d '{"image_name": "my_agent_env:latest"}'
POST /api/system/env/install 安装环境依赖Install environment dependencies

触发环境安装:后台异步执行。若已在安装中,则直接返回当前安装态而不会重复触发。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
enginebodyBodystring否No目标引擎,默认 docker

响应Response

{ "status": "started", "message": "开始安装 docker 环境...", "progress": 0 }

已在安装中时返回 {"status": "installing", "message": "正在安装中,请稍候...", "progress": <当前进度>}。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/system/env/install' \
  -H 'Content-Type: application/json' \
  -d '{"engine": "docker"}'
GET /api/system/env/install/status 安装进度Install progress

查询环境安装进度。

请求Request

无请求参数。

响应Response

{ "status": "completed", "message": "安装进行中...", "progress": 100 }

status 取值 idle / installing / completed / failed;失败时 message 携带错误原因。

示例Example

curl 'http://127.0.0.1:8000/api/system/env/install/status'
GET /api/system/container-engine 容器引擎信息Container engine info

获取容器引擎信息:当前引擎、版本、可用引擎与已选引擎。

请求Request

无请求参数。

响应Response

{
  "engine": "docker",
  "version": "Docker version 27.x.x, build xxxxx",
  "available_engines": { "docker": true },
  "selected_engine": "docker"
}

获取失败返回 500。

示例Example

curl 'http://127.0.0.1:8000/api/system/container-engine'
POST /api/system/agent/upload 上传 Agent 包Upload an agent bundle

上传单个文件到 agent_vm/.buffer/upload 目录,供 Agent 读取。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
filebodyBodyfile是Yes上传的文件(multipart/form-data)
filenamequeryQuerystring否No保存文件名;缺省时使用原始文件名或随机名

响应Response

{
  "success": true,
  "saved_path": ".purrcat/agent_vm/.buffer/upload/demo.txt",
  "size_bytes": 1024,
  "agent_path": "D:\\...\\.buffer\\upload\\demo.txt"
}

示例Example

curl -X POST 'http://127.0.0.1:8000/api/system/agent/upload' \
  -F 'file=@./demo.txt' \
  -F 'filename=demo.txt'
GET /api/system/agent/stats Agent 运行统计Agent stats

前端首页调用:返回今日调用统计与历史热力图。

请求Request

无请求参数。

响应Response

{
  "today": { "calls": 12, "total_tokens": 34567, "cached_tokens": 8901 },
  "heatmap": { "2026-10-14": 12, "2026-10-13": 8 }
}

heatmap 的键为日期(YYYY-MM-DD),值为当日调用次数;无统计文件时各项为 0 / 空对象。

示例Example

curl 'http://127.0.0.1:8000/api/system/agent/stats'

/api/tasks · Tasks

任务Tasks/api/tasks

源码:src/server/api/task.py | 前缀:/api/tasks | 端点:10 个

任务的创建、状态查询、指令注入、节点重置与产物读取。状态与记忆同时覆盖内存中的活跃任务与磁盘上的休眠任务。

GET /api/tasks 任务列表List tasks

获取任务列表:合并磁盘上的历史(休眠)任务与内存中的活跃任务,按创建时间降序返回。

请求Request

无请求参数。

响应Response

[
  {
    "id": "tsk_ab12cd34",
    "name": "示例任务",
    "graph_name": "default",
    "state": "running",
    "step": 3,
    "expert_type": "Task",
    "create_time": "2026-10-14 10:00:00",
    "token_usage": 1234,
    "checkpoint_dir": "data/checkpoints/task/demo_tsk_ab12cd34"
  }
]

示例Example

curl 'http://127.0.0.1:8000/api/tasks'
POST /api/tasks/run 运行任务(异步)Run a task (async)

创建并启动新任务:接收工作流(Graph)名称与初始输入参数,抛入后台异步执行后立即返回受理信息。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_namebodyBodystring是Yes任务名称
graph_namebodyBodystring是Yes工作流(Graph)名称
inputsbodyBodyobject否No初始输入参数,默认 {}

响应Response

{
  "status": "success",
  "task_id": "tsk_ab12cd34",
  "message": "Task started in background."
}

任务初始化失败时返回 400(detail 为初始化错误信息),其它异常返回 500。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tasks/run' \
  -H 'Content-Type: application/json' \
  -d '{"task_name": "示例任务", "graph_name": "default", "inputs": {}}'
GET /api/tasks/{task_id}/state 任务状态Task state

获取统一状态,并拼装前端气泡所需的 memory(活跃任务读内存、休眠任务扫磁盘 checkpoint)。响应头带 Cache-Control: no-store。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID

响应Response

{
  "task_id": "tsk_ab12cd34",
  "state": "running",
  "graph": "default",
  "node_states": { "node_1": "running" },
  "outputs": {},
  "node_memory": { "node_1": { "messages": [] } }
}

node_states、outputs 与 node_memory 的具体结构由任务运行时数据决定,此处为示意。任务不存在返回 404。

示例Example

curl 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/state'
POST /api/tasks/{task_id}/submit 提交人工输入Submit human input

注入人工指令。任务须处于活跃状态,否则先按需从磁盘 checkpoint 加载回内存(找不到返回 404)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID
node_idbodyBodystring是Yes目标节点 ID(仅 Agent 类型节点可注入)
contentbodyBodystring是Yes注入的指令内容

响应Response

{ "status": "success", "message": "指令已注入,下游链路状态已重置!" }

注入失败(如节点不存在或非 Agent 节点)返回 400。任务原本未运行时,返回后会自动重启后台引擎。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/submit' \
  -H 'Content-Type: application/json' \
  -d '{"node_id": "node_1", "content": "请补充说明"}'
POST /api/tasks/{task_id}/push 推送流式输出Push streaming output

精确注入:只向指定 Agent 节点注入消息。任务必须已在内存中活跃,否则返回 404。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID
messagebodyBodystring是Yes注入的消息内容
node_idbodyBodystring是Yes目标节点 ID;为空时返回 400(已废弃全局广播注入)

响应Response

{ "status": "success", "message": "指令已精确注入" }

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/push' \
  -H 'Content-Type: application/json' \
  -d '{"node_id": "node_1", "message": "继续下一步"}'
GET /api/tasks/{task_id}/log 任务日志Task log

统一日志读取:直接读纯文本盘,按节点分组,不唤醒休眠引擎。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID

响应Response

{
  "task_id": "tsk_ab12cd34",
  "grouped_logs": {
    "node_1": [ { "node_id": "node_1", "level": "INFO", "message": "..." } ],
    "system": [ { "node_id": "system", "level": "ERROR", "message": "..." } ]
  }
}

无日志时 grouped_logs 为空对象 {}。日志条目结构由任务日志格式决定,此处为示意。

示例Example

curl 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/log'
GET /api/tasks/{task_id}/artifact 下载任务产物Download an artifact

按 purrcat:// URI(或绝对路径兜底)返回任务产物文件,供前端 preview 渲染。URI 非法或文件不存在返回 404。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID
uriqueryQuerystring是Yes产物 purrcat:// URI(解析失败时按绝对路径兜底)
mimequeryQuerystring否No返回文件的 MIME 类型

响应Response

返回文件字节流(FileResponse),响应头带 Content-Security-Policy: sandbox allow-scripts(HTML 类产物强制沙箱)与 Cache-Control: no-store。

示例Example

curl 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/artifact?uri=purrcat://output/result.html&mime=text/html'
DELETE /api/tasks/{task_id} 删除任务Delete a task

物理删除任务,同时支持清理休眠与活跃任务。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID

响应Response

{ "status": "ok", "message": "Task destroyed." }

任务不存在或删除失败返回 404。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34'
POST /api/tasks/{task_id}/nodes/{node_id}/reset 重置节点Reset a node

重置节点:触发级联清理并重启引擎。任务可能已结束或程序重启后不在内存,先按需从 checkpoint 激活。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID
node_idpathPathstring是Yes要重置的节点 ID

响应Response

{ "status": "success", "message": "节点及其下游已彻底重置!" }

节点不存在等错误返回 400,任务无法激活返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/nodes/node_1/reset'
POST /api/tasks/{task_id}/stop 停止任务Stop a task

优雅终止运行中的任务:与 DELETE 不同,只杀死进程、保留 checkpoint 供后续查看。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
task_idpathPathstring是Yes任务 ID

响应Response

{ "status": "success", "message": "Task killed gracefully." }

任务不在活跃状态或不存在返回 404。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/tasks/tsk_ab12cd34/stop'

/api/memory · Memory

记忆Memory/api/memory

源码:src/server/api/memory.py | 前缀:/api/memory | 端点:9 个

记忆系统接口:事件(SQLite + FTS5)、工作经验(VectorDB)、记忆图谱(GraphEngine)的读取与删除,以及 MEMORY.md 的读写。

GET /api/memory/events 事件记忆Event memory

获取最近事件列表(SQLite + FTS5),固定取最近 30 条;读取异常时返回空数组。

请求Request

无请求参数。

响应Response

[
  { "id": "evt_a1b2c3", "content": "示例事件内容", "timestamp": "2026-10-14T10:00:00" }
]

事件字段结构由事件引擎决定,此处为示意;无数据时为 []。

示例Example

curl 'http://127.0.0.1:8000/api/memory/events'
GET /api/memory/experiences 经验记忆Experience memory

获取最近工作经验列表(VectorDB),固定取最近 30 条;读取异常时返回空数组。

请求Request

无请求参数。

响应Response

[
  { "id": "exp_x9y8z7", "title": "示例经验", "content": "……" }
]

经验字段结构由向量引擎决定,此处为示意;无数据时为 []。

示例Example

curl 'http://127.0.0.1:8000/api/memory/experiences'
GET /api/memory/graph 记忆图谱Memory graph

获取记忆图谱,返回节点与边;读取异常时返回 {"nodes": [], "edges": []}。

请求Request

无请求参数。

响应Response

{
  "nodes": [ { "id": "n1", "label": "示例节点" } ],
  "edges": [ { "source": "n1", "target": "n2" } ]
}

节点/边字段结构由图谱引擎决定,此处为示意。

示例Example

curl 'http://127.0.0.1:8000/api/memory/graph'
GET /api/memory/search 检索记忆Search memory

按关键词搜索记忆。q 为空时直接返回空结果;搜索异常时以文本形式返回失败原因。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
qqueryQuerystring否No搜索关键词;为空时返回 {"result": ""}

响应Response

{ "result": "命中的记忆文本……" }

搜索失败时 result 为 搜索失败: <原因>。

示例Example

curl 'http://127.0.0.1:8000/api/memory/search?q=项目配置'
DELETE /api/memory/experiences/{exp_id} 删除一条经验Delete an experience

删除一条工作经验(VectorDB)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
exp_idpathPathstring是Yes工作经验 ID

响应Response

{ "status": "success", "message": "经验已删除" }

经验不存在返回 404,其它异常返回 500。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/memory/experiences/exp_x9y8z7'
DELETE /api/memory/events/{event_id} 删除一条事件Delete an event

删除一条事件(SQLite + FTS5)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
event_idpathPathstring是Yes事件 ID

响应Response

{ "status": "success", "message": "事件已删除" }

事件不存在返回 404,其它异常返回 500。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/memory/events/evt_a1b2c3'
DELETE /api/memory/graph/relation 删除图谱关系Delete a graph relation

物理删除图谱关系边(由源节点与目标节点标识)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
source_node_idqueryQuerystring是Yes源节点 ID
target_node_idqueryQuerystring是Yes目标节点 ID

响应Response

{ "status": "success", "message": "关系边已删除" }

未找到该关系边返回 404,其它异常返回 500。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/memory/graph/relation?source_node_id=n1&target_node_id=n2'
GET / PUT /api/memory/markdown 读取 / 写入记忆 markdownRead or write memory markdown

读取或覆盖写入 .purrcat/core/MEMORY.md 文件内容(基于 AGENT_CORE_DIR)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
contentbodyBodystring否NoPUT 时的写入内容,默认空字符串

GET 无参数;PUT 请求体为 { "content": "<Markdown 文本>" }。

响应Response

GET 返回文件内容:

{ "content": "# 记忆\n……" }

文件不存在时 content 为空字符串。PUT 返回保存结果:

{ "status": "success", "message": "MEMORY.md 已成功落盘保存" }

读写失败均返回 500(detail 携带具体原因)。

示例Example

curl 'http://127.0.0.1:8000/api/memory/markdown'

curl -X PUT 'http://127.0.0.1:8000/api/memory/markdown' \
  -H 'Content-Type: application/json' \
  -d '{"content": "# 记忆\n新的内容"}'

/api/graphs · Graphs

图谱Graphs/api/graphs

源码:src/server/api/graph.py | 前缀:/api/graphs | 端点:5 个

DAG 图谱(工作流)管理接口。每个 Graph 以 {GRAPHS_DIR}/{name}/ 文件夹为单位,核心文件为 graph.json,另有 asset/ 目录存放素材。

约定Conventions

  • 路径参数 {name} 为 Graph 名称(即文件夹名),不含 .json 后缀。
  • 节点类型清单可由 GET /api/graphs/nodes 返回(读取 src/harness/node/extensions/*/*.json 的节点定义)。
  • Graph 中的 global_schema 驱动前端表单:GET /api/graphs/{name}/schema 单独暴露该字段,前端据此动态生成工作流全局输入参数填写表单。
GET /api/graphs/nodes 可用节点类型清单Available node types

获取所有可用的节点类型定义。

请求Request

参数Parameter位置Location类型Type必填Required说明Description

响应Response

[
  {
    "type": "llm",
    "name": "LLM",
    "description": "调用大模型",
    "inputs": {},
    "outputs": {}
  }
]

返回一个数组,元素为节点定义 JSON(来自 src/harness/node/extensions/*/*.json,仅保留含 type 字段的定义)。

示例Example

curl 'http://127.0.0.1:8000/api/graphs/nodes'
GET /api/graphs 图列表List graphs

列出所有 Graph。

请求Request

参数Parameter位置Location类型Type必填Required说明Description

响应Response

[
  {
    "name": "trading",
    "path": "/abs/path/graphs/trading/graph.json"
  }
]

返回数组,元素为 { name, path };仅包含目录下存在 graph.json 的 Graph。

示例Example

curl 'http://127.0.0.1:8000/api/graphs'
GET /api/graphs/{name} 读取图定义Read a graph

读取某个 Graph 的完整定义。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是YesGraph 名称(文件夹名)

响应Response

{
  "nodes": [],
  "edges": [],
  "global_schema": {}
}

返回 graph.json 解析后的对象。若 Graph 不存在或解析失败,返回 404 与 { "detail": "Graph not found" }。

示例Example

curl 'http://127.0.0.1:8000/api/graphs/trading'
GET /api/graphs/{name}/schema 图输入 schemaGraph input schema

获取工作流的全局输入参数 Schema,前端可据此动态生成参数填写表单。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是YesGraph 名称(文件夹名)

响应Response

{
  "graph_name": "trading",
  "global_schema": {
    "symbol": { "required": true, "description": "交易标的" }
  }
}

global_schema 取自 graph.json 的 global_schema 字段(缺失时为空对象 {})。若 Graph 不存在,返回 404 与 { "detail": "Graph not found" }。

示例Example

curl 'http://127.0.0.1:8000/api/graphs/trading/schema'
POST /api/graphs/{name} 保存图定义Save a graph

保存(新建或覆盖)某个 Graph。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是YesGraph 名称(文件夹名)
graph_databodyBodyobject是YesGraph 完整定义的 JSON 对象(原样写入 graph.json)

响应Response

{
  "status": "ok",
  "name": "trading"
}

写出时会创建 {name}/ 目录与 {name}/asset/ 子目录,并以缩进 JSON 覆盖写入 graph.json。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/graphs/trading' \
  -H 'Content-Type: application/json' \
  -d '{"nodes": [], "edges": [], "global_schema": {}}'

/api/paradigms · Paradigms

范式Paradigms/api/paradigms

源码:src/server/api/paradigms.py | 前缀:/api/paradigms | 端点:4 个

PARADIGM(Agent Loop)配置文件管理接口。所有配置存放于 ~/.purrcat/paradigms/ 下,一个文件一个 loop:PARADIGM.yaml 为默认 Agent Loop,其它文件为可切换编辑的备选 loop。

约定Conventions

  • {name} 均为不带 .yaml 后缀的文件名。
  • POST 会整体覆盖写回,天然承担「新建」与「保存」两种语义。
GET /api/paradigms 范式列表List paradigms

列出 paradigms 目录下所有可编辑文件。

请求Request

参数Parameter位置Location类型Type必填Required说明Description

响应Response

{
  "default": "PARADIGM",
  "files": [
    { "name": "PARADIGM", "is_default": true },
    { "name": "coding", "is_default": false }
  ]
}

default 为默认棱式的 base 名;files 列出目录下所有 .yaml 文件(默认文件排在首位)。列出前会确保默认 PARADIGM.yaml 存在。

示例Example

curl 'http://127.0.0.1:8000/api/paradigms'
GET /api/paradigms/{name} 读取范式Read a paradigm

读取某个 paradigm 的完整结构化内容(含 hooks)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是Yesparadigm 名称(不含 .yaml)

响应Response

{
  "name": "PARADIGM",
  "data": {}
}

data 为该 YAML 解析后的完整 dict(顶层元信息 + hooks)。文件不存在返回 404;名称不合法或 YAML 解析失败返回 400。

示例Example

curl 'http://127.0.0.1:8000/api/paradigms/PARADIGM'
POST /api/paradigms/{name} 保存范式Save a paradigm

整体写回(新建 / 保存同一接口)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是Yesparadigm 名称(不含 .yaml)
databodyBodyobject是Yes要写入的 YAML 对象,需置于 { "data": {...} } 中

响应Response

{
  "ok": true,
  "name": "coding",
  "path": "/abs/path/paradigms/coding.yaml"
}

data 非对象或名称不合法时返回 400。写出采用 sort_keys=False 以保留键顺序。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/paradigms/coding' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"name": "coding", "hooks": {}}}'
DELETE /api/paradigms/{name} 删除范式Delete a paradigm

删除指定 paradigm(默认 PARADIGM.yaml 除外)。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
namepathPathstring是Yesparadigm 名称(不含 .yaml)

响应Response

{
  "ok": true,
  "name": "coding"
}

尝试删除默认 PARADIGM 或名称不合法时返回 400。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/paradigms/coding'

/api/requests · Pending requests

待办请求Pending requests/api/requests

源码:src/server/api/request.py | 前缀:/api/requests | 端点:4 个

Agent 审批请求(同意 / 拒绝 / 忽略)的查询与处理。

GET /api/requests 待处理请求Pending requests

获取前端需要弹窗提示的所有待处理请求。返回前会为新请求自动触发 skill_test / sensor_test 的免审测试(测试失败会被静默忽略,不影响返回)。

请求Request

无请求参数。

响应Response

[
  { "id": "req_a1b2c3", "type": "skill_test", "content": "……" }
]

请求条目结构由请求工具层决定,此处为示意;无待处理请求时为 []。查询异常返回 500。

示例Example

curl 'http://127.0.0.1:8000/api/requests'
POST /api/requests/{req_id}/resolve 处理请求Resolve a request

前端点同意、拒绝或忽略时调用。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
req_idpathPathstring是Yes请求 ID
approvedbodyBodyboolean否No是否同意,默认 false
feedbackbodyBodystring否No反馈文本,默认空字符串
ignorebodyBodyboolean否No是否静默忽略,默认 false

响应Response

{ "status": "success", "message": "请求已处理" }

处理失败返回 400(detail 携带原因),其它异常返回 500;具体字段由请求工具层的返回值决定。

示例Example

curl -X POST 'http://127.0.0.1:8000/api/requests/req_a1b2c3/resolve' \
  -H 'Content-Type: application/json' \
  -d '{"approved": true, "feedback": "同意", "ignore": false}'
GET /api/requests/resolved 已处理请求Resolved requests

获取所有已处理完毕的请求。

请求Request

无请求参数。

响应Response

[
  { "id": "req_a1b2c3", "approved": true, "feedback": "同意" }
]

条目结构由请求工具层决定,此处为示意;无记录时为 []。查询异常返回 500。

示例Example

curl 'http://127.0.0.1:8000/api/requests/resolved'
DELETE /api/requests/{req_id} 删除请求Delete a request

彻底删除某个请求记录。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
req_idpathPathstring是Yes请求 ID

响应Response

{ "status": "success", "message": "请求已移除" }

请求未找到返回 404,其它异常返回 500。

示例Example

curl -X DELETE 'http://127.0.0.1:8000/api/requests/req_a1b2c3'

/acp · ACP gateway

ACP 网关ACP gateway/acp

源码:src/server/api/acp.py | 前缀:/acp | 端点:4 个

面向外部频道(Zed 转接 sensor / HTTP 版 sensor)的传输入口,是鉴权薄壳。词汇分发与翻译的唯一实现是 src/server/acp/dispatch.py;stdio 版 sensor 由 src/sensor/bridge.py 同进程直调 dispatch,不经本端点。

约定Conventions

  • 前缀为 /acp(非 /api)。
  • 全部端点均需本地鉴权:请求头携带 X-PurrCat-Token,取值须等于 ~/.purrcat/acp_token 的内容,否则返回 401 与 { "detail": "invalid ACP token" }。
  • 会话标识在 rpc 语境下称 ACP session(映射到 purrcat 会话 id)。
POST /acp/rpc ACP RPC 调用(需 token)ACP RPC call (token required)

JSON-RPC 2.0 单条分发(v1 不做 batch),直接调用 dispatch,返回 dispatch 的 JSON-RPC 结果。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
X-PurrCat-TokenheaderHeaderstring是YesACP 网关令牌
(JSON-RPC 报文)bodyBodyobject是Yes标准 JSON-RPC 2.0 对象,含 jsonrpc、id、method、params

响应Response

{ "jsonrpc": "2.0", "result": {}, "id": 1 }

响应体由 handle_rpc 直接返回,结构随 method 而定;不合法调用按 JSON-RPC 规范返回 error。

示例Example

curl -X POST 'http://127.0.0.1:8000/acp/rpc' \
  -H 'X-PurrCat-Token: <token>' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
GET /acp/stream ACP 事件流(SSE)ACP event stream (SSE)

SSE 事件流:按 ACP session 订阅对应 purrcat 会话的事件流,将内部事件翻译为 ACP 词汇后推送。每 15 秒无事件时发送一行 : keepalive 心跳。支持 session/load 前置流场景(编辑器先连流再发 load):此时映射尚未建立,只要该 id 存在于 purrcat 会话列表即放行订阅。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
X-PurrCat-TokenheaderHeaderstring是YesACP 网关令牌
sessionqueryQuerystring是YesACP 会话 id(同时也是映射前的 purrcat 会话 id)

响应Response

text/event-stream 流,事件名与载荷如下:

event: update
data: {"method":"session/update","params":{"sessionId":"<session>", ...}}

event: turn_end
data: {"stopReason":"end_turn","promptId":"<promptId>", ...}

event: replay_end
data: {"replayDone":true, ...}

event: phase
data: { ... }

session/update 载荷回填 ACP sessionId;turn_end 回填 promptId。会话既不在映射表也不在 purrcat 会话列表时返回 404 与 { "detail": "unknown sessionId: <session>" }。

示例Example

curl -N 'http://127.0.0.1:8000/acp/stream?session=<session>' \
  -H 'X-PurrCat-Token: <token>'
POST /acp/file 上传文件Upload a file

multipart 上传文件,落盘到 agent_vm/sensor/files/acp/,返回可直接在 prompt 里引用的 sandbox 路径。文件名只保留 basename 并清洗 Windows 非法字符以防路径穿越。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
X-PurrCat-TokenheaderHeaderstring是YesACP 网关令牌
fileform-datafile是Yes上传文件(multipart/form-data 字段名 file)
sessionqueryQuerystring否NoACP 会话 id;须为已登记会话,否则 404

响应Response

{
  "path": "/agent_vm/sensor/files/acp/1712345678901_foo.txt",
  "size": 1024
}

session 不在会话登记表中时返回 404 与 { "detail": "unknown sessionId: <session>" }。

示例Example

curl -X POST 'http://127.0.0.1:8000/acp/file?session=<session>' \
  -H 'X-PurrCat-Token: <token>' \
  -F 'file=@./foo.txt'
GET /acp/file 下载文件Download a file

下载 sandbox 文件,仅允许 /agent_vm 前缀路径,防止任意路径读取。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
X-PurrCat-TokenheaderHeaderstring是YesACP 网关令牌
pathqueryQuerystring是Yessandbox 路径,须以 /agent_vm/ 开头

响应Response

直接返回文件流(FileResponse),无 JSON 包装。

路径不以 /agent_vm/ 开头时返回 400 与 { "detail": "only /agent_vm paths allowed" };解析后的宿主机路径未落在 AgentVM 根内或不是普通文件时返回 404 与 { "detail": "file not found" }。

示例Example

curl -OJ 'http://127.0.0.1:8000/acp/file?path=/agent_vm/sensor/files/acp/1712345678901_foo.txt' \
  -H 'X-PurrCat-Token: <token>'

/api/terminal · Terminal WebSocket

终端 WebSocketTerminal WebSocket/api/terminal

源码:src/server/api/terminal.py | 前缀:/api/terminal | 端点:1 个

基于 PTY(伪终端)的终端桥接接口,让 PowerShell/bash 认为自己在跟真终端对话,从而启用 readline、退格、Tab 补全、颜色、提示符等交互特性。Windows 使用 pywinpty(VS Code/Jupyter 同款),*nix 使用标准库 pty + os.fork。

约定Conventions

  • 单条 WebSocket 长连接对应一个 PTY 子进程;连接断开即杀掉该进程及其子进程树。
  • 主程序退出(Ctrl+C / uvicorn shutdown)时会统一清理所有活跃终端子进程。
  • 终端工作目录优先为 AGENT_VM_DIR,创建失败时回退用户主目录。
WS /api/terminal/ws 终端 WebSocketTerminal WebSocket

建立终端桥接连接:接受连接后启动 PTY(交互 shell 或指定命令),双向转发输入输出。

请求Request

参数Parameter位置Location类型Type必填Required说明Description
cmdqueryQuerystring否No不传 → 启动交互 shell;传字符串 → 执行该命令(执行完保持可交互)

消息协议Message protocol

前端 → 服务端(文本帧):

  • 普通文本:作为 stdin 原样写入 PTY。
  • 控制消息:以 \x00(NULL)开头,其后为 JSON。目前仅支持尺寸调整:
"\x00{\"type\":\"resize\",\"cols\":120,\"rows\":30}"

服务端 → 前端(文本帧):

  • PTY 原始输出文本(含 ANSI 转义序列)。
  • 启动失败或运行异常时,以红色 ANSI 包裹的错误文本回传,例如 \r\n\x1b[31m[Failed to spawn] ...\x1b[0m\r\n;失败后连接关闭。

无独立 JSON 响应;交互数据全部经 WebSocket 文本帧双向流动。

示例Example

const ws = new WebSocket('ws://127.0.0.1:8000/api/terminal/ws?cmd=dir');
ws.onmessage = (e) => console.log(e.data);
ws.send('\x00{"type":"resize","cols":120,"rows":30}');
ws.send('echo hello\r');

— · Misc

通用Misc—

源码:main.py | 前缀:/api | 端点:1 个

main.py 中直接注册的通用路由与静态托管,不属于任何 src/server/api/*.py 业务模块。

约定Conventions

  • 应用为 FastAPI(title="PurrCat API System"),CORS 中间件允许全部来源、方法与请求头(本地优先,无鉴权)。
  • 静态文件挂载注册在所有 API 路由之后,避免贪婪前缀匹配遮蔽接口。
GET /api/health 健康检查Health check

健康检查。Electron 生产模式据此轮询后端是否就绪。该路由必须注册在静态挂载之前,否则会被静态挂载吞掉而返回 404。

请求Request

无请求参数。

响应Response

{ "message": "PurrCat Backend is running." }

示例Example

curl 'http://127.0.0.1:8000/api/health'

静态托管与生命周期

  • 极简宿主静态托管:将 ui/web-minimal 目录以 StaticFiles(html=True)挂载到 /minimal(目录存在时)。访问 http://127.0.0.1:8000/minimal 即打开极简模式宿主页面。
  • 极简模式禁用缓存:中间件对以 /minimal 或 /api/webmin 开头的请求追加 Cache-Control: no-store, no-cache, must-revalidate, max-age=0 与 Pragma: no-cache,改动宿主/插件资源后刷新页面即生效。
  • MIME 修正:启动时强制将 .js/.mjs 注册为 text/javascript、.css 注册为 text/css,规避 Windows 注册表误判导致白屏。
  • 生命周期:shutdown 事件会调用 plugin_runtime.stop_all() 停止全部插件后端子进程;终端 PTY 子进程另有退出清理钩子统一回收。