接口参考 · 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:8000by default; override withPURRCAT_API_PORTormain.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 theX-PurrCat-Tokenheader 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
极简模式(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_id | pathPath | string | 是Yes | 插件 id(不得含 /、\、..) |
| handler | pathPath | string | 是Yes | 后端 handler 名 |
| payload | bodyBody | object | 否No | 传给 handler 的参数,默认 {} |
| timeout | bodyBody | number | 否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 |
|---|---|---|---|---|
| plugins | bodyBody | object | 否No | { plugin_id: config },整体替换 plugins 分节 |
| rail | bodyBody | object | 否No | { stage, opacity, hidden };stage 归一化到 0–1(越界取 0),opacity 收敛到 0.0–1.0 |
| active | bodyBody | object | 否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_id | pathPath | string | 是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 |
|---|---|---|---|---|
| path | bodyBody | string | 是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 |
|---|---|---|---|---|
| filename | pathPath | string | 是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_id | pathPath | string | 是Yes | 插件 id |
| path | pathPath | string | 否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_id | pathPath | string | 是Yes | 插件 id |
| path | pathPath | string | 否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
涵盖会话管理(/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 |
|---|---|---|---|---|
alias | bodyBody | string | 否No | 会话别名,默认 New Session |
paradigm | bodyBody | string | 否No | paradigms/ 下的文件名(不带 .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_id | pathPath | string | 是Yes | 会话 id |
branch_id | queryQuery | string | 否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_id | pathPath | string | 是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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 会话 id |
alias | bodyBody | string | 是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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 源会话 id |
alias | bodyBody | string | 否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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 会话 id |
paradigm | bodyBody | string | 否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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 会话 id |
branch_id | pathPath | string | 是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_id | bodyBody | string | 是Yes | 目标会话 id |
message | bodyBody | string | 是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_id | bodyBody | string | 否No | 目标会话 id;为空时路由到当前活跃会话 |
events | bodyBody | array | 是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_id | queryQuery | string | 否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
配置文件均落盘在 ~/.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 |
|---|---|---|---|---|
config | bodyBody | object | 是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 |
|---|---|---|---|---|
config | bodyBody | object | 是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 |
|---|---|---|---|---|
config | bodyBody | object | 是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 |
|---|---|---|---|---|
config | bodyBody | object | 是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 |
|---|---|---|---|---|
config | bodyBody | object | 是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 |
|---|---|---|
port | int | 用户期望端口(settings.json 的 acp_port,未设置时 8000) |
actual_port | int \ | null |
port_mismatch | bool | 期望端口与实际端口不一致(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 |
|---|---|---|---|---|
port | bodyBody | int | 否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 |
|---|---|---|---|---|
item | pathPath | string | 是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_registry | bodyBody | string | 否No | registry 前缀,如 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 |
|---|---|---|---|---|
filename | pathPath | string | 是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 |
|---|---|---|---|---|
filename | pathPath | string | 是Yes | 仅允许 SOUL 或 GOAL |
content | bodyBody | string | 否No | Markdown 全文内容,缺省为空串 |
响应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_root | bodyBody | string | 是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_root | bodyBody | string | 是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 |
|---|---|---|---|---|
config | bodyBody | object | 是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
覆盖 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 |
|---|---|---|---|---|
url | bodyBody | string | 是Yes | Skill 所在 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 |
|---|---|---|---|---|
urls | bodyBody | array<string> | 是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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | Skill 目录名或 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_json | bodyBody | string | 是Yes | 合法的 JSON 字符串,顶层键必须为 mcpServers |
repo | bodyBody | string | 否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 |
|---|---|---|---|---|
name | bodyBody | string | 是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 |
|---|---|---|---|---|
title | bodyBody | string | 是Yes | 闹钟标题 |
trigger_time | bodyBody | string | 是Yes | 触发时间 |
repeat_rule | bodyBody | string | 否No | 重复规则,默认 none |
task_hook | bodyBody | string | 否No | 到点触发的任务钩子,默认 Agent |
task_inputs | bodyBody | object | 否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 |
|---|---|---|---|---|
identifier | pathPath | string | 是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 |
|---|---|---|---|---|
interval | bodyBody | integer | 是Yes | 心跳间隔(秒),最短 60,实际落盘取 max(60, interval) |
active | bodyBody | boolean | 是Yes | 是否开启心跳 |
goal | bodyBody | string | 否No | GOAL.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 |
|---|---|---|---|---|
sensor | bodyBody | object | 是Yes | registry 中的单条 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 |
|---|---|---|---|---|
name | bodyBody | string | 是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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | Graph 名称 |
响应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 |
|---|---|---|---|---|
name | bodyBody | string | 是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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | UI 插件名称 |
响应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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | UI 插件名称 |
响应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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | AgentLoop 名称 |
响应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 |
|---|---|---|---|---|
name | bodyBody | string | 是Yes | AgentLoop 名称 |
响应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
面向 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 |
|---|---|---|---|---|
path | queryQuery | string | 是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 |
|---|---|---|---|---|
path | queryQuery | string | 是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 |
|---|---|---|---|---|
path | queryQuery | string | 是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 |
|---|---|---|---|---|
path | bodyBody | string | 是Yes | 目标文件路径 |
content | bodyBody | string | 是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 |
|---|---|---|---|---|
path | bodyBody | string | 是Yes | 目标文件路径 |
backup_id | bodyBody | string | 是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 |
|---|---|---|---|---|
path | bodyBody | string | 是Yes | 目标文件路径 |
backup_id | bodyBody | string | 是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 |
|---|---|---|---|---|
path | queryQuery | string | 是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 |
|---|---|---|---|---|
path | queryQuery | string | 是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
进化工厂(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 |
|---|---|---|---|---|
| type | queryQuery | string | 否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 |
|---|---|---|---|---|
| type | bodyBody | string | 否No | 加工厂类型,默认 skill |
| name | bodyBody | string | 是Yes | 模块名称 |
| is_upgrade | bodyBody | boolean | 是Yes | 是否为升级(false 为改进) |
| goal | bodyBody | string | 否No | 本次构建目标(写入 GOAL.md 并嵌入 GUIDE.md),默认空串 |
| trace | bodyBody | boolean | 否No | trace2skill 入口:为 true 时快照来源会话 Token 到沙盒 trace_meta.json,默认 false |
| session_id | bodyBody | string | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| name | queryQuery | string | 是Yes | 模块名称 |
| type | queryQuery | string | 否No | 加工厂类型,默认 skill |
| filename | queryQuery | string | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| name | queryQuery | string | 是Yes | 模块名称 |
| filename | queryQuery | string | 是Yes | 相对文件名 |
| type | queryQuery | string | 否No | 加工厂类型,默认 skill |
| content | bodyBody | string | 是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 |
|---|---|---|---|---|
| type | bodyBody | string | 否No | 加工厂类型,默认 skill |
| workplace_id | bodyBody | string | 是Yes | 沙盒工作区 ID |
| name | bodyBody | string | 是Yes | 模块名称 |
| session_id | bodyBody | string | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| type | queryQuery | string | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| name | queryQuery | string | 是Yes | 模块名称 |
| type | queryQuery | string | 否No | 加工厂类型,默认 skill |
| iteration | queryQuery | integer | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| type | queryQuery | string | 否No | 加工厂类型,默认 sensor |
| iteration | queryQuery | integer | 否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_id | queryQuery | string | 是Yes | 沙盒工作区 ID |
| name | queryQuery | string | 是Yes | 模块名称 |
| type | queryQuery | string | 否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 |
|---|---|---|---|---|
| type | bodyBody | string | 否No | 加工厂类型,默认 skill |
| workplace_id | bodyBody | string | 是Yes | 沙盒工作区 ID |
| name | bodyBody | string | 是Yes | 模块名称 |
| is_approved | bodyBody | boolean | 是Yes | 是否批准 |
| reject_reason | bodyBody | string | 否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 |
|---|---|---|---|---|
| type | bodyBody | string | 否No | 加工厂类型,默认 skill |
| name | bodyBody | string | 是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_id | pathPath | string | 是Yes | 沙盒工作区 ID |
| type | queryQuery | string | 否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
运行环境探测、容器引擎/镜像状态、环境安装进度、文件上传与 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_name | queryQuery | string | 否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_name | bodyBody | string | 是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 |
|---|---|---|---|---|
| engine | bodyBody | string | 否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 |
|---|---|---|---|---|
| file | bodyBody | file | 是Yes | 上传的文件(multipart/form-data) |
| filename | queryQuery | string | 否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
任务的创建、状态查询、指令注入、节点重置与产物读取。状态与记忆同时覆盖内存中的活跃任务与磁盘上的休眠任务。
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_name | bodyBody | string | 是Yes | 任务名称 |
| graph_name | bodyBody | string | 是Yes | 工作流(Graph)名称 |
| inputs | bodyBody | object | 否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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 任务 ID |
| node_id | bodyBody | string | 是Yes | 目标节点 ID(仅 Agent 类型节点可注入) |
| content | bodyBody | string | 是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_id | pathPath | string | 是Yes | 任务 ID |
| message | bodyBody | string | 是Yes | 注入的消息内容 |
| node_id | bodyBody | string | 是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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 任务 ID |
| uri | queryQuery | string | 是Yes | 产物 purrcat:// URI(解析失败时按绝对路径兜底) |
| mime | queryQuery | string | 否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_id | pathPath | string | 是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_id | pathPath | string | 是Yes | 任务 ID |
| node_id | pathPath | string | 是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_id | pathPath | string | 是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
记忆系统接口:事件(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 |
|---|---|---|---|---|
| q | queryQuery | string | 否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_id | pathPath | string | 是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_id | pathPath | string | 是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_id | queryQuery | string | 是Yes | 源节点 ID |
| target_node_id | queryQuery | string | 是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 |
|---|---|---|---|---|
| content | bodyBody | string | 否No | PUT 时的写入内容,默认空字符串 |
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
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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | Graph 名称(文件夹名) |
响应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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | Graph 名称(文件夹名) |
响应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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | Graph 名称(文件夹名) |
| graph_data | bodyBody | object | 是Yes | Graph 完整定义的 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
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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | paradigm 名称(不含 .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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | paradigm 名称(不含 .yaml) |
| data | bodyBody | object | 是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 |
|---|---|---|---|---|
| name | pathPath | string | 是Yes | paradigm 名称(不含 .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
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_id | pathPath | string | 是Yes | 请求 ID |
| approved | bodyBody | boolean | 否No | 是否同意,默认 false |
| feedback | bodyBody | string | 否No | 反馈文本,默认空字符串 |
| ignore | bodyBody | boolean | 否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_id | pathPath | string | 是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
面向外部频道(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-Token | headerHeader | string | 是Yes | ACP 网关令牌 |
| (JSON-RPC 报文) | bodyBody | object | 是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-Token | headerHeader | string | 是Yes | ACP 网关令牌 |
| session | queryQuery | string | 是Yes | ACP 会话 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-Token | headerHeader | string | 是Yes | ACP 网关令牌 |
| file | form-data | file | 是Yes | 上传文件(multipart/form-data 字段名 file) |
| session | queryQuery | string | 否No | ACP 会话 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-Token | headerHeader | string | 是Yes | ACP 网关令牌 |
| path | queryQuery | string | 是Yes | sandbox 路径,须以 /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
基于 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 |
|---|---|---|---|---|
| cmd | queryQuery | string | 否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 中直接注册的通用路由与静态托管,不属于任何 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 子进程另有退出清理钩子统一回收。