From 44073b26121d0251e69829cfdcbcfd96c6a5fed0 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:03:28 +0800 Subject: [PATCH 01/47] docs(zh): rewrite the server API reference as typed endpoint and frame entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite docs/zh/reference/server-api.md as a field-level reference: minimal prose, structured tables for every endpoint's body/query/data and non-zero codes, plus one compact example per endpoint. Covers all 104 v1 endpoints (the 101 previously documented plus the new workspaces add-dir route and the two experimental file-history routes), 15 v2 endpoints, and all 80 WS frame types, with a new WebSocket lifecycle section (handshake, one turn, interaction branches, reconnect recovery) and a shared-type dictionary at the bottom. The English page is intentionally left unchanged for now. Corrected against the current server: - GET /sessions/{id} last_seq is now the real event watermark (the old page claimed it was always 0) - the heartbeat behavior is documented (the old page claimed the server sends no heartbeats and never disconnects idle connections) - terminal WS frames are documented as a dead protocol (declared in AsyncAPI, never produced or consumed by the server) - profile agent_config now lists tower_mode / tower_base - message no longer lists the phantom prompt_id / parent_message_id fields (declared in schema, never produced) - the 40911 undo error data shape is marked engine-dependent instead of a fixed object - subscribe payload gains the watch_fs field, and watch_fs_add/remove payload gains runtime_id alongside recursive - event delivery scopes are documented precisely: event.question.*/event.approval.* are session events, event.fs.changed goes only to watchers Moved: - the "用 API 驱动一个会话" walkthrough moves to docs/zh/guides/web.md as a new section (guide-style narrative belongs in a guide; the reference page keeps a link); docs/zh/reference/kimi-command.md now points at the new anchor Omitted: - per-endpoint narrative paragraphs whose facts now live in the same entry's body/data/error tables (compressed, no fact lost) - the rollback-buffer note on the terminal object (it described output replay over the terminal WS channel, which is a dead protocol and is now documented as such) - the fixed 40911 undo data shape {reason, requestedCount, undoableCount} (unverifiable; the server passes through engine details whose shape is not fixed) --- docs/zh/guides/web.md | 59 + docs/zh/reference/kimi-command.md | 2 +- docs/zh/reference/server-api.md | 4490 +++++++++++++++++++---------- 3 files changed, 2963 insertions(+), 1588 deletions(-) diff --git a/docs/zh/guides/web.md b/docs/zh/guides/web.md index 7dc4c623d34..b33ce8a67f7 100644 --- a/docs/zh/guides/web.md +++ b/docs/zh/guides/web.md @@ -91,6 +91,65 @@ Web 里的斜杠命令与 CLI 不完全一致,支持常用指令 `/new`、`/go 确认启动时带了 `--host`(裸写即可),并用横幅中局域网地址(形如 `http://192.168.x.x:58627/#token=...`)访问。仍不通时检查电脑防火墙是否放行了该端口,以及两台设备是否真的在同一网段(访客 WiFi、VPN、4G/5G 热点切换都会造成隔离)。 +## 用 API 驱动一个会话 + +`kimi web` 的服务同时暴露 REST 与 WebSocket 接口(实验性,字段级协议见 [服务 API](../reference/server-api.md))。下面用 curl 走一遍最小流程:确认服务状态 → 创建会话 → 订阅事件 → 提交提示词 → 回读历史。示例假设服务跑在默认地址,token 已存入 shell 变量 `TOKEN`。 + +1. 确认服务状态: + +```sh +curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:58627/api/v1/meta +``` + +所有 JSON 响应都包在统一信封里——`{ "code": 0, "msg": "success", "data": ..., "request_id": "..." }`,业务结果以 `code` 为准(`0` 表示成功),HTTP 状态码只表达传输层结果。 + +2. 创建会话,`metadata.cwd` 指定工作目录: + +```sh +curl -s -X POST http://127.0.0.1:58627/api/v1/sessions \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"metadata": {"cwd": "/path/to/project"}}' +``` + +返回的 `data.id`(形如 `session_...`)就是后续所有请求要用的会话 id。 + +3. 连接 WebSocket 并订阅会话事件。任何 WebSocket 客户端都可以;下面是一个零依赖的 Node.js 脚本(Node.js 22+ 内置 `WebSocket` 客户端): + +```js +// subscribe.mjs —— 用法:TOKEN=... node subscribe.mjs session_... +const ws = new WebSocket('ws://127.0.0.1:58627/api/v1/ws', [ + `kimi-code.bearer.${process.env.TOKEN}`, +]); +ws.onmessage = (e) => console.log(e.data); +ws.onopen = () => + ws.send( + JSON.stringify({ + type: 'subscribe', + id: '1', + payload: { session_ids: [process.argv[2]] }, + }), + ); +``` + +4. 提交提示词: + +```sh +curl -s -X POST http://127.0.0.1:58627/api/v1/sessions//prompts \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"content": [{"type": "text", "text": "用一句话介绍这个仓库"}]}' +``` + +订阅端会依次看到 `turn.started`(轮次开始)→ `assistant.delta`(流式文本增量)→ 发生工具调用时的 `tool.call.started` / `tool.result` → `turn.ended`(轮次结束)。 + +5. 随时可以用 REST 回读历史消息: + +```sh +curl -s -H "Authorization: Bearer $TOKEN" \ + "http://127.0.0.1:58627/api/v1/sessions//messages?page_size=20" +``` + ## 下一步 - [服务 API](../reference/server-api.md) — 面向脚本与第三方集成的 REST / WebSocket 接口(实验性) diff --git a/docs/zh/reference/kimi-command.md b/docs/zh/reference/kimi-command.md index 7239346ef7e..be3d755ef5b 100644 --- a/docs/zh/reference/kimi-command.md +++ b/docs/zh/reference/kimi-command.md @@ -157,7 +157,7 @@ kimi acp 在当前终端前台运行本地 Kimi 服务 —— 同一个进程同时挂载 REST + WebSocket API 与 web UI —— 并在服务就绪后用默认浏览器打开 web UI。命令会一直挂在终端,直到收到 `SIGINT` / `SIGTERM`(如 `Ctrl-C`)时干净退出。 -服务运行时,`GET /openapi.json` 会返回 REST OpenAPI 文档,`GET /asyncapi.json` 会返回本地 WebSocket 协议的 AsyncAPI 文档。用 API 驱动会话的完整流程见[服务 API:用 API 驱动一个会话](./server-api.md#用-api-驱动一个会话),协议细节见[服务 API](./server-api.md)。 +服务运行时,`GET /openapi.json` 会返回 REST OpenAPI 文档,`GET /asyncapi.json` 会返回本地 WebSocket 协议的 AsyncAPI 文档。用 API 驱动会话的完整流程见[在网页中使用:用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话),协议细节见[服务 API](./server-api.md)。 ```sh kimi web # 前台运行服务并打开浏览器 diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 776dadfff78..7c6b7a39f4e 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -1,8 +1,8 @@ # 服务 API -`kimi web` 启动的本地服务暴露两组程序化接口:REST API(`/api/v1`,另有 `/api/v2/sessions` 和 `/api/v2/mcp`)和 WebSocket 事件流(`/api/v1/ws`)。本页是这两组接口的协议参考。如何启动服务及其命令行选项见 [kimi 命令](./kimi-command.md#kimi-web) 参考;端到端的上手流程见下文「[用 API 驱动一个会话](#用-api-驱动一个会话)」。 +`kimi web` 启动的本地服务暴露两组程序化接口:REST API(`/api/v1`,另有 `/api/v2/sessions` 与 `/api/v2/mcp`)和 WebSocket 事件流(`/api/v1/ws`)。本页是这两组接口的协议参考:基础约定、事件时序、全部端点与帧型、共享类型字典。启动服务及其命令行选项见 [kimi 命令](./kimi-command.md#kimi-web);端到端的上手流程见 [用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话)。 -本页是一份经过整理、面向人阅读的参考:下文逐一记录每个端点的参数、请求体与响应结构。每个端点精确的机器可读 schema 以服务的在线规范文档为准:`GET /openapi.json`(OpenAPI)与 `GET /asyncapi.json`(AsyncAPI),两者都由服务运行时实际执行的校验 schema 生成。两者都需要鉴权;当本页与在线规范不一致时,以在线规范为准。 +每个端点精确的机器可读 schema 以服务的在线规范文档为准:`GET /openapi.json`(OpenAPI)与 `GET /asyncapi.json`(AsyncAPI),两者都由服务运行时实际执行的校验 schema 生成,也都需要鉴权。 ::: warning 注意 本页描述的 REST 与 WebSocket API 为实验性特性:不保证接口稳定性,端点、字段与事件类型可能随任何版本更改。集成时请以你所用版本服务的 `/openapi.json` 与 `/asyncapi.json` 文档为准。 @@ -16,7 +16,7 @@ ### 鉴权 -除以下例外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求 bearer token: +除以下例外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求 bearer token(持有方令牌): - `OPTIONS` 预检请求 - `GET /api/v1/healthz`(探活) @@ -28,32 +28,51 @@ ### 响应信封 -所有 JSON 响应统一包在信封里: +所有 JSON 响应统一包在信封(envelope)里;业务结果以 `code` 为准(`0` 表示成功),HTTP 状态码几乎总是 200。 -```json -{ - "code": 0, - "msg": "success", - "data": {}, - "request_id": "01JZX4A6E7M8V0R3Q0N2K2M5Q9" -} -``` +成功信封: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `code` | number | 恒 `0` | +| `msg` | string | 恒 `"success"` | +| `data` | any | 业务负载;少数端点为 `null`(GUI 存储写操作、v2 MCP 的 `auth:complete` / `auth:cancel` / `auth:reset`) | +| `request_id` | string | 请求 id(ULID);客户端可用 `X-Request-Id` 请求头指定,非法值会被服务端重新生成 | + +错误信封: -- `code`:业务结果,`0` 表示成功;错误码分段见下文。 -- `data`:成功时的业务数据。注意部分「错误」信封也携带非空 `data`——例如重复解决审批返回 `40902` 且 `data.resolved` 为 `false`——客户端应先判 `code` 再看 `data`。 -- `request_id`:本次请求的 ULID;客户端可用 `X-Request-Id` 请求头指定,非法值会被服务端重新生成。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `code` | number | 非零业务错误码,段位见 [错误码](#错误码) | +| `msg` | string | 错误消息 | +| `data` | null | 恒 `null`;例外见下文「非零 code 携带 data」 | +| `request_id` | string | 请求 id | +| `stack` | string | 可缺省:服务端 `Error.stack`,多数错误路径会携带 | +| `details` | any | 可缺省:结构化详情,形态按 `code` 分派(见各端点条目) | + +`40001`(输入校验失败)的 `details` 恒为 `{ path, message }[]`——校验问题数组,`path` 为 `.` 连接的字段路径(根级为 `""`),`msg` 取首条。 + +非零 `code` 但 `data` 非 `null` 的特例: -HTTP 状态码几乎总是 200,业务结果以 `code` 为准。例外情况: +| code | 端点 | `data` 形态 | +| --- | --- | --- | +| `40903` | `POST /api/v1/sessions/{id}/prompts`、`POST .../prompts/{prompt_id}:{action}` | `{ "aborted": false }` | +| `40902` | `POST .../approvals/{approval_id}`、`POST .../questions/{question_id}` | `{ "resolved": false }` | +| `40909` | `POST .../questions/{question_id}:dismiss` | `{ "dismissed": true, "dismissed_at" }`——dismiss 成功以非零码返回 | +| `40904` | `POST .../tasks/{task_id}:cancel` | `{ "cancelled": false }`,且 `details` 为 `{ "current_status" }` | +| `40911` | `POST /api/v1/sessions/{id}:undo` | 引擎返回的 details 或 `null`,形态不定 | + +HTTP 状态码例外(非 200): | 场景 | HTTP 状态 | | --- | --- | -| 鉴权失败 / 触发限流 | 401 / 429 | -| 创建供应商、导入供应商目录成功 | 201 | -| 删除供应商成功 | 204 | -| 二进制与流式端点 | 支持时返回 206(Range 分段)/ 304(ETag 未变),各端点能力不同,详见「[二进制与流式端点](#二进制与流式端点)」 | -| `GET /api/v1/files/{file_id}` 下载错误 | 真实 404 / 500(响应体仍为信封) | +| 鉴权失败 / 触发限流 / Host 检查失败 | 401 / 429 / 403 | +| 创建供应商、导入供应商目录成功 | 201(响应体仍是标准信封) | +| 删除供应商成功 | 204(无响应体) | +| 二进制与流式端点 | 200 / 206(Range 分段)/ 304(ETag 未变),能力见 [二进制与流式端点](#二进制与流式端点) | +| `GET /api/v1/files/{file_id}`、`GET .../media/{file_id}` 下载错误 | 真实 404 / 500(响应体仍为信封) | -其中 201 的响应体仍是标准信封(`code` 为 `0`),只是状态行遵循 REST 的资源创建惯例;204 按定义没有响应体,删除成功以状态码本身为准。 +不走信封的端点:四个二进制下载与 zip 导出(见 [二进制与流式端点](#二进制与流式端点))、`DELETE /api/v1/providers/{provider_id}`(204 空体)、web 静态资源(非 `/api` 路径)。 ### 错误码 @@ -72,205 +91,205 @@ HTTP 状态码几乎总是 200,业务结果以 `code` 为准。例外情况: | `500xx` | 服务端内部错误 | `50001` 未捕获异常、`50003` 持久化失败 | | `6xxxx` / `7xxxx` / `8xxxx` | 工具运行时 / LLM 供应商 / MCP 透传错误,`msg` 保留上游原文 | | +完整错误码集:`0` / `40001`–`40005` / `40110`–`40113` / `40401`–`40420` / `40901`–`40929`(无 `40928`)/ `41001`–`41003` / `41301`–`41305` / `42902` / `50001`–`50004` / `60001`–`60002`;另有中间件码 `40101`(鉴权失败)与 `42901`(鉴权限流封禁)。 + +### null 与缺省语义 + +字段表中的「可缺省」与「可空」不等价: + +| 形态 | 语义 | 实例 | +| --- | --- | --- | +| key 缺省(`undefined` 被序列化丢弃) | 「无值 / 不适用」 | `archived_at`、`last_prompt`、大部分可选事件字段 | +| 显式 `null` | 「有键、值为空」 | `GET /api/v1/oauth/login` 无进行中流程、`GET .../goal` 无目标、快照的 `in_flight_turn` | +| 空串 `""` | 「未设置但键存在」 | session 的 `title`、`agent_config.model`、冷会话快照的 `epoch` | +| 空数组 / 空对象 | 「确定为空」 | `permission_rules: []`、`open_in_apps: []`、`queued: []` | +| 恒 0 占位 | 「字段保留但未接线」 | session 的 `usage`(快照除外)、`message_count` | + ### 分页 列表端点有两种分页风格: -- **游标式**:`before_id` / `after_id`(互斥)加 `page_size`(1–100),响应为 `{ items, has_more }`。用于会话列表、消息列表、转录等。 +- **游标式**:`before_id` / `after_id`(互斥)加 `page_size`(1–100),响应为 `{ items, has_more }`。用于会话列表、消息列表、子会话列表;转录分页的游标为 `before_turn` / `after_turn`。 - **`page_token`**:不透明令牌(绑定了查询条件的指纹),用于 `POST /api/v1/search` 与 `GET /api/v2/sessions`。翻页途中改变任何查询条件会使令牌失效:v2 返回 `40922`,search 返回 `40001`。`GET /api/v2/sessions` 另提供无状态的 `page` 页码模式作为替代。 -## 用 API 驱动一个会话 +## WebSocket 时序 -下面用 curl 走一遍最小流程:确认服务状态 → 创建会话 → 订阅事件 → 提交提示词 → 回读历史。示例假设服务跑在默认地址,token 已存入 shell 变量 `TOKEN`。 +事件流端点为 `ws://:/api/v1/ws`,鉴权在升级请求时完成(见 [鉴权](#鉴权))。本节按生命周期梳理帧的到达顺序;各帧型的字段定义见 [WebSocket 帧](#websocket-帧)。 -1. 确认服务状态: +### 连接与握手 -```sh -curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:58627/api/v1/meta -``` +连接建立后服务端立即发送 `server_hello`(携带 `protocol_version` 与 `heartbeat_ms`)。客户端随后可发 `client_hello` 声明身份与初始订阅,再发 `subscribe` 订阅会话事件;每个带 `id` 的入站帧都收到一个 `ack` 应答。保活由服务端驱动:每 `heartbeat_ms`(默认 10000 毫秒)发送 `ping`,客户端回 `pong`;连续两个周期没有任何入站帧,服务端以 `close(1001, 'heartbeat timeout')` 断连。 -所有 JSON 响应都包在统一信封里——`{ "code": 0, "msg": "success", "data": ..., "request_id": "..." }`,业务结果以 `code` 为准(`0` 表示成功),HTTP 状态码只表达传输层结果。 +### 一个轮次的事件顺序 -2. 创建会话,`metadata.cwd` 指定工作目录: +提交提示词的 REST 调用在提示词被接受后立即返回,轮次(turn)进度全部经事件流推送: -```sh -curl -s -X POST http://127.0.0.1:58627/api/v1/sessions \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"metadata": {"cwd": "/path/to/project"}}' +```text +POST /sessions/{id}/prompts → 200(T-PromptItem) + → prompt.submitted + → turn.started + → (turn.step.started → assistant.delta / thinking.delta → tool.call.started → tool.progress → tool.result → turn.step.completed)× N + → turn.ended + → prompt.completed ``` -返回的 `data.id`(形如 `session_...`)就是后续所有请求要用的会话 id。 +流式增量帧(`assistant.delta` / `thinking.delta` 等)是易失(volatile)事件:不落盘、不回放,帧上带 `offset`(该轮次内的累计文本长度)用于对齐;相邻同轮次的增量帧在发送前可能被合并,客户端不能把增量帧当作不可变日志。 -3. 连接 WebSocket 并订阅会话事件。任何 WebSocket 客户端都可以;下面是一个零依赖的 Node.js 脚本(Node.js 22+ 内置 `WebSocket` 客户端): +### 交互:审批与提问 -```js -// subscribe.mjs —— 用法:TOKEN=... node subscribe.mjs session_... -const ws = new WebSocket('ws://127.0.0.1:58627/api/v1/ws', [ - `kimi-code.bearer.${process.env.TOKEN}`, -]); -ws.onmessage = (e) => console.log(e.data); -ws.onopen = () => - ws.send( - JSON.stringify({ - type: 'subscribe', - id: '1', - payload: { session_ids: [process.argv[2]] }, - }), - ); -``` - -4. 提交提示词: +工具调用需要许可或结构化输入时,轮次暂停并等待 REST 答复,解决后事件流继续: -```sh -curl -s -X POST http://127.0.0.1:58627/api/v1/sessions//prompts \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"content": [{"type": "text", "text": "用一句话介绍这个仓库"}]}' +```text +event.approval.requested → POST .../approvals/{approval_id} → event.approval.resolved +event.question.requested → POST .../questions/{question_id}(或 :dismiss)→ event.question.answered(或 event.question.dismissed) ``` -订阅端会依次看到 `turn.started`(轮次开始)→ `assistant.delta`(流式文本增量)→ 发生工具调用时的 `tool.call.started` / `tool.result` → `turn.ended`(轮次结束)。 - -5. 随时可以用 REST 回读历史消息: +### 断线恢复 -```sh -curl -s -H "Authorization: Bearer $TOKEN" \ - "http://127.0.0.1:58627/api/v1/sessions//messages?page_size=20" +重连后在 `subscribe` 的 `cursors` 里带上每个会话最后应用事件的 `{ seq, epoch }`,服务端回放缺口;落后超过事件缓冲(`max_event_buffer_size`,默认 1000 条)、`epoch` 不符或会话被重建时,改为收到 `resync_required`。此时调用 `GET /api/v1/sessions/{session_id}/snapshot` 拿全量快照(含 `as_of_seq` 水位与 `epoch`),再以新游标重新订阅。「水位」(watermark)指事件日志的序列号位置:`seq` 严格递增,同一 `epoch` 内可比较先后。 + +```mermaid +sequenceDiagram + participant C as 客户端 + participant S as 服务 + + Note over C,S: 连接与握手 + C->>S: GET /api/v1/ws(upgrade,Bearer token) + S->>C: server_hello + C->>S: client_hello / subscribe(可带 cursors) + S->>C: ack(accepted、resync_required、cursors) + loop 每 heartbeat_ms + S->>C: ping + C->>S: pong + end + + Note over C,S: 一个轮次 + C->>S: POST /sessions/{id}/prompts + S->>C: 200 信封(T-PromptItem) + S->>C: prompt.submitted → turn.started + loop 每个 step + S->>C: turn.step.started → delta / 工具调用帧 → turn.step.completed + end + S->>C: turn.ended → prompt.completed + + Note over C,S: 交互与恢复 + S->>C: event.approval.requested + C->>S: POST .../approvals/{approval_id} + S->>C: event.approval.resolved + C->>S: subscribe(cursors: {seq, epoch}) + alt 缺口可回放 + S->>C: 回放错过的事件 + else 缓冲溢出 / epoch 不符 / 会话重建 + S->>C: resync_required + C->>S: GET .../snapshot → 以新游标重新订阅 + end ``` ## REST 端点 -下文按资源分组列出端点。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`)。 +下文按资源分组列出全部端点。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 ### 服务与元信息 +服务自身的探活、身份、关停与连接管理。 + | 方法与路径 | 说明 | | --- | --- | | `GET /api/v1/healthz` | 探活,免鉴权 | | `GET /api/v1/meta` | 服务版本、能力集、`server_id`、实验开关 | +| `GET /api/v1/auth` | 鉴权状态快照 | | `POST /api/v1/shutdown` | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 | +| `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | #### `GET /api/v1/healthz` -供脚本与进程管理器使用的探活端点。它是唯一豁免 bearer token 的 `/api` 端点(见 [鉴权](#鉴权)),应答时不触碰配置与引擎。 - -成功时 `data` 为 `{ "ok": true }`。 +供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。 -#### `GET /api/v1/meta` - -返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析,因此开关翻转或某个 feature 失败会体现在下一次响应中。 - -成功时 `data` 携带: +**data**(code = 0): | 字段 | 类型 | 说明 | | --- | --- | --- | -| `server_version` | string | 服务版本 | -| `capabilities` | object | 能力集——`websocket`、`file_upload`、`fs_query`、`mcp`、`tasks`、`terminal`,均恒为 `true` | -| `server_id` | string | 本服务实例的唯一 id | -| `started_at` | string | 启动时间,ISO 8601 格式 | -| `open_in_apps` | array | 可作为 `open-in` 目标的宿主应用(`finder` / `cursor` / `vscode` / `iterm` / `terminal`);目前恒为空 | -| `dangerous_bypass_auth` | boolean | 服务是否以 `--dangerous-bypass-auth` 启动(客户端可跳过 token 提示) | -| `backend` | string | 引擎后端,`v1` 或 `v2`;本服务恒为 `v2` | -| `web_title` | string | 来自 `--web-title` 的自定义浏览器标签页标题;未设置时省略 | -| `experimental_flags` | object | 实验开关 id → 是否启用,按请求时解析 | -| `features` | array | 引擎 feature,形如 `{ name, state, meta }`;`state` 为 `Pending` / `Activating` / `Active` / `Unloading` / `Failed` | +| `ok` | boolean | 恒 `true` | -#### `POST /api/v1/shutdown` - -请求服务优雅退出。响应先发出,随后立即执行关闭,因此调用方可以信任收到的响应。该路由仅在 loopback 绑定时挂载——非 loopback 绑定时它根本不会被注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。 - -成功时 `data` 为 `{ "ok": true }`。 - -### 登录与用量 - -这组端点驱动托管 Kimi OAuth 登录的生命周期,并暴露账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/auth` | 鉴权状态快照 | -| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | -| `GET /api/v1/oauth/login` | 轮询登录流程状态 | -| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | -| `POST /api/v1/oauth/logout` | 登出托管供应商 | -| `GET /api/v1/oauth/usage` | 套餐用量与限额 | -| `GET /api/v1/oauth/userinfo` | 账号资料 | -| `GET /api/v1/oauth/region` | 解析客户端所属区域(`mainland-cn` / `global`) | +**示例**: -#### `GET /api/v1/auth` - -鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。当全局 `default_model` 别名存在于模型表中且能解析到已配置的供应商时,`models_ready` 为 `true`——包括自带 `base_url` 的平铺(providerless)模型,以及通过 `KIMI_MODEL_*` 环境变量注入的模型。它不做凭据校验,因此此后的对话请求仍可能以 `40111` / `40112` 失败。 - -成功时 `data` 携带 `models_ready`(布尔值)、`providers_count`(已配置供应商数量)与 `managed_provider`(`null`,或 `{ name, status }`,其中 `status` 为 `authenticated` / `expired` / `revoked` / `unauthenticated` 之一)。全局默认模型别名本身改从 `GET /api/v1/config` 的 `default_model` 读取,本端点不再携带。 - -#### `POST /api/v1/oauth/login` - -为托管供应商发起 OAuth device-code 登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 - -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | body | string | 托管供应商名称。默认 `managed:kimi-code` | -| `region` | body | string | `mainland-cn` 或 `global`;覆盖 `GET /api/v1/oauth/region` 一节描述的区域解析结果,仅对本次流程生效 | - -成功时 `data` 有两种形态。进行中的流程——`{ flow_id, provider, status: "pending", verification_uri, verification_uri_complete, user_code, expires_in, interval, expires_at }`:打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`,直到流程完结或超过 `expires_at`(`expires_in` 是以秒表示的同一时限)。已登录的快速路径——`{ flow_id, provider, status: "authenticated" }`。 - -#### `GET /api/v1/oauth/login` - -轮询某供应商的登录流程状态。尚未发起过流程时返回 `null`。 +```json +{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | query | string | 托管供应商名称。默认 `managed:kimi-code` | +#### `GET /api/v1/meta` -成功时 `data` 为 `null` 或流程快照:`{ flow_id, provider, status, verification_uri, verification_uri_complete, user_code, expires_in, expires_at, interval }`,其中 `status` 为 `pending` / `authenticated` / `denied` / `expired` / `cancelled`。流程离开 `pending` 后,`resolved_at` 记录其到达终态的时间,`error_message` 描述失败的流程。 +返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 -#### `DELETE /api/v1/oauth/login` +**data**(code = 0): -取消某供应商进行中的登录流程。没有进行中的流程时,该调用为空操作,返回最近一次已知状态。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `server_version` | string | 服务版本 | +| `capabilities` | object | 恒 `{ "websocket": true, "file_upload": true, "fs_query": true, "mcp": true, "tasks": true, "terminal": true }` | +| `server_id` | string | 本次启动生成的 ULID | +| `started_at` | string | 启动时间,ISO 8601 | +| `open_in_apps` | array | 恒 `[]` | +| `dangerous_bypass_auth` | boolean | 服务是否以 `--dangerous-bypass-auth` 启动 | +| `backend` | string | 恒 `"v2"` | +| `web_title` | string | 可缺省:`--web-title` 自定义标题,未设置时不出现 | +| `experimental_flags` | object | 实验开关 id → 是否启用 | +| `features` | array | 引擎 feature 单元,形如 `{ name, state, meta }`;`state` 为 `Pending` / `Activating` / `Active` / `Unloading` / `Failed` | + +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | query | string | 托管供应商名称。默认 `managed:kimi-code` | +```json +{ + "code": 0, "msg": "success", + "data": { "server_version": "0.40.0", "capabilities": { "websocket": true, "...": true }, "server_id": "01JZX4...", "started_at": "2026-09-02T08:00:00.000Z", "open_in_apps": [], "dangerous_bypass_auth": false, "backend": "v2", "experimental_flags": { "search_worker": true }, "features": [ { "name": "fileHistory", "state": "Active", "meta": {} } ] }, + "request_id": "01JZX4..." +} +``` -成功时 `data` 为 `{ cancelled, status }`:只有确实中止了一个 `pending` 流程时 `cancelled` 才为 `true`,`status` 为调用后的流程状态。 +#### `GET /api/v1/auth` -#### `POST /api/v1/oauth/logout` +鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 -登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除(见下文 `PUT` / `DELETE /api/v1/providers/{provider_id}`),因此要移除它需先登出。 +**data**(code = 0):[T-AuthSummary](#t-authsummary)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | body | string | 托管供应商名称。默认 `managed:kimi-code` | +**示例**: -成功时 `data` 为 `{ logged_out: true, provider }`。 +```json +{ "code": 0, "msg": "success", "data": { "models_ready": true, "providers_count": 1, "managed_provider": { "name": "managed:kimi-code", "status": "authenticated" } }, "request_id": "01JZX4..." } +``` -#### `GET /api/v1/oauth/usage` +#### `POST /api/v1/shutdown` -托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让信封失败——它以 `kind: "error"` 的形式带内返回。 +请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | query | string | 托管供应商名称。默认 `managed:kimi-code` | +**data**(code = 0):`{ "ok": true }`。 -成功时 `data` 为 `{ kind: "ok", summary, limits, extra_usage }` 或 `{ kind: "error", message, status? }`,其中 `status` 为上游 HTTP 状态码(如存在)。在 `ok` 形态中,`summary`(可空)是主配额行,`limits` 列出每个配额窗口;一行的结构为 `{ name?, window?, used, limit, reset_at? }`,其中 `window` 为 `{ duration, unit }`,`unit` 为 `minute` / `hour` / `day` / `week` 之一。`extra_usage`(可空)是按量付费钱包:`{ balance_cents, total_cents, monthly_charge_limit_enabled, monthly_charge_limit_cents, monthly_used_cents, currency }`。 +**示例**: -#### `GET /api/v1/oauth/userinfo` +```json +{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +``` -托管账号的资料,带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 +#### `GET /api/v1/connections` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider` | query | string | 托管供应商名称。默认 `managed:kimi-code` | +列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。无参数。 -成功时 `data` 为 `{ kind: "ok", userInfo }` 或 `{ kind: "error", message, status? }`。`userInfo` 始终携带 `userId`、`nickname`、`status`、`region`、`userLevel`、`userLevelName`、`domain`、`domainName`,并可能附加 `globalId`、`bio`、`avatar`、`username`、`email`、`phone`(`{ countryCode, number }`)、`createdTime` 与 `lastLoginTime`。 +**data**(code = 0): -#### `GET /api/v1/oauth/region` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `connections` | array | [T-Connection](#t-connection) 数组 | -解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。 +**示例**: -成功时 `data` 为 `{ region }`,`region` 为 `mainland-cn` / `global` 之一。 +```json +{ "code": 0, "msg": "success", "data": { "connections": [ { "id": "conn_01JZX4...", "connected_at": "2026-09-02T08:00:00.000Z", "remote_address": "127.0.0.1", "user_agent": "Mozilla/5.0 ...", "has_client_hello": true, "subscriptions": [ "session_..." ] } ] }, "request_id": "01JZX4..." } +``` ### 配置 +全局配置的读取与合并式更新;密钥字段一律脱敏。 + | 方法与路径 | 说明 | | --- | --- | | `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | @@ -278,70 +297,35 @@ curl -s -H "Authorization: Bearer $TOKEN" \ #### `GET /api/v1/config` -返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:每个供应商只报告 `has_api_key`,绝不返回存储的密钥。 +返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:供应商与模型只报告 `has_api_key`,绝不返回存储的密钥。 -成功时 `data` 为配置对象;其字段与 [顶层字段](../configuration/config-files.md#top-level-fields) 记录的顶层域一一对应: +**data**(code = 0):[T-ConfigResponse](#t-configresponse)。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `providers` | object | 供应商 id → `{ type, base_url?, default_model?, has_api_key }` 的映射 | -| `default_provider` | string | 全局默认供应商 id | -| `default_model` | string | 全局默认模型别名 | -| `models` | object | 模型别名 → 模型记录的映射 | -| `thinking` | object | Thinking 模式的默认参数 | -| `plan_mode` | boolean | Plan 模式开关 | -| `yolo` | boolean | 派生值:`default_permission_mode` 为 `yolo` 时为 `true` | -| `default_permission_mode` | string | 新会话的默认权限模式 | -| `default_plan_mode` | boolean | 新会话是否以 Plan 模式启动 | -| `permission` | object | 初始权限规则 | -| `hooks` | array | 生命周期钩子 | -| `services` | object | 内置外部服务配置 | -| `merge_all_available_skills` | boolean | 是否合并所有可用目录中的 Agent Skills | -| `extra_skill_dirs` | array | 额外的 Skill 搜索目录 | -| `loop_control` | object | Agent 循环控制参数 | -| `background` | object | 后台任务运行参数 | -| `subagent` | object | subagent 配置 | -| `secondary_model` | object | subagent 的次级模型池 | -| `experimental` | object | 实验开关 id → 是否启用 | -| `telemetry` | boolean | 是否启用匿名遥测 | -| `raw` | object | 原始解析的 `config.toml` 内容,包含未建模字段 | +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "providers": { "my-provider": { "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true } }, "default_provider": "my-provider", "default_model": "my-provider/kimi-for-coding", "models": { "...": {} } }, "request_id": "01JZX4..." } +``` #### `POST /api/v1/config` -合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现在请求体中的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写;被拒绝的补丁(值非法或持久化失败)返回 `40001` 与底层错误信息。 +合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写(`false` 被忽略)。每一次配置变更——经本端点、在进程外编辑 `config.toml`,或服务端内部写入——都会广播全局 `event.config.changed` 事件。 -每一次配置变更——经本端点成功更新、在进程外编辑 `config.toml`,或服务端内部写入(如 OAuth 登录刷新)——都会广播全局 `event.config.changed` 事件。短时间窗内的多次变更会合并为一个事件,其 `changedFields` 携带受影响的域名(camelCase 配置域,例如 `defaultModel`),`config` 携带当前完整的配置投影(与 `GET /api/v1/config` 响应同形状)。 +**Body**:部分配置对象,[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 -请求体是部分配置对象——上述响应域中除 `raw` 外的任意子集,均为可选: +**data**(code = 0):[T-ConfigResponse](#t-configresponse)(合并写入后的全量)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `providers` | body | object | 供应商 id → 供应商表的映射 | -| `default_provider` | body | string | 全局默认供应商 id | -| `default_model` | body | string | 全局默认模型别名 | -| `models` | body | object | 模型别名 → 模型记录的映射 | -| `thinking` | body | object | Thinking 模式的默认参数 | -| `plan_mode` | body | boolean | Plan 模式开关 | -| `yolo` | body | boolean | `true` 映射为 `default_permission_mode: "yolo"`;`false` 被忽略 | -| `default_permission_mode` | body | string | `manual` / `yolo` / `auto` | -| `default_plan_mode` | body | boolean | 新会话是否以 Plan 模式启动 | -| `permission` | body | object | 初始权限规则 | -| `hooks` | body | array | 生命周期钩子 | -| `services` | body | object | 内置外部服务配置 | -| `merge_all_available_skills` | body | boolean | 是否合并所有可用目录中的 Agent Skills | -| `extra_skill_dirs` | body | array | 额外的 Skill 搜索目录 | -| `loop_control` | body | object | Agent 循环控制参数 | -| `background` | body | object | 后台任务运行参数 | -| `subagent` | body | object | subagent 配置 | -| `secondary_model` | body | object | subagent 的次级模型池 | -| `experimental` | body | object | 实验开关 id → 是否启用 | -| `telemetry` | body | boolean | 是否启用匿名遥测 | - -成功时 `data` 为完整的更新后配置,形态与 `GET /api/v1/config` 相同。 +**非零 code**:`40001`(值非法或持久化失败,`details` 逐字段说明)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "default_model": "my-provider/kimi-for-coding", "yolo": true, "providers": { "...": {} } }, "request_id": "01JZX4..." } +``` ### 模型与供应商 -这组端点管理模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录,用于一次性导入。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),而模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方(包括全局 `default_model`)指的都是这个别名 id。`:{action}` 路由上不支持的动作返回 `40001`。 +模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方指的都是这个别名 id。 | 方法与路径 | 说明 | | --- | --- | @@ -359,2043 +343,3375 @@ curl -s -H "Authorization: Bearer $TOKEN" \ #### `GET /api/v1/models` -列出所有供应商下已配置的模型别名。 +列出所有供应商下已配置的模型别名。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-ModelCatalogItem](#t-modelcatalogitem) 数组 | + +**示例**: -成功时 `data.items` 为 `{ provider, model, display_name?, max_context_size, capabilities?, support_efforts?, default_effort? }` 数组:`model` 是别名 id(供应商管理的别名为 `provider_id/model`,否则为裸键),`provider` 是所属供应商 id,`max_context_size` 是以 token 计的上下文窗口,`capabilities` / `support_efforts` / `default_effort` 描述能力标志与 Thinking 模式的 effort 支持。 +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "provider": "my-provider", "model": "my-provider/kimi-for-coding", "max_context_size": 262144, "capabilities": [ "thinking", "image_in" ] } ] }, "request_id": "01JZX4..." } +``` #### `POST /api/v1/models/{model_id}:set_default` -把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;当 id 含 `/` 时需做 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 +把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。无请求体。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `model_id` | path | string | **必填。** 配置中的模型别名键原样;含 `/` 时需 URL 编码 | +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `default_model` | string | 当前生效的别名 | +| `model` | object | [T-ModelCatalogItem](#t-modelcatalogitem) | -成功时 `data` 为 `{ default_model, model }`——当前生效的别名及其目录项(形态与 `GET /api/v1/models` 的单项相同)。 +**非零 code**:`40001`(动作后缀非法)、`40413`(模型别名不存在)。 -- `40001`:路径中的动作后缀非法或不支持 -- `40413`:不存在该 id 的模型别名 +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "default_model": "turbo", "model": { "provider": "my-provider", "model": "turbo", "max_context_size": 262144 } }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/providers` -列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。这也是其他供应商端点引用的供应商条目形态。 +列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。无参数。 -成功时 `data.items` 为如下结构的数组: +**data**(code = 0): | 字段 | 类型 | 说明 | | --- | --- | --- | -| `id` | string | 供应商 id | -| `type` | string | 通信协议:`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai` | -| `base_url` | string | API 基础 URL,如已设置 | -| `default_model` | string | 该供应商的默认模型别名,如已设置 | -| `has_api_key` | boolean | 是否已存储凭据 | -| `status` | string | 存在 API 密钥或缓存的 OAuth token 时为 `connected`,否则为 `unconfigured`(`error` 在 schema 中保留) | -| `models` | array | 该供应商的模型别名 id | +| `items` | array | [T-ProviderCatalogItem](#t-providercatalogitem) 数组 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "my-provider", "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true, "status": "connected", "models": [ "my-provider/kimi-for-coding" ] } ] }, "request_id": "01JZX4..." } +``` #### `POST /api/v1/providers` -一次保存创建供应商及其模型别名;响应为 HTTP 201 加标准信封。当全局 `default_model` 完全未配置时(全新安装),会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 +一次保存创建供应商及其模型别名;响应为 HTTP 201 加标准信封。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 + +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `id` | body | string | **必填。** 供应商 id——字母、数字、`-`、`_` 与空格;必须以字母或数字开头 | -| `type` | body | string | **必填。** 通信协议:`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai` | -| `api_key` | body | string | API 密钥,存储于 `config.toml` | -| `base_url` | body | string | API 基础 URL;不得包含环境变量占位符(`${...}`) | -| `default_model` | body | string | 该供应商的默认模型;必须是 `models[].model` 之一 | -| `models` | body | array | **必填。** 至少一条,不允许重复的 `model` 值;条目结构见下文 | +| `id` | string | 是 | 供应商 id——字母、数字、`-`、`_` 与空格;必须以字母或数字开头 | +| `type` | string | 是 | 通信协议:`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai` | +| `api_key` | string | 否 | API 密钥,存储于 `config.toml` | +| `base_url` | string | 否 | API 基础 URL;不得包含环境变量占位符(`${...}`) | +| `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | +| `models` | array | 是 | 至少一条,不允许重复的 `model` 值;条目结构见下 | -每个 `models[]` 条目声明一个别名,其 id 为 `id/model`: +`models[]` 条目(每个声明一个别名,其 id 为 `id/model`): -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `model` | string | **必填。** 上游模型名 | -| `max_context_size` | integer | **必填。** 以 token 计的上下文窗口,≥ 1 | -| `display_name` | string | 显示名 | -| `capabilities` | array | 能力标志,如 `thinking` 或 `image_in` | -| `max_output_size` | integer | 最大输出 token 数,≥ 1 | -| `support_efforts` | array | 支持的 Thinking 模式 effort 档位 | -| `adaptive_thinking` | boolean | 自适应 thinking 开关 | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `model` | string | 是 | 上游模型名 | +| `max_context_size` | integer | 是 | 以 token 计的上下文窗口,≥ 1 | +| `display_name` | string | 否 | 显示名 | +| `capabilities` | array | 否 | 能力标志,如 `thinking` 或 `image_in` | +| `max_output_size` | integer | 否 | 最大输出 token 数,≥ 1 | +| `support_efforts` | array | 否 | 支持的 Thinking 模式 effort 档位 | +| `adaptive_thinking` | boolean | 否 | 自适应 thinking 开关 | + +**data**(code = 0):[T-ProviderCatalogItem](#t-providercatalogitem)(新建对象)。 -成功时 `data` 为创建好的供应商条目(形态与 `GET /api/v1/providers` 的单项相同)。 +**非零 code**:`40001`、`40921`(已存在该 `id` 的供应商)。 -- `40921`:已存在该 `id` 的供应商 +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected", "models": [ "my-provider/kimi-for-coding" ] }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/providers/{provider_id}` -读取单个供应商。与列表路由不同,设置了密钥时响应会暴露存储的 `api_key`,以便本地编辑表单预填——暴露端口时请牢记这一点。 +读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider_id` | path | string | **必填。** 供应商 id | +**data**(code = 0):[T-ProviderCatalogItem](#t-providercatalogitem),存有密钥时附带 `api_key: string`。 -成功时 `data` 为供应商条目,存有密钥时附带 `api_key`。 +**非零 code**:`40001`、`40412`。 -- `40412`:供应商不存在 +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "my-provider", "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true, "status": "connected", "api_key": "sk-..." }, "request_id": "01JZX4..." } +``` #### `PUT /api/v1/providers/{provider_id}` -一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,该供应商的别名按 `models` 重建——不再列出的别名从 `config.toml` 中消失,其他供应商的别名不受影响。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 +一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,不再列出的别名从 `config.toml` 中消失。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider_id` | path | string | **必填。** 当前供应商 id | -| `new_id` | body | string | 重命名供应商;providers 键、模型别名、`default_provider`、指向旧别名的 `default_model` 以及 subagent 次级模型池都会随之迁移。id 规则与 `POST /api/v1/providers` 相同 | -| `type` | body | string | **必填。** 通信协议:`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai` | -| `api_key` | body | string | 三态,见上文 | -| `base_url` | body | string | API 基础 URL;不得包含环境变量占位符(`${...}`) | -| `default_model` | body | string | 该供应商的默认模型;必须是 `models[].model` 之一 | -| `models` | body | array | **必填。** 至少一条,不允许重复的 `model` 值;条目结构与 `POST /api/v1/providers` 相同 | +**Body**: -成功时 `data` 为 `{ provider }`,即保存后的供应商条目。 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `new_id` | string | 否 | 重命名供应商;providers 键、模型别名、`default_provider`、指向旧别名的 `default_model` 与 subagent 次级模型池随之迁移。id 规则同 `POST /api/v1/providers` | +| `type` | string | 是 | 通信协议,取值同 `POST /api/v1/providers` | +| `api_key` | string | 否 | 三态,见上文 | +| `base_url` | string | 否 | API 基础 URL;不得包含环境变量占位符 | +| `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | +| `models` | array | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | -- `40001`:重命名后的别名 id 会与其他供应商的别名冲突 -- `40003`:供应商由 OAuth 托管——请改用 `POST /api/v1/oauth/logout` 登出 -- `40412`:供应商不存在 -- `40921`:`new_id` 已被占用 +**data**(code = 0): -#### `DELETE /api/v1/providers/{provider_id}` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | object | [T-ProviderCatalogItem](#t-providercatalogitem) | -删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商——那是用户的设置,不由本端点代为回收。 +**非零 code**:`40001`(重命名后的别名 id 冲突)、`40003`(供应商由 OAuth 托管,改用 `POST /api/v1/oauth/logout`)、`40412`、`40921`(`new_id` 已被占用)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider_id` | path | string | **必填。** 供应商 id | +**示例**: -成功时服务应答 204 且无响应体——状态行本身即表示删除成功(见 [响应信封](#响应信封))。 +```json +{ "code": 0, "msg": "success", "data": { "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" } }, "request_id": "01JZX4..." } +``` -- `40003`:供应商由 OAuth 托管——请改用 `POST /api/v1/oauth/logout` 登出 -- `40412`:供应商不存在 +#### `DELETE /api/v1/providers/{provider_id}` -#### `POST /api/v1/providers/{provider_id}:refresh` +删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。无请求体。 -从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名。模型来源为静态的供应商不经任何网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时,服务会广播全局 `event.model_catalog.changed` 事件。 +**成功形态**:HTTP 204 空体——状态行本身即表示删除成功。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `provider_id` | path | string | **必填。** 供应商 id | +**非零 code**:`40001`、`40003`、`40412`。 -成功时 `data` 为刷新报告:`changed` 是 `{ provider_id, provider_name, added, removed }`(新增 / 移除的别名数)的数组,`unchanged` 是无差异的供应商 id 数组,`failed` 是 `{ provider, reason }` 的数组。 +#### `POST /api/v1/providers/{provider_id}:refresh` -- `40001`:路径中的动作后缀非法或不支持 -- `40412`:供应商不存在 +从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。无请求体。 -#### `POST /api/v1/providers:refresh` +**data**(code = 0):[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)。 -刷新每个供应商的模型元数据。请求体可选且被忽略。 +**非零 code**:`40001`、`40412`。 -成功时 `data` 为与 `POST /api/v1/providers/{provider_id}:refresh` 相同的刷新报告(`changed` / `unchanged` / `failed`)。 +**示例**: -#### `POST /api/v1/providers:refresh_oauth` +```json +{ "code": 0, "msg": "success", "data": { "changed": [ { "provider_id": "my-provider", "provider_name": "my-provider", "added": 2, "removed": 0 } ], "unchanged": [], "failed": [] }, "request_id": "01JZX4..." } +``` -与 `POST /api/v1/providers:refresh` 相同的刷新,仅限 OAuth 凭据的供应商。请求体可选且被忽略。 +#### `POST /api/v1/providers:{action}` -成功时 `data` 为刷新报告(`changed` / `unchanged` / `failed`)。 +集合级动作路由;请求体按动作校验。四个动作: -#### `POST /api/v1/providers:import_catalog` +| 动作 | Body | data(code = 0) | +| --- | --- | --- | +| `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | +| `:refresh_oauth` | 可选,被忽略 | 同上,仅限 OAuth 凭据的供应商 | +| `:import_catalog` | 见下 | `{ provider, models_imported }`,HTTP 201 | +| `:import_registry` | 见下 | `{ providers, models_imported }`,HTTP 201 | -把一个 models.dev 目录条目导入为已配置供应商;响应为 HTTP 201 加标准信封。通信协议与端点来自目录解析,目录中的每个模型都写为一个别名。导入已存在的 id 等同于刷新——供应商条目及其别名按目录重写,省略 `api_key` 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时,以第一个导入的模型播种 `default_model`。 +`:import_catalog` 的 Body——把一个 models.dev 目录条目导入为已配置供应商:通信协议与端点来自目录解析,目录中的每个模型都写为一个别名;导入已存在的 id 等同于刷新,省略 `api_key` 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时以第一个导入的模型播种 `default_model`: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `catalog_id` | body | string | **必填。** 来自 `GET /api/v1/catalog/providers` 的目录条目 id | -| `id` | body | string | 覆盖目录 id 作为本地供应商 id。id 规则与 `POST /api/v1/providers` 相同 | -| `api_key` | body | string | 导入供应商的 API 密钥 | -| `base_url` | body | string | 覆盖目录解析出的端点;条目的 `needs_base_url` 为 `true` 时必填 | +| `catalog_id` | string | 是 | 来自 `GET /api/v1/catalog/providers` 的目录条目 id | +| `id` | string | 否 | 覆盖目录 id 作为本地供应商 id | +| `api_key` | string | 否 | 导入供应商的 API 密钥 | +| `base_url` | string | 否 | 覆盖目录解析出的端点;条目的 `needs_base_url` 为 `true` 时必填 | -成功时 `data` 为 `{ provider, models_imported }`——供应商条目与写入的别名数量。 +`:import_registry` 的 Body——把一个 models.dev 形态的私有注册表(一个 `api.json` URL 加可选的 Bearer key)导入:每个列出的供应商都带 `source` 记录写入,以便定时刷新重新发现;重复导入同一 URL 会移除上游已消失的供应商——URL 是注册表的稳定身份,因此轮换 key 是安全的。全局默认指针遵循与 `:import_catalog` 相同的规则: -- `40001`:缺少 `catalog_id` 或其他请求体校验失败 -- `40003`:目标供应商已存在且由 OAuth 托管 -- `40004`:条目无法导入(被拒绝、要求 `base_url`、没有可导入的模型,或其 id 不能用作供应商 id) -- `40417`:不存在该 `catalog_id` 的目录条目 -- `50004`:models.dev 目录不可用 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `url` | string | 是 | 注册表 `api.json` 的 URL | +| `api_key` | string | 否 | 注册表的 Bearer key;省略时复用上一次导入同一 URL 所用的 key | -#### `POST /api/v1/providers:import_registry` +**非零 code**:`40001`、`40003`、`40004`(目录条目无法导入)、`40005`(注册表无法获取或解析)、`40417`、`50004`(models.dev 目录不可用)。 -把一个 models.dev 形态的私有注册表——一个 `api.json` URL 加可选的 Bearer key——导入为已配置供应商;响应为 HTTP 201 加标准信封。每个列出的供应商都带 `source` 记录写入,以便定时刷新重新发现。重复导入同一 URL 会移除上游已消失的供应商——URL 是注册表的稳定身份,因此轮换 key 是安全的。全局默认指针遵循与 `:import_catalog` 相同的规则。 +**示例**(`:import_catalog`): -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `url` | body | string | **必填。** 注册表 `api.json` 的 URL | -| `api_key` | body | string | 注册表的 Bearer key;省略时复用上一次导入同一 URL 所用的 key | +```json +{ "code": 0, "msg": "success", "data": { "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" }, "models_imported": 3 }, "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ providers, models_imported }`——供应商条目数组与写入的别名总数。 +#### `GET /api/v1/catalog/providers` -- `40001`:缺少 `url` 或其他请求体校验失败 -- `40003`:某个列出的供应商已存在且由 OAuth 托管 -- `40005`:注册表无法获取或解析,或未列出可导入的供应商 +浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。无参数。 -#### `GET /api/v1/catalog/providers` +**data**(code = 0): -浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底。条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`;`needs_base_url: true` 的条目在导入时要求提供 base URL。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-CatalogProviderItem](#t-catalogprovideritem) 数组 | -成功时 `data.items` 为 `{ id, name, wire_type, guessed, needs_base_url, rejected, reject_reason, env_key, models }` 数组:`wire_type` 是解析出的协议(可空,枚举与供应商 `type` 相同),`guessed` 标记启发式解析,`env_key` 是上游约定的 API 密钥环境变量(可空),`models` 是 `{ id, name?, max_context_size, capabilities?, reasoning }` 的数组。 +**非零 code**:`50004`(在线拉取与内置快照均失败)。 -- `50004`:目录不可用(在线拉取与内置快照均失败) +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ { "id": "gpt-5", "max_context_size": 400000, "reasoning": true } ] } ] }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/catalog/providers/{catalog_id}` -按 catalog id 读取单个 models.dev 目录条目——条目形态与 `GET /api/v1/catalog/providers` 相同。 +按 catalog id 读取单个 models.dev 目录条目。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `catalog_id` | path | string | **必填。** 目录条目 id | +**data**(code = 0):[T-CatalogProviderItem](#t-catalogprovideritem)。 -成功时 `data` 为该目录条目(形态与 `GET /api/v1/catalog/providers` 的单项相同)。 +**非零 code**:`40417`、`50004`。 -- `40417`:不存在该 `catalog_id` 的目录条目 -- `50004`:目录不可用 +**示例**: -### 会话 +```json +{ "code": 0, "msg": "success", "data": { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ "..." ] }, "request_id": "01JZX4..." } +``` + +### 登录与用量 -这些端点用于创建、列出和查看会话,执行会话级动作(fork、compact、undo 等),并读取会话级汇总。其中大多数返回的会话采用 [session 对象](#session-对象) 中统一说明的线上格式;非 CRUD 操作使用上文介绍的 `:{action}` 约定。 +托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 | 方法与路径 | 说明 | | --- | --- | -| `POST /api/v1/sessions` | 创建会话(需 `workspace_id` 或 `metadata.cwd`) | -| `GET /api/v1/sessions` | 列出会话,游标分页,支持 `busy` / `archived_only` 等过滤 | -| `GET /api/v1/sessions/{session_id}` | 读取单个会话 | -| `GET /api/v1/sessions/{session_id}/profile` | 读取会话档案 | -| `POST /api/v1/sessions/{session_id}/profile` | 更新标题、元数据、Agent 配置 | -| `POST /api/v1/sessions/{session_id}/title/generate` | 通过托管的 `chat_title` 工具生成标题 | -| `POST /api/v1/sessions/{session_id}:{action}` | 会话动作:`fork` / `compact` / `undo` / `abort` / `btw` / `archive` / `restore` | -| `GET /api/v1/sessions/{session_id}/children` | 列出子会话 | -| `POST /api/v1/sessions/{session_id}/children` | 创建子会话(fork 并打标) | -| `GET /api/v1/sessions/{session_id}/status` | 实时状态汇总 | -| `GET /api/v1/sessions/{session_id}/goal` | 当前目标快照(无则 `null`) | -| `GET /api/v1/sessions/{session_id}/warnings` | 会话级告警 | -| `GET /api/v1/sessions/{session_id}/runtime` | 读取 main agent 的运行时绑定 | -| `POST /api/v1/sessions/{session_id}/runtime` | 切换 main agent 的运行时绑定 | -| `POST /api/v1/sessions/{session_id}/export` | 导出会话与诊断信息(zip 流,不走信封) | -| `GET /api/v1/sessions/{session_id}/snapshot` | 客户端重建用全量快照(含 `as_of_seq` 与 `epoch`) | -| `GET /api/v1/sessions/{session_id}/media/{file_id}` | 按文件 id 下载提示词媒体(二进制) | +| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | +| `GET /api/v1/oauth/login` | 轮询登录流程状态 | +| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | +| `POST /api/v1/oauth/logout` | 登出托管供应商 | +| `GET /api/v1/oauth/usage` | 套餐用量与限额 | +| `GET /api/v1/oauth/userinfo` | 账号资料 | +| `GET /api/v1/oauth/region` | 解析客户端所属区域 | -#### session 对象 +#### `POST /api/v1/oauth/login` -每个返回会话的端点都使用这种线上格式。实时状态字段(`busy`、`main_turn_active`、`pending_interaction`、`last_turn_reason`)由会话的活动聚合解析得出:未加载到本服务进程中的会话(冷会话)始终上报为不忙碌且无待处理交互。少数字段在当前投影中是占位值——已逐字段注明。 +为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | string | 会话 id(`session_...`) | -| `workspace_id` | string | 所属工作区 id | -| `title` | string | 会话标题;无标题时为 `""` | -| `created_at` / `updated_at` | string | 创建时间与最后更新时间,ISO 8601 | -| `archived` | boolean | 会话是否已归档(归档后从默认会话列表中隐藏) | -| `archived_at` | string | 归档时间,ISO 8601;仅在已归档时存在 | -| `busy` | boolean | 是否有任一 Agent 存在进行中的轮次或后台任务 | -| `main_turn_active` | boolean | main agent 是否有进行中的轮次 | -| `pending_interaction` | string | `none` / `approval` / `question`——有未答复的交互在等待 | -| `last_turn_reason` | string | main agent 最近一次轮次的结果:`completed` / `cancelled` / `failed` | -| `last_prompt` | string | 最近一条用户提示词文本(如有) | -| `metadata` | object | 自定义元数据;始终携带 `cwd`(会话的工作目录) | -| `agent_config` | object | 投影为 `{ model }`;`model` 在大多数响应中为 `""`,仅由 `GET /api/v1/sessions/{session_id}/snapshot` 填入实时模型 | -| `usage` | object | token 汇总 `{ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, context_tokens, context_limit?, total_cost_usd?, turn_count? }`;在 snapshot 端点之外全为零 | -| `permission_rules` | array | 会话权限规则;当前始终为 `[]` | -| `message_count` | integer | 消息数;当前始终为 `0` | -| `last_seq` | integer | 最后的事件序列号;当前始终为 `0` | +**Body**: -#### `POST /api/v1/sessions` +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | +| `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | -创建会话并返回。目标目录来自 `workspace_id`(已注册的工作区)或 `metadata.cwd`(首次使用时注册该工作区);两者同时提供时必须一致。创建时会广播全局 `event.session.created` 事件。 +**data**(code = 0):[T-OAuthFlowStart](#t-oauthflowstart)——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | body | string | 未提供 `metadata.cwd` 时**必填**。已注册的工作区 id;会话创建于该工作区的根目录 | -| `metadata` | body | object | 自定义元数据。`metadata.cwd` 为工作目录,未提供 `workspace_id` 时**必填**;两者同时提供时必须等于工作区根目录 | -| `title` | body | string | 初始标题(至少 1 个字符);否则会话无标题 | -| `agent_config` | body | object | schema 接受该字段但当前不会应用——模型与各模式请通过 `POST /api/v1/sessions/{session_id}/profile` 设置 | +**示例**: -成功时,`data` 为新会话的 [session 对象](#session-对象)。 +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +``` -- `40001`:`workspace_id` 与 `metadata.cwd` 都未提供,或 `metadata.cwd` 与工作区根目录不一致(`details` 会列出该字段) -- `40409`:工作目录不存在或不是目录 -- `40410`:没有以该 `workspace_id` 注册的工作区 +#### `GET /api/v1/oauth/login` -#### `GET /api/v1/sessions` +轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 -跨工作区列出会话,按 `updated_at` 最新在前。游标分页遵循 [分页](#分页),但有一个特例:不提供 `page_size`(且不提供 `archived_only`)时,响应是单个不分页的窗口,其 `has_more` 恒为 `false`,因此要真正翻页请传入 `page_size`。 +**Query**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `before_id` | query | string | 只保留早于该 id 的会话;与 `after_id` 互斥 | -| `after_id` | query | string | 只保留晚于该 id 的会话;与 `before_id` 互斥 | -| `page_size` | query | integer | 1–100。分页生效时默认为 `20`;不分页的默认行为见上文说明 | -| `busy` | query | boolean | 只保留忙碌(或只保留空闲)的会话 | -| `include_archive` | query | boolean | 在活跃会话之外同时包含已归档会话。默认 `false` | -| `archived_only` | query | boolean | 只保留已归档会话;与 `include_archive` 互斥;即使不提供 `page_size` 也会启用游标分页 | -| `exclude_empty` | query | boolean | 去掉没有任何用户提示词的会话 | -| `workspace_id` | query | string | 限定到单个工作区(别名会被解析) | +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -成功时,`data` 为 `{ items, has_more }`,其中每个元素为 [session 对象](#session-对象)。 +**data**(code = 0):[T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 或 `null`。 -- `40001`:校验失败——例如 `before_id` 与 `after_id` 同用,或 `archived_only` 与 `include_archive` 同用 -- `40410`:未知的 `workspace_id` +**示例**: -#### `GET /api/v1/sessions/{session_id}` +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } +``` -从索引中读取单个会话。会话已加载到本进程时会包含实时状态字段;冷会话上报为不忙碌,并携带其最后持久化的轮次结果。 +#### `DELETE /api/v1/oauth/login` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 -成功时,`data` 为 [session 对象](#session-对象)。 +**Query**: -- `40401`:会话不存在,或其工作区已无法解析 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -#### `GET /api/v1/sessions/{session_id}/profile` +**data**(code = 0): -读取会话档案——与 `GET /api/v1/sessions/{session_id}` 相同的线上载荷。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | +| `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**示例**: -成功时,`data` 为 [session 对象](#session-对象)。 +```json +{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } +``` -- `40401`:会话不存在 +#### `POST /api/v1/oauth/logout` -#### `POST /api/v1/sessions/{session_id}/profile` +登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 -更新会话档案:标题、自定义元数据以及 main agent 的配置。在这里设置的标题会成为自定义标题,优先级高于生成的标题;设置标题会广播全局 `session.meta.updated` 事件。 +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `title` | body | string | 新标题(至少 1 个字符);会成为自定义标题 | -| `metadata` | body | object | 合并进会话自定义元数据的键 | -| `agent_config` | body | object | main agent 的部分配置;字段如下,均为可选 | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | -每个 `agent_config` 字段都会立即应用到 main agent: +**data**(code = 0): | 字段 | 类型 | 说明 | | --- | --- | --- | -| `model` | string | 模型别名 id;空字符串会被忽略 | -| `thinking` | string | Thinking 强度等级 | -| `permission_mode` | string | `manual` / `yolo` / `auto` | -| `plan_mode` | boolean | 进入或退出 Plan 模式 | -| `swarm_mode` | boolean | 进入或退出 swarm 模式 | -| `goal_objective` | string | 以该文本为内容创建一个目标 | -| `goal_control` | string | `pause` / `resume` / `cancel` 当前目标 | +| `logged_out` | boolean | 恒 `true` | +| `provider` | string | 被登出的供应商名 | -schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers`,以及顶层的 `permission_rules` 数组,但更新路由当前不会应用它们。 +**示例**: -成功时,`data` 为更新后的 [session 对象](#session-对象)。 - -- `40401`:会话不存在 +```json +{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } +``` -#### `POST /api/v1/sessions/{session_id}/title/generate` +#### `GET /api/v1/oauth/usage` -通过托管供应商的 `chat_title` 工具根据会话的提示词生成标题并应用,同时广播 `session.meta.updated`。生成需要托管 OAuth 登录和 `auto_session_title` 实验开关;未提供 `force` 时,已有自定义标题或已生成标题的会话会上报为不可用,而不会被覆盖。 +托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让信封失败——以 `kind: "error"` 带内返回。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `force` | body | boolean | 即使已有自定义或生成的标题也重新生成。默认 `false` | -| `source` | body | string | 标题输入:`user_prompts`(默认)/ `first_turn` / `digest` | +**Query**: -成功时,`data` 为 `{ title }`——当前应用到会话的标题。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -- `40401`:会话不存在 -- `40923`:生成不可用——开关未开启、没有托管 OAuth 登录或尚无任何提示词内容、已有标题但未提供 `force`,或后端请求失败 +**data**(code = 0):[T-ManagedUsageResult](#t-managedusageresult)。 -#### `POST /api/v1/sessions/{session_id}:{action}` +**示例**: -会话动作通过同一条路由分发:路径尾部解析为 `{session_id}:{action}`,请求体按该动作的 schema 校验,动作缺失或未知时返回 `40001`(`unsupported action: ...`)。每个动作都会先解析会话,因此会话未知时都可能返回 `40401`。支持的动作在下面逐一说明。 +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } +``` -#### `POST /api/v1/sessions/{session_id}:fork` +#### `GET /api/v1/oauth/userinfo` -将会话——其转录、Agent 状态与文件——复制到同一工作区中的新会话,并广播 `event.session.created`。当会话中任一 Agent 有进行中的轮次时,fork 会被拒绝。 +托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `title` | body | string | fork 的标题(至少 1 个字符)。默认 `Fork: ` | -| `metadata` | body | object | fork 的自定义元数据 | +**Query**: -成功时,`data` 为新会话的 [session 对象](#session-对象)。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -- `40901`:会话有进行中的轮次,无法 fork +**data**(code = 0):[T-ManagedUserInfoResult](#t-manageduserinforesult)(camelCase 载荷)。 -#### `POST /api/v1/sessions/{session_id}:compact` +**示例**: -对 main agent 的上下文发起一次手动全量压缩。调用立即返回;进度与完成通过 `compaction.*` WebSocket 事件投递。 +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `instruction` | body | string | 给压缩摘要的额外指引;空值会被忽略 | +#### `GET /api/v1/oauth/region` -成功时,`data` 为空对象。 +解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 -- `40910`:有轮次或其他上下文变更正在进行,或历史中没有可压缩的内容 +**data**(code = 0): -#### `POST /api/v1/sessions/{session_id}:undo` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `region` | string | `mainland-cn` / `global` | -将 main agent 的对话回退 `count` 个轮次,并同步修正派生的会话状态(包括会话的 `last_prompt`)。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `count` | body | integer | 要撤销的轮次数;正整数。默认 `1` | -| `page_size` | body | integer | 返回的历史窗口大小,1–100。默认 `50` | +```json +{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } +``` -成功时,`data` 为 `{ messages, status }`:`messages` 是剩余上下文消息按最新在前的 `{ items, has_more }` 分页,`status` 与 `GET /api/v1/sessions/{session_id}/status` 的汇总相同。 +### 插件 -- `40901`:有轮次正在进行或压缩正在运行——等其结束后重试 -- `40911`:无法撤销那么多轮次(遇到压缩边界或检查点丢失);`data` 携带 `{ reason, requestedCount, undoableCount }` +插件是已安装的技能、MCP 服务、hook 与命令的打包集合。这组端点管理插件从市场列表到移除的整个生命周期。 -#### `POST /api/v1/sessions/{session_id}:abort` +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/plugins/marketplace` | 插件市场目录,合并实时安装状态 | +| `GET /api/v1/plugins` | 列出已安装插件 | +| `POST /api/v1/plugins` | 从本地路径、zip URL 或 GitHub 仓库安装插件 | +| `POST /api/v1/plugins/{plugin_id}:{action}` | 插件动作:`enable` / `disable` / `remove` | -取消 main agent 正在运行的轮次——等同于用户在 TUI 中中止轮次的程序化版本。 +#### `GET /api/v1/plugins/marketplace` -成功时,`data` 为 `{ aborted: true }`。 +列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),当前平台不支持的能力对应条目会被剔除。无参数。 -#### `POST /api/v1/sessions/{session_id}:btw` +**data**(code = 0): -开启一个 `"by the way"` 旁路对话:把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文。需要可用的模型配置。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `entries` | array | 市场条目(camelCase):`{ id, tier, displayName, description?, homepage?, keywords?, version?, source, installed?, updateAvailable?, capabilityId? }`;`tier` 为 `official` / `curated` / `third-party`;`installed` 为 `{ version?, enabled }`;`source` 即 `POST /api/v1/plugins` 的 `source` 取值 | -成功时,`data` 为 `{ agent_id }`——新子 Agent 的 id。 +**非零 code**:`50001`(市场不可达或返回了非法目录)。 -#### `POST /api/v1/sessions/{session_id}:archive` +**示例**: -将会话标记为已归档:它从默认会话列表中消失(使用 `include_archive` 或 `archived_only` 时仍会列出),并且服务端广播全局 `event.session.archived` 事件。 +```json +{ "code": 0, "msg": "success", "data": { "entries": [ { "id": "my-plugin", "tier": "official", "displayName": "My Plugin", "source": "https://github.com/example/my-plugin", "installed": { "version": "1.2.0", "enabled": true }, "updateAvailable": false } ] }, "request_id": "01JZX4..." } +``` -成功时,`data` 为 `{ archived: true }`。 +#### `GET /api/v1/plugins` -#### `POST /api/v1/sessions/{session_id}:restore` +列出已安装插件。无参数。 -取消会话的归档状态并恢复它。 +**data**(code = 0): -成功时,`data` 为 `archived: false` 的 [session 对象](#session-对象)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `plugins` | array | [T-PluginSummary](#t-pluginsummary) 数组 | -#### `GET /api/v1/sessions/{session_id}/children` +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "plugins": [ { "id": "my-plugin", "displayName": "My Plugin", "version": "1.2.0", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 1, "enabledMcpServerCount": 1, "hookCount": 0, "commandCount": 1, "hasErrors": false, "source": "github" } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/plugins` + +安装插件并返回其摘要。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | + +**data**(code = 0):[T-PluginSummary](#t-pluginsummary)。 + +**非零 code**:`40001`(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "my-plugin", "displayName": "My Plugin", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 0, "enabledMcpServerCount": 0, "hookCount": 0, "commandCount": 0, "hasErrors": false, "source": "local-path" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/plugins/{plugin_id}:{action}` + +插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 + +**data**(code = 0):`{ "ok": true }`。 + +**非零 code**:`40001`(缺少动作后缀或动作未知)、`40419`(没有该 id 的已安装插件)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +``` + +### 能力 + +能力是带有分层就绪状态的内置特性——由检测步骤加后台安装组成;当前版本注册了 `kimi-cu`(Kimi Computer Use)与 `kimi-webbridge`(Kimi WebBridge)。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/capabilities` | 列出内置能力及其就绪状态 | +| `GET /api/v1/capabilities/{capability_id}` | 读取单个能力的状态 | +| `POST /api/v1/capabilities/{capability_id}:install` | 开始安装能力(后台进行,轮询 GET 查看进度) | + +#### `GET /api/v1/capabilities` + +列出所有已注册能力及其就绪状态。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `capabilities` | array | [T-CapabilityStatus](#t-capabilitystatus) 数组 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "capabilities": [ { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "ready", "steps": [ { "id": "os", "state": "ok" } ], "install": { "running": false } } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/capabilities/{capability_id}` + +读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 + +**data**(code = 0):[T-CapabilityStatus](#t-capabilitystatus)。 + +**非零 code**:`40418`(没有该 id 的能力)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "partial", "steps": [ { "id": "app", "state": "missing", "optional": true } ], "install": { "running": true, "percent": 40 } }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/capabilities/{capability_id}:install` + +在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 + +**data**(code = 0):[T-CapabilityStatus](#t-capabilitystatus)。 + +**非零 code**:`40001`(缺少动作后缀或动作未知)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "not_installed", "steps": [ "..." ], "install": { "running": true, "step": "download", "percent": 0 } }, "request_id": "01JZX4..." } +``` + +### 工具与 MCP(v1) + +当前生效 Agent 的工具列表及其 MCP 服务;管理 MCP 服务的完整面在 [v2 MCP](#v2-mcp)。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/tools` | 列出当前生效 Agent 的工具 | +| `GET /api/v1/mcp/servers` | 列出 MCP 服务 | +| `POST /api/v1/mcp/servers/{mcp_server_id}:restart` | 重启 MCP 服务 | + +#### `GET /api/v1/tools` + +列出当前生效 Agent 的工具——即 `session_id` 指定会话的 main agent;省略参数时取最近创建的存活会话。会话不在本服务进程中存活时列表为空。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `session_id` | string | 要查看其 main agent 的会话。默认最近创建的存活会话 | + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `tools` | array | [T-ToolDescriptor](#t-tooldescriptor) 数组 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "tools": [ { "name": "Bash", "description": "...", "input_schema": null, "source": "builtin", "active": true } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/mcp/servers` + +列出当前生效 Agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同的会话选取规则);没有存活会话时列表为空。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `servers` | array | [T-McpServer](#t-mcpserver) 数组 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "servers": [ { "id": "my-server", "name": "my-server", "transport": "stdio", "status": "connected", "tool_count": 5 } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/mcp/servers/{mcp_server_id}:restart` + +重新连接当前生效 Agent 的某个 MCP 服务。经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作。无请求体。 + +**data**(code = 0):`{ "restarting": true }`。 + +**非零 code**:`40001`(缺少动作后缀或动作未知)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "restarting": true }, "request_id": "01JZX4..." } +``` + +### 会话 + +创建、列出和查看会话,执行会话级动作,并读取会话级汇总。返回的会话对象统一为 [T-Session](#t-session);其实时状态字段(`busy`、`main_turn_active`、`pending_interaction`、`last_turn_reason`)由会话的活动聚合解析——未加载到本服务进程中的会话(冷会话)始终上报为不忙碌且无待处理交互。 + +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/sessions` | 创建会话(需 `workspace_id` 或 `metadata.cwd`) | +| `GET /api/v1/sessions` | 列出会话,游标分页,支持 `busy` / `archived_only` 等过滤 | +| `GET /api/v1/sessions/{session_id}` | 读取单个会话(`last_seq` 为真实事件水位) | +| `GET /api/v1/sessions/{session_id}/profile` | 读取会话档案 | +| `POST /api/v1/sessions/{session_id}/profile` | 更新标题、元数据、Agent 配置 | +| `POST /api/v1/sessions/{session_id}/title/generate` | 通过托管的 `chat_title` 工具生成标题 | +| `POST /api/v1/sessions/{session_id}:{action}` | 会话动作:`fork` / `compact` / `undo` / `abort` / `btw` / `archive` / `restore` | +| `GET /api/v1/sessions/{session_id}/children` | 列出子会话 | +| `POST /api/v1/sessions/{session_id}/children` | 创建子会话(fork 并打标) | +| `GET /api/v1/sessions/{session_id}/status` | 实时状态汇总 | +| `GET /api/v1/sessions/{session_id}/goal` | 当前目标快照(无则 `null`) | +| `GET /api/v1/sessions/{session_id}/warnings` | 会话级告警 | + +#### `POST /api/v1/sessions` + +创建会话并返回。目标目录来自 `workspace_id`(已注册的工作区)或 `metadata.cwd`(首次使用时注册该工作区);两者同时提供时必须一致。创建时广播全局 `event.session.created` 事件。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `workspace_id` | string | 条件 | 未提供 `metadata.cwd` 时必填。已注册的工作区 id | +| `metadata` | object | 条件 | 自定义元数据。`metadata.cwd` 为工作目录,未提供 `workspace_id` 时必填;同时提供时必须等于工作区根目录 | +| `title` | string | 否 | 初始标题(至少 1 个字符) | +| `agent_config` | object | 否 | schema 接受但当前不会应用——模型与各模式请经 `POST .../profile` 设置 | -列出会话的子会话——即通过 `POST /api/v1/sessions/{session_id}/children` 创建的会话。游标分页遵循 [分页](#分页)。 +**data**(code = 0):[T-Session](#t-session)。 -| 参数 | 位置 | 类型 | 说明 | +**非零 code**:`40001`(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "", "created_at": "2026-09-02T08:00:00.000Z", "updated_at": "2026-09-02T08:00:00.000Z", "busy": false, "main_turn_active": false, "pending_interaction": "none", "archived": false, "metadata": { "cwd": "/Users/dev/my-app" }, "agent_config": { "model": "" }, "usage": { "...": 0 }, "permission_rules": [], "message_count": 0, "last_seq": 0 }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions` + +跨工作区列出会话,按 `updated_at` 最新在前。特例:不提供 `page_size`(且不提供 `archived_only`)时,响应是单个不分页的窗口,`has_more` 恒为 `false`——要真正翻页请传入 `page_size`。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `before_id` | string | 只保留早于该 id 的会话;与 `after_id` 互斥 | +| `after_id` | string | 只保留晚于该 id 的会话;与 `before_id` 互斥 | +| `page_size` | integer | 1–100。分页生效时默认 `20` | +| `busy` | boolean | 只保留忙碌(或只保留空闲)的会话 | +| `include_archive` | boolean | 同时包含已归档会话。默认 `false` | +| `archived_only` | boolean | 只保留已归档会话;与 `include_archive` 互斥;即使不提供 `page_size` 也启用游标分页 | +| `exclude_empty` | boolean | 去掉没有任何用户提示词的会话 | +| `workspace_id` | string | 限定到单个工作区(别名会被解析) | + +**data**(code = 0):`{ items: T-Session[], has_more: boolean }`。 + +**非零 code**:`40001`(互斥参数同用)、`40410`(未知的 `workspace_id`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fix the login page", "...": "..." } ], "has_more": false }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}` + +从索引中读取单个会话。`last_seq` 携带真实的事件水位(watermark):存活会话为当前事件日志的序列号,冷会话为最后持久化的水位——用它作为 `subscribe` 的 `cursors` 起点时回放为空。其余会话端点的 `last_seq` 均为 `0` 占位。 + +**data**(code = 0):[T-Session](#t-session)。 + +**非零 code**:`40401`(会话不存在,或其工作区已无法解析)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fix the login page", "busy": false, "main_turn_active": false, "pending_interaction": "none", "last_turn_reason": "completed", "archived": false, "last_prompt": "adjust the button spacing", "metadata": { "cwd": "/Users/dev/my-app" }, "agent_config": { "model": "kimi-for-coding" }, "usage": { "...": 0 }, "permission_rules": [], "message_count": 0, "last_seq": 128 }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/profile` + +读取会话档案——与 `GET /api/v1/sessions/{session_id}` 相同的线上载荷(`last_seq` 为 `0` 占位)。 + +**data**(code = 0):[T-Session](#t-session)。 + +**非零 code**:`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "...": "..." }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/profile` + +更新会话档案:标题、自定义元数据以及 main agent 的配置。设置的标题会成为自定义标题,优先级高于生成的标题;设置标题会广播全局 `session.meta.updated` 事件。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `title` | string | 否 | 新标题(至少 1 个字符);会成为自定义标题 | +| `metadata` | object | 否 | 合并进会话自定义元数据的键 | +| `agent_config` | object | 否 | main agent 的部分配置;字段见下,均为可选,且都会立即应用 | +| `permission_rules` | array | 否 | 被接受但不回显(T-Session 恒 `permission_rules: []`) | + +`agent_config` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `model` | string | 模型别名 id;空字符串会被忽略 | +| `thinking` | string | Thinking 强度等级 | +| `permission_mode` | string | `manual` / `yolo` / `auto` | +| `plan_mode` | boolean | 进入或退出 Plan 模式 | +| `swarm_mode` | boolean | 进入或退出 swarm 模式 | +| `tower_mode` | boolean | 进入或退出 tower 模式 | +| `tower_base` | string | 配合 `tower_mode: true` 的 tower 基础引用 | +| `goal_objective` | string | 以该文本为内容创建一个目标 | +| `goal_control` | string | `pause` / `resume` / `cancel` 当前目标 | + +schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers`,但更新路由当前不会应用它们。 + +**data**(code = 0):[T-Session](#t-session)(更新后)。 + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "title": "Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/title/generate` + +通过托管供应商的 `chat_title` 工具根据会话的提示词生成标题并应用,同时广播 `session.meta.updated`。生成需要托管 OAuth 登录和 `auto_session_title` 实验开关;未提供 `force` 时,已有自定义标题或已生成标题的会话会上报为不可用。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `force` | boolean | 否 | 即使已有自定义或生成的标题也重新生成。默认 `false` | +| `source` | string | 否 | 标题输入:`user_prompts`(默认)/ `first_turn` / `digest` | + +**data**(code = 0):`{ "title": string }`——当前应用到会话的标题。 + +**非零 code**:`40401`、`40923`(开关未开启、没有托管登录或尚无提示词内容、已有标题但未提供 `force`,或后端请求失败)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "title": "Fix the login page" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}:{action}` + +会话动作经同一条路由分发:路径尾部解析为 `{session_id}:{action}`,请求体按动作的 schema 校验。每个动作都会先解析会话,因此会话未知时都可能返回 `40401`。 + +| 动作 | Body | data(code = 0) | 特有非零 code | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `before_id` | query | string | 只保留早于该 id 的子会话;与 `after_id` 互斥 | -| `after_id` | query | string | 只保留晚于该 id 的子会话;与 `before_id` 互斥 | -| `page_size` | query | integer | 1–100。默认 `100` | -| `busy` | query | boolean | 只保留忙碌(或只保留空闲)的子会话 | +| `:fork` | `{ title?, metadata? }` | [T-Session](#t-session)(新会话;广播 `event.session.created`) | `40901`(有进行中的轮次) | +| `:compact` | `{ instruction? }` | `{}`(空对象;进度经 `compaction.*` 事件投递) | `40910`(有轮次或上下文变更进行中,或无可压缩内容) | +| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,见 [响应信封](#响应信封)) | +| `:abort` | 无 | `{ "aborted": true }` | — | +| `:btw` | 无 | `{ "agent_id": string }`——把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文;需要可用的模型配置 | — | +| `:archive` | 无 | `{ "archived": true }`——会话从默认列表中消失(`include_archive` / `archived_only` 仍会列出),广播 `event.session.archived` | — | +| `:restore` | 无 | [T-Session](#t-session)(`archived: false`) | — | + +共有非零 code:`40001`(动作缺失或未知)、`40401`。 + +**示例**(`:fork`): + +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX5...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fork: Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/children` + +列出会话的子会话——即通过 `POST .../children` 创建的会话。游标分页遵循 [分页](#分页)。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `before_id` | string | 只保留早于该 id 的子会话;与 `after_id` 互斥 | +| `after_id` | string | 只保留晚于该 id 的子会话;与 `before_id` 互斥 | +| `page_size` | integer | 1–100。默认 `100` | +| `busy` | boolean | 只保留忙碌(或只保留空闲)的子会话 | + +**data**(code = 0):`{ items: T-Session[], has_more: boolean }`。 -成功时,`data` 为 `{ items, has_more }`,其中每个元素为 [session 对象](#session-对象)。 +**非零 code**:`40401`。 -- `40401`:会话不存在 +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "session_01JZX5...", "...": "..." } ], "has_more": false }, "request_id": "01JZX4..." } +``` #### `POST /api/v1/sessions/{session_id}/children` -创建子会话:fork 当前会话并记录为其子会话,因此会出现在 `GET /api/v1/sessions/{session_id}/children` 下。适用与 `:fork` 相同的进行中轮次限制。 +创建子会话:fork 当前会话并记录为其子会话;广播 `event.session.created`。适用与 `:fork` 相同的进行中轮次限制。 + +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `title` | body | string | 子会话的标题(至少 1 个字符)。默认 `Child: ` | -| `metadata` | body | object | 子会话的自定义元数据 | +| `title` | string | 否 | 子会话的标题(至少 1 个字符)。默认 `Child: ` | +| `metadata` | object | 否 | 子会话的自定义元数据 | + +**data**(code = 0):[T-Session](#t-session)。 + +**非零 code**:`40001`、`40401`、`40901`。 -成功时,`data` 为新会话的 [session 对象](#session-对象),并且服务端广播 `event.session.created`。 +**示例**: -- `40901`:会话有进行中的轮次,无法 fork +```json +{ "code": 0, "msg": "success", "data": { "id": "session_01JZX6...", "title": "Child: Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/sessions/{session_id}/status` -main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复。 +main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**data**(code = 0):[T-SessionStatus](#t-sessionstatus)。 + +**非零 code**:`40401`。 -成功时,`data` 为 `{ busy, model?, thinking_level, permission, plan_mode, swarm_mode, context_tokens, max_context_tokens?, context_usage? }`:`busy` 表示是否有进行中的轮次,`model` / `thinking_level` / `permission` 为当前生效的 Agent 设置,`plan_mode` / `swarm_mode` 为模式标志,`context_tokens` 与 `max_context_tokens`、`context_usage`(0–1)描述上下文窗口的占用情况。 +**示例**: -- `40401`:会话不存在 +```json +{ "code": 0, "msg": "success", "data": { "busy": false, "model": "kimi-for-coding", "thinking_level": "medium", "permission": "manual", "plan_mode": false, "swarm_mode": false, "tower_mode": false, "context_tokens": 15230, "max_context_tokens": 262144, "context_usage": 0.058 }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/sessions/{session_id}/goal` -读取会话当前的目标快照;没有活跃目标时为 `null`。注意,与本 API 的大多数载荷不同,该载荷使用 camelCase 键。 +读取会话当前的目标快照;没有活跃目标时为 `null`。注意该载荷使用 camelCase 键。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**data**(code = 0):[T-GoalSnapshot](#t-goalsnapshot) 或 `null`。 + +**非零 code**:`40401`。 -成功时,`data` 为 `null` 或 `{ goalId, objective, completionCriterion?, status, turnsUsed, tokensUsed, wallClockMs, budget, terminalReason? }`,其中 `status` 为 `active` / `paused` / `blocked` / `complete`,`budget` 报告 token、轮次与 wall-clock 三项预算,以及各自的剩余量与每项预算的 reached 标志(未设置对应预算时各项为 null)。 +**示例**: -- `40401`:会话不存在 +```json +{ "code": 0, "msg": "success", "data": { "goalId": "goal_...", "objective": "Ship the release", "status": "active", "turnsUsed": 3, "tokensUsed": 152000, "wallClockMs": 540000, "budget": { "tokenBudget": 1000000, "turnBudget": 50, "wallClockBudgetMs": null, "remainingTokens": 848000, "remainingTurns": 47, "remainingWallClockMs": null, "tokenBudgetReached": false, "turnBudgetReached": false, "wallClockBudgetReached": false, "overBudget": false } }, "request_id": "01JZX4..." } +``` #### `GET /api/v1/sessions/{session_id}/warnings` -读取会话级告警。目前的产生者只有 `AGENTS.md` 过大检查(`agents-md-oversized`),因此大多数会话的列表为空。 +读取会话级告警。目前的产生者只有 `AGENTS.md` 过大检查(`agents-md-oversized`),因此大多数会话的列表为空。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `warnings` | array | `{ code, message, severity }[]`;`severity` 为 `info` / `warning` / `error` | + +**非零 code**:`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "warnings": [ { "code": "agents-md-oversized", "message": "AGENTS.md is ...", "severity": "warning" } ] }, "request_id": "01JZX4..." } +``` + +### 运行时绑定 -成功时,`data` 为 `{ warnings }`,每个条目为 `{ code, message, severity }`,其中 `severity` 为 `info` / `warning` / `error` 之一。 +main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 -- `40401`:会话不存在 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/runtime` | 读取 main agent 的运行时绑定 | +| `POST /api/v1/sessions/{session_id}/runtime` | 切换 main agent 的运行时绑定 | #### `GET /api/v1/sessions/{session_id}/runtime` -读取 main agent 的运行时绑定——即该会话的 Agent 循环运行在哪个运行时上。 +读取 main agent 的运行时绑定。无参数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `workspace_id` | string | 所属工作区 id | +| `runtime_id` | string | 当前绑定的运行时 id | + +**非零 code**:`40401`。 -成功时,`data` 为 `{ workspace_id, runtime_id }`。 +**示例**: -- `40401`:会话不存在 +```json +{ "code": 0, "msg": "success", "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, "request_id": "01JZX4..." } +``` #### `POST /api/v1/sessions/{session_id}/runtime` 切换 main agent 的运行时绑定。 -| 参数 | 位置 | 类型 | 说明 | +**Body**: + +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `runtime_id` | body | string | **必填。** 目标运行时 id | +| `runtime_id` | string | 是 | 目标运行时 id | + +**data**(code = 0):同 `GET .../runtime`。 + +**非零 code**:`40001`、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 + +**示例**: -成功时,`data` 为新的绑定 `{ workspace_id, runtime_id }`。 +```json +{ "code": 0, "msg": "success", "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, "request_id": "01JZX4..." } +``` + +### 会话导出 + +#### `POST /api/v1/sessions/{session_id}/export` + +将会话连同诊断日志一起导出为 zip 附件(`kimi-session-.zip`)。响应是 `application/zip` 二进制流,不走信封(`content-disposition: attachment`、`cache-control: no-store`);客户端断连即中止导出。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `web_log` | string | 否 | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 | +| `desktop` | boolean | 否 | 同时包含桌面宿主的日志。默认 `false` | + +**非零 code**(JSON 信封):`40001`、`40401`、`50001`。 + +### 消息 + +`messages` 端点分页返回 main agent 的扁平化消息历史;按 Agent 组织的结构化转录见 [转录](#转录)。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/messages` | 消息分页(`before_id` / `after_id` / `role`) | +| `GET /api/v1/sessions/{session_id}/messages/{message_id}` | 读取单条消息 | + +#### `GET /api/v1/sessions/{session_id}/messages` + +分页返回 main agent 的消息历史,最新在前;读取历史会在会话为冷态时将其恢复。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `before_id` | string | 只保留早于该消息 id 的消息;与 `after_id` 互斥 | +| `after_id` | string | 只保留晚于该消息 id 的消息;与 `before_id` 互斥 | +| `page_size` | integer | 1–100。默认 `50` | +| `role` | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | + +**data**(code = 0):`{ items: T-Message[], has_more: boolean }`([T-Message](#t-message))。 + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "assistant", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:05:00.000Z" } ], "has_more": true }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/messages/{message_id}` + +按 id 从同一历史中读取单条消息。无参数。 + +**data**(code = 0):[T-Message](#t-message)。 + +**非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "user", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "request_id": "01JZX4..." } +``` + +### 提示词 + +提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列;轮次进度通过 [WebSocket 时序](#websocket-时序) 推送,不经过这些端点。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/prompts` | 进行中与排队中的提示词 | +| `POST /api/v1/sessions/{session_id}/prompts` | 提交提示词(内容块数组,可带模型 / 权限模式覆盖) | +| `POST /api/v1/sessions/{session_id}/prompts:steer` | 把排队的提示词插入进行中的轮次 | +| `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:{action}` | 单条提示词动作:`abort` / `steer` | + +#### `GET /api/v1/sessions/{session_id}/prompts` + +读取 main agent 的提示词队列快照。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `active` | object \| null | 运行中的提示词([T-PromptItem](#t-promptitem)),空闲时为 `null` | +| `queued` | array | 等待中的 [T-PromptItem](#t-promptitem),按顺序 | + +**非零 code**:`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "active": { "prompt_id": "prompt_01J...", "user_message_id": "msg_session_..._000007", "status": "running", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "queued": [] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/prompts` + +向会话提交一条用户提示词。先校验媒体引用,然后把可选的覆盖项应用到目标 Agent——`profile`(与 `model` / `thinking` 一起绑定),接着是 `model`、`thinking`、`permission_mode` 和 `disabled_tools`——随后提示词入队;响应在提示词被接受后立即返回,不等待轮次执行。提供 `skills` 时,提示词以打包的 Skill 激活方式运行,而不是普通用户提示词。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `content` | array | 是 | 非空的内容块数组;变体见下 | +| `agent_id` | string | 否 | 目标 Agent。默认为 main agent | +| `prompt_id` | string | 否 | 客户端选定的提示词 id,用于幂等提交;已被进行中提示词占用的 id 返回 `40927`,已完成的返回 `40903`。不能与 `skills` 同用 | +| `skills` | array | 否 | 打包的 Skill 激活,至少 1 个 `{ name, args? }` 条目;每个 Skill 必须存在且可由用户激活 | +| `profile` | string | 否 | 提交前要绑定的 Agent 档案 | +| `model` | string | 否 | 要切换到的模型别名 | +| `thinking` | string | 否 | Thinking 强度等级 | +| `permission_mode` | string | 否 | `manual` / `yolo` / `auto` | +| `disabled_tools` | array | 否 | 要为会话禁用的工具名 | + +schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 `goal_control`,但提交路由当前不会应用它们。每个 `content` 内容块是按 `type` 区分的对象: + +| 内容块 | 字段 | 说明 | +| --- | --- | --- | +| `text` | `text` | 纯文本 | +| `image` / `video` | `source` | 媒体输入;`source` 为 `{ kind: "url", url, id? }`、`{ kind: "base64", media_type, data }`、`{ kind: "file", file_id }`(来自 `POST /api/v1/files` 的上传)或 `{ kind: "session_media", file_id }`(已提交到本会话的媒体)之一 | +| `file` | `file_id`、`name`、`media_type`、`size` | 通过 `POST /api/v1/files` 上传的文件附件 | + +schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinking` 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 `file_id` 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。 + +**data**(code = 0):[T-PromptItem](#t-promptitem)(被接受的提示词)。 + +**非零 code**(鉴权错误族的 `data` / `details` 形态各异): + +- `40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40407`(引用的 `file_id` 不存在或 kind 不匹配)、`40415`(未知的 Skill)、`40901`(会话忙)、`40912`(Skill 无法由用户激活)、`40927`(`prompt_id` 冲突) +- `40110`(尚未配置供应商):`data: null`,`details: null` +- `40111` / `40112`(供应商没有凭据 / 凭据被拒绝):`data: null`,`details: { provider_id }`(缺 `provider_id` 时降级为 `50001`) +- `40113`(模型无法解析):`data: null`,`details: { model_id?, provider_id? }` 或 `null` +- `40903`(`prompt_id` 属于已完成的提示词):`data: { "aborted": false }` + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "prompt_id": "prompt_01J...", "user_message_id": "msg_session_..._000008", "status": "running", "content": [ { "type": "text", "text": "用一句话介绍这个仓库" } ], "created_at": "2026-09-02T08:06:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/prompts:steer` + +把排队的提示词插入进行中的轮次,让运行中的轮次立即消费它们,而不是先运行结束。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `prompt_ids` | array | 是 | 非空的排队提示词 id 数组 | + +**data**(code = 0):`{ "steered": true, "prompt_ids": string[] }`。 + +**非零 code**:`40001`、`40401`、`40402`(所列提示词 id 不在队列中)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "steered": true, "prompt_ids": [ "prompt_01J..." ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:{action}` + +单条提示词动作,经 `POST .../prompts/{tail}` 分发:`:abort` 中止运行中的提示词;`:steer` 把单条排队的提示词插入进行中的轮次(集合形式的单提示词版)。无请求体。 + +**data**(code = 0):`:abort` → `{ "aborted": true }`;`:steer` → `{ "steered": true, "prompt_ids": [prompt_id] }`。 + +**非零 code**:`40001`(动作缺失或未知)、`40401`、`40402`、`40903`(提示词已完成,`data: { "aborted": false }`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "aborted": true }, "request_id": "01JZX4..." } +``` + +### 审批 + +审批是为工具调用请求许可的待处理交互。新的请求通过 WebSocket 以 `event.approval.requested` 到达;这两个端点用于列出和答复。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/approvals` | 列出待处理的审批请求(必须 `status=pending`) | +| `POST /api/v1/sessions/{session_id}/approvals/{approval_id}` | 答复审批 | + +#### `GET /api/v1/sessions/{session_id}/approvals` + +列出会话待处理的审批请求;读取列表会在会话为冷态时将其恢复。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-ApprovalRequest](#t-approvalrequest) 数组 | + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "approval_id": "approval_01J...", "session_id": "session_01JZX4...", "turn_id": 3, "tool_call_id": "toolu_01J...", "tool_name": "Bash", "action": "run", "tool_input_display": { "kind": "command", "command": "pnpm test" }, "created_at": "2026-09-02T08:06:30.000Z", "expires_at": "2026-09-03T08:06:30.000Z" } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/approvals/{approval_id}` + +答复一个待处理的审批请求,让等待中的工具调用继续执行(或不执行)。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `decision` | string | 是 | `approved` / `rejected` / `cancelled` | +| `scope` | string | 否 | 配合 `approved` 使用,`session`(唯一取值)还会让该审批规则在会话的剩余时间内被记住 | +| `feedback` | string | 否 | 回传给 Agent 的自由文本反馈 | +| `selected_label` | string | 否 | 当请求提供了带标签的选项时(例如计划审阅),所选选项的标签 | + +**data**(code = 0):`{ "resolved": true, "resolved_at": ISO }`。 + +**非零 code**:`40001`、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:00.000Z" }, "request_id": "01JZX4..." } +``` + +### 提问 + +提问是请求带标签选项的结构化输入的待处理交互。新的请求通过 WebSocket 以 `event.question.requested` 到达。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/questions` | 列出待处理的提问(必须 `status=pending`) | +| `POST /api/v1/sessions/{session_id}/questions/{question_id}` | 回答提问 | +| `POST /api/v1/sessions/{session_id}/questions/{question_id}:dismiss` | 忽略提问 | + +#### `GET /api/v1/sessions/{session_id}/questions` + +列出会话待处理的提问。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-QuestionRequest](#t-questionrequest) 数组 | + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "question_id": "question_01J...", "session_id": "session_01JZX4...", "questions": [ { "id": "q_0", "question": "选择部署目标", "options": [ { "id": "opt_0_0", "label": "staging" }, { "id": "opt_0_1", "label": "production" } ], "allow_other": true } ], "created_at": "2026-09-02T08:06:40.000Z" } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/questions/{question_id}` + +回答一个待处理的提问。两个提问端点经同一条路由 `POST .../questions/{tail}` 分发:单独的提问 id 表示回答问题,`{question_id}:dismiss` 尾部表示忽略。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `answers` | object | 是 | 提问条目 id(`q_0`……)到答案对象的映射;答案变体见下 | +| `method` | string | 否 | 答案的产生方式:`enter` / `space` / `number_key` / `click` | +| `note` | string | 否 | 附在回答上的自由文本备注 | + +每个答案是按 `kind` 区分的对象: + +| `kind` | 字段 | 说明 | +| --- | --- | --- | +| `single` | `option_id` | 选中的单个选项 | +| `multi` | `option_ids` | 选中的多个选项(至少 1 个) | +| `other` | `text` | 自由文本回答 | +| `multi_with_other` | `option_ids`、`other_text` | 选项加自由文本 | +| `skipped` | — | 跳过了该条目 | + +**data**(code = 0):`{ "resolved": true, "resolved_at": ISO }`。 + +**非零 code**:`40001`(`details` 逐字段说明)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:10.000Z" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/questions/{question_id}:dismiss` + +忽略一个待处理的提问,不作回答。无请求体。 + +**成功形态**:信封的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码(见 [响应信封](#响应信封))。 + +**非零 code**:`40401`、`40405`、`40902`(已被答复,`data: { "resolved": false }`)。 + +**示例**: + +```json +{ "code": 40909, "msg": "question dismissed", "data": { "dismissed": true, "dismissed_at": "2026-09-02T08:07:20.000Z" }, "request_id": "01JZX4..." } +``` + +### 后台任务 + +后台任务是会话的异步单元——后台 Shell、subagent 与长时间运行的工具任务。注册表仅包含实时数据:未加载到本服务进程中的会话会返回空列表。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/tasks` | 列出后台任务 | +| `GET /api/v1/sessions/{session_id}/tasks/{task_id}` | 读取任务(可选输出预览) | +| `POST /api/v1/sessions/{session_id}/tasks/{task_id}:{action}` | 任务动作:`cancel` / `detach` | + +#### `GET /api/v1/sessions/{session_id}/tasks` + +列出会话的后台任务。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `status` | string | 只保留单一状态:`running` / `completed` / `failed` / `cancelled` | + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-Task](#t-task) 数组;冷会话为 `[]` | + +**非零 code**:`40001`(未知的 `status`)、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "task_01J...", "session_id": "session_01JZX4...", "kind": "bash", "description": "pnpm test", "status": "running", "created_at": "2026-09-02T08:06:00.000Z", "started_at": "2026-09-02T08:06:00.000Z", "command": "pnpm test", "run_in_background": true } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/tasks/{task_id}` + +读取单个后台任务,可选携带输出的末尾片段。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `with_output` | boolean | 在响应中包含输出末尾片段。默认 `false` | +| `output_bytes` | integer | 请求的输出末尾片段的字节大小,最小 `0`。默认 `32768` | + +**data**(code = 0):[T-Task](#t-task);`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 + +**非零 code**:`40001`、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "task_01J...", "session_id": "session_01JZX4...", "kind": "bash", "description": "pnpm test", "status": "completed", "created_at": "2026-09-02T08:06:00.000Z", "started_at": "2026-09-02T08:06:00.000Z", "completed_at": "2026-09-02T08:06:40.000Z", "command": "pnpm test", "output_preview": "... tail of output ...", "output_bytes": 4096, "run_in_background": true }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/tasks/{task_id}:{action}` + +任务动作经 `POST .../tasks/{tail}` 分发:`:cancel` 取消运行中的任务;`:detach` 将运行中的前台任务转入后台而不终止它(等待该任务的工具调用立即以后台任务结果返回,轮次继续推进)。已在后台或已结束的任务上 `:detach` 为幂等空操作。无请求体。 + +**data**(code = 0):`:cancel` → `{ "cancelled": true }`;`:detach` → `{ "detached": boolean, "status": string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 + +**非零 code**:`40001`(动作缺失或未知)、`40401`、`40406`、`40904`(任务已结束,`data: { "cancelled": false }` 且 `details: { "current_status" }`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "detached": true, "status": "running" }, "request_id": "01JZX4..." } +``` + +### 终端 + +PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定会跳过它们,除非传入 `--allow-remote-terminals`)。注意:终端输入输出的 `terminal_*` WebSocket 帧当前是死协议(见 [terminal 帧](#terminal-帧))——REST 侧只管理终端生命周期。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/terminals` | 列出终端 | +| `POST /api/v1/sessions/{session_id}/terminals` | 创建终端 | +| `GET /api/v1/sessions/{session_id}/terminals/{terminal_id}` | 读取终端 | +| `POST /api/v1/sessions/{session_id}/terminals/{terminal_id}:close` | 关闭终端 | + +#### `GET /api/v1/sessions/{session_id}/terminals` + +列出会话的终端;读取列表会在会话为冷态时将其恢复。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-Terminal](#t-terminal) 数组 | + +**非零 code**:`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "running", "created_at": "2026-09-02T08:08:00.000Z" } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/terminals` + +为会话创建一个 PTY 终端。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `runtime_id` | string | 否 | 生成终端进程的运行时。默认 `local` | +| `cwd` | string | 否 | 工作目录,相对于会话工作区(传绝对路径会校验失败)。默认工作区根目录 | +| `shell` | string | 否 | Shell 可执行文件。默认该运行时的 shell | +| `cols` | integer | 否 | 终端宽度,正数。默认 `80` | +| `rows` | integer | 否 | 终端高度,正数。默认 `24` | + +**data**(code = 0):[T-Terminal](#t-terminal)。 + +**非零 code**:`40001`(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "running", "created_at": "2026-09-02T08:08:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/terminals/{terminal_id}` + +读取单个终端。无参数。 + +**data**(code = 0):[T-Terminal](#t-terminal)。 + +**非零 code**:`40401`、`40414`(没有该 id 的终端)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "exited", "created_at": "2026-09-02T08:08:00.000Z", "exited_at": "2026-09-02T08:09:00.000Z", "exit_code": 0 }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/terminals/{terminal_id}:close` + +关闭终端并结束其进程。经 `POST .../terminals/{tail}` 分发,`close` 是唯一动作。无请求体。 + +**data**(code = 0):`{ "closed": true }`。 + +**非零 code**:`40001`(缺少动作后缀或动作未知)、`40401`、`40414`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "closed": true }, "request_id": "01JZX4..." } +``` + +### 技能 + +会话或工作区可见的技能目录,以及技能激活——激活即斜杠命令 `/` 的 REST 等价形式。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/skills` | 会话级技能目录 | +| `GET /api/v1/workspaces/{workspace_id}/skills` | 无会话的工作区技能目录 | +| `POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate` | 激活技能(开启一个轮次) | + +#### `GET /api/v1/sessions/{session_id}/skills` + +列出单个会话可用的技能,按会话的优先级合并所有来源(内置、插件、extra、用户、项目);会话处于冷态时读取目录会恢复该会话。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `skills` | array | [T-SkillDescriptor](#t-skilldescriptor) 数组 | + +**非零 code**:`40401`(会话不存在或未激活)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "skills": [ { "name": "review", "description": "...", "path": "/Users/dev/my-app/.agents/skills/review/SKILL.md", "source": "project" } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/workspaces/{workspace_id}/skills` + +列出该工作区中的会话将看到的技能目录,但不创建或恢复会话。无参数。 + +**data**(code = 0):同 `GET /api/v1/sessions/{session_id}/skills`。 + +**非零 code**:`40410`(工作区不存在)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "skills": [ { "name": "review", "description": "...", "path": "...", "source": "project" } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate` + +在会话中激活技能——以技能内容加上 `args` 与附件在 main agent 上开启一个轮次。经 `POST .../skills/{tail}` 分发,`activate` 是唯一动作。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `args` | string | 否 | 传给技能的自由文本参数,相当于斜杠命令后的文本 | +| `attachments` | array | 否 | 随激活携带的媒体块。`image` / `video` 块带 `source` 对象(`kind` 为 `url` / `base64` / `file` / `session_media`,与提示词内容块同形);`file` 块带顶层 `file_id`、`name`、`media_type`、`size` | + +**data**(code = 0):`{ "activated": true, "skill_name": string }`。 + +**非零 code**:`40001`(校验失败或动作后缀不支持)、`40401`、`40407`(引用的附件文件不存在)、`40415`(没有该名称的技能)、`40912`(技能类型不允许用户激活)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "activated": true, "skill_name": "review" }, "request_id": "01JZX4..." } +``` + +### 工作区 + +工作区是已注册的项目目录,会话都落在其中。这组端点管理注册表与每工作区信任状态(控制项目级 MCP 配置是否加载),以及附加目录。返回的工作区对象统一为 [T-Workspace](#t-workspace)。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/workspaces` | 列出已注册工作区 | +| `POST /api/v1/workspaces` | 注册工作区(按根路径幂等) | +| `PATCH /api/v1/workspaces/{workspace_id}` | 重命名 | +| `DELETE /api/v1/workspaces/{workspace_id}` | 注销(保留磁盘内容) | +| `GET /api/v1/workspaces/{workspace_id}/trust` | 读取信任状态 | +| `POST /api/v1/workspaces/{workspace_id}/trust` | 授予信任 | +| `POST /api/v1/workspaces/{workspace_id}/untrust` | 撤销信任 | +| `POST /api/v1/workspaces/{workspace_id}/add-dir` | 添加附加目录 | + +#### `GET /api/v1/workspaces` + +列出所有已注册工作区。无参数。 + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | array | [T-Workspace](#t-workspace) 数组 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 } ] }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/workspaces` + +注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `root` | string | 是 | 已存在目录的绝对路径 | +| `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | + +**data**(code = 0):[T-Workspace](#t-workspace)。 + +**非零 code**:`40001`(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-02T08:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 0 }, "request_id": "01JZX4..." } +``` + +#### `PATCH /api/v1/workspaces/{workspace_id}` + +重命名工作区——仅修改显示名,根路径不变。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `name` | string | 是 | 新的显示名,1–100 个字符 | + +**data**(code = 0):[T-Workspace](#t-workspace)。 + +**非零 code**:`40001`、`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "My App", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 }, "request_id": "01JZX4..." } +``` + +#### `DELETE /api/v1/workspaces/{workspace_id}` + +注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 + +**data**(code = 0):`{ "deleted": true }`。 + +**非零 code**:`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/workspaces/{workspace_id}/trust` + +读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。无参数。 + +**data**(code = 0):`{ "trusted": boolean }`。 + +**非零 code**:`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/workspaces/{workspace_id}/trust` + +将工作区标记为信任,并加载其项目级 MCP 配置。无请求体。 + +**data**(code = 0):`{ "trusted": true }`。 + +**非零 code**:`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/workspaces/{workspace_id}/untrust` + +撤销工作区信任,并卸载其项目级 MCP 配置。无请求体。 + +**data**(code = 0):`{ "trusted": false }`。 + +**非零 code**:`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "trusted": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/workspaces/{workspace_id}/add-dir` + +为工作区添加附加目录,语义与 CLI `--add-dir` 及 TUI `/add-dir` 一致。路径支持绝对路径、相对路径(相对工作区根目录解析)与 `~` 展开。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要添加的目录 | +| `persist` | boolean | 否 | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | + +**data**(code = 0): + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `project_root` | string | 项目根目录 | +| `config_path` | string | 写入的本地配置文件路径 | +| `additional_dirs` | array | 全部附加目录(含既有目录) | +| `persisted` | boolean | 本次是否写盘 | + +**非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误)、`40409`(`path` 不存在或不是目录)、`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "project_root": "/Users/dev/my-app", "config_path": "/Users/dev/my-app/.kimi-code/local.toml", "additional_dirs": [ "/Users/dev/shared-lib" ], "persisted": true }, "request_id": "01JZX4..." } +``` + +### 文件系统 + +会话内文件操作走 `POST /api/v1/sessions/{session_id}/fs:{action}`,请求体为 JSON;另有工作区级与本机级的补充端点。每个动作的请求体还接受可选的 `runtime_id`(string,默认 `local`),用于选择执行操作的运行时;`search`、`grep`、`git_status` 与 `diff` 额外要求运行时具备 process capability(进程执行能力),`open`、`open-in` 与 `reveal` 仅在 `local` 运行时上可用。 + +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/sessions/{session_id}/fs:{action}` | 会话内文件操作:`list` / `read` / `list_many` / `stat` / `stat_many` / `mkdir` / `search` / `grep` / `git_status` / `diff` / `open` / `open-in` / `reveal` | +| `POST /api/v1/workspace/fs:search` | 无会话的工作区搜索(body 携带工作区引用) | +| `POST /api/v1/workspace/fs:suggest` | 无会话的文件补全候选(用于 `@` 文件提及) | +| `POST /api/v1/fs:suggest` | 跨根目录的文件补全候选(body 携带 `roots`) | +| `GET /api/v1/sessions/{session_id}/fs/{path}:download` | 下载会话文件(二进制) | +| `GET /api/v1/fs:browse` | 列出本机目录(文件夹选择器用) | +| `GET /api/v1/fs:home` | 用户主目录与最近工作区 | +| `GET /api/v1/fs:content` | 读取本机任意文件原始字节(仅受 token 保护,谨慎暴露端口) | +| `POST /api/v1/fs:mkdir` | 按绝对路径创建目录 | + +#### `POST /api/v1/sessions/{session_id}/fs:list` + +列出会话工作区目录下的条目,可选递归子目录。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 否 | 要列出的目录,相对于会话工作目录。默认 `.` | +| `depth` | integer | 否 | 递归深度,1–10。默认 `1` | +| `limit` | integer | 否 | 最大条目数,1–1000。默认 `200` | +| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `exclude_globs` | array | 否 | 额外要跳过的 glob | +| `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | +| `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | + +**data**(code = 0):[T-FsListResponse](#t-fslistresponse)。 + +**非零 code**:`40001`、`40401`、`40409`(路径不存在或不是目录)、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src", "name": "src", "kind": "directory", "modified_at": "2026-09-01T10:00:00.000Z", "child_count": 12 }, { "path": "package.json", "name": "package.json", "kind": "file", "size": 1024, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "application/json" } ], "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:read` + +以文本或 base64 读取会话文件的一段内容。`encoding: "auto"` 时文本以 `utf-8` 返回(非 UTF-8 文本会被转码),二进制内容以 `base64` 返回;`encoding: "utf-8"` 强制按文本读取并拒绝二进制文件。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 文件路径,相对于会话工作目录 | +| `offset` | integer | 否 | 起始字节偏移。默认 `0` | +| `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | +| `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | + +**data**(code = 0):[T-FsReadResponse](#t-fsreadresponse)。 + +**非零 code**:`40001`、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "content": "import ...", "encoding": "utf-8", "size": 20480, "truncated": false, "etag": "...", "mime": "text/typescript", "language_id": "typescript", "line_count": 512, "is_binary": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:list_many` + +一次调用列出多个会话目录;失败的路径折进响应里,而不是让整个请求失败。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `paths` | array | 是 | 要列出的目录,1–100 条 | + +其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 + +**data**(code = 0):[T-FsListManyResponse](#t-fslistmanyresponse)。 + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "results": { "src": [ { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." } ] }, "truncated_paths": [ "src" ], "partial_errors": { "vendor": { "code": 40409, "msg": "path does not exist" } } }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:stat` + +查询会话工作区内单个路径的元信息。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要查询的路径,相对于会话工作目录 | + +**data**(code = 0):[T-FsEntry](#t-fsentry)。 + +**非零 code**:`40001`、`40401`、`40409`、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "size": 20480, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "text/typescript", "is_binary": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:stat_many` + +一次调用查询多个会话路径的元信息;不存在的路径返回 `null`,不会让整个请求失败。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `paths` | array | 是 | 要查询的路径,1–1000 条 | + +**data**(code = 0):[T-FsStatManyResponse](#t-fsstatmanyresponse)。 + +**非零 code**:`40001`、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "entries": { "src/index.ts": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." }, "vendor": null } }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:mkdir` + +在会话工作区内创建目录。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要创建的目录,相对于会话工作目录 | +| `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | + +**data**(code = 0):[T-FsEntry](#t-fsentry)(所建目录)。 + +**非零 code**:`40001`、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "path": "docs/api", "name": "api", "kind": "directory", "modified_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:search` + +在会话工作区内模糊搜索文件与目录名。`query` 为空时改为列出顶层条目。当 `{session_id}` 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 `POST /api/v1/workspace/fs:search`。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | +| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | + +**data**(code = 0):`{ items: T-FsSearchHit[], truncated: boolean }`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 + +**非零 code**:`40001`、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:grep` + +在会话工作区内搜索文件内容——默认按字面字符串,`regex: true` 时按正则表达式。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `pattern` | string | 是 | 要搜索的文本或正则 | +| `regex` | boolean | 否 | 将 `pattern` 视为正则表达式。默认 `false` | +| `case_sensitive` | boolean | 否 | 默认 `true` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的文件 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的文件 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `max_files` | integer | 否 | 最多扫描的文件数,1–10000。默认 `200` | +| `max_matches_per_file` | integer | 否 | 每个文件保留的匹配数,1–10000。默认 `50` | +| `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | +| `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | + +**data**(code = 0):[T-FsGrepResponse](#t-fsgrepresponse)。 + +**非零 code**:`40001`、`40401`、`41303`、`41305`(搜索超时)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "files": [ { "path": "src/index.ts", "matches": [ { "line": 12, "col": 8, "text": "const token = ...", "before": [ "..." ], "after": [ "..." ] } ] } ], "files_scanned": 87, "truncated": false, "elapsed_ms": 42 }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:git_status` + +读取会话工作区的 git 状态,可选限定在一组路径内。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | + +**data**(code = 0):[T-FsGitStatusResponse](#t-fsgitstatusresponse)(注意 camelCase `pullRequest`)。 + +**非零 code**:`40001`、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "branch": "main", "ahead": 1, "behind": 0, "entries": { "src/index.ts": "modified" }, "additions": 12, "deletions": 3, "pullRequest": { "number": 3451, "state": "open", "url": "https://github.com/example/repo/pull/3451" } }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:diff` + +返回会话工作区内单个文件的 unified git diff。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | + +**data**(code = 0):[T-FsDiffResponse](#t-fsdiffresponse)。 + +**非零 code**:`40001`、`40401`、`40908`、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "diff": "@@ -1,4 +1,5 @@\n ...", "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:open` + +用宿主操作系统的默认程序打开会话文件。仅限 local 运行时。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要打开的文件,相对于会话工作目录 | +| `line` | integer | 否 | 在处理程序支持时跳转到的行号(正整数) | + +**data**(code = 0):`{ "opened": true }`。 + +**非零 code**:`40001`、`40401`、`40409`、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:open-in` + +在指定的宿主应用程序中打开会话文件或目录。仅限 local 运行时。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `app_id` | string | 是 | 目标应用:`finder` / `cursor` / `vscode` / `iterm` / `terminal` | +| `path` | string | 是 | 要打开的文件或目录,相对于会话工作目录 | +| `line` | integer | 否 | 在应用支持时跳转到的行号(正整数) | + +**data**(code = 0):`{ "opened": true }`。 + +**非零 code**:`40001`、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/sessions/{session_id}/fs:reveal` + +在宿主操作系统的文件管理器中显示会话文件。仅限 local 运行时。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要显示的文件,相对于会话工作目录 | + +**data**(code = 0):`{ "revealed": true }`。 + +**非零 code**:`40001`、`40401`、`40409`、`41304`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "revealed": true }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/fs/{path}:download` + +从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流——见 [二进制与流式端点](#二进制与流式端点)。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `runtime_id` | string | 从哪个运行时读取。默认 `local` | + +**非零 code**(JSON 信封):`40001`(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 + +#### `POST /api/v1/workspace/fs:search` + +`fs:search` 的无会话形式:工作区改由请求体而非 URL 携带。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | +| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | +| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `runtime_id` | string | 否 | 在哪个运行时上搜索。默认 `local` | + +**data**(code = 0):`{ items: T-FsSearchHit[], truncated: boolean }`,命中结构与排序同 `fs:search`。 + +**非零 code**:`40001`、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/workspace/fs:suggest` + +在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 `@` 文件提及的后端。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | +| `query` | string | 是 | 要补全的部分路径文本 | +| `limit` | integer | 否 | 最大候选数,1–200。默认 `50` | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `runtime_id` | string | 否 | 在哪个运行时上补全。默认 `local` | + +**data**(code = 0):`{ items: T-FsSuggestItem[], truncated: boolean }`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 + +**非零 code**:`40001`、`40410`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/fs:suggest` + +`fs:suggest` 的工作区无关形式:请求体直接携带绝对 `roots`(1–32 条)。首 root 为主——其候选以相对路径返回,附加 root 的候选为绝对路径;重叠的 root 按 realpath 去重。每个 root 都会先 stat,不存在则整个请求失败。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `roots` | array | 是 | 绝对根路径数组,1–32 条 | +| `query` | string | 是 | 要补全的部分路径文本 | +| `limit` | integer | 否 | 最大候选数。默认 `50` | +| `follow_gitignore` | boolean | 否 | 默认 `true` | +| `show_hidden` | boolean | 否 | 默认 `false` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `runtime_id` | string | 否 | 默认 `local` | + +**data**(code = 0):`{ items: T-FsSuggestItem[], truncated: boolean }`。 + +**非零 code**:`40001`、`40409`(某个 root 不存在)、`40420`、`40926`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/fs:browse` + +列出某个本机目录的子目录——文件夹选择器的后端。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `path` | string | 绝对目录路径。默认用户主目录 | + +**data**(code = 0):[T-FsBrowseResponse](#t-fsbrowseresponse)。 + +**非零 code**:`40001`(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "path": "/Users/dev", "parent": "/Users", "entries": [ { "name": "my-app", "path": "/Users/dev/my-app", "is_dir": true } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/fs:home` + +返回文件夹选择器的落地数据。无参数。 + +**data**(code = 0):[T-FsHomeResponse](#t-fshomeresponse)(`recent_roots` 上限 8)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "home": "/Users/dev", "recent_roots": [ "/Users/dev/my-app" ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/fs:content` + +以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 [二进制与流式端点](#二进制与流式端点)。 -- `40420`:不存在该 `runtime_id` 的运行时 -- `40926`:运行时存在但不可用 +**Query**: -#### `POST /api/v1/sessions/{session_id}/export` +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `path` | string | **必填。** 绝对文件路径(realpath 解析) | -将会话连同诊断日志一起导出为 zip 附件(`kimi-session-.zip`)。响应是二进制流,不是 JSON 信封——能力与失败语义见 [二进制与流式端点](#二进制与流式端点)。 +**非零 code**(JSON 信封):`40001`(不是绝对路径或不是普通文件)、`40409`、`40411`、`40906`(路径是目录)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `web_log` | body | string | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 | -| `desktop` | body | boolean | 同时包含桌面宿主的日志。默认 `false` | +#### `POST /api/v1/fs:mkdir` -#### `GET /api/v1/sessions/{session_id}/snapshot` +按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。 -为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。 +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +| `path` | string | 是 | 绝对目录路径 | -成功时,`data` 为 `{ as_of_seq, epoch, session, messages, in_flight_turn, subagents?, pending_approvals, pending_questions }`:`session` 为 [session 对象](#session-对象),`messages` 为最新 100 条消息的 `{ items, has_more }`,`in_flight_turn` 为已部分流式输出的轮次(空闲时为 `null`,已知时带 `current_prompt_id`),`subagents` 列出存活的 subagent 任务,`pending_approvals` / `pending_questions` 承载未答复的交互。 +**data**(code = 0):`{ "path": string }`。 -- `40401`:会话不存在 - -#### `GET /api/v1/sessions/{session_id}/media/{file_id}` +**非零 code**:`40001`、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 -按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 `Range`(范围请求返回 206)——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里走信封的端点不同,会话或文件不存在时会返回真正的 404 状态码并携带信封体。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `file_id` | path | string | **必填。** 媒体文件 id | +```json +{ "code": 0, "msg": "success", "data": { "path": "/Users/dev/new-project" }, "request_id": "01JZX4..." } +``` -### 消息与转录 +### 文件上传与媒体 -`messages` 端点分页返回 main agent 的扁平化消息历史,`transcript` 端点则提供按 Agent 组织的结构化转录——轮次、任务、交互、附件——即 WebSocket [转录协议](#转录协议) 实时流式推送的内容。历史分页与补漏用这些端点,实时尾部用 WebSocket 订阅。 +提示词附件的上传、下载与删除;会话媒体按会话作用域寻址。 | 方法与路径 | 说明 | | --- | --- | -| `GET /api/v1/sessions/{session_id}/messages` | 消息分页(`before_id` / `after_id` / `role`) | -| `GET /api/v1/sessions/{session_id}/messages/{message_id}` | 读取单条消息 | -| `GET /api/v1/sessions/{session_id}/transcript` | 按轮次分页的转录(需 `agent_id`);全局状态不分页随响应返回 | -| `GET /api/v1/sessions/{session_id}/transcript/ops` | op 批次补漏(`since_seq`);`complete: false` 表示需要全量刷新 | -| `GET /api/v1/sessions/{session_id}/transcript/user-messages` | 各轮次起始的用户输入,不分页 | -| `GET /api/v1/sessions/{session_id}/transcript/plan` | ExitPlanMode 计划内容、路径与审阅结果 | +| `POST /api/v1/files` | multipart 上传,返回文件元信息 | +| `GET /api/v1/files/{file_id}` | 下载(二进制,错误用真实 HTTP 状态码) | +| `DELETE /api/v1/files/{file_id}` | 删除 | +| `GET /api/v1/sessions/{session_id}/media/{file_id}` | 按文件 id 下载提示词媒体(二进制) | -#### `GET /api/v1/sessions/{session_id}/messages` +#### `POST /api/v1/files` -分页返回 main agent 的消息历史——与会话快照共享的扁平化上下文转录——最新在前。游标分页遵循 [分页](#分页);读取历史会在会话为冷态时将其恢复。 +以 `multipart/form-data` 上传文件,供后续引用(例如作为提示词附件)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `before_id` | query | string | 只保留早于该消息 id 的消息;与 `after_id` 互斥 | -| `after_id` | query | string | 只保留晚于该消息 id 的消息;与 `before_id` 互斥 | -| `page_size` | query | integer | 1–100。默认 `50` | -| `role` | query | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | +**Body**(multipart): -成功时,`data` 为 `{ items, has_more }`,其中每个元素是消息对象 `{ id, session_id, role, content, created_at, prompt_id?, parent_message_id?, metadata? }`;`content` 是按 [提示词](#提示词) 中说明的线上格式组成的内容块数组(`text`、`tool_use`、`tool_result`、`image`、`video`、`file`、`thinking`)。 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `file` | binary | 是 | multipart 的文件部分 | +| `name` | string | 否 | 存储的显示名。默认上传文件名 | +| `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | -- `40001`:校验失败——例如 `before_id` 与 `after_id` 同用 -- `40401`:会话不存在 +**data**(code = 0):[T-FileMeta](#t-filemeta)。 -#### `GET /api/v1/sessions/{session_id}/messages/{message_id}` +**非零 code**:`40001`(multipart 未初始化或缺少 `file` 字段)。 -按 id 从同一历史中读取单条消息。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `message_id` | path | string | **必填。** 消息 id | +```json +{ "code": 0, "msg": "success", "data": { "id": "f_01JZX4...", "name": "screenshot.png", "media_type": "image/png", "size": 204800, "created_at": "2026-09-02T08:12:00.000Z" }, "request_id": "01JZX4..." } +``` -成功时,`data` 为上文 `GET /api/v1/sessions/{session_id}/messages` 中说明的元素形态的消息对象。 +#### `GET /api/v1/files/{file_id}` -- `40401`:会话不存在 -- `40403`:该会话中不存在此 id 的消息 +下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 -#### `GET /api/v1/sessions/{session_id}/transcript` +**非零 code**:`40407`(HTTP 404:没有该 id 的文件,包括已过期的)、`50001`(HTTP 500)。 -返回某个 Agent 的结构化转录中的一页:轮次(含其步骤与帧)以及轮次之间的标记与任务引用。活跃会话从内存存储应答(先回填所请求 Agent 的持久化历史);冷会话则从持久化的线上记录重建 Agent。这是转录能力的历史半边——实时流式半边是 [转录协议](#转录协议) 订阅。 +#### `DELETE /api/v1/files/{file_id}` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `agent_id` | query | string | **必填。** 要读取其转录的 Agent;必须是纯文本形式的 agent id(字母、数字、`.`、`_`、`-`——不含路径分隔符) | -| `before_turn` | query | string | 只保留早于该轮次 id 的轮次;与 `after_turn` 互斥 | -| `after_turn` | query | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | -| `page_size` | query | integer | 1–100 个轮次。默认 `20` | +删除已上传的文件。无请求体。 -分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次。成功时,`data` 为 `{ agent_id, items, has_more, tasks, interactions, attachments, todos, meta, agents, pending_interactions, seq? }`——`items` 是本次分页的轮次切片,`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态,`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话)。 +**data**(code = 0):`{ "deleted": true }`。 -- `40001`:校验失败——`before_turn` 与 `after_turn` 同用,或 `agent_id` 不是纯文本形式 -- `40401`:会话不存在 +**非零 code**:同下载——`40407`(HTTP 404)、`50001`(HTTP 500)。 -#### `GET /api/v1/sessions/{session_id}/transcript/ops` +**示例**: -从服务端的 op 日志提供点对点的补漏:某个 Agent 的 `seq > since_seq` 的已记录 op 批次,最旧在前。它是 [转录协议](#转录协议) 中 `transcript_since` 恢复游标的 REST 对应物,共享同一份有界日志,因此适用相同的回退规则。 +```json +{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `agent_id` | query | string | **必填。** Agent id(纯文本形式,约束与转录端点相同) | -| `since_seq` | query | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | +#### `GET /api/v1/sessions/{session_id}/media/{file_id}` -成功时,`data` 为 `{ agent_id, batches, latest_seq, complete }`,每个批次为 `{ seq, ops }`。`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。 +按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里走信封的端点不同,会话或文件不存在时返回真正的 404 状态码并携带信封体。 -- `40001`:校验失败 -- `40401`:会话不存在 +**非零 code**:`40401`(HTTP 404)、`40407`(HTTP 404)。 -#### `GET /api/v1/sessions/{session_id}/transcript/user-messages` +### 全局搜索 -列出会话中每个开启轮次的输入,按 Agent 分组且不分页:真实用户文本、以斜杠命令形式使用的 Skill 与插件命令、以及 cron 提示词——可通过 `origin` 区分——另有仅含附件的提示词,其 `prompt` 投影为空。所列消息引用的附件实体会随响应一起返回(仅元数据,绝不包含字节内容)。 +#### `POST /api/v1/search` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `agent_id` | query | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent | +跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。当 `container.session_id` 指向本服务进程中存活的会话时,搜索改为直接扫描该会话的内存转录,响应的 `source` 字段(`index` 或 `live`)会报告本页结果由哪条路径提供。分页遵循 [`page_token`](#分页) 风格。 -成功时,`data` 为 `{ agents }`,每个条目为 `{ agent_id, messages, attachments }`;消息为 `{ turn_id, ordinal, state, origin, prompt, attachment_ids?, started_at? }`,其中 `state` 为轮次状态(`queued` / `running` / `completed` / `failed` / `cancelled`)。 +**Body**: -- `40001`:校验失败——`agent_id` 不是纯文本形式 -- `40401`:会话不存在 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `query` | string | 是 | 搜索文本 | +| `mode` | string | 否 | `terms`(默认)/ `literal`(零误报的精确子串搜索) | +| `op` | string | 否 | `terms` 模式下的词项组合符:`AND`(默认)/ `OR` | +| `container` | object | 否 | 将搜索限定在 `{ session_id?, agent_id? }` | +| `role` | string | 否 | 限定 `user` / `assistant` / `title` 命中 | +| `start_time` | integer | 否 | 只看不早于该时间的命中(epoch 毫秒) | +| `end_time` | integer | 否 | 只看不晚于该时间的命中(epoch 毫秒) | +| `sort` | string | 否 | `score`(默认)/ `time_desc` / `time_asc`;`literal` 模式忽略此参数,始终最新在前 | +| `page_size` | integer | 否 | 每页命中数,1–50。默认 `20` | +| `page_token` | string | 否 | 上一页响应返回的令牌 | -#### `GET /api/v1/sessions/{session_id}/transcript/plan` +`terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 -按时间线顺序读取某个 Agent 的 `ExitPlanMode` 工具调用的计划信息——计划内容、计划文件路径、提供的选项以及审阅结果。内容投影自第一个可用的事实来源:关联的审批交互(交互式审阅)、实时工具帧的展示(auto 模式),或工具结果的输出文本;每个条目在 `source` 中记录了具体来源。 +**data**(code = 0):[T-SearchResponse](#t-searchresponse)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `agent_id` | query | string | **必填。** Agent id(纯文本形式) | -| `tool_call_id` | query | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | +**非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法)、`50001`。 -成功时,`data` 为 `{ agent_id, plans }`,每个计划为 `{ tool_call_id, turn_id, source, plan, path?, options?, review? }`:`source` 为 `interaction` / `display` / `output`,`options` 是审阅选项,形如 `{ label, description? }`,`review`(仅交互式审阅时存在)为 `{ state, selected_option?, feedback? }`,其中 `state` 为 `pending` / `approved` / `rejected` / `cancelled` 之一。 +**示例**: -- `40001`:校验失败 -- `40401`:会话不存在 -- `40416`:提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用 +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "session_id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "session_title": "Fix the login page", "agent_id": "main", "role": "user", "snippet": "...adjust the button spacing...", "time": 1787000000000, "turn": 3, "score": 2.31 } ], "has_more": false, "index_state": { "state": "ready", "indexed_sessions": 12, "total_sessions": 12, "documents": 340 }, "source": "index" }, "request_id": "01JZX4..." } +``` -### 提示词 +### GUI 存储 -提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列,排队中的提示词可以插入进行中的轮次,运行中的提示词可以中止。轮次进度本身通过 WebSocket [事件](#事件) 流式推送,不经过这些端点。 +由服务端支撑的键值存储,接口对齐浏览器的 `localStorage`,持久化在服务的 home 目录下;web UI 用它保存跨客户端的 UI 状态。值是不透明字符串——序列化由调用方负责。 | 方法与路径 | 说明 | | --- | --- | -| `GET /api/v1/sessions/{session_id}/prompts` | 进行中与排队中的提示词 | -| `POST /api/v1/sessions/{session_id}/prompts` | 提交提示词(内容块数组,可带模型 / 权限模式覆盖) | -| `POST /api/v1/sessions/{session_id}/prompts:steer` | 把排队的提示词插入进行中的轮次 | -| `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:abort` | 中止运行中的提示词 | -| `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:steer` | 插入单条排队的提示词 | +| `GET /api/v1/gui/store/length` | 已存键的数量 | +| `GET /api/v1/gui/store/getItem` | 按键读取值 | +| `POST /api/v1/gui/store/setItem` | 按键写入值 | +| `POST /api/v1/gui/store/removeItem` | 按键删除值 | +| `POST /api/v1/gui/store/clear` | 删除所有值 | -#### `GET /api/v1/sessions/{session_id}/prompts` +`key` 的长度上限为 256 个字符,缺省或超长返回 `40001`。 -读取 main agent 的提示词队列快照。 +#### `GET /api/v1/gui/store/length` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +返回已存键的数量(对齐 `localStorage.length`)。无参数。 -成功时,`data` 为 `{ active, queued }`:`active` 是运行中的提示词(空闲时为 `null`),`queued` 按顺序列出等待中的提示词。提示词为 `{ prompt_id, user_message_id, status, content, created_at }`,其中 `status` 为 `running` / `queued` / `blocked` 之一,`content` 采用 `POST /api/v1/sessions/{session_id}/prompts` 接受的内容块格式。 +**data**(code = 0):`{ "length": number }`。 -- `40401`:会话不存在 +**示例**: -#### `POST /api/v1/sessions/{session_id}/prompts` +```json +{ "code": 0, "msg": "success", "data": { "length": 3 }, "request_id": "01JZX4..." } +``` -向会话提交一条用户提示词。先校验媒体引用,然后把可选的覆盖项应用到目标 Agent——`profile`(与 `model` / `thinking` 一起绑定),接着是 `model`、`thinking`、`permission_mode` 和 `disabled_tools`——随后提示词入队;响应在提示词被接受后立即返回,不等待轮次执行。提供 `skills` 时,提示词以打包的 Skill 激活方式运行,而不是普通用户提示词。 +#### `GET /api/v1/gui/store/getItem` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `content` | body | array | **必填。** 非空的内容块数组;变体见下 | -| `agent_id` | body | string | 目标 Agent。默认为 main agent | -| `prompt_id` | body | string | 客户端选定的提示词 id,用于幂等提交;已被进行中提示词占用的 id 返回 `40927`,已完成的返回 `40903`。不能与 `skills` 同用 | -| `skills` | body | array | 打包的 Skill 激活,至少 1 个 `{ name, args? }` 条目;每个 Skill 必须存在且可由用户激活 | -| `profile` | body | string | 提交前要绑定的 Agent 档案 | -| `model` | body | string | 要切换到的模型别名 | -| `thinking` | body | string | Thinking 强度等级 | -| `permission_mode` | body | string | `manual` / `yolo` / `auto` | -| `disabled_tools` | body | array | 要为会话禁用的工具名 | +读取一个值(对齐 `localStorage.getItem`)。 -schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 `goal_control`,但提交路由当前不会应用它们。每个 `content` 内容块是按 `type` 区分的对象: +**Query**: -| 内容块 | 字段 | 说明 | +| 参数 | 类型 | 说明 | | --- | --- | --- | -| `text` | `text` | 纯文本 | -| `image` / `video` | `source` | 媒体输入;`source` 为 `{ kind: "url", url, id? }`、`{ kind: "base64", media_type, data }`、`{ kind: "file", file_id }`(来自 `POST /api/v1/files` 的上传)或 `{ kind: "session_media", file_id }`(已提交到本会话的媒体)之一 | -| `file` | `file_id`、`name`、`media_type`、`size` | 通过 `POST /api/v1/files` 上传的文件附件 | - -schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinking` 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 `file_id` 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。 - -成功时,`data` 为被接受的提示词 `{ prompt_id, user_message_id, status, content, created_at }`。 +| `key` | string | **必填。** 要读取的键,1–256 个字符 | -- `40001`:校验失败——例如 `prompt_id` 与 `skills` 同用,或未知的 `profile` -- `40110`:尚未配置供应商——请先完成登录 -- `40111`:解析出的供应商没有凭据(`details.provider_id`) -- `40112`:供应商的凭据被拒绝(`details.provider_id`) -- `40113`:模型无法解析(已知时带 `details.model_id` / `details.provider_id`) -- `40401`:会话不存在 -- `40407`:引用的 `file_id` 不存在(或与内容块的媒体 kind 不匹配) -- `40415`:某个 `skills` 条目指向未知的 Skill -- `40903`:`prompt_id` 属于已完成的提示词;`data` 携带 `{ aborted: false }` -- `40912`:Skill 存在但无法由用户激活 -- `40927`:`prompt_id` 已被进行中的提示词占用 - -#### `POST /api/v1/sessions/{session_id}/prompts:steer` - -把排队的提示词插入进行中的轮次,让运行中的轮次立即消费它们,而不是先运行结束。 +**data**(code = 0):`{ "value": string | null }`——键不存在时为 `null`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `prompt_ids` | body | array | **必填。** 非空的排队提示词 id 数组 | +**示例**: -成功时,`data` 为 `{ steered: true, prompt_ids }`。 +```json +{ "code": 0, "msg": "success", "data": { "value": "{ \"sidebar\": \"collapsed\" }" }, "request_id": "01JZX4..." } +``` -- `40001`:校验失败 -- `40401`:会话不存在 -- `40402`:所列提示词 id 不在队列中 +#### `POST /api/v1/gui/store/setItem` -#### `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:abort` +写入一个值(对齐 `localStorage.setItem`)。 -中止运行中的提示词。本端点与下面的 `:steer` 通过同一条路由 `POST /api/v1/sessions/{session_id}/prompts/{tail}` 分发:尾部解析为 `{prompt_id}:{action}`,动作缺失或未知时返回 `40001`(`unsupported action: ...`)。 +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `prompt_id` | path | string | **必填。** 提示词 id | - -成功时,`data` 为 `{ aborted: true }`。 +| `key` | string | 是 | 要写入的键,1–256 个字符 | +| `value` | string | 是 | 要存储的值 | -- `40401`:会话不存在 -- `40402`:不存在该 id 的提示词 -- `40903`:提示词已完成;`data` 携带 `{ aborted: false }` +**data**(code = 0):`null`。 -#### `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:steer` +**示例**: -把单条排队的提示词插入进行中的轮次——是 `POST /api/v1/sessions/{session_id}/prompts:steer` 的单提示词形式。 +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `prompt_id` | path | string | **必填。** 排队中的提示词 id | +#### `POST /api/v1/gui/store/removeItem` -成功时,`data` 为 `{ steered: true, prompt_ids: [prompt_id] }`。 +删除一个值(对齐 `localStorage.removeItem`)。 -- `40401`:会话不存在 -- `40402`:没有该 id 的排队提示词 +**Body**: -### 审批与提问 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `key` | string | 是 | 要删除的键,1–256 个字符 | -审批与提问是会话的两类待处理交互:审批是为工具调用请求许可,提问是请求带标签选项的结构化输入。这些端点用于列出和答复它们;新的请求通过 WebSocket 以 `event.approval.requested` 与 `event.question.requested` 到达。 +**data**(code = 0):`null`。 -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/sessions/{session_id}/approvals` | 列出待处理的审批请求(必须 `status=pending`) | -| `POST /api/v1/sessions/{session_id}/approvals/{approval_id}` | 答复审批 | -| `GET /api/v1/sessions/{session_id}/questions` | 列出待处理的提问(必须 `status=pending`) | -| `POST /api/v1/sessions/{session_id}/questions/{question_id}` | 回答提问 | -| `POST /api/v1/sessions/{session_id}/questions/{question_id}:dismiss` | 忽略提问 | +**示例**: -#### `GET /api/v1/sessions/{session_id}/approvals` +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -列出会话待处理的审批请求——即工具调用发起的权限提示。读取列表会在会话为冷态时将其恢复。 +#### `POST /api/v1/gui/store/clear` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `status` | query | string | **必填。** 必须为 `pending` | +删除所有已存值(对齐 `localStorage.clear`)。无请求体。 -成功时,`data` 为 `{ items }`,每个元素为 `{ approval_id, session_id, turn_id?, tool_call_id, tool_name, action, tool_input_display, created_at, expires_at }`:`tool_name` / `action` / `tool_input_display` 描述等待许可的调用,`expires_at` 为 `created_at` 之后 24 小时。 +**data**(code = 0):`null`。 -- `40001`:`status` 缺失或不是 `pending` -- `40401`:会话不存在 +**示例**: -#### `POST /api/v1/sessions/{session_id}/approvals/{approval_id}` +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -答复一个待处理的审批请求,让等待中的工具调用继续执行(或不执行)。 +### 会话快照 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `approval_id` | path | string | **必填。** 审批请求 id | -| `decision` | body | string | **必填。** `approved` / `rejected` / `cancelled` | -| `scope` | body | string | 配合 `approved` 使用,`session`(唯一取值)还会让该审批规则在会话的剩余时间内被记住 | -| `feedback` | body | string | 回传给 Agent 的自由文本反馈 | -| `selected_label` | body | string | 当请求提供了带标签的选项时(例如计划审阅),所选选项的标签 | +#### `GET /api/v1/sessions/{session_id}/snapshot` -成功时,`data` 为 `{ resolved: true, resolved_at }`。 +为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 -- `40001`:校验失败 -- `40401`:会话不存在 -- `40404`:没有该 id 的待处理审批 -- `40902`:审批已被答复;`data` 携带 `{ resolved: false }` +**data**(code = 0):[T-SnapshotResponse](#t-snapshotresponse)。 -#### `GET /api/v1/sessions/{session_id}/questions` +**非零 code**:`40401`、`50001`。 -列出会话待处理的提问。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `status` | query | string | **必填。** 必须为 `pending` | +```json +{ "code": 0, "msg": "success", "data": { "as_of_seq": 128, "epoch": "01JZX4...", "session": { "id": "session_01JZX4...", "agent_config": { "model": "kimi-for-coding" }, "usage": { "input_tokens": 152000, "...": 0 }, "...": "..." }, "messages": { "items": [ "..." ], "has_more": true }, "in_flight_turn": null, "subagents": [], "pending_approvals": [], "pending_questions": [] }, "request_id": "01JZX4..." } +``` -成功时,`data` 为 `{ items }`,每个元素为 `{ question_id, session_id, turn_id?, tool_call_id?, questions, created_at }`。`questions` 包含 1–4 个 `{ id, question, header?, body?, options, multi_select?, allow_other?, other_label?, other_description? }` 条目,每个条目带 2–4 个 `{ id, label, description? }` 形式的 `options`;`multi_select` 允许选择多个选项,`allow_other` 允许自由文本回答。 +### 转录 -- `40001`:`status` 缺失或不是 `pending` -- `40401`:会话不存在 +`transcript` 端点提供按 Agent 组织的结构化转录——轮次、任务、交互、附件——即 WebSocket [transcript 帧](#transcript-帧) 实时流式推送的内容。历史分页与补漏用这些端点,实时尾部用 WebSocket 订阅。转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约([T-Transcript 族](#t-transcript-族))。 -#### `POST /api/v1/sessions/{session_id}/questions/{question_id}` +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/transcript` | 按轮次分页的转录(需 `agent_id`) | +| `GET /api/v1/sessions/{session_id}/transcript/ops` | op 批次补漏(`since_seq`) | +| `GET /api/v1/sessions/{session_id}/transcript/user-messages` | 各轮次起始的用户输入,不分页 | +| `GET /api/v1/sessions/{session_id}/transcript/plan` | ExitPlanMode 计划内容、路径与审阅结果 | -回答一个待处理的提问。两个提问端点通过同一条路由 `POST /api/v1/sessions/{session_id}/questions/{tail}` 分发:单独的提问 id 表示回答问题,`{question_id}:dismiss` 尾部表示忽略问题,其他情况返回 `40001`。 +#### `GET /api/v1/sessions/{session_id}/transcript` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `question_id` | path | string | **必填。** 提问 id | -| `answers` | body | object | **必填。** 提问条目 id(`q_0`……)到答案对象的映射;变体见下 | -| `method` | body | string | 答案的产生方式:`enter` / `space` / `number_key` / `click` | -| `note` | body | string | 附在回答上的自由文本备注 | +返回某个 Agent 的结构化转录中的一页:轮次(含其步骤与帧)以及轮次之间的标记与任务引用。活跃会话从内存存储应答(先回填所请求 Agent 的持久化历史);冷会话则从持久化的线上记录重建 Agent。 -每个答案是按 `kind` 区分的对象: +**Query**: -| kind 值 | 字段 | 说明 | +| 参数 | 类型 | 说明 | | --- | --- | --- | -| `single` | `option_id` | 选中的单个选项 | -| `multi` | `option_ids` | 选中的多个选项(至少 1 个) | -| `other` | `text` | 自由文本回答 | -| `multi_with_other` | `option_ids`、`other_text` | 选项加自由文本 | -| `skipped` | — | 跳过了该条目 | +| `agent_id` | string | **必填。** 要读取其转录的 Agent;必须是纯文本形式的 agent id(字母、数字、`.`、`_`、`-`,不含路径分隔符) | +| `before_turn` | string | 只保留早于该轮次 id 的轮次;与 `after_turn` 互斥 | +| `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | +| `page_size` | integer | 1–100 个轮次。默认 `20` | -成功时,`data` 为 `{ resolved: true, resolved_at }`。 +**data**(code = 0):[T-TranscriptResponse](#t-transcriptresponse)——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 -- `40001`:校验失败(`details` 列出每个字段) -- `40401`:会话不存在 -- `40405`:没有该 id 的待处理提问 -- `40902`:提问已被答复;`data` 携带 `{ resolved: false }` +**非零 code**:`40001`、`40401`。 -#### `POST /api/v1/sessions/{session_id}/questions/{question_id}:dismiss` - -忽略一个待处理的提问,不作回答。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `question_id` | path | string | **必填。** 提问 id | +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "items": [ { "kind": "turn", "turnId": 3, "...": "..." } ], "has_more": true, "tasks": [], "interactions": [], "attachments": [], "todos": [], "prompts": [], "meta": { "...": "..." }, "agents": [ { "agentId": "main", "...": "..." } ], "pending_interactions": [], "seq": 42 }, "request_id": "01JZX4..." } +``` -成功时信封的 `code` 是 `40909`(`question dismissed`)而不是 `0`,`data` 为 `{ dismissed: true, dismissed_at }`——客户端必须特殊处理该端点的成功码。 +#### `GET /api/v1/sessions/{session_id}/transcript/ops` -- `40401`:会话不存在 -- `40405`:没有该 id 的待处理提问 -- `40902`:提问已被答复;`data` 携带 `{ resolved: false }` +从服务端的 op 日志提供点对点的补漏:某个 Agent 的 `seq > since_seq` 的已记录 op 批次,最旧在前。它是 `transcript_since` 恢复游标的 REST 对应物,共享同一份有界日志,因此适用相同的回退规则。 -### 后台任务 +**Query**: -后台任务是会话的异步单元——后台 Shell、subagent 与长时间运行的工具任务。注册表仅包含实时数据:未加载到本服务进程中的会话会返回空列表。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | **必填。** Agent id(纯文本形式) | +| `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/sessions/{session_id}/tasks` | 列出后台任务 | -| `GET /api/v1/sessions/{session_id}/tasks/{task_id}` | 读取任务(可选输出预览) | -| `POST /api/v1/sessions/{session_id}/tasks/{task_id}:cancel` | 取消任务 | -| `POST /api/v1/sessions/{session_id}/tasks/{task_id}:detach` | 将前台任务转入后台 | +**data**(code = 0):[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 -#### `GET /api/v1/sessions/{session_id}/tasks` +**非零 code**:`40001`、`40401`。 -列出会话的后台任务。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `status` | query | string | 只保留单一状态:`running` / `completed` / `failed` / `cancelled` | +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "batches": [ { "seq": 41, "ops": [ { "op": "append", "...": "..." } ] } ], "latest_seq": 42, "complete": true }, "request_id": "01JZX4..." } +``` -成功时,`data` 为 `{ items }`,每个元素是任务对象 `{ id, session_id, kind, description, status, created_at, started_at?, completed_at?, command?, model?, thinking_effort?, agent_id?, subagent_type?, parent_tool_call_id?, output_preview?, output_bytes? }`。`kind` 为 `bash` / `subagent` / `tool`;`command` 仅在 `bash` 任务时设置,模型与 Agent 字段仅在 `subagent` 任务时设置,输出字段仅在以 `with_output` 读取任务时设置。超时与丢失的任务上报为 `failed`;被杀死的任务上报为 `cancelled`。 +#### `GET /api/v1/sessions/{session_id}/transcript/user-messages` -- `40001`:校验失败——未知的 `status` -- `40401`:会话不存在 +列出会话中每个开启轮次的输入,按 Agent 分组且不分页:真实用户文本、以斜杠命令形式使用的 Skill 与插件命令、以及 cron 提示词——可通过 `origin` 区分——另有仅含附件的提示词,其 `prompt` 投影为空。所列消息引用的附件实体会随响应一起返回(仅元数据,绝不包含字节内容)。 -#### `GET /api/v1/sessions/{session_id}/tasks/{task_id}` +**Query**: -读取单个后台任务,可选携带输出的末尾片段。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `task_id` | path | string | **必填。** 任务 id | -| `with_output` | query | boolean | 在响应中包含输出末尾片段。默认 `false` | -| `output_bytes` | query | integer | 请求的输出末尾片段的字节大小,最小 `0`。默认 `32768` | +**data**(code = 0):[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)。 -成功时,`data` 为上文 `GET /api/v1/sessions/{session_id}/tasks` 中说明的任务对象;当 `with_output=true` 且输出非空时,`output_preview` 携带末尾片段文本,`output_bytes` 为其字节长度。 +**非零 code**:`40001`、`40401`。 -- `40001`:校验失败 -- `40401`:会话不存在 -- `40406`:没有该 id 的任务(冷会话完全没有实时任务) +**示例**: -#### `POST /api/v1/sessions/{session_id}/tasks/{task_id}:cancel` +```json +{ "code": 0, "msg": "success", "data": { "agents": [ { "agent_id": "main", "messages": [ { "turn_id": 3, "ordinal": 0, "state": "completed", "origin": { "kind": "user" }, "prompt": "adjust the button spacing", "started_at": "2026-09-02T08:04:00.000Z" } ], "attachments": [] } ] }, "request_id": "01JZX4..." } +``` -取消运行中的任务。它通过 `POST /api/v1/sessions/{session_id}/tasks/{tail}` 分发,支持 `cancel` / `detach` 两个动作——单独的任务 id 或未知动作返回 `40001`。 +#### `GET /api/v1/sessions/{session_id}/transcript/plan` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `task_id` | path | string | **必填。** 任务 id | +按时间线顺序读取某个 Agent 的 `ExitPlanMode` 工具调用的计划信息——计划内容、计划文件路径、提供的选项以及审阅结果。内容投影自第一个可用的事实来源:关联的审批交互(交互式审阅)、实时工具帧的展示(auto 模式),或工具结果的输出文本;每个条目在 `source` 中记录具体来源。 -成功时,`data` 为 `{ cancelled: true }`。 +**Query**: -- `40001`:动作后缀缺失或未知 -- `40401`:会话不存在 -- `40406`:没有该 id 的任务 -- `40904`:任务已结束;`data` 携带 `{ cancelled: false }`,`details.current_status` 为最终状态 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | **必填。** Agent id(纯文本形式) | +| `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | -#### `POST /api/v1/sessions/{session_id}/tasks/{task_id}:detach` +**data**(code = 0):[T-TranscriptPlanResponse](#t-transcriptplanresponse)。 -将运行中的前台任务转入后台而不终止它:等待该任务的工具调用会立即以后台任务结果返回,轮次继续推进,任务则在后台任务注册表下继续运行(输出持久化,完成时以任务通知投递)。已在后台或已结束的任务为幂等空操作。它通过 `POST /api/v1/sessions/{session_id}/tasks/{tail}` 分发,支持 `cancel` / `detach` 两个动作——单独的任务 id 或未知动作返回 `40001`。 +**非零 code**:`40001`、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `task_id` | path | string | **必填。** 任务 id | +**示例**: -成功时,`data` 为 `{ detached, status }`:本次调用确实将运行中的前台任务转入后台时 `detached` 为 `true`,幂等空操作时为 `false`;`status` 为调用后的任务状态。 +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "plans": [ { "tool_call_id": "toolu_01J...", "turn_id": 2, "source": "interaction", "plan": "# Plan\n ...", "path": "/Users/dev/my-app/.kimi-code/plans/....md", "options": [ { "label": "实施" } ], "review": { "state": "approved", "selected_option": "实施" } } ] }, "request_id": "01JZX4..." } +``` -- `40001`:动作后缀缺失或未知 -- `40401`:会话不存在 -- `40406`:没有该 id 的任务 +### 文件历史(实验性) -### 技能、工具与 MCP +::: info 新增 +实验特性:由 `KIMI_CODE_EXPERIMENTAL_FILE_HISTORY` 开关控制(默认关闭),接口形态可能随版本更改。 +::: -这组端点暴露会话或工作区可见的技能目录、当前生效 agent 的工具列表及其 MCP 服务。技能激活与 MCP 重启使用 `:{action}` 约定;激活即斜杠命令 `/` 的 REST 等价形式。 +按轮次记录的文件历史快照:main agent 每个轮次在开始与结束两个检查点版本化所有被 Edit / Write 工具触碰的文件(未变化的文件按内容哈希去重,超过 4 MiB 的文件只记录哨兵指纹)。这两个端点从检查点计算单个轮次的逐文件增删行数与任一检查点的完整内容;冷会话会按需恢复。开关关闭时路由仍注册,但 `changes` 恒返回空列表、`enabled` 恒为 `false`、`content` 恒为 `null`。 | 方法与路径 | 说明 | | --- | --- | -| `GET /api/v1/sessions/{session_id}/skills` | 会话级技能目录 | -| `GET /api/v1/workspaces/{workspace_id}/skills` | 无会话的工作区技能目录 | -| `POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate` | 激活技能(开启一个轮次) | -| `GET /api/v1/tools` | 列出当前生效 agent 的工具 | -| `GET /api/v1/mcp/servers` | 列出 MCP 服务 | -| `POST /api/v1/mcp/servers/{mcp_server_id}:restart` | 重启 MCP 服务 | +| `GET /api/v1/sessions/{session_id}/file-history/changes` | 单个轮次的逐文件增删统计 | +| `GET /api/v1/sessions/{session_id}/file-history/content` | 某文件在指定检查点的完整内容 | -#### `GET /api/v1/sessions/{session_id}/skills` +#### `GET /api/v1/sessions/{session_id}/file-history/changes` -列出单个会话可用的技能,按会话的优先级合并所有来源(内置、插件、extra、用户、项目)。会话处于冷态时,读取目录会恢复该会话。 +返回单个轮次开始与结束检查点之间每个文件的精确增删行数。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +**Query**: -成功时 `data` 为 `{ skills }`,每项是一个技能描述符 `{ name, description, path, source, type?, disable_model_invocation? }`:`source` 为 `project` / `user` / `extra` / `builtin`;`type` 标识技能类别(只有用户可激活的类型才能被激活);`disable_model_invocation` 会让技能对模型不可见。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | -- `40401`:会话不存在(或未激活) +**data**(code = 0): -#### `GET /api/v1/workspaces/{workspace_id}/skills` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `changes` | array | `{ path, status, additions, deletions, binary?, oversize? }[]`;`status` 为 `added` / `modified` / `deleted`;二进制与超大文件的增删行为 `0`,并以 `binary` / `oversize` 标记 | +| `enabled` | boolean | 实验开关是否开启 | +| `recorded` | boolean | 该轮次是否有已记录的检查点 | -列出该工作区中的会话将看到的技能目录,但不创建或恢复会话——即针对工作区根目录计算出的同一套内置、插件、extra、用户、项目来源合并结果。 +**非零 code**:`40401`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 已注册工作区 id | +**示例**: -成功时 `data` 为 `{ skills }`,技能描述符见上文 `GET /api/v1/sessions/{session_id}/skills` 的说明。 +```json +{ "code": 0, "msg": "success", "data": { "changes": [ { "path": "src/index.ts", "status": "modified", "additions": 12, "deletions": 3 } ], "enabled": true, "recorded": true }, "request_id": "01JZX4..." } +``` -- `40410`:工作区不存在 +#### `GET /api/v1/sessions/{session_id}/file-history/content` -#### `POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate` +返回某文件在指定轮次检查点的完整内容;`phase: "end"` 时若该文件在结束检查点没有记录,回退到开始检查点的版本。 -在会话中激活技能——即斜杠命令 `/` 的 REST 等价形式——以技能内容加上 `args` 与附件在 main agent 上开启一个轮次。该端点经单一路由 `POST /api/v1/sessions/{session_id}/skills/{tail}` 分发:尾部按 `{skill_name}:{action}` 解析,`activate` 是唯一动作;只给名称或动作未知时返回 `40001`(`unsupported action: ...`)。 +**Query**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `skill_name` | path | string | **必填。** 要激活的技能名 | -| `args` | body | string | 传给技能的自由文本参数,相当于斜杠命令后的文本 | -| `attachments` | body | array | 随激活携带的媒体块。`image` / `video` 块带 `source` 对象(`kind` 为 `url` / `base64` / `file` / `session_media`,与提示词内容块同形);`file` 块带顶层 `file_id`、`name`、`media_type`、`size` | +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | +| `path` | string | **必填。** 文件路径 | +| `phase` | string | `start`(默认)/ `end`——取轮次开始还是结束检查点 | -成功时 `data` 为 `{ activated: true, skill_name }`。 +**data**(code = 0): -- `40001`:校验失败或动作后缀不支持 -- `40401`:会话不存在(或未激活) -- `40407`:引用的附件文件不存在 -- `40415`:没有该名称的技能 -- `40912`:技能存在,但其类型不允许用户激活 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `content` | object \| null | `{ version, content?, binary? }`——`version` 为该文件在检查点的版本号;二进制文件只携带 `binary: true` 不携带文本;无记录时为 `null` | -#### `GET /api/v1/tools` +**非零 code**:`40401`。 -列出当前生效 agent 的工具——即 `session_id` 指定会话的 main agent;省略参数时取最近创建的会话。若该会话不在本服务进程中存活,列表为空。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | query | string | 要查看其 main agent 的会话。默认最近创建的会话 | +```json +{ "code": 0, "msg": "success", "data": { "content": { "version": 2, "content": "import ..." } }, "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ tools }`,每项为 `{ name, description, input_schema, source, mcp_server_id?, active? }`:`source` 为 `builtin` / `skill` / `mcp`;`mcp_server_id` 仅 MCP 工具携带(从 `mcp____` 名称解析);`active` 报告工具策略的判定结果。`input_schema` 目前恒为 `null`。 +### v2 会话 -#### `GET /api/v1/mcp/servers` +`/api/v2` 的会话查询与批量管理。与 v1 共享信封与错误约定;分页为绑定查询指纹的 `page_token`(见 [分页](#分页))。 -列出当前生效 agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同,取最近创建的存活会话的 main agent)。没有存活会话时列表为空。 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v2/sessions` | 新一代会话列表:筛选、排序、字段组、分组视图 | +| `POST /api/v2/sessions:archive` | 批量归档会话 | +| `POST /api/v2/sessions:restore` | 批量恢复已归档会话 | -成功时 `data` 为 `{ servers }`,每项为 `{ id, name, transport, status, last_error?, tool_count }`:`transport` 为 `stdio` / `http` / `sse`;`status` 为 `connected` / `connecting` / `disconnected` / `error`;服务处于 `error` 时 `last_error` 携带失败信息。 +#### `GET /api/v2/sessions` -#### `POST /api/v1/mcp/servers/{mcp_server_id}:restart` +面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里。 -重新连接当前生效 agent 的某个 MCP 服务。该端点经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作——只给服务 id 或动作未知时返回 `40001`。 +**Query**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `mcp_server_id` | path | string | **必填。** MCP 服务 id(即其配置名称) | +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `workspace.id` | string | 按工作区过滤,可重复 | +| `activity.status` | string | 按活动状态过滤:`running` / `approval` / `question` / `failed` / `idle`,可重复 | +| `meta.updated_after` | integer | 只看该时间(epoch 毫秒)之后更新过的会话 | +| `meta.updated_before` | integer | 只看该时间(epoch 毫秒)之前更新过的会话 | +| `meta.archived` | string | `true` / `false`(默认)/ `all` | +| `meta.has_prompt` | string | `true` 只保留有用户 prompt 的会话,`false` 只保留空会话(等价 v1 的 `exclude_empty`) | +| `view` | string | `flat`(默认)/ `by_workspace`(按工作区分组) | +| `group.page_size` | integer | `view=by_workspace` 时每个工作区返回的会话数:1–100,默认 `5`(`id,archived` 投影时上限 10000);未开分组视图时传入返回 `40001` | +| `sort` | string | `meta.updated_at_desc`(默认)/ `meta.updated_at_asc` / `meta.created_at_desc` | +| `include` | string | 逗号分隔的附加字段组;目前支持 `git`(分支与 PR 信息,按目录去重并缓存 60 秒) | +| `fields` | string | 逗号分隔的字段投影;目前仅支持 `id,archived`,每项裁剪为 `{ id, archived }`。不可与 `include=git` 同传(`40001`) | +| `page_size` | integer | 1–100,默认 `50`;`id,archived` 投影时上限放宽至 10000。`view=by_workspace` 时按组计数 | +| `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | +| `page_token` | string | 上一页返回的翻页令牌 | + +**data**(code = 0):[T-V2SessionPage](#t-v2sessionpage)(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 + +**非零 code**:`40001`(未知 `include` / `fields`、组合非法)、`40922`。 + +**示例**(`view=by_workspace`): + +```json +{ "code": 0, "msg": "success", "data": { "groups": [ { "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "sessions": [ { "id": "session_01JZX4...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ], "total": 42 } ], "total": 7, "has_more": true, "next_page_token": "eyJ2IjoxLCJmIjoi..." }, "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ restarting: true }`。 +#### `POST /api/v2/sessions:archive` 与 `POST /api/v2/sessions:restore` -- `40001`:缺少动作后缀或动作未知 -- `40408`:没有该 id 的 MCP 服务(无存活会话时同样返回此错误) +面向会话管理页的批量归档 / 恢复。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回。 -### 能力与插件 +**Body**: -能力是带有分层就绪状态的内置特性——由检测步骤加后台安装组成;当前版本注册了 `kimi-cu`(Kimi Computer Use)与 `kimi-webbridge`(Kimi WebBridge)。插件是已安装的技能、MCP 服务、hook 与命令的打包集合。这组端点报告能力状态、驱动能力安装,并管理插件从市场列表到移除的整个生命周期。 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/capabilities` | 列出内置能力及其就绪状态 | -| `GET /api/v1/capabilities/{capability_id}` | 读取单个能力的状态 | -| `POST /api/v1/capabilities/{capability_id}:install` | 开始安装能力(后台进行,轮询 GET 查看进度) | -| `GET /api/v1/plugins` | 列出已安装插件 | -| `POST /api/v1/plugins` | 从本地路径、zip URL 或 GitHub 仓库安装插件 | -| `GET /api/v1/plugins/marketplace` | 插件市场目录,合并实时安装状态 | -| `POST /api/v1/plugins/{plugin_id}:{action}` | 插件动作:`enable` / `disable` / `remove` | +**data**(code = 0):[T-V2BatchSessionResponse](#t-v2batchsessionresponse)——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 -#### `GET /api/v1/capabilities` +**非零 code**:`40001`。 -列出所有已注册能力及其就绪状态。 +**示例**: -成功时 `data` 为 `{ capabilities }`,每项是一个能力状态对象 `{ id, pluginId?, displayName, description, supported, state, version?, steps, install }`。`state` 为 `ready`(所有必需检测步骤均为 `ok`)/ `partial`(部分步骤 `ok`)/ `not_installed` / `unsupported`(当前平台/架构不可用);`steps` 以 `{ id, state, detail?, optional? }` 列出各检测步骤,其 `state` 为 `ok` / `missing` / `failed` 之一;`install` 为安装进度 `{ running, step?, percent?, error?, note? }`,其中 `percent` 取值 0 到 100。 +```json +{ "code": 0, "msg": "success", "data": { "results": [ { "id": "session_a", "ok": true }, { "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } } ], "succeeded": 1, "failed": 1 }, "request_id": "01JZX4..." } +``` -#### `GET /api/v1/capabilities/{capability_id}` +### v2 MCP -读取单个能力的就绪状态——即 `:install` 动作的轮询对应端点。 +`/api/v2/mcp/*` 是统一的 MCP 管理面:独立于任何会话,直接管理 MCP server 注册表本身——全局(用户级)CRUD 与逐条校验、连接测试探测、locator 寻址的检查目录、按 server 的授权状态列表,以及完整的 OAuth 流程生命周期。响应该组一律不包 `{ items }`:`data` 直接为数组或对象。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `capability_id` | path | string | **必填。** 能力 id | +该管理面有两种寻址方式。CRUD 路由与 `servers:test` 使用普通的运行时 `name`;检查与 OAuth 路由使用 **locator**——文件层条目用 `{ "source": "global", "name" }`,插件清单条目用 `{ "source": "plugin", "pluginId", "serverName" }`——因为插件条目和文件条目可能共用同一个运行时名称。检查条目还带有一个稳定的 `serverId` 线上标识:`global:` 或 `plugin::`(URL 编码)。 -成功时 `data` 为上文 `GET /api/v1/capabilities` 说明的能力状态对象。 +大多数路由接受可选的 `cwd`(查询参数,`:`-action 路由则为请求体字段)。不传时目录只覆盖用户级文件与插件清单;传入后,该目录的项目根层与项目本地层会并入——但仅当工作区受信任时,否则项目层会被跳过。对 stdio server 执行 `servers:test` 时,`cwd` 同时是子进程的工作目录。 -- `40418`:没有该 id 的能力 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v2/mcp/servers` | 列出所有已知 MCP server | +| `GET /api/v2/mcp/servers/{name}` | 按运行时名称获取单个 server | +| `POST /api/v2/mcp/servers` | 向用户级 `mcp.json` 添加 server | +| `PUT /api/v2/mcp/servers/{name}` | 替换一个用户级条目 | +| `DELETE /api/v2/mcp/servers/{name}` | 删除一个用户级条目 | +| `POST /api/v2/mcp/servers:test` | 对单个 server 发起真实连接探测 | +| `POST /api/v2/mcp/servers:inspect` | locator 寻址的目录及批量连接探测 | +| `GET /api/v2/mcp/auth-statuses` | 目录中各 server 的 OAuth 状态 | +| `POST /api/v2/mcp/auth:begin` | 开始一次交互式 OAuth 流程 | +| `POST /api/v2/mcp/auth:complete` | 等待浏览器回调并完成 code 交换 | +| `POST /api/v2/mcp/auth:cancel` | 终止已开始的 OAuth 流程 | +| `POST /api/v2/mcp/auth:reset` | 清除某个 server 已存储的凭据 | -#### `POST /api/v1/capabilities/{capability_id}:install` +#### `GET /api/v2/mcp/servers` -在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。该端点经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作——只给 id 或动作未知时返回 `40001`。 +列出管理面已知的全部 MCP server。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `capability_id` | path | string | **必填。** 能力 id | +**Query**: -成功时 `data` 为上文 `GET /api/v1/capabilities` 说明的能力状态对象。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | -- `40001`:缺少动作后缀或动作未知 -- `40418`:没有该 id 的能力 -- `40924`:该能力的安装已在进行中 -- `40925`:当前平台/架构不支持该能力 +**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组。 -#### `GET /api/v1/plugins` +**示例**: -列出已安装插件。 +```json +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ], "envKeys": [ "API_KEY" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true } ], "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ plugins }`,每项为 `{ id, displayName, version?, enabled, state, skillCount, mcpServerCount, enabledMcpServerCount, hookCount, commandCount, hasErrors, source, originalSource?, github? }`:`state` 为 `ok` / `error`(加载失败也会置 `hasErrors`);`source` 为 `local-path` / `zip-url` / `github`;GitHub 来源的插件由 `github` 携带来源信息 `{ owner, repo, ref, installedSha? }`,其中 `ref` 为 `{ kind: branch|tag|sha, value }`。 +#### `GET /api/v2/mcp/servers/{name}` -#### `POST /api/v1/plugins` +按运行时名称获取单个 server。 -安装插件并返回其摘要。 +**Query**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `source` | body | string | **必填。** 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | -成功时 `data` 为上文 `GET /api/v1/plugins` 说明的插件摘要。 +**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver)。 -- `40001`:校验失败——例如 `source` 既不是 URL 也不是绝对路径,或插件加载失败 -- `40409`:本地路径不存在 +**非零 code**:`40001`、`40408`(不存在该名称的 server)。 -#### `GET /api/v1/plugins/marketplace` +**示例**: -列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),而当前平台不支持的能力对应条目会被剔除。 +```json +{ "code": 0, "msg": "success", "data": { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true }, "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ entries }`,每项为 `{ id, tier, displayName, description?, homepage?, keywords?, version?, source, installed?, updateAvailable?, capabilityId? }`:`tier` 为 `official` / `curated` / `third-party`;插件已安装时 `installed` 为 `{ version?, enabled }`;`updateAvailable` 标记目录版本新于已安装版本的条目。条目的 `source` 即 `POST /api/v1/plugins` 的 `source` 字段取值。 +#### `POST /api/v2/mcp/servers` -- `50001`:市场不可达或返回了非法目录 +向用户级 `mcp.json` 添加 server。若写入与项目层的同名条目冲突,会因只读被拒绝;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。 -#### `POST /api/v1/plugins/{plugin_id}:enable` +**Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 -启用一个已安装插件。插件动作经单一路由 `POST /api/v1/plugins/{tail}` 分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable` / `disable` / `remove`;只给 id 或动作未知时返回 `40001`(`unsupported action: ...`)。 +**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `plugin_id` | path | string | **必填。** 已安装插件 id | +**非零 code**:`40001`(校验失败,或目标条目为只读)。 -成功时 `data` 为 `{ ok: true }`。 +**示例**: -- `40001`:缺少动作后缀或动作未知 -- `40419`:没有该 id 的已安装插件 +```json +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } +``` -#### `POST /api/v1/plugins/{plugin_id}:disable` +#### `PUT /api/v2/mcp/servers/{name}` -停用一个已安装插件但不移除它;分发约定同上文 `:enable`。 +替换一个用户级条目;身份由路径指定。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `plugin_id` | path | string | **必填。** 已安装插件 id | +**Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 -成功时 `data` 为 `{ ok: true }`。 +**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 -- `40001`:缺少动作后缀或动作未知 -- `40419`:没有该 id 的已安装插件 +**非零 code**:`40001`、`40408`。 -#### `POST /api/v1/plugins/{plugin_id}:remove` +**示例**: -移除一个已安装插件;分发约定同上文 `:enable`。 +```json +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "http", "url": "https://mcp.example.com" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `plugin_id` | path | string | **必填。** 已安装插件 id | +#### `DELETE /api/v2/mcp/servers/{name}` -成功时 `data` 为 `{ ok: true }`。 +删除一个用户级条目。无请求体。 -- `40001`:缺少动作后缀或动作未知 -- `40419`:没有该 id 的已安装插件 +**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 -### 终端 +**非零 code**:`40001`、`40408`。 -PTY 终端接口;仅在 loopback 绑定时挂载(非 loopback 绑定会跳过它们,除非传入 `--allow-remote-terminals`)。终端的输入、输出与尺寸调整经 WebSocket 的 `terminal_*` 帧传输——REST 侧只管理终端生命周期。 +**示例**: -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/sessions/{session_id}/terminals` | 列出终端 | -| `POST /api/v1/sessions/{session_id}/terminals` | 创建终端 | -| `GET /api/v1/sessions/{session_id}/terminals/{terminal_id}` | 读取终端 | -| `POST /api/v1/sessions/{session_id}/terminals/{terminal_id}:close` | 关闭终端 | +```json +{ "code": 0, "msg": "success", "data": [], "request_id": "01JZX4..." } +``` -#### `GET /api/v1/sessions/{session_id}/terminals` +#### `POST /api/v2/mcp/servers:test` + +对单个 server 发起真实连接探测,不持久化任何内容。传 `name` 探测注册表条目(含插件与受信任的项目层),或传 `server`(包含 `name` 的完整内联配置)按原样探测;两者都传或都不传会报 `40001`。 -列出会话的终端。会话处于冷态时,读取列表会恢复该会话。 +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | +| `name` | string | 二选一 | 注册表条目的运行时名称 | +| `server` | object | 二选一 | 按原样探测的内联 server 配置(含 `name`) | +| `cwd` | string | 否 | 项目层并入解析;同时是 stdio 的工作目录 | -成功时 `data` 为 `{ items }`,每项是一个终端对象 `{ id, session_id, cwd, shell, cols, rows, status, created_at, exited_at?, exit_code? }`:`status` 为 `running` / `exited`;已退出的终端携带 `exited_at` 与 `exit_code`(进程未报告退出码时为 `null`,例如因信号终止)。回滚缓冲不属于该对象——输出经 WebSocket 回放与流式推送。 +**data**(code = 0):`{ "success": boolean, "output": string }`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 -- `40401`:会话不存在 +**非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用)、`40408`。 -#### `POST /api/v1/sessions/{session_id}/terminals` - -为会话创建一个 PTY 终端。 - -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `runtime_id` | body | string | 生成终端进程的运行时。默认 `local` | -| `cwd` | body | string | 工作目录,相对于会话工作区(传绝对路径会校验失败)。默认工作区根目录 | -| `shell` | body | string | Shell 可执行文件。默认该运行时的 shell | -| `cols` | body | integer | 终端宽度,正数。默认 `80` | -| `rows` | body | integer | 终端高度,正数。默认 `24` | +**示例**: -成功时 `data` 为上文 `GET /api/v1/sessions/{session_id}/terminals` 说明的终端对象。 +```json +{ "code": 0, "msg": "success", "data": { "success": true, "output": "5 tools: search, fetch, ..." }, "request_id": "01JZX4..." } +``` -- `40001`:校验失败(`details` 逐字段说明) -- `40401`:会话不存在 -- `41304`:`cwd` 解析后越出会话工作区 +#### `POST /api/v2/mcp/servers:inspect` -#### `GET /api/v1/sessions/{session_id}/terminals/{terminal_id}` +locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 `unavailable` 并在 `error` 中给出说明;探测遇到过期授权时,可能刷新或作废已存储的凭据。 -读取单个终端。 +**Body**: -| 参数 | 位置 | 类型 | 说明 | +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `terminal_id` | path | string | **必填。** 终端 id | +| `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | +| `cwd` | string | 否 | 并入该(受信任)目录的项目层 | -成功时 `data` 为上文 `GET /api/v1/sessions/{session_id}/terminals` 说明的终端对象。 +**data**(code = 0):[T-McpServerInspection](#t-mcpserverinspection) 数组。 -- `40401`:会话不存在 -- `40414`:没有该 id 的终端 +**非零 code**:`40001`、`40408`(`targets` 中有 locator 未匹配到任何条目)。 -#### `POST /api/v1/sessions/{session_id}/terminals/{terminal_id}:close` +**示例**: -关闭终端并结束其进程。该端点经 `POST /api/v1/sessions/{session_id}/terminals/{tail}` 分发,`close` 是唯一动作——只给 id 或动作未知时返回 `40001`。 +```json +{ "code": 0, "msg": "success", "data": [ { "serverId": "global:my-server", "locator": { "source": "global", "name": "my-server" }, "runtimeName": "my-server", "origin": "global", "config": { "transport": "http", "url": "https://mcp.example.com" }, "enabled": true, "editable": true, "authStatus": "oauth-authorized", "checkedAt": 1787000000000 } ], "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `terminal_id` | path | string | **必填。** 终端 id | +#### `GET /api/v2/mcp/auth-statuses` -成功时 `data` 为 `{ closed: true }`。 +注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 `servers:inspect` 更轻量的选择。 -- `40001`:缺少动作后缀或动作未知 -- `40401`:会话不存在 -- `40414`:没有该 id 的终端 +**Query**: -### 工作区 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | +| `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | -工作区是已注册的项目目录,会话都落在其中。这组端点管理注册表——列出、注册、重命名、注销——以及控制项目级 MCP 配置是否加载的每工作区信任状态。所有返回工作区的端点都使用 [workspace 对象](#workspace-对象) 中统一说明的传输结构。 +**data**(code = 0):[T-McpServerAuthStatus](#t-mcpserverauthstatus) 数组。验证探测可能刷新或作废已存储的凭据。 -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/workspaces` | 列出已注册工作区 | -| `POST /api/v1/workspaces` | 注册工作区(按根路径幂等) | -| `PATCH /api/v1/workspaces/{workspace_id}` | 重命名 | -| `DELETE /api/v1/workspaces/{workspace_id}` | 注销(保留磁盘内容) | -| `GET /api/v1/workspaces/{workspace_id}/trust` | 读取信任状态 | -| `POST /api/v1/workspaces/{workspace_id}/trust` | 授予信任 | -| `POST /api/v1/workspaces/{workspace_id}/untrust` | 撤销信任 | -| `POST /api/v1/workspaces/{workspace_id}/add-dir` | 添加附加目录 | +**示例**: -#### workspace 对象 +```json +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "authStatus": "oauth-authorized" } ], "request_id": "01JZX4..." } +``` -所有返回工作区的端点都使用此传输结构。注册与重命名会广播全局事件 `event.workspace.created` / `event.workspace.updated`。 +#### `POST /api/v2/mcp/auth:begin` -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | string | 工作区 id,由根路径派生的 `wd__` 字符串 | -| `root` | string | 项目目录的绝对路径 | -| `name` | string | 显示名,1–100 个字符;默认取根目录的基名 | -| `created_at` | string | 注册时间,ISO 8601 | -| `last_opened_at` | string | 最近一次打开或重新注册工作区的时间,ISO 8601 | -| `session_count` | integer | 工作区内的会话数 | +开始一次交互式 OAuth 流程。目标 server 必须使用远程传输(`http` / `sse`)且不含静态 bearer token;静态请求头仅当配置显式设置 `auth: "oauth"` 时允许。 -#### `GET /api/v1/workspaces` +**Body**:locator(`{ "source": "global", "name" }` 或 `{ "source": "plugin", "pluginId", "serverName" }`);另有可选的 `cwd` 查询参数。 -列出所有已注册工作区。 +**data**(code = 0):`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 -成功时 `data` 为 `{ items }`,每项是一个 [workspace 对象](#workspace-对象)。 +**非零 code**:`40001`(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 -#### `POST /api/v1/workspaces` +**示例**: -注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 +```json +{ "code": 0, "msg": "success", "data": { "status": "authorization-required", "flowId": "flow_01J...", "authorizationUrl": "https://mcp.example.com/authorize?..." }, "request_id": "01JZX4..." } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `root` | body | string | **必填。** 已存在目录的绝对路径 | -| `name` | body | string | 显示名,1–100 个字符。默认根目录的基名 | +#### `POST /api/v2/mcp/auth:complete` -成功时 `data` 为 [workspace 对象](#workspace-对象)。 +等待已开始流程的浏览器回调并完成 code 交换。等待默认 15 分钟(`timeoutMs` 可覆盖),空闲流程无论如何都会在 15 分钟后过期;关闭 HTTP 连接会中止等待。 -- `40001`:`root` 缺失或不是绝对路径(`details` 会列出该字段) -- `40409`:`root` 不存在或不是目录 +**Body**: -#### `PATCH /api/v1/workspaces/{workspace_id}` +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `flowId` | string | 是 | `auth:begin` 返回的流程 id | +| `timeoutMs` | integer | 否 | 等待上限(毫秒)。默认 15 分钟 | -重命名工作区——仅修改显示名,根路径不变。 +**data**(code = 0):`null`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | -| `name` | body | string | **必填。** 新的显示名,1–100 个字符 | +**非零 code**:`40001`(`flowId` 未知)、`40929`。 -成功时 `data` 为 [workspace 对象](#workspace-对象)。 +**示例**: -- `40001`:校验失败(`details` 逐字段说明) -- `40410`:工作区不存在 +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -#### `DELETE /api/v1/workspaces/{workspace_id}` +#### `POST /api/v2/mcp/auth:cancel` -注销工作区。只移除注册表条目——磁盘上的目录不受影响。 +在未完成的情况下终止已开始的流程;未知流程会被忽略。 -| 参数 | 位置 | 类型 | 说明 | +**Body**: + +| 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | +| `flowId` | string | 是 | 要终止的流程 id | -成功时 `data` 为 `{ deleted: true }`。 +**data**(code = 0):`null`。 -- `40410`:工作区不存在 +**示例**: -#### `GET /api/v1/workspaces/{workspace_id}/trust` +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。 +#### `POST /api/v2/mcp/auth:reset` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | +清除某个 server 已存储的凭据;失效事件会送达存活的会话。 -成功时 `data` 为 `{ trusted }`。 +**Body**:locator(形态同 `auth:begin`)。 -- `40410`:工作区不存在 +**data**(code = 0):`null`。 -#### `POST /api/v1/workspaces/{workspace_id}/trust` +**非零 code**:`40001`、`40408`(locator 未匹配)、`40929`。 -将工作区标记为信任,并加载其项目级 MCP 配置。 +**示例**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` -成功时 `data` 为 `{ trusted: true }`。 +## WebSocket 帧 -- `40410`:工作区不存在 +事件流端点为 `/api/v1/ws`。服务端到客户端的帧分五路: -#### `POST /api/v1/workspaces/{workspace_id}/untrust` +| 路由 | type 值 | 说明 | +| --- | --- | --- | +| 控制帧 | `server_hello` / `ping` / `ack` / `resync_required`(`error` 已声明但从不产出) | 连接管理,见 [控制帧](#控制帧) | +| 事件帧 | `event.*` 协议事件与裸 agent 事件 | 共享事件信封,见 [事件信封](#事件信封)、[event.\* 协议事件](#event-协议事件)、[agent 事件](#agent-事件) | +| transcript 帧 | `transcript.reset` / `transcript.ops` | 结构化转录流,见 [transcript 帧](#transcript-帧) | +| terminal 帧 | `terminal_output` / `terminal_exit` | 死协议,见 [terminal 帧](#terminal-帧) | -撤销工作区信任,并卸载其项目级 MCP 配置。 +入站(客户端→服务端)控制帧按到达顺序串行处理;未知 `type` 被静默忽略。出站事件先进批量队列(16 毫秒或 64 条 flush,1 MB 高水位背压);相邻同轮次的 `assistant.delta` / `thinking.delta` 帧在 flush 时会合并 `delta` 字符串——客户端不能把 delta 帧当不可变日志。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | +### 控制帧 -成功时 `data` 为 `{ trusted: false }`。 +客户端发送 JSON 帧 `{ "type", "id"?, "payload" }`;每个带 `id` 的入站帧都会收到一个 `ack` 应答。 -- `40410`:工作区不存在 +#### server_hello(服务端→客户端) -#### `POST /api/v1/workspaces/{workspace_id}/add-dir` +连接建立后的首帧。 -为工作区添加附加目录,语义与 CLI `--add-dir` 及 TUI `/add-dir` 一致。路径支持绝对路径、相对路径(相对工作区根目录解析)与 `~` 展开。 +**payload**: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace_id` | path | string | **必填。** 工作区 id | -| `path` | body | string | **必填。** 要添加的目录 | -| `persist` | body | boolean | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `ws_connection_id` | string | 连接 id(`conn_`) | +| `protocol_version` | number | 恒 `2`。当前无任何一侧判定该版本号 | +| `heartbeat_ms` | number | 心跳间隔(默认 `10000`) | +| `max_event_buffer_size` | number | 每会话事件缓冲容量(默认 `1000`),断线回放的上限 | +| `capabilities` | object | 恒 `{ "event_batching": false, "compression": false }` | -成功时 `data` 为 `{ project_root, config_path, additional_dirs, persisted }`,其中 `additional_dirs` 是全部附加目录(含既有目录),`persisted` 表示本次是否写盘。 +**示例**: -- `40001`:校验失败(`details` 逐字段说明),或项目本地配置损坏等引擎校验错误 -- `40409`:`path` 不存在或不是目录 -- `40410`:工作区不存在 +```json +{ "type": "server_hello", "timestamp": "2026-09-02T08:00:00.000Z", "payload": { "ws_connection_id": "conn_01JZX4...", "protocol_version": 2, "heartbeat_ms": 10000, "max_event_buffer_size": 1000, "capabilities": { "event_batching": false, "compression": false } } } +``` -### 文件系统 +#### ping / pong -会话内文件操作走 `POST /api/v1/sessions/{session_id}/fs:{action}`,请求体为 JSON;动作包括 `list` / `read` / `list_many` / `stat` / `stat_many` / `mkdir` / `search` / `grep` / `git_status` / `diff` / `open` / `open-in` / `reveal`。每个动作的请求体还接受可选的 `runtime_id`(string,默认 `local`),用于选择执行操作的运行时;`open`、`open-in` 与 `reveal` 仅在 `local` 运行时上可用。另有: +- 服务端→客户端:`{ "type": "ping", "timestamp", "payload": { "nonce": number } }`,每 `heartbeat_ms` 一帧。 +- 客户端→服务端:`{ "type": "pong", "payload": { "nonce": number } }`——服务端只重置心跳计时,不回 `ack`。连续两个周期没有任何入站帧,服务端以 `close(1001, 'heartbeat timeout')` 断连。 -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/workspace/fs:search` | 无会话的工作区搜索(body 携带工作区引用) | -| `POST /api/v1/workspace/fs:suggest` | 无会话的文件补全候选(用于 `@` 文件提及) | -| `GET /api/v1/sessions/{session_id}/fs/{path}:download` | 下载会话文件(二进制,见下文) | -| `GET /api/v1/fs:browse` | 列出本机目录(文件夹选择器用) | -| `GET /api/v1/fs:home` | 用户主目录与最近工作区 | -| `GET /api/v1/fs:content` | 读取本机任意文件原始字节(仅受 token 保护,谨慎暴露端口) | -| `POST /api/v1/fs:mkdir` | 按绝对路径创建目录 | +#### ack(服务端→客户端) -#### `POST /api/v1/sessions/{session_id}/fs:list` +每个带 `id` 的入站控制帧一个应答:`{ "type": "ack", "id", "code", "msg", "payload" }`。`code: 0` 成功;`1` 参数或内部错误;`40112` 鉴权失败(`client_hello.payload.token` 校验失败,随后连接关闭)。 -列出会话工作区目录下的条目,可选递归子目录。 +各入站帧及其 `ack` 的 payload: -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | 要列出的目录,相对于会话工作目录。默认 `.` | -| `depth` | body | integer | 递归深度,1–10。默认 `1` | -| `limit` | body | integer | 最大条目数,1–1000。默认 `200` | -| `show_hidden` | body | boolean | 包含点文件。默认 `false` | -| `follow_gitignore` | body | boolean | 跳过 gitignore 的路径。默认 `true` | -| `exclude_globs` | body | string[] | 额外要跳过的 glob | -| `sort` | body | string | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | -| `include_git_status` | body | boolean | 附带每个条目的 git 状态。默认 `false` | - -成功时 `data` 为 `{ items, truncated }`——`depth` 大于 1 时另附 `children_by_path`(路径 → 条目的映射)。每项是一个条目对象 `{ path, name, kind, size?, modified_at, etag?, mime?, language_id?, is_binary?, is_symlink_to?, git_status?, child_count? }`,其中 `kind` 为 `file` / `directory` / `symlink`;`git_status`(仅 `include_git_status: true` 时存在)为 `clean` / `modified` / `added` / `deleted` / `renamed` / `untracked` / `ignored` / `conflicted` 之一;`truncated` 表示 `limit` 截断了列表。 - -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在(包括 `path` 不是目录的情况) -- `41304`:路径越出会话工作区 +| 入站帧 | payload(入) | ack payload(出) | +| --- | --- | --- | +| `client_hello` | `{ client_id, subscriptions?, cursors?, agent_filter?, token? }` | `{ accepted_subscriptions, resync_required, cursors }` | +| `subscribe` | `{ session_ids: string[], cursors?, watch_fs?, agent_filter? }` | `{ accepted, not_found, resync_required, cursors }` | +| `subscribe_v2` | `{ session_id, transcript, transcript_since? }`(见 [transcript 帧](#transcript-帧)) | 同 `subscribe` | +| `unsubscribe_v2` | `{ session_id, agent_ids? }` | `{ accepted: [session_id], not_found: [], resync_required: [] }`(无 `cursors` 键) | +| `unsubscribe` | `{ session_ids: string[] }` | `{ accepted: [], not_found: [], resync_required: [] }`(恒空数组) | +| `watch_fs_add` / `watch_fs_remove` | `{ session_id, paths: string[], runtime_id?, recursive? }` | `{ watched_paths, current_count }`;bridge 缺失或异常时 `code: 1` | -#### `POST /api/v1/sessions/{session_id}/fs:read` +字段说明: -以文本或 base64 读取会话文件的一段内容。 +- `cursors`:`Record`——断线恢复游标,见 [断线恢复](#断线恢复)。带游标订阅时服务端回放缺口事件;无法回放时先发 `resync_required`,并把该会话 id 列入 `ack` 的 `resync_required`。 +- `watch_fs`:`Record`——随订阅一并登记的文件监听(等价于逐会话发 `watch_fs_add`),变更经 `event.fs.changed` 送达。 +- `agent_filter`:`Record`——只接收所列 Agent 的事件。 +- `token`:`client_hello` 的冗余第二鉴权通道(升级请求已鉴权,缺省直接放行)。 +- `client_id === 'kimi-inspect'` 的连接会被加入 DI 事件目标集(`event.di.*` 的门控,见 [event.\* 协议事件](#event-协议事件))。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 文件路径,相对于会话工作目录 | -| `offset` | body | integer | 起始字节偏移。默认 `0` | -| `length` | body | integer | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | -| `encoding` | body | string | `auto`(默认)/ `utf-8` / `base64` | - -成功时 `data` 为 `{ path, content, encoding, size, truncated, etag, mime, language_id?, line_count?, is_binary }`,其中 `encoding` 报告实际使用的编码(`utf-8` 或 `base64`),`size` 为文件完整大小。`encoding: "auto"` 时文本以 `utf-8` 返回(非 UTF-8 文本会被转码),二进制内容以 `base64` 返回;`encoding: "utf-8"` 强制按文本读取并拒绝二进制文件。 - -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `40906`:路径是目录 -- `40907`:二进制文件却指定了 `encoding: "utf-8"` -- `41302`:文件超过 10 MiB 读取上限 -- `41304`:路径越出会话工作区 +**示例**(`subscribe` 的 `ack`): -#### `POST /api/v1/sessions/{session_id}/fs:list_many` +```json +{ "type": "ack", "id": "1", "code": 0, "msg": "ok", "payload": { "accepted": [ "session_01JZX4..." ], "not_found": [], "resync_required": [], "cursors": { "session_01JZX4...": { "seq": 128, "epoch": "01JZX4..." } } } } +``` -一次调用列出多个会话目录;失败的路径会折进响应里,而不是让整个请求失败。 +#### resync_required(服务端→客户端) -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `paths` | body | string[] | **必填。** 要列出的目录,1–100 条 | +订阅游标无法回放时下发:事件缓冲溢出(`buffer_overflow`)、会话被重建(`session_recreated`)或 `epoch` 不符(`epoch_changed`)。处理方式见 [断线恢复](#断线恢复)。 -其余请求体字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)的类型、取值范围与默认值同 `fs:list`。成功时 `data` 为 `{ results }`——每个请求路径到其条目数组(条目对象见 `fs:list` 的说明)的映射,另附 `truncated_paths`(达到 `limit` 的路径)与 `partial_errors`(失败路径到其 `{ code, msg }` 错误的映射)。 +**payload**: -- `40001`:请求体校验失败 -- `40401`:会话不存在 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `session_id` | string | 需要重新同步的会话 | +| `reason` | string | `buffer_overflow` / `session_recreated` / `epoch_changed` | +| `current_seq` | integer | 当前事件水位 | +| `epoch` | string | 可缺省:当前 epoch | -#### `POST /api/v1/sessions/{session_id}/fs:stat` +**示例**: -查询会话工作区内单个路径的元信息。 +```json +{ "type": "resync_required", "timestamp": "2026-09-02T08:10:00.000Z", "payload": { "session_id": "session_01JZX4...", "reason": "buffer_overflow", "current_seq": 1420, "epoch": "01JZX4..." } } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 要查询的路径,相对于会话工作目录 | +#### error(控制帧,死声明) -成功时 `data` 为 `fs:list` 中说明的条目对象。 +控制帧形态的 `error`(`{ type: "error", timestamp, payload: { code, msg, fatal, request_id?, details? } }`)在 AsyncAPI 中声明,但服务端没有任何产出点。事件流中出现的 `type: "error"` 帧均为裸 agent `error` 事件(带 `session_id` / `seq` 事件信封,见 [agent 事件](#agent-事件)),客户端可按有无 `session_id` 分流。 -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `41304`:路径越出会话工作区 +### 事件信封 -#### `POST /api/v1/sessions/{session_id}/fs:stat_many` +所有事件帧共享外层 `{ "type", "seq", "epoch"?, "volatile"?, "offset"?, "session_id", "timestamp", "payload" }`:`type` 与 `payload` 内事件的 `type` 重复一次;`session_id` 在全局事件上为 `__global__`;`timestamp` 为 ISO 8601(事件自带时间时取之)。`seq` / `epoch` / `volatile` / `offset` 的语义随产出器分四种形态: -一次调用查询多个会话路径的元信息;不存在的路径返回 `null`,不会让整个请求失败。 +| 形态 | `seq` | `epoch` | `volatile` | `offset` | +| --- | --- | --- | --- | --- | +| 持久(durable)事件 | 事件日志水位,严格递增并落盘 | 有 | 缺省 | 缺省 | +| 易失(volatile)事件 | 当前水位(不递增,与前后持久帧同 `seq`) | 有 | `true` | delta 类携带(该轮次内累计文本长度) | +| transcript 帧 | 外层为会话事件水位(非 transcript seq);transcript seq 在 `payload.seq` | 有 | `true` | 缺省 | +| `event.fs.changed` | 文件监听作用域自增计数(与事件日志无关) | **无** | 缺省 | 缺省 | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `paths` | body | string[] | **必填。** 要查询的路径,1–1000 条 | +易失类型全集:`assistant.delta` / `thinking.delta` / `tool.call.delta` / `tool.progress` / `shell.started` / `shell.output` / `shell.completed` / `agent.status.updated`,另有 `event.di.unit_changed` 与 `event.capability.changed`。易失事件不落盘、不回放;消费易失文本流时用 `offset` 与本地已累积文本比对:小于本地长度说明是重复帧,大于说明有缺漏、需走快照恢复。 -成功时 `data` 为 `{ entries }`——每个请求路径到其条目对象(见 `fs:list` 的说明)的映射,路径不存在时为 `null`。 +投递范围分两类:**全局事件**广播给每个已建立连接(含未订阅该会话的)——`session.meta.updated`、`event.session.*`、`event.workspace.*`、`event.config.*`、`event.model_catalog.*`、`event.plugin.*`、`event.capability.*`、`event.di.*`(仅发往 `client_id: "kimi-inspect"` 的连接);**会话事件**只发给订阅了该会话的连接,受 `agent_filter` 过滤——`event.question.*`、`event.approval.*` 与全部裸 agent 事件。`event.fs.changed` 单独一路:仅发往经 `watch_fs_add`(或 `subscribe` 的 `watch_fs`)登记了对应路径监听的连接。这些事件只覆盖本服务进程内的变更;其他进程(例如写同一 home 目录的 CLI)的变更要等索引 reconcile(约一分钟)才可见,因此概览客户端应保留低频兜底轮询。目前没有会话删除事件。 -- `40001`:请求体校验失败 -- `40401`:会话不存在 +### event.* 协议事件 -#### `POST /api/v1/sessions/{session_id}/fs:mkdir` +payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__global__` 或真实会话 id)。除标注外均为持久事件;各族的投递范围见 [事件信封](#事件信封)。 -在会话工作区内创建目录。 +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `event.session.created` | `session: T-Session` | 创建会话 / fork / 创建子会话时 | +| `event.session.archived` | `workspace_id`(另有 `agentId` 与 camelCase `sessionId`) | 在线与冷归档两条路径都会发出;概览免轮询 | +| `event.session.work_changed` | `busy, main_turn_active, pending_interaction, last_turn_reason?` | 会话工作聚合变化时 | +| `event.session.status_changed` | — | schema 已声明但**无产出点** | +| `event.workspace.created` | `workspace: T-Workspace` | 注册工作区时 | +| `event.workspace.updated` | `workspace: T-Workspace` | 重命名 / 重新注册 / 会话创建触碰工作区时 | +| `event.workspace.deleted` | `workspace_id, root` | 注销工作区时 | +| `event.config.changed` | `changedFields: string[]`(camelCase 域名)、`config: T-ConfigResponse` | 任何来源的配置变更;短时间窗内多次变更合并为一个事件 | +| `event.config.warning` | `warnings: { domain?, message }[]` | 配置告警 | +| `event.model_catalog.changed` | `changed, unchanged, failed`(同 [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)) | 至少一个供应商的别名变化时 | +| `event.plugin.changed` | (无附加字段) | 插件安装 / 启用 / 停用 / 移除时 | +| `event.capability.changed` | `capability_id, install: { running, step?, percent?, error?, note? }` | 易失;能力安装进度 | +| `event.di.unit_changed` | `scope, token, state, error?` | 易失;仅发往 `client_id: "kimi-inspect"` 的连接;`state` 取值同 meta `features[].state`,枚举非封闭 | +| `event.question.requested` | [T-QuestionRequest](#t-questionrequest) 全字段 | 提问到达 | +| `event.question.answered` | `question_id, answers, resolved_at` | `answers` 为拍平的文本 map(`Record<条目 id, 文本>`),与 REST 的结构化 answers 形态不同 | +| `event.question.dismissed` | `question_id, dismissed_at` | | +| `event.approval.requested` | [T-ApprovalRequest](#t-approvalrequest) 全字段 | 审批到达 | +| `event.approval.resolved` | `approval_id, decision?, scope?, feedback?, selected_label?, resolved_at` | | +| `event.fs.changed` | `changes: { path, change, kind, size_delta?, etag? }[], coalesced_window_ms, truncated?, count?` | `change` 为 `created` / `modified` / `deleted`,`kind` 为 `file` / `directory` / `symlink`;`truncated: true` 时 `changes` 为空数组。信封特殊(见 [事件信封](#事件信封)) | + +**示例**(`event.session.work_changed`): -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 要创建的目录,相对于会话工作目录 | -| `recursive` | body | boolean | 创建缺失的父目录。默认 `false` | +```json +{ "type": "event.session.work_changed", "seq": 129, "epoch": "01JZX4...", "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:00.000Z", "payload": { "type": "event.session.work_changed", "busy": true, "main_turn_active": true, "pending_interaction": "none", "agentId": "main", "sessionId": "session_01JZX4..." } } +``` -成功时 `data` 为所建目录的条目对象(见 `fs:list` 的说明)。 +### agent 事件 -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:父目录不存在(非递归创建) -- `40919`:路径已存在(非递归创建) -- `41304`:路径越出会话工作区 +裸 agent 事件的 `payload` 为核心事件对象字段外加广播器补充的 `{ agentId, sessionId }`(camelCase);除标注外均为持久事件。广播器的特判: -#### `POST /api/v1/sessions/{session_id}/fs:search` +- `prompt.accepted` 被过滤,不广播。 +- `turn.started` 的 `promptAttachments` 被显式剥离(schema 声明但 wire 上不出现)。 +- `prompt.submitted` / `prompt.queued` / `prompt.steered` 的 `content` 从核心内容块投影为 [T-MessageContent](#t-messagecontent) 数组。 +- `task.started` / `task.terminated` 各自额外派生一条 `background.task.started` / `background.task.terminated`(同 payload 改 type,随后发出)。 +- `context.spliced` 触发一次 main agent 的 `agent.status.updated` 重发。 -在会话工作区内模糊搜索文件与目录名。`query` 为空时改为列出顶层条目。当 `{session_id}` 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 `POST /api/v1/workspace/fs:search`。 +#### 轮次族 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id,或工作区引用 | -| `query` | body | string | **必填。** 搜索文本;`""` 表示列出顶层 | -| `limit` | body | integer | 最大命中数,1–200。默认 `50` | -| `include_globs` | body | string[] | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | body | string[] | 跳过匹配这些 glob 的路径 | -| `follow_gitignore` | body | boolean | 跳过 gitignore 的路径。默认 `true` | +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `turn.started` | `turnId, origin, prompt?, promptId?` | `origin` 为 [T-PromptOrigin](#t-promptorigin);无 `promptAttachments` | +| `turn.ended` | `turnId, reason, error?, durationMs?, interruptReason?, time?` | `reason` 为 `completed` / `cancelled` / `failed` / `blocked`;`error` 为 [T-KimiError](#t-kimierror) | +| `turn.step.started` | `turnId, step, stepId?` | | +| `turn.step.completed` | `turnId, step, stepId?, usage?, finishReason?, providerFinishReason?, rawFinishReason?` 及时延组字段 | `usage` 为 [T-TokenUsage](#t-tokenusage) | +| `turn.step.retrying` | `turnId, step, stepId?, failedAttempt, nextAttempt, maxAttempts, delayMs, errorName, errorMessage, statusCode?` | | +| `turn.step.interrupted` | `turnId, step, stepId?, reason, message?` | | -成功时 `data` 为 `{ items, truncated }`,每项为 `{ path, name, kind, score, match_positions }`——`kind` 为 `file` / `directory` / `symlink`,`score` 为 0 到 1 之间的模糊匹配得分,`match_positions` 列出匹配到的字符偏移。命中按得分排序(同分按路径),`truncated` 表示超出 `limit` 的命中被丢弃。 +#### 流式文本族(易失) -- `40001`:请求体校验失败 -- `40401`:该引用既不是会话,也不是可解析的工作区 +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `assistant.delta` | `turnId, delta` | 带 `offset`;相邻同轮次帧可能被合并 | +| `thinking.delta` | `turnId, delta` | 同上 | -#### `POST /api/v1/sessions/{session_id}/fs:grep` +#### 工具调用族 -在会话工作区内搜索文件内容——默认按字面字符串,`regex: true` 时按正则表达式。 +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `tool.call.delta` | `turnId, toolCallId, name?, argumentsPart?` | 易失 | +| `tool.call.started` | `turnId, toolCallId, name, args, description?, display?` | `display` 为 [T-ToolInputDisplay](#t-toolinputdisplay) | +| `tool.progress` | `turnId, toolCallId, update` | 易失;`update` 为 `{ kind: "stdout" \| "stderr" \| "progress" \| "status" \| "custom", text?, percent?, customKind?, customData?, replace? }` | +| `tool.result` | `turnId, toolCallId, output, isError?, synthetic?` | | +| `tool.list.updated` | `reason, serverName` | `reason` 为 `mcp.connected` / `mcp.disconnected` / `mcp.failed` | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `pattern` | body | string | **必填。** 要搜索的文本或正则 | -| `regex` | body | boolean | 将 `pattern` 视为正则表达式。默认 `false` | -| `case_sensitive` | body | boolean | 默认 `true` | -| `include_globs` | body | string[] | 只保留匹配这些 glob 之一的文件 | -| `exclude_globs` | body | string[] | 跳过匹配这些 glob 的文件 | -| `follow_gitignore` | body | boolean | 跳过 gitignore 的路径。默认 `true` | -| `max_files` | body | integer | 最多扫描的文件数,1–10000。默认 `200` | -| `max_matches_per_file` | body | integer | 每个文件保留的匹配数,1–10000。默认 `50` | -| `max_total_matches` | body | integer | 总共保留的匹配数,1–100000。默认 `5000` | -| `context_lines` | body | integer | 每个匹配携带的上下文行数,0–10。默认 `2` | - -成功时 `data` 为 `{ files, files_scanned, truncated, elapsed_ms }`,其中 `files` 的每项为 `{ path, matches }`,每个匹配为 `{ line, col, text, before, after }`(`before` / `after` 最多携带 `context_lines` 行上下文);`truncated` 表示某个匹配配额截断了结果。 - -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `41305`:搜索超时 +#### Shell 族(易失) -#### `POST /api/v1/sessions/{session_id}/fs:git_status` +| type | payload 字段 | +| --- | --- | +| `shell.started` | `commandId, taskId` | +| `shell.output` | `commandId, update, taskId?`(`update` 形态同 `tool.progress`) | +| `shell.completed` | `commandId, isError, taskId?` | -读取会话工作区的 git 状态,可选限定在一组路径内。 +#### 任务族 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `paths` | body | string[] | 将状态限定在这些路径;省略表示整个工作区 | +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `task.started` | `info` | `info` 为 T-TaskInfo(camelCase:`taskId, description, status, detached?, startedAt, endedAt?, stopReason?, timeoutMs?` 及 process / agent / question 三态各自扩展) | +| `task.terminated` | `info` | 同上 | +| `background.task.started` | 同 `task.started` | 派生帧 | +| `background.task.terminated` | 同 `task.terminated` | 派生帧 | +| `task.notified` | `notificationType, title, body, severity, sourceKind, sourceId` | `severity` 为 `info` / `warning` | -成功时 `data` 为 `{ branch, ahead, behind, entries, additions, deletions, pullRequest }`,其中 `entries` 把每个变更路径映射到其状态(`clean` / `modified` / `added` / `deleted` / `renamed` / `untracked` / `ignored` / `conflicted`),`pullRequest` 为 `{ number, state, url }`(`state` 为 `open` / `merged` / `closed` / `draft`)或 `null`。 +#### subagent 族 -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40908`:git 不可用(不是仓库,或没有 git 可执行文件) +| type | payload 字段 | +| --- | --- | +| `subagent.spawned` | `subagentId, subagentName, parentToolCallId, parentToolCallUuid?, parentAgentId?, callerAgentId?, description?, swarmIndex?, runInBackground, model?, thinkingEffort?, taskId?` | +| `subagent.started` | `subagentId` | +| `subagent.suspended` | `subagentId, reason` | +| `subagent.completed` | `subagentId, resultSummary, usage?, contextTokens?` | +| `subagent.failed` | `subagentId, error` | -#### `POST /api/v1/sessions/{session_id}/fs:diff` +#### prompt 族 -返回会话工作区内单个文件的 unified git diff。 +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `prompt.submitted` | `promptId, userMessageId, status, content, createdAt` | `status` 为 `running` / `queued`;`content` 为投影后的 [T-MessageContent](#t-messagecontent) 数组 | +| `prompt.queued` | `promptId, content, queueLength` | | +| `prompt.started` | `promptId` | | +| `prompt.completed` | `promptId, finishedAt, reason` | `reason` 恒产出,为 `completed` / `failed` / `blocked` | +| `prompt.aborted` | `promptId, abortedAt` | | +| `prompt.steered` | `activePromptId, promptIds, content, steeredAt` | | +| `turn.steer` | `input, origin` | `input` 为核心内容块数组(**未投影**);`origin` 为 [T-PromptOrigin](#t-promptorigin) | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 要 diff 的文件,相对于会话工作目录 | +#### compaction 族 -成功时 `data` 为 `{ path, diff, truncated }`,其中 `diff` 为 unified diff 文本,`truncated` 表示过长的 diff 被截断。 +| type | payload 字段 | +| --- | --- | +| `compaction.started` | `trigger?`(`manual` / `auto`)、`instruction?` | +| `compaction.blocked` | `turnId?` | +| `compaction.cancelled` | — | +| `compaction.completed` | `result: { summary, compactedCount, tokensBefore, tokensAfter, keptUserMessageCount?, keptHeadUserMessageCount?, droppedCount? }` | +| `context.spliced` | `start, deleteCount, messages, tokens?`(`messages` 为核心 ContextMessage 数组,**未投影**) | -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40908`:git 不可用(不是仓库,或没有 git 可执行文件) -- `41304`:路径越出会话工作区 +#### 其他 agent 事件 -#### `POST /api/v1/sessions/{session_id}/fs:open` +| type | payload 字段 | 备注 | +| --- | --- | --- | +| `goal.updated` | `snapshot, change?` | `snapshot` 为 [T-GoalSnapshot](#t-goalsnapshot) 或 `null`;`change` 为 `{ kind: "lifecycle" \| "completion", status?, reason?, stats?, actor? }` | +| `plan.revision` | `id, version, path, sha256, bytes` | | +| `skill.activated` | `activationId, skillName, skillArgs?, trigger, skillPath?, skillSource?` | `trigger` 为 `user-slash` / `model-tool` / `nested-skill` | +| `plugin_command.activated` | `activationId, pluginId, commandName, commandArgs?, trigger` | `trigger` 恒 `user-slash` | +| `agent.status.updated` | `usage?, swarmMode?, towerMode?, planMode?, model?, thinkingEffort?, maxContextTokens?, contextTokens?` 合并 legacy 状态(`usage?, contextTokens, maxContextTokens?, model`),外加 `phase?` | 易失;`phase` 为 [T-AgentPhase](#t-agentphase)。schema 声明的 `permission` / `contextUsage` 无产出路径 | +| `agent.created` | (仅 `agentId` / `sessionId`) | | +| `agent.disposed` | (仅 `agentId` / `sessionId`) | | +| `session.meta.updated` | `title?, patch?` | 全局事件(广播给所有连接) | +| `error` | [T-KimiError](#t-kimierror) | 带事件信封;与控制帧 `error`(死声明)不同 | +| `warning` | `message, code?` | | +| `cron.fired` | `origin, prompt` | `origin` 为 T-CronJobOrigin | +| `hook.result` | `turnId?, hookEvent, content, blocked?` | | +| `mcp.server.status` | `server: { name, transport, status, toolCount, error? }` | `status` 直接透传核心六态:`pending` / `connected` / `failed` / `disabled` / `needs-auth` / `removed`——与 REST [T-McpServer](#t-mcpserver) 的四态取值域不同 | + +**示例**(`tool.call.started`): -用宿主操作系统的默认程序打开会话文件。仅限 local 运行时。 +```json +{ "type": "tool.call.started", "seq": 131, "epoch": "01JZX4...", "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:05.000Z", "payload": { "type": "tool.call.started", "turnId": 3, "toolCallId": "toolu_01J...", "name": "Bash", "args": { "command": "pnpm test" }, "display": { "kind": "command", "command": "pnpm test" }, "agentId": "main", "sessionId": "session_01JZX4..." } } +``` -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 要打开的文件,相对于会话工作目录 | -| `line` | body | integer | 在处理程序支持时跳转到的行号(正整数) | +### transcript 帧 -成功时 `data` 为 `{ opened: true }`。 +`subscribe_v2` 是唯一的转录订阅通道:其 `transcript` 按 Agent 指定粒度(`off` / `turn` / `block` / `delta`,键 `"*"` 表示默认粒度),粒度越高推送越细。粒度非 `off` 的 Agent 改由转录帧承载,该 Agent 的旧式事件在同一连接上被抑制(其他连接不受影响)。两种帧型: -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `41304`:路径越出会话工作区 +| type | payload | 触发 | +| --- | --- | --- | +| `transcript.reset` | `{ type, agent_id, snapshot, has_more_older, seq? }` | 订阅、粒度升级或新 Agent 上名册时发送基线快照(`snapshot` 按订阅粒度裁剪,items 为空、仅全局状态与水位;历史经 REST 分页回读) | +| `transcript.ops` | `{ type, agent_id, ops, seq? }` | 转录存储产生 op 批次,或 `transcript_since` 游标回放 | -#### `POST /api/v1/sessions/{session_id}/fs:open-in` +两帧的信封均为 `volatile: true`,外层 `seq` 为会话事件水位;每个 Agent 连续递增的 transcript seq 在 `payload.seq`。断线时用 `subscribe_v2` 的 `transcript_since`(`Record`)续传:服务端批次日志完整覆盖缺口时走 `transcript.ops` 回放,否则重发 `transcript.reset`;REST 侧对应 `GET .../transcript/ops?since_seq=`(补漏返回 `complete: false` 时需全量刷新)。粒度升降是否重发 reset 由转录契约的粒度规则决定。 -在指定的宿主应用程序中打开会话文件或目录。仅限 local 运行时。 +**示例**(`transcript.ops`): -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `app_id` | body | string | **必填。** 目标应用:`finder` / `cursor` / `vscode` / `iterm` / `terminal` | -| `path` | body | string | **必填。** 要打开的文件或目录,相对于会话工作目录 | -| `line` | body | integer | 在应用支持时跳转到的行号(正整数) | +```json +{ "type": "transcript.ops", "seq": 132, "epoch": "01JZX4...", "volatile": true, "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:06.000Z", "payload": { "type": "transcript.ops", "agent_id": "main", "ops": [ { "op": "append", "...": "..." } ], "seq": 43 } } +``` -成功时 `data` 为 `{ opened: true }`。 +### terminal 帧 -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `41304`:路径越出会话工作区 -- `50001`:应用启动失败 +`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点(见 [终端](#终端))不受影响。 -#### `POST /api/v1/sessions/{session_id}/fs:reveal` +## 类型汇总 -在宿主操作系统的文件管理器中显示会话文件。仅限 local 运行时。 +端点与帧型共享的类型字典。「可缺省」表示该键可能不出现(`undefined` 被序列化丢弃),「可空」表示显式 `null`,两者语义不同(见 [null 与缺省语义](#null-与缺省语义))。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | body | string | **必填。** 要显示的文件,相对于会话工作目录 | +### T-Session -成功时 `data` 为 `{ revealed: true }`。 +会话对象。返回会话的各端点(除快照)中 `usage` 恒为全 0 的 T-SessionUsage、`permission_rules` 恒 `[]`、`message_count` 恒 `0`;`last_seq` 仅 `GET /api/v1/sessions/{session_id}` 携带真实事件水位,其余端点恒 `0`。 -- `40001`:请求体校验失败 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `41304`:路径越出会话工作区 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `id` | string | 会话 id(`session_...`) | +| `workspace_id` | string | 所属工作区 id(`wd__`) | +| `title` | string | 标题;未设置时为 `""` | +| `created_at` | string | 创建时间,ISO 8601 | +| `updated_at` | string | 最后更新时间,ISO 8601 | +| `archived_at` | string | 可缺省:归档时间;未归档时不出现 | +| `busy` | boolean | 任一 Agent 有活动轮次或后台任务 | +| `main_turn_active` | boolean | main agent 轮次进行中 | +| `pending_interaction` | string | `none` / `approval` / `question` | +| `last_turn_reason` | string | 可缺省:`completed` / `cancelled` / `failed`——存活会话取实时值,冷会话取最后持久化值,均无则缺省 | +| `archived` | boolean | 归档标记 | +| `last_prompt` | string | 可缺省:最近一条提示词文本 | +| `metadata` | object | 必含 `cwd: string`;附加自定义任意键(`goal` 键被剔除) | +| `agent_config` | object | 恒 `{ "model": string }`——存活会话取绑定模型,否则 `""`;schema 声明的其余配置键产出侧均不出现 | +| `usage` | object | [T-SessionUsage](#t-sessionusage) | +| `permission_rules` | array | 恒 `[]` | +| `message_count` | integer | 恒 `0` | +| `last_seq` | integer | 事件水位或 `0`,见上 | + +schema 另声明的 `current_prompt_id` 产出侧从不出现(仅快照的 `in_flight_turn` 有同名字段)。 + +### T-SessionUsage + +`{ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, total_cost_usd, context_tokens, context_limit, turn_count }`——全部 number。普通会话端点恒全 0;快照端点用法不同,见 [T-SnapshotUsage](#t-snapshotusage)。 + +### T-SessionStatus + +main agent 的实时状态汇总。 -#### `GET /api/v1/sessions/{session_id}/fs/{path}:download` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `busy` | boolean | 同 T-Session 的 `busy` | +| `model` | string | 可缺省:模型别名;未绑定时不出现 | +| `thinking_level` | string | 思考档位;模型未绑定时为 `""` | +| `permission` | string | `manual` / `yolo` / `auto` | +| `plan_mode` | boolean | Plan 模式 | +| `swarm_mode` | boolean | swarm 模式 | +| `tower_mode` | boolean | tower 模式 | +| `context_tokens` | integer | 当前上下文 tokens | +| `max_context_tokens` | integer | 可缺省:上下文上限;不可解析时不出现 | +| `context_usage` | number | 可缺省:上下文占比(0–1);无上限时不出现 | -从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流——见 [二进制与流式端点](#二进制与流式端点)。 +### T-GoalSnapshot -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `session_id` | path | string | **必填。** 会话 id | -| `path` | path | string | **必填。** 相对于工作区的文件路径,加 `:download` 后缀 | -| `runtime_id` | query | string | 从哪个运行时读取。默认 `local` | +目标快照(camelCase 载荷):`{ goalId, objective, completionCriterion?, status, turnsUsed, tokensUsed, wallClockMs, budget, terminalReason? }`。 -- `40001`:路径缺失或为空 -- `40401`:会话不存在 -- `40409`:路径不存在 -- `41304`:路径越出会话工作区 +- `status`:`active` / `paused` / `blocked` / `complete`。 +- `budget`:`{ tokenBudget, turnBudget, wallClockBudgetMs, remainingTokens, remainingTurns, remainingWallClockMs }`(六项均 number 或 `null`)加 `{ tokenBudgetReached, turnBudgetReached, wallClockBudgetReached, overBudget }`(均 boolean)。 -#### `POST /api/v1/workspace/fs:search` +### T-Message -`fs:search` 的无会话形式:工作区改由请求体而非 URL 携带。 +消息对象。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace` | body | string | **必填。** 已注册工作区 id 或绝对根路径(当场注册) | -| `query` | body | string | **必填。** 搜索文本;`""` 表示列出顶层 | -| `limit` | body | integer | 最大命中数,1–200。默认 `50` | -| `include_globs` | body | string[] | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | body | string[] | 跳过匹配这些 glob 的路径 | -| `follow_gitignore` | body | boolean | 跳过 gitignore 的路径。默认 `true` | -| `runtime_id` | body | string | 在哪个运行时上搜索。默认 `local` | +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `id` | string | 消息 id(`msg__<6 位序号>` 或核心 id) | +| `session_id` | string | 所属会话 | +| `role` | string | `user` / `assistant` / `tool` / `system` | +| `content` | array | [T-MessageContent](#t-messagecontent) 数组 | +| `created_at` | string | ISO 8601,单调递增 | +| `metadata` | object | 可缺省:仅当消息带 origin 时——`{ origin: <核心 PromptOrigin 对象> }`(camelCase 嵌套,原样透传) | -成功时 `data` 为 `{ items, truncated }`,命中结构与排序同 `fs:search`。 +schema 声明的 `prompt_id` / `parent_message_id` 产出侧从不出现。 -- `40001`:请求体校验失败 -- `40410`:工作区不存在,且不是可用的绝对路径 +### T-MessageContent -#### `POST /api/v1/workspace/fs:suggest` +消息内容块,按 `type` 区分: -在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 `@` 文件提及的后端。 +| `type` | 字段 | 说明 | +| --- | --- | --- | +| `text` | `text: string` | 文本;`audio_url` 降级为 `[audio:]` 文本 | +| `thinking` | `thinking: string, signature?: string` | 思考块 | +| `tool_use` | `tool_call_id, tool_name, input` | assistant 消息的工具调用;`input` 为解析后的参数(解析失败回原字符串) | +| `tool_result` | `tool_call_id, output, is_error?: boolean` | tool 角色消息;`output` 有媒体块时为原始内容块数组,否则为拼接文本;`is_error` 仅 `true` 时出现 | +| `image` / `video` | `source` | 见下 | +| `file` | `file_id?, path?, name?, media_type?, size?` | 仅出现在输入(提示词 / 技能提交);REST 投影不产出 | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `workspace` | body | string | **必填。** 已注册工作区 id 或绝对根路径(当场注册) | -| `query` | body | string | **必填。** 要补全的部分路径文本 | -| `limit` | body | integer | 最大候选数,1–200。默认 `50` | -| `follow_gitignore` | body | boolean | 跳过 gitignore 的路径。默认 `true` | -| `show_hidden` | body | boolean | 包含点文件。默认 `false` | -| `include_globs` | body | string[] | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | body | string[] | 跳过匹配这些 glob 的路径 | -| `runtime_id` | body | string | 在哪个运行时上补全。默认 `local` | +`image` / `video` 的 `source`(产出侧三种,按 `kind` 区分):`{ kind: "url", url, id? }`(外部 URL)、`{ kind: "base64", media_type, data }`(仅提示词提交回显)、`{ kind: "session_media", file_id }`(会话媒体引用)。schema 声明的 `{ kind: "file", file_id }` 与 `{ kind: "path", path }` 为输入专用变体,产出侧不出现。 -成功时 `data` 为 `{ items, truncated }`,每项为 `{ path, name, kind, score, match_positions }`,命中结构同 `fs:search`。 +### T-PromptItem -- `40001`:请求体校验失败 -- `40410`:工作区不存在,且不是可用的绝对路径 +提示词队列项 / 提交结果。 -#### `GET /api/v1/fs:browse` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `prompt_id` | string | 提示词 id | +| `user_message_id` | string | 用户消息 id(Skill 捆绑提交时与 `prompt_id` 相同) | +| `status` | string | `running` / `queued` / `blocked` | +| `content` | array | 投影后的用户输入([T-MessageContent](#t-messagecontent) 数组,剥离 Skill 捆绑块) | +| `created_at` | string | ISO 8601 | -列出某个本机目录的子目录——文件夹选择器的后端。 +### T-ApprovalRequest -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `path` | query | string | 绝对目录路径。默认用户主目录 | +审批请求:`{ approval_id, session_id, turn_id?, tool_call_id, tool_name, action, tool_input_display, created_at, expires_at }`。 -成功时 `data` 为 `{ path, parent, entries }`,其中 `path` 为解析后的目录,`parent` 为其父目录(文件系统根处为 `null`),每条目为 `{ name, path, is_dir: true }`。 +- `turn_id`:number,可缺省。 +- `tool_call_id`:缺省时回退为交互 id。 +- `tool_input_display`:[T-ToolInputDisplay](#t-toolinputdisplay)。 +- `expires_at`:`created_at` 之后 24 小时。 -- `40001`:`path` 不是绝对路径 -- `40409`:路径不存在 -- `40411`:权限不足 +### T-ToolInputDisplay -#### `GET /api/v1/fs:home` +工具输入展示,按 `kind` 区分:`command`(`command` / `cwd?` / `description?` / `language?`)、`file_io`(`operation` / `path` / `detail?` / `content?` / `before?` / `after?`)、`diff`(`path` / `before` / `after` / `hunks?`)、`search`(`query` / `scope?`)、`url_fetch`(`url` / `method?`)、`agent_call`(`agent_name` / `prompt` / `background?`)、`skill_call`(`skill_name` / `args?`)、`todo_list`(`items: { title, status }[]`)、`task`(`task_id` / `status` / `description` / `task_kind?`)、`task_stop`(`task_id` / `task_description`)、`plan_review`(`plan` / `path?` / `options?: { label, description }[]`)、`goal_start`(`objective` / `completionCriterion?` / `mode`)、`generic`(`summary` / `detail?`)。 -返回文件夹选择器的落地数据。无参数。 +### T-QuestionRequest -成功时 `data` 为 `{ home, recent_roots }`,其中 `home` 为用户主目录,`recent_roots` 列出已注册工作区的根目录。 +提问请求。 -#### `GET /api/v1/fs:content` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `question_id` | string | 交互 id | +| `session_id` | string | 所属会话 | +| `turn_id` | number | 可缺省 | +| `tool_call_id` | string | 可缺省 | +| `questions` | array | 1–4 个 T-QuestionItem | +| `created_at` | string | ISO 8601 | -以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 [二进制与流式端点](#二进制与流式端点)。 +T-QuestionItem:`{ id: "q_", question, header?, body?, options, multi_select?, allow_other, other_label?, other_description? }`——`options` 为 2–4 个 `{ id: "opt__", label, description? }`(id 由投影合成);`allow_other` 恒产出。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `path` | query | string | **必填。** 绝对文件路径 | +### T-Task -- `40001`:`path` 不是绝对路径,或不是普通文件 -- `40409`:路径不存在 -- `40411`:权限不足 -- `40906`:路径是目录 +后台任务。 -#### `POST /api/v1/fs:mkdir` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `id` | string | 任务 id | +| `session_id` | string | 所属会话 | +| `kind` | string | `subagent` / `bash` / `tool`(核心映射:process→`bash`、agent→`subagent`、question→`tool`) | +| `description` | string | 描述 | +| `status` | string | `running` / `completed` / `failed` / `cancelled`(核心映射:timed_out→`failed`、killed→`cancelled`、lost→`failed`) | +| `created_at` | string | 取 startedAt,ISO 8601 | +| `started_at` | string | 与 `created_at` 相同 | +| `completed_at` | string | 可缺省:结束时间 | +| `command` | string | 可缺省:仅 `bash` 任务 | +| `model` | string | 可缺省:仅 `subagent` 任务且有值 | +| `thinking_effort` | string | 可缺省:同上 | +| `agent_id` | string | 可缺省:同上 | +| `subagent_type` | string | 可缺省:同上 | +| `parent_tool_call_id` | string | 可缺省:`subagent` / `bash` 任务且有值 | +| `output_preview` | string | 可缺省:仅 `with_output` 读取且输出非空 | +| `output_bytes` | integer | 可缺省:同上 | +| `run_in_background` | boolean | `detached ?? true` | -按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。 +REST 的 T-Task 不含 `subagent_phase` / `suspended_reason` / `swarm_index`——那些字段只在快照的 subagent 条目上(见 [T-SnapshotSubagent](#t-snapshotsubagent))。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `path` | body | string | **必填。** 绝对目录路径 | +### T-Terminal -成功时 `data` 为 `{ path }`。 +`{ id, session_id, cwd, shell, cols, rows, status, created_at, exited_at?, exit_code? }`——`status` 为 `running` / `exited`;`exited_at` 与 `exit_code`(integer 或 `null`,例如因信号终止时)可缺省。 -- `40001`:`path` 不是绝对路径 -- `40409`:父路径不存在 -- `40411`:权限不足 -- `40919`:路径已存在 +### T-Workspace -### 文件上传 +`{ id, root, name, created_at, last_opened_at, session_count }`——全字段必有;`created_at` / `last_opened_at` 为 ISO 8601,`session_count` 为 integer。注册与重命名会广播全局事件 `event.workspace.created` / `event.workspace.updated`。 -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/files` | multipart 上传(字段 `file`,可选 `name`、`expires_in_sec`),返回文件元信息 | -| `GET /api/v1/files/{file_id}` | 下载(二进制,错误用真实 HTTP 状态码) | -| `DELETE /api/v1/files/{file_id}` | 删除 | +### T-SkillDescriptor -#### `POST /api/v1/files` +`{ name, description, path, source, type?, disable_model_invocation? }`——`source` 为 `project` / `user` / `extra` / `builtin`;`type` 标识技能类别(只有用户可激活的类型才能被激活);`disable_model_invocation` 会让技能对模型不可见。 -以 `multipart/form-data` 上传文件,供后续引用(例如作为提示词附件)。 +### T-CapabilityStatus -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `file` | body | binary | **必填。** multipart 的文件部分 | -| `name` | body | string | 存储的显示名。默认上传文件名 | -| `expires_in_sec` | body | number | 文件过期前的秒数(非负)。默认永不过期 | +能力状态(camelCase 载荷):`{ id, pluginId?, displayName, description, supported, state, version?, steps, install }`。 -成功时 `data` 为文件元信息 `{ id, name, media_type, size, created_at, expires_at? }`,其中 `media_type` 取自上传的内容类型。 +- `state`:`ready`(所有必需检测步骤均为 `ok`)/ `partial` / `not_installed` / `unsupported`。 +- `steps`:`{ id, state, detail?, optional? }[]`,其 `state` 为 `ok` / `missing` / `failed`。 +- `install`:`{ running, step?, percent?, error?, note? }`,`percent` 取值 0–100。 -- `40001`:multipart 请求体缺少 `file` 字段 +### T-PluginSummary -#### `GET /api/v1/files/{file_id}` +插件摘要(camelCase 载荷):`{ id, displayName, version?, enabled, state, skillCount, mcpServerCount, enabledMcpServerCount, hookCount, commandCount, hasErrors, source, originalSource?, github? }`。 -下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 +- `state`:`ok` / `error`(加载失败也会置 `hasErrors`)。 +- `source`:`local-path` / `zip-url` / `github`。 +- `github`:`{ owner, repo, ref, installedSha? }`,`ref` 为 `{ kind: "branch" \| "tag" \| "sha", value }`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `file_id` | path | string | **必填。** 上传响应返回的文件 id | +### T-ToolDescriptor -- `40407`(HTTP 404):没有该 id 的文件(包括已过期的文件) +`{ name, description, input_schema, source, active, mcp_server_id? }`——`input_schema` 恒 `null`;`source` 为 `builtin` / `skill` / `mcp`;`mcp_server_id` 仅 MCP 工具携带(从 `mcp____` 名称解析);`active` 报告工具策略的判定结果。 -#### `DELETE /api/v1/files/{file_id}` +### T-McpServer -删除已上传的文件。 +`{ id, name, transport, status, tool_count, last_error? }`——`id` 与 `name` 均为 server 名称;`transport` 为 `stdio` / `http` / `sse`;`status` 为 `connected` / `connecting` / `disconnected` / `error`(核心六态压为四态:pending→`connecting`、disabled/removed→`disconnected`、failed/needs-auth→`error`)。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `file_id` | path | string | **必填。** 上传响应返回的文件 id | +### T-Connection -成功时 `data` 为 `{ deleted: true }`。 +`{ id, connected_at, remote_address, user_agent, has_client_hello, subscriptions }`——`id` 为 `conn_`;`remote_address` 与 `user_agent` 可空(`null`);`subscriptions` 为排序的会话 id 数组。 -- `40407`(HTTP 404):没有该 id 的文件 +### T-FsEntry -### GUI 存储 +文件条目:`{ path, name, kind, size?, modified_at, etag?, mime?, language_id?, is_binary?, is_symlink_to?, git_status?, child_count? }`。 -由服务端支撑的键值存储,接口对齐浏览器的 `localStorage`,持久化在服务的 home 目录下;web UI 用它保存跨客户端的 UI 状态。值是不透明字符串——序列化由调用方负责。 +- `kind`:`file` / `directory` / `symlink`。 +- `git_status`:`clean` / `modified` / `added` / `deleted` / `renamed` / `untracked` / `ignored` / `conflicted`(仅 `include_git_status: true` 时存在)。 +- `size` 为 integer;`modified_at` 为 ISO 8601。 -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/gui/store/length` | 已存键的数量 | -| `GET /api/v1/gui/store/getItem` | 按键读取值 | -| `POST /api/v1/gui/store/setItem` | 按键写入值 | -| `POST /api/v1/gui/store/removeItem` | 按键删除值 | -| `POST /api/v1/gui/store/clear` | 删除所有值 | +### T-FsListResponse -#### `GET /api/v1/gui/store/length` +`{ items: T-FsEntry[], children_by_path?, truncated }`——`depth` 大于 1 时另附 `children_by_path`(路径 → 条目数组的映射);`truncated` 表示 `limit` 截断了列表。 -返回已存键的数量(对齐 `localStorage.length`)。无参数。 +### T-FsReadResponse -成功时 `data` 为 `{ length }`。 +`{ path, content, encoding, size, truncated, etag, mime, language_id?, line_count?, is_binary }`——`encoding` 报告实际使用的编码(`utf-8` 或 `base64`);`size` 为文件完整大小。 -#### `GET /api/v1/gui/store/getItem` +### T-FsListManyResponse -读取一个值(对齐 `localStorage.getItem`)。 +`{ results, truncated_paths?, partial_errors? }`——`results` 为每个请求路径到其条目数组的映射;`truncated_paths` 为达到 `limit` 的路径;`partial_errors` 为失败路径到其 `{ code, msg }` 错误的映射。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `key` | query | string | **必填。** 要读取的键,1–256 个字符 | +### T-FsStatManyResponse -成功时 `data` 为 `{ value }`——已存字符串,键不存在时为 `null`。 +`{ entries }`——每个请求路径到其 [T-FsEntry](#t-fsentry)(不存在时为 `null`)的映射。 -#### `POST /api/v1/gui/store/setItem` +### T-FsSearchHit -写入一个值(对齐 `localStorage.setItem`)。 +`{ path, name, kind, score, match_positions }`——`score` 为 0–1 的模糊匹配得分;`match_positions` 为匹配到的字符偏移数组。响应形态为 `{ items: T-FsSearchHit[], truncated: boolean }`。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `key` | body | string | **必填。** 要写入的键,1–256 个字符 | -| `value` | body | string | **必填。** 要存储的值 | +### T-FsSuggestItem -成功时 `data` 为 `null`。 +结构同 [T-FsSearchHit](#t-fssearchhit);响应形态相同。 -#### `POST /api/v1/gui/store/removeItem` +### T-FsGrepResponse -删除一个值(对齐 `localStorage.removeItem`)。 +`{ files, files_scanned, truncated, elapsed_ms }`——`files` 的每项为 `{ path, matches }`,每个匹配为 `{ line, col, text, before, after }`(`before` / `after` 最多携带 `context_lines` 行上下文);`truncated` 表示某个匹配配额截断了结果。 -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `key` | body | string | **必填。** 要删除的键,1–256 个字符 | +### T-FsGitStatusResponse -成功时 `data` 为 `null`。 +`{ branch, ahead, behind, entries, additions, deletions, pullRequest }`——`entries` 把每个变更路径映射到其 `git_status`;`pullRequest`(camelCase)为 `{ number, state, url }`(`state` 为 `open` / `merged` / `closed` / `draft`)或 `null`。 -#### `POST /api/v1/gui/store/clear` +### T-FsDiffResponse -删除所有已存值(对齐 `localStorage.clear`)。无参数。 +`{ path, diff, truncated }`——`diff` 为 unified diff 文本;`truncated` 表示过长的 diff 被截断。 -成功时 `data` 为 `null`。 +### T-FsBrowseResponse -### 全局搜索与其他 +`{ path, parent, entries }`——`path` 为解析后的目录;`parent` 为其父目录(文件系统根处为 `null`);`entries` 每条目为 `{ name, path, is_dir: true }`。 -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/search` | 跨会话全文搜索,`mode` 为 `terms`(默认)或 `literal`(精确子串),`page_token` 分页 | -| `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | -| `GET /api/v2/sessions` | 新一代会话列表,见下文 | -| `POST /api/v2/sessions:archive` | 批量归档会话,见下文 | -| `POST /api/v2/sessions:restore` | 批量恢复已归档会话,见下文 | -| `/api/v2/mcp/*` | 统一的 MCP 管理面,见下文 | -| `/api/v1/debug/*` | 反射式调试 RPC,仅 `--debug-endpoints` 且 loopback 时挂载,不属于稳定协议 | +### T-FsHomeResponse -#### `POST /api/v1/search` +`{ home, recent_roots }`——`home` 为用户主目录;`recent_roots` 列出已注册工作区的根目录(上限 8)。 -跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。当 `container.session_id` 指向本服务进程中存活的会话时,搜索改为直接扫描该会话的内存转录,响应的 `source` 字段(`index` 或 `live`)会报告本页结果由哪条路径提供。 +### T-FileMeta -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `query` | body | string | **必填。** 搜索文本 | -| `mode` | body | string | `terms`(默认)/ `literal` | -| `op` | body | string | `terms` 模式下的词项组合符:`AND`(默认)/ `OR` | -| `container` | body | object | 将搜索限定在 `{ session_id?, agent_id? }` | -| `role` | body | string | 限定 `user` / `assistant` / `title` 命中 | -| `start_time` | body | integer | 只看不早于该时间的命中(epoch 毫秒) | -| `end_time` | body | integer | 只看不晚于该时间的命中(epoch 毫秒) | -| `sort` | body | string | `score`(默认)/ `time_desc` / `time_asc`;`literal` 模式忽略此参数,始终最新在前 | -| `page_size` | body | integer | 每页命中数,1–50。默认 `20` | -| `page_token` | body | string | 上一页响应返回的令牌 | +`{ id, name, media_type, size, created_at, expires_at? }`——`id` 为 `f_...`;`media_type` 取自上传的内容类型;`expires_at` 可缺省。 -`terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引;`literal` 模式是零误报的精确子串搜索。成功时 `data` 为 `{ items, has_more, page_token?, index_state, source }`,每项为 `{ session_id, workspace_id, session_title, agent_id, role, snippet, time, turn?, step_id?, score }`。`index_state` 为 `{ state, indexed_sessions, total_sessions, documents, stale?, degraded? }`,其中 `state` 为 `building` / `ready` / `readonly` 之一;`stale` 标记仍在追赶的落后视图,`degraded` 携带最近一次刷新失败的信息。超出预算的页会额外携带 `incomplete`,取值为 `candidate_cap` / `postings_budget` / `deadline` 之一。分页令牌锁定索引代际与查询条件——索引重建或查询变更会使其失效。 +### T-ConfigResponse -- `40001`:请求体校验失败、查询不可用(为空或超过 32 个词项),或分页令牌非法 +配置全域对象(camelCase 域名转 snake_case)加合成键;未列出的域原样透传: -#### `GET /api/v1/connections` +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `providers` | object | 供应商 id → `{ type, base_url?, default_model?, has_api_key }` 的映射(必有,空为 `{}`;密钥被剥离为 `has_api_key`) | +| `models` | object | 模型别名 → 模型记录的映射(剥离 `apiKey` / `oauth`,加 `has_api_key`,其余键原样) | +| `services` | object | 内置外部服务配置(同 `models`,另把 `customHeaders` 换成 `custom_header_keys: string[]`) | +| `yolo` | boolean | 可缺省:由 `default_permission_mode === "yolo"` 合成 | +| `default_provider` | string | 全局默认供应商 id | +| `default_model` | string | 全局默认模型别名 | +| 其余域 | — | `thinking` / `plan_mode` / `default_permission_mode` / `default_plan_mode` / `permission` / `hooks` / `merge_all_available_skills` / `extra_skill_dirs` / `loop_control` / `background` / `subagent` / `secondary_model` / `experimental` / `telemetry` / `raw` 等,原样透传,可缺省 | -列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。无参数。 +### T-AuthSummary -成功时 `data` 为 `{ connections }`,每项为 `{ id, connected_at, remote_address, user_agent, has_client_hello, subscriptions }`:`connected_at` 为 ISO 8601 时间戳;`remote_address` 与 `user_agent` 未知时为 `null`;`has_client_hello` 报告客户端是否已发送握手帧;`subscriptions` 列出该连接订阅的会话 id。 +`{ models_ready, providers_count, managed_provider }`——`managed_provider` 为 `{ name, status }`(`status` 为 `authenticated` / `expired` / `revoked` / `unauthenticated`)或 `null`。全局默认模型别名改从 `GET /api/v1/config` 的 `default_model` 读取,本对象不携带。 -### `GET /api/v2/sessions` +### T-OAuthFlowStart -面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里: +OAuth 流程发起结果,按 `status` 区分: -| 参数 | 说明 | -| --- | --- | -| `workspace.id` | 按工作区过滤,可重复 | -| `activity.status` | 按活动状态过滤:`running` / `approval` / `question` / `failed` / `idle`,可重复 | -| `meta.updated_after` | 只看该时间(epoch 毫秒)之后更新过的会话 | -| `meta.updated_before` | 只看该时间(epoch 毫秒)之前更新过的会话 | -| `meta.archived` | `true` / `false`(默认)/ `all` | -| `meta.has_prompt` | `true` 只保留有用户 prompt 的会话,`false` 只保留空会话(等价 `GET /api/v1/sessions` 的 `exclude_empty`) | -| `view` | `flat`(默认)/ `by_workspace`,见下文 | -| `group.page_size` | `view=by_workspace` 时每个工作区返回的会话数:1–100,默认 5(使用 `id,archived` 投影时上限 10000);未开分组视图时传入返回 `40001` | -| `sort` | `meta.updated_at_desc`(默认)/ `meta.updated_at_asc` / `meta.created_at_desc` | -| `include` | 逗号分隔的附加字段组;目前支持 `git`(分支与 PR 信息,按目录去重并缓存 60 秒) | -| `fields` | 逗号分隔的字段投影;目前仅支持 `id,archived`,每项裁剪为 `{ id, archived }`(用于全选匹配场景)。不可与 `include=git` 同传(`40001`) | -| `page_size` | 1–100,默认 50;使用 `id,archived` 投影时上限放宽至 10000。`view=by_workspace` 时按组计数 | -| `page_token` | 上一页返回的翻页令牌 | -| `page` | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | - -响应每项固定包含 `workspace`、`meta`、`activity` 三组,`include=git` 时附加 `git` 组;`fields=id,archived` 时仅返回 `{ id, archived }`。`activity` 组还会带上 `model`:会话仍加载在当前进程时为其绑定的模型别名,冷会话(未加载)为 `null`。每页额外携带 `total`,即过滤后的集合大小。翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`。`page` 模式是跳页用的无状态替代:每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。 - -`view=by_workspace` 时,同一份过滤、排序后的集合会重新投影为按工作区分组的形态,概览页因此可以用一次请求替代「每个工作区各一轮询」: +- `pending`:`{ flow_id, provider, status: "pending", verification_uri, verification_uri_complete, user_code, expires_in, interval, expires_at }`——`expires_in`(秒)与 `expires_at`(ISO 8601)是同一时限的两种表示。 +- `authenticated`:`{ flow_id, provider, status: "authenticated" }`。 -```json -{ - "code": 0, - "msg": "success", - "data": { - "groups": [ - { - "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, - "sessions": [ { "id": "session_...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ], - "total": 42 - } - ], - "total": 7, - "has_more": true, - "next_page_token": "eyJ2IjoxLCJmIjoi..." - }, - "request_id": "req_..." -} -``` +### T-OAuthFlowSnapshot -每组携带该工作区按请求 `sort` 排序的前 `group.page_size` 条会话,以及该工作区匹配过滤条件的会话总数 `total`(用作「查看全部」入口)。只有至少有一条匹配会话的工作区才会出现;组间按组内首条会话的 sort key 排序,相同则按工作区 id。`page` 与 `page_token` 按组翻页(外层 `total` 为组数),指纹绑定规则相同:令牌同时覆盖 `view` 与分组参数,翻页途中变更同样返回 `40922`。 +`{ flow_id, provider, status, verification_uri, verification_uri_complete, user_code, expires_in, expires_at, interval, resolved_at?, error_message? }`——`status` 为 `pending` / `authenticated` / `denied` / `expired` / `cancelled`;离开 `pending` 后 `resolved_at` 记录到达终态的时间,`error_message` 描述失败的流程。 -### `POST /api/v2/sessions:archive` 与 `POST /api/v2/sessions:restore` +### T-ManagedUsageResult -面向会话管理页的批量归档/恢复。请求体为 `{ "ids": ["session_..."] }`——非空、去重后不超过 5000 条。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。 +托管用量结果,按 `kind` 区分: -只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回:`data.results` 保持输入顺序,每项为 `{ id, ok }` 或 `{ id, ok: false, error }`(不存在的 id 在自身条目里报 `40401`),并附 `succeeded` / `failed` 计数。 +- `ok`:`{ kind: "ok", summary, limits, extra_usage }`——`summary`(可空)是主配额行,`limits` 列出每个配额窗口;一行(T-UsageRow)为 `{ name?, window?, used, limit, reset_at? }`,其中 `window` 为 `{ duration, unit }`(`unit` 为 `minute` / `hour` / `day` / `week`)。`extra_usage`(可空)是按量付费钱包:`{ balance_cents, total_cents, monthly_charge_limit_enabled, monthly_charge_limit_cents, monthly_used_cents, currency }`(金额均 integer 分)。 +- `error`:`{ kind: "error", message, status? }`——`status` 为上游 HTTP 状态码(如存在)。 -```json -{ - "code": 0, - "msg": "success", - "data": { - "results": [ - { "id": "session_a", "ok": true }, - { "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } } - ], - "succeeded": 1, - "failed": 1 - }, - "request_id": "req_..." -} -``` +### T-ManagedUserInfoResult -### MCP 管理(`/api/v2/mcp`) +托管账号资料(camelCase 载荷),按 `kind` 区分: -`/api/v2/mcp/*` 路由是服务的统一 MCP 管理面:独立于任何会话,直接管理 MCP server 注册表本身——全局(用户级)CRUD 与逐条校验、连接测试探测、locator 寻址的检查目录、按 server 的授权状态列表,以及完整的 OAuth 流程生命周期。 +- `ok`:`{ kind: "ok", userInfo }`——`userInfo` 始终携带 `userId`、`nickname`、`status`、`region`、`userLevel`、`userLevelName`、`domain`、`domainName`,并可能附加 `globalId`、`bio`、`avatar`、`username`、`email`、`phone`(`{ countryCode, number }`)、`createdTime`、`lastLoginTime`。 +- `error`:`{ kind: "error", message, status? }`。 -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v2/mcp/servers` | 列出所有已知 MCP server | -| `GET /api/v2/mcp/servers/{name}` | 按运行时名称获取单个 server | -| `POST /api/v2/mcp/servers` | 向用户级 `mcp.json` 添加 server | -| `PUT /api/v2/mcp/servers/{name}` | 替换一个用户级条目 | -| `DELETE /api/v2/mcp/servers/{name}` | 删除一个用户级条目 | -| `POST /api/v2/mcp/servers:test` | 对单个 server 发起真实连接探测 | -| `POST /api/v2/mcp/servers:inspect` | locator 寻址的目录及批量连接探测 | -| `GET /api/v2/mcp/auth-statuses` | 目录中各 server 的 OAuth 状态 | -| `POST /api/v2/mcp/auth:begin` | 开始一次交互式 OAuth 流程 | -| `POST /api/v2/mcp/auth:complete` | 等待浏览器回调并完成 code 交换 | -| `POST /api/v2/mcp/auth:cancel` | 终止已开始的 OAuth 流程 | -| `POST /api/v2/mcp/auth:reset` | 清除某个 server 已存储的凭据 | +### T-ModelCatalogItem -该管理面有两种寻址方式。CRUD 路由与 `servers:test` 使用普通的运行时 `name`;检查与 OAuth 路由使用 **locator**——文件层条目用 `{ "source": "global", "name" }`,插件清单条目用 `{ "source": "plugin", "pluginId", "serverName" }`——因为插件条目和文件条目可能共用同一个运行时名称。检查条目还带有一个稳定的 `serverId` 线上标识:`global:` 或 `plugin::`(URL 编码)。 +`{ provider, model, display_name?, max_context_size, capabilities?, support_efforts?, default_effort? }`——`model` 是别名 id,`provider` 是所属供应商 id;`max_context_size` 是以 token 计的上下文窗口。 -大多数路由接受可选的 `cwd`(查询参数,`:`-action 路由则为请求体字段)。不传时目录只覆盖用户级文件与插件清单;传入后,该目录的项目根层与项目本地层会并入——但仅当工作区受信任时,否则项目层会被跳过。对 stdio server 执行 `servers:test` 时,`cwd` 同时是子进程的工作目录。连接探测与 OAuth 调用会等待服务配置加载完成后再执行。 +### T-ProviderCatalogItem -#### `GET /api/v2/mcp/servers` 与 `GET /api/v2/mcp/servers/{name}` +`{ id, type, base_url?, default_model?, has_api_key, status, models? }`——`type` 为通信协议(`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai`);`status` 为 `connected` / `error` / `unconfigured`;`models` 为该供应商的模型别名 id 数组。 -列出管理面已知的全部 MCP server;第二个路由返回该运行时名称对应的单个条目。 +### T-CatalogProviderItem -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `name` | path | string | **必填(仅 get)。** server 的运行时名称 | -| `cwd` | query | string | 并入该(受信任)目录的项目层 | +models.dev 目录条目:`{ id, name, wire_type, guessed, needs_base_url, rejected, reject_reason, env_key, models }`——`wire_type` 为解析出的协议(可空,枚举与供应商 `type` 相同);`guessed` 标记启发式解析;`env_key` 是上游约定的 API 密钥环境变量(可空);`reject_reason` 可空;`models` 为 `{ id, name?, max_context_size, capabilities?, reasoning }[]`。 -成功时 `data` 是受管 server 数组(get 路由为单个对象),每项为 `{ name, config, source, origin, mutable, plugin? }`: +### T-RefreshProviderModelsResponse -- `source`:`global`(配置文件层)或 `plugin`(插件清单) -- `origin`:条目的定义位置——文件路径或插件 id -- `mutable`:只有用户级条目可变;插件与项目层条目均为只读 -- `config`:可变条目携带完整配置,便于编辑界面预填;只读条目被脱敏为排序后的键名列表(`envKeys` / `headerKeys`),绝不泄露密钥值 -- `plugin`:`{ id, name }`,仅插件条目携带 +`{ changed, unchanged, failed }`——`changed` 为 `{ provider_id, provider_name, added, removed }[]`(新增 / 移除的别名数);`unchanged` 为无差异的供应商 id 数组;`failed` 为 `{ provider, reason }[]`。 -- `40001`:校验失败 -- `40408`:不存在该名称的 server +### T-SearchResponse -#### `POST` / `PUT` / `DELETE /api/v2/mcp/servers` +`{ items, has_more, page_token?, incomplete?, index_state, source }`。 -针对用户级 `mcp.json` 的全局 CRUD。新增请求体是包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状,每条配置写入前都会校验。更新请求体携带同样的配置但不含 `name`(由路径指定条目);删除无请求体。三者都在 `data` 中返回刷新后的 server 列表。若写入与项目层的同名条目冲突,会因只读被拒绝——请改为编辑定义它的文件;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。 +- 每项:`{ session_id, workspace_id, session_title, agent_id, role, snippet, time, turn?, step_id?, score }`——`role` 为 `user` / `assistant` / `title`;`time` 为 epoch 毫秒。 +- `incomplete`:超出预算的页携带,取值 `candidate_cap` / `postings_budget` / `deadline`。 +- `index_state`:`{ state, indexed_sessions, total_sessions, documents, stale?, degraded? }`——`state` 为 `building` / `ready` / `readonly`;`stale` 标记仍在追赶的落后视图,`degraded` 携带最近一次刷新失败的信息。 +- `source`:`live` / `index`——本页结果由内存转录还是持久索引提供。 -- `40001`:校验失败,或目标条目为只读 -- `40408`:(更新/删除)不存在该名称的 server +### T-SnapshotResponse -#### `POST /api/v2/mcp/servers:test` +会话快照。 -对单个 server 发起真实连接探测,不持久化任何内容。传 `name` 探测注册表条目(含插件与受信任的项目层),或传 `server`(包含 `name` 的完整内联配置)按原样探测;两者都传或都不传会报 `40001`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `as_of_seq` | integer | 事件日志水位 | +| `epoch` | string | 事件 epoch(冷会话可为 `""`) | +| `session` | object | [T-Session](#t-session)——`agent_config.model` 取实时绑定,`usage` 为 [T-SnapshotUsage](#t-snapshotusage) | +| `messages` | object | `{ items: T-Message[], has_more }`——尾部最多 100 条 | +| `in_flight_turn` | object \| null | [T-InFlightTurn](#t-inflightturn);无进行中轮次时为 `null` | +| `subagents` | array | [T-SnapshotSubagent](#t-snapshotsubagent) 数组(无存活时 `[]`) | +| `pending_approvals` | array | [T-ApprovalRequest](#t-approvalrequest) 数组 | +| `pending_questions` | array | [T-QuestionRequest](#t-questionrequest) 数组 | -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `name` | body | string | 注册表条目的运行时名称 | -| `server` | body | object | 按原样探测的内联 server 配置 | -| `cwd` | body | string | 项目层并入解析;同时是 stdio 的工作目录 | +### T-SnapshotUsage -成功时 `data` 为 `{ success, output }`:连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 +`{ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, context_tokens, context_limit }`——与 [T-SessionUsage](#t-sessionusage) 不同:**无** `total_cost_usd` / `turn_count`,且 `context_limit` 可缺省。 -- `40001`:两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用 -- `40408`:不存在该名称的 server +### T-InFlightTurn -#### `POST /api/v2/mcp/servers:inspect` +`{ turn_id, assistant_text, thinking_text, running_tools, current_prompt_id? }`——`running_tools` 为 `{ tool_call_id, name, args?, description?, display?, last_progress? }[]`,`last_progress` 为 `{ kind: "stdout" \| "stderr" \| "progress" \| "status" \| "custom", text?, percent? }`。 -locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。 +### T-SnapshotSubagent -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `targets` | body | array | 缩小目录范围的 locator 数组;不传则检查全部 server | -| `cwd` | body | string | 并入该(受信任)目录的项目层 | +快照中的 subagent 条目:`{ id, session_id, kind: "subagent", description, status, subagent_phase?, subagent_type?, parent_tool_call_id?, swarm_index?, run_in_background, model?, thinking_effort?, created_at, started_at?, completed_at?, output_preview?, suspended_reason? }`——`status` 取值同 [T-Task](#t-task);`subagent_phase` 为 `queued` / `working` / `suspended` / `completed` / `failed`。 -成功时 `data` 是检查结果数组,每项为 `{ serverId, locator, runtimeName, canonicalUrl?, origin, config, enabled, editable, authStatus, checkedAt?, error? }`:`canonicalUrl` 是远程 server 的凭据 URL,`config` 为脱敏视图,`authStatus` 取值为 `not-applicable` / `bearer-token` / `oauth-required` / `oauth-authorized` / `oauth-expired` / `unavailable` 之一。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 `unavailable` 并在 `error` 中给出说明。探测遇到过期授权时,可能刷新或作废已存储的凭据。 +### T-Transcript 族 -- `40001`:校验失败 -- `40408`:`targets` 中有 locator 未匹配到任何条目 +转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约(客户端经同一依赖消费): -#### `GET /api/v2/mcp/auth-statuses` +- **T-TranscriptResponse**:`{ agent_id, items, has_more, tasks, interactions, attachments, todos, prompts, meta, agents, pending_interactions, seq? }`——`items` 为 TranscriptItem(turn / marker / taskref 三态;turn 含 `steps[].frames[]`,frame 分 text / thinking / tool / notice 四种)。 +- **T-TranscriptOpsCatchupResponse**:`{ agent_id, batches, latest_seq, complete }`——`batches` 为 `{ seq, ops }[]`;TranscriptOperation 全集(判别字段为 `op`):reset / turn.upsert / step.upsert / frame.upsert / append / marker.upsert / taskref.upsert / task.upsert / interaction.upsert / attachment.upsert / todo.upsert / prompt.upsert / meta.merge / items.remove。 +- **T-TranscriptUserMessagesResponse**:`{ agents }`——每条目为 `{ agent_id, messages, attachments }`;`messages` 为 `{ turn_id, ordinal, state, origin, prompt, attachment_ids?, started_at? }[]`,`state` 为轮次状态(`queued` / `running` / `completed` / `failed` / `cancelled`)。 +- **T-TranscriptPlanResponse**:`{ agent_id, plans }`——每个计划为 `{ tool_call_id, turn_id, source, plan, path?, options?, review? }`;`source` 为 `interaction` / `display` / `output`;`review`(仅交互式审阅时存在)为 `{ state, selected_option?, feedback? }`,`state` 为 `pending` / `approved` / `rejected` / `cancelled`。 -注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 `servers:inspect` 更轻量的选择。 +### T-V2Session -| 参数 | 位置 | 类型 | 说明 | -| --- | --- | --- | --- | -| `cwd` | query | string | 并入该(受信任)目录的项目层 | -| `verify` | query | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | +v2 会话对象:`{ id, workspace, meta, activity, git? }`。 -成功时 `data` 是 `{ name, authStatus }` 数组,`authStatus` 取值与 `servers:inspect` 相同。验证探测可能刷新或作废已存储的凭据。 +- `workspace`:`{ id, cwd }`——`cwd` 可空。 +- `meta`:`{ title, last_prompt, created_at, updated_at, archived, archived_at }`——`title` / `last_prompt` 可空;`created_at` / `updated_at` 为 epoch 毫秒;`archived_at` 恒产出(integer 或 `null`)。 +- `activity`:`{ status, model }`——`status` 为 `running` / `approval` / `question` / `failed` / `idle`(冷会话恒 `idle`);`model` 为存活会话的绑定模型别名,冷会话为 `null`。 +- `git`:仅 `include=git` 时产出——`{ branch, pull_request }`,不可用时为 `{ branch: null, pull_request: null }`;`pull_request` 为 `{ number, state, url }`(`state` 为 `open` / `closed` / `merged`)或 `null`。 -#### `POST /api/v2/mcp/auth:begin` / `:complete` / `:cancel` / `:reset` +### T-V2SessionPage -远程 server 的 OAuth 流程生命周期。`auth:begin` 接受 locator 请求体(外加可选的 `cwd` 查询参数),返回 `data` 为 `{ status: "authorization-required", flowId, authorizationUrl }`——在浏览器中打开该 URL 完成授权——或当授权已存在时返回 `{ status: "already-authorized" }`。目标 server 必须使用远程传输(`http` / `sse`)且不含静态 bearer token;静态请求头仅当配置显式设置 `auth: "oauth"` 时允许。 +`{ items, total, has_more, next_page_token }`——`items` 为 [T-V2Session](#t-v2session) 数组(`fields=id,archived` 投影时裁剪为 `{ id, archived }`);`next_page_token` 可空。 -`auth:complete` 等待已开始流程的浏览器回调并完成 code 交换。请求体为 `{ flowId, timeoutMs? }`:等待默认 15 分钟(`timeoutMs` 可覆盖),空闲流程无论如何都会在 15 分钟后过期,关闭 HTTP 连接会中止等待。成功时 `data` 为 `null`。 +### T-V2SessionGroupPage -`auth:cancel` 在未完成的情况下终止已开始的流程(`{ flowId }`);未知流程会被忽略。`auth:reset` 接受 locator 请求体,清除该 server 已存储的凭据——失效事件会送达存活的会话。 +`{ groups, total, has_more, next_page_token }`——`groups` 为 `{ workspace, sessions, total }[]`(`workspace` 形态同 T-V2Session 的 `workspace` 组,`total` 为该工作区匹配过滤条件的会话总数);外层 `total` 为组数。 -- `40001`:校验失败——包括 `:complete` 的 `flowId` 未知,或 `:begin` 的 server 无法使用 OAuth(stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头) -- `40408`:(`:begin` / `:reset`)locator 未匹配到任何条目 -- `40929`:OAuth 流程本身失败 +### T-V2BatchSessionResponse -## WebSocket 协议 +`{ results, succeeded, failed }`——`results` 为 `{ id, ok, error? }[]`(保持输入顺序;`error` 为 `{ code, message }`);`succeeded` / `failed` 为计数。 -### 建立连接 +### T-McpManagedServer -唯一端点是 `ws://:/api/v1/ws`;鉴权在升级请求时完成(见上文 [鉴权](#鉴权))。连接建立后服务端立即发送 `server_hello`: +受管 MCP server(camelCase 载荷):`{ name, config, source, origin, mutable, plugin? }`。 -```json -{ - "type": "server_hello", - "timestamp": "2026-01-01T00:00:00.000Z", - "payload": { - "ws_connection_id": "conn_01JZX4...", - "protocol_version": 2, - "max_event_buffer_size": 1000, - "capabilities": { "event_batching": false, "compression": false } - } -} -``` +- `source`:`global`(配置文件层)/ `plugin`(插件清单)/ `caller`。 +- `origin`:条目的定义位置——文件路径或插件 id。 +- `mutable`:只有用户级条目可变;插件与项目层条目均为只读。 +- `config`:[T-McpServerConfigView](#t-mcpserverconfigview)——可变条目携带完整配置;只读条目被脱敏为排序后的键名列表。 +- `plugin`:`{ id, name }`,仅插件条目携带。 -注意服务端不发送心跳,也不会主动断开空闲连接——保活与重连由客户端自己负责。 +### T-McpServerConfigView -### 控制帧 +MCP server 配置的脱敏视图,按 `transport` 区分: -客户端发送 JSON 帧 `{ "type", "id"?, "payload" }`;每个请求帧都会收到应答 `{ "type": "ack", "id", "code", "msg", "payload" }`,`code` 为 `0` 表示成功。 +- `stdio`:`{ transport: "stdio", command, args?, cwd?, executor?, runtime_id?, envKeys?, enabled?, startupTimeoutMs?, toolTimeoutMs?, enabledTools?, disabledTools? }`——`envKeys`(排序的键名)替代 `env`,绝不泄露密钥值。 +- `http` / `sse`:`{ transport: "http" \| "sse", url, auth?, bearerTokenEnvVar?, headerKeys? }` 加上述公共字段——`auth` 仅取值 `"oauth"`;`headerKeys` 替代 `headers`。 -| 帧 | payload | 说明 | -| --- | --- | --- | -| `subscribe` | `{ session_ids, cursors?, agent_filter? }` | 订阅会话事件;带 `cursors`(每会话 `{seq, epoch}`)时回放错过的持久事件 | -| `unsubscribe` | `{ session_ids }` | 取消会话订阅 | -| `subscribe_v2` | `{ session_id, transcript, transcript_since? }` | 订阅转录流(唯一的转录订阅通道),`transcript` 按 agent 指定粒度 | -| `unsubscribe_v2` | `{ session_id, agent_ids? }` | 退订转录流;省略 `agent_ids` 表示整个会话 | -| `watch_fs_add` / `watch_fs_remove` | `{ session_id, paths, recursive? }` | 订阅 / 取消文件变更通知(`event.fs.changed`) | -| `client_hello` | `{ client_id }` | 握手帧,其余字段为遗留兼容 | +### T-McpServerInspection -### 事件 +`{ serverId, locator, runtimeName, canonicalUrl?, origin, config, enabled, editable, authStatus, checkedAt?, error? }`——`serverId` 为 `global:` 或 `plugin::`(URL 编码);`locator` 为 `{ source: "global", name }` 或 `{ source: "plugin", pluginId, serverName }`;`config` 为 [T-McpServerConfigView](#t-mcpserverconfigview);`checkedAt` 为 epoch 毫秒。 -事件帧形状为 `{ "type", "seq", "epoch"?, "volatile"?, "offset"?, "session_id"?, "timestamp", "payload" }`,`type` 即事件类型。按投递范围分两类: +### T-McpServerAuthStatus -- **全局事件**:发送到每个已建立连接,无需订阅——`session.meta.updated`、`event.session.created`、`event.session.archived`、`event.session.work_changed`、`event.session.status_changed`、`event.workspace.*`、`event.config.*`、`event.model_catalog.*`。 -- **会话事件**:只发给订阅了该会话的连接,受 `agent_filter` 过滤。主要事件族: +`{ name, authStatus }`——`authStatus` 为 `not-applicable` / `bearer-token` / `oauth-required` / `oauth-authorized` / `oauth-expired` / `unavailable`。 -| 事件族 | 主要事件 | -| --- | --- | -| 轮次 | `turn.started`、`turn.ended`、`turn.step.started` / `completed` / `interrupted` / `retrying` | -| 流式文本 | `assistant.delta`、`thinking.delta`(带 `offset` 用于对齐) | -| 工具调用 | `tool.call.started`、`tool.call.delta`、`tool.progress`、`tool.result` | -| 交互 | `event.approval.requested` / `resolved`、`event.question.requested` / `answered` / `dismissed` | -| subagent | `subagent.spawned` / `started` / `suspended` / `completed` / `failed` | -| 后台 | `task.started` / `terminated`、`shell.started` / `output` / `completed` | -| 其他 | `compaction.*`、`skill.activated`、`goal.updated`、`prompt.*`、`error`、`warning` | +### T-TokenUsage -有三个全局生命周期事件可以让跨工作区概览免掉逐工作区轮询。`event.session.archived` 在在线归档与冷归档两条路径上都会发出;其事件帧 `session_id` 是全局水位 `__global__`,真实会话 id 在 payload 里:`{ "type": "event.session.archived", "workspace_id": "wd_...", "sessionId": "session_..." }`(payload 字段为 `workspace_id` / `sessionId`)。`event.workspace.created` / `updated` 携带完整工作区对象(`{ id, root, name, created_at, last_opened_at, session_count }`——会话创建触碰工作区时也会发 `updated`),`event.workspace.deleted` 携带 `{ "workspace_id", "root" }`。这些事件只覆盖本服务进程内的变更;其他进程(例如写同一 home 目录的 CLI)的变更要等索引 reconcile(约一分钟)才可见,因此概览客户端应保留低频兜底轮询。目前没有会话删除事件。 +`{ inputOther, output, inputCacheRead, inputCacheCreation }`(camelCase)。 -事件另分持久与易失两种:持久事件带严格递增的 `seq`,落盘并可回放;易失事件(各 `*.delta`、`tool.progress`、`shell.*` 等)标 `volatile: true`,不回放。消费易失文本流时用 `offset`(该轮次内的累计字符偏移)与本地已累积文本比对:小于本地长度说明是重复帧,大于说明有缺漏、需走快照恢复。 +### T-AgentPhase -### 断线恢复 +agent 阶段(`agent.status.updated` 的 `phase` 字段):按 `kind` 区分的对象,`kind` 为 `idle` / `running` / `streaming` / `tool_call` / `retrying` / `awaiting_approval` / `interrupted` / `ended` 之一,各态附带相应上下文字段(如 `turnId`、`step`)。 + +### T-PromptOrigin -重连后在 `subscribe` 的 `cursors` 里带上每个会话最后应用事件的 `{seq, epoch}`,服务端会回放缺口;落后超过缓冲(1000 条)或游标失效时改为收到 `resync_required`。此时调用 `GET /api/v1/sessions/{session_id}/snapshot` 拿全量快照(含 `as_of_seq` 与 `epoch`),再以新游标重新订阅。 +提示词来源十三态:`user` / `skill_activation` / `plugin_command` / `injection` / `shell_command` / `compaction_summary` / `system_trigger` / `task` / `background_task` / `cron_job` / `cron_missed` / `hook_result` / `retry`(camelCase 嵌套对象,原样透传)。 -### 转录协议 +### T-KimiError -`subscribe_v2` 的 `transcript` 按 agent 指定粒度:`off` / `turn` / `block` / `delta`(键 `"*"` 表示默认粒度),粒度越高推送越细。粒度非 `off` 的 agent 走两帧推送:`transcript.reset`(基线快照,历史经 REST 分页回读)和 `transcript.ops`(增量批次,带每个 agent 连续递增的 `seq`);该 agent 的旧式事件在同一连接上被抑制,改由转录帧承载。断线时用 `transcript_since` 续传;服务端批次日志无法覆盖缺口时(REST 补漏返回 `complete: false`)需全量刷新。REST 侧对应 `GET .../transcript`(按轮次分页)与 `GET .../transcript/ops?since_seq=`(批次补漏)。 +核心错误对象:`{ code, message, name?, details?, retryable, cause? }`——`code` 为核心错误码字符串;`retryable` 为 boolean;`cause` 递归同构。 ## 二进制与流式端点 @@ -2408,9 +3724,9 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `GET /api/v1/fs:content` | 读取本机任意文件(仅受 token 保护,谨慎暴露端口) | 支持 | 支持 | | `POST /api/v1/sessions/{session_id}/export` | 导出会话与诊断信息(zip 流) | 不支持 | 不支持 | -错误语义也不相同:`GET /api/v1/files/{file_id}` 对查找和存储失败返回真实 404 / 500 状态码(参数校验失败仍走 HTTP 200 信封),其余三个端点的所有失败都走标准 [响应信封](#响应信封)——客户端在这三个端点上仍需检查信封中的 `code`。 +错误语义也不相同:`GET /api/v1/files/{file_id}` 与 `GET .../media/{file_id}` 对查找和存储失败返回真实 404 / 500 状态码(参数校验失败仍走 HTTP 200 信封),其余三个端点的所有失败都走标准 [响应信封](#响应信封)——客户端在这三个端点上仍需检查信封中的 `code`。 ## 下一步 -- [在网页中使用](../guides/web.md) — 启动服务并在浏览器中使用 Kimi Code +- [在网页中使用](../guides/web.md) — 启动服务并在浏览器中使用 Kimi Code;含 [用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话) 的端到端上手 - [kimi 命令](./kimi-command.md#kimi-web) — `kimi web` 的全部命令行选项 From 6eae8a57ed6319f9cacea3e200b7a5d3fbdbfcde Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:12:50 +0800 Subject: [PATCH 02/47] docs(zh): drop the API walkthrough section entirely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the "用 API 驱动一个会话" walkthrough instead of relocating it to guides/web.md (per review direction). The reference page and kimi-command.md no longer link to it. --- docs/zh/guides/web.md | 59 ------------------------------- docs/zh/reference/kimi-command.md | 2 +- docs/zh/reference/server-api.md | 4 +-- 3 files changed, 3 insertions(+), 62 deletions(-) diff --git a/docs/zh/guides/web.md b/docs/zh/guides/web.md index b33ce8a67f7..7dc4c623d34 100644 --- a/docs/zh/guides/web.md +++ b/docs/zh/guides/web.md @@ -91,65 +91,6 @@ Web 里的斜杠命令与 CLI 不完全一致,支持常用指令 `/new`、`/go 确认启动时带了 `--host`(裸写即可),并用横幅中局域网地址(形如 `http://192.168.x.x:58627/#token=...`)访问。仍不通时检查电脑防火墙是否放行了该端口,以及两台设备是否真的在同一网段(访客 WiFi、VPN、4G/5G 热点切换都会造成隔离)。 -## 用 API 驱动一个会话 - -`kimi web` 的服务同时暴露 REST 与 WebSocket 接口(实验性,字段级协议见 [服务 API](../reference/server-api.md))。下面用 curl 走一遍最小流程:确认服务状态 → 创建会话 → 订阅事件 → 提交提示词 → 回读历史。示例假设服务跑在默认地址,token 已存入 shell 变量 `TOKEN`。 - -1. 确认服务状态: - -```sh -curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:58627/api/v1/meta -``` - -所有 JSON 响应都包在统一信封里——`{ "code": 0, "msg": "success", "data": ..., "request_id": "..." }`,业务结果以 `code` 为准(`0` 表示成功),HTTP 状态码只表达传输层结果。 - -2. 创建会话,`metadata.cwd` 指定工作目录: - -```sh -curl -s -X POST http://127.0.0.1:58627/api/v1/sessions \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"metadata": {"cwd": "/path/to/project"}}' -``` - -返回的 `data.id`(形如 `session_...`)就是后续所有请求要用的会话 id。 - -3. 连接 WebSocket 并订阅会话事件。任何 WebSocket 客户端都可以;下面是一个零依赖的 Node.js 脚本(Node.js 22+ 内置 `WebSocket` 客户端): - -```js -// subscribe.mjs —— 用法:TOKEN=... node subscribe.mjs session_... -const ws = new WebSocket('ws://127.0.0.1:58627/api/v1/ws', [ - `kimi-code.bearer.${process.env.TOKEN}`, -]); -ws.onmessage = (e) => console.log(e.data); -ws.onopen = () => - ws.send( - JSON.stringify({ - type: 'subscribe', - id: '1', - payload: { session_ids: [process.argv[2]] }, - }), - ); -``` - -4. 提交提示词: - -```sh -curl -s -X POST http://127.0.0.1:58627/api/v1/sessions//prompts \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"content": [{"type": "text", "text": "用一句话介绍这个仓库"}]}' -``` - -订阅端会依次看到 `turn.started`(轮次开始)→ `assistant.delta`(流式文本增量)→ 发生工具调用时的 `tool.call.started` / `tool.result` → `turn.ended`(轮次结束)。 - -5. 随时可以用 REST 回读历史消息: - -```sh -curl -s -H "Authorization: Bearer $TOKEN" \ - "http://127.0.0.1:58627/api/v1/sessions//messages?page_size=20" -``` - ## 下一步 - [服务 API](../reference/server-api.md) — 面向脚本与第三方集成的 REST / WebSocket 接口(实验性) diff --git a/docs/zh/reference/kimi-command.md b/docs/zh/reference/kimi-command.md index be3d755ef5b..6255408de6b 100644 --- a/docs/zh/reference/kimi-command.md +++ b/docs/zh/reference/kimi-command.md @@ -157,7 +157,7 @@ kimi acp 在当前终端前台运行本地 Kimi 服务 —— 同一个进程同时挂载 REST + WebSocket API 与 web UI —— 并在服务就绪后用默认浏览器打开 web UI。命令会一直挂在终端,直到收到 `SIGINT` / `SIGTERM`(如 `Ctrl-C`)时干净退出。 -服务运行时,`GET /openapi.json` 会返回 REST OpenAPI 文档,`GET /asyncapi.json` 会返回本地 WebSocket 协议的 AsyncAPI 文档。用 API 驱动会话的完整流程见[在网页中使用:用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话),协议细节见[服务 API](./server-api.md)。 +服务运行时,`GET /openapi.json` 会返回 REST OpenAPI 文档,`GET /asyncapi.json` 会返回本地 WebSocket 协议的 AsyncAPI 文档。协议细节见[服务 API](./server-api.md)。 ```sh kimi web # 前台运行服务并打开浏览器 diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 7c6b7a39f4e..8ebd8b21fc6 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -1,6 +1,6 @@ # 服务 API -`kimi web` 启动的本地服务暴露两组程序化接口:REST API(`/api/v1`,另有 `/api/v2/sessions` 与 `/api/v2/mcp`)和 WebSocket 事件流(`/api/v1/ws`)。本页是这两组接口的协议参考:基础约定、事件时序、全部端点与帧型、共享类型字典。启动服务及其命令行选项见 [kimi 命令](./kimi-command.md#kimi-web);端到端的上手流程见 [用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话)。 +`kimi web` 启动的本地服务暴露两组程序化接口:REST API(`/api/v1`,另有 `/api/v2/sessions` 与 `/api/v2/mcp`)和 WebSocket 事件流(`/api/v1/ws`)。本页是这两组接口的协议参考:基础约定、事件时序、全部端点与帧型、共享类型字典。启动服务及其命令行选项见 [kimi 命令](./kimi-command.md#kimi-web)。 每个端点精确的机器可读 schema 以服务的在线规范文档为准:`GET /openapi.json`(OpenAPI)与 `GET /asyncapi.json`(AsyncAPI),两者都由服务运行时实际执行的校验 schema 生成,也都需要鉴权。 @@ -3728,5 +3728,5 @@ agent 阶段(`agent.status.updated` 的 `phase` 字段):按 `kind` 区分 ## 下一步 -- [在网页中使用](../guides/web.md) — 启动服务并在浏览器中使用 Kimi Code;含 [用 API 驱动一个会话](../guides/web.md#用-api-驱动一个会话) 的端到端上手 +- [在网页中使用](../guides/web.md) — 启动服务并在浏览器中使用 Kimi Code - [kimi 命令](./kimi-command.md#kimi-web) — `kimi web` 的全部命令行选项 From 5a6be67acafa42421012ad2ea165350883194a26 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:18:33 +0800 Subject: [PATCH 03/47] docs(zh): drop the WebSocket lifecycle section from the server API reference --- docs/zh/reference/server-api.md | 75 +-------------------------------- 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 8ebd8b21fc6..45a797bce4e 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -112,79 +112,6 @@ HTTP 状态码例外(非 200): - **游标式**:`before_id` / `after_id`(互斥)加 `page_size`(1–100),响应为 `{ items, has_more }`。用于会话列表、消息列表、子会话列表;转录分页的游标为 `before_turn` / `after_turn`。 - **`page_token`**:不透明令牌(绑定了查询条件的指纹),用于 `POST /api/v1/search` 与 `GET /api/v2/sessions`。翻页途中改变任何查询条件会使令牌失效:v2 返回 `40922`,search 返回 `40001`。`GET /api/v2/sessions` 另提供无状态的 `page` 页码模式作为替代。 -## WebSocket 时序 - -事件流端点为 `ws://:/api/v1/ws`,鉴权在升级请求时完成(见 [鉴权](#鉴权))。本节按生命周期梳理帧的到达顺序;各帧型的字段定义见 [WebSocket 帧](#websocket-帧)。 - -### 连接与握手 - -连接建立后服务端立即发送 `server_hello`(携带 `protocol_version` 与 `heartbeat_ms`)。客户端随后可发 `client_hello` 声明身份与初始订阅,再发 `subscribe` 订阅会话事件;每个带 `id` 的入站帧都收到一个 `ack` 应答。保活由服务端驱动:每 `heartbeat_ms`(默认 10000 毫秒)发送 `ping`,客户端回 `pong`;连续两个周期没有任何入站帧,服务端以 `close(1001, 'heartbeat timeout')` 断连。 - -### 一个轮次的事件顺序 - -提交提示词的 REST 调用在提示词被接受后立即返回,轮次(turn)进度全部经事件流推送: - -```text -POST /sessions/{id}/prompts → 200(T-PromptItem) - → prompt.submitted - → turn.started - → (turn.step.started → assistant.delta / thinking.delta → tool.call.started → tool.progress → tool.result → turn.step.completed)× N - → turn.ended - → prompt.completed -``` - -流式增量帧(`assistant.delta` / `thinking.delta` 等)是易失(volatile)事件:不落盘、不回放,帧上带 `offset`(该轮次内的累计文本长度)用于对齐;相邻同轮次的增量帧在发送前可能被合并,客户端不能把增量帧当作不可变日志。 - -### 交互:审批与提问 - -工具调用需要许可或结构化输入时,轮次暂停并等待 REST 答复,解决后事件流继续: - -```text -event.approval.requested → POST .../approvals/{approval_id} → event.approval.resolved -event.question.requested → POST .../questions/{question_id}(或 :dismiss)→ event.question.answered(或 event.question.dismissed) -``` - -### 断线恢复 - -重连后在 `subscribe` 的 `cursors` 里带上每个会话最后应用事件的 `{ seq, epoch }`,服务端回放缺口;落后超过事件缓冲(`max_event_buffer_size`,默认 1000 条)、`epoch` 不符或会话被重建时,改为收到 `resync_required`。此时调用 `GET /api/v1/sessions/{session_id}/snapshot` 拿全量快照(含 `as_of_seq` 水位与 `epoch`),再以新游标重新订阅。「水位」(watermark)指事件日志的序列号位置:`seq` 严格递增,同一 `epoch` 内可比较先后。 - -```mermaid -sequenceDiagram - participant C as 客户端 - participant S as 服务 - - Note over C,S: 连接与握手 - C->>S: GET /api/v1/ws(upgrade,Bearer token) - S->>C: server_hello - C->>S: client_hello / subscribe(可带 cursors) - S->>C: ack(accepted、resync_required、cursors) - loop 每 heartbeat_ms - S->>C: ping - C->>S: pong - end - - Note over C,S: 一个轮次 - C->>S: POST /sessions/{id}/prompts - S->>C: 200 信封(T-PromptItem) - S->>C: prompt.submitted → turn.started - loop 每个 step - S->>C: turn.step.started → delta / 工具调用帧 → turn.step.completed - end - S->>C: turn.ended → prompt.completed - - Note over C,S: 交互与恢复 - S->>C: event.approval.requested - C->>S: POST .../approvals/{approval_id} - S->>C: event.approval.resolved - C->>S: subscribe(cursors: {seq, epoch}) - alt 缺口可回放 - S->>C: 回放错过的事件 - else 缓冲溢出 / epoch 不符 / 会话重建 - S->>C: resync_required - C->>S: GET .../snapshot → 以新游标重新订阅 - end -``` - ## REST 端点 下文按资源分组列出全部端点。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 @@ -1285,7 +1212,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 ### 提示词 -提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列;轮次进度通过 [WebSocket 时序](#websocket-时序) 推送,不经过这些端点。 +提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列;轮次进度通过 [WebSocket 帧](#websocket-帧) 推送,不经过这些端点。 | 方法与路径 | 说明 | | --- | --- | From 71d7e400a04e3915f3788822e23b41c67aaf7b66 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:20:48 +0800 Subject: [PATCH 04/47] docs(zh): trim the server API reference opening to one sentence --- docs/zh/reference/server-api.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 45a797bce4e..ffb8bd4c252 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -1,8 +1,6 @@ # 服务 API -`kimi web` 启动的本地服务暴露两组程序化接口:REST API(`/api/v1`,另有 `/api/v2/sessions` 与 `/api/v2/mcp`)和 WebSocket 事件流(`/api/v1/ws`)。本页是这两组接口的协议参考:基础约定、事件时序、全部端点与帧型、共享类型字典。启动服务及其命令行选项见 [kimi 命令](./kimi-command.md#kimi-web)。 - -每个端点精确的机器可读 schema 以服务的在线规范文档为准:`GET /openapi.json`(OpenAPI)与 `GET /asyncapi.json`(AsyncAPI),两者都由服务运行时实际执行的校验 schema 生成,也都需要鉴权。 +此页面记录 kap-server 的 API 接口类型,分为 REST API 与 WebSocket 事件流两种。 ::: warning 注意 本页描述的 REST 与 WebSocket API 为实验性特性:不保证接口稳定性,端点、字段与事件类型可能随任何版本更改。集成时请以你所用版本服务的 `/openapi.json` 与 `/asyncapi.json` 文档为准。 From ebfaf18ff6d5df46611f339203e22623ba6b9fde Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:21:55 +0800 Subject: [PATCH 05/47] docs(zh): drop the experimental notice from the server API reference --- docs/zh/reference/server-api.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index ffb8bd4c252..c6d70be62c2 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -2,10 +2,6 @@ 此页面记录 kap-server 的 API 接口类型,分为 REST API 与 WebSocket 事件流两种。 -::: warning 注意 -本页描述的 REST 与 WebSocket API 为实验性特性:不保证接口稳定性,端点、字段与事件类型可能随任何版本更改。集成时请以你所用版本服务的 `/openapi.json` 与 `/asyncapi.json` 文档为准。 -::: - ## 基础约定 ### 地址 From 8f8b655d80f0ee41c4c5f1dbc7567636c74c350b Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:22:29 +0800 Subject: [PATCH 06/47] docs(zh): drop the address section from the server API reference --- docs/zh/reference/server-api.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index c6d70be62c2..0d779e32464 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4,10 +4,6 @@ ## 基础约定 -### 地址 - -默认地址为 `http://127.0.0.1:58627`。端口被占用时,服务会用下一个端口重试(至多 100 次);可用 `--port` / `--host` 修改绑定。同一 home 目录下可并存多个实例,运行中的实例登记在 `~/.kimi-code/server/instances/`。 - ### 鉴权 除以下例外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求 bearer token(持有方令牌): From d7ad1efb2e5e622eca4a9a34343077496557b6d8 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:23:30 +0800 Subject: [PATCH 07/47] docs(zh): restructure the auth section as how-to, failure shape, and exempt endpoints --- docs/zh/reference/server-api.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 0d779e32464..d13209cac2e 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -6,15 +6,17 @@ ### 鉴权 -除以下例外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求 bearer token(持有方令牌): +REST 请求在请求头携带 bearer token(持有方令牌):`Authorization: Bearer `;WebSocket 升级请求接受同一请求头,或子协议 `kimi-code.bearer.`。除下方例外接口外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求鉴权。token 的生成与轮换见 [在网页中使用:开始使用](../guides/web.md#开始使用)。 -- `OPTIONS` 预检请求 -- `GET /api/v1/healthz`(探活) -- 静态 web 资源(非 `/api/` 路径) +鉴权失败返回 HTTP 401,响应体为标准 [错误信封](#响应信封),`code` 为 `40101`。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(`code` 为 `42901`)。 -携带方式:REST 用 `Authorization: Bearer ` 请求头;WebSocket 升级请求接受同一请求头,或子协议 `kimi-code.bearer.`。token 的生成与轮换见 [在网页中使用:开始使用](../guides/web.md#开始使用)。 +例外接口(不要求鉴权): -鉴权失败返回 HTTP 401,信封 `code` 为 `40101`。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(`code` 为 `42901`)。 +| 接口 | 说明 | +| --- | --- | +| `OPTIONS` 预检请求 | 全部路径 | +| `GET /api/v1/healthz` | 探活 | +| 静态 web 资源 | 非 `/api/` 路径 | ### 响应信封 From f891b5efb8824e10cba32facbadda16633f826af Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:24:56 +0800 Subject: [PATCH 08/47] docs(zh): drop the default-auth and token-rotation sentences from the auth section --- docs/zh/reference/server-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index d13209cac2e..78c44d820d0 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -6,7 +6,7 @@ ### 鉴权 -REST 请求在请求头携带 bearer token(持有方令牌):`Authorization: Bearer `;WebSocket 升级请求接受同一请求头,或子协议 `kimi-code.bearer.`。除下方例外接口外,所有 `/api/*` 路径(含 `/openapi.json` 与 `/asyncapi.json`)都要求鉴权。token 的生成与轮换见 [在网页中使用:开始使用](../guides/web.md#开始使用)。 +REST 请求在请求头携带 bearer token(持有方令牌):`Authorization: Bearer `;WebSocket 升级请求接受同一请求头,或子协议 `kimi-code.bearer.`。 鉴权失败返回 HTTP 401,响应体为标准 [错误信封](#响应信封),`code` 为 `40101`。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(`code` 为 `42901`)。 From 8f674a05c4b44456dc7e6744101825a04995100d Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:28:19 +0800 Subject: [PATCH 09/47] docs(zh): replace the envelope concept with a defined ResponseType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define ResponseType once in the conventions section and rewrite all 122 endpoint entries from "**data**(code = 0)" to "**返回**:ResponseType". The WS event-envelope concept (frame outer fields) is a separate concept and stays. --- docs/zh/reference/server-api.md | 307 ++++++++++++++++---------------- 1 file changed, 149 insertions(+), 158 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 78c44d820d0..12434ad4057 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -8,7 +8,7 @@ REST 请求在请求头携带 bearer token(持有方令牌):`Authorization: Bearer `;WebSocket 升级请求接受同一请求头,或子协议 `kimi-code.bearer.`。 -鉴权失败返回 HTTP 401,响应体为标准 [错误信封](#响应信封),`code` 为 `40101`。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(`code` 为 `42901`)。 +鉴权失败返回 HTTP 401,响应体为 [`ResponseType`](#responsetype),`code` 为 `40101`。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(`code` 为 `42901`)。 例外接口(不要求鉴权): @@ -18,29 +18,20 @@ REST 请求在请求头携带 bearer token(持有方令牌):`Authorization | `GET /api/v1/healthz` | 探活 | | 静态 web 资源 | 非 `/api/` 路径 | -### 响应信封 +### ResponseType -所有 JSON 响应统一包在信封(envelope)里;业务结果以 `code` 为准(`0` 表示成功),HTTP 状态码几乎总是 200。 +除下方例外外,所有 JSON 响应返回同一个泛型 `ResponseType`;HTTP 状态码几乎总是 200,业务结果以 `code` 为准。 -成功信封: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `code` | number | 恒 `0` | -| `msg` | string | 恒 `"success"` | -| `data` | any | 业务负载;少数端点为 `null`(GUI 存储写操作、v2 MCP 的 `auth:complete` / `auth:cancel` / `auth:reset`) | -| `request_id` | string | 请求 id(ULID);客户端可用 `X-Request-Id` 请求头指定,非法值会被服务端重新生成 | - -错误信封: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `code` | number | 非零业务错误码,段位见 [错误码](#错误码) | -| `msg` | string | 错误消息 | -| `data` | null | 恒 `null`;例外见下文「非零 code 携带 data」 | -| `request_id` | string | 请求 id | -| `stack` | string | 可缺省:服务端 `Error.stack`,多数错误路径会携带 | -| `details` | any | 可缺省:结构化详情,形态按 `code` 分派(见各端点条目) | +```ts +type ResponseType = { + code: number // 0 = 成功;非零 = 业务错误码(段位见错误码) + msg: string // 成功恒 "success";失败为错误消息 + data: T | null // code = 0 为端点数据;非零一般为 null(特例见下) + request_id: string // 请求 id(ULID);可用 X-Request-Id 请求头指定,非法值由服务端重新生成 + stack?: string // 服务端 Error.stack,多数错误路径携带 + details?: unknown // 结构化详情,形态按 code 分派(见各端点条目) +} +``` `40001`(输入校验失败)的 `details` 恒为 `{ path, message }[]`——校验问题数组,`path` 为 `.` 连接的字段路径(根级为 `""`),`msg` 取首条。 @@ -59,12 +50,12 @@ HTTP 状态码例外(非 200): | 场景 | HTTP 状态 | | --- | --- | | 鉴权失败 / 触发限流 / Host 检查失败 | 401 / 429 / 403 | -| 创建供应商、导入供应商目录成功 | 201(响应体仍是标准信封) | +| 创建供应商、导入供应商目录成功 | 201(响应体仍是 `ResponseType`) | | 删除供应商成功 | 204(无响应体) | | 二进制与流式端点 | 200 / 206(Range 分段)/ 304(ETag 未变),能力见 [二进制与流式端点](#二进制与流式端点) | -| `GET /api/v1/files/{file_id}`、`GET .../media/{file_id}` 下载错误 | 真实 404 / 500(响应体仍为信封) | +| `GET /api/v1/files/{file_id}`、`GET .../media/{file_id}` 下载错误 | 真实 404 / 500(响应体仍为 `ResponseType`) | -不走信封的端点:四个二进制下载与 zip 导出(见 [二进制与流式端点](#二进制与流式端点))、`DELETE /api/v1/providers/{provider_id}`(204 空体)、web 静态资源(非 `/api` 路径)。 +不返回 `ResponseType` 的端点:四个二进制下载与 zip 导出(见 [二进制与流式端点](#二进制与流式端点))、`DELETE /api/v1/providers/{provider_id}`(204 空体)、web 静态资源(非 `/api` 路径)。 ### 错误码 @@ -124,7 +115,7 @@ HTTP 状态码例外(非 200): 供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -140,7 +131,7 @@ HTTP 状态码例外(非 200): 返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -169,7 +160,7 @@ HTTP 状态码例外(非 200): 鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 -**data**(code = 0):[T-AuthSummary](#t-authsummary)。 +**返回**:`ResponseType<[T-AuthSummary](#t-authsummary)>`。 **示例**: @@ -181,7 +172,7 @@ HTTP 状态码例外(非 200): 请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。无参数。 -**data**(code = 0):`{ "ok": true }`。 +**返回**:`ResponseType<{ "ok": true }>`。 **示例**: @@ -193,7 +184,7 @@ HTTP 状态码例外(非 200): 列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -218,7 +209,7 @@ HTTP 状态码例外(非 200): 返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:供应商与模型只报告 `has_api_key`,绝不返回存储的密钥。 -**data**(code = 0):[T-ConfigResponse](#t-configresponse)。 +**返回**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 **示例**: @@ -232,7 +223,7 @@ HTTP 状态码例外(非 200): **Body**:部分配置对象,[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 -**data**(code = 0):[T-ConfigResponse](#t-configresponse)(合并写入后的全量)。 +**返回**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`(合并写入后的全量)。 **非零 code**:`40001`(值非法或持久化失败,`details` 逐字段说明)。 @@ -264,7 +255,7 @@ HTTP 状态码例外(非 200): 列出所有供应商下已配置的模型别名。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -280,7 +271,7 @@ HTTP 状态码例外(非 200): 把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。无请求体。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -299,7 +290,7 @@ HTTP 状态码例外(非 200): 列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -313,7 +304,7 @@ HTTP 状态码例外(非 200): #### `POST /api/v1/providers` -一次保存创建供应商及其模型别名;响应为 HTTP 201 加标准信封。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 +一次保存创建供应商及其模型别名;响应为 HTTP 201 加 `ResponseType`。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 **Body**: @@ -338,7 +329,7 @@ HTTP 状态码例外(非 200): | `support_efforts` | array | 否 | 支持的 Thinking 模式 effort 档位 | | `adaptive_thinking` | boolean | 否 | 自适应 thinking 开关 | -**data**(code = 0):[T-ProviderCatalogItem](#t-providercatalogitem)(新建对象)。 +**返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`(新建对象)。 **非零 code**:`40001`、`40921`(已存在该 `id` 的供应商)。 @@ -352,7 +343,7 @@ HTTP 状态码例外(非 200): 读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。无参数。 -**data**(code = 0):[T-ProviderCatalogItem](#t-providercatalogitem),存有密钥时附带 `api_key: string`。 +**返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`,存有密钥时附带 `api_key: string`。 **非零 code**:`40001`、`40412`。 @@ -377,7 +368,7 @@ HTTP 状态码例外(非 200): | `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | | `models` | array | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -403,7 +394,7 @@ HTTP 状态码例外(非 200): 从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。无请求体。 -**data**(code = 0):[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)。 +**返回**:`ResponseType<[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)>`。 **非零 code**:`40001`、`40412`。 @@ -452,7 +443,7 @@ HTTP 状态码例外(非 200): 浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -470,7 +461,7 @@ HTTP 状态码例外(非 200): 按 catalog id 读取单个 models.dev 目录条目。无参数。 -**data**(code = 0):[T-CatalogProviderItem](#t-catalogprovideritem)。 +**返回**:`ResponseType<[T-CatalogProviderItem](#t-catalogprovideritem)>`。 **非零 code**:`40417`、`50004`。 @@ -505,7 +496,7 @@ HTTP 状态码例外(非 200): | `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | | `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | -**data**(code = 0):[T-OAuthFlowStart](#t-oauthflowstart)——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 +**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 **示例**: @@ -523,7 +514,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**data**(code = 0):[T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 或 `null`。 +**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 **示例**: @@ -541,7 +532,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -564,7 +555,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | --- | | `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -579,7 +570,7 @@ HTTP 状态码例外(非 200): #### `GET /api/v1/oauth/usage` -托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让信封失败——以 `kind: "error"` 带内返回。 +托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 **Query**: @@ -587,7 +578,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**data**(code = 0):[T-ManagedUsageResult](#t-managedusageresult)。 +**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 **示例**: @@ -605,7 +596,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**data**(code = 0):[T-ManagedUserInfoResult](#t-manageduserinforesult)(camelCase 载荷)。 +**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 **示例**: @@ -617,7 +608,7 @@ HTTP 状态码例外(非 200): 解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -644,7 +635,7 @@ HTTP 状态码例外(非 200): 列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),当前平台不支持的能力对应条目会被剔除。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -662,7 +653,7 @@ HTTP 状态码例外(非 200): 列出已安装插件。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -684,7 +675,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | --- | | `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | -**data**(code = 0):[T-PluginSummary](#t-pluginsummary)。 +**返回**:`ResponseType<[T-PluginSummary](#t-pluginsummary)>`。 **非零 code**:`40001`(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 @@ -698,7 +689,7 @@ HTTP 状态码例外(非 200): 插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 -**data**(code = 0):`{ "ok": true }`。 +**返回**:`ResponseType<{ "ok": true }>`。 **非零 code**:`40001`(缺少动作后缀或动作未知)、`40419`(没有该 id 的已安装插件)。 @@ -722,7 +713,7 @@ HTTP 状态码例外(非 200): 列出所有已注册能力及其就绪状态。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -738,7 +729,7 @@ HTTP 状态码例外(非 200): 读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 -**data**(code = 0):[T-CapabilityStatus](#t-capabilitystatus)。 +**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 **非零 code**:`40418`(没有该 id 的能力)。 @@ -752,7 +743,7 @@ HTTP 状态码例外(非 200): 在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 -**data**(code = 0):[T-CapabilityStatus](#t-capabilitystatus)。 +**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 **非零 code**:`40001`(缺少动作后缀或动作未知)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 @@ -782,7 +773,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `session_id` | string | 要查看其 main agent 的会话。默认最近创建的存活会话 | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -798,7 +789,7 @@ HTTP 状态码例外(非 200): 列出当前生效 Agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同的会话选取规则);没有存活会话时列表为空。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -814,7 +805,7 @@ HTTP 状态码例外(非 200): 重新连接当前生效 Agent 的某个 MCP 服务。经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作。无请求体。 -**data**(code = 0):`{ "restarting": true }`。 +**返回**:`ResponseType<{ "restarting": true }>`。 **非零 code**:`40001`(缺少动作后缀或动作未知)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 @@ -856,7 +847,7 @@ HTTP 状态码例外(非 200): | `title` | string | 否 | 初始标题(至少 1 个字符) | | `agent_config` | object | 否 | schema 接受但当前不会应用——模型与各模式请经 `POST .../profile` 设置 | -**data**(code = 0):[T-Session](#t-session)。 +**返回**:`ResponseType<[T-Session](#t-session)>`。 **非零 code**:`40001`(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 @@ -883,7 +874,7 @@ HTTP 状态码例外(非 200): | `exclude_empty` | boolean | 去掉没有任何用户提示词的会话 | | `workspace_id` | string | 限定到单个工作区(别名会被解析) | -**data**(code = 0):`{ items: T-Session[], has_more: boolean }`。 +**返回**:`ResponseType<{ items: T-Session[], has_more: boolean }>`。 **非零 code**:`40001`(互斥参数同用)、`40410`(未知的 `workspace_id`)。 @@ -897,7 +888,7 @@ HTTP 状态码例外(非 200): 从索引中读取单个会话。`last_seq` 携带真实的事件水位(watermark):存活会话为当前事件日志的序列号,冷会话为最后持久化的水位——用它作为 `subscribe` 的 `cursors` 起点时回放为空。其余会话端点的 `last_seq` 均为 `0` 占位。 -**data**(code = 0):[T-Session](#t-session)。 +**返回**:`ResponseType<[T-Session](#t-session)>`。 **非零 code**:`40401`(会话不存在,或其工作区已无法解析)。 @@ -911,7 +902,7 @@ HTTP 状态码例外(非 200): 读取会话档案——与 `GET /api/v1/sessions/{session_id}` 相同的线上载荷(`last_seq` 为 `0` 占位)。 -**data**(code = 0):[T-Session](#t-session)。 +**返回**:`ResponseType<[T-Session](#t-session)>`。 **非零 code**:`40401`。 @@ -950,7 +941,7 @@ HTTP 状态码例外(非 200): schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers`,但更新路由当前不会应用它们。 -**data**(code = 0):[T-Session](#t-session)(更新后)。 +**返回**:`ResponseType<[T-Session](#t-session)>`(更新后)。 **非零 code**:`40001`、`40401`。 @@ -971,7 +962,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | `force` | boolean | 否 | 即使已有自定义或生成的标题也重新生成。默认 `false` | | `source` | string | 否 | 标题输入:`user_prompts`(默认)/ `first_turn` / `digest` | -**data**(code = 0):`{ "title": string }`——当前应用到会话的标题。 +**返回**:`ResponseType<{ "title": string }>`——当前应用到会话的标题。 **非零 code**:`40401`、`40923`(开关未开启、没有托管登录或尚无提示词内容、已有标题但未提供 `force`,或后端请求失败)。 @@ -989,7 +980,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | --- | --- | --- | --- | | `:fork` | `{ title?, metadata? }` | [T-Session](#t-session)(新会话;广播 `event.session.created`) | `40901`(有进行中的轮次) | | `:compact` | `{ instruction? }` | `{}`(空对象;进度经 `compaction.*` 事件投递) | `40910`(有轮次或上下文变更进行中,或无可压缩内容) | -| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,见 [响应信封](#响应信封)) | +| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,见 [ResponseType](#responsetype)) | | `:abort` | 无 | `{ "aborted": true }` | — | | `:btw` | 无 | `{ "agent_id": string }`——把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文;需要可用的模型配置 | — | | `:archive` | 无 | `{ "archived": true }`——会话从默认列表中消失(`include_archive` / `archived_only` 仍会列出),广播 `event.session.archived` | — | @@ -1016,7 +1007,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | `page_size` | integer | 1–100。默认 `100` | | `busy` | boolean | 只保留忙碌(或只保留空闲)的子会话 | -**data**(code = 0):`{ items: T-Session[], has_more: boolean }`。 +**返回**:`ResponseType<{ items: T-Session[], has_more: boolean }>`。 **非零 code**:`40401`。 @@ -1037,7 +1028,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | `title` | string | 否 | 子会话的标题(至少 1 个字符)。默认 `Child: ` | | `metadata` | object | 否 | 子会话的自定义元数据 | -**data**(code = 0):[T-Session](#t-session)。 +**返回**:`ResponseType<[T-Session](#t-session)>`。 **非零 code**:`40001`、`40401`、`40901`。 @@ -1051,7 +1042,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复。无参数。 -**data**(code = 0):[T-SessionStatus](#t-sessionstatus)。 +**返回**:`ResponseType<[T-SessionStatus](#t-sessionstatus)>`。 **非零 code**:`40401`。 @@ -1065,7 +1056,7 @@ main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复 读取会话当前的目标快照;没有活跃目标时为 `null`。注意该载荷使用 camelCase 键。无参数。 -**data**(code = 0):[T-GoalSnapshot](#t-goalsnapshot) 或 `null`。 +**返回**:`ResponseType<[T-GoalSnapshot](#t-goalsnapshot)>` 或 `null`。 **非零 code**:`40401`。 @@ -1079,7 +1070,7 @@ main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复 读取会话级告警。目前的产生者只有 `AGENTS.md` 过大检查(`agents-md-oversized`),因此大多数会话的列表为空。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1106,7 +1097,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 读取 main agent 的运行时绑定。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1131,7 +1122,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | --- | --- | --- | --- | | `runtime_id` | string | 是 | 目标运行时 id | -**data**(code = 0):同 `GET .../runtime`。 +**返回**:同 `GET .../runtime`。 **非零 code**:`40001`、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 @@ -1145,7 +1136,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 #### `POST /api/v1/sessions/{session_id}/export` -将会话连同诊断日志一起导出为 zip 附件(`kimi-session-.zip`)。响应是 `application/zip` 二进制流,不走信封(`content-disposition: attachment`、`cache-control: no-store`);客户端断连即中止导出。 +将会话连同诊断日志一起导出为 zip 附件(`kimi-session-.zip`)。响应是 `application/zip` 二进制流,不返回 `ResponseType`(`content-disposition: attachment`、`cache-control: no-store`);客户端断连即中止导出。 **Body**: @@ -1154,7 +1145,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `web_log` | string | 否 | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 | | `desktop` | boolean | 否 | 同时包含桌面宿主的日志。默认 `false` | -**非零 code**(JSON 信封):`40001`、`40401`、`50001`。 +**非零 code**(`ResponseType`):`40001`、`40401`、`50001`。 ### 消息 @@ -1178,7 +1169,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `page_size` | integer | 1–100。默认 `50` | | `role` | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | -**data**(code = 0):`{ items: T-Message[], has_more: boolean }`([T-Message](#t-message))。 +**返回**:`ResponseType<{ items: T-Message[], has_more: boolean }>`([T-Message](#t-message))。 **非零 code**:`40001`、`40401`。 @@ -1192,7 +1183,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 按 id 从同一历史中读取单条消息。无参数。 -**data**(code = 0):[T-Message](#t-message)。 +**返回**:`ResponseType<[T-Message](#t-message)>`。 **非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 @@ -1217,7 +1208,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 读取 main agent 的提示词队列快照。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1260,7 +1251,7 @@ schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinking` 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 `file_id` 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。 -**data**(code = 0):[T-PromptItem](#t-promptitem)(被接受的提示词)。 +**返回**:`ResponseType<[T-PromptItem](#t-promptitem)>`(被接受的提示词)。 **非零 code**(鉴权错误族的 `data` / `details` 形态各异): @@ -1286,7 +1277,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | --- | | `prompt_ids` | array | 是 | 非空的排队提示词 id 数组 | -**data**(code = 0):`{ "steered": true, "prompt_ids": string[] }`。 +**返回**:`ResponseType<{ "steered": true, "prompt_ids": string[] }>`。 **非零 code**:`40001`、`40401`、`40402`(所列提示词 id 不在队列中)。 @@ -1300,7 +1291,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 单条提示词动作,经 `POST .../prompts/{tail}` 分发:`:abort` 中止运行中的提示词;`:steer` 把单条排队的提示词插入进行中的轮次(集合形式的单提示词版)。无请求体。 -**data**(code = 0):`:abort` → `{ "aborted": true }`;`:steer` → `{ "steered": true, "prompt_ids": [prompt_id] }`。 +**返回**:`ResponseType`:`:abort` → `{ "aborted": true }`;`:steer` → `{ "steered": true, "prompt_ids": [prompt_id] }`。 **非零 code**:`40001`(动作缺失或未知)、`40401`、`40402`、`40903`(提示词已完成,`data: { "aborted": false }`)。 @@ -1329,7 +1320,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1356,7 +1347,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `feedback` | string | 否 | 回传给 Agent 的自由文本反馈 | | `selected_label` | string | 否 | 当请求提供了带标签的选项时(例如计划审阅),所选选项的标签 | -**data**(code = 0):`{ "resolved": true, "resolved_at": ISO }`。 +**返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 **非零 code**:`40001`、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 @@ -1386,7 +1377,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1422,7 +1413,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `multi_with_other` | `option_ids`、`other_text` | 选项加自由文本 | | `skipped` | — | 跳过了该条目 | -**data**(code = 0):`{ "resolved": true, "resolved_at": ISO }`。 +**返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 **非零 code**:`40001`(`details` 逐字段说明)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 @@ -1436,7 +1427,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 忽略一个待处理的提问,不作回答。无请求体。 -**成功形态**:信封的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码(见 [响应信封](#响应信封))。 +**成功形态**:`ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码(见 [ResponseType](#responsetype))。 **非零 code**:`40401`、`40405`、`40902`(已被答复,`data: { "resolved": false }`)。 @@ -1466,7 +1457,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `status` | string | 只保留单一状态:`running` / `completed` / `failed` / `cancelled` | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1491,7 +1482,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `with_output` | boolean | 在响应中包含输出末尾片段。默认 `false` | | `output_bytes` | integer | 请求的输出末尾片段的字节大小,最小 `0`。默认 `32768` | -**data**(code = 0):[T-Task](#t-task);`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 +**返回**:`ResponseType<[T-Task](#t-task)>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 **非零 code**:`40001`、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 @@ -1505,7 +1496,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 任务动作经 `POST .../tasks/{tail}` 分发:`:cancel` 取消运行中的任务;`:detach` 将运行中的前台任务转入后台而不终止它(等待该任务的工具调用立即以后台任务结果返回,轮次继续推进)。已在后台或已结束的任务上 `:detach` 为幂等空操作。无请求体。 -**data**(code = 0):`:cancel` → `{ "cancelled": true }`;`:detach` → `{ "detached": boolean, "status": string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 +**返回**:`ResponseType`:`:cancel` → `{ "cancelled": true }`;`:detach` → `{ "detached": boolean, "status": string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 **非零 code**:`40001`(动作缺失或未知)、`40401`、`40406`、`40904`(任务已结束,`data: { "cancelled": false }` 且 `details: { "current_status" }`)。 @@ -1530,7 +1521,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出会话的终端;读取列表会在会话为冷态时将其恢复。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1558,7 +1549,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `cols` | integer | 否 | 终端宽度,正数。默认 `80` | | `rows` | integer | 否 | 终端高度,正数。默认 `24` | -**data**(code = 0):[T-Terminal](#t-terminal)。 +**返回**:`ResponseType<[T-Terminal](#t-terminal)>`。 **非零 code**:`40001`(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 @@ -1572,7 +1563,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 读取单个终端。无参数。 -**data**(code = 0):[T-Terminal](#t-terminal)。 +**返回**:`ResponseType<[T-Terminal](#t-terminal)>`。 **非零 code**:`40401`、`40414`(没有该 id 的终端)。 @@ -1586,7 +1577,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 关闭终端并结束其进程。经 `POST .../terminals/{tail}` 分发,`close` 是唯一动作。无请求体。 -**data**(code = 0):`{ "closed": true }`。 +**返回**:`ResponseType<{ "closed": true }>`。 **非零 code**:`40001`(缺少动作后缀或动作未知)、`40401`、`40414`。 @@ -1610,7 +1601,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出单个会话可用的技能,按会话的优先级合并所有来源(内置、插件、extra、用户、项目);会话处于冷态时读取目录会恢复该会话。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1628,7 +1619,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出该工作区中的会话将看到的技能目录,但不创建或恢复会话。无参数。 -**data**(code = 0):同 `GET /api/v1/sessions/{session_id}/skills`。 +**返回**:同 `GET /api/v1/sessions/{session_id}/skills`。 **非零 code**:`40410`(工作区不存在)。 @@ -1649,7 +1640,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `args` | string | 否 | 传给技能的自由文本参数,相当于斜杠命令后的文本 | | `attachments` | array | 否 | 随激活携带的媒体块。`image` / `video` 块带 `source` 对象(`kind` 为 `url` / `base64` / `file` / `session_media`,与提示词内容块同形);`file` 块带顶层 `file_id`、`name`、`media_type`、`size` | -**data**(code = 0):`{ "activated": true, "skill_name": string }`。 +**返回**:`ResponseType<{ "activated": true, "skill_name": string }>`。 **非零 code**:`40001`(校验失败或动作后缀不支持)、`40401`、`40407`(引用的附件文件不存在)、`40415`(没有该名称的技能)、`40912`(技能类型不允许用户激活)。 @@ -1678,7 +1669,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出所有已注册工作区。无参数。 -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1701,7 +1692,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `root` | string | 是 | 已存在目录的绝对路径 | | `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | -**data**(code = 0):[T-Workspace](#t-workspace)。 +**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 **非零 code**:`40001`(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 @@ -1721,7 +1712,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `name` | string | 是 | 新的显示名,1–100 个字符 | -**data**(code = 0):[T-Workspace](#t-workspace)。 +**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 **非零 code**:`40001`、`40410`。 @@ -1735,7 +1726,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 -**data**(code = 0):`{ "deleted": true }`。 +**返回**:`ResponseType<{ "deleted": true }>`。 **非零 code**:`40410`。 @@ -1749,7 +1740,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。无参数。 -**data**(code = 0):`{ "trusted": boolean }`。 +**返回**:`ResponseType<{ "trusted": boolean }>`。 **非零 code**:`40410`。 @@ -1763,7 +1754,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 将工作区标记为信任,并加载其项目级 MCP 配置。无请求体。 -**data**(code = 0):`{ "trusted": true }`。 +**返回**:`ResponseType<{ "trusted": true }>`。 **非零 code**:`40410`。 @@ -1777,7 +1768,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 撤销工作区信任,并卸载其项目级 MCP 配置。无请求体。 -**data**(code = 0):`{ "trusted": false }`。 +**返回**:`ResponseType<{ "trusted": false }>`。 **非零 code**:`40410`。 @@ -1798,7 +1789,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `path` | string | 是 | 要添加的目录 | | `persist` | boolean | 否 | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1848,7 +1839,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | | `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | -**data**(code = 0):[T-FsListResponse](#t-fslistresponse)。 +**返回**:`ResponseType<[T-FsListResponse](#t-fslistresponse)>`。 **非零 code**:`40001`、`40401`、`40409`(路径不存在或不是目录)、`41304`。 @@ -1871,7 +1862,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | | `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | -**data**(code = 0):[T-FsReadResponse](#t-fsreadresponse)。 +**返回**:`ResponseType<[T-FsReadResponse](#t-fsreadresponse)>`。 **非零 code**:`40001`、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 @@ -1893,7 +1884,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 -**data**(code = 0):[T-FsListManyResponse](#t-fslistmanyresponse)。 +**返回**:`ResponseType<[T-FsListManyResponse](#t-fslistmanyresponse)>`。 **非零 code**:`40001`、`40401`。 @@ -1913,7 +1904,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `path` | string | 是 | 要查询的路径,相对于会话工作目录 | -**data**(code = 0):[T-FsEntry](#t-fsentry)。 +**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`。 **非零 code**:`40001`、`40401`、`40409`、`41304`。 @@ -1933,7 +1924,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `paths` | array | 是 | 要查询的路径,1–1000 条 | -**data**(code = 0):[T-FsStatManyResponse](#t-fsstatmanyresponse)。 +**返回**:`ResponseType<[T-FsStatManyResponse](#t-fsstatmanyresponse)>`。 **非零 code**:`40001`、`40401`。 @@ -1954,7 +1945,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `path` | string | 是 | 要创建的目录,相对于会话工作目录 | | `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | -**data**(code = 0):[T-FsEntry](#t-fsentry)(所建目录)。 +**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`(所建目录)。 **非零 code**:`40001`、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 @@ -1978,7 +1969,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -**data**(code = 0):`{ items: T-FsSearchHit[], truncated: boolean }`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 +**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 **非零 code**:`40001`、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 @@ -2007,7 +1998,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | | `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | -**data**(code = 0):[T-FsGrepResponse](#t-fsgrepresponse)。 +**返回**:`ResponseType<[T-FsGrepResponse](#t-fsgrepresponse)>`。 **非零 code**:`40001`、`40401`、`41303`、`41305`(搜索超时)。 @@ -2027,7 +2018,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | -**data**(code = 0):[T-FsGitStatusResponse](#t-fsgitstatusresponse)(注意 camelCase `pullRequest`)。 +**返回**:`ResponseType<[T-FsGitStatusResponse](#t-fsgitstatusresponse)>`(注意 camelCase `pullRequest`)。 **非零 code**:`40001`、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 @@ -2047,7 +2038,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | -**data**(code = 0):[T-FsDiffResponse](#t-fsdiffresponse)。 +**返回**:`ResponseType<[T-FsDiffResponse](#t-fsdiffresponse)>`。 **非零 code**:`40001`、`40401`、`40908`、`41304`。 @@ -2068,7 +2059,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `path` | string | 是 | 要打开的文件,相对于会话工作目录 | | `line` | integer | 否 | 在处理程序支持时跳转到的行号(正整数) | -**data**(code = 0):`{ "opened": true }`。 +**返回**:`ResponseType<{ "opened": true }>`。 **非零 code**:`40001`、`40401`、`40409`、`41304`。 @@ -2090,7 +2081,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `path` | string | 是 | 要打开的文件或目录,相对于会话工作目录 | | `line` | integer | 否 | 在应用支持时跳转到的行号(正整数) | -**data**(code = 0):`{ "opened": true }`。 +**返回**:`ResponseType<{ "opened": true }>`。 **非零 code**:`40001`、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 @@ -2110,7 +2101,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `path` | string | 是 | 要显示的文件,相对于会话工作目录 | -**data**(code = 0):`{ "revealed": true }`。 +**返回**:`ResponseType<{ "revealed": true }>`。 **非零 code**:`40001`、`40401`、`40409`、`41304`。 @@ -2130,7 +2121,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `runtime_id` | string | 从哪个运行时读取。默认 `local` | -**非零 code**(JSON 信封):`40001`(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 +**非零 code**(`ResponseType`):`40001`(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 #### `POST /api/v1/workspace/fs:search` @@ -2148,7 +2139,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | | `runtime_id` | string | 否 | 在哪个运行时上搜索。默认 `local` | -**data**(code = 0):`{ items: T-FsSearchHit[], truncated: boolean }`,命中结构与排序同 `fs:search`。 +**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`,命中结构与排序同 `fs:search`。 **非零 code**:`40001`、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 @@ -2175,7 +2166,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | | `runtime_id` | string | 否 | 在哪个运行时上补全。默认 `local` | -**data**(code = 0):`{ items: T-FsSuggestItem[], truncated: boolean }`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 +**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 **非零 code**:`40001`、`40410`。 @@ -2202,7 +2193,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | | `runtime_id` | string | 否 | 默认 `local` | -**data**(code = 0):`{ items: T-FsSuggestItem[], truncated: boolean }`。 +**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`。 **非零 code**:`40001`、`40409`(某个 root 不存在)、`40420`、`40926`。 @@ -2222,7 +2213,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `path` | string | 绝对目录路径。默认用户主目录 | -**data**(code = 0):[T-FsBrowseResponse](#t-fsbrowseresponse)。 +**返回**:`ResponseType<[T-FsBrowseResponse](#t-fsbrowseresponse)>`。 **非零 code**:`40001`(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 @@ -2236,7 +2227,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 返回文件夹选择器的落地数据。无参数。 -**data**(code = 0):[T-FsHomeResponse](#t-fshomeresponse)(`recent_roots` 上限 8)。 +**返回**:`ResponseType<[T-FsHomeResponse](#t-fshomeresponse)>`(`recent_roots` 上限 8)。 **示例**: @@ -2254,7 +2245,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `path` | string | **必填。** 绝对文件路径(realpath 解析) | -**非零 code**(JSON 信封):`40001`(不是绝对路径或不是普通文件)、`40409`、`40411`、`40906`(路径是目录)。 +**非零 code**(`ResponseType`):`40001`(不是绝对路径或不是普通文件)、`40409`、`40411`、`40906`(路径是目录)。 #### `POST /api/v1/fs:mkdir` @@ -2266,7 +2257,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `path` | string | 是 | 绝对目录路径 | -**data**(code = 0):`{ "path": string }`。 +**返回**:`ResponseType<{ "path": string }>`。 **非零 code**:`40001`、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 @@ -2299,7 +2290,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `name` | string | 否 | 存储的显示名。默认上传文件名 | | `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | -**data**(code = 0):[T-FileMeta](#t-filemeta)。 +**返回**:`ResponseType<[T-FileMeta](#t-filemeta)>`。 **非零 code**:`40001`(multipart 未初始化或缺少 `file` 字段)。 @@ -2319,7 +2310,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 删除已上传的文件。无请求体。 -**data**(code = 0):`{ "deleted": true }`。 +**返回**:`ResponseType<{ "deleted": true }>`。 **非零 code**:同下载——`40407`(HTTP 404)、`50001`(HTTP 500)。 @@ -2331,7 +2322,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 #### `GET /api/v1/sessions/{session_id}/media/{file_id}` -按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里走信封的端点不同,会话或文件不存在时返回真正的 404 状态码并携带信封体。 +按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里返回 `ResponseType` 的端点不同,会话或文件不存在时返回真正的 404 状态码且响应体仍为 `ResponseType`。 **非零 code**:`40401`(HTTP 404)、`40407`(HTTP 404)。 @@ -2358,7 +2349,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 `terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 -**data**(code = 0):[T-SearchResponse](#t-searchresponse)。 +**返回**:`ResponseType<[T-SearchResponse](#t-searchresponse)>`。 **非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法)、`50001`。 @@ -2386,7 +2377,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 返回已存键的数量(对齐 `localStorage.length`)。无参数。 -**data**(code = 0):`{ "length": number }`。 +**返回**:`ResponseType<{ "length": number }>`。 **示例**: @@ -2404,7 +2395,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `key` | string | **必填。** 要读取的键,1–256 个字符 | -**data**(code = 0):`{ "value": string | null }`——键不存在时为 `null`。 +**返回**:`ResponseType<{ "value": string | null }>`——键不存在时为 `null`。 **示例**: @@ -2423,7 +2414,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `key` | string | 是 | 要写入的键,1–256 个字符 | | `value` | string | 是 | 要存储的值 | -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **示例**: @@ -2441,7 +2432,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `key` | string | 是 | 要删除的键,1–256 个字符 | -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **示例**: @@ -2453,7 +2444,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 删除所有已存值(对齐 `localStorage.clear`)。无请求体。 -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **示例**: @@ -2467,7 +2458,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 -**data**(code = 0):[T-SnapshotResponse](#t-snapshotresponse)。 +**返回**:`ResponseType<[T-SnapshotResponse](#t-snapshotresponse)>`。 **非零 code**:`40401`、`50001`。 @@ -2501,7 +2492,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | | `page_size` | integer | 1–100 个轮次。默认 `20` | -**data**(code = 0):[T-TranscriptResponse](#t-transcriptresponse)——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 +**返回**:`ResponseType<[T-TranscriptResponse](#t-transcriptresponse)>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 **非零 code**:`40001`、`40401`。 @@ -2522,7 +2513,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | -**data**(code = 0):[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 +**返回**:`ResponseType<[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 **非零 code**:`40001`、`40401`。 @@ -2542,7 +2533,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | -**data**(code = 0):[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)。 +**返回**:`ResponseType<[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)>`。 **非零 code**:`40001`、`40401`。 @@ -2563,7 +2554,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | -**data**(code = 0):[T-TranscriptPlanResponse](#t-transcriptplanresponse)。 +**返回**:`ResponseType<[T-TranscriptPlanResponse](#t-transcriptplanresponse)>`。 **非零 code**:`40001`、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 @@ -2596,7 +2587,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `turn_id` | integer | **必填。** 轮次 id(≥ 0) | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -2624,7 +2615,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `path` | string | **必填。** 文件路径 | | `phase` | string | `start`(默认)/ `end`——取轮次开始还是结束检查点 | -**data**(code = 0): +**返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -2640,7 +2631,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 ### v2 会话 -`/api/v2` 的会话查询与批量管理。与 v1 共享信封与错误约定;分页为绑定查询指纹的 `page_token`(见 [分页](#分页))。 +`/api/v2` 的会话查询与批量管理。与 v1 共享 `ResponseType` 与错误约定;分页为绑定查询指纹的 `page_token`(见 [分页](#分页))。 | 方法与路径 | 说明 | | --- | --- | @@ -2671,7 +2662,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | | `page_token` | string | 上一页返回的翻页令牌 | -**data**(code = 0):[T-V2SessionPage](#t-v2sessionpage)(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 +**返回**:`ResponseType<[T-V2SessionPage](#t-v2sessionpage)>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 **非零 code**:`40001`(未知 `include` / `fields`、组合非法)、`40922`。 @@ -2691,7 +2682,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | -**data**(code = 0):[T-V2BatchSessionResponse](#t-v2batchsessionresponse)——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 +**返回**:`ResponseType<[T-V2BatchSessionResponse](#t-v2batchsessionresponse)>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 **非零 code**:`40001`。 @@ -2734,7 +2725,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组。 **示例**: @@ -2752,7 +2743,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>`。 **非零 code**:`40001`、`40408`(不存在该名称的 server)。 @@ -2768,7 +2759,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 -**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 **非零 code**:`40001`(校验失败,或目标条目为只读)。 @@ -2784,7 +2775,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 -**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 **非零 code**:`40001`、`40408`。 @@ -2798,7 +2789,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 删除一个用户级条目。无请求体。 -**data**(code = 0):[T-McpManagedServer](#t-mcpmanagedserver) 数组(刷新后的列表)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 **非零 code**:`40001`、`40408`。 @@ -2820,7 +2811,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `server` | object | 二选一 | 按原样探测的内联 server 配置(含 `name`) | | `cwd` | string | 否 | 项目层并入解析;同时是 stdio 的工作目录 | -**data**(code = 0):`{ "success": boolean, "output": string }`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 +**返回**:`ResponseType<{ "success": boolean, "output": string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 **非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用)、`40408`。 @@ -2841,7 +2832,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | | `cwd` | string | 否 | 并入该(受信任)目录的项目层 | -**data**(code = 0):[T-McpServerInspection](#t-mcpserverinspection) 数组。 +**返回**:`ResponseType<[T-McpServerInspection](#t-mcpserverinspection)>` 数组。 **非零 code**:`40001`、`40408`(`targets` 中有 locator 未匹配到任何条目)。 @@ -2862,7 +2853,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `cwd` | string | 并入该(受信任)目录的项目层 | | `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | -**data**(code = 0):[T-McpServerAuthStatus](#t-mcpserverauthstatus) 数组。验证探测可能刷新或作废已存储的凭据。 +**返回**:`ResponseType<[T-McpServerAuthStatus](#t-mcpserverauthstatus)>` 数组。验证探测可能刷新或作废已存储的凭据。 **示例**: @@ -2876,7 +2867,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **Body**:locator(`{ "source": "global", "name" }` 或 `{ "source": "plugin", "pluginId", "serverName" }`);另有可选的 `cwd` 查询参数。 -**data**(code = 0):`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 +**返回**:`ResponseType`:`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 **非零 code**:`40001`(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 @@ -2897,7 +2888,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `flowId` | string | 是 | `auth:begin` 返回的流程 id | | `timeoutMs` | integer | 否 | 等待上限(毫秒)。默认 15 分钟 | -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **非零 code**:`40001`(`flowId` 未知)、`40929`。 @@ -2917,7 +2908,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | --- | | `flowId` | string | 是 | 要终止的流程 id | -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **示例**: @@ -2931,7 +2922,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **Body**:locator(形态同 `auth:begin`)。 -**data**(code = 0):`null`。 +**返回**:`ResponseType`。 **非零 code**:`40001`、`40408`(locator 未匹配)、`40929`。 @@ -3643,7 +3634,7 @@ agent 阶段(`agent.status.updated` 的 `phase` 字段):按 `kind` 区分 | `GET /api/v1/fs:content` | 读取本机任意文件(仅受 token 保护,谨慎暴露端口) | 支持 | 支持 | | `POST /api/v1/sessions/{session_id}/export` | 导出会话与诊断信息(zip 流) | 不支持 | 不支持 | -错误语义也不相同:`GET /api/v1/files/{file_id}` 与 `GET .../media/{file_id}` 对查找和存储失败返回真实 404 / 500 状态码(参数校验失败仍走 HTTP 200 信封),其余三个端点的所有失败都走标准 [响应信封](#响应信封)——客户端在这三个端点上仍需检查信封中的 `code`。 +错误语义也不相同:`GET /api/v1/files/{file_id}` 与 `GET .../media/{file_id}` 对查找和存储失败返回真实 404 / 500 状态码(参数校验失败仍返回 HTTP 200 的 `ResponseType`),其余三个端点的所有失败都返回 [`ResponseType`](#responsetype)——客户端在这三个端点上仍需检查 `code`。 ## 下一步 From 9f7660219e80ce5c527c279da68e144a41c29c9a Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:30:21 +0800 Subject: [PATCH 10/47] docs(zh): move non-zero-code data shapes into the endpoint entries Remove the 40001 details note and the non-zero-code-with-data specials table from the ResponseType section; each affected endpoint entry already carries (or now carries) its own data shape inline, and 40001 mentions in non-zero-code lines now state the { path, message }[] details shape. --- docs/zh/reference/server-api.md | 160 +++++++++++++++----------------- 1 file changed, 74 insertions(+), 86 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 12434ad4057..6988dd25782 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -33,18 +33,6 @@ type ResponseType = { } ``` -`40001`(输入校验失败)的 `details` 恒为 `{ path, message }[]`——校验问题数组,`path` 为 `.` 连接的字段路径(根级为 `""`),`msg` 取首条。 - -非零 `code` 但 `data` 非 `null` 的特例: - -| code | 端点 | `data` 形态 | -| --- | --- | --- | -| `40903` | `POST /api/v1/sessions/{id}/prompts`、`POST .../prompts/{prompt_id}:{action}` | `{ "aborted": false }` | -| `40902` | `POST .../approvals/{approval_id}`、`POST .../questions/{question_id}` | `{ "resolved": false }` | -| `40909` | `POST .../questions/{question_id}:dismiss` | `{ "dismissed": true, "dismissed_at" }`——dismiss 成功以非零码返回 | -| `40904` | `POST .../tasks/{task_id}:cancel` | `{ "cancelled": false }`,且 `details` 为 `{ "current_status" }` | -| `40911` | `POST /api/v1/sessions/{id}:undo` | 引擎返回的 details 或 `null`,形态不定 | - HTTP 状态码例外(非 200): | 场景 | HTTP 状态 | @@ -225,7 +213,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`(合并写入后的全量)。 -**非零 code**:`40001`(值非法或持久化失败,`details` 逐字段说明)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(值非法或持久化失败,`details` 逐字段说明)。 **示例**: @@ -278,7 +266,7 @@ HTTP 状态码例外(非 200): | `default_model` | string | 当前生效的别名 | | `model` | object | [T-ModelCatalogItem](#t-modelcatalogitem) | -**非零 code**:`40001`(动作后缀非法)、`40413`(模型别名不存在)。 +**非零 code**:`40001`(动作后缀非法;`details` 为 `{ path, message }[]`)、`40413`(模型别名不存在)。 **示例**: @@ -331,7 +319,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`(新建对象)。 -**非零 code**:`40001`、`40921`(已存在该 `id` 的供应商)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40921`(已存在该 `id` 的供应商)。 **示例**: @@ -345,7 +333,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`,存有密钥时附带 `api_key: string`。 -**非零 code**:`40001`、`40412`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40412`。 **示例**: @@ -374,7 +362,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | object | [T-ProviderCatalogItem](#t-providercatalogitem) | -**非零 code**:`40001`(重命名后的别名 id 冲突)、`40003`(供应商由 OAuth 托管,改用 `POST /api/v1/oauth/logout`)、`40412`、`40921`(`new_id` 已被占用)。 +**非零 code**:`40001`(重命名后的别名 id 冲突;`details` 为 `{ path, message }[]`)、`40003`(供应商由 OAuth 托管,改用 `POST /api/v1/oauth/logout`)、`40412`、`40921`(`new_id` 已被占用)。 **示例**: @@ -388,7 +376,7 @@ HTTP 状态码例外(非 200): **成功形态**:HTTP 204 空体——状态行本身即表示删除成功。 -**非零 code**:`40001`、`40003`、`40412`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40003`、`40412`。 #### `POST /api/v1/providers/{provider_id}:refresh` @@ -396,7 +384,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)>`。 -**非零 code**:`40001`、`40412`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40412`。 **示例**: @@ -431,7 +419,7 @@ HTTP 状态码例外(非 200): | `url` | string | 是 | 注册表 `api.json` 的 URL | | `api_key` | string | 否 | 注册表的 Bearer key;省略时复用上一次导入同一 URL 所用的 key | -**非零 code**:`40001`、`40003`、`40004`(目录条目无法导入)、`40005`(注册表无法获取或解析)、`40417`、`50004`(models.dev 目录不可用)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40003`、`40004`(目录条目无法导入)、`40005`(注册表无法获取或解析)、`40417`、`50004`(models.dev 目录不可用)。 **示例**(`:import_catalog`): @@ -677,7 +665,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-PluginSummary](#t-pluginsummary)>`。 -**非零 code**:`40001`(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 **示例**: @@ -691,7 +679,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<{ "ok": true }>`。 -**非零 code**:`40001`(缺少动作后缀或动作未知)、`40419`(没有该 id 的已安装插件)。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40419`(没有该 id 的已安装插件)。 **示例**: @@ -745,7 +733,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 -**非零 code**:`40001`(缺少动作后缀或动作未知)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 **示例**: @@ -807,7 +795,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<{ "restarting": true }>`。 -**非零 code**:`40001`(缺少动作后缀或动作未知)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 **示例**: @@ -849,7 +837,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<[T-Session](#t-session)>`。 -**非零 code**:`40001`(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 **示例**: @@ -876,7 +864,7 @@ HTTP 状态码例外(非 200): **返回**:`ResponseType<{ items: T-Session[], has_more: boolean }>`。 -**非零 code**:`40001`(互斥参数同用)、`40410`(未知的 `workspace_id`)。 +**非零 code**:`40001`(互斥参数同用;`details` 为 `{ path, message }[]`)、`40410`(未知的 `workspace_id`)。 **示例**: @@ -943,7 +931,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` **返回**:`ResponseType<[T-Session](#t-session)>`(更新后)。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -980,13 +968,13 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | --- | --- | --- | --- | | `:fork` | `{ title?, metadata? }` | [T-Session](#t-session)(新会话;广播 `event.session.created`) | `40901`(有进行中的轮次) | | `:compact` | `{ instruction? }` | `{}`(空对象;进度经 `compaction.*` 事件投递) | `40910`(有轮次或上下文变更进行中,或无可压缩内容) | -| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,见 [ResponseType](#responsetype)) | +| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,形态不定) | | `:abort` | 无 | `{ "aborted": true }` | — | | `:btw` | 无 | `{ "agent_id": string }`——把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文;需要可用的模型配置 | — | | `:archive` | 无 | `{ "archived": true }`——会话从默认列表中消失(`include_archive` / `archived_only` 仍会列出),广播 `event.session.archived` | — | | `:restore` | 无 | [T-Session](#t-session)(`archived: false`) | — | -共有非零 code:`40001`(动作缺失或未知)、`40401`。 +共有非零 code:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`。 **示例**(`:fork`): @@ -1030,7 +1018,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` **返回**:`ResponseType<[T-Session](#t-session)>`。 -**非零 code**:`40001`、`40401`、`40901`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40901`。 **示例**: @@ -1124,7 +1112,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 **返回**:同 `GET .../runtime`。 -**非零 code**:`40001`、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 **示例**: @@ -1145,7 +1133,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `web_log` | string | 否 | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 | | `desktop` | boolean | 否 | 同时包含桌面宿主的日志。默认 `false` | -**非零 code**(`ResponseType`):`40001`、`40401`、`50001`。 +**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`50001`。 ### 消息 @@ -1171,7 +1159,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 **返回**:`ResponseType<{ items: T-Message[], has_more: boolean }>`([T-Message](#t-message))。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -1279,7 +1267,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType<{ "steered": true, "prompt_ids": string[] }>`。 -**非零 code**:`40001`、`40401`、`40402`(所列提示词 id 不在队列中)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40402`(所列提示词 id 不在队列中)。 **示例**: @@ -1293,7 +1281,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType`:`:abort` → `{ "aborted": true }`;`:steer` → `{ "steered": true, "prompt_ids": [prompt_id] }`。 -**非零 code**:`40001`(动作缺失或未知)、`40401`、`40402`、`40903`(提示词已完成,`data: { "aborted": false }`)。 +**非零 code**:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`、`40402`、`40903`(提示词已完成,`data: { "aborted": false }`)。 **示例**: @@ -1326,7 +1314,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `items` | array | [T-ApprovalRequest](#t-approvalrequest) 数组 | -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -1349,7 +1337,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 -**非零 code**:`40001`、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 **示例**: @@ -1383,7 +1371,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `items` | array | [T-QuestionRequest](#t-questionrequest) 数组 | -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -1415,7 +1403,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 -**非零 code**:`40001`(`details` 逐字段说明)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`details` 逐字段说明)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 **示例**: @@ -1427,7 +1415,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 忽略一个待处理的提问,不作回答。无请求体。 -**成功形态**:`ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码(见 [ResponseType](#responsetype))。 +**成功形态**:`ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码。 **非零 code**:`40401`、`40405`、`40902`(已被答复,`data: { "resolved": false }`)。 @@ -1463,7 +1451,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `items` | array | [T-Task](#t-task) 数组;冷会话为 `[]` | -**非零 code**:`40001`(未知的 `status`)、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知的 `status`)、`40401`。 **示例**: @@ -1484,7 +1472,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType<[T-Task](#t-task)>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 -**非零 code**:`40001`、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 **示例**: @@ -1498,7 +1486,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin **返回**:`ResponseType`:`:cancel` → `{ "cancelled": true }`;`:detach` → `{ "detached": boolean, "status": string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 -**非零 code**:`40001`(动作缺失或未知)、`40401`、`40406`、`40904`(任务已结束,`data: { "cancelled": false }` 且 `details: { "current_status" }`)。 +**非零 code**:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`、`40406`、`40904`(任务已结束,`data: { "cancelled": false }` 且 `details: { "current_status" }`)。 **示例**: @@ -1551,7 +1539,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-Terminal](#t-terminal)>`。 -**非零 code**:`40001`(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 **示例**: @@ -1579,7 +1567,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "closed": true }>`。 -**非零 code**:`40001`(缺少动作后缀或动作未知)、`40401`、`40414`。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40401`、`40414`。 **示例**: @@ -1642,7 +1630,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "activated": true, "skill_name": string }>`。 -**非零 code**:`40001`(校验失败或动作后缀不支持)、`40401`、`40407`(引用的附件文件不存在)、`40415`(没有该名称的技能)、`40912`(技能类型不允许用户激活)。 +**非零 code**:`40001`(校验失败或动作后缀不支持;`details` 为 `{ path, message }[]`)、`40401`、`40407`(引用的附件文件不存在)、`40415`(没有该名称的技能)、`40912`(技能类型不允许用户激活)。 **示例**: @@ -1694,7 +1682,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 -**非零 code**:`40001`(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 **示例**: @@ -1714,7 +1702,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 -**非零 code**:`40001`、`40410`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 **示例**: @@ -1798,7 +1786,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `additional_dirs` | array | 全部附加目录(含既有目录) | | `persisted` | boolean | 本次是否写盘 | -**非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误)、`40409`(`path` 不存在或不是目录)、`40410`。 +**非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误;`details` 为 `{ path, message }[]`)、`40409`(`path` 不存在或不是目录)、`40410`。 **示例**: @@ -1841,7 +1829,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsListResponse](#t-fslistresponse)>`。 -**非零 code**:`40001`、`40401`、`40409`(路径不存在或不是目录)、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 **示例**: @@ -1864,7 +1852,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsReadResponse](#t-fsreadresponse)>`。 -**非零 code**:`40001`、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 **示例**: @@ -1886,7 +1874,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsListManyResponse](#t-fslistmanyresponse)>`。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -1906,7 +1894,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`。 -**非零 code**:`40001`、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: @@ -1926,7 +1914,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsStatManyResponse](#t-fsstatmanyresponse)>`。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -1947,7 +1935,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`(所建目录)。 -**非零 code**:`40001`、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 **示例**: @@ -1971,7 +1959,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 -**非零 code**:`40001`、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 **示例**: @@ -2000,7 +1988,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsGrepResponse](#t-fsgrepresponse)>`。 -**非零 code**:`40001`、`40401`、`41303`、`41305`(搜索超时)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 **示例**: @@ -2020,7 +2008,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsGitStatusResponse](#t-fsgitstatusresponse)>`(注意 camelCase `pullRequest`)。 -**非零 code**:`40001`、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 **示例**: @@ -2040,7 +2028,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsDiffResponse](#t-fsdiffresponse)>`。 -**非零 code**:`40001`、`40401`、`40908`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 **示例**: @@ -2061,7 +2049,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "opened": true }>`。 -**非零 code**:`40001`、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: @@ -2083,7 +2071,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "opened": true }>`。 -**非零 code**:`40001`、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 **示例**: @@ -2103,7 +2091,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "revealed": true }>`。 -**非零 code**:`40001`、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: @@ -2121,7 +2109,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `runtime_id` | string | 从哪个运行时读取。默认 `local` | -**非零 code**(`ResponseType`):`40001`(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 +**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 #### `POST /api/v1/workspace/fs:search` @@ -2141,7 +2129,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`,命中结构与排序同 `fs:search`。 -**非零 code**:`40001`、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 **示例**: @@ -2168,7 +2156,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 -**非零 code**:`40001`、`40410`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 **示例**: @@ -2195,7 +2183,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`。 -**非零 code**:`40001`、`40409`(某个 root 不存在)、`40420`、`40926`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(某个 root 不存在)、`40420`、`40926`。 **示例**: @@ -2215,7 +2203,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FsBrowseResponse](#t-fsbrowseresponse)>`。 -**非零 code**:`40001`(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 **示例**: @@ -2245,7 +2233,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `path` | string | **必填。** 绝对文件路径(realpath 解析) | -**非零 code**(`ResponseType`):`40001`(不是绝对路径或不是普通文件)、`40409`、`40411`、`40906`(路径是目录)。 +**非零 code**(`ResponseType`):`40001`(不是绝对路径或不是普通文件;`details` 为 `{ path, message }[]`)、`40409`、`40411`、`40906`(路径是目录)。 #### `POST /api/v1/fs:mkdir` @@ -2259,7 +2247,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "path": string }>`。 -**非零 code**:`40001`、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 **示例**: @@ -2292,7 +2280,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-FileMeta](#t-filemeta)>`。 -**非零 code**:`40001`(multipart 未初始化或缺少 `file` 字段)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(multipart 未初始化或缺少 `file` 字段)。 **示例**: @@ -2351,7 +2339,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-SearchResponse](#t-searchresponse)>`。 -**非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法)、`50001`。 +**非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法;`details` 为 `{ path, message }[]`)、`50001`。 **示例**: @@ -2494,7 +2482,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-TranscriptResponse](#t-transcriptresponse)>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -2515,7 +2503,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -2535,7 +2523,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)>`。 -**非零 code**:`40001`、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: @@ -2556,7 +2544,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-TranscriptPlanResponse](#t-transcriptplanresponse)>`。 -**非零 code**:`40001`、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 **示例**: @@ -2664,7 +2652,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-V2SessionPage](#t-v2sessionpage)>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 -**非零 code**:`40001`(未知 `include` / `fields`、组合非法)、`40922`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知 `include` / `fields`、组合非法)、`40922`。 **示例**(`view=by_workspace`): @@ -2684,7 +2672,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-V2BatchSessionResponse](#t-v2batchsessionresponse)>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 -**非零 code**:`40001`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)。 **示例**: @@ -2745,7 +2733,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>`。 -**非零 code**:`40001`、`40408`(不存在该名称的 server)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 **示例**: @@ -2761,7 +2749,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`(校验失败,或目标条目为只读)。 +**非零 code**:`40001`(校验失败,或目标条目为只读;`details` 为 `{ path, message }[]`)。 **示例**: @@ -2777,7 +2765,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`、`40408`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 **示例**: @@ -2791,7 +2779,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`、`40408`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 **示例**: @@ -2813,7 +2801,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **返回**:`ResponseType<{ "success": boolean, "output": string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 -**非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用)、`40408`。 +**非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用;`details` 为 `{ path, message }[]`)、`40408`。 **示例**: @@ -2834,7 +2822,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **返回**:`ResponseType<[T-McpServerInspection](#t-mcpserverinspection)>` 数组。 -**非零 code**:`40001`、`40408`(`targets` 中有 locator 未匹配到任何条目)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 **示例**: @@ -2869,7 +2857,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **返回**:`ResponseType`:`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 -**非零 code**:`40001`(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 **示例**: @@ -2890,7 +2878,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **返回**:`ResponseType`。 -**非零 code**:`40001`(`flowId` 未知)、`40929`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`flowId` 未知)、`40929`。 **示例**: @@ -2924,7 +2912,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 **返回**:`ResponseType`。 -**非零 code**:`40001`、`40408`(locator 未匹配)、`40929`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`。 **示例**: From 219e9c8913f3516c9eefa129b8cf1cd31f70ceef Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:31:43 +0800 Subject: [PATCH 11/47] docs(zh): add a complete error code section with a TODO placeholder --- docs/zh/reference/server-api.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 6988dd25782..44a4348967a 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -62,8 +62,6 @@ HTTP 状态码例外(非 200): | `500xx` | 服务端内部错误 | `50001` 未捕获异常、`50003` 持久化失败 | | `6xxxx` / `7xxxx` / `8xxxx` | 工具运行时 / LLM 供应商 / MCP 透传错误,`msg` 保留上游原文 | | -完整错误码集:`0` / `40001`–`40005` / `40110`–`40113` / `40401`–`40420` / `40901`–`40929`(无 `40928`)/ `41001`–`41003` / `41301`–`41305` / `42902` / `50001`–`50004` / `60001`–`60002`;另有中间件码 `40101`(鉴权失败)与 `42901`(鉴权限流封禁)。 - ### null 与缺省语义 字段表中的「可缺省」与「可空」不等价: @@ -3194,6 +3192,10 @@ payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__glob `terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点(见 [终端](#终端))不受影响。 +## 完整错误码 + +> TODO:逐个列出全部错误码(code / 含义 / 产出端点与形态)。范围:`0` / `40001`–`40005` / `40110`–`40113` / `40401`–`40420` / `40901`–`40929`(无 `40928`)/ `41001`–`41003` / `41301`–`41305` / `42902` / `50001`–`50004` / `60001`–`60002`;另有中间件码 `40101`(鉴权失败)与 `42901`(鉴权限流封禁)。 + ## 类型汇总 端点与帧型共享的类型字典。「可缺省」表示该键可能不出现(`undefined` 被序列化丢弃),「可空」表示显式 `null`,两者语义不同(见 [null 与缺省语义](#null-与缺省语义))。 From e3c958e50ef3a768f4ae85284d4ad39df904e25f Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:32:33 +0800 Subject: [PATCH 12/47] docs(zh): link the error code ranges section to the complete error code chapter --- docs/zh/reference/server-api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 44a4348967a..755d700c12c 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -62,6 +62,8 @@ HTTP 状态码例外(非 200): | `500xx` | 服务端内部错误 | `50001` 未捕获异常、`50003` 持久化失败 | | `6xxxx` / `7xxxx` / `8xxxx` | 工具运行时 / LLM 供应商 / MCP 透传错误,`msg` 保留上游原文 | | +逐个错误码的详情见 [完整错误码](#完整错误码)。 + ### null 与缺省语义 字段表中的「可缺省」与「可空」不等价: From 73cfae28251b40854c18529d11f0a9b20164768e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:39:04 +0800 Subject: [PATCH 13/47] docs(zh): regroup the REST endpoints from 27 registry domains into 6 business domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge the flat per-registry sections into business domains (服务与账号 / 工作区与会话 / 对话 / 任务与终端 / 扩展 / 文件与其他); former sections become bold dividers inside each domain. v2 sessions and v2 MCP fold into their business domains, with the /api/v1 vs /api/v2 path prefix called out as the version marker. Endpoint headings and anchors are unchanged. --- docs/zh/reference/server-api.md | 1998 ++++++++++++++++--------------- 1 file changed, 1011 insertions(+), 987 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 755d700c12c..15133d386dc 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -85,9 +85,13 @@ HTTP 状态码例外(非 200): ## REST 端点 -下文按资源分组列出全部端点。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 +下文按业务域分组列出全部端点,覆盖 `/api/v1` 与 `/api/v2`(路径前缀区分版本)。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 -### 服务与元信息 +### 服务与账号 + +服务接入、登录与账号、全局配置、模型与供应商。 + +**服务与元信息。** 服务自身的探活、身份、关停与连接管理。 @@ -184,7 +188,156 @@ HTTP 状态码例外(非 200): { "code": 0, "msg": "success", "data": { "connections": [ { "id": "conn_01JZX4...", "connected_at": "2026-09-02T08:00:00.000Z", "remote_address": "127.0.0.1", "user_agent": "Mozilla/5.0 ...", "has_client_hello": true, "subscriptions": [ "session_..." ] } ] }, "request_id": "01JZX4..." } ``` -### 配置 +**登录与用量。** + +托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 + +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | +| `GET /api/v1/oauth/login` | 轮询登录流程状态 | +| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | +| `POST /api/v1/oauth/logout` | 登出托管供应商 | +| `GET /api/v1/oauth/usage` | 套餐用量与限额 | +| `GET /api/v1/oauth/userinfo` | 账号资料 | +| `GET /api/v1/oauth/region` | 解析客户端所属区域 | + +#### `POST /api/v1/oauth/login` + +为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | +| `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | + +**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/login` + +轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `DELETE /api/v1/oauth/login` + +取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | +| `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/oauth/logout` + +登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `logged_out` | boolean | 恒 `true` | +| `provider` | string | 被登出的供应商名 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/usage` + +托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/userinfo` + +托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/region` + +解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `region` | string | `mainland-cn` / `global` | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } +``` + +**配置。** 全局配置的读取与合并式更新;密钥字段一律脱敏。 @@ -221,7 +374,7 @@ HTTP 状态码例外(非 200): { "code": 0, "msg": "success", "data": { "default_model": "my-provider/kimi-for-coding", "yolo": true, "providers": { "...": {} } }, "request_id": "01JZX4..." } ``` -### 模型与供应商 +**模型与供应商。** 模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方指的都是这个别名 id。 @@ -459,351 +612,167 @@ HTTP 状态码例外(非 200): { "code": 0, "msg": "success", "data": { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ "..." ] }, "request_id": "01JZX4..." } ``` -### 登录与用量 - -托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 - -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | -| `GET /api/v1/oauth/login` | 轮询登录流程状态 | -| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | -| `POST /api/v1/oauth/logout` | 登出托管供应商 | -| `GET /api/v1/oauth/usage` | 套餐用量与限额 | -| `GET /api/v1/oauth/userinfo` | 账号资料 | -| `GET /api/v1/oauth/region` | 解析客户端所属区域 | - -#### `POST /api/v1/oauth/login` - -为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 - -**Body**: +### 工作区与会话 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | -| `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | +工作区与会话两个核心业务对象的生命周期。路径前缀区分版本:`/api/v1` 与 `/api/v2`。 -**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 +**工作区。** -**示例**: +工作区是已注册的项目目录,会话都落在其中。这组端点管理注册表与每工作区信任状态(控制项目级 MCP 配置是否加载),以及附加目录。返回的工作区对象统一为 [T-Workspace](#t-workspace)。 -```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } -``` +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/workspaces` | 列出已注册工作区 | +| `POST /api/v1/workspaces` | 注册工作区(按根路径幂等) | +| `PATCH /api/v1/workspaces/{workspace_id}` | 重命名 | +| `DELETE /api/v1/workspaces/{workspace_id}` | 注销(保留磁盘内容) | +| `GET /api/v1/workspaces/{workspace_id}/trust` | 读取信任状态 | +| `POST /api/v1/workspaces/{workspace_id}/trust` | 授予信任 | +| `POST /api/v1/workspaces/{workspace_id}/untrust` | 撤销信任 | +| `POST /api/v1/workspaces/{workspace_id}/add-dir` | 添加附加目录 | -#### `GET /api/v1/oauth/login` +#### `GET /api/v1/workspaces` -轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 +列出所有已注册工作区。无参数。 -**Query**: +**返回**:`ResponseType`,`data` 字段: -| 参数 | 类型 | 说明 | +| 字段 | 类型 | 说明 | | --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 +| `items` | array | [T-Workspace](#t-workspace) 数组 | **示例**: ```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 } ] }, "request_id": "01JZX4..." } ``` -#### `DELETE /api/v1/oauth/login` +#### `POST /api/v1/workspaces` -取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 +注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `root` | string | 是 | 已存在目录的绝对路径 | +| `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | -**返回**:`ResponseType`,`data` 字段: +**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | -| `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-02T08:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 0 }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/oauth/logout` +#### `PATCH /api/v1/workspaces/{workspace_id}` -登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 +重命名工作区——仅修改显示名,根路径不变。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | +| `name` | string | 是 | 新的显示名,1–100 个字符 | -**返回**:`ResponseType`,`data` 字段: +**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `logged_out` | boolean | 恒 `true` | -| `provider` | string | 被登出的供应商名 | +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "My App", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/oauth/usage` - -托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 +#### `DELETE /api/v1/workspaces/{workspace_id}` -**Query**: +注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | +**返回**:`ResponseType<{ "deleted": true }>`。 -**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 +**非零 code**:`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/oauth/userinfo` +#### `GET /api/v1/workspaces/{workspace_id}/trust` -托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/oauth/region` - -解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 +读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。无参数。 -**返回**:`ResponseType`,`data` 字段: +**返回**:`ResponseType<{ "trusted": boolean }>`。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `region` | string | `mainland-cn` / `global` | +**非零 code**:`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } ``` -### 插件 - -插件是已安装的技能、MCP 服务、hook 与命令的打包集合。这组端点管理插件从市场列表到移除的整个生命周期。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/plugins/marketplace` | 插件市场目录,合并实时安装状态 | -| `GET /api/v1/plugins` | 列出已安装插件 | -| `POST /api/v1/plugins` | 从本地路径、zip URL 或 GitHub 仓库安装插件 | -| `POST /api/v1/plugins/{plugin_id}:{action}` | 插件动作:`enable` / `disable` / `remove` | - -#### `GET /api/v1/plugins/marketplace` - -列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),当前平台不支持的能力对应条目会被剔除。无参数。 +#### `POST /api/v1/workspaces/{workspace_id}/trust` -**返回**:`ResponseType`,`data` 字段: +将工作区标记为信任,并加载其项目级 MCP 配置。无请求体。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `entries` | array | 市场条目(camelCase):`{ id, tier, displayName, description?, homepage?, keywords?, version?, source, installed?, updateAvailable?, capabilityId? }`;`tier` 为 `official` / `curated` / `third-party`;`installed` 为 `{ version?, enabled }`;`source` 即 `POST /api/v1/plugins` 的 `source` 取值 | +**返回**:`ResponseType<{ "trusted": true }>`。 -**非零 code**:`50001`(市场不可达或返回了非法目录)。 +**非零 code**:`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "entries": [ { "id": "my-plugin", "tier": "official", "displayName": "My Plugin", "source": "https://github.com/example/my-plugin", "installed": { "version": "1.2.0", "enabled": true }, "updateAvailable": false } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/plugins` +#### `POST /api/v1/workspaces/{workspace_id}/untrust` -列出已安装插件。无参数。 +撤销工作区信任,并卸载其项目级 MCP 配置。无请求体。 -**返回**:`ResponseType`,`data` 字段: +**返回**:`ResponseType<{ "trusted": false }>`。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `plugins` | array | [T-PluginSummary](#t-pluginsummary) 数组 | +**非零 code**:`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "plugins": [ { "id": "my-plugin", "displayName": "My Plugin", "version": "1.2.0", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 1, "enabledMcpServerCount": 1, "hookCount": 0, "commandCount": 1, "hasErrors": false, "source": "github" } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "trusted": false }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/plugins` +#### `POST /api/v1/workspaces/{workspace_id}/add-dir` -安装插件并返回其摘要。 +为工作区添加附加目录,语义与 CLI `--add-dir` 及 TUI `/add-dir` 一致。路径支持绝对路径、相对路径(相对工作区根目录解析)与 `~` 展开。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | - -**返回**:`ResponseType<[T-PluginSummary](#t-pluginsummary)>`。 - -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "id": "my-plugin", "displayName": "My Plugin", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 0, "enabledMcpServerCount": 0, "hookCount": 0, "commandCount": 0, "hasErrors": false, "source": "local-path" }, "request_id": "01JZX4..." } -``` - -#### `POST /api/v1/plugins/{plugin_id}:{action}` - -插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 - -**返回**:`ResponseType<{ "ok": true }>`。 - -**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40419`(没有该 id 的已安装插件)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } -``` - -### 能力 - -能力是带有分层就绪状态的内置特性——由检测步骤加后台安装组成;当前版本注册了 `kimi-cu`(Kimi Computer Use)与 `kimi-webbridge`(Kimi WebBridge)。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/capabilities` | 列出内置能力及其就绪状态 | -| `GET /api/v1/capabilities/{capability_id}` | 读取单个能力的状态 | -| `POST /api/v1/capabilities/{capability_id}:install` | 开始安装能力(后台进行,轮询 GET 查看进度) | - -#### `GET /api/v1/capabilities` - -列出所有已注册能力及其就绪状态。无参数。 - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `capabilities` | array | [T-CapabilityStatus](#t-capabilitystatus) 数组 | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "capabilities": [ { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "ready", "steps": [ { "id": "os", "state": "ok" } ], "install": { "running": false } } ] }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/capabilities/{capability_id}` - -读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 - -**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 - -**非零 code**:`40418`(没有该 id 的能力)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "partial", "steps": [ { "id": "app", "state": "missing", "optional": true } ], "install": { "running": true, "percent": 40 } }, "request_id": "01JZX4..." } -``` - -#### `POST /api/v1/capabilities/{capability_id}:install` - -在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 - -**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 - -**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "not_installed", "steps": [ "..." ], "install": { "running": true, "step": "download", "percent": 0 } }, "request_id": "01JZX4..." } -``` - -### 工具与 MCP(v1) - -当前生效 Agent 的工具列表及其 MCP 服务;管理 MCP 服务的完整面在 [v2 MCP](#v2-mcp)。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/tools` | 列出当前生效 Agent 的工具 | -| `GET /api/v1/mcp/servers` | 列出 MCP 服务 | -| `POST /api/v1/mcp/servers/{mcp_server_id}:restart` | 重启 MCP 服务 | - -#### `GET /api/v1/tools` - -列出当前生效 Agent 的工具——即 `session_id` 指定会话的 main agent;省略参数时取最近创建的存活会话。会话不在本服务进程中存活时列表为空。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `session_id` | string | 要查看其 main agent 的会话。默认最近创建的存活会话 | - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `tools` | array | [T-ToolDescriptor](#t-tooldescriptor) 数组 | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "tools": [ { "name": "Bash", "description": "...", "input_schema": null, "source": "builtin", "active": true } ] }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/mcp/servers` - -列出当前生效 Agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同的会话选取规则);没有存活会话时列表为空。无参数。 +| `path` | string | 是 | 要添加的目录 | +| `persist` | boolean | 否 | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | **返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | -| `servers` | array | [T-McpServer](#t-mcpserver) 数组 | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "servers": [ { "id": "my-server", "name": "my-server", "transport": "stdio", "status": "connected", "tool_count": 5 } ] }, "request_id": "01JZX4..." } -``` - -#### `POST /api/v1/mcp/servers/{mcp_server_id}:restart` - -重新连接当前生效 Agent 的某个 MCP 服务。经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作。无请求体。 - -**返回**:`ResponseType<{ "restarting": true }>`。 +| `project_root` | string | 项目根目录 | +| `config_path` | string | 写入的本地配置文件路径 | +| `additional_dirs` | array | 全部附加目录(含既有目录) | +| `persisted` | boolean | 本次是否写盘 | -**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 +**非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误;`details` 为 `{ path, message }[]`)、`40409`(`path` 不存在或不是目录)、`40410`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "restarting": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "project_root": "/Users/dev/my-app", "config_path": "/Users/dev/my-app/.kimi-code/local.toml", "additional_dirs": [ "/Users/dev/shared-lib" ], "persisted": true }, "request_id": "01JZX4..." } ``` -### 会话 +**会话。** 创建、列出和查看会话,执行会话级动作,并读取会话级汇总。返回的会话对象统一为 [T-Session](#t-session);其实时状态字段(`busy`、`main_turn_active`、`pending_interaction`、`last_turn_reason`)由会话的活动聚合解析——未加载到本服务进程中的会话(冷会话)始终上报为不忙碌且无待处理交互。 @@ -1072,7 +1041,7 @@ main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复 { "code": 0, "msg": "success", "data": { "warnings": [ { "code": "agents-md-oversized", "message": "AGENTS.md is ...", "severity": "warning" } ] }, "request_id": "01JZX4..." } ``` -### 运行时绑定 +**运行时绑定。** main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 @@ -1120,7 +1089,23 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 { "code": 0, "msg": "success", "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, "request_id": "01JZX4..." } ``` -### 会话导出 +**会话快照。** + +#### `GET /api/v1/sessions/{session_id}/snapshot` + +为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 + +**返回**:`ResponseType<[T-SnapshotResponse](#t-snapshotresponse)>`。 + +**非零 code**:`40401`、`50001`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "as_of_seq": 128, "epoch": "01JZX4...", "session": { "id": "session_01JZX4...", "agent_config": { "model": "kimi-for-coding" }, "usage": { "input_tokens": 152000, "...": 0 }, "...": "..." }, "messages": { "items": [ "..." ], "has_more": true }, "in_flight_turn": null, "subagents": [], "pending_approvals": [], "pending_questions": [] }, "request_id": "01JZX4..." } +``` + +**会话导出。** #### `POST /api/v1/sessions/{session_id}/export` @@ -1135,53 +1120,139 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 **非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`50001`。 -### 消息 +**文件历史(实验性)。** + +::: info 新增 +实验特性:由 `KIMI_CODE_EXPERIMENTAL_FILE_HISTORY` 开关控制(默认关闭),接口形态可能随版本更改。 +::: -`messages` 端点分页返回 main agent 的扁平化消息历史;按 Agent 组织的结构化转录见 [转录](#转录)。 +按轮次记录的文件历史快照:main agent 每个轮次在开始与结束两个检查点版本化所有被 Edit / Write 工具触碰的文件(未变化的文件按内容哈希去重,超过 4 MiB 的文件只记录哨兵指纹)。这两个端点从检查点计算单个轮次的逐文件增删行数与任一检查点的完整内容;冷会话会按需恢复。开关关闭时路由仍注册,但 `changes` 恒返回空列表、`enabled` 恒为 `false`、`content` 恒为 `null`。 | 方法与路径 | 说明 | | --- | --- | -| `GET /api/v1/sessions/{session_id}/messages` | 消息分页(`before_id` / `after_id` / `role`) | -| `GET /api/v1/sessions/{session_id}/messages/{message_id}` | 读取单条消息 | +| `GET /api/v1/sessions/{session_id}/file-history/changes` | 单个轮次的逐文件增删统计 | +| `GET /api/v1/sessions/{session_id}/file-history/content` | 某文件在指定检查点的完整内容 | -#### `GET /api/v1/sessions/{session_id}/messages` +#### `GET /api/v1/sessions/{session_id}/file-history/changes` -分页返回 main agent 的消息历史,最新在前;读取历史会在会话为冷态时将其恢复。 +返回单个轮次开始与结束检查点之间每个文件的精确增删行数。 **Query**: | 参数 | 类型 | 说明 | | --- | --- | --- | -| `before_id` | string | 只保留早于该消息 id 的消息;与 `after_id` 互斥 | -| `after_id` | string | 只保留晚于该消息 id 的消息;与 `before_id` 互斥 | -| `page_size` | integer | 1–100。默认 `50` | -| `role` | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | +| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | -**返回**:`ResponseType<{ items: T-Message[], has_more: boolean }>`([T-Message](#t-message))。 +**返回**:`ResponseType`,`data` 字段: -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `changes` | array | `{ path, status, additions, deletions, binary?, oversize? }[]`;`status` 为 `added` / `modified` / `deleted`;二进制与超大文件的增删行为 `0`,并以 `binary` / `oversize` 标记 | +| `enabled` | boolean | 实验开关是否开启 | +| `recorded` | boolean | 该轮次是否有已记录的检查点 | + +**非零 code**:`40401`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "assistant", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:05:00.000Z" } ], "has_more": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "changes": [ { "path": "src/index.ts", "status": "modified", "additions": 12, "deletions": 3 } ], "enabled": true, "recorded": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/messages/{message_id}` - -按 id 从同一历史中读取单条消息。无参数。 +#### `GET /api/v1/sessions/{session_id}/file-history/content` -**返回**:`ResponseType<[T-Message](#t-message)>`。 +返回某文件在指定轮次检查点的完整内容;`phase: "end"` 时若该文件在结束检查点没有记录,回退到开始检查点的版本。 -**非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 +**Query**: -**示例**: +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | +| `path` | string | **必填。** 文件路径 | +| `phase` | string | `start`(默认)/ `end`——取轮次开始还是结束检查点 | + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `content` | object \| null | `{ version, content?, binary? }`——`version` 为该文件在检查点的版本号;二进制文件只携带 `binary: true` 不携带文本;无记录时为 `null` | + +**非零 code**:`40401`。 + +**示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "user", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "content": { "version": 2, "content": "import ..." } }, "request_id": "01JZX4..." } +``` + +**v2 会话。** + +`/api/v2` 的会话查询与批量管理。与 v1 共享 `ResponseType` 与错误约定;分页为绑定查询指纹的 `page_token`(见 [分页](#分页))。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v2/sessions` | 新一代会话列表:筛选、排序、字段组、分组视图 | +| `POST /api/v2/sessions:archive` | 批量归档会话 | +| `POST /api/v2/sessions:restore` | 批量恢复已归档会话 | + +#### `GET /api/v2/sessions` + +面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `workspace.id` | string | 按工作区过滤,可重复 | +| `activity.status` | string | 按活动状态过滤:`running` / `approval` / `question` / `failed` / `idle`,可重复 | +| `meta.updated_after` | integer | 只看该时间(epoch 毫秒)之后更新过的会话 | +| `meta.updated_before` | integer | 只看该时间(epoch 毫秒)之前更新过的会话 | +| `meta.archived` | string | `true` / `false`(默认)/ `all` | +| `meta.has_prompt` | string | `true` 只保留有用户 prompt 的会话,`false` 只保留空会话(等价 v1 的 `exclude_empty`) | +| `view` | string | `flat`(默认)/ `by_workspace`(按工作区分组) | +| `group.page_size` | integer | `view=by_workspace` 时每个工作区返回的会话数:1–100,默认 `5`(`id,archived` 投影时上限 10000);未开分组视图时传入返回 `40001` | +| `sort` | string | `meta.updated_at_desc`(默认)/ `meta.updated_at_asc` / `meta.created_at_desc` | +| `include` | string | 逗号分隔的附加字段组;目前支持 `git`(分支与 PR 信息,按目录去重并缓存 60 秒) | +| `fields` | string | 逗号分隔的字段投影;目前仅支持 `id,archived`,每项裁剪为 `{ id, archived }`。不可与 `include=git` 同传(`40001`) | +| `page_size` | integer | 1–100,默认 `50`;`id,archived` 投影时上限放宽至 10000。`view=by_workspace` 时按组计数 | +| `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | +| `page_token` | string | 上一页返回的翻页令牌 | + +**返回**:`ResponseType<[T-V2SessionPage](#t-v2sessionpage)>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知 `include` / `fields`、组合非法)、`40922`。 + +**示例**(`view=by_workspace`): + +```json +{ "code": 0, "msg": "success", "data": { "groups": [ { "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "sessions": [ { "id": "session_01JZX4...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ], "total": 42 } ], "total": 7, "has_more": true, "next_page_token": "eyJ2IjoxLCJmIjoi..." }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v2/sessions:archive` 与 `POST /api/v2/sessions:restore` + +面向会话管理页的批量归档 / 恢复。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | + +**返回**:`ResponseType<[T-V2BatchSessionResponse](#t-v2batchsessionresponse)>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "results": [ { "id": "session_a", "ok": true }, { "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } } ], "succeeded": 1, "failed": 1 }, "request_id": "01JZX4..." } ``` -### 提示词 +### 对话 + +驱动一轮对话:提交提示词、流式消息、审批与提问交互、转录。 + +**提示词。** 提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列;轮次进度通过 [WebSocket 帧](#websocket-帧) 推送,不经过这些端点。 @@ -1289,7 +1360,53 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 0, "msg": "success", "data": { "aborted": true }, "request_id": "01JZX4..." } ``` -### 审批 +**消息。** + +`messages` 端点分页返回 main agent 的扁平化消息历史;按 Agent 组织的结构化转录见「对话」域的 [转录](#对话) 部分。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/messages` | 消息分页(`before_id` / `after_id` / `role`) | +| `GET /api/v1/sessions/{session_id}/messages/{message_id}` | 读取单条消息 | + +#### `GET /api/v1/sessions/{session_id}/messages` + +分页返回 main agent 的消息历史,最新在前;读取历史会在会话为冷态时将其恢复。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `before_id` | string | 只保留早于该消息 id 的消息;与 `after_id` 互斥 | +| `after_id` | string | 只保留晚于该消息 id 的消息;与 `before_id` 互斥 | +| `page_size` | integer | 1–100。默认 `50` | +| `role` | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | + +**返回**:`ResponseType<{ items: T-Message[], has_more: boolean }>`([T-Message](#t-message))。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "items": [ { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "assistant", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:05:00.000Z" } ], "has_more": true }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/messages/{message_id}` + +按 id 从同一历史中读取单条消息。无参数。 + +**返回**:`ResponseType<[T-Message](#t-message)>`。 + +**非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "user", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "request_id": "01JZX4..." } +``` + +**审批。** 审批是为工具调用请求许可的待处理交互。新的请求通过 WebSocket 以 `event.approval.requested` 到达;这两个端点用于列出和答复。 @@ -1345,7 +1462,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 0, "msg": "success", "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:00.000Z" }, "request_id": "01JZX4..." } ``` -### 提问 +**提问。** 提问是请求带标签选项的结构化输入的待处理交互。新的请求通过 WebSocket 以 `event.question.requested` 到达。 @@ -1425,7 +1542,107 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 40909, "msg": "question dismissed", "data": { "dismissed": true, "dismissed_at": "2026-09-02T08:07:20.000Z" }, "request_id": "01JZX4..." } ``` -### 后台任务 +**转录。** + +`transcript` 端点提供按 Agent 组织的结构化转录——轮次、任务、交互、附件——即 WebSocket [transcript 帧](#transcript-帧) 实时流式推送的内容。历史分页与补漏用这些端点,实时尾部用 WebSocket 订阅。转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约([T-Transcript 族](#t-transcript-族))。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/sessions/{session_id}/transcript` | 按轮次分页的转录(需 `agent_id`) | +| `GET /api/v1/sessions/{session_id}/transcript/ops` | op 批次补漏(`since_seq`) | +| `GET /api/v1/sessions/{session_id}/transcript/user-messages` | 各轮次起始的用户输入,不分页 | +| `GET /api/v1/sessions/{session_id}/transcript/plan` | ExitPlanMode 计划内容、路径与审阅结果 | + +#### `GET /api/v1/sessions/{session_id}/transcript` + +返回某个 Agent 的结构化转录中的一页:轮次(含其步骤与帧)以及轮次之间的标记与任务引用。活跃会话从内存存储应答(先回填所请求 Agent 的持久化历史);冷会话则从持久化的线上记录重建 Agent。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | **必填。** 要读取其转录的 Agent;必须是纯文本形式的 agent id(字母、数字、`.`、`_`、`-`,不含路径分隔符) | +| `before_turn` | string | 只保留早于该轮次 id 的轮次;与 `after_turn` 互斥 | +| `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | +| `page_size` | integer | 1–100 个轮次。默认 `20` | + +**返回**:`ResponseType<[T-TranscriptResponse](#t-transcriptresponse)>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "items": [ { "kind": "turn", "turnId": 3, "...": "..." } ], "has_more": true, "tasks": [], "interactions": [], "attachments": [], "todos": [], "prompts": [], "meta": { "...": "..." }, "agents": [ { "agentId": "main", "...": "..." } ], "pending_interactions": [], "seq": 42 }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/transcript/ops` + +从服务端的 op 日志提供点对点的补漏:某个 Agent 的 `seq > since_seq` 的已记录 op 批次,最旧在前。它是 `transcript_since` 恢复游标的 REST 对应物,共享同一份有界日志,因此适用相同的回退规则。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | **必填。** Agent id(纯文本形式) | +| `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | + +**返回**:`ResponseType<[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "batches": [ { "seq": 41, "ops": [ { "op": "append", "...": "..." } ] } ], "latest_seq": 42, "complete": true }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/transcript/user-messages` + +列出会话中每个开启轮次的输入,按 Agent 分组且不分页:真实用户文本、以斜杠命令形式使用的 Skill 与插件命令、以及 cron 提示词——可通过 `origin` 区分——另有仅含附件的提示词,其 `prompt` 投影为空。所列消息引用的附件实体会随响应一起返回(仅元数据,绝不包含字节内容)。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | + +**返回**:`ResponseType<[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)>`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "agents": [ { "agent_id": "main", "messages": [ { "turn_id": 3, "ordinal": 0, "state": "completed", "origin": { "kind": "user" }, "prompt": "adjust the button spacing", "started_at": "2026-09-02T08:04:00.000Z" } ], "attachments": [] } ] }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/sessions/{session_id}/transcript/plan` + +按时间线顺序读取某个 Agent 的 `ExitPlanMode` 工具调用的计划信息——计划内容、计划文件路径、提供的选项以及审阅结果。内容投影自第一个可用的事实来源:关联的审批交互(交互式审阅)、实时工具帧的展示(auto 模式),或工具结果的输出文本;每个条目在 `source` 中记录具体来源。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `agent_id` | string | **必填。** Agent id(纯文本形式) | +| `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | + +**返回**:`ResponseType<[T-TranscriptPlanResponse](#t-transcriptplanresponse)>`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "agent_id": "main", "plans": [ { "tool_call_id": "toolu_01J...", "turn_id": 2, "source": "interaction", "plan": "# Plan\n ...", "path": "/Users/dev/my-app/.kimi-code/plans/....md", "options": [ { "label": "实施" } ], "review": { "state": "approved", "selected_option": "实施" } } ] }, "request_id": "01JZX4..." } +``` + +### 任务与终端 + +后台任务与终端。 + +**后台任务。** 后台任务是会话的异步单元——后台 Shell、subagent 与长时间运行的工具任务。注册表仅包含实时数据:未加载到本服务进程中的会话会返回空列表。 @@ -1494,7 +1711,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 0, "msg": "success", "data": { "detached": true, "status": "running" }, "request_id": "01JZX4..." } ``` -### 终端 +**终端。** PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定会跳过它们,除非传入 `--allow-remote-terminals`)。注意:终端输入输出的 `terminal_*` WebSocket 帧当前是死协议(见 [terminal 帧](#terminal-帧))——REST 侧只管理终端生命周期。 @@ -1575,7 +1792,11 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 { "code": 0, "msg": "success", "data": { "closed": true }, "request_id": "01JZX4..." } ``` -### 技能 +### 扩展 + +技能、插件、能力与 MCP。路径前缀区分版本:`/api/v1` 与 `/api/v2`。 + +**技能。** 会话或工作区可见的技能目录,以及技能激活——激活即斜杠命令 `/` 的 REST 等价形式。 @@ -1638,1263 +1859,1070 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 { "code": 0, "msg": "success", "data": { "activated": true, "skill_name": "review" }, "request_id": "01JZX4..." } ``` -### 工作区 +**插件。** -工作区是已注册的项目目录,会话都落在其中。这组端点管理注册表与每工作区信任状态(控制项目级 MCP 配置是否加载),以及附加目录。返回的工作区对象统一为 [T-Workspace](#t-workspace)。 +插件是已安装的技能、MCP 服务、hook 与命令的打包集合。这组端点管理插件从市场列表到移除的整个生命周期。 | 方法与路径 | 说明 | | --- | --- | -| `GET /api/v1/workspaces` | 列出已注册工作区 | -| `POST /api/v1/workspaces` | 注册工作区(按根路径幂等) | -| `PATCH /api/v1/workspaces/{workspace_id}` | 重命名 | -| `DELETE /api/v1/workspaces/{workspace_id}` | 注销(保留磁盘内容) | -| `GET /api/v1/workspaces/{workspace_id}/trust` | 读取信任状态 | -| `POST /api/v1/workspaces/{workspace_id}/trust` | 授予信任 | -| `POST /api/v1/workspaces/{workspace_id}/untrust` | 撤销信任 | -| `POST /api/v1/workspaces/{workspace_id}/add-dir` | 添加附加目录 | +| `GET /api/v1/plugins/marketplace` | 插件市场目录,合并实时安装状态 | +| `GET /api/v1/plugins` | 列出已安装插件 | +| `POST /api/v1/plugins` | 从本地路径、zip URL 或 GitHub 仓库安装插件 | +| `POST /api/v1/plugins/{plugin_id}:{action}` | 插件动作:`enable` / `disable` / `remove` | -#### `GET /api/v1/workspaces` +#### `GET /api/v1/plugins/marketplace` -列出所有已注册工作区。无参数。 +列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),当前平台不支持的能力对应条目会被剔除。无参数。 **返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-Workspace](#t-workspace) 数组 | +| `entries` | array | 市场条目(camelCase):`{ id, tier, displayName, description?, homepage?, keywords?, version?, source, installed?, updateAvailable?, capabilityId? }`;`tier` 为 `official` / `curated` / `third-party`;`installed` 为 `{ version?, enabled }`;`source` 即 `POST /api/v1/plugins` 的 `source` 取值 | + +**非零 code**:`50001`(市场不可达或返回了非法目录)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "entries": [ { "id": "my-plugin", "tier": "official", "displayName": "My Plugin", "source": "https://github.com/example/my-plugin", "installed": { "version": "1.2.0", "enabled": true }, "updateAvailable": false } ] }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/workspaces` +#### `GET /api/v1/plugins` -注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 +列出已安装插件。无参数。 -**Body**: +**返回**:`ResponseType`,`data` 字段: -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `root` | string | 是 | 已存在目录的绝对路径 | -| `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | - -**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 - -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `plugins` | array | [T-PluginSummary](#t-pluginsummary) 数组 | **示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-02T08:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 0 }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "plugins": [ { "id": "my-plugin", "displayName": "My Plugin", "version": "1.2.0", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 1, "enabledMcpServerCount": 1, "hookCount": 0, "commandCount": 1, "hasErrors": false, "source": "github" } ] }, "request_id": "01JZX4..." } ``` -#### `PATCH /api/v1/workspaces/{workspace_id}` +#### `POST /api/v1/plugins` -重命名工作区——仅修改显示名,根路径不变。 +安装插件并返回其摘要。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `name` | string | 是 | 新的显示名,1–100 个字符 | +| `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | -**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 +**返回**:`ResponseType<[T-PluginSummary](#t-pluginsummary)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "My App", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "my-plugin", "displayName": "My Plugin", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 0, "enabledMcpServerCount": 0, "hookCount": 0, "commandCount": 0, "hasErrors": false, "source": "local-path" }, "request_id": "01JZX4..." } ``` -#### `DELETE /api/v1/workspaces/{workspace_id}` +#### `POST /api/v1/plugins/{plugin_id}:{action}` -注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 +插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 -**返回**:`ResponseType<{ "deleted": true }>`。 +**返回**:`ResponseType<{ "ok": true }>`。 -**非零 code**:`40410`。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40419`(没有该 id 的已安装插件)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/workspaces/{workspace_id}/trust` +**能力。** -读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。无参数。 +能力是带有分层就绪状态的内置特性——由检测步骤加后台安装组成;当前版本注册了 `kimi-cu`(Kimi Computer Use)与 `kimi-webbridge`(Kimi WebBridge)。 -**返回**:`ResponseType<{ "trusted": boolean }>`。 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/capabilities` | 列出内置能力及其就绪状态 | +| `GET /api/v1/capabilities/{capability_id}` | 读取单个能力的状态 | +| `POST /api/v1/capabilities/{capability_id}:install` | 开始安装能力(后台进行,轮询 GET 查看进度) | -**非零 code**:`40410`。 +#### `GET /api/v1/capabilities` + +列出所有已注册能力及其就绪状态。无参数。 + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `capabilities` | array | [T-CapabilityStatus](#t-capabilitystatus) 数组 | **示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "capabilities": [ { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "ready", "steps": [ { "id": "os", "state": "ok" } ], "install": { "running": false } } ] }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/workspaces/{workspace_id}/trust` +#### `GET /api/v1/capabilities/{capability_id}` -将工作区标记为信任,并加载其项目级 MCP 配置。无请求体。 +读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 -**返回**:`ResponseType<{ "trusted": true }>`。 +**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 -**非零 code**:`40410`。 +**非零 code**:`40418`(没有该 id 的能力)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "partial", "steps": [ { "id": "app", "state": "missing", "optional": true } ], "install": { "running": true, "percent": 40 } }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/workspaces/{workspace_id}/untrust` +#### `POST /api/v1/capabilities/{capability_id}:install` -撤销工作区信任,并卸载其项目级 MCP 配置。无请求体。 +在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 -**返回**:`ResponseType<{ "trusted": false }>`。 +**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 -**非零 code**:`40410`。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "not_installed", "steps": [ "..." ], "install": { "running": true, "step": "download", "percent": 0 } }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/workspaces/{workspace_id}/add-dir` +**工具与 MCP(v1)。** -为工作区添加附加目录,语义与 CLI `--add-dir` 及 TUI `/add-dir` 一致。路径支持绝对路径、相对路径(相对工作区根目录解析)与 `~` 展开。 +当前生效 Agent 的工具列表及其 MCP 服务;管理 MCP 服务的完整面在「扩展」域的 [v2 MCP](#扩展) 部分。 -**Body**: +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/tools` | 列出当前生效 Agent 的工具 | +| `GET /api/v1/mcp/servers` | 列出 MCP 服务 | +| `POST /api/v1/mcp/servers/{mcp_server_id}:restart` | 重启 MCP 服务 | -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 要添加的目录 | -| `persist` | boolean | 否 | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | +#### `GET /api/v1/tools` + +列出当前生效 Agent 的工具——即 `session_id` 指定会话的 main agent;省略参数时取最近创建的存活会话。会话不在本服务进程中存活时列表为空。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `session_id` | string | 要查看其 main agent 的会话。默认最近创建的存活会话 | **返回**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | -| `project_root` | string | 项目根目录 | -| `config_path` | string | 写入的本地配置文件路径 | -| `additional_dirs` | array | 全部附加目录(含既有目录) | -| `persisted` | boolean | 本次是否写盘 | - -**非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误;`details` 为 `{ path, message }[]`)、`40409`(`path` 不存在或不是目录)、`40410`。 +| `tools` | array | [T-ToolDescriptor](#t-tooldescriptor) 数组 | **示例**: ```json -{ "code": 0, "msg": "success", "data": { "project_root": "/Users/dev/my-app", "config_path": "/Users/dev/my-app/.kimi-code/local.toml", "additional_dirs": [ "/Users/dev/shared-lib" ], "persisted": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "tools": [ { "name": "Bash", "description": "...", "input_schema": null, "source": "builtin", "active": true } ] }, "request_id": "01JZX4..." } ``` -### 文件系统 - -会话内文件操作走 `POST /api/v1/sessions/{session_id}/fs:{action}`,请求体为 JSON;另有工作区级与本机级的补充端点。每个动作的请求体还接受可选的 `runtime_id`(string,默认 `local`),用于选择执行操作的运行时;`search`、`grep`、`git_status` 与 `diff` 额外要求运行时具备 process capability(进程执行能力),`open`、`open-in` 与 `reveal` 仅在 `local` 运行时上可用。 - -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/sessions/{session_id}/fs:{action}` | 会话内文件操作:`list` / `read` / `list_many` / `stat` / `stat_many` / `mkdir` / `search` / `grep` / `git_status` / `diff` / `open` / `open-in` / `reveal` | -| `POST /api/v1/workspace/fs:search` | 无会话的工作区搜索(body 携带工作区引用) | -| `POST /api/v1/workspace/fs:suggest` | 无会话的文件补全候选(用于 `@` 文件提及) | -| `POST /api/v1/fs:suggest` | 跨根目录的文件补全候选(body 携带 `roots`) | -| `GET /api/v1/sessions/{session_id}/fs/{path}:download` | 下载会话文件(二进制) | -| `GET /api/v1/fs:browse` | 列出本机目录(文件夹选择器用) | -| `GET /api/v1/fs:home` | 用户主目录与最近工作区 | -| `GET /api/v1/fs:content` | 读取本机任意文件原始字节(仅受 token 保护,谨慎暴露端口) | -| `POST /api/v1/fs:mkdir` | 按绝对路径创建目录 | - -#### `POST /api/v1/sessions/{session_id}/fs:list` - -列出会话工作区目录下的条目,可选递归子目录。 - -**Body**: +#### `GET /api/v1/mcp/servers` -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 否 | 要列出的目录,相对于会话工作目录。默认 `.` | -| `depth` | integer | 否 | 递归深度,1–10。默认 `1` | -| `limit` | integer | 否 | 最大条目数,1–1000。默认 `200` | -| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | -| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -| `exclude_globs` | array | 否 | 额外要跳过的 glob | -| `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | -| `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | +列出当前生效 Agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同的会话选取规则);没有存活会话时列表为空。无参数。 -**返回**:`ResponseType<[T-FsListResponse](#t-fslistresponse)>`。 +**返回**:`ResponseType`,`data` 字段: -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `servers` | array | [T-McpServer](#t-mcpserver) 数组 | **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src", "name": "src", "kind": "directory", "modified_at": "2026-09-01T10:00:00.000Z", "child_count": 12 }, { "path": "package.json", "name": "package.json", "kind": "file", "size": 1024, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "application/json" } ], "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "servers": [ { "id": "my-server", "name": "my-server", "transport": "stdio", "status": "connected", "tool_count": 5 } ] }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:read` - -以文本或 base64 读取会话文件的一段内容。`encoding: "auto"` 时文本以 `utf-8` 返回(非 UTF-8 文本会被转码),二进制内容以 `base64` 返回;`encoding: "utf-8"` 强制按文本读取并拒绝二进制文件。 - -**Body**: +#### `POST /api/v1/mcp/servers/{mcp_server_id}:restart` -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 文件路径,相对于会话工作目录 | -| `offset` | integer | 否 | 起始字节偏移。默认 `0` | -| `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | -| `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | +重新连接当前生效 Agent 的某个 MCP 服务。经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作。无请求体。 -**返回**:`ResponseType<[T-FsReadResponse](#t-fsreadresponse)>`。 +**返回**:`ResponseType<{ "restarting": true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 +**非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "content": "import ...", "encoding": "utf-8", "size": 20480, "truncated": false, "etag": "...", "mime": "text/typescript", "language_id": "typescript", "line_count": 512, "is_binary": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "restarting": true }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:list_many` +**v2 MCP。** -一次调用列出多个会话目录;失败的路径折进响应里,而不是让整个请求失败。 +`/api/v2/mcp/*` 是统一的 MCP 管理面:独立于任何会话,直接管理 MCP server 注册表本身——全局(用户级)CRUD 与逐条校验、连接测试探测、locator 寻址的检查目录、按 server 的授权状态列表,以及完整的 OAuth 流程生命周期。响应该组一律不包 `{ items }`:`data` 直接为数组或对象。 -**Body**: +该管理面有两种寻址方式。CRUD 路由与 `servers:test` 使用普通的运行时 `name`;检查与 OAuth 路由使用 **locator**——文件层条目用 `{ "source": "global", "name" }`,插件清单条目用 `{ "source": "plugin", "pluginId", "serverName" }`——因为插件条目和文件条目可能共用同一个运行时名称。检查条目还带有一个稳定的 `serverId` 线上标识:`global:` 或 `plugin::`(URL 编码)。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `paths` | array | 是 | 要列出的目录,1–100 条 | +大多数路由接受可选的 `cwd`(查询参数,`:`-action 路由则为请求体字段)。不传时目录只覆盖用户级文件与插件清单;传入后,该目录的项目根层与项目本地层会并入——但仅当工作区受信任时,否则项目层会被跳过。对 stdio server 执行 `servers:test` 时,`cwd` 同时是子进程的工作目录。 -其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v2/mcp/servers` | 列出所有已知 MCP server | +| `GET /api/v2/mcp/servers/{name}` | 按运行时名称获取单个 server | +| `POST /api/v2/mcp/servers` | 向用户级 `mcp.json` 添加 server | +| `PUT /api/v2/mcp/servers/{name}` | 替换一个用户级条目 | +| `DELETE /api/v2/mcp/servers/{name}` | 删除一个用户级条目 | +| `POST /api/v2/mcp/servers:test` | 对单个 server 发起真实连接探测 | +| `POST /api/v2/mcp/servers:inspect` | locator 寻址的目录及批量连接探测 | +| `GET /api/v2/mcp/auth-statuses` | 目录中各 server 的 OAuth 状态 | +| `POST /api/v2/mcp/auth:begin` | 开始一次交互式 OAuth 流程 | +| `POST /api/v2/mcp/auth:complete` | 等待浏览器回调并完成 code 交换 | +| `POST /api/v2/mcp/auth:cancel` | 终止已开始的 OAuth 流程 | +| `POST /api/v2/mcp/auth:reset` | 清除某个 server 已存储的凭据 | -**返回**:`ResponseType<[T-FsListManyResponse](#t-fslistmanyresponse)>`。 +#### `GET /api/v2/mcp/servers` -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +列出管理面已知的全部 MCP server。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | + +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "results": { "src": [ { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." } ] }, "truncated_paths": [ "src" ], "partial_errors": { "vendor": { "code": 40409, "msg": "path does not exist" } } }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ], "envKeys": [ "API_KEY" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true } ], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:stat` +#### `GET /api/v2/mcp/servers/{name}` -查询会话工作区内单个路径的元信息。 +按运行时名称获取单个 server。 -**Body**: +**Query**: -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 要查询的路径,相对于会话工作目录 | +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "size": 20480, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "text/typescript", "is_binary": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:stat_many` - -一次调用查询多个会话路径的元信息;不存在的路径返回 `null`,不会让整个请求失败。 +#### `POST /api/v2/mcp/servers` -**Body**: +向用户级 `mcp.json` 添加 server。若写入与项目层的同名条目冲突,会因只读被拒绝;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `paths` | array | 是 | 要查询的路径,1–1000 条 | +**Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 -**返回**:`ResponseType<[T-FsStatManyResponse](#t-fsstatmanyresponse)>`。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败,或目标条目为只读;`details` 为 `{ path, message }[]`)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "entries": { "src/index.ts": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." }, "vendor": null } }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:mkdir` - -在会话工作区内创建目录。 +#### `PUT /api/v2/mcp/servers/{name}` -**Body**: +替换一个用户级条目;身份由路径指定。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 要创建的目录,相对于会话工作目录 | -| `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | +**Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 -**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`(所建目录)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "docs/api", "name": "api", "kind": "directory", "modified_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "http", "url": "https://mcp.example.com" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:search` +#### `DELETE /api/v2/mcp/servers/{name}` -在会话工作区内模糊搜索文件与目录名。`query` 为空时改为列出顶层条目。当 `{session_id}` 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 `POST /api/v1/workspace/fs:search`。 +删除一个用户级条目。无请求体。 -**Body**: - -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | -| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | -| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | - -**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 +**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:grep` +#### `POST /api/v2/mcp/servers:test` -在会话工作区内搜索文件内容——默认按字面字符串,`regex: true` 时按正则表达式。 +对单个 server 发起真实连接探测,不持久化任何内容。传 `name` 探测注册表条目(含插件与受信任的项目层),或传 `server`(包含 `name` 的完整内联配置)按原样探测;两者都传或都不传会报 `40001`。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `pattern` | string | 是 | 要搜索的文本或正则 | -| `regex` | boolean | 否 | 将 `pattern` 视为正则表达式。默认 `false` | -| `case_sensitive` | boolean | 否 | 默认 `true` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的文件 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的文件 | -| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -| `max_files` | integer | 否 | 最多扫描的文件数,1–10000。默认 `200` | -| `max_matches_per_file` | integer | 否 | 每个文件保留的匹配数,1–10000。默认 `50` | -| `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | -| `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | +| `name` | string | 二选一 | 注册表条目的运行时名称 | +| `server` | object | 二选一 | 按原样探测的内联 server 配置(含 `name`) | +| `cwd` | string | 否 | 项目层并入解析;同时是 stdio 的工作目录 | -**返回**:`ResponseType<[T-FsGrepResponse](#t-fsgrepresponse)>`。 +**返回**:`ResponseType<{ "success": boolean, "output": string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 +**非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用;`details` 为 `{ path, message }[]`)、`40408`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "files": [ { "path": "src/index.ts", "matches": [ { "line": 12, "col": 8, "text": "const token = ...", "before": [ "..." ], "after": [ "..." ] } ] } ], "files_scanned": 87, "truncated": false, "elapsed_ms": 42 }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "success": true, "output": "5 tools: search, fetch, ..." }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:git_status` +#### `POST /api/v2/mcp/servers:inspect` -读取会话工作区的 git 状态,可选限定在一组路径内。 +locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 `unavailable` 并在 `error` 中给出说明;探测遇到过期授权时,可能刷新或作废已存储的凭据。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | +| `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | +| `cwd` | string | 否 | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<[T-FsGitStatusResponse](#t-fsgitstatusresponse)>`(注意 camelCase `pullRequest`)。 +**返回**:`ResponseType<[T-McpServerInspection](#t-mcpserverinspection)>` 数组。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "branch": "main", "ahead": 1, "behind": 0, "entries": { "src/index.ts": "modified" }, "additions": 12, "deletions": 3, "pullRequest": { "number": 3451, "state": "open", "url": "https://github.com/example/repo/pull/3451" } }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [ { "serverId": "global:my-server", "locator": { "source": "global", "name": "my-server" }, "runtimeName": "my-server", "origin": "global", "config": { "transport": "http", "url": "https://mcp.example.com" }, "enabled": true, "editable": true, "authStatus": "oauth-authorized", "checkedAt": 1787000000000 } ], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:diff` - -返回会话工作区内单个文件的 unified git diff。 +#### `GET /api/v2/mcp/auth-statuses` -**Body**: +注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 `servers:inspect` 更轻量的选择。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | +**Query**: -**返回**:`ResponseType<[T-FsDiffResponse](#t-fsdiffresponse)>`。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `cwd` | string | 并入该(受信任)目录的项目层 | +| `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 +**返回**:`ResponseType<[T-McpServerAuthStatus](#t-mcpserverauthstatus)>` 数组。验证探测可能刷新或作废已存储的凭据。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "diff": "@@ -1,4 +1,5 @@\n ...", "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "authStatus": "oauth-authorized" } ], "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:open` - -用宿主操作系统的默认程序打开会话文件。仅限 local 运行时。 +#### `POST /api/v2/mcp/auth:begin` -**Body**: +开始一次交互式 OAuth 流程。目标 server 必须使用远程传输(`http` / `sse`)且不含静态 bearer token;静态请求头仅当配置显式设置 `auth: "oauth"` 时允许。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `path` | string | 是 | 要打开的文件,相对于会话工作目录 | -| `line` | integer | 否 | 在处理程序支持时跳转到的行号(正整数) | +**Body**:locator(`{ "source": "global", "name" }` 或 `{ "source": "plugin", "pluginId", "serverName" }`);另有可选的 `cwd` 查询参数。 -**返回**:`ResponseType<{ "opened": true }>`。 +**返回**:`ResponseType`:`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "status": "authorization-required", "flowId": "flow_01J...", "authorizationUrl": "https://mcp.example.com/authorize?..." }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:open-in` +#### `POST /api/v2/mcp/auth:complete` -在指定的宿主应用程序中打开会话文件或目录。仅限 local 运行时。 +等待已开始流程的浏览器回调并完成 code 交换。等待默认 15 分钟(`timeoutMs` 可覆盖),空闲流程无论如何都会在 15 分钟后过期;关闭 HTTP 连接会中止等待。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `app_id` | string | 是 | 目标应用:`finder` / `cursor` / `vscode` / `iterm` / `terminal` | -| `path` | string | 是 | 要打开的文件或目录,相对于会话工作目录 | -| `line` | integer | 否 | 在应用支持时跳转到的行号(正整数) | +| `flowId` | string | 是 | `auth:begin` 返回的流程 id | +| `timeoutMs` | integer | 否 | 等待上限(毫秒)。默认 15 分钟 | -**返回**:`ResponseType<{ "opened": true }>`。 +**返回**:`ResponseType`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`flowId` 未知)、`40929`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/sessions/{session_id}/fs:reveal` +#### `POST /api/v2/mcp/auth:cancel` -在宿主操作系统的文件管理器中显示会话文件。仅限 local 运行时。 +在未完成的情况下终止已开始的流程;未知流程会被忽略。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `path` | string | 是 | 要显示的文件,相对于会话工作目录 | +| `flowId` | string | 是 | 要终止的流程 id | -**返回**:`ResponseType<{ "revealed": true }>`。 +**返回**:`ResponseType`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +**示例**: + +```json +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +``` + +#### `POST /api/v2/mcp/auth:reset` + +清除某个 server 已存储的凭据;失效事件会送达存活的会话。 + +**Body**:locator(形态同 `auth:begin`)。 + +**返回**:`ResponseType`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "revealed": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/fs/{path}:download` +### 文件与其他 -从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流——见 [二进制与流式端点](#二进制与流式端点)。 +文件操作、全局搜索与界面存储。 -**Query**: +**文件系统。** -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `runtime_id` | string | 从哪个运行时读取。默认 `local` | +会话内文件操作走 `POST /api/v1/sessions/{session_id}/fs:{action}`,请求体为 JSON;另有工作区级与本机级的补充端点。每个动作的请求体还接受可选的 `runtime_id`(string,默认 `local`),用于选择执行操作的运行时;`search`、`grep`、`git_status` 与 `diff` 额外要求运行时具备 process capability(进程执行能力),`open`、`open-in` 与 `reveal` 仅在 `local` 运行时上可用。 -**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/sessions/{session_id}/fs:{action}` | 会话内文件操作:`list` / `read` / `list_many` / `stat` / `stat_many` / `mkdir` / `search` / `grep` / `git_status` / `diff` / `open` / `open-in` / `reveal` | +| `POST /api/v1/workspace/fs:search` | 无会话的工作区搜索(body 携带工作区引用) | +| `POST /api/v1/workspace/fs:suggest` | 无会话的文件补全候选(用于 `@` 文件提及) | +| `POST /api/v1/fs:suggest` | 跨根目录的文件补全候选(body 携带 `roots`) | +| `GET /api/v1/sessions/{session_id}/fs/{path}:download` | 下载会话文件(二进制) | +| `GET /api/v1/fs:browse` | 列出本机目录(文件夹选择器用) | +| `GET /api/v1/fs:home` | 用户主目录与最近工作区 | +| `GET /api/v1/fs:content` | 读取本机任意文件原始字节(仅受 token 保护,谨慎暴露端口) | +| `POST /api/v1/fs:mkdir` | 按绝对路径创建目录 | -#### `POST /api/v1/workspace/fs:search` +#### `POST /api/v1/sessions/{session_id}/fs:list` -`fs:search` 的无会话形式:工作区改由请求体而非 URL 携带。 +列出会话工作区目录下的条目,可选递归子目录。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | -| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | -| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `path` | string | 否 | 要列出的目录,相对于会话工作目录。默认 `.` | +| `depth` | integer | 否 | 递归深度,1–10。默认 `1` | +| `limit` | integer | 否 | 最大条目数,1–1000。默认 `200` | +| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -| `runtime_id` | string | 否 | 在哪个运行时上搜索。默认 `local` | +| `exclude_globs` | array | 否 | 额外要跳过的 glob | +| `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | +| `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | -**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`,命中结构与排序同 `fs:search`。 +**返回**:`ResponseType<[T-FsListResponse](#t-fslistresponse)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src", "name": "src", "kind": "directory", "modified_at": "2026-09-01T10:00:00.000Z", "child_count": 12 }, { "path": "package.json", "name": "package.json", "kind": "file", "size": 1024, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "application/json" } ], "truncated": false }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/workspace/fs:suggest` +#### `POST /api/v1/sessions/{session_id}/fs:read` -在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 `@` 文件提及的后端。 +以文本或 base64 读取会话文件的一段内容。`encoding: "auto"` 时文本以 `utf-8` 返回(非 UTF-8 文本会被转码),二进制内容以 `base64` 返回;`encoding: "utf-8"` 强制按文本读取并拒绝二进制文件。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | -| `query` | string | 是 | 要补全的部分路径文本 | -| `limit` | integer | 否 | 最大候选数,1–200。默认 `50` | -| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | -| `runtime_id` | string | 否 | 在哪个运行时上补全。默认 `local` | +| `path` | string | 是 | 文件路径,相对于会话工作目录 | +| `offset` | integer | 否 | 起始字节偏移。默认 `0` | +| `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | +| `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | -**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 +**返回**:`ResponseType<[T-FsReadResponse](#t-fsreadresponse)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "content": "import ...", "encoding": "utf-8", "size": 20480, "truncated": false, "etag": "...", "mime": "text/typescript", "language_id": "typescript", "line_count": 512, "is_binary": false }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/fs:suggest` +#### `POST /api/v1/sessions/{session_id}/fs:list_many` -`fs:suggest` 的工作区无关形式:请求体直接携带绝对 `roots`(1–32 条)。首 root 为主——其候选以相对路径返回,附加 root 的候选为绝对路径;重叠的 root 按 realpath 去重。每个 root 都会先 stat,不存在则整个请求失败。 +一次调用列出多个会话目录;失败的路径折进响应里,而不是让整个请求失败。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `roots` | array | 是 | 绝对根路径数组,1–32 条 | -| `query` | string | 是 | 要补全的部分路径文本 | -| `limit` | integer | 否 | 最大候选数。默认 `50` | -| `follow_gitignore` | boolean | 否 | 默认 `true` | -| `show_hidden` | boolean | 否 | 默认 `false` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | -| `runtime_id` | string | 否 | 默认 `local` | +| `paths` | array | 是 | 要列出的目录,1–100 条 | -**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`。 +其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(某个 root 不存在)、`40420`、`40926`。 +**返回**:`ResponseType<[T-FsListManyResponse](#t-fslistmanyresponse)>`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "results": { "src": [ { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." } ] }, "truncated_paths": [ "src" ], "partial_errors": { "vendor": { "code": 40409, "msg": "path does not exist" } } }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/fs:browse` +#### `POST /api/v1/sessions/{session_id}/fs:stat` -列出某个本机目录的子目录——文件夹选择器的后端。 +查询会话工作区内单个路径的元信息。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `path` | string | 绝对目录路径。默认用户主目录 | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要查询的路径,相对于会话工作目录 | -**返回**:`ResponseType<[T-FsBrowseResponse](#t-fsbrowseresponse)>`。 +**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "/Users/dev", "parent": "/Users", "entries": [ { "name": "my-app", "path": "/Users/dev/my-app", "is_dir": true } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "size": 20480, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "text/typescript", "is_binary": false }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/fs:home` +#### `POST /api/v1/sessions/{session_id}/fs:stat_many` -返回文件夹选择器的落地数据。无参数。 +一次调用查询多个会话路径的元信息;不存在的路径返回 `null`,不会让整个请求失败。 -**返回**:`ResponseType<[T-FsHomeResponse](#t-fshomeresponse)>`(`recent_roots` 上限 8)。 +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `paths` | array | 是 | 要查询的路径,1–1000 条 | + +**返回**:`ResponseType<[T-FsStatManyResponse](#t-fsstatmanyresponse)>`。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "home": "/Users/dev", "recent_roots": [ "/Users/dev/my-app" ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "entries": { "src/index.ts": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." }, "vendor": null } }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/fs:content` +#### `POST /api/v1/sessions/{session_id}/fs:mkdir` -以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 [二进制与流式端点](#二进制与流式端点)。 +在会话工作区内创建目录。 -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `path` | string | **必填。** 绝对文件路径(realpath 解析) | - -**非零 code**(`ResponseType`):`40001`(不是绝对路径或不是普通文件;`details` 为 `{ path, message }[]`)、`40409`、`40411`、`40906`(路径是目录)。 - -#### `POST /api/v1/fs:mkdir` - -按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。 - -**Body**: +**Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `path` | string | 是 | 绝对目录路径 | +| `path` | string | 是 | 要创建的目录,相对于会话工作目录 | +| `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | -**返回**:`ResponseType<{ "path": string }>`。 +**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`(所建目录)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "/Users/dev/new-project" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "path": "docs/api", "name": "api", "kind": "directory", "modified_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } ``` -### 文件上传与媒体 - -提示词附件的上传、下载与删除;会话媒体按会话作用域寻址。 - -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/files` | multipart 上传,返回文件元信息 | -| `GET /api/v1/files/{file_id}` | 下载(二进制,错误用真实 HTTP 状态码) | -| `DELETE /api/v1/files/{file_id}` | 删除 | -| `GET /api/v1/sessions/{session_id}/media/{file_id}` | 按文件 id 下载提示词媒体(二进制) | - -#### `POST /api/v1/files` +#### `POST /api/v1/sessions/{session_id}/fs:search` -以 `multipart/form-data` 上传文件,供后续引用(例如作为提示词附件)。 +在会话工作区内模糊搜索文件与目录名。`query` 为空时改为列出顶层条目。当 `{session_id}` 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 `POST /api/v1/workspace/fs:search`。 -**Body**(multipart): +**Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `file` | binary | 是 | multipart 的文件部分 | -| `name` | string | 否 | 存储的显示名。默认上传文件名 | -| `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | - -**返回**:`ResponseType<[T-FileMeta](#t-filemeta)>`。 - -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(multipart 未初始化或缺少 `file` 字段)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "id": "f_01JZX4...", "name": "screenshot.png", "media_type": "image/png", "size": 204800, "created_at": "2026-09-02T08:12:00.000Z" }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/files/{file_id}` - -下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 - -**非零 code**:`40407`(HTTP 404:没有该 id 的文件,包括已过期的)、`50001`(HTTP 500)。 - -#### `DELETE /api/v1/files/{file_id}` - -删除已上传的文件。无请求体。 +| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | +| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -**返回**:`ResponseType<{ "deleted": true }>`。 +**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 -**非零 code**:同下载——`40407`(HTTP 404)、`50001`(HTTP 500)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/media/{file_id}` - -按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里返回 `ResponseType` 的端点不同,会话或文件不存在时返回真正的 404 状态码且响应体仍为 `ResponseType`。 - -**非零 code**:`40401`(HTTP 404)、`40407`(HTTP 404)。 - -### 全局搜索 - -#### `POST /api/v1/search` +#### `POST /api/v1/sessions/{session_id}/fs:grep` -跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。当 `container.session_id` 指向本服务进程中存活的会话时,搜索改为直接扫描该会话的内存转录,响应的 `source` 字段(`index` 或 `live`)会报告本页结果由哪条路径提供。分页遵循 [`page_token`](#分页) 风格。 +在会话工作区内搜索文件内容——默认按字面字符串,`regex: true` 时按正则表达式。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `query` | string | 是 | 搜索文本 | -| `mode` | string | 否 | `terms`(默认)/ `literal`(零误报的精确子串搜索) | -| `op` | string | 否 | `terms` 模式下的词项组合符:`AND`(默认)/ `OR` | -| `container` | object | 否 | 将搜索限定在 `{ session_id?, agent_id? }` | -| `role` | string | 否 | 限定 `user` / `assistant` / `title` 命中 | -| `start_time` | integer | 否 | 只看不早于该时间的命中(epoch 毫秒) | -| `end_time` | integer | 否 | 只看不晚于该时间的命中(epoch 毫秒) | -| `sort` | string | 否 | `score`(默认)/ `time_desc` / `time_asc`;`literal` 模式忽略此参数,始终最新在前 | -| `page_size` | integer | 否 | 每页命中数,1–50。默认 `20` | -| `page_token` | string | 否 | 上一页响应返回的令牌 | - -`terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 - -**返回**:`ResponseType<[T-SearchResponse](#t-searchresponse)>`。 - -**非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法;`details` 为 `{ path, message }[]`)、`50001`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "items": [ { "session_id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "session_title": "Fix the login page", "agent_id": "main", "role": "user", "snippet": "...adjust the button spacing...", "time": 1787000000000, "turn": 3, "score": 2.31 } ], "has_more": false, "index_state": { "state": "ready", "indexed_sessions": 12, "total_sessions": 12, "documents": 340 }, "source": "index" }, "request_id": "01JZX4..." } -``` - -### GUI 存储 - -由服务端支撑的键值存储,接口对齐浏览器的 `localStorage`,持久化在服务的 home 目录下;web UI 用它保存跨客户端的 UI 状态。值是不透明字符串——序列化由调用方负责。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/gui/store/length` | 已存键的数量 | -| `GET /api/v1/gui/store/getItem` | 按键读取值 | -| `POST /api/v1/gui/store/setItem` | 按键写入值 | -| `POST /api/v1/gui/store/removeItem` | 按键删除值 | -| `POST /api/v1/gui/store/clear` | 删除所有值 | - -`key` 的长度上限为 256 个字符,缺省或超长返回 `40001`。 - -#### `GET /api/v1/gui/store/length` - -返回已存键的数量(对齐 `localStorage.length`)。无参数。 - -**返回**:`ResponseType<{ "length": number }>`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "length": 3 }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/gui/store/getItem` - -读取一个值(对齐 `localStorage.getItem`)。 - -**Query**: +| `pattern` | string | 是 | 要搜索的文本或正则 | +| `regex` | boolean | 否 | 将 `pattern` 视为正则表达式。默认 `false` | +| `case_sensitive` | boolean | 否 | 默认 `true` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的文件 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的文件 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `max_files` | integer | 否 | 最多扫描的文件数,1–10000。默认 `200` | +| `max_matches_per_file` | integer | 否 | 每个文件保留的匹配数,1–10000。默认 `50` | +| `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | +| `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `key` | string | **必填。** 要读取的键,1–256 个字符 | +**返回**:`ResponseType<[T-FsGrepResponse](#t-fsgrepresponse)>`。 -**返回**:`ResponseType<{ "value": string | null }>`——键不存在时为 `null`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "value": "{ \"sidebar\": \"collapsed\" }" }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "files": [ { "path": "src/index.ts", "matches": [ { "line": 12, "col": 8, "text": "const token = ...", "before": [ "..." ], "after": [ "..." ] } ] } ], "files_scanned": 87, "truncated": false, "elapsed_ms": 42 }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/gui/store/setItem` +#### `POST /api/v1/sessions/{session_id}/fs:git_status` -写入一个值(对齐 `localStorage.setItem`)。 +读取会话工作区的 git 状态,可选限定在一组路径内。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `key` | string | 是 | 要写入的键,1–256 个字符 | -| `value` | string | 是 | 要存储的值 | +| `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | -**返回**:`ResponseType`。 +**返回**:`ResponseType<[T-FsGitStatusResponse](#t-fsgitstatusresponse)>`(注意 camelCase `pullRequest`)。 + +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "branch": "main", "ahead": 1, "behind": 0, "entries": { "src/index.ts": "modified" }, "additions": 12, "deletions": 3, "pullRequest": { "number": 3451, "state": "open", "url": "https://github.com/example/repo/pull/3451" } }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/gui/store/removeItem` +#### `POST /api/v1/sessions/{session_id}/fs:diff` -删除一个值(对齐 `localStorage.removeItem`)。 +返回会话工作区内单个文件的 unified git diff。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `key` | string | 是 | 要删除的键,1–256 个字符 | - -**返回**:`ResponseType`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } -``` - -#### `POST /api/v1/gui/store/clear` - -删除所有已存值(对齐 `localStorage.clear`)。无请求体。 - -**返回**:`ResponseType`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } -``` - -### 会话快照 - -#### `GET /api/v1/sessions/{session_id}/snapshot` - -为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 - -**返回**:`ResponseType<[T-SnapshotResponse](#t-snapshotresponse)>`。 - -**非零 code**:`40401`、`50001`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "as_of_seq": 128, "epoch": "01JZX4...", "session": { "id": "session_01JZX4...", "agent_config": { "model": "kimi-for-coding" }, "usage": { "input_tokens": 152000, "...": 0 }, "...": "..." }, "messages": { "items": [ "..." ], "has_more": true }, "in_flight_turn": null, "subagents": [], "pending_approvals": [], "pending_questions": [] }, "request_id": "01JZX4..." } -``` - -### 转录 - -`transcript` 端点提供按 Agent 组织的结构化转录——轮次、任务、交互、附件——即 WebSocket [transcript 帧](#transcript-帧) 实时流式推送的内容。历史分页与补漏用这些端点,实时尾部用 WebSocket 订阅。转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约([T-Transcript 族](#t-transcript-族))。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/sessions/{session_id}/transcript` | 按轮次分页的转录(需 `agent_id`) | -| `GET /api/v1/sessions/{session_id}/transcript/ops` | op 批次补漏(`since_seq`) | -| `GET /api/v1/sessions/{session_id}/transcript/user-messages` | 各轮次起始的用户输入,不分页 | -| `GET /api/v1/sessions/{session_id}/transcript/plan` | ExitPlanMode 计划内容、路径与审阅结果 | - -#### `GET /api/v1/sessions/{session_id}/transcript` - -返回某个 Agent 的结构化转录中的一页:轮次(含其步骤与帧)以及轮次之间的标记与任务引用。活跃会话从内存存储应答(先回填所请求 Agent 的持久化历史);冷会话则从持久化的线上记录重建 Agent。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `agent_id` | string | **必填。** 要读取其转录的 Agent;必须是纯文本形式的 agent id(字母、数字、`.`、`_`、`-`,不含路径分隔符) | -| `before_turn` | string | 只保留早于该轮次 id 的轮次;与 `after_turn` 互斥 | -| `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | -| `page_size` | integer | 1–100 个轮次。默认 `20` | +| `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | -**返回**:`ResponseType<[T-TranscriptResponse](#t-transcriptresponse)>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 +**返回**:`ResponseType<[T-FsDiffResponse](#t-fsdiffresponse)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "items": [ { "kind": "turn", "turnId": 3, "...": "..." } ], "has_more": true, "tasks": [], "interactions": [], "attachments": [], "todos": [], "prompts": [], "meta": { "...": "..." }, "agents": [ { "agentId": "main", "...": "..." } ], "pending_interactions": [], "seq": 42 }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "diff": "@@ -1,4 +1,5 @@\n ...", "truncated": false }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/transcript/ops` +#### `POST /api/v1/sessions/{session_id}/fs:open` -从服务端的 op 日志提供点对点的补漏:某个 Agent 的 `seq > since_seq` 的已记录 op 批次,最旧在前。它是 `transcript_since` 恢复游标的 REST 对应物,共享同一份有界日志,因此适用相同的回退规则。 +用宿主操作系统的默认程序打开会话文件。仅限 local 运行时。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `agent_id` | string | **必填。** Agent id(纯文本形式) | -| `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要打开的文件,相对于会话工作目录 | +| `line` | integer | 否 | 在处理程序支持时跳转到的行号(正整数) | -**返回**:`ResponseType<[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 +**返回**:`ResponseType<{ "opened": true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "batches": [ { "seq": 41, "ops": [ { "op": "append", "...": "..." } ] } ], "latest_seq": 42, "complete": true }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/transcript/user-messages` +#### `POST /api/v1/sessions/{session_id}/fs:open-in` -列出会话中每个开启轮次的输入,按 Agent 分组且不分页:真实用户文本、以斜杠命令形式使用的 Skill 与插件命令、以及 cron 提示词——可通过 `origin` 区分——另有仅含附件的提示词,其 `prompt` 投影为空。所列消息引用的附件实体会随响应一起返回(仅元数据,绝不包含字节内容)。 +在指定的宿主应用程序中打开会话文件或目录。仅限 local 运行时。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `app_id` | string | 是 | 目标应用:`finder` / `cursor` / `vscode` / `iterm` / `terminal` | +| `path` | string | 是 | 要打开的文件或目录,相对于会话工作目录 | +| `line` | integer | 否 | 在应用支持时跳转到的行号(正整数) | -**返回**:`ResponseType<[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)>`。 +**返回**:`ResponseType<{ "opened": true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "agents": [ { "agent_id": "main", "messages": [ { "turn_id": 3, "ordinal": 0, "state": "completed", "origin": { "kind": "user" }, "prompt": "adjust the button spacing", "started_at": "2026-09-02T08:04:00.000Z" } ], "attachments": [] } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } ``` -#### `GET /api/v1/sessions/{session_id}/transcript/plan` +#### `POST /api/v1/sessions/{session_id}/fs:reveal` -按时间线顺序读取某个 Agent 的 `ExitPlanMode` 工具调用的计划信息——计划内容、计划文件路径、提供的选项以及审阅结果。内容投影自第一个可用的事实来源:关联的审批交互(交互式审阅)、实时工具帧的展示(auto 模式),或工具结果的输出文本;每个条目在 `source` 中记录具体来源。 +在宿主操作系统的文件管理器中显示会话文件。仅限 local 运行时。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `agent_id` | string | **必填。** Agent id(纯文本形式) | -| `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 要显示的文件,相对于会话工作目录 | -**返回**:`ResponseType<[T-TranscriptPlanResponse](#t-transcriptplanresponse)>`。 +**返回**:`ResponseType<{ "revealed": true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "plans": [ { "tool_call_id": "toolu_01J...", "turn_id": 2, "source": "interaction", "plan": "# Plan\n ...", "path": "/Users/dev/my-app/.kimi-code/plans/....md", "options": [ { "label": "实施" } ], "review": { "state": "approved", "selected_option": "实施" } } ] }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "revealed": true }, "request_id": "01JZX4..." } ``` -### 文件历史(实验性) - -::: info 新增 -实验特性:由 `KIMI_CODE_EXPERIMENTAL_FILE_HISTORY` 开关控制(默认关闭),接口形态可能随版本更改。 -::: - -按轮次记录的文件历史快照:main agent 每个轮次在开始与结束两个检查点版本化所有被 Edit / Write 工具触碰的文件(未变化的文件按内容哈希去重,超过 4 MiB 的文件只记录哨兵指纹)。这两个端点从检查点计算单个轮次的逐文件增删行数与任一检查点的完整内容;冷会话会按需恢复。开关关闭时路由仍注册,但 `changes` 恒返回空列表、`enabled` 恒为 `false`、`content` 恒为 `null`。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/sessions/{session_id}/file-history/changes` | 单个轮次的逐文件增删统计 | -| `GET /api/v1/sessions/{session_id}/file-history/content` | 某文件在指定检查点的完整内容 | - -#### `GET /api/v1/sessions/{session_id}/file-history/changes` +#### `GET /api/v1/sessions/{session_id}/fs/{path}:download` -返回单个轮次开始与结束检查点之间每个文件的精确增删行数。 +从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流——见 [二进制与流式端点](#二进制与流式端点)。 **Query**: | 参数 | 类型 | 说明 | | --- | --- | --- | -| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `changes` | array | `{ path, status, additions, deletions, binary?, oversize? }[]`;`status` 为 `added` / `modified` / `deleted`;二进制与超大文件的增删行为 `0`,并以 `binary` / `oversize` 标记 | -| `enabled` | boolean | 实验开关是否开启 | -| `recorded` | boolean | 该轮次是否有已记录的检查点 | - -**非零 code**:`40401`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "changes": [ { "path": "src/index.ts", "status": "modified", "additions": 12, "deletions": 3 } ], "enabled": true, "recorded": true }, "request_id": "01JZX4..." } -``` +| `runtime_id` | string | 从哪个运行时读取。默认 `local` | -#### `GET /api/v1/sessions/{session_id}/file-history/content` +**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 -返回某文件在指定轮次检查点的完整内容;`phase: "end"` 时若该文件在结束检查点没有记录,回退到开始检查点的版本。 +#### `POST /api/v1/workspace/fs:search` -**Query**: +`fs:search` 的无会话形式:工作区改由请求体而非 URL 携带。 -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `turn_id` | integer | **必填。** 轮次 id(≥ 0) | -| `path` | string | **必填。** 文件路径 | -| `phase` | string | `start`(默认)/ `end`——取轮次开始还是结束检查点 | +**Body**: -**返回**:`ResponseType`,`data` 字段: +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | +| `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | +| `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `runtime_id` | string | 否 | 在哪个运行时上搜索。默认 `local` | -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `content` | object \| null | `{ version, content?, binary? }`——`version` 为该文件在检查点的版本号;二进制文件只携带 `binary: true` 不携带文本;无记录时为 `null` | +**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`,命中结构与排序同 `fs:search`。 -**非零 code**:`40401`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "content": { "version": 2, "content": "import ..." } }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } ``` -### v2 会话 - -`/api/v2` 的会话查询与批量管理。与 v1 共享 `ResponseType` 与错误约定;分页为绑定查询指纹的 `page_token`(见 [分页](#分页))。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v2/sessions` | 新一代会话列表:筛选、排序、字段组、分组视图 | -| `POST /api/v2/sessions:archive` | 批量归档会话 | -| `POST /api/v2/sessions:restore` | 批量恢复已归档会话 | - -#### `GET /api/v2/sessions` +#### `POST /api/v1/workspace/fs:suggest` -面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里。 +在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 `@` 文件提及的后端。 -**Query**: +**Body**: -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `workspace.id` | string | 按工作区过滤,可重复 | -| `activity.status` | string | 按活动状态过滤:`running` / `approval` / `question` / `failed` / `idle`,可重复 | -| `meta.updated_after` | integer | 只看该时间(epoch 毫秒)之后更新过的会话 | -| `meta.updated_before` | integer | 只看该时间(epoch 毫秒)之前更新过的会话 | -| `meta.archived` | string | `true` / `false`(默认)/ `all` | -| `meta.has_prompt` | string | `true` 只保留有用户 prompt 的会话,`false` 只保留空会话(等价 v1 的 `exclude_empty`) | -| `view` | string | `flat`(默认)/ `by_workspace`(按工作区分组) | -| `group.page_size` | integer | `view=by_workspace` 时每个工作区返回的会话数:1–100,默认 `5`(`id,archived` 投影时上限 10000);未开分组视图时传入返回 `40001` | -| `sort` | string | `meta.updated_at_desc`(默认)/ `meta.updated_at_asc` / `meta.created_at_desc` | -| `include` | string | 逗号分隔的附加字段组;目前支持 `git`(分支与 PR 信息,按目录去重并缓存 60 秒) | -| `fields` | string | 逗号分隔的字段投影;目前仅支持 `id,archived`,每项裁剪为 `{ id, archived }`。不可与 `include=git` 同传(`40001`) | -| `page_size` | integer | 1–100,默认 `50`;`id,archived` 投影时上限放宽至 10000。`view=by_workspace` 时按组计数 | -| `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | -| `page_token` | string | 上一页返回的翻页令牌 | +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | +| `query` | string | 是 | 要补全的部分路径文本 | +| `limit` | integer | 否 | 最大候选数,1–200。默认 `50` | +| `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | +| `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `runtime_id` | string | 否 | 在哪个运行时上补全。默认 `local` | -**返回**:`ResponseType<[T-V2SessionPage](#t-v2sessionpage)>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 +**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知 `include` / `fields`、组合非法)、`40922`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 -**示例**(`view=by_workspace`): +**示例**: ```json -{ "code": 0, "msg": "success", "data": { "groups": [ { "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "sessions": [ { "id": "session_01JZX4...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ], "total": 42 } ], "total": 7, "has_more": true, "next_page_token": "eyJ2IjoxLCJmIjoi..." }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/sessions:archive` 与 `POST /api/v2/sessions:restore` +#### `POST /api/v1/fs:suggest` -面向会话管理页的批量归档 / 恢复。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回。 +`fs:suggest` 的工作区无关形式:请求体直接携带绝对 `roots`(1–32 条)。首 root 为主——其候选以相对路径返回,附加 root 的候选为绝对路径;重叠的 root 按 realpath 去重。每个 root 都会先 stat,不存在则整个请求失败。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | +| `roots` | array | 是 | 绝对根路径数组,1–32 条 | +| `query` | string | 是 | 要补全的部分路径文本 | +| `limit` | integer | 否 | 最大候选数。默认 `50` | +| `follow_gitignore` | boolean | 否 | 默认 `true` | +| `show_hidden` | boolean | 否 | 默认 `false` | +| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `runtime_id` | string | 否 | 默认 `local` | -**返回**:`ResponseType<[T-V2BatchSessionResponse](#t-v2batchsessionresponse)>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 +**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(某个 root 不存在)、`40420`、`40926`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "results": [ { "id": "session_a", "ok": true }, { "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } } ], "succeeded": 1, "failed": 1 }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } ``` -### v2 MCP +#### `GET /api/v1/fs:browse` -`/api/v2/mcp/*` 是统一的 MCP 管理面:独立于任何会话,直接管理 MCP server 注册表本身——全局(用户级)CRUD 与逐条校验、连接测试探测、locator 寻址的检查目录、按 server 的授权状态列表,以及完整的 OAuth 流程生命周期。响应该组一律不包 `{ items }`:`data` 直接为数组或对象。 +列出某个本机目录的子目录——文件夹选择器的后端。 -该管理面有两种寻址方式。CRUD 路由与 `servers:test` 使用普通的运行时 `name`;检查与 OAuth 路由使用 **locator**——文件层条目用 `{ "source": "global", "name" }`,插件清单条目用 `{ "source": "plugin", "pluginId", "serverName" }`——因为插件条目和文件条目可能共用同一个运行时名称。检查条目还带有一个稳定的 `serverId` 线上标识:`global:` 或 `plugin::`(URL 编码)。 +**Query**: -大多数路由接受可选的 `cwd`(查询参数,`:`-action 路由则为请求体字段)。不传时目录只覆盖用户级文件与插件清单;传入后,该目录的项目根层与项目本地层会并入——但仅当工作区受信任时,否则项目层会被跳过。对 stdio server 执行 `servers:test` 时,`cwd` 同时是子进程的工作目录。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `path` | string | 绝对目录路径。默认用户主目录 | -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v2/mcp/servers` | 列出所有已知 MCP server | -| `GET /api/v2/mcp/servers/{name}` | 按运行时名称获取单个 server | -| `POST /api/v2/mcp/servers` | 向用户级 `mcp.json` 添加 server | -| `PUT /api/v2/mcp/servers/{name}` | 替换一个用户级条目 | -| `DELETE /api/v2/mcp/servers/{name}` | 删除一个用户级条目 | -| `POST /api/v2/mcp/servers:test` | 对单个 server 发起真实连接探测 | -| `POST /api/v2/mcp/servers:inspect` | locator 寻址的目录及批量连接探测 | -| `GET /api/v2/mcp/auth-statuses` | 目录中各 server 的 OAuth 状态 | -| `POST /api/v2/mcp/auth:begin` | 开始一次交互式 OAuth 流程 | -| `POST /api/v2/mcp/auth:complete` | 等待浏览器回调并完成 code 交换 | -| `POST /api/v2/mcp/auth:cancel` | 终止已开始的 OAuth 流程 | -| `POST /api/v2/mcp/auth:reset` | 清除某个 server 已存储的凭据 | +**返回**:`ResponseType<[T-FsBrowseResponse](#t-fsbrowseresponse)>`。 -#### `GET /api/v2/mcp/servers` +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 -列出管理面已知的全部 MCP server。 +**示例**: -**Query**: +```json +{ "code": 0, "msg": "success", "data": { "path": "/Users/dev", "parent": "/Users", "entries": [ { "name": "my-app", "path": "/Users/dev/my-app", "is_dir": true } ] }, "request_id": "01JZX4..." } +``` -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `cwd` | string | 并入该(受信任)目录的项目层 | +#### `GET /api/v1/fs:home` -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组。 +返回文件夹选择器的落地数据。无参数。 + +**返回**:`ResponseType<[T-FsHomeResponse](#t-fshomeresponse)>`(`recent_roots` 上限 8)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ], "envKeys": [ "API_KEY" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true } ], "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "home": "/Users/dev", "recent_roots": [ "/Users/dev/my-app" ] }, "request_id": "01JZX4..." } ``` -#### `GET /api/v2/mcp/servers/{name}` +#### `GET /api/v1/fs:content` -按运行时名称获取单个 server。 +以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 [二进制与流式端点](#二进制与流式端点)。 **Query**: | 参数 | 类型 | 说明 | | --- | --- | --- | -| `cwd` | string | 并入该(受信任)目录的项目层 | - -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>`。 - -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 +| `path` | string | **必填。** 绝对文件路径(realpath 解析) | -**示例**: +**非零 code**(`ResponseType`):`40001`(不是绝对路径或不是普通文件;`details` 为 `{ path, message }[]`)、`40409`、`40411`、`40906`(路径是目录)。 -```json -{ "code": 0, "msg": "success", "data": { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true }, "request_id": "01JZX4..." } -``` +#### `POST /api/v1/fs:mkdir` -#### `POST /api/v2/mcp/servers` +按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。 -向用户级 `mcp.json` 添加 server。若写入与项目层的同名条目冲突,会因只读被拒绝;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。 +**Body**: -**Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `path` | string | 是 | 绝对目录路径 | -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +**返回**:`ResponseType<{ "path": string }>`。 -**非零 code**:`40001`(校验失败,或目标条目为只读;`details` 为 `{ path, message }[]`)。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "path": "/Users/dev/new-project" }, "request_id": "01JZX4..." } ``` -#### `PUT /api/v2/mcp/servers/{name}` - -替换一个用户级条目;身份由路径指定。 - -**Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 +**文件上传与媒体。** -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +提示词附件的上传、下载与删除;会话媒体按会话作用域寻址。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/files` | multipart 上传,返回文件元信息 | +| `GET /api/v1/files/{file_id}` | 下载(二进制,错误用真实 HTTP 状态码) | +| `DELETE /api/v1/files/{file_id}` | 删除 | +| `GET /api/v1/sessions/{session_id}/media/{file_id}` | 按文件 id 下载提示词媒体(二进制) | -**示例**: +#### `POST /api/v1/files` -```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "http", "url": "https://mcp.example.com" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } -``` +以 `multipart/form-data` 上传文件,供后续引用(例如作为提示词附件)。 -#### `DELETE /api/v2/mcp/servers/{name}` +**Body**(multipart): -删除一个用户级条目。无请求体。 +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `file` | binary | 是 | multipart 的文件部分 | +| `name` | string | 否 | 存储的显示名。默认上传文件名 | +| `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +**返回**:`ResponseType<[T-FileMeta](#t-filemeta)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 +**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(multipart 未初始化或缺少 `file` 字段)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": [], "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "id": "f_01JZX4...", "name": "screenshot.png", "media_type": "image/png", "size": 204800, "created_at": "2026-09-02T08:12:00.000Z" }, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/servers:test` +#### `GET /api/v1/files/{file_id}` -对单个 server 发起真实连接探测,不持久化任何内容。传 `name` 探测注册表条目(含插件与受信任的项目层),或传 `server`(包含 `name` 的完整内联配置)按原样探测;两者都传或都不传会报 `40001`。 +下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 -**Body**: +**非零 code**:`40407`(HTTP 404:没有该 id 的文件,包括已过期的)、`50001`(HTTP 500)。 -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `name` | string | 二选一 | 注册表条目的运行时名称 | -| `server` | object | 二选一 | 按原样探测的内联 server 配置(含 `name`) | -| `cwd` | string | 否 | 项目层并入解析;同时是 stdio 的工作目录 | +#### `DELETE /api/v1/files/{file_id}` -**返回**:`ResponseType<{ "success": boolean, "output": string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 +删除已上传的文件。无请求体。 -**非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用;`details` 为 `{ path, message }[]`)、`40408`。 +**返回**:`ResponseType<{ "deleted": true }>`。 + +**非零 code**:同下载——`40407`(HTTP 404)、`50001`(HTTP 500)。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "success": true, "output": "5 tools: search, fetch, ..." }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/servers:inspect` +#### `GET /api/v1/sessions/{session_id}/media/{file_id}` -locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 `unavailable` 并在 `error` 中给出说明;探测遇到过期授权时,可能刷新或作废已存储的凭据。 +按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里返回 `ResponseType` 的端点不同,会话或文件不存在时返回真正的 404 状态码且响应体仍为 `ResponseType`。 + +**非零 code**:`40401`(HTTP 404)、`40407`(HTTP 404)。 + +**全局搜索。** + +#### `POST /api/v1/search` + +跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。当 `container.session_id` 指向本服务进程中存活的会话时,搜索改为直接扫描该会话的内存转录,响应的 `source` 字段(`index` 或 `live`)会报告本页结果由哪条路径提供。分页遵循 [`page_token`](#分页) 风格。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | -| `cwd` | string | 否 | 并入该(受信任)目录的项目层 | +| `query` | string | 是 | 搜索文本 | +| `mode` | string | 否 | `terms`(默认)/ `literal`(零误报的精确子串搜索) | +| `op` | string | 否 | `terms` 模式下的词项组合符:`AND`(默认)/ `OR` | +| `container` | object | 否 | 将搜索限定在 `{ session_id?, agent_id? }` | +| `role` | string | 否 | 限定 `user` / `assistant` / `title` 命中 | +| `start_time` | integer | 否 | 只看不早于该时间的命中(epoch 毫秒) | +| `end_time` | integer | 否 | 只看不晚于该时间的命中(epoch 毫秒) | +| `sort` | string | 否 | `score`(默认)/ `time_desc` / `time_asc`;`literal` 模式忽略此参数,始终最新在前 | +| `page_size` | integer | 否 | 每页命中数,1–50。默认 `20` | +| `page_token` | string | 否 | 上一页响应返回的令牌 | -**返回**:`ResponseType<[T-McpServerInspection](#t-mcpserverinspection)>` 数组。 +`terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 +**返回**:`ResponseType<[T-SearchResponse](#t-searchresponse)>`。 + +**非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法;`details` 为 `{ path, message }[]`)、`50001`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "serverId": "global:my-server", "locator": { "source": "global", "name": "my-server" }, "runtimeName": "my-server", "origin": "global", "config": { "transport": "http", "url": "https://mcp.example.com" }, "enabled": true, "editable": true, "authStatus": "oauth-authorized", "checkedAt": 1787000000000 } ], "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "items": [ { "session_id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "session_title": "Fix the login page", "agent_id": "main", "role": "user", "snippet": "...adjust the button spacing...", "time": 1787000000000, "turn": 3, "score": 2.31 } ], "has_more": false, "index_state": { "state": "ready", "indexed_sessions": 12, "total_sessions": 12, "documents": 340 }, "source": "index" }, "request_id": "01JZX4..." } ``` -#### `GET /api/v2/mcp/auth-statuses` +**GUI 存储。** -注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 `servers:inspect` 更轻量的选择。 +由服务端支撑的键值存储,接口对齐浏览器的 `localStorage`,持久化在服务的 home 目录下;web UI 用它保存跨客户端的 UI 状态。值是不透明字符串——序列化由调用方负责。 -**Query**: +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/gui/store/length` | 已存键的数量 | +| `GET /api/v1/gui/store/getItem` | 按键读取值 | +| `POST /api/v1/gui/store/setItem` | 按键写入值 | +| `POST /api/v1/gui/store/removeItem` | 按键删除值 | +| `POST /api/v1/gui/store/clear` | 删除所有值 | -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `cwd` | string | 并入该(受信任)目录的项目层 | -| `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | +`key` 的长度上限为 256 个字符,缺省或超长返回 `40001`。 -**返回**:`ResponseType<[T-McpServerAuthStatus](#t-mcpserverauthstatus)>` 数组。验证探测可能刷新或作废已存储的凭据。 +#### `GET /api/v1/gui/store/length` + +返回已存键的数量(对齐 `localStorage.length`)。无参数。 + +**返回**:`ResponseType<{ "length": number }>`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "authStatus": "oauth-authorized" } ], "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "length": 3 }, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/auth:begin` +#### `GET /api/v1/gui/store/getItem` -开始一次交互式 OAuth 流程。目标 server 必须使用远程传输(`http` / `sse`)且不含静态 bearer token;静态请求头仅当配置显式设置 `auth: "oauth"` 时允许。 +读取一个值(对齐 `localStorage.getItem`)。 -**Body**:locator(`{ "source": "global", "name" }` 或 `{ "source": "plugin", "pluginId", "serverName" }`);另有可选的 `cwd` 查询参数。 +**Query**: -**返回**:`ResponseType`:`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `key` | string | **必填。** 要读取的键,1–256 个字符 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 +**返回**:`ResponseType<{ "value": string | null }>`——键不存在时为 `null`。 **示例**: ```json -{ "code": 0, "msg": "success", "data": { "status": "authorization-required", "flowId": "flow_01J...", "authorizationUrl": "https://mcp.example.com/authorize?..." }, "request_id": "01JZX4..." } +{ "code": 0, "msg": "success", "data": { "value": "{ \"sidebar\": \"collapsed\" }" }, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/auth:complete` +#### `POST /api/v1/gui/store/setItem` -等待已开始流程的浏览器回调并完成 code 交换。等待默认 15 分钟(`timeoutMs` 可覆盖),空闲流程无论如何都会在 15 分钟后过期;关闭 HTTP 连接会中止等待。 +写入一个值(对齐 `localStorage.setItem`)。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `flowId` | string | 是 | `auth:begin` 返回的流程 id | -| `timeoutMs` | integer | 否 | 等待上限(毫秒)。默认 15 分钟 | +| `key` | string | 是 | 要写入的键,1–256 个字符 | +| `value` | string | 是 | 要存储的值 | **返回**:`ResponseType`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`flowId` 未知)、`40929`。 - **示例**: ```json { "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/auth:cancel` +#### `POST /api/v1/gui/store/removeItem` -在未完成的情况下终止已开始的流程;未知流程会被忽略。 +删除一个值(对齐 `localStorage.removeItem`)。 **Body**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `flowId` | string | 是 | 要终止的流程 id | +| `key` | string | 是 | 要删除的键,1–256 个字符 | **返回**:`ResponseType`。 @@ -2904,16 +2932,12 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 { "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } ``` -#### `POST /api/v2/mcp/auth:reset` - -清除某个 server 已存储的凭据;失效事件会送达存活的会话。 +#### `POST /api/v1/gui/store/clear` -**Body**:locator(形态同 `auth:begin`)。 +删除所有已存值(对齐 `localStorage.clear`)。无请求体。 **返回**:`ResponseType`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`。 - **示例**: ```json @@ -3192,7 +3216,7 @@ payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__glob ### terminal 帧 -`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点(见 [终端](#终端))不受影响。 +`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点(见「任务与终端」域的 [终端](#任务与终端) 部分)不受影响。 ## 完整错误码 From d1438c29731a41bcfd055797af2a7004e333d49e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:40:25 +0800 Subject: [PATCH 14/47] docs(zh): split the service-and-account domain into service and account --- docs/zh/reference/server-api.md | 306 ++++++++++++++++---------------- 1 file changed, 155 insertions(+), 151 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 15133d386dc..8e7a78bd53e 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -87,9 +87,9 @@ HTTP 状态码例外(非 200): 下文按业务域分组列出全部端点,覆盖 `/api/v1` 与 `/api/v2`(路径前缀区分版本)。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 -### 服务与账号 +### 服务 -服务接入、登录与账号、全局配置、模型与供应商。 +服务接入信息、全局配置、模型与供应商。 **服务与元信息。** @@ -188,155 +188,6 @@ HTTP 状态码例外(非 200): { "code": 0, "msg": "success", "data": { "connections": [ { "id": "conn_01JZX4...", "connected_at": "2026-09-02T08:00:00.000Z", "remote_address": "127.0.0.1", "user_agent": "Mozilla/5.0 ...", "has_client_hello": true, "subscriptions": [ "session_..." ] } ] }, "request_id": "01JZX4..." } ``` -**登录与用量。** - -托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 - -| 方法与路径 | 说明 | -| --- | --- | -| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | -| `GET /api/v1/oauth/login` | 轮询登录流程状态 | -| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | -| `POST /api/v1/oauth/logout` | 登出托管供应商 | -| `GET /api/v1/oauth/usage` | 套餐用量与限额 | -| `GET /api/v1/oauth/userinfo` | 账号资料 | -| `GET /api/v1/oauth/region` | 解析客户端所属区域 | - -#### `POST /api/v1/oauth/login` - -为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 - -**Body**: - -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | -| `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | - -**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/oauth/login` - -轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } -``` - -#### `DELETE /api/v1/oauth/login` - -取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | -| `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } -``` - -#### `POST /api/v1/oauth/logout` - -登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 - -**Body**: - -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `logged_out` | boolean | 恒 `true` | -| `provider` | string | 被登出的供应商名 | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/oauth/usage` - -托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/oauth/userinfo` - -托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 - -**Query**: - -| 参数 | 类型 | 说明 | -| --- | --- | --- | -| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | - -**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } -``` - -#### `GET /api/v1/oauth/region` - -解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 - -**返回**:`ResponseType`,`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `region` | string | `mainland-cn` / `global` | - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } -``` - **配置。** 全局配置的读取与合并式更新;密钥字段一律脱敏。 @@ -612,6 +463,159 @@ HTTP 状态码例外(非 200): { "code": 0, "msg": "success", "data": { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ "..." ] }, "request_id": "01JZX4..." } ``` +### 账号 + +托管账号的登录、用量与资料。 + +**登录与用量。** + +托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 + +| 方法与路径 | 说明 | +| --- | --- | +| `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | +| `GET /api/v1/oauth/login` | 轮询登录流程状态 | +| `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | +| `POST /api/v1/oauth/logout` | 登出托管供应商 | +| `GET /api/v1/oauth/usage` | 套餐用量与限额 | +| `GET /api/v1/oauth/userinfo` | 账号资料 | +| `GET /api/v1/oauth/region` | 解析客户端所属区域 | + +#### `POST /api/v1/oauth/login` + +为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | +| `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | + +**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/login` + +轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } +``` + +#### `DELETE /api/v1/oauth/login` + +取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | +| `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } +``` + +#### `POST /api/v1/oauth/logout` + +登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 + +**Body**: + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `logged_out` | boolean | 恒 `true` | +| `provider` | string | 被登出的供应商名 | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/usage` + +托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/userinfo` + +托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 + +**Query**: + +| 参数 | 类型 | 说明 | +| --- | --- | --- | +| `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | + +**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } +``` + +#### `GET /api/v1/oauth/region` + +解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 + +**返回**:`ResponseType`,`data` 字段: + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `region` | string | `mainland-cn` / `global` | + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } +``` + ### 工作区与会话 工作区与会话两个核心业务对象的生命周期。路径前缀区分版本:`/api/v1` 与 `/api/v2`。 From 7e032072ab4aebcbd3b4c1aa7e6014d818d31808 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:42:13 +0800 Subject: [PATCH 15/47] docs(zh): move GET /auth from the service domain to the account domain --- docs/zh/reference/server-api.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 8e7a78bd53e..2827c2dc3cf 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -99,7 +99,6 @@ HTTP 状态码例外(非 200): | --- | --- | | `GET /api/v1/healthz` | 探活,免鉴权 | | `GET /api/v1/meta` | 服务版本、能力集、`server_id`、实验开关 | -| `GET /api/v1/auth` | 鉴权状态快照 | | `POST /api/v1/shutdown` | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 | | `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | @@ -148,18 +147,6 @@ HTTP 状态码例外(非 200): } ``` -#### `GET /api/v1/auth` - -鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 - -**返回**:`ResponseType<[T-AuthSummary](#t-authsummary)>`。 - -**示例**: - -```json -{ "code": 0, "msg": "success", "data": { "models_ready": true, "providers_count": 1, "managed_provider": { "name": "managed:kimi-code", "status": "authenticated" } }, "request_id": "01JZX4..." } -``` - #### `POST /api/v1/shutdown` 请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。无参数。 @@ -473,6 +460,7 @@ HTTP 状态码例外(非 200): | 方法与路径 | 说明 | | --- | --- | +| `GET /api/v1/auth` | 鉴权状态快照 | | `POST /api/v1/oauth/login` | 发起 OAuth device-code 登录流程 | | `GET /api/v1/oauth/login` | 轮询登录流程状态 | | `DELETE /api/v1/oauth/login` | 取消进行中的登录流程 | @@ -481,6 +469,18 @@ HTTP 状态码例外(非 200): | `GET /api/v1/oauth/userinfo` | 账号资料 | | `GET /api/v1/oauth/region` | 解析客户端所属区域 | +#### `GET /api/v1/auth` + +鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 + +**返回**:`ResponseType<[T-AuthSummary](#t-authsummary)>`。 + +**示例**: + +```json +{ "code": 0, "msg": "success", "data": { "models_ready": true, "providers_count": 1, "managed_provider": { "name": "managed:kimi-code", "status": "authenticated" } }, "request_id": "01JZX4..." } +``` + #### `POST /api/v1/oauth/login` 为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 From 729cfcd9251692b4b2ceb1f10234f5b67f225eb8 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:42:53 +0800 Subject: [PATCH 16/47] docs(zh): drop duplicated domain intros and the single-block divider --- docs/zh/reference/server-api.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 2827c2dc3cf..d23e9c57968 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -89,8 +89,6 @@ HTTP 状态码例外(非 200): ### 服务 -服务接入信息、全局配置、模型与供应商。 - **服务与元信息。** 服务自身的探活、身份、关停与连接管理。 @@ -452,10 +450,6 @@ HTTP 状态码例外(非 200): ### 账号 -托管账号的登录、用量与资料。 - -**登录与用量。** - 托管 Kimi OAuth 登录的生命周期与账号级信息。托管供应商名为 `managed:kimi-code`;下面每个端点上可选的 `provider` 参数都默认取它。 | 方法与路径 | 说明 | @@ -618,7 +612,7 @@ HTTP 状态码例外(非 200): ### 工作区与会话 -工作区与会话两个核心业务对象的生命周期。路径前缀区分版本:`/api/v1` 与 `/api/v2`。 +路径前缀区分版本:`/api/v1` 与 `/api/v2`。 **工作区。** @@ -1254,8 +1248,6 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 ### 对话 -驱动一轮对话:提交提示词、流式消息、审批与提问交互、转录。 - **提示词。** 提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列;轮次进度通过 [WebSocket 帧](#websocket-帧) 推送,不经过这些端点。 @@ -1644,8 +1636,6 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin ### 任务与终端 -后台任务与终端。 - **后台任务。** 后台任务是会话的异步单元——后台 Shell、subagent 与长时间运行的工具任务。注册表仅包含实时数据:未加载到本服务进程中的会话会返回空列表。 @@ -1798,7 +1788,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 ### 扩展 -技能、插件、能力与 MCP。路径前缀区分版本:`/api/v1` 与 `/api/v2`。 +路径前缀区分版本:`/api/v1` 与 `/api/v2`。 **技能。** @@ -2300,8 +2290,6 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 ### 文件与其他 -文件操作、全局搜索与界面存储。 - **文件系统。** 会话内文件操作走 `POST /api/v1/sessions/{session_id}/fs:{action}`,请求体为 JSON;另有工作区级与本机级的补充端点。每个动作的请求体还接受可选的 `runtime_id`(string,默认 `local`),用于选择执行操作的运行时;`search`、`grep`、`git_status` 与 `diff` 额外要求运行时具备 process capability(进程执行能力),`open`、`open-in` 与 `reveal` 仅在 `local` 运行时上可用。 From 1fb22a017c54d338285450059f3849d42fd8c4b0 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 17:43:36 +0800 Subject: [PATCH 17/47] docs(zh): drop the divider that duplicated the service domain name --- docs/zh/reference/server-api.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index d23e9c57968..efc98315779 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -89,8 +89,6 @@ HTTP 状态码例外(非 200): ### 服务 -**服务与元信息。** - 服务自身的探活、身份、关停与连接管理。 | 方法与路径 | 说明 | From b7c874e884df180e3c5f7c7ce79b9b9ed753d45e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:06:33 +0800 Subject: [PATCH 18/47] docs(zh): classify the type dictionary by REST and WS with TypeScript definition blocks --- docs/zh/reference/server-api.md | 1265 +++++++++++++++++++++++++------ 1 file changed, 1037 insertions(+), 228 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index efc98315779..00909eac36c 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -3214,420 +3214,1229 @@ payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__glob ## 类型汇总 -端点与帧型共享的类型字典。「可缺省」表示该键可能不出现(`undefined` 被序列化丢弃),「可空」表示显式 `null`,两者语义不同(见 [null 与缺省语义](#null-与缺省语义))。 +端点与帧型共享的类型字典,按传输面分为 REST 与 WS 两类,每条目以一个 TypeScript 定义块给出。「可缺省」(`field?: T`)表示该键可能不出现(`undefined` 被序列化丢弃),「可空」(`field: T | null`)表示显式 `null`,两者语义不同(见 [null 与缺省语义](#null-与缺省语义));简短语义以 `//` 行尾注释标注。 + +### REST 类型 + +REST 端点的请求与响应类型,按域分组。 + +**会话。** ### T-Session -会话对象。返回会话的各端点(除快照)中 `usage` 恒为全 0 的 T-SessionUsage、`permission_rules` 恒 `[]`、`message_count` 恒 `0`;`last_seq` 仅 `GET /api/v1/sessions/{session_id}` 携带真实事件水位,其余端点恒 `0`。 +会话对象。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | string | 会话 id(`session_...`) | -| `workspace_id` | string | 所属工作区 id(`wd__`) | -| `title` | string | 标题;未设置时为 `""` | -| `created_at` | string | 创建时间,ISO 8601 | -| `updated_at` | string | 最后更新时间,ISO 8601 | -| `archived_at` | string | 可缺省:归档时间;未归档时不出现 | -| `busy` | boolean | 任一 Agent 有活动轮次或后台任务 | -| `main_turn_active` | boolean | main agent 轮次进行中 | -| `pending_interaction` | string | `none` / `approval` / `question` | -| `last_turn_reason` | string | 可缺省:`completed` / `cancelled` / `failed`——存活会话取实时值,冷会话取最后持久化值,均无则缺省 | -| `archived` | boolean | 归档标记 | -| `last_prompt` | string | 可缺省:最近一条提示词文本 | -| `metadata` | object | 必含 `cwd: string`;附加自定义任意键(`goal` 键被剔除) | -| `agent_config` | object | 恒 `{ "model": string }`——存活会话取绑定模型,否则 `""`;schema 声明的其余配置键产出侧均不出现 | -| `usage` | object | [T-SessionUsage](#t-sessionusage) | -| `permission_rules` | array | 恒 `[]` | -| `message_count` | integer | 恒 `0` | -| `last_seq` | integer | 事件水位或 `0`,见上 | - -schema 另声明的 `current_prompt_id` 产出侧从不出现(仅快照的 `in_flight_turn` 有同名字段)。 +```ts +type Session = { + id: string; // `session_...` + workspace_id: string; // 所属工作区 id(`wd__`) + title: string; // 未设置时为 "" + created_at: string; // ISO 8601 + updated_at: string; // ISO 8601 + archived_at?: string; // ISO 8601;未归档时不出现 + busy: boolean; // 任一 Agent 有活动轮次或后台任务 + main_turn_active: boolean; // main agent 轮次进行中 + pending_interaction: 'none' | 'approval' | 'question'; + last_turn_reason?: 'completed' | 'cancelled' | 'failed'; + archived: boolean; + last_prompt?: string; // 最近一条提示词文本 + metadata: { + cwd: string; + [key: string]: unknown; // 附加自定义任意键(goal 键被剔除) + }; + agent_config: { + model: string; // 存活会话取绑定模型,否则 "" + }; + usage: SessionUsage; + permission_rules: unknown[]; // 恒 [] + message_count: number; // 恒 0 + last_seq: number; // 事件水位或 0 +}; +``` + +- 返回会话的各端点(除快照)中 `usage` 恒为全 0 的 [T-SessionUsage](#t-sessionusage)、`permission_rules` 恒 `[]`、`message_count` 恒 `0`;`last_seq` 仅 `GET /api/v1/sessions/{session_id}` 携带真实事件水位,其余端点恒 `0`。 +- `last_turn_reason`:存活会话取实时值,冷会话取最后持久化值,均无则缺省。 +- `agent_config` 恒只有 `model` 一键,schema 声明的其余配置键产出侧均不出现;schema 另声明的 `current_prompt_id` 产出侧从不出现(仅快照的 `in_flight_turn` 有同名字段)。 ### T-SessionUsage -`{ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, total_cost_usd, context_tokens, context_limit, turn_count }`——全部 number。普通会话端点恒全 0;快照端点用法不同,见 [T-SnapshotUsage](#t-snapshotusage)。 +```ts +type SessionUsage = { + input_tokens: number; + output_tokens: number; + cache_read_tokens: number; + cache_creation_tokens: number; + total_cost_usd: number; + context_tokens: number; + context_limit: number; + turn_count: number; +}; +``` + +普通会话端点恒全 0;快照端点用法不同,见 [T-SnapshotUsage](#t-snapshotusage)。 ### T-SessionStatus main agent 的实时状态汇总。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `busy` | boolean | 同 T-Session 的 `busy` | -| `model` | string | 可缺省:模型别名;未绑定时不出现 | -| `thinking_level` | string | 思考档位;模型未绑定时为 `""` | -| `permission` | string | `manual` / `yolo` / `auto` | -| `plan_mode` | boolean | Plan 模式 | -| `swarm_mode` | boolean | swarm 模式 | -| `tower_mode` | boolean | tower 模式 | -| `context_tokens` | integer | 当前上下文 tokens | -| `max_context_tokens` | integer | 可缺省:上下文上限;不可解析时不出现 | -| `context_usage` | number | 可缺省:上下文占比(0–1);无上限时不出现 | +```ts +type SessionStatus = { + busy: boolean; // 同 Session.busy + model?: string; // 模型别名;未绑定时不出现 + thinking_level: string; // 模型未绑定时为 "" + permission: 'manual' | 'yolo' | 'auto'; + plan_mode: boolean; // Plan 模式 + swarm_mode: boolean; + tower_mode: boolean; + context_tokens: number; // 当前上下文 tokens + max_context_tokens?: number; // 上下文上限;不可解析时不出现 + context_usage?: number; // 上下文占比(0–1);无上限时不出现 +}; +``` ### T-GoalSnapshot -目标快照(camelCase 载荷):`{ goalId, objective, completionCriterion?, status, turnsUsed, tokensUsed, wallClockMs, budget, terminalReason? }`。 +目标快照(camelCase 载荷),与 `goal.updated` 事件的载荷共享。 -- `status`:`active` / `paused` / `blocked` / `complete`。 -- `budget`:`{ tokenBudget, turnBudget, wallClockBudgetMs, remainingTokens, remainingTurns, remainingWallClockMs }`(六项均 number 或 `null`)加 `{ tokenBudgetReached, turnBudgetReached, wallClockBudgetReached, overBudget }`(均 boolean)。 +```ts +type GoalSnapshot = { + goalId: string; + objective: string; + completionCriterion?: string; + status: 'active' | 'paused' | 'blocked' | 'complete'; + turnsUsed: number; + tokensUsed: number; + wallClockMs: number; + terminalReason?: string; + budget: { + tokenBudget: number | null; + turnBudget: number | null; + wallClockBudgetMs: number | null; + remainingTokens: number | null; + remainingTurns: number | null; + remainingWallClockMs: number | null; + tokenBudgetReached: boolean; + turnBudgetReached: boolean; + wallClockBudgetReached: boolean; + overBudget: boolean; + }; +}; +``` + +### T-InFlightTurn + +进行中轮次的实时投影,仅由快照的 `in_flight_turn` 产出。 + +```ts +type InFlightTurn = { + turn_id: number; + assistant_text: string; + thinking_text: string; + running_tools: { + tool_call_id: string; + name: string; + args?: unknown; + description?: string; + display?: unknown; + last_progress?: { + kind: 'stdout' | 'stderr' | 'progress' | 'status' | 'custom'; + text?: string; + percent?: number; + }; + }[]; + current_prompt_id?: string; +}; +``` + +**消息与提示词。** ### T-Message 消息对象。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | string | 消息 id(`msg__<6 位序号>` 或核心 id) | -| `session_id` | string | 所属会话 | -| `role` | string | `user` / `assistant` / `tool` / `system` | -| `content` | array | [T-MessageContent](#t-messagecontent) 数组 | -| `created_at` | string | ISO 8601,单调递增 | -| `metadata` | object | 可缺省:仅当消息带 origin 时——`{ origin: <核心 PromptOrigin 对象> }`(camelCase 嵌套,原样透传) | +```ts +type Message = { + id: string; // `msg__<6 位序号>` 或核心 id + session_id: string; + role: 'user' | 'assistant' | 'tool' | 'system'; + content: MessageContent[]; + created_at: string; // ISO 8601,单调递增 + metadata?: Record; // 仅当消息带 origin 时:{ origin: PromptOrigin }(camelCase 嵌套,原样透传) +}; +``` schema 声明的 `prompt_id` / `parent_message_id` 产出侧从不出现。 ### T-MessageContent -消息内容块,按 `type` 区分: +消息内容块,按 `type` 区分。 -| `type` | 字段 | 说明 | -| --- | --- | --- | -| `text` | `text: string` | 文本;`audio_url` 降级为 `[audio:]` 文本 | -| `thinking` | `thinking: string, signature?: string` | 思考块 | -| `tool_use` | `tool_call_id, tool_name, input` | assistant 消息的工具调用;`input` 为解析后的参数(解析失败回原字符串) | -| `tool_result` | `tool_call_id, output, is_error?: boolean` | tool 角色消息;`output` 有媒体块时为原始内容块数组,否则为拼接文本;`is_error` 仅 `true` 时出现 | -| `image` / `video` | `source` | 见下 | -| `file` | `file_id?, path?, name?, media_type?, size?` | 仅出现在输入(提示词 / 技能提交);REST 投影不产出 | +```ts +type MessageContent = + | { type: 'text'; text: string } // audio_url 降级为 [audio:] 文本 + | { type: 'thinking'; thinking: string; signature?: string } + | { type: 'tool_use'; tool_call_id: string; tool_name: string; input: unknown } // input 为解析后的参数(解析失败回原字符串) + | { type: 'tool_result'; tool_call_id: string; output: unknown; is_error?: boolean } // is_error 仅 true 时出现 + | { type: 'image' | 'video'; source: ImageSource } + | { type: 'file'; file_id?: string; path?: string; name?: string; media_type?: string; size?: number }; // 仅出现在输入(提示词 / 技能提交);REST 投影不产出 + +type ImageSource = + | { kind: 'url'; url: string; id?: string } // 外部 URL + | { kind: 'base64'; media_type: string; data: string } // 仅提示词提交回显 + | { kind: 'session_media'; file_id: string }; // 会话媒体引用 +``` -`image` / `video` 的 `source`(产出侧三种,按 `kind` 区分):`{ kind: "url", url, id? }`(外部 URL)、`{ kind: "base64", media_type, data }`(仅提示词提交回显)、`{ kind: "session_media", file_id }`(会话媒体引用)。schema 声明的 `{ kind: "file", file_id }` 与 `{ kind: "path", path }` 为输入专用变体,产出侧不出现。 +- `tool_result` 的 `output`:有媒体块时为原始内容块数组,否则为拼接文本。 +- `image` / `video` 的 `source` 产出侧仅上述三种;schema 声明的 `{ kind: 'file', file_id }` 与 `{ kind: 'path', path }` 为输入专用变体,产出侧不出现。 ### T-PromptItem 提示词队列项 / 提交结果。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `prompt_id` | string | 提示词 id | -| `user_message_id` | string | 用户消息 id(Skill 捆绑提交时与 `prompt_id` 相同) | -| `status` | string | `running` / `queued` / `blocked` | -| `content` | array | 投影后的用户输入([T-MessageContent](#t-messagecontent) 数组,剥离 Skill 捆绑块) | -| `created_at` | string | ISO 8601 | +```ts +type PromptItem = { + prompt_id: string; + user_message_id: string; // Skill 捆绑提交时与 prompt_id 相同 + status: 'running' | 'queued' | 'blocked'; + content: MessageContent[]; // 投影后的用户输入(剥离 Skill 捆绑块) + created_at: string; // ISO 8601 +}; +``` + +### T-PromptOrigin + +提示词来源(camelCase 嵌套对象,原样透传)。 + +```ts +type PromptOrigin = { + kind: + | 'user' + | 'skill_activation' + | 'plugin_command' + | 'injection' + | 'shell_command' + | 'compaction_summary' + | 'system_trigger' + | 'task' + | 'background_task' + | 'cron_job' + | 'cron_missed' + | 'hook_result' + | 'retry'; + [key: string]: unknown; // 各态附带相应上下文字段 +}; +``` + +**交互。** ### T-ApprovalRequest -审批请求:`{ approval_id, session_id, turn_id?, tool_call_id, tool_name, action, tool_input_display, created_at, expires_at }`。 +审批请求。 -- `turn_id`:number,可缺省。 -- `tool_call_id`:缺省时回退为交互 id。 -- `tool_input_display`:[T-ToolInputDisplay](#t-toolinputdisplay)。 -- `expires_at`:`created_at` 之后 24 小时。 +```ts +type ApprovalRequest = { + approval_id: string; + session_id: string; + turn_id?: number; + tool_call_id: string; // 缺省时回退为交互 id + tool_name: string; + action: string; + tool_input_display: ToolInputDisplay; + created_at: string; // ISO 8601 + expires_at: string; // ISO 8601,created_at 之后 24 小时 +}; +``` ### T-ToolInputDisplay -工具输入展示,按 `kind` 区分:`command`(`command` / `cwd?` / `description?` / `language?`)、`file_io`(`operation` / `path` / `detail?` / `content?` / `before?` / `after?`)、`diff`(`path` / `before` / `after` / `hunks?`)、`search`(`query` / `scope?`)、`url_fetch`(`url` / `method?`)、`agent_call`(`agent_name` / `prompt` / `background?`)、`skill_call`(`skill_name` / `args?`)、`todo_list`(`items: { title, status }[]`)、`task`(`task_id` / `status` / `description` / `task_kind?`)、`task_stop`(`task_id` / `task_description`)、`plan_review`(`plan` / `path?` / `options?: { label, description }[]`)、`goal_start`(`objective` / `completionCriterion?` / `mode`)、`generic`(`summary` / `detail?`)。 +工具输入展示,按 `kind` 区分。 + +```ts +type ToolInputDisplay = + | { kind: 'command'; command: string; cwd?: string; description?: string; language?: 'bash' } + | { + kind: 'file_io'; + operation: 'read' | 'write' | 'edit' | 'glob' | 'grep'; + path: string; + detail?: string; + content?: string; + before?: string; + after?: string; + } + | { kind: 'diff'; path: string; before: string; after: string; hunks?: unknown } + | { kind: 'search'; query: string; scope?: string } + | { kind: 'url_fetch'; url: string; method?: string } + | { kind: 'agent_call'; agent_name: string; prompt: string; background?: boolean } + | { kind: 'skill_call'; skill_name: string; args?: string } + | { kind: 'todo_list'; items: { title: string; status: string }[] } + | { kind: 'task'; task_id: string; status: string; description: string; task_kind?: string } + | { kind: 'task_stop'; task_id: string; task_description: string } + | { kind: 'plan_review'; plan: string; path?: string; options?: { label: string; description: string }[] } + | { kind: 'goal_start'; objective: string; completionCriterion?: string; mode: 'manual' | 'yolo' } + | { kind: 'generic'; summary: string; detail?: string }; +``` ### T-QuestionRequest 提问请求。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `question_id` | string | 交互 id | -| `session_id` | string | 所属会话 | -| `turn_id` | number | 可缺省 | -| `tool_call_id` | string | 可缺省 | -| `questions` | array | 1–4 个 T-QuestionItem | -| `created_at` | string | ISO 8601 | - -T-QuestionItem:`{ id: "q_", question, header?, body?, options, multi_select?, allow_other, other_label?, other_description? }`——`options` 为 2–4 个 `{ id: "opt__", label, description? }`(id 由投影合成);`allow_other` 恒产出。 +```ts +type QuestionRequest = { + question_id: string; // 交互 id + session_id: string; + turn_id?: number; + tool_call_id?: string; + questions: QuestionItem[]; // 1–4 个 + created_at: string; // ISO 8601 +}; + +type QuestionItem = { + id: string; // `q_`,投影合成 + question: string; + header?: string; + body?: string; + options: QuestionOption[]; // 2–4 个 + multi_select?: boolean; + allow_other: true; // 恒产出 + other_label?: string; + other_description?: string; +}; + +type QuestionOption = { + id: string; // `opt__`,投影合成 + label: string; + description?: string; +}; +``` + +**任务与终端。** ### T-Task 后台任务。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | string | 任务 id | -| `session_id` | string | 所属会话 | -| `kind` | string | `subagent` / `bash` / `tool`(核心映射:process→`bash`、agent→`subagent`、question→`tool`) | -| `description` | string | 描述 | -| `status` | string | `running` / `completed` / `failed` / `cancelled`(核心映射:timed_out→`failed`、killed→`cancelled`、lost→`failed`) | -| `created_at` | string | 取 startedAt,ISO 8601 | -| `started_at` | string | 与 `created_at` 相同 | -| `completed_at` | string | 可缺省:结束时间 | -| `command` | string | 可缺省:仅 `bash` 任务 | -| `model` | string | 可缺省:仅 `subagent` 任务且有值 | -| `thinking_effort` | string | 可缺省:同上 | -| `agent_id` | string | 可缺省:同上 | -| `subagent_type` | string | 可缺省:同上 | -| `parent_tool_call_id` | string | 可缺省:`subagent` / `bash` 任务且有值 | -| `output_preview` | string | 可缺省:仅 `with_output` 读取且输出非空 | -| `output_bytes` | integer | 可缺省:同上 | -| `run_in_background` | boolean | `detached ?? true` | +```ts +type Task = { + id: string; + session_id: string; + kind: 'subagent' | 'bash' | 'tool'; // 核心映射:process→bash、agent→subagent、question→tool + description: string; + status: 'running' | 'completed' | 'failed' | 'cancelled'; // 核心映射:timed_out→failed、killed→cancelled、lost→failed + created_at: string; // ISO 8601,取 startedAt + started_at: string; // 与 created_at 相同 + completed_at?: string; // ISO 8601 + command?: string; // 仅 bash 任务 + model?: string; // 仅 subagent 任务且有值 + thinking_effort?: string; // 同上 + agent_id?: string; // 同上 + subagent_type?: string; // 同上 + parent_tool_call_id?: string; // subagent / bash 任务且有值 + output_preview?: string; // 仅 with_output 读取且输出非空 + output_bytes?: number; // 同上 + run_in_background: boolean; // detached ?? true +}; +``` REST 的 T-Task 不含 `subagent_phase` / `suspended_reason` / `swarm_index`——那些字段只在快照的 subagent 条目上(见 [T-SnapshotSubagent](#t-snapshotsubagent))。 ### T-Terminal -`{ id, session_id, cwd, shell, cols, rows, status, created_at, exited_at?, exit_code? }`——`status` 为 `running` / `exited`;`exited_at` 与 `exit_code`(integer 或 `null`,例如因信号终止时)可缺省。 - -### T-Workspace - -`{ id, root, name, created_at, last_opened_at, session_count }`——全字段必有;`created_at` / `last_opened_at` 为 ISO 8601,`session_count` 为 integer。注册与重命名会广播全局事件 `event.workspace.created` / `event.workspace.updated`。 +```ts +type Terminal = { + id: string; + session_id: string; + cwd: string; + shell: string; + cols: number; + rows: number; + status: 'running' | 'exited'; + created_at: string; // ISO 8601 + exited_at?: string; // ISO 8601 + exit_code?: number | null; // 例如因信号终止时为 null +}; +``` + +**快照。** -### T-SkillDescriptor +### T-SnapshotResponse -`{ name, description, path, source, type?, disable_model_invocation? }`——`source` 为 `project` / `user` / `extra` / `builtin`;`type` 标识技能类别(只有用户可激活的类型才能被激活);`disable_model_invocation` 会让技能对模型不可见。 +会话快照。 -### T-CapabilityStatus +```ts +type SnapshotResponse = { + as_of_seq: number; // 事件日志水位 + epoch: string; // 事件 epoch(冷会话可为 "") + session: Session; // agent_config.model 取实时绑定,usage 为 SnapshotUsage + messages: { items: Message[]; has_more: boolean }; // 尾部最多 100 条 + in_flight_turn: InFlightTurn | null; // 无进行中轮次时为 null + subagents: SnapshotSubagent[]; // 无存活时 [] + pending_approvals: ApprovalRequest[]; + pending_questions: QuestionRequest[]; +}; +``` -能力状态(camelCase 载荷):`{ id, pluginId?, displayName, description, supported, state, version?, steps, install }`。 +### T-SnapshotUsage -- `state`:`ready`(所有必需检测步骤均为 `ok`)/ `partial` / `not_installed` / `unsupported`。 -- `steps`:`{ id, state, detail?, optional? }[]`,其 `state` 为 `ok` / `missing` / `failed`。 -- `install`:`{ running, step?, percent?, error?, note? }`,`percent` 取值 0–100。 +```ts +type SnapshotUsage = { + input_tokens: number; + output_tokens: number; + cache_read_tokens: number; + cache_creation_tokens: number; + context_tokens: number; + context_limit?: number; +}; +``` -### T-PluginSummary +与 [T-SessionUsage](#t-sessionusage) 不同:**无** `total_cost_usd` / `turn_count`,且 `context_limit` 可缺省。 -插件摘要(camelCase 载荷):`{ id, displayName, version?, enabled, state, skillCount, mcpServerCount, enabledMcpServerCount, hookCount, commandCount, hasErrors, source, originalSource?, github? }`。 +### T-SnapshotSubagent -- `state`:`ok` / `error`(加载失败也会置 `hasErrors`)。 -- `source`:`local-path` / `zip-url` / `github`。 -- `github`:`{ owner, repo, ref, installedSha? }`,`ref` 为 `{ kind: "branch" \| "tag" \| "sha", value }`。 +快照中的 subagent 条目。 -### T-ToolDescriptor +```ts +type SnapshotSubagent = { + id: string; // subagentId + session_id: string; + kind: 'subagent'; + description: string; + status: Task['status']; + subagent_phase?: 'queued' | 'working' | 'suspended' | 'completed' | 'failed'; + subagent_type?: string; + parent_tool_call_id?: string; + swarm_index?: number; + run_in_background: boolean; + model?: string; + thinking_effort?: string; + created_at: string; // ISO 8601 + started_at?: string; // ISO 8601 + completed_at?: string; // ISO 8601 + output_preview?: string; + suspended_reason?: string; +}; +``` -`{ name, description, input_schema, source, active, mcp_server_id? }`——`input_schema` 恒 `null`;`source` 为 `builtin` / `skill` / `mcp`;`mcp_server_id` 仅 MCP 工具携带(从 `mcp____` 名称解析);`active` 报告工具策略的判定结果。 +**工作区。** -### T-McpServer +### T-Workspace -`{ id, name, transport, status, tool_count, last_error? }`——`id` 与 `name` 均为 server 名称;`transport` 为 `stdio` / `http` / `sse`;`status` 为 `connected` / `connecting` / `disconnected` / `error`(核心六态压为四态:pending→`connecting`、disabled/removed→`disconnected`、failed/needs-auth→`error`)。 +```ts +type Workspace = { + id: string; + root: string; + name: string; + created_at: string; // ISO 8601 + last_opened_at: string; // ISO 8601 + session_count: number; +}; +``` -### T-Connection +注册与重命名会广播全局事件 `event.workspace.created` / `event.workspace.updated`。 -`{ id, connected_at, remote_address, user_agent, has_client_hello, subscriptions }`——`id` 为 `conn_`;`remote_address` 与 `user_agent` 可空(`null`);`subscriptions` 为排序的会话 id 数组。 +**文件与搜索。** ### T-FsEntry -文件条目:`{ path, name, kind, size?, modified_at, etag?, mime?, language_id?, is_binary?, is_symlink_to?, git_status?, child_count? }`。 +文件条目。 -- `kind`:`file` / `directory` / `symlink`。 -- `git_status`:`clean` / `modified` / `added` / `deleted` / `renamed` / `untracked` / `ignored` / `conflicted`(仅 `include_git_status: true` 时存在)。 -- `size` 为 integer;`modified_at` 为 ISO 8601。 +```ts +type FsGitStatus = + | 'clean' + | 'modified' + | 'added' + | 'deleted' + | 'renamed' + | 'untracked' + | 'ignored' + | 'conflicted'; + +type FsEntry = { + path: string; + name: string; + kind: 'file' | 'directory' | 'symlink'; + size?: number; + modified_at: string; // ISO 8601 + etag?: string; + mime?: string; + language_id?: string; + is_binary?: boolean; + is_symlink_to?: string; + git_status?: FsGitStatus; // 仅 include_git_status: true 时存在 + child_count?: number; +}; +``` ### T-FsListResponse -`{ items: T-FsEntry[], children_by_path?, truncated }`——`depth` 大于 1 时另附 `children_by_path`(路径 → 条目数组的映射);`truncated` 表示 `limit` 截断了列表。 +```ts +type FsListResponse = { + items: FsEntry[]; + children_by_path?: Record; // depth 大于 1 时另附 + truncated: boolean; // limit 截断了列表 +}; +``` ### T-FsReadResponse -`{ path, content, encoding, size, truncated, etag, mime, language_id?, line_count?, is_binary }`——`encoding` 报告实际使用的编码(`utf-8` 或 `base64`);`size` 为文件完整大小。 +```ts +type FsReadResponse = { + path: string; + content: string; + encoding: 'utf-8' | 'base64'; // 实际使用的编码 + size: number; // 文件完整大小 + truncated: boolean; + etag: string; + mime: string; + language_id?: string; + line_count?: number; + is_binary: boolean; +}; +``` ### T-FsListManyResponse -`{ results, truncated_paths?, partial_errors? }`——`results` 为每个请求路径到其条目数组的映射;`truncated_paths` 为达到 `limit` 的路径;`partial_errors` 为失败路径到其 `{ code, msg }` 错误的映射。 +```ts +type FsListManyResponse = { + results: Record; // 每个请求路径到其条目数组 + truncated_paths?: string[]; // 达到 limit 的路径 + partial_errors?: Record; // 失败路径到其错误 +}; +``` ### T-FsStatManyResponse -`{ entries }`——每个请求路径到其 [T-FsEntry](#t-fsentry)(不存在时为 `null`)的映射。 +```ts +type FsStatManyResponse = { + entries: Record; // 每个请求路径到其条目(不存在时为 null) +}; +``` ### T-FsSearchHit -`{ path, name, kind, score, match_positions }`——`score` 为 0–1 的模糊匹配得分;`match_positions` 为匹配到的字符偏移数组。响应形态为 `{ items: T-FsSearchHit[], truncated: boolean }`。 +```ts +type FsSearchHit = { + path: string; + name: string; + kind: FsEntry['kind']; + score: number; // 0–1 的模糊匹配得分 + match_positions: number[]; // 匹配到的字符偏移 +}; +``` + +响应形态为 `{ items: FsSearchHit[], truncated: boolean }`。 ### T-FsSuggestItem -结构同 [T-FsSearchHit](#t-fssearchhit);响应形态相同。 +结构同 [T-FsSearchHit](#t-fssearchhit),响应形态相同。 + +```ts +type FsSuggestItem = FsSearchHit; +``` ### T-FsGrepResponse -`{ files, files_scanned, truncated, elapsed_ms }`——`files` 的每项为 `{ path, matches }`,每个匹配为 `{ line, col, text, before, after }`(`before` / `after` 最多携带 `context_lines` 行上下文);`truncated` 表示某个匹配配额截断了结果。 +```ts +type FsGrepResponse = { + files: { + path: string; + matches: { + line: number; + col: number; + text: string; + before: string[]; // 最多携带 context_lines 行上下文 + after: string[]; // 同上 + }[]; + }[]; + files_scanned: number; + truncated: boolean; // 某个匹配配额截断了结果 + elapsed_ms: number; +}; +``` ### T-FsGitStatusResponse -`{ branch, ahead, behind, entries, additions, deletions, pullRequest }`——`entries` 把每个变更路径映射到其 `git_status`;`pullRequest`(camelCase)为 `{ number, state, url }`(`state` 为 `open` / `merged` / `closed` / `draft`)或 `null`。 +```ts +type FsGitStatusResponse = { + branch: string; + ahead: number; + behind: number; + entries: Record; // 每个变更路径到其 git_status + additions: number; + deletions: number; + pullRequest: { number: number; state: 'open' | 'merged' | 'closed' | 'draft'; url: string } | null; // camelCase 岛屿 +}; +``` ### T-FsDiffResponse -`{ path, diff, truncated }`——`diff` 为 unified diff 文本;`truncated` 表示过长的 diff 被截断。 +```ts +type FsDiffResponse = { + path: string; + diff: string; // unified diff 文本 + truncated: boolean; // 过长的 diff 被截断 +}; +``` ### T-FsBrowseResponse -`{ path, parent, entries }`——`path` 为解析后的目录;`parent` 为其父目录(文件系统根处为 `null`);`entries` 每条目为 `{ name, path, is_dir: true }`。 +```ts +type FsBrowseResponse = { + path: string; // 解析后的目录 + parent: string | null; // 父目录(文件系统根处为 null) + entries: { name: string; path: string; is_dir: true }[]; +}; +``` ### T-FsHomeResponse -`{ home, recent_roots }`——`home` 为用户主目录;`recent_roots` 列出已注册工作区的根目录(上限 8)。 +```ts +type FsHomeResponse = { + home: string; // 用户主目录 + recent_roots: string[]; // 已注册工作区的根目录(上限 8) +}; +``` ### T-FileMeta -`{ id, name, media_type, size, created_at, expires_at? }`——`id` 为 `f_...`;`media_type` 取自上传的内容类型;`expires_at` 可缺省。 +```ts +type FileMeta = { + id: string; // `f_...` + name: string; + media_type: string; // 取自上传的内容类型 + size: number; + created_at: string; // ISO 8601 + expires_at?: string; // ISO 8601 +}; +``` + +### T-SearchResponse + +```ts +type SearchResponse = { + items: { + session_id: string; + workspace_id: string; + session_title: string; + agent_id: string; + role: 'user' | 'assistant' | 'title'; + snippet: string; + time: number; // epoch 毫秒 + turn?: number; + step_id?: string; + score: number; + }[]; + has_more: boolean; + page_token?: string; + incomplete?: 'candidate_cap' | 'postings_budget' | 'deadline'; // 超出预算的页携带 + index_state: { + state: 'building' | 'ready' | 'readonly'; + indexed_sessions: number; + total_sessions: number; + documents: number; + stale?: boolean; // 仍在追赶的落后视图 + degraded?: string; // 最近一次刷新失败的信息 + }; + source: 'live' | 'index'; // 本页结果由内存转录还是持久索引提供 +}; +``` + +**配置与模型。** ### T-ConfigResponse -配置全域对象(camelCase 域名转 snake_case)加合成键;未列出的域原样透传: +配置全域对象(camelCase 域名转 snake_case)加合成键。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `providers` | object | 供应商 id → `{ type, base_url?, default_model?, has_api_key }` 的映射(必有,空为 `{}`;密钥被剥离为 `has_api_key`) | -| `models` | object | 模型别名 → 模型记录的映射(剥离 `apiKey` / `oauth`,加 `has_api_key`,其余键原样) | -| `services` | object | 内置外部服务配置(同 `models`,另把 `customHeaders` 换成 `custom_header_keys: string[]`) | -| `yolo` | boolean | 可缺省:由 `default_permission_mode === "yolo"` 合成 | -| `default_provider` | string | 全局默认供应商 id | -| `default_model` | string | 全局默认模型别名 | -| 其余域 | — | `thinking` / `plan_mode` / `default_permission_mode` / `default_plan_mode` / `permission` / `hooks` / `merge_all_available_skills` / `extra_skill_dirs` / `loop_control` / `background` / `subagent` / `secondary_model` / `experimental` / `telemetry` / `raw` 等,原样透传,可缺省 | +```ts +type ConfigResponse = { + providers: Record< + string, + { + type: string; + base_url?: string; + default_model?: string; + has_api_key: boolean; // 密钥被剥离为 has_api_key + } + >; // 必有,空为 {} + models?: Record; // 模型别名 → 模型记录(剥离 apiKey / oauth,加 has_api_key,其余键原样) + services?: unknown; // 内置外部服务配置(同 models,另把 customHeaders 换成 custom_header_keys: string[]) + yolo?: boolean; // 由 default_permission_mode === "yolo" 合成 + default_provider?: string; // 全局默认供应商 id + default_model?: string; // 全局默认模型别名 + [key: string]: unknown; // 未列出的域原样透传 +}; +``` + +未列出域(`thinking` / `plan_mode` / `default_permission_mode` / `default_plan_mode` / `permission` / `hooks` / `merge_all_available_skills` / `extra_skill_dirs` / `loop_control` / `background` / `subagent` / `secondary_model` / `experimental` / `telemetry` / `raw` 等)原样透传,可缺省。 -### T-AuthSummary +### T-ModelCatalogItem -`{ models_ready, providers_count, managed_provider }`——`managed_provider` 为 `{ name, status }`(`status` 为 `authenticated` / `expired` / `revoked` / `unauthenticated`)或 `null`。全局默认模型别名改从 `GET /api/v1/config` 的 `default_model` 读取,本对象不携带。 +```ts +type ModelCatalogItem = { + provider: string; // 所属供应商 id + model: string; // 别名 id + display_name?: string; + max_context_size: number; // 以 token 计的上下文窗口 + capabilities?: string[]; + support_efforts?: string[]; + default_effort?: string; +}; +``` -### T-OAuthFlowStart +### T-ProviderCatalogItem -OAuth 流程发起结果,按 `status` 区分: +```ts +type ProviderCatalogItem = { + id: string; + type: string; // 通信协议:kimi / openai / openai_responses / anthropic / google-genai / vertexai + base_url?: string; + default_model?: string; + has_api_key: boolean; + status: 'connected' | 'error' | 'unconfigured'; + models?: string[]; // 该供应商的模型别名 id +}; +``` -- `pending`:`{ flow_id, provider, status: "pending", verification_uri, verification_uri_complete, user_code, expires_in, interval, expires_at }`——`expires_in`(秒)与 `expires_at`(ISO 8601)是同一时限的两种表示。 -- `authenticated`:`{ flow_id, provider, status: "authenticated" }`。 +### T-CatalogProviderItem -### T-OAuthFlowSnapshot +models.dev 目录条目。 -`{ flow_id, provider, status, verification_uri, verification_uri_complete, user_code, expires_in, expires_at, interval, resolved_at?, error_message? }`——`status` 为 `pending` / `authenticated` / `denied` / `expired` / `cancelled`;离开 `pending` 后 `resolved_at` 记录到达终态的时间,`error_message` 描述失败的流程。 +```ts +type CatalogProviderItem = { + id: string; + name: string; + wire_type: 'kimi' | 'openai' | 'openai_responses' | 'anthropic' | 'google-genai' | 'vertexai' | null; // 解析出的协议 + guessed: boolean; // 启发式解析标记 + needs_base_url: boolean; + rejected: boolean; + reject_reason: string | null; + env_key: string | null; // 上游约定的 API 密钥环境变量 + models: { + id: string; + name?: string; + max_context_size: number; + capabilities?: string[]; + reasoning: boolean; + }[]; +}; +``` -### T-ManagedUsageResult +### T-RefreshProviderModelsResponse -托管用量结果,按 `kind` 区分: +```ts +type RefreshProviderModelsResponse = { + changed: { provider_id: string; provider_name: string; added: number; removed: number }[]; // 新增 / 移除的别名数 + unchanged: string[]; // 无差异的供应商 id + failed: { provider: string; reason: string }[]; +}; +``` -- `ok`:`{ kind: "ok", summary, limits, extra_usage }`——`summary`(可空)是主配额行,`limits` 列出每个配额窗口;一行(T-UsageRow)为 `{ name?, window?, used, limit, reset_at? }`,其中 `window` 为 `{ duration, unit }`(`unit` 为 `minute` / `hour` / `day` / `week`)。`extra_usage`(可空)是按量付费钱包:`{ balance_cents, total_cents, monthly_charge_limit_enabled, monthly_charge_limit_cents, monthly_used_cents, currency }`(金额均 integer 分)。 -- `error`:`{ kind: "error", message, status? }`——`status` 为上游 HTTP 状态码(如存在)。 +**账号。** -### T-ManagedUserInfoResult +### T-AuthSummary -托管账号资料(camelCase 载荷),按 `kind` 区分: +```ts +type AuthSummary = { + models_ready: boolean; + providers_count: number; + managed_provider: { + name: string; + status: 'authenticated' | 'expired' | 'revoked' | 'unauthenticated'; + } | null; +}; +``` -- `ok`:`{ kind: "ok", userInfo }`——`userInfo` 始终携带 `userId`、`nickname`、`status`、`region`、`userLevel`、`userLevelName`、`domain`、`domainName`,并可能附加 `globalId`、`bio`、`avatar`、`username`、`email`、`phone`(`{ countryCode, number }`)、`createdTime`、`lastLoginTime`。 -- `error`:`{ kind: "error", message, status? }`。 +全局默认模型别名改从 `GET /api/v1/config` 的 `default_model` 读取,本对象不携带。 -### T-ModelCatalogItem +### T-OAuthFlowStart -`{ provider, model, display_name?, max_context_size, capabilities?, support_efforts?, default_effort? }`——`model` 是别名 id,`provider` 是所属供应商 id;`max_context_size` 是以 token 计的上下文窗口。 +OAuth 流程发起结果,按 `status` 区分。 -### T-ProviderCatalogItem +```ts +type OAuthFlowStart = + | { + flow_id: string; + provider: string; + status: 'pending'; + verification_uri: string; + verification_uri_complete: string; + user_code: string; + expires_in: number; // 秒;与 expires_at 是同一时限的两种表示 + interval: number; + expires_at: string; // ISO 8601 + } + | { flow_id: string; provider: string; status: 'authenticated' }; +``` -`{ id, type, base_url?, default_model?, has_api_key, status, models? }`——`type` 为通信协议(`kimi` / `openai` / `openai_responses` / `anthropic` / `google-genai` / `vertexai`);`status` 为 `connected` / `error` / `unconfigured`;`models` 为该供应商的模型别名 id 数组。 +### T-OAuthFlowSnapshot -### T-CatalogProviderItem +```ts +type OAuthFlowSnapshot = { + flow_id: string; + provider: string; + status: 'pending' | 'authenticated' | 'denied' | 'expired' | 'cancelled'; + verification_uri: string; + verification_uri_complete: string; + user_code: string; + expires_in: number; + expires_at: string; // ISO 8601 + interval: number; + resolved_at?: string; // ISO 8601;离开 pending 后记录到达终态的时间 + error_message?: string; // 描述失败的流程 +}; +``` -models.dev 目录条目:`{ id, name, wire_type, guessed, needs_base_url, rejected, reject_reason, env_key, models }`——`wire_type` 为解析出的协议(可空,枚举与供应商 `type` 相同);`guessed` 标记启发式解析;`env_key` 是上游约定的 API 密钥环境变量(可空);`reject_reason` 可空;`models` 为 `{ id, name?, max_context_size, capabilities?, reasoning }[]`。 +### T-ManagedUsageResult -### T-RefreshProviderModelsResponse +托管用量结果,按 `kind` 区分。 -`{ changed, unchanged, failed }`——`changed` 为 `{ provider_id, provider_name, added, removed }[]`(新增 / 移除的别名数);`unchanged` 为无差异的供应商 id 数组;`failed` 为 `{ provider, reason }[]`。 +```ts +type ManagedUsageResult = + | { + kind: 'ok'; + summary: UsageRow | null; // 主配额行 + limits: UsageRow[]; // 每个配额窗口一行 + extra_usage: { + balance_cents: number; + total_cents: number; + monthly_charge_limit_enabled: boolean; + monthly_charge_limit_cents: number; + monthly_used_cents: number; + currency: string; + } | null; // 按量付费钱包(金额均 integer 分) + } + | { kind: 'error'; message: string; status?: number }; // status 为上游 HTTP 状态码(如存在) + +type UsageRow = { + name?: string; + window?: { duration: number; unit: 'minute' | 'hour' | 'day' | 'week' }; + used: number; + limit: number; + reset_at?: string; +}; +``` -### T-SearchResponse +### T-ManagedUserInfoResult -`{ items, has_more, page_token?, incomplete?, index_state, source }`。 +托管账号资料(camelCase 载荷),按 `kind` 区分。 -- 每项:`{ session_id, workspace_id, session_title, agent_id, role, snippet, time, turn?, step_id?, score }`——`role` 为 `user` / `assistant` / `title`;`time` 为 epoch 毫秒。 -- `incomplete`:超出预算的页携带,取值 `candidate_cap` / `postings_budget` / `deadline`。 -- `index_state`:`{ state, indexed_sessions, total_sessions, documents, stale?, degraded? }`——`state` 为 `building` / `ready` / `readonly`;`stale` 标记仍在追赶的落后视图,`degraded` 携带最近一次刷新失败的信息。 -- `source`:`live` / `index`——本页结果由内存转录还是持久索引提供。 +```ts +type ManagedUserInfoResult = + | { + kind: 'ok'; + userInfo: { + userId: string; + nickname: string; + status: string; + region: string; + userLevel: number; + userLevelName: string; + domain: number; + domainName: string; + globalId?: string; + bio?: string; + avatar?: string; + username?: string; + email?: string; + phone?: { countryCode: string; number: string }; + createdTime?: string; + lastLoginTime?: string; + }; + } + | { kind: 'error'; message: string; status?: number }; +``` + +**扩展。** -### T-SnapshotResponse +### T-SkillDescriptor -会话快照。 +```ts +type SkillDescriptor = { + name: string; + description: string; + path: string; + source: 'project' | 'user' | 'extra' | 'builtin'; + type?: string; // 技能类别(只有用户可激活的类型才能被激活) + disable_model_invocation?: boolean; // 让技能对模型不可见 +}; +``` -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `as_of_seq` | integer | 事件日志水位 | -| `epoch` | string | 事件 epoch(冷会话可为 `""`) | -| `session` | object | [T-Session](#t-session)——`agent_config.model` 取实时绑定,`usage` 为 [T-SnapshotUsage](#t-snapshotusage) | -| `messages` | object | `{ items: T-Message[], has_more }`——尾部最多 100 条 | -| `in_flight_turn` | object \| null | [T-InFlightTurn](#t-inflightturn);无进行中轮次时为 `null` | -| `subagents` | array | [T-SnapshotSubagent](#t-snapshotsubagent) 数组(无存活时 `[]`) | -| `pending_approvals` | array | [T-ApprovalRequest](#t-approvalrequest) 数组 | -| `pending_questions` | array | [T-QuestionRequest](#t-questionrequest) 数组 | +### T-CapabilityStatus -### T-SnapshotUsage +能力状态(camelCase 载荷)。 -`{ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, context_tokens, context_limit }`——与 [T-SessionUsage](#t-sessionusage) 不同:**无** `total_cost_usd` / `turn_count`,且 `context_limit` 可缺省。 +```ts +type CapabilityStatus = { + id: 'kimi-cu' | 'kimi-webbridge'; + pluginId?: string; + displayName: string; + description: string; + supported: boolean; + state: 'ready' | 'partial' | 'not_installed' | 'unsupported'; // ready = 所有必需检测步骤均为 ok + version?: string; + steps: { id: string; state: 'ok' | 'missing' | 'failed'; detail?: string; optional?: boolean }[]; + install: { + running: boolean; + step?: string; + percent?: number; // 0–100 + error?: string; + note?: string; + }; +}; +``` -### T-InFlightTurn +### T-PluginSummary -`{ turn_id, assistant_text, thinking_text, running_tools, current_prompt_id? }`——`running_tools` 为 `{ tool_call_id, name, args?, description?, display?, last_progress? }[]`,`last_progress` 为 `{ kind: "stdout" \| "stderr" \| "progress" \| "status" \| "custom", text?, percent? }`。 +插件摘要(camelCase 载荷)。 -### T-SnapshotSubagent +```ts +type PluginSummary = { + id: string; + displayName: string; + version?: string; + enabled: boolean; + state: 'ok' | 'error'; // 加载失败也会置 hasErrors + skillCount: number; + mcpServerCount: number; + enabledMcpServerCount: number; + hookCount: number; + commandCount: number; + hasErrors: boolean; + source: 'local-path' | 'zip-url' | 'github'; + originalSource?: string; + github?: { + owner: string; + repo: string; + ref: { kind: 'branch' | 'tag' | 'sha'; value: string }; + installedSha?: string; + }; +}; +``` -快照中的 subagent 条目:`{ id, session_id, kind: "subagent", description, status, subagent_phase?, subagent_type?, parent_tool_call_id?, swarm_index?, run_in_background, model?, thinking_effort?, created_at, started_at?, completed_at?, output_preview?, suspended_reason? }`——`status` 取值同 [T-Task](#t-task);`subagent_phase` 为 `queued` / `working` / `suspended` / `completed` / `failed`。 +### T-ToolDescriptor -### T-Transcript 族 +```ts +type ToolDescriptor = { + name: string; + description: string; + input_schema: null; // 恒 null + source: 'builtin' | 'skill' | 'mcp'; + active: boolean; // 工具策略的判定结果 + mcp_server_id?: string; // 仅 MCP 工具携带(从 mcp____ 名称解析) +}; +``` + +### T-McpServer + +```ts +type McpServer = { + id: string; // server 名称 + name: string; // 同 id + transport: 'stdio' | 'http' | 'sse'; + status: 'connected' | 'connecting' | 'disconnected' | 'error'; + tool_count: number; + last_error?: string; +}; +``` -转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约(客户端经同一依赖消费): +`status` 由核心六态压为四态:pending→`connecting`、disabled/removed→`disconnected`、failed/needs-auth→`error`。 -- **T-TranscriptResponse**:`{ agent_id, items, has_more, tasks, interactions, attachments, todos, prompts, meta, agents, pending_interactions, seq? }`——`items` 为 TranscriptItem(turn / marker / taskref 三态;turn 含 `steps[].frames[]`,frame 分 text / thinking / tool / notice 四种)。 -- **T-TranscriptOpsCatchupResponse**:`{ agent_id, batches, latest_seq, complete }`——`batches` 为 `{ seq, ops }[]`;TranscriptOperation 全集(判别字段为 `op`):reset / turn.upsert / step.upsert / frame.upsert / append / marker.upsert / taskref.upsert / task.upsert / interaction.upsert / attachment.upsert / todo.upsert / prompt.upsert / meta.merge / items.remove。 -- **T-TranscriptUserMessagesResponse**:`{ agents }`——每条目为 `{ agent_id, messages, attachments }`;`messages` 为 `{ turn_id, ordinal, state, origin, prompt, attachment_ids?, started_at? }[]`,`state` 为轮次状态(`queued` / `running` / `completed` / `failed` / `cancelled`)。 -- **T-TranscriptPlanResponse**:`{ agent_id, plans }`——每个计划为 `{ tool_call_id, turn_id, source, plan, path?, options?, review? }`;`source` 为 `interaction` / `display` / `output`;`review`(仅交互式审阅时存在)为 `{ state, selected_option?, feedback? }`,`state` 为 `pending` / `approved` / `rejected` / `cancelled`。 +**v2。** ### T-V2Session -v2 会话对象:`{ id, workspace, meta, activity, git? }`。 +v2 会话对象。 -- `workspace`:`{ id, cwd }`——`cwd` 可空。 -- `meta`:`{ title, last_prompt, created_at, updated_at, archived, archived_at }`——`title` / `last_prompt` 可空;`created_at` / `updated_at` 为 epoch 毫秒;`archived_at` 恒产出(integer 或 `null`)。 -- `activity`:`{ status, model }`——`status` 为 `running` / `approval` / `question` / `failed` / `idle`(冷会话恒 `idle`);`model` 为存活会话的绑定模型别名,冷会话为 `null`。 -- `git`:仅 `include=git` 时产出——`{ branch, pull_request }`,不可用时为 `{ branch: null, pull_request: null }`;`pull_request` 为 `{ number, state, url }`(`state` 为 `open` / `closed` / `merged`)或 `null`。 +```ts +type V2Session = { + id: string; + workspace: { id: string; cwd: string | null }; + meta: { + title: string | null; + last_prompt: string | null; + created_at: number; // epoch 毫秒 + updated_at: number; // epoch 毫秒 + archived: boolean; + archived_at: number | null; // 恒产出 + }; + activity: { + status: 'running' | 'approval' | 'question' | 'failed' | 'idle'; // 冷会话恒 idle + model: string | null; // 存活会话的绑定模型别名,冷会话为 null + }; + git?: { + // 仅 include=git 时产出;不可用时为 { branch: null, pull_request: null } + branch: string | null; + pull_request: { number: number; state: 'open' | 'closed' | 'merged'; url: string } | null; + }; +}; +``` ### T-V2SessionPage -`{ items, total, has_more, next_page_token }`——`items` 为 [T-V2Session](#t-v2session) 数组(`fields=id,archived` 投影时裁剪为 `{ id, archived }`);`next_page_token` 可空。 +```ts +type V2SessionPage = { + items: V2Session[]; // fields=id,archived 投影时裁剪为 { id, archived } + total: number; + has_more: boolean; + next_page_token: string | null; +}; +``` ### T-V2SessionGroupPage -`{ groups, total, has_more, next_page_token }`——`groups` 为 `{ workspace, sessions, total }[]`(`workspace` 形态同 T-V2Session 的 `workspace` 组,`total` 为该工作区匹配过滤条件的会话总数);外层 `total` 为组数。 +```ts +type V2SessionGroupPage = { + groups: { + workspace: { id: string; cwd: string | null }; + sessions: V2Session[]; + total: number; // 该工作区匹配过滤条件的会话总数 + }[]; + total: number; // 组数 + has_more: boolean; + next_page_token: string | null; +}; +``` ### T-V2BatchSessionResponse -`{ results, succeeded, failed }`——`results` 为 `{ id, ok, error? }[]`(保持输入顺序;`error` 为 `{ code, message }`);`succeeded` / `failed` 为计数。 +```ts +type V2BatchSessionResponse = { + results: { id: string; ok: boolean; error?: { code: number; message: string } }[]; // 保持输入顺序 + succeeded: number; + failed: number; +}; +``` ### T-McpManagedServer -受管 MCP server(camelCase 载荷):`{ name, config, source, origin, mutable, plugin? }`。 +受管 MCP server(camelCase 载荷)。 -- `source`:`global`(配置文件层)/ `plugin`(插件清单)/ `caller`。 -- `origin`:条目的定义位置——文件路径或插件 id。 -- `mutable`:只有用户级条目可变;插件与项目层条目均为只读。 -- `config`:[T-McpServerConfigView](#t-mcpserverconfigview)——可变条目携带完整配置;只读条目被脱敏为排序后的键名列表。 -- `plugin`:`{ id, name }`,仅插件条目携带。 +```ts +type McpManagedServer = { + name: string; + config: McpServerConfigView | string[]; // 可变条目携带完整配置;只读条目被脱敏为排序后的键名列表 + source: 'global' | 'plugin' | 'caller'; // global = 配置文件层,plugin = 插件清单 + origin: string; // 条目的定义位置——文件路径或插件 id + mutable: boolean; // 只有用户级条目可变;插件与项目层条目均为只读 + plugin?: { id: string; name: string }; // 仅插件条目携带 +}; +``` ### T-McpServerConfigView -MCP server 配置的脱敏视图,按 `transport` 区分: +MCP server 配置的脱敏视图,按 `transport` 区分。 -- `stdio`:`{ transport: "stdio", command, args?, cwd?, executor?, runtime_id?, envKeys?, enabled?, startupTimeoutMs?, toolTimeoutMs?, enabledTools?, disabledTools? }`——`envKeys`(排序的键名)替代 `env`,绝不泄露密钥值。 -- `http` / `sse`:`{ transport: "http" \| "sse", url, auth?, bearerTokenEnvVar?, headerKeys? }` 加上述公共字段——`auth` 仅取值 `"oauth"`;`headerKeys` 替代 `headers`。 +```ts +type McpServerConfigView = + | { + transport: 'stdio'; + command: string; + args?: string[]; + cwd?: string; + executor?: string; + runtime_id?: string; + envKeys?: string[]; // 替代 env(排序的键名),绝不泄露密钥值 + enabled?: boolean; + startupTimeoutMs?: number; + toolTimeoutMs?: number; + enabledTools?: string[]; + disabledTools?: string[]; + } + | { + transport: 'http' | 'sse'; + url: string; + auth?: 'oauth'; + bearerTokenEnvVar?: string; + headerKeys?: string[]; // 替代 headers + enabled?: boolean; + startupTimeoutMs?: number; + toolTimeoutMs?: number; + enabledTools?: string[]; + disabledTools?: string[]; + }; +``` ### T-McpServerInspection -`{ serverId, locator, runtimeName, canonicalUrl?, origin, config, enabled, editable, authStatus, checkedAt?, error? }`——`serverId` 为 `global:` 或 `plugin::`(URL 编码);`locator` 为 `{ source: "global", name }` 或 `{ source: "plugin", pluginId, serverName }`;`config` 为 [T-McpServerConfigView](#t-mcpserverconfigview);`checkedAt` 为 epoch 毫秒。 +```ts +type McpServerInspection = { + serverId: string; // `global:` 或 `plugin::`(URL 编码) + locator: { source: 'global'; name: string } | { source: 'plugin'; pluginId: string; serverName: string }; + runtimeName: string; + canonicalUrl?: string; + origin: 'global' | 'plugin' | 'caller'; + config: McpServerConfigView; + enabled: boolean; + editable: boolean; + authStatus: McpServerAuthStatus['authStatus']; + checkedAt?: number; // epoch 毫秒 + error?: string; +}; +``` ### T-McpServerAuthStatus -`{ name, authStatus }`——`authStatus` 为 `not-applicable` / `bearer-token` / `oauth-required` / `oauth-authorized` / `oauth-expired` / `unavailable`。 +```ts +type McpServerAuthStatus = { + name: string; + authStatus: + | 'not-applicable' + | 'bearer-token' + | 'oauth-required' + | 'oauth-authorized' + | 'oauth-expired' + | 'unavailable'; +}; +``` -### T-TokenUsage +**服务。** + +### T-Connection -`{ inputOther, output, inputCacheRead, inputCacheCreation }`(camelCase)。 +活跃 WS 连接,由 REST `GET /connections` 返回。 + +```ts +type Connection = { + id: string; // `conn_` + connected_at: string; // ISO 8601 + remote_address: string | null; + user_agent: string | null; + has_client_hello: boolean; + subscriptions: string[]; // 排序的会话 id +}; +``` + +### WS 类型 + +WS 帧携带的载荷类型:协议事件的内嵌对象与转录契约。 + +**事件载荷。** ### T-AgentPhase -agent 阶段(`agent.status.updated` 的 `phase` 字段):按 `kind` 区分的对象,`kind` 为 `idle` / `running` / `streaming` / `tool_call` / `retrying` / `awaiting_approval` / `interrupted` / `ended` 之一,各态附带相应上下文字段(如 `turnId`、`step`)。 +agent 阶段(`agent.status.updated` 的 `phase` 字段)。 -### T-PromptOrigin +```ts +type AgentPhase = { + kind: + | 'idle' + | 'running' + | 'streaming' + | 'tool_call' + | 'retrying' + | 'awaiting_approval' + | 'interrupted' + | 'ended'; + [key: string]: unknown; // 各态附带相应上下文字段(如 turnId、step) +}; +``` + +### T-TokenUsage -提示词来源十三态:`user` / `skill_activation` / `plugin_command` / `injection` / `shell_command` / `compaction_summary` / `system_trigger` / `task` / `background_task` / `cron_job` / `cron_missed` / `hook_result` / `retry`(camelCase 嵌套对象,原样透传)。 +token 用量(camelCase 载荷)。 + +```ts +type TokenUsage = { + inputOther: number; + output: number; + inputCacheRead: number; + inputCacheCreation: number; +}; +``` ### T-KimiError -核心错误对象:`{ code, message, name?, details?, retryable, cause? }`——`code` 为核心错误码字符串;`retryable` 为 boolean;`cause` 递归同构。 +核心错误对象。 + +```ts +type KimiError = { + code: string; // 核心错误码字符串 + message: string; + name?: string; + details?: unknown; + retryable: boolean; + cause?: unknown; // 递归同构 +}; +``` + +**转录。** + +### T-Transcript 族 + +转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约(客户端经同一依赖消费),`TranscriptItem` / `TranscriptOperation` 等嵌套类型均定义于该包。 + +**T-TranscriptResponse**: + +```ts +type TranscriptResponse = { + agent_id: string; + items: TranscriptItem[]; // turn / marker / taskref 三态;turn 含 steps[].frames[],frame 分 text / thinking / tool / notice 四种 + has_more: boolean; + tasks: TranscriptTask[]; + interactions: Interaction[]; + attachments: Attachment[]; + todos: Todo[]; + prompts: TranscriptPrompt[]; + meta: TranscriptMeta; + agents: AgentDescriptor[]; + pending_interactions: string[]; + seq?: number; +}; +``` + +**T-TranscriptOpsCatchupResponse**: + +```ts +type TranscriptOpsCatchupResponse = { + agent_id: string; + batches: { seq: number; ops: TranscriptOperation[] }[]; + latest_seq: number; + complete: boolean; +}; +``` + +`TranscriptOperation` 全集(判别字段为 `op`):reset / turn.upsert / step.upsert / frame.upsert / append / marker.upsert / taskref.upsert / task.upsert / interaction.upsert / attachment.upsert / todo.upsert / prompt.upsert / meta.merge / items.remove。 + +**T-TranscriptUserMessagesResponse**: + +```ts +type TranscriptUserMessagesResponse = { + agents: { + agent_id: string; + messages: { + turn_id: string; + ordinal: number; + state: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'; // 轮次状态 + origin: TurnOrigin; + prompt: string; + attachment_ids?: string[]; + started_at?: string; + }[]; + attachments: Attachment[]; + }[]; +}; +``` + +**T-TranscriptPlanResponse**: + +```ts +type TranscriptPlanResponse = { + agent_id: string; + plans: { + tool_call_id: string; + turn_id: string; + source: 'interaction' | 'display' | 'output'; + plan: string; + path?: string; + options?: { label: string; description?: string }[]; + review?: { + // 仅交互式审阅时存在 + state: 'pending' | 'approved' | 'rejected' | 'cancelled'; + selected_option?: string; + feedback?: string; + }; + }[]; +}; +``` ## 二进制与流式端点 From f6e2cff0c95b5ff13345f94b50bfb30d33e75128 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:10:44 +0800 Subject: [PATCH 19/47] docs(zh): split the tasks-and-terminal domain into tasks and terminal --- docs/zh/reference/server-api.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 00909eac36c..2faa0c5b368 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -1632,7 +1632,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 0, "msg": "success", "data": { "agent_id": "main", "plans": [ { "tool_call_id": "toolu_01J...", "turn_id": 2, "source": "interaction", "plan": "# Plan\n ...", "path": "/Users/dev/my-app/.kimi-code/plans/....md", "options": [ { "label": "实施" } ], "review": { "state": "approved", "selected_option": "实施" } } ] }, "request_id": "01JZX4..." } ``` -### 任务与终端 +### 任务 **后台任务。** @@ -1703,6 +1703,9 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin { "code": 0, "msg": "success", "data": { "detached": true, "status": "running" }, "request_id": "01JZX4..." } ``` + +### 终端 + **终端。** PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定会跳过它们,除非传入 `--allow-remote-terminals`)。注意:终端输入输出的 `terminal_*` WebSocket 帧当前是死协议(见 [terminal 帧](#terminal-帧))——REST 侧只管理终端生命周期。 @@ -3206,7 +3209,7 @@ payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__glob ### terminal 帧 -`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点(见「任务与终端」域的 [终端](#任务与终端) 部分)不受影响。 +`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点见 [终端](#终端) 域。 ## 完整错误码 From 446586dadda4a2575c3bab735f3985db826ae1a7 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:16:03 +0800 Subject: [PATCH 20/47] docs(zh): rewrite the service module as the endpoint format reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New per-endpoint shape: domain H2 with intro and one merged endpoint table; endpoint H3 with description, 请求体 table (when present), 响应体 type + table, non-zero codes, and a pretty-printed 响应示例. The REST 端点 wrapper heading is dropped in favor of an unheaded lead-in. --- docs/zh/reference/server-api.md | 436 +++++++++++++++++++++++--------- 1 file changed, 316 insertions(+), 120 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 2faa0c5b368..31da719bce7 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -83,13 +83,11 @@ HTTP 状态码例外(非 200): - **游标式**:`before_id` / `after_id`(互斥)加 `page_size`(1–100),响应为 `{ items, has_more }`。用于会话列表、消息列表、子会话列表;转录分页的游标为 `before_turn` / `after_turn`。 - **`page_token`**:不透明令牌(绑定了查询条件的指纹),用于 `POST /api/v1/search` 与 `GET /api/v2/sessions`。翻页途中改变任何查询条件会使令牌失效:v2 返回 `40922`,search 返回 `40001`。`GET /api/v2/sessions` 另提供无状态的 `page` 页码模式作为替代。 -## REST 端点 - 下文按业务域分组列出全部端点,覆盖 `/api/v1` 与 `/api/v2`(路径前缀区分版本)。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 -### 服务 +## 服务 -服务自身的探活、身份、关停与连接管理。 +服务自身的探活、身份、关停与连接管理;全局配置的读取与合并式更新;模型别名与供应商管理,以及 models.dev 目录浏览。 | 方法与路径 | 说明 | | --- | --- | @@ -97,28 +95,46 @@ HTTP 状态码例外(非 200): | `GET /api/v1/meta` | 服务版本、能力集、`server_id`、实验开关 | | `POST /api/v1/shutdown` | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 | | `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | +| `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | +| `POST /api/v1/config` | 合并式更新配置,并广播 `event.config.changed` | +| `GET /api/v1/models` | 列出已配置的模型别名 | +| `POST /api/v1/models/{model_id}:set_default` | 设置全局默认模型 | +| `GET /api/v1/providers` | 列出供应商 | +| `POST /api/v1/providers` | 创建供应商(201) | +| `GET /api/v1/providers/{provider_id}` | 读取供应商(含已存密钥) | +| `PUT /api/v1/providers/{provider_id}` | 整体替换供应商配置 | +| `DELETE /api/v1/providers/{provider_id}` | 删除供应商(204) | +| `POST /api/v1/providers/{provider_id}:refresh` | 刷新该供应商的模型元数据 | +| `POST /api/v1/providers:{action}` | 集合级动作:`refresh` / `refresh_oauth` / `import_catalog` / `import_registry` | +| `GET /api/v1/catalog/providers` | 浏览 models.dev 目录(服务端代理) | +| `GET /api/v1/catalog/providers/{catalog_id}` | 读取目录中单个条目 | -#### `GET /api/v1/healthz` +### `GET /api/v1/healthz` -供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。 +供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。免鉴权(见 [例外接口](#鉴权))。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `ok` | boolean | 恒 `true` | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "ok": true }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/meta` +### `GET /api/v1/meta` 返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -133,120 +149,178 @@ HTTP 状态码例外(非 200): | `experimental_flags` | object | 实验开关 id → 是否启用 | | `features` | array | 引擎 feature 单元,形如 `{ name, state, meta }`;`state` 为 `Pending` / `Activating` / `Active` / `Unloading` / `Failed` | -**示例**: +**响应示例**: ```json { - "code": 0, "msg": "success", - "data": { "server_version": "0.40.0", "capabilities": { "websocket": true, "...": true }, "server_id": "01JZX4...", "started_at": "2026-09-02T08:00:00.000Z", "open_in_apps": [], "dangerous_bypass_auth": false, "backend": "v2", "experimental_flags": { "search_worker": true }, "features": [ { "name": "fileHistory", "state": "Active", "meta": {} } ] }, + "code": 0, + "msg": "success", + "data": { + "server_version": "0.40.0", + "capabilities": { "websocket": true, "...": true }, + "server_id": "01JZX4...", + "started_at": "2026-09-02T08:00:00.000Z", + "open_in_apps": [], + "dangerous_bypass_auth": false, + "backend": "v2", + "experimental_flags": { "search_worker": true }, + "features": [ { "name": "fileHistory", "state": "Active", "meta": {} } ] + }, "request_id": "01JZX4..." } ``` -#### `POST /api/v1/shutdown` +### `POST /api/v1/shutdown` -请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。无参数。 +请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。 -**返回**:`ResponseType<{ "ok": true }>`。 +**响应体**:`ResponseType`,`data` 字段: -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `ok` | boolean | 恒 `true` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "ok": true }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/connections` +### `GET /api/v1/connections` -列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。无参数。 +列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `connections` | array | [T-Connection](#t-connection) 数组 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "connections": [ { "id": "conn_01JZX4...", "connected_at": "2026-09-02T08:00:00.000Z", "remote_address": "127.0.0.1", "user_agent": "Mozilla/5.0 ...", "has_client_hello": true, "subscriptions": [ "session_..." ] } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "connections": [ + { + "id": "conn_01JZX4...", + "connected_at": "2026-09-02T08:00:00.000Z", + "remote_address": "127.0.0.1", + "user_agent": "Mozilla/5.0 ...", + "has_client_hello": true, + "subscriptions": [ "session_..." ] + } + ] + }, + "request_id": "01JZX4..." +} ``` **配置。** -全局配置的读取与合并式更新;密钥字段一律脱敏。 - -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | -| `POST /api/v1/config` | 合并式更新配置,并广播 `event.config.changed` | - -#### `GET /api/v1/config` +### `GET /api/v1/config` 返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:供应商与模型只报告 `has_api_key`,绝不返回存储的密钥。 -**返回**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 +**响应体**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ConfigResponse](#t-configresponse) | 生效的全量配置;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "providers": { "my-provider": { "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true } }, "default_provider": "my-provider", "default_model": "my-provider/kimi-for-coding", "models": { "...": {} } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "providers": { + "my-provider": { "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true } + }, + "default_provider": "my-provider", + "default_model": "my-provider/kimi-for-coding", + "models": { "...": {} } + }, + "request_id": "01JZX4..." +} ``` -#### `POST /api/v1/config` +### `POST /api/v1/config` 合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写(`false` 被忽略)。每一次配置变更——经本端点、在进程外编辑 `config.toml`,或服务端内部写入——都会广播全局 `event.config.changed` 事件。 -**Body**:部分配置对象,[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 +**请求体**:部分配置对象——[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 -**返回**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`(合并写入后的全量)。 +**响应体**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(值非法或持久化失败,`details` 逐字段说明)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ConfigResponse](#t-configresponse) | 合并写入后的全量配置;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(值非法或持久化失败;`details` 为 `{ path, message }[]`)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "default_model": "my-provider/kimi-for-coding", "yolo": true, "providers": { "...": {} } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "default_model": "my-provider/kimi-for-coding", + "yolo": true, + "providers": { "...": {} } + }, + "request_id": "01JZX4..." +} ``` **模型与供应商。** 模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方指的都是这个别名 id。 -| 方法与路径 | 说明 | -| --- | --- | -| `GET /api/v1/models` | 列出已配置的模型别名 | -| `POST /api/v1/models/{model_id}:set_default` | 设置全局默认模型 | -| `GET /api/v1/providers` | 列出供应商 | -| `POST /api/v1/providers` | 创建供应商(201) | -| `GET /api/v1/providers/{provider_id}` | 读取供应商(含已存密钥) | -| `PUT /api/v1/providers/{provider_id}` | 整体替换供应商配置 | -| `DELETE /api/v1/providers/{provider_id}` | 删除供应商(204) | -| `POST /api/v1/providers/{provider_id}:refresh` | 刷新该供应商的模型元数据 | -| `POST /api/v1/providers:{action}` | 集合级动作:`refresh` / `refresh_oauth` / `import_catalog` / `import_registry` | -| `GET /api/v1/catalog/providers` | 浏览 models.dev 目录(服务端代理) | -| `GET /api/v1/catalog/providers/{catalog_id}` | 读取目录中单个条目 | +### `GET /api/v1/models` -#### `GET /api/v1/models` +列出所有供应商下已配置的模型别名。 -列出所有供应商下已配置的模型别名。无参数。 - -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `items` | array | [T-ModelCatalogItem](#t-modelcatalogitem) 数组 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "provider": "my-provider", "model": "my-provider/kimi-for-coding", "max_context_size": 262144, "capabilities": [ "thinking", "image_in" ] } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "provider": "my-provider", + "model": "my-provider/kimi-for-coding", + "max_context_size": 262144, + "capabilities": [ "thinking", "image_in" ] + } + ] + }, + "request_id": "01JZX4..." +} ``` -#### `POST /api/v1/models/{model_id}:set_default` +### `POST /api/v1/models/{model_id}:set_default` -把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。无请求体。 +把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -255,33 +329,57 @@ HTTP 状态码例外(非 200): **非零 code**:`40001`(动作后缀非法;`details` 为 `{ path, message }[]`)、`40413`(模型别名不存在)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "default_model": "turbo", "model": { "provider": "my-provider", "model": "turbo", "max_context_size": 262144 } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "default_model": "turbo", + "model": { "provider": "my-provider", "model": "turbo", "max_context_size": 262144 } + }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/providers` +### `GET /api/v1/providers` -列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。无参数。 +列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `items` | array | [T-ProviderCatalogItem](#t-providercatalogitem) 数组 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "my-provider", "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true, "status": "connected", "models": [ "my-provider/kimi-for-coding" ] } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "my-provider", + "type": "openai", + "base_url": "https://api.example.com/v1", + "has_api_key": true, + "status": "connected", + "models": [ "my-provider/kimi-for-coding" ] + } + ] + }, + "request_id": "01JZX4..." +} ``` -#### `POST /api/v1/providers` +### `POST /api/v1/providers` 一次保存创建供应商及其模型别名;响应为 HTTP 201 加 `ResponseType`。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -304,35 +402,67 @@ HTTP 状态码例外(非 200): | `support_efforts` | array | 否 | 支持的 Thinking 模式 effort 档位 | | `adaptive_thinking` | boolean | 否 | 自适应 thinking 开关 | -**返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`(新建对象)。 +**响应体**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`(新建对象,HTTP 201)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40921`(已存在该 `id` 的供应商)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ProviderCatalogItem](#t-providercatalogitem) | 新建的供应商;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40921`(已存在该 `id` 的供应商)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected", "models": [ "my-provider/kimi-for-coding" ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "my-provider", + "type": "openai", + "has_api_key": true, + "status": "connected", + "models": [ "my-provider/kimi-for-coding" ] + }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/providers/{provider_id}` +### `GET /api/v1/providers/{provider_id}` + +读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。 -读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。无参数。 +**响应体**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`,存有密钥时附带 `api_key: string`。 -**返回**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`,存有密钥时附带 `api_key: string`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ProviderCatalogItem](#t-providercatalogitem) | 供应商;字段见类型汇总 | +| `data.api_key` | string | 可缺省:存储的密钥,仅本端点回显 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40412`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40412`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "my-provider", "type": "openai", "base_url": "https://api.example.com/v1", "has_api_key": true, "status": "connected", "api_key": "sk-..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "my-provider", + "type": "openai", + "base_url": "https://api.example.com/v1", + "has_api_key": true, + "status": "connected", + "api_key": "sk-..." + }, + "request_id": "01JZX4..." +} ``` -#### `PUT /api/v1/providers/{provider_id}` +### `PUT /api/v1/providers/{provider_id}` 一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,不再列出的别名从 `config.toml` 中消失。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -343,54 +473,74 @@ HTTP 状态码例外(非 200): | `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | | `models` | array | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | -| `provider` | object | [T-ProviderCatalogItem](#t-providercatalogitem) | +| `provider` | [T-ProviderCatalogItem](#t-providercatalogitem) | 替换后的供应商 | **非零 code**:`40001`(重命名后的别名 id 冲突;`details` 为 `{ path, message }[]`)、`40003`(供应商由 OAuth 托管,改用 `POST /api/v1/oauth/logout`)、`40412`、`40921`(`new_id` 已被占用)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" } + }, + "request_id": "01JZX4..." +} ``` -#### `DELETE /api/v1/providers/{provider_id}` +### `DELETE /api/v1/providers/{provider_id}` -删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。无请求体。 +删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。 -**成功形态**:HTTP 204 空体——状态行本身即表示删除成功。 +**响应体**:HTTP 204 空体——状态行本身即表示删除成功,无 `ResponseType`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40003`、`40412`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40003`、`40412`。 -#### `POST /api/v1/providers/{provider_id}:refresh` +### `POST /api/v1/providers/{provider_id}:refresh` -从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。无请求体。 +从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。 -**返回**:`ResponseType<[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)>`。 +**响应体**:`ResponseType<[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40412`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse) | 按供应商分组的刷新结果;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40412`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "changed": [ { "provider_id": "my-provider", "provider_name": "my-provider", "added": 2, "removed": 0 } ], "unchanged": [], "failed": [] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "changed": [ { "provider_id": "my-provider", "provider_name": "my-provider", "added": 2, "removed": 0 } ], + "unchanged": [], + "failed": [] + }, + "request_id": "01JZX4..." +} ``` -#### `POST /api/v1/providers:{action}` +### `POST /api/v1/providers:{action}` 集合级动作路由;请求体按动作校验。四个动作: -| 动作 | Body | data(code = 0) | -| --- | --- | --- | -| `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | -| `:refresh_oauth` | 可选,被忽略 | 同上,仅限 OAuth 凭据的供应商 | -| `:import_catalog` | 见下 | `{ provider, models_imported }`,HTTP 201 | -| `:import_registry` | 见下 | `{ providers, models_imported }`,HTTP 201 | +| 动作 | 请求体 | `data`(code = 0) | HTTP 状态 | +| --- | --- | --- | --- | +| `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | 200 | +| `:refresh_oauth` | 可选,被忽略 | 同上,仅限 OAuth 凭据的供应商 | 200 | +| `:import_catalog` | 见下 | `{ provider, models_imported }` | 201 | +| `:import_registry` | 见下 | `{ providers, models_imported }` | 201 | -`:import_catalog` 的 Body——把一个 models.dev 目录条目导入为已配置供应商:通信协议与端点来自目录解析,目录中的每个模型都写为一个别名;导入已存在的 id 等同于刷新,省略 `api_key` 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时以第一个导入的模型播种 `default_model`: +`:import_catalog` 把一个 models.dev 目录条目导入为已配置供应商:通信协议与端点来自目录解析,目录中的每个模型都写为一个别名;导入已存在的 id 等同于刷新,省略 `api_key` 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时以第一个导入的模型播种 `default_model`。请求体: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -399,26 +549,34 @@ HTTP 状态码例外(非 200): | `api_key` | string | 否 | 导入供应商的 API 密钥 | | `base_url` | string | 否 | 覆盖目录解析出的端点;条目的 `needs_base_url` 为 `true` 时必填 | -`:import_registry` 的 Body——把一个 models.dev 形态的私有注册表(一个 `api.json` URL 加可选的 Bearer key)导入:每个列出的供应商都带 `source` 记录写入,以便定时刷新重新发现;重复导入同一 URL 会移除上游已消失的供应商——URL 是注册表的稳定身份,因此轮换 key 是安全的。全局默认指针遵循与 `:import_catalog` 相同的规则: +`:import_registry` 把一个 models.dev 形态的私有注册表(一个 `api.json` URL 加可选的 Bearer key)导入:每个列出的供应商都带 `source` 记录写入,以便定时刷新重新发现;重复导入同一 URL 会移除上游已消失的供应商——URL 是注册表的稳定身份,因此轮换 key 是安全的。全局默认指针遵循与 `:import_catalog` 相同的规则。请求体: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `url` | string | 是 | 注册表 `api.json` 的 URL | | `api_key` | string | 否 | 注册表的 Bearer key;省略时复用上一次导入同一 URL 所用的 key | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40003`、`40004`(目录条目无法导入)、`40005`(注册表无法获取或解析)、`40417`、`50004`(models.dev 目录不可用)。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40003`、`40004`(目录条目无法导入)、`40005`(注册表无法获取或解析)、`40417`、`50004`(models.dev 目录不可用)。 -**示例**(`:import_catalog`): +**响应示例**(`:import_catalog`): ```json -{ "code": 0, "msg": "success", "data": { "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" }, "models_imported": 3 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "provider": { "id": "my-provider", "type": "openai", "has_api_key": true, "status": "connected" }, + "models_imported": 3 + }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/catalog/providers` +### `GET /api/v1/catalog/providers` -浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。无参数。 +浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType`,`data` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -426,24 +584,62 @@ HTTP 状态码例外(非 200): **非零 code**:`50004`(在线拉取与内置快照均失败)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ { "id": "gpt-5", "max_context_size": 400000, "reasoning": true } ] } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "openai", + "name": "OpenAI", + "wire_type": "openai", + "guessed": false, + "needs_base_url": false, + "rejected": false, + "reject_reason": null, + "env_key": "OPENAI_API_KEY", + "models": [ { "id": "gpt-5", "max_context_size": 400000, "reasoning": true } ] + } + ] + }, + "request_id": "01JZX4..." +} ``` -#### `GET /api/v1/catalog/providers/{catalog_id}` +### `GET /api/v1/catalog/providers/{catalog_id}` + +按 catalog id 读取单个 models.dev 目录条目。 -按 catalog id 读取单个 models.dev 目录条目。无参数。 +**响应体**:`ResponseType<[T-CatalogProviderItem](#t-catalogprovideritem)>`。 -**返回**:`ResponseType<[T-CatalogProviderItem](#t-catalogprovideritem)>`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-CatalogProviderItem](#t-catalogprovideritem) | 目录条目;字段见类型汇总 | **非零 code**:`40417`、`50004`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "openai", "name": "OpenAI", "wire_type": "openai", "guessed": false, "needs_base_url": false, "rejected": false, "reject_reason": null, "env_key": "OPENAI_API_KEY", "models": [ "..." ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "openai", + "name": "OpenAI", + "wire_type": "openai", + "guessed": false, + "needs_base_url": false, + "rejected": false, + "reject_reason": null, + "env_key": "OPENAI_API_KEY", + "models": [ "..." ] + }, + "request_id": "01JZX4..." +} ``` ### 账号 From 3286eea08da19bfabbb4b381981db95a73db150d Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:19:50 +0800 Subject: [PATCH 21/47] docs(zh): split config and models/providers out of the service domain --- docs/zh/reference/server-api.md | 40 ++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 31da719bce7..107276904f9 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -87,7 +87,7 @@ HTTP 状态码例外(非 200): ## 服务 -服务自身的探活、身份、关停与连接管理;全局配置的读取与合并式更新;模型别名与供应商管理,以及 models.dev 目录浏览。 +服务自身的探活、身份、关停与连接管理。 | 方法与路径 | 说明 | | --- | --- | @@ -95,19 +95,6 @@ HTTP 状态码例外(非 200): | `GET /api/v1/meta` | 服务版本、能力集、`server_id`、实验开关 | | `POST /api/v1/shutdown` | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 | | `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | -| `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | -| `POST /api/v1/config` | 合并式更新配置,并广播 `event.config.changed` | -| `GET /api/v1/models` | 列出已配置的模型别名 | -| `POST /api/v1/models/{model_id}:set_default` | 设置全局默认模型 | -| `GET /api/v1/providers` | 列出供应商 | -| `POST /api/v1/providers` | 创建供应商(201) | -| `GET /api/v1/providers/{provider_id}` | 读取供应商(含已存密钥) | -| `PUT /api/v1/providers/{provider_id}` | 整体替换供应商配置 | -| `DELETE /api/v1/providers/{provider_id}` | 删除供应商(204) | -| `POST /api/v1/providers/{provider_id}:refresh` | 刷新该供应商的模型元数据 | -| `POST /api/v1/providers:{action}` | 集合级动作:`refresh` / `refresh_oauth` / `import_catalog` / `import_registry` | -| `GET /api/v1/catalog/providers` | 浏览 models.dev 目录(服务端代理) | -| `GET /api/v1/catalog/providers/{catalog_id}` | 读取目录中单个条目 | ### `GET /api/v1/healthz` @@ -223,7 +210,14 @@ HTTP 状态码例外(非 200): } ``` -**配置。** +## 配置 + +全局配置的读取与合并式更新;密钥字段一律脱敏。 + +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | +| `POST /api/v1/config` | 合并式更新配置,并广播 `event.config.changed` | ### `GET /api/v1/config` @@ -282,10 +276,24 @@ HTTP 状态码例外(非 200): } ``` -**模型与供应商。** +## 模型与供应商 模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方指的都是这个别名 id。 +| 方法与路径 | 说明 | +| --- | --- | +| `GET /api/v1/models` | 列出已配置的模型别名 | +| `POST /api/v1/models/{model_id}:set_default` | 设置全局默认模型 | +| `GET /api/v1/providers` | 列出供应商 | +| `POST /api/v1/providers` | 创建供应商(201) | +| `GET /api/v1/providers/{provider_id}` | 读取供应商(含已存密钥) | +| `PUT /api/v1/providers/{provider_id}` | 整体替换供应商配置 | +| `DELETE /api/v1/providers/{provider_id}` | 删除供应商(204) | +| `POST /api/v1/providers/{provider_id}:refresh` | 刷新该供应商的模型元数据 | +| `POST /api/v1/providers:{action}` | 集合级动作:`refresh` / `refresh_oauth` / `import_catalog` / `import_registry` | +| `GET /api/v1/catalog/providers` | 浏览 models.dev 目录(服务端代理) | +| `GET /api/v1/catalog/providers/{catalog_id}` | 读取目录中单个条目 | + ### `GET /api/v1/models` 列出所有供应商下已配置的模型别名。 From 78d8224e112e417b43de487278eed276bbacc0a0 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:20:40 +0800 Subject: [PATCH 22/47] docs(zh): demote endpoint headings to h4 so the outline only shows domains --- docs/zh/reference/server-api.md | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 107276904f9..e04716ac67f 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -96,7 +96,7 @@ HTTP 状态码例外(非 200): | `POST /api/v1/shutdown` | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 | | `GET /api/v1/connections` | 列出当前在线的 WebSocket 连接 | -### `GET /api/v1/healthz` +#### `GET /api/v1/healthz` 供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。免鉴权(见 [例外接口](#鉴权))。 @@ -117,7 +117,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/meta` +#### `GET /api/v1/meta` 返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 @@ -157,7 +157,7 @@ HTTP 状态码例外(非 200): } ``` -### `POST /api/v1/shutdown` +#### `POST /api/v1/shutdown` 请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。 @@ -178,7 +178,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/connections` +#### `GET /api/v1/connections` 列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。 @@ -219,7 +219,7 @@ HTTP 状态码例外(非 200): | `GET /api/v1/config` | 读取全局配置(密钥字段脱敏) | | `POST /api/v1/config` | 合并式更新配置,并广播 `event.config.changed` | -### `GET /api/v1/config` +#### `GET /api/v1/config` 返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:供应商与模型只报告 `has_api_key`,绝不返回存储的密钥。 @@ -247,7 +247,7 @@ HTTP 状态码例外(非 200): } ``` -### `POST /api/v1/config` +#### `POST /api/v1/config` 合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写(`false` 被忽略)。每一次配置变更——经本端点、在进程外编辑 `config.toml`,或服务端内部写入——都会广播全局 `event.config.changed` 事件。 @@ -294,7 +294,7 @@ HTTP 状态码例外(非 200): | `GET /api/v1/catalog/providers` | 浏览 models.dev 目录(服务端代理) | | `GET /api/v1/catalog/providers/{catalog_id}` | 读取目录中单个条目 | -### `GET /api/v1/models` +#### `GET /api/v1/models` 列出所有供应商下已配置的模型别名。 @@ -324,7 +324,7 @@ HTTP 状态码例外(非 200): } ``` -### `POST /api/v1/models/{model_id}:set_default` +#### `POST /api/v1/models/{model_id}:set_default` 把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 @@ -351,7 +351,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/providers` +#### `GET /api/v1/providers` 列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。 @@ -383,7 +383,7 @@ HTTP 状态码例外(非 200): } ``` -### `POST /api/v1/providers` +#### `POST /api/v1/providers` 一次保存创建供应商及其模型别名;响应为 HTTP 201 加 `ResponseType`。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 @@ -435,7 +435,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/providers/{provider_id}` +#### `GET /api/v1/providers/{provider_id}` 读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。 @@ -466,7 +466,7 @@ HTTP 状态码例外(非 200): } ``` -### `PUT /api/v1/providers/{provider_id}` +#### `PUT /api/v1/providers/{provider_id}` 一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,不再列出的别名从 `config.toml` 中消失。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 @@ -502,7 +502,7 @@ HTTP 状态码例外(非 200): } ``` -### `DELETE /api/v1/providers/{provider_id}` +#### `DELETE /api/v1/providers/{provider_id}` 删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。 @@ -510,7 +510,7 @@ HTTP 状态码例外(非 200): **非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40003`、`40412`。 -### `POST /api/v1/providers/{provider_id}:refresh` +#### `POST /api/v1/providers/{provider_id}:refresh` 从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。 @@ -537,7 +537,7 @@ HTTP 状态码例外(非 200): } ``` -### `POST /api/v1/providers:{action}` +#### `POST /api/v1/providers:{action}` 集合级动作路由;请求体按动作校验。四个动作: @@ -580,7 +580,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/catalog/providers` +#### `GET /api/v1/catalog/providers` 浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。 @@ -617,7 +617,7 @@ HTTP 状态码例外(非 200): } ``` -### `GET /api/v1/catalog/providers/{catalog_id}` +#### `GET /api/v1/catalog/providers/{catalog_id}` 按 catalog id 读取单个 models.dev 目录条目。 From 7ba51a14bfb7e5644ca9aff9c7ffa8f75f5b1e5d Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:21:43 +0800 Subject: [PATCH 23/47] docs(zh): restore the REST API umbrella heading with domains at h3 --- docs/zh/reference/server-api.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index e04716ac67f..8bccfb97899 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -83,9 +83,11 @@ HTTP 状态码例外(非 200): - **游标式**:`before_id` / `after_id`(互斥)加 `page_size`(1–100),响应为 `{ items, has_more }`。用于会话列表、消息列表、子会话列表;转录分页的游标为 `before_turn` / `after_turn`。 - **`page_token`**:不透明令牌(绑定了查询条件的指纹),用于 `POST /api/v1/search` 与 `GET /api/v2/sessions`。翻页途中改变任何查询条件会使令牌失效:v2 返回 `40922`,search 返回 `40001`。`GET /api/v2/sessions` 另提供无状态的 `page` 页码模式作为替代。 +## REST API + 下文按业务域分组列出全部端点,覆盖 `/api/v1` 与 `/api/v2`(路径前缀区分版本)。路径里的 `:{action}` 后缀是动作约定——对单个资源 POST 到 `路径:动作` 执行非 CRUD 操作(如会话的 `:fork`、`:archive`);动作缺失或未知时返回 `40001`。共享类型(T-Session 等)不在条目内展开,统一见 [类型汇总](#类型汇总);「可缺省」「可空」的语义区分见 [null 与缺省语义](#null-与缺省语义)。 -## 服务 +### 服务 服务自身的探活、身份、关停与连接管理。 @@ -210,7 +212,7 @@ HTTP 状态码例外(非 200): } ``` -## 配置 +### 配置 全局配置的读取与合并式更新;密钥字段一律脱敏。 @@ -276,7 +278,7 @@ HTTP 状态码例外(非 200): } ``` -## 模型与供应商 +### 模型与供应商 模型配置的两半——`config.toml` 的 [供应商](../configuration/providers.md) 表与模型别名表——外加一个由服务端代理的 models.dev 目录。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 `provider_id/model`(例如 `my-provider/kimi-for-coding`),模型别名表中的裸键(如 `turbo`)原样使用;API 中任何接收 `model_id` 的地方指的都是这个别名 id。 From a1d967960faa63027a172d0c945a0c0412b78300 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:23:48 +0800 Subject: [PATCH 24/47] docs(zh): state the full ResponseType generic in every response body line --- docs/zh/reference/server-api.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 8bccfb97899..7e79d4d8852 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -102,7 +102,7 @@ HTTP 状态码例外(非 200): 供脚本与进程管理器使用的探活端点,应答时不触碰配置与引擎。免鉴权(见 [例外接口](#鉴权))。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ ok: boolean }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -123,7 +123,7 @@ HTTP 状态码例外(非 200): 返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ server_version: string, capabilities: object, server_id: string, started_at: string, open_in_apps: array, dangerous_bypass_auth: boolean, backend: string, web_title?: string, experimental_flags: object, features: array }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -163,7 +163,7 @@ HTTP 状态码例外(非 200): 请求服务优雅退出;响应先发出,随后立即执行关闭。仅在 loopback 绑定时挂载——非 loopback 绑定时不会注册(请求得到 404),除非服务以 `--allow-remote-shutdown` 启动。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ ok: boolean }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -184,7 +184,7 @@ HTTP 状态码例外(非 200): 列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ connections: T-Connection[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -300,7 +300,7 @@ HTTP 状态码例外(非 200): 列出所有供应商下已配置的模型别名。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: T-ModelCatalogItem[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -330,7 +330,7 @@ HTTP 状态码例外(非 200): 把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ default_model: string, model: T-ModelCatalogItem }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -357,7 +357,7 @@ HTTP 状态码例外(非 200): 列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: T-ProviderCatalogItem[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -483,7 +483,7 @@ HTTP 状态码例外(非 200): | `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | | `models` | array | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ provider: T-ProviderCatalogItem }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -586,7 +586,7 @@ HTTP 状态码例外(非 200): 浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。 -**响应体**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: T-CatalogProviderItem[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | From 7a1abe8edf48b4e891ebc8e0df98e4eb561fac6e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:28:03 +0800 Subject: [PATCH 25/47] docs(zh): unwrap type links from inline code so anchors work --- docs/zh/reference/server-api.md | 110 ++++++++++++++++---------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 7e79d4d8852..005ab41d1b9 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -225,7 +225,7 @@ HTTP 状态码例外(非 200): 返回解析后的全局配置——`config.toml` 叠加覆盖层后的生效结果。密钥已脱敏:供应商与模型只报告 `has_api_key`,绝不返回存储的密钥。 -**响应体**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 +**响应体**:`ResponseType<`[T-ConfigResponse](#t-configresponse)`>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -255,7 +255,7 @@ HTTP 状态码例外(非 200): **请求体**:部分配置对象——[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 -**响应体**:`ResponseType<[T-ConfigResponse](#t-configresponse)>`。 +**响应体**:`ResponseType<`[T-ConfigResponse](#t-configresponse)`>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -412,7 +412,7 @@ HTTP 状态码例外(非 200): | `support_efforts` | array | 否 | 支持的 Thinking 模式 effort 档位 | | `adaptive_thinking` | boolean | 否 | 自适应 thinking 开关 | -**响应体**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`(新建对象,HTTP 201)。 +**响应体**:`ResponseType<`[T-ProviderCatalogItem](#t-providercatalogitem)`>`(新建对象,HTTP 201)。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -441,7 +441,7 @@ HTTP 状态码例外(非 200): 读取单个供应商。与列表路由不同,设置了密钥时响应会附带存储的 `api_key`,以便本地编辑表单预填——这是唯一回显密钥的端点,暴露端口时请牢记这一点。 -**响应体**:`ResponseType<[T-ProviderCatalogItem](#t-providercatalogitem)>`,存有密钥时附带 `api_key: string`。 +**响应体**:`ResponseType<`[T-ProviderCatalogItem](#t-providercatalogitem)`>`,存有密钥时附带 `api_key: string`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -516,7 +516,7 @@ HTTP 状态码例外(非 200): 从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。 -**响应体**:`ResponseType<[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)>`。 +**响应体**:`ResponseType<`[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)`>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -623,7 +623,7 @@ HTTP 状态码例外(非 200): 按 catalog id 读取单个 models.dev 目录条目。 -**响应体**:`ResponseType<[T-CatalogProviderItem](#t-catalogprovideritem)>`。 +**响应体**:`ResponseType<`[T-CatalogProviderItem](#t-catalogprovideritem)`>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -671,7 +671,7 @@ HTTP 状态码例外(非 200): 鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 -**返回**:`ResponseType<[T-AuthSummary](#t-authsummary)>`。 +**返回**:`ResponseType<`[T-AuthSummary](#t-authsummary)`>`。 **示例**: @@ -690,7 +690,7 @@ HTTP 状态码例外(非 200): | `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | | `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | -**返回**:`ResponseType<[T-OAuthFlowStart](#t-oauthflowstart)>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 +**返回**:`ResponseType<`[T-OAuthFlowStart](#t-oauthflowstart)`>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 **示例**: @@ -708,7 +708,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)>` 或 `null`。 +**返回**:`ResponseType<`[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)`>` 或 `null`。 **示例**: @@ -772,7 +772,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<[T-ManagedUsageResult](#t-managedusageresult)>`。 +**返回**:`ResponseType<`[T-ManagedUsageResult](#t-managedusageresult)`>`。 **示例**: @@ -790,7 +790,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<[T-ManagedUserInfoResult](#t-manageduserinforesult)>`(camelCase 载荷)。 +**返回**:`ResponseType<`[T-ManagedUserInfoResult](#t-manageduserinforesult)`>`(camelCase 载荷)。 **示例**: @@ -860,7 +860,7 @@ HTTP 状态码例外(非 200): | `root` | string | 是 | 已存在目录的绝对路径 | | `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | -**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 +**返回**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 @@ -880,7 +880,7 @@ HTTP 状态码例外(非 200): | --- | --- | --- | --- | | `name` | string | 是 | 新的显示名,1–100 个字符 | -**返回**:`ResponseType<[T-Workspace](#t-workspace)>`。 +**返回**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 @@ -1006,7 +1006,7 @@ HTTP 状态码例外(非 200): | `title` | string | 否 | 初始标题(至少 1 个字符) | | `agent_config` | object | 否 | schema 接受但当前不会应用——模型与各模式请经 `POST .../profile` 设置 | -**返回**:`ResponseType<[T-Session](#t-session)>`。 +**返回**:`ResponseType<`[T-Session](#t-session)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 @@ -1047,7 +1047,7 @@ HTTP 状态码例外(非 200): 从索引中读取单个会话。`last_seq` 携带真实的事件水位(watermark):存活会话为当前事件日志的序列号,冷会话为最后持久化的水位——用它作为 `subscribe` 的 `cursors` 起点时回放为空。其余会话端点的 `last_seq` 均为 `0` 占位。 -**返回**:`ResponseType<[T-Session](#t-session)>`。 +**返回**:`ResponseType<`[T-Session](#t-session)`>`。 **非零 code**:`40401`(会话不存在,或其工作区已无法解析)。 @@ -1061,7 +1061,7 @@ HTTP 状态码例外(非 200): 读取会话档案——与 `GET /api/v1/sessions/{session_id}` 相同的线上载荷(`last_seq` 为 `0` 占位)。 -**返回**:`ResponseType<[T-Session](#t-session)>`。 +**返回**:`ResponseType<`[T-Session](#t-session)`>`。 **非零 code**:`40401`。 @@ -1100,7 +1100,7 @@ HTTP 状态码例外(非 200): schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers`,但更新路由当前不会应用它们。 -**返回**:`ResponseType<[T-Session](#t-session)>`(更新后)。 +**返回**:`ResponseType<`[T-Session](#t-session)`>`(更新后)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -1187,7 +1187,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | `title` | string | 否 | 子会话的标题(至少 1 个字符)。默认 `Child: ` | | `metadata` | object | 否 | 子会话的自定义元数据 | -**返回**:`ResponseType<[T-Session](#t-session)>`。 +**返回**:`ResponseType<`[T-Session](#t-session)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40901`。 @@ -1201,7 +1201,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复。无参数。 -**返回**:`ResponseType<[T-SessionStatus](#t-sessionstatus)>`。 +**返回**:`ResponseType<`[T-SessionStatus](#t-sessionstatus)`>`。 **非零 code**:`40401`。 @@ -1215,7 +1215,7 @@ main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复 读取会话当前的目标快照;没有活跃目标时为 `null`。注意该载荷使用 camelCase 键。无参数。 -**返回**:`ResponseType<[T-GoalSnapshot](#t-goalsnapshot)>` 或 `null`。 +**返回**:`ResponseType<`[T-GoalSnapshot](#t-goalsnapshot)`>` 或 `null`。 **非零 code**:`40401`。 @@ -1297,7 +1297,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 -**返回**:`ResponseType<[T-SnapshotResponse](#t-snapshotresponse)>`。 +**返回**:`ResponseType<`[T-SnapshotResponse](#t-snapshotresponse)`>`。 **非零 code**:`40401`、`50001`。 @@ -1420,7 +1420,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | | `page_token` | string | 上一页返回的翻页令牌 | -**返回**:`ResponseType<[T-V2SessionPage](#t-v2sessionpage)>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 +**返回**:`ResponseType<`[T-V2SessionPage](#t-v2sessionpage)`>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知 `include` / `fields`、组合非法)、`40922`。 @@ -1440,7 +1440,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | --- | --- | --- | --- | | `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | -**返回**:`ResponseType<[T-V2BatchSessionResponse](#t-v2batchsessionresponse)>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 +**返回**:`ResponseType<`[T-V2BatchSessionResponse](#t-v2batchsessionresponse)`>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)。 @@ -1510,7 +1510,7 @@ schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinking` 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 `file_id` 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。 -**返回**:`ResponseType<[T-PromptItem](#t-promptitem)>`(被接受的提示词)。 +**返回**:`ResponseType<`[T-PromptItem](#t-promptitem)`>`(被接受的提示词)。 **非零 code**(鉴权错误族的 `data` / `details` 形态各异): @@ -1596,7 +1596,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 按 id 从同一历史中读取单条消息。无参数。 -**返回**:`ResponseType<[T-Message](#t-message)>`。 +**返回**:`ResponseType<`[T-Message](#t-message)`>`。 **非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 @@ -1766,7 +1766,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | | `page_size` | integer | 1–100 个轮次。默认 `20` | -**返回**:`ResponseType<[T-TranscriptResponse](#t-transcriptresponse)>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 +**返回**:`ResponseType<`[T-TranscriptResponse](#t-transcriptresponse)`>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -1787,7 +1787,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | -**返回**:`ResponseType<[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 +**返回**:`ResponseType<`[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)`>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -1807,7 +1807,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | --- | --- | --- | | `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | -**返回**:`ResponseType<[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)>`。 +**返回**:`ResponseType<`[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -1828,7 +1828,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | -**返回**:`ResponseType<[T-TranscriptPlanResponse](#t-transcriptplanresponse)>`。 +**返回**:`ResponseType<`[T-TranscriptPlanResponse](#t-transcriptplanresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 @@ -1885,7 +1885,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `with_output` | boolean | 在响应中包含输出末尾片段。默认 `false` | | `output_bytes` | integer | 请求的输出末尾片段的字节大小,最小 `0`。默认 `32768` | -**返回**:`ResponseType<[T-Task](#t-task)>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 +**返回**:`ResponseType<`[T-Task](#t-task)`>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 @@ -1955,7 +1955,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `cols` | integer | 否 | 终端宽度,正数。默认 `80` | | `rows` | integer | 否 | 终端高度,正数。默认 `24` | -**返回**:`ResponseType<[T-Terminal](#t-terminal)>`。 +**返回**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 @@ -1969,7 +1969,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 读取单个终端。无参数。 -**返回**:`ResponseType<[T-Terminal](#t-terminal)>`。 +**返回**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 **非零 code**:`40401`、`40414`(没有该 id 的终端)。 @@ -2115,7 +2115,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | --- | | `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | -**返回**:`ResponseType<[T-PluginSummary](#t-pluginsummary)>`。 +**返回**:`ResponseType<`[T-PluginSummary](#t-pluginsummary)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 @@ -2169,7 +2169,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 -**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 +**返回**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 **非零 code**:`40418`(没有该 id 的能力)。 @@ -2183,7 +2183,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 -**返回**:`ResponseType<[T-CapabilityStatus](#t-capabilitystatus)>`。 +**返回**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 **非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 @@ -2288,7 +2288,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组。 +**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组。 **示例**: @@ -2306,7 +2306,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>`。 +**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 @@ -2322,7 +2322,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 **非零 code**:`40001`(校验失败,或目标条目为只读;`details` 为 `{ path, message }[]`)。 @@ -2338,7 +2338,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 **Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 @@ -2352,7 +2352,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 删除一个用户级条目。无请求体。 -**返回**:`ResponseType<[T-McpManagedServer](#t-mcpmanagedserver)>` 数组(刷新后的列表)。 +**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 @@ -2395,7 +2395,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | | `cwd` | string | 否 | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<[T-McpServerInspection](#t-mcpserverinspection)>` 数组。 +**返回**:`ResponseType<`[T-McpServerInspection](#t-mcpserverinspection)`>` 数组。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 @@ -2416,7 +2416,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `cwd` | string | 并入该(受信任)目录的项目层 | | `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | -**返回**:`ResponseType<[T-McpServerAuthStatus](#t-mcpserverauthstatus)>` 数组。验证探测可能刷新或作废已存储的凭据。 +**返回**:`ResponseType<`[T-McpServerAuthStatus](#t-mcpserverauthstatus)`>` 数组。验证探测可能刷新或作废已存储的凭据。 **示例**: @@ -2530,7 +2530,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | | `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | -**返回**:`ResponseType<[T-FsListResponse](#t-fslistresponse)>`。 +**返回**:`ResponseType<`[T-FsListResponse](#t-fslistresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 @@ -2553,7 +2553,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | | `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | -**返回**:`ResponseType<[T-FsReadResponse](#t-fsreadresponse)>`。 +**返回**:`ResponseType<`[T-FsReadResponse](#t-fsreadresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 @@ -2575,7 +2575,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 -**返回**:`ResponseType<[T-FsListManyResponse](#t-fslistmanyresponse)>`。 +**返回**:`ResponseType<`[T-FsListManyResponse](#t-fslistmanyresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -2595,7 +2595,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | --- | | `path` | string | 是 | 要查询的路径,相对于会话工作目录 | -**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`。 +**返回**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 @@ -2615,7 +2615,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | --- | | `paths` | array | 是 | 要查询的路径,1–1000 条 | -**返回**:`ResponseType<[T-FsStatManyResponse](#t-fsstatmanyresponse)>`。 +**返回**:`ResponseType<`[T-FsStatManyResponse](#t-fsstatmanyresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 @@ -2636,7 +2636,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `path` | string | 是 | 要创建的目录,相对于会话工作目录 | | `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | -**返回**:`ResponseType<[T-FsEntry](#t-fsentry)>`(所建目录)。 +**返回**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`(所建目录)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 @@ -2689,7 +2689,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | | `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | -**返回**:`ResponseType<[T-FsGrepResponse](#t-fsgrepresponse)>`。 +**返回**:`ResponseType<`[T-FsGrepResponse](#t-fsgrepresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 @@ -2709,7 +2709,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | --- | | `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | -**返回**:`ResponseType<[T-FsGitStatusResponse](#t-fsgitstatusresponse)>`(注意 camelCase `pullRequest`)。 +**返回**:`ResponseType<`[T-FsGitStatusResponse](#t-fsgitstatusresponse)`>`(注意 camelCase `pullRequest`)。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 @@ -2729,7 +2729,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | --- | | `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | -**返回**:`ResponseType<[T-FsDiffResponse](#t-fsdiffresponse)>`。 +**返回**:`ResponseType<`[T-FsDiffResponse](#t-fsdiffresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 @@ -2904,7 +2904,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | --- | --- | --- | | `path` | string | 绝对目录路径。默认用户主目录 | -**返回**:`ResponseType<[T-FsBrowseResponse](#t-fsbrowseresponse)>`。 +**返回**:`ResponseType<`[T-FsBrowseResponse](#t-fsbrowseresponse)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 @@ -2918,7 +2918,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 返回文件夹选择器的落地数据。无参数。 -**返回**:`ResponseType<[T-FsHomeResponse](#t-fshomeresponse)>`(`recent_roots` 上限 8)。 +**返回**:`ResponseType<`[T-FsHomeResponse](#t-fshomeresponse)`>`(`recent_roots` 上限 8)。 **示例**: @@ -2981,7 +2981,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `name` | string | 否 | 存储的显示名。默认上传文件名 | | `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | -**返回**:`ResponseType<[T-FileMeta](#t-filemeta)>`。 +**返回**:`ResponseType<`[T-FileMeta](#t-filemeta)`>`。 **非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(multipart 未初始化或缺少 `file` 字段)。 @@ -3040,7 +3040,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 `terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 -**返回**:`ResponseType<[T-SearchResponse](#t-searchresponse)>`。 +**返回**:`ResponseType<`[T-SearchResponse](#t-searchresponse)`>`。 **非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法;`details` 为 `{ path, message }[]`)、`50001`。 From 50a9beff42697d3ecded1ee223212989a1e0d2eb Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:28:33 +0800 Subject: [PATCH 26/47] docs(zh): add T-MetaResponse to the type dictionary and reference it from GET /meta --- docs/zh/reference/server-api.md | 49 +++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 005ab41d1b9..cb8b5e0a94a 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -123,20 +123,11 @@ HTTP 状态码例外(非 200): 返回本实例的身份信息与能力集。大多数字段在启动时即固定;`experimental_flags` 与 `features` 按请求实时解析。 -**响应体**:`ResponseType<{ server_version: string, capabilities: object, server_id: string, started_at: string, open_in_apps: array, dangerous_bypass_auth: boolean, backend: string, web_title?: string, experimental_flags: object, features: array }>` +**响应体**:`ResponseType<`[T-MetaResponse](#t-metaresponse)`>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `server_version` | string | 服务版本 | -| `capabilities` | object | 恒 `{ "websocket": true, "file_upload": true, "fs_query": true, "mcp": true, "tasks": true, "terminal": true }` | -| `server_id` | string | 本次启动生成的 ULID | -| `started_at` | string | 启动时间,ISO 8601 | -| `open_in_apps` | array | 恒 `[]` | -| `dangerous_bypass_auth` | boolean | 服务是否以 `--dangerous-bypass-auth` 启动 | -| `backend` | string | 恒 `"v2"` | -| `web_title` | string | 可缺省:`--web-title` 自定义标题,未设置时不出现 | -| `experimental_flags` | object | 实验开关 id → 是否启用 | -| `features` | array | 引擎 feature 单元,形如 `{ name, state, meta }`;`state` 为 `Pending` / `Activating` / `Active` / `Unloading` / `Failed` | +| `data` | [T-MetaResponse](#t-metaresponse) | 实例身份与能力集;字段见类型汇总 | **响应示例**: @@ -4499,6 +4490,42 @@ type McpServerAuthStatus = { **服务。** +### T-MetaResponse + +`GET /meta` 的响应,服务端正名为 `MetaResponse`。 + +```ts +type MetaResponse = { + server_version: string; + capabilities: MetaCapabilities; + server_id: string; // 本次启动生成的 ULID + started_at: string; // ISO 8601 + open_in_apps: string[]; // 恒 [] + dangerous_bypass_auth: boolean; + experimental_flags: Record; // 按请求实时解析 + backend: 'v2'; + web_title?: string; // --web-title,未设置时缺省 + features: MetaFeature[]; // 按请求实时解析 +}; + +type MetaCapabilities = { + websocket: true; + file_upload: true; + fs_query: true; + mcp: true; + tasks: true; + terminal: true; +}; + +type MetaFeature = { + name: string; + state: 'Pending' | 'Activating' | 'Active' | 'Unloading' | 'Failed'; + meta: Record; +}; +``` + +服务端 schema 中 `experimental_flags` / `backend` / `features` 为可选,但产出恒带这三个字段。 + ### T-Connection 活跃 WS 连接,由 REST `GET /connections` 返回。 From 5f71cd093c09bd372649fb802d4711a98e0456bc Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:47:31 +0800 Subject: [PATCH 27/47] docs(zh): add trigger-event lines to the finalized reference domains --- docs/zh/reference/server-api.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index cb8b5e0a94a..6c56de2b4ea 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -244,6 +244,8 @@ HTTP 状态码例外(非 200): 合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写(`false` 被忽略)。每一次配置变更——经本端点、在进程外编辑 `config.toml`,或服务端内部写入——都会广播全局 `event.config.changed` 事件。 +**触发事件**:`event.config.changed` + **请求体**:部分配置对象——[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 **响应体**:`ResponseType<`[T-ConfigResponse](#t-configresponse)`>`。 @@ -321,6 +323,8 @@ HTTP 状态码例外(非 200): 把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 +**触发事件**:`event.config.changed` + **响应体**:`ResponseType<{ default_model: string, model: T-ModelCatalogItem }>` | 字段 | 类型 | 说明 | @@ -380,6 +384,8 @@ HTTP 状态码例外(非 200): 一次保存创建供应商及其模型别名;响应为 HTTP 201 加 `ResponseType`。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 +**触发事件**:`event.config.changed` + **请求体**: | 字段 | 类型 | 必填 | 说明 | @@ -463,6 +469,8 @@ HTTP 状态码例外(非 200): 一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,不再列出的别名从 `config.toml` 中消失。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 +**触发事件**:`event.config.changed` + **请求体**: | 字段 | 类型 | 必填 | 说明 | @@ -499,13 +507,17 @@ HTTP 状态码例外(非 200): 删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。 +**触发事件**:`event.config.changed` + **响应体**:HTTP 204 空体——状态行本身即表示删除成功,无 `ResponseType`。 **非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40003`、`40412`。 #### `POST /api/v1/providers/{provider_id}:refresh` -从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。至少一个供应商的别名发生变化时广播全局 `event.model_catalog.changed` 事件。 +从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。 + +**触发事件**:`event.model_catalog.changed`(至少一个供应商的别名发生变化时;配置写入同时触发 `event.config.changed`) **响应体**:`ResponseType<`[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)`>`。 @@ -534,6 +546,8 @@ HTTP 状态码例外(非 200): 集合级动作路由;请求体按动作校验。四个动作: +**触发事件**:`:refresh` / `:refresh_oauth` → `event.model_catalog.changed`(至少一个供应商的别名发生变化时;配置写入同时触发 `event.config.changed`);`:import_catalog` / `:import_registry` → `event.config.changed` + | 动作 | 请求体 | `data`(code = 0) | HTTP 状态 | | --- | --- | --- | --- | | `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | 200 | From a9e8bbfb517d5fffee03502dd3439221a0458c98 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:48:38 +0800 Subject: [PATCH 28/47] docs(zh): link every named type in the finalized reference domains --- docs/zh/reference/server-api.md | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 6c56de2b4ea..db2dfe67039 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -175,11 +175,11 @@ HTTP 状态码例外(非 200): 列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。 -**响应体**:`ResponseType<{ connections: T-Connection[] }>` +**响应体**:`ResponseType<{ connections: `[T-Connection](#t-connection)`[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | -| `connections` | array | [T-Connection](#t-connection) 数组 | +| `connections` | [T-Connection](#t-connection)`[]` | 当前在线的 WebSocket 连接 | **响应示例**: @@ -293,11 +293,11 @@ HTTP 状态码例外(非 200): 列出所有供应商下已配置的模型别名。 -**响应体**:`ResponseType<{ items: T-ModelCatalogItem[] }>` +**响应体**:`ResponseType<{ items: `[T-ModelCatalogItem](#t-modelcatalogitem)`[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-ModelCatalogItem](#t-modelcatalogitem) 数组 | +| `items` | [T-ModelCatalogItem](#t-modelcatalogitem)`[]` | 已配置的模型别名 | **响应示例**: @@ -325,12 +325,12 @@ HTTP 状态码例外(非 200): **触发事件**:`event.config.changed` -**响应体**:`ResponseType<{ default_model: string, model: T-ModelCatalogItem }>` +**响应体**:`ResponseType<{ default_model: string, model: `[T-ModelCatalogItem](#t-modelcatalogitem)` }>` | 字段 | 类型 | 说明 | | --- | --- | --- | | `default_model` | string | 当前生效的别名 | -| `model` | object | [T-ModelCatalogItem](#t-modelcatalogitem) | +| `model` | [T-ModelCatalogItem](#t-modelcatalogitem) | 别名对应的模型条目 | **非零 code**:`40001`(动作后缀非法;`details` 为 `{ path, message }[]`)、`40413`(模型别名不存在)。 @@ -352,11 +352,11 @@ HTTP 状态码例外(非 200): 列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。 -**响应体**:`ResponseType<{ items: T-ProviderCatalogItem[] }>` +**响应体**:`ResponseType<{ items: `[T-ProviderCatalogItem](#t-providercatalogitem)`[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-ProviderCatalogItem](#t-providercatalogitem) 数组 | +| `items` | [T-ProviderCatalogItem](#t-providercatalogitem)`[]` | 已配置的供应商 | **响应示例**: @@ -395,7 +395,7 @@ HTTP 状态码例外(非 200): | `api_key` | string | 否 | API 密钥,存储于 `config.toml` | | `base_url` | string | 否 | API 基础 URL;不得包含环境变量占位符(`${...}`) | | `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | -| `models` | array | 是 | 至少一条,不允许重复的 `model` 值;条目结构见下 | +| `models` | `{ model: string, max_context_size: number, … }[]` | 是 | 至少一条,不允许重复的 `model` 值;条目结构见下 | `models[]` 条目(每个声明一个别名,其 id 为 `id/model`): @@ -404,9 +404,9 @@ HTTP 状态码例外(非 200): | `model` | string | 是 | 上游模型名 | | `max_context_size` | integer | 是 | 以 token 计的上下文窗口,≥ 1 | | `display_name` | string | 否 | 显示名 | -| `capabilities` | array | 否 | 能力标志,如 `thinking` 或 `image_in` | +| `capabilities` | `string[]` | 否 | 能力标志,如 `thinking` 或 `image_in` | | `max_output_size` | integer | 否 | 最大输出 token 数,≥ 1 | -| `support_efforts` | array | 否 | 支持的 Thinking 模式 effort 档位 | +| `support_efforts` | `string[]` | 否 | 支持的 Thinking 模式 effort 档位 | | `adaptive_thinking` | boolean | 否 | 自适应 thinking 开关 | **响应体**:`ResponseType<`[T-ProviderCatalogItem](#t-providercatalogitem)`>`(新建对象,HTTP 201)。 @@ -480,9 +480,9 @@ HTTP 状态码例外(非 200): | `api_key` | string | 否 | 三态,见上文 | | `base_url` | string | 否 | API 基础 URL;不得包含环境变量占位符 | | `default_model` | string | 否 | 该供应商的默认模型;必须是 `models[].model` 之一 | -| `models` | array | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | +| `models` | `{ model: string, max_context_size: number, … }[]` | 是 | 至少一条,条目结构与 `POST /api/v1/providers` 相同 | -**响应体**:`ResponseType<{ provider: T-ProviderCatalogItem }>` +**响应体**:`ResponseType<{ provider: `[T-ProviderCatalogItem](#t-providercatalogitem)` }>` | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -552,8 +552,8 @@ HTTP 状态码例外(非 200): | --- | --- | --- | --- | | `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | 200 | | `:refresh_oauth` | 可选,被忽略 | 同上,仅限 OAuth 凭据的供应商 | 200 | -| `:import_catalog` | 见下 | `{ provider, models_imported }` | 201 | -| `:import_registry` | 见下 | `{ providers, models_imported }` | 201 | +| `:import_catalog` | 见下 | `{ provider: `[T-ProviderCatalogItem](#t-providercatalogitem)`, models_imported: number }` | 201 | +| `:import_registry` | 见下 | `{ providers: `[T-ProviderCatalogItem](#t-providercatalogitem)`[]`, models_imported: number }` | 201 | `:import_catalog` 把一个 models.dev 目录条目导入为已配置供应商:通信协议与端点来自目录解析,目录中的每个模型都写为一个别名;导入已存在的 id 等同于刷新,省略 `api_key` 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时以第一个导入的模型播种 `default_model`。请求体: @@ -591,11 +591,11 @@ HTTP 状态码例外(非 200): 浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底;条目保持上游目录顺序。服务无法导入的条目携带 `rejected: true` 与机器可读的 `reject_reason`。 -**响应体**:`ResponseType<{ items: T-CatalogProviderItem[] }>` +**响应体**:`ResponseType<{ items: `[T-CatalogProviderItem](#t-catalogprovideritem)`[] }>` | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-CatalogProviderItem](#t-catalogprovideritem) 数组 | +| `items` | [T-CatalogProviderItem](#t-catalogprovideritem)`[]` | 目录条目,保持上游顺序 | **非零 code**:`50004`(在线拉取与内置快照均失败)。 From 0ce674855f5b1e781172333b3d759a06137eaf44 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:50:07 +0800 Subject: [PATCH 29/47] docs(zh): normalize the account domain to the endpoint format --- docs/zh/reference/server-api.md | 170 ++++++++++++++++++++++++++------ 1 file changed, 140 insertions(+), 30 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index db2dfe67039..82fa33b9e7c 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -676,147 +676,257 @@ HTTP 状态码例外(非 200): 鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。它不做凭据校验,此后的对话请求仍可能以 `40111` / `40112` 失败。 -**返回**:`ResponseType<`[T-AuthSummary](#t-authsummary)`>`。 +**响应体**:`ResponseType<`[T-AuthSummary](#t-authsummary)`>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-AuthSummary](#t-authsummary) | 鉴权状态快照;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "models_ready": true, "providers_count": 1, "managed_provider": { "name": "managed:kimi-code", "status": "authenticated" } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "models_ready": true, + "providers_count": 1, + "managed_provider": { "name": "managed:kimi-code", "status": "authenticated" } + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/oauth/login` 为托管供应商发起 OAuth device-code(设备码)登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 `authenticated`。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | | `region` | string | 否 | `mainland-cn` 或 `global`;覆盖区域解析结果,仅对本次流程生效 | -**返回**:`ResponseType<`[T-OAuthFlowStart](#t-oauthflowstart)`>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 +**响应体**:`ResponseType<`[T-OAuthFlowStart](#t-oauthflowstart)`>`——进行中的流程报告 `status: "pending"`,打开 `verification_uri_complete`(或打开 `verification_uri` 并输入 `user_code`),然后每隔 `interval` 秒轮询 `GET /api/v1/oauth/login`;已登录的快速路径报告 `status: "authenticated"`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-OAuthFlowStart](#t-oauthflowstart) | 流程发起结果;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "pending", "verification_uri": "https://www.kimi.com/code/device", "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", "user_code": "ABCD-EFGH", "expires_in": 600, "interval": 5, "expires_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "flow_id": "01JZX4...", + "provider": "managed:kimi-code", + "status": "pending", + "verification_uri": "https://www.kimi.com/code/device", + "verification_uri_complete": "https://www.kimi.com/code/device?code=ABCD-EFGH", + "user_code": "ABCD-EFGH", + "expires_in": 600, + "interval": 5, + "expires_at": "2026-09-02T08:10:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/oauth/login` 轮询某供应商的登录流程状态;尚未发起过流程时 `data` 为 `null`。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<`[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)`>` 或 `null`。 +**响应体**:`ResponseType<`[T-OAuthFlowSnapshot](#t-oauthflowsnapshot)` | null>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) `| null` | 流程状态快照;未发起过流程时为 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "flow_id": "01JZX4...", "provider": "managed:kimi-code", "status": "authenticated", "verification_uri": "...", "verification_uri_complete": "...", "user_code": "ABCD-EFGH", "expires_in": 600, "expires_at": "2026-09-02T08:10:00.000Z", "interval": 5, "resolved_at": "2026-09-02T08:02:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "flow_id": "01JZX4...", + "provider": "managed:kimi-code", + "status": "authenticated", + "verification_uri": "...", + "verification_uri_complete": "...", + "user_code": "ABCD-EFGH", + "expires_in": 600, + "expires_at": "2026-09-02T08:10:00.000Z", + "interval": 5, + "resolved_at": "2026-09-02T08:02:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `DELETE /api/v1/oauth/login` 取消某供应商进行中的登录流程;没有进行中的流程时为空操作,返回最近一次已知状态。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ cancelled: boolean, status: string }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `cancelled` | boolean | 只有确实中止了一个 `pending` 流程时才为 `true` | | `status` | string | 调用后的流程状态,取值同 [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) 的 `status` | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "cancelled": true, "status": "cancelled" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "cancelled": true, "status": "cancelled" }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/oauth/logout` 登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 -**Body**: +**触发事件**:`event.config.changed` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `provider` | string | 否 | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ logged_out: boolean, provider: string }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `logged_out` | boolean | 恒 `true` | | `provider` | string | 被登出的供应商名 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "logged_out": true, "provider": "managed:kimi-code" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "logged_out": true, "provider": "managed:kimi-code" }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/oauth/usage` 托管账号的套餐用量与限额,实时取自账号服务。上游失败不会让响应失败——以 `kind: "error"` 带内返回。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<`[T-ManagedUsageResult](#t-managedusageresult)`>`。 +**响应体**:`ResponseType<`[T-ManagedUsageResult](#t-managedusageresult)`>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ManagedUsageResult](#t-managedusageresult) | 用量与限额;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "summary": { "name": "每周额度", "window": { "duration": 1, "unit": "week" }, "used": 42, "limit": 100, "reset_at": "2026-09-09T00:00:00.000Z" }, "limits": [ "..." ], "extra_usage": null }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "kind": "ok", + "summary": { + "name": "每周额度", + "window": { "duration": 1, "unit": "week" }, + "used": 42, + "limit": 100, + "reset_at": "2026-09-09T00:00:00.000Z" + }, + "limits": [ "..." ], + "extra_usage": null + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/oauth/userinfo` 托管账号的资料;带内 `kind: "error"` 约定与 `GET /api/v1/oauth/usage` 相同。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `provider` | string | 托管供应商名称。默认 `managed:kimi-code` | -**返回**:`ResponseType<`[T-ManagedUserInfoResult](#t-manageduserinforesult)`>`(camelCase 载荷)。 +**响应体**:`ResponseType<`[T-ManagedUserInfoResult](#t-manageduserinforesult)`>`(camelCase 载荷)。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-ManagedUserInfoResult](#t-manageduserinforesult) | 账号资料(camelCase);字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "kind": "ok", "userInfo": { "userId": "u_...", "nickname": "dev", "status": "active", "region": "mainland-cn", "userLevel": 2, "userLevelName": "...", "domain": 1, "domainName": "..." } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "kind": "ok", + "userInfo": { + "userId": "u_...", + "nickname": "dev", + "status": "active", + "region": "mainland-cn", + "userLevel": 2, + "userLevelName": "...", + "domain": 1, + "domainName": "..." + } + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/oauth/region` 解析该客户端所属的 Kimi 区域。结果在本地推导,不经网络探测:优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 home 目录中的区域标记文件;默认为 `mainland-cn`。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ region: string }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `region` | string | `mainland-cn` / `global` | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "region": "mainland-cn" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "region": "mainland-cn" }, + "request_id": "01JZX4..." +} ``` ### 工作区与会话 From 6bcbdc6108b93eb6cb707abdbf83dadad1bf9eb3 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:53:40 +0800 Subject: [PATCH 30/47] docs(zh): normalize the workspace-and-session domain to the endpoint format --- docs/zh/reference/server-api.md | 662 ++++++++++++++++++++++++++------ 1 file changed, 536 insertions(+), 126 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 82fa33b9e7c..7ec5d3866f3 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -952,141 +952,241 @@ HTTP 状态码例外(非 200): 列出所有已注册工作区。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: `[T-Workspace](#t-workspace)`[] }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-Workspace](#t-workspace) 数组 | +| `items` | [T-Workspace](#t-workspace)`[]` | 全部已注册工作区 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "wd_my-app_a1b2c3d4e5f6", + "root": "/Users/dev/my-app", + "name": "my-app", + "created_at": "2026-09-01T10:00:00.000Z", + "last_opened_at": "2026-09-02T08:00:00.000Z", + "session_count": 3 + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/workspaces` 注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 -**Body**: +**触发事件**:`event.workspace.created`(根路径首次注册)或 `event.workspace.updated`(重复注册同一根路径) + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `root` | string | 是 | 已存在目录的绝对路径 | | `name` | string | 否 | 显示名,1–100 个字符。默认根目录的基名 | -**返回**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 +**响应体**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`root` 缺失或不是绝对路径)、`40409`(`root` 不存在或不是目录)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Workspace](#t-workspace) | 工作区对象;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(`root` 缺失或不是绝对路径;`details` 为 `{ path, message }[]`)、`40409`(`root` 不存在或不是目录)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "my-app", "created_at": "2026-09-02T08:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 0 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "wd_my-app_a1b2c3d4e5f6", + "root": "/Users/dev/my-app", + "name": "my-app", + "created_at": "2026-09-02T08:00:00.000Z", + "last_opened_at": "2026-09-02T08:00:00.000Z", + "session_count": 0 + }, + "request_id": "01JZX4..." +} ``` #### `PATCH /api/v1/workspaces/{workspace_id}` 重命名工作区——仅修改显示名,根路径不变。 -**Body**: +**触发事件**:`event.workspace.updated` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `name` | string | 是 | 新的显示名,1–100 个字符 | -**返回**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 +**响应体**:`ResponseType<`[T-Workspace](#t-workspace)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Workspace](#t-workspace) | 重命名后的工作区;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40410`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "wd_my-app_a1b2c3d4e5f6", "root": "/Users/dev/my-app", "name": "My App", "created_at": "2026-09-01T10:00:00.000Z", "last_opened_at": "2026-09-02T08:00:00.000Z", "session_count": 3 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "wd_my-app_a1b2c3d4e5f6", + "root": "/Users/dev/my-app", + "name": "My App", + "created_at": "2026-09-01T10:00:00.000Z", + "last_opened_at": "2026-09-02T08:00:00.000Z", + "session_count": 3 + }, + "request_id": "01JZX4..." +} ``` #### `DELETE /api/v1/workspaces/{workspace_id}` 注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 -**返回**:`ResponseType<{ "deleted": true }>`。 +**触发事件**:`event.workspace.deleted` + +**响应体**:`ResponseType<{ deleted: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `deleted` | boolean | 恒 `true` | **非零 code**:`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "deleted": true }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/workspaces/{workspace_id}/trust` 读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。无参数。 -**返回**:`ResponseType<{ "trusted": boolean }>`。 +**响应体**:`ResponseType<{ trusted: boolean }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `trusted` | boolean | 当前信任状态 | **非零 code**:`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "trusted": true }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/workspaces/{workspace_id}/trust` 将工作区标记为信任,并加载其项目级 MCP 配置。无请求体。 -**返回**:`ResponseType<{ "trusted": true }>`。 +**响应体**:`ResponseType<{ trusted: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `trusted` | boolean | 恒 `true` | **非零 code**:`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "trusted": true }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/workspaces/{workspace_id}/untrust` 撤销工作区信任,并卸载其项目级 MCP 配置。无请求体。 -**返回**:`ResponseType<{ "trusted": false }>`。 +**响应体**:`ResponseType<{ trusted: false }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `trusted` | boolean | 恒 `false` | **非零 code**:`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "trusted": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "trusted": false }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/workspaces/{workspace_id}/add-dir` 为工作区添加附加目录,语义与 CLI `--add-dir` 及 TUI `/add-dir` 一致。路径支持绝对路径、相对路径(相对工作区根目录解析)与 `~` 展开。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要添加的目录 | | `persist` | boolean | 否 | 缺省 `true`:追加到 `<项目根>/.kimi-code/local.toml` 的 `workspace.additional_dir`;为 `false` 时仅加入内存中的临时集合(同一工作区所有会话共享),不写盘 | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ project_root: string, config_path: string, additional_dirs: string[], persisted: boolean }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `project_root` | string | 项目根目录 | | `config_path` | string | 写入的本地配置文件路径 | -| `additional_dirs` | array | 全部附加目录(含既有目录) | +| `additional_dirs` | `string[]` | 全部附加目录(含既有目录) | | `persisted` | boolean | 本次是否写盘 | **非零 code**:`40001`(校验失败,或项目本地配置损坏等引擎校验错误;`details` 为 `{ path, message }[]`)、`40409`(`path` 不存在或不是目录)、`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "project_root": "/Users/dev/my-app", "config_path": "/Users/dev/my-app/.kimi-code/local.toml", "additional_dirs": [ "/Users/dev/shared-lib" ], "persisted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "project_root": "/Users/dev/my-app", + "config_path": "/Users/dev/my-app/.kimi-code/local.toml", + "additional_dirs": [ "/Users/dev/shared-lib" ], + "persisted": true + }, + "request_id": "01JZX4..." +} ``` **会话。** @@ -1110,32 +1210,59 @@ HTTP 状态码例外(非 200): #### `POST /api/v1/sessions` -创建会话并返回。目标目录来自 `workspace_id`(已注册的工作区)或 `metadata.cwd`(首次使用时注册该工作区);两者同时提供时必须一致。创建时广播全局 `event.session.created` 事件。 +创建会话并返回。目标目录来自 `workspace_id`(已注册的工作区)或 `metadata.cwd`(首次使用时注册该工作区);两者同时提供时必须一致。 -**Body**: +**触发事件**:`event.session.created`;触碰工作区另触发 `event.workspace.updated`(首次经 `metadata.cwd` 注册时为 `event.workspace.created`) + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `workspace_id` | string | 条件 | 未提供 `metadata.cwd` 时必填。已注册的工作区 id | -| `metadata` | object | 条件 | 自定义元数据。`metadata.cwd` 为工作目录,未提供 `workspace_id` 时必填;同时提供时必须等于工作区根目录 | +| `metadata` | `Record` | 条件 | 自定义元数据。`metadata.cwd` 为工作目录,未提供 `workspace_id` 时必填;同时提供时必须等于工作区根目录 | | `title` | string | 否 | 初始标题(至少 1 个字符) | -| `agent_config` | object | 否 | schema 接受但当前不会应用——模型与各模式请经 `POST .../profile` 设置 | +| `agent_config` | `{ model?: string, … }` | 否 | schema 接受但当前不会应用——模型与各模式请经 `POST .../profile` 设置 | -**返回**:`ResponseType<`[T-Session](#t-session)`>`。 +**响应体**:`ResponseType<`[T-Session](#t-session)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Session](#t-session) | 新建的会话;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(`workspace_id` 与 `metadata.cwd` 二缺一,或不一致;`details` 为 `{ path, message }[]`)、`40409`(工作目录不存在或不是目录)、`40410`(工作区未注册)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "", "created_at": "2026-09-02T08:00:00.000Z", "updated_at": "2026-09-02T08:00:00.000Z", "busy": false, "main_turn_active": false, "pending_interaction": "none", "archived": false, "metadata": { "cwd": "/Users/dev/my-app" }, "agent_config": { "model": "" }, "usage": { "...": 0 }, "permission_rules": [], "message_count": 0, "last_seq": 0 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "session_01JZX4...", + "workspace_id": "wd_my-app_a1b2c3d4e5f6", + "title": "", + "created_at": "2026-09-02T08:00:00.000Z", + "updated_at": "2026-09-02T08:00:00.000Z", + "busy": false, + "main_turn_active": false, + "pending_interaction": "none", + "archived": false, + "metadata": { "cwd": "/Users/dev/my-app" }, + "agent_config": { "model": "" }, + "usage": { "...": 0 }, + "permission_rules": [], + "message_count": 0, + "last_seq": 0 + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions` 跨工作区列出会话,按 `updated_at` 最新在前。特例:不提供 `page_size`(且不提供 `archived_only`)时,响应是单个不分页的窗口,`has_more` 恒为 `false`——要真正翻页请传入 `page_size`。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -1148,56 +1275,112 @@ HTTP 状态码例外(非 200): | `exclude_empty` | boolean | 去掉没有任何用户提示词的会话 | | `workspace_id` | string | 限定到单个工作区(别名会被解析) | -**返回**:`ResponseType<{ items: T-Session[], has_more: boolean }>`。 +**响应体**:`ResponseType<{ items: `[T-Session](#t-session)`[]`, has_more: boolean }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-Session](#t-session)`[]` | 一页会话,按 `updated_at` 最新在前 | +| `has_more` | boolean | 是否还有更早的会话 | **非零 code**:`40001`(互斥参数同用;`details` 为 `{ path, message }[]`)、`40410`(未知的 `workspace_id`)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fix the login page", "...": "..." } ], "has_more": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "session_01JZX4...", + "workspace_id": "wd_my-app_a1b2c3d4e5f6", + "title": "Fix the login page", + "...": "..." + } + ], + "has_more": false + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}` 从索引中读取单个会话。`last_seq` 携带真实的事件水位(watermark):存活会话为当前事件日志的序列号,冷会话为最后持久化的水位——用它作为 `subscribe` 的 `cursors` 起点时回放为空。其余会话端点的 `last_seq` 均为 `0` 占位。 -**返回**:`ResponseType<`[T-Session](#t-session)`>`。 +**响应体**:`ResponseType<`[T-Session](#t-session)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Session](#t-session) | 会话对象;字段见类型汇总 | **非零 code**:`40401`(会话不存在,或其工作区已无法解析)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fix the login page", "busy": false, "main_turn_active": false, "pending_interaction": "none", "last_turn_reason": "completed", "archived": false, "last_prompt": "adjust the button spacing", "metadata": { "cwd": "/Users/dev/my-app" }, "agent_config": { "model": "kimi-for-coding" }, "usage": { "...": 0 }, "permission_rules": [], "message_count": 0, "last_seq": 128 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "session_01JZX4...", + "workspace_id": "wd_my-app_a1b2c3d4e5f6", + "title": "Fix the login page", + "busy": false, + "main_turn_active": false, + "pending_interaction": "none", + "last_turn_reason": "completed", + "archived": false, + "last_prompt": "adjust the button spacing", + "metadata": { "cwd": "/Users/dev/my-app" }, + "agent_config": { "model": "kimi-for-coding" }, + "usage": { "...": 0 }, + "permission_rules": [], + "message_count": 0, + "last_seq": 128 + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/profile` 读取会话档案——与 `GET /api/v1/sessions/{session_id}` 相同的线上载荷(`last_seq` 为 `0` 占位)。 -**返回**:`ResponseType<`[T-Session](#t-session)`>`。 +**响应体**:`ResponseType<`[T-Session](#t-session)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Session](#t-session) | 会话档案;字段见类型汇总 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "...": "..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "id": "session_01JZX4...", "...": "..." }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/profile` -更新会话档案:标题、自定义元数据以及 main agent 的配置。设置的标题会成为自定义标题,优先级高于生成的标题;设置标题会广播全局 `session.meta.updated` 事件。 +更新会话档案:标题、自定义元数据以及 main agent 的配置。设置的标题会成为自定义标题,优先级高于生成的标题。 -**Body**: +**触发事件**:`session.meta.updated`(设置标题时)、`goal.updated`(`goal_objective` / `goal_control` 变更目标时) + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `title` | string | 否 | 新标题(至少 1 个字符);会成为自定义标题 | -| `metadata` | object | 否 | 合并进会话自定义元数据的键 | -| `agent_config` | object | 否 | main agent 的部分配置;字段见下,均为可选,且都会立即应用 | -| `permission_rules` | array | 否 | 被接受但不回显(T-Session 恒 `permission_rules: []`) | +| `metadata` | `Record` | 否 | 合并进会话自定义元数据的键 | +| `agent_config` | `{ model?: string, thinking?: string, … }` | 否 | main agent 的部分配置;字段见下,均为可选,且都会立即应用 | +| `permission_rules` | `{ id: string, tool_name: string, … }[]` | 否 | 被接受但不回显(T-Session 恒 `permission_rules: []`) | `agent_config` 字段: @@ -1215,64 +1398,98 @@ HTTP 状态码例外(非 200): schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers`,但更新路由当前不会应用它们。 -**返回**:`ResponseType<`[T-Session](#t-session)`>`(更新后)。 +**响应体**:`ResponseType<`[T-Session](#t-session)`>`(更新后)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Session](#t-session) | 更新后的会话;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX4...", "title": "Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "id": "session_01JZX4...", "title": "Fix the login page", "...": "..." }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/title/generate` -通过托管供应商的 `chat_title` 工具根据会话的提示词生成标题并应用,同时广播 `session.meta.updated`。生成需要托管 OAuth 登录和 `auto_session_title` 实验开关;未提供 `force` 时,已有自定义标题或已生成标题的会话会上报为不可用。 +通过托管供应商的 `chat_title` 工具根据会话的提示词生成标题并应用。生成需要托管 OAuth 登录和 `auto_session_title` 实验开关;未提供 `force` 时,已有自定义标题或已生成标题的会话会上报为不可用。 -**Body**: +**触发事件**:`session.meta.updated` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `force` | boolean | 否 | 即使已有自定义或生成的标题也重新生成。默认 `false` | | `source` | string | 否 | 标题输入:`user_prompts`(默认)/ `first_turn` / `digest` | -**返回**:`ResponseType<{ "title": string }>`——当前应用到会话的标题。 +**响应体**:`ResponseType<{ title: string }>`——当前应用到会话的标题。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `title` | string | 应用到会话的标题 | **非零 code**:`40401`、`40923`(开关未开启、没有托管登录或尚无提示词内容、已有标题但未提供 `force`,或后端请求失败)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "title": "Fix the login page" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "title": "Fix the login page" }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}:{action}` 会话动作经同一条路由分发:路径尾部解析为 `{session_id}:{action}`,请求体按动作的 schema 校验。每个动作都会先解析会话,因此会话未知时都可能返回 `40401`。 -| 动作 | Body | data(code = 0) | 特有非零 code | +**触发事件**:`:fork` → `event.session.created`;`:compact` → `compaction.started`(随后进入 compaction 事件流,见 [agent 事件](#agent-事件));`:undo` → `session.meta.updated`;`:btw` → `agent.created`;`:archive` → `event.session.archived`;`:abort` / `:restore` 无 + +**响应体**:统一 `ResponseType` 信封,`data` 形态随动作(见下表)。 + +| 动作 | 请求体 | `data`(code = 0) | 特有非零 code | | --- | --- | --- | --- | -| `:fork` | `{ title?, metadata? }` | [T-Session](#t-session)(新会话;广播 `event.session.created`) | `40901`(有进行中的轮次) | +| `:fork` | `{ title?, metadata? }` | [T-Session](#t-session)(新会话) | `40901`(有进行中的轮次) | | `:compact` | `{ instruction? }` | `{}`(空对象;进度经 `compaction.*` 事件投递) | `40910`(有轮次或上下文变更进行中,或无可压缩内容) | -| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items, has_more }, status }`——剩余上下文消息最新在前;`status` 同 [T-SessionStatus](#t-sessionstatus)。回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,形态不定) | -| `:abort` | 无 | `{ "aborted": true }` | — | -| `:btw` | 无 | `{ "agent_id": string }`——把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文;需要可用的模型配置 | — | -| `:archive` | 无 | `{ "archived": true }`——会话从默认列表中消失(`include_archive` / `archived_only` 仍会列出),广播 `event.session.archived` | — | +| `:undo` | `{ count?=1, page_size?≤100 }` | `{ messages: { items: `[T-Message](#t-message)`[]`, has_more: boolean }, status: `[T-SessionStatus](#t-sessionstatus)` }`——剩余上下文消息最新在前;回退 main agent 的对话 `count` 个轮次,并同步修正派生的会话状态(包括 `last_prompt`) | `40901`、`40911`(`data` 为引擎 details 或 `null`,形态不定) | +| `:abort` | 无 | `{ aborted: true }` | — | +| `:btw` | 无 | `{ agent_id: string }`——把 main agent fork 成一个禁用工具调用的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文;需要可用的模型配置 | — | +| `:archive` | 无 | `{ archived: true }`——会话从默认列表中消失(`include_archive` / `archived_only` 仍会列出) | — | | `:restore` | 无 | [T-Session](#t-session)(`archived: false`) | — | 共有非零 code:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`。 -**示例**(`:fork`): +**响应示例**(`:fork`): ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX5...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "title": "Fork: Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "session_01JZX5...", + "workspace_id": "wd_my-app_a1b2c3d4e5f6", + "title": "Fork: Fix the login page", + "...": "..." + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/children` 列出会话的子会话——即通过 `POST .../children` 创建的会话。游标分页遵循 [分页](#分页)。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -1281,81 +1498,162 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` | `page_size` | integer | 1–100。默认 `100` | | `busy` | boolean | 只保留忙碌(或只保留空闲)的子会话 | -**返回**:`ResponseType<{ items: T-Session[], has_more: boolean }>`。 +**响应体**:`ResponseType<{ items: `[T-Session](#t-session)`[]`, has_more: boolean }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-Session](#t-session)`[]` | 一页子会话 | +| `has_more` | boolean | 是否还有更早的子会话 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "session_01JZX5...", "...": "..." } ], "has_more": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ { "id": "session_01JZX5...", "...": "..." } ], + "has_more": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/children` -创建子会话:fork 当前会话并记录为其子会话;广播 `event.session.created`。适用与 `:fork` 相同的进行中轮次限制。 +创建子会话:fork 当前会话并记录为其子会话。适用与 `:fork` 相同的进行中轮次限制。 -**Body**: +**触发事件**:`event.session.created` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `title` | string | 否 | 子会话的标题(至少 1 个字符)。默认 `Child: ` | -| `metadata` | object | 否 | 子会话的自定义元数据 | +| `metadata` | `Record` | 否 | 子会话的自定义元数据 | -**返回**:`ResponseType<`[T-Session](#t-session)`>`。 +**响应体**:`ResponseType<`[T-Session](#t-session)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40901`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Session](#t-session) | 新建的子会话;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40901`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "session_01JZX6...", "title": "Child: Fix the login page", "...": "..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "id": "session_01JZX6...", "title": "Child: Fix the login page", "...": "..." }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/status` main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复。无参数。 -**返回**:`ResponseType<`[T-SessionStatus](#t-sessionstatus)`>`。 +**响应体**:`ResponseType<`[T-SessionStatus](#t-sessionstatus)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-SessionStatus](#t-sessionstatus) | 实时状态汇总;字段见类型汇总 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "busy": false, "model": "kimi-for-coding", "thinking_level": "medium", "permission": "manual", "plan_mode": false, "swarm_mode": false, "tower_mode": false, "context_tokens": 15230, "max_context_tokens": 262144, "context_usage": 0.058 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "busy": false, + "model": "kimi-for-coding", + "thinking_level": "medium", + "permission": "manual", + "plan_mode": false, + "swarm_mode": false, + "tower_mode": false, + "context_tokens": 15230, + "max_context_tokens": 262144, + "context_usage": 0.058 + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/goal` 读取会话当前的目标快照;没有活跃目标时为 `null`。注意该载荷使用 camelCase 键。无参数。 -**返回**:`ResponseType<`[T-GoalSnapshot](#t-goalsnapshot)`>` 或 `null`。 +**响应体**:`ResponseType<`[T-GoalSnapshot](#t-goalsnapshot)` | null>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-GoalSnapshot](#t-goalsnapshot) `| null` | 目标快照(camelCase);无活跃目标时为 `null` | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "goalId": "goal_...", "objective": "Ship the release", "status": "active", "turnsUsed": 3, "tokensUsed": 152000, "wallClockMs": 540000, "budget": { "tokenBudget": 1000000, "turnBudget": 50, "wallClockBudgetMs": null, "remainingTokens": 848000, "remainingTurns": 47, "remainingWallClockMs": null, "tokenBudgetReached": false, "turnBudgetReached": false, "wallClockBudgetReached": false, "overBudget": false } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "goalId": "goal_...", + "objective": "Ship the release", + "status": "active", + "turnsUsed": 3, + "tokensUsed": 152000, + "wallClockMs": 540000, + "budget": { + "tokenBudget": 1000000, + "turnBudget": 50, + "wallClockBudgetMs": null, + "remainingTokens": 848000, + "remainingTurns": 47, + "remainingWallClockMs": null, + "tokenBudgetReached": false, + "turnBudgetReached": false, + "wallClockBudgetReached": false, + "overBudget": false + } + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/warnings` 读取会话级告警。目前的产生者只有 `AGENTS.md` 过大检查(`agents-md-oversized`),因此大多数会话的列表为空。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ warnings: { code: string, message: string, severity: 'info' | 'warning' | 'error' }[] }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `warnings` | array | `{ code, message, severity }[]`;`severity` 为 `info` / `warning` / `error` | +| `warnings` | `{ code: string, message: string, severity: 'info' \| 'warning' \| 'error' }[]` | 会话级告警;大多数会话为空 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "warnings": [ { "code": "agents-md-oversized", "message": "AGENTS.md is ...", "severity": "warning" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "warnings": [ + { "code": "agents-md-oversized", "message": "AGENTS.md is ...", "severity": "warning" } + ] + }, + "request_id": "01JZX4..." +} ``` **运行时绑定。** @@ -1371,7 +1669,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 读取 main agent 的运行时绑定。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ workspace_id: string, runtime_id: string }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | @@ -1380,30 +1678,45 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/runtime` 切换 main agent 的运行时绑定。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `runtime_id` | string | 是 | 目标运行时 id | -**返回**:同 `GET .../runtime`。 +**响应体**:`ResponseType<{ workspace_id: string, runtime_id: string }>`(同 `GET .../runtime`)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `workspace_id` | string | 所属工作区 id | +| `runtime_id` | string | 切换后绑定的运行时 id | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40420`(不存在该 `runtime_id` 的运行时)、`40926`(运行时存在但不可用)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "workspace_id": "wd_my-app_a1b2c3d4e5f6", "runtime_id": "local" }, + "request_id": "01JZX4..." +} ``` **会话快照。** @@ -1412,14 +1725,37 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 为重新同步后重建客户端组装一份原子快照:会话、最近的消息、进行中的轮次、存活的 subagent 以及待处理交互,全部盖上 `as_of_seq` 水位与用于重新订阅的 `epoch`——恢复流程见 [断线恢复](#断线恢复)。与普通的会话端点不同,内嵌的会话携带实时的 `agent_config.model` 与真实的 `usage` 总计。无参数。 -**返回**:`ResponseType<`[T-SnapshotResponse](#t-snapshotresponse)`>`。 +**响应体**:`ResponseType<`[T-SnapshotResponse](#t-snapshotresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-SnapshotResponse](#t-snapshotresponse) | 原子快照;字段见类型汇总 | **非零 code**:`40401`、`50001`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "as_of_seq": 128, "epoch": "01JZX4...", "session": { "id": "session_01JZX4...", "agent_config": { "model": "kimi-for-coding" }, "usage": { "input_tokens": 152000, "...": 0 }, "...": "..." }, "messages": { "items": [ "..." ], "has_more": true }, "in_flight_turn": null, "subagents": [], "pending_approvals": [], "pending_questions": [] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "as_of_seq": 128, + "epoch": "01JZX4...", + "session": { + "id": "session_01JZX4...", + "agent_config": { "model": "kimi-for-coding" }, + "usage": { "input_tokens": 152000, "...": 0 }, + "...": "..." + }, + "messages": { "items": [ "..." ], "has_more": true }, + "in_flight_turn": null, + "subagents": [], + "pending_approvals": [], + "pending_questions": [] + }, + "request_id": "01JZX4..." +} ``` **会话导出。** @@ -1428,14 +1764,14 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 将会话连同诊断日志一起导出为 zip 附件(`kimi-session-.zip`)。响应是 `application/zip` 二进制流,不返回 `ResponseType`(`content-disposition: attachment`、`cache-control: no-store`);客户端断连即中止导出。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `web_log` | string | 否 | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 | | `desktop` | boolean | 否 | 同时包含桌面宿主的日志。默认 `false` | -**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`50001`。 +**非零 code**(`ResponseType`):`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`50001`。 **文件历史(实验性)。** @@ -1454,33 +1790,44 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 返回单个轮次开始与结束检查点之间每个文件的精确增删行数。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `turn_id` | integer | **必填。** 轮次 id(≥ 0) | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ changes: { path: string, status: 'added' | 'modified' | 'deleted', additions: number, deletions: number, binary?: boolean, oversize?: boolean }[], enabled: boolean, recorded: boolean }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `changes` | array | `{ path, status, additions, deletions, binary?, oversize? }[]`;`status` 为 `added` / `modified` / `deleted`;二进制与超大文件的增删行为 `0`,并以 `binary` / `oversize` 标记 | +| `changes` | `{ path: string, status: 'added' \| 'modified' \| 'deleted', additions: number, deletions: number, binary?: boolean, oversize?: boolean }[]` | 逐文件增删统计;二进制与超大文件的增删行为 `0`,并以 `binary` / `oversize` 标记 | | `enabled` | boolean | 实验开关是否开启 | | `recorded` | boolean | 该轮次是否有已记录的检查点 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "changes": [ { "path": "src/index.ts", "status": "modified", "additions": 12, "deletions": 3 } ], "enabled": true, "recorded": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "changes": [ + { "path": "src/index.ts", "status": "modified", "additions": 12, "deletions": 3 } + ], + "enabled": true, + "recorded": true + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/file-history/content` 返回某文件在指定轮次检查点的完整内容;`phase: "end"` 时若该文件在结束检查点没有记录,回退到开始检查点的版本。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -1488,18 +1835,23 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `path` | string | **必填。** 文件路径 | | `phase` | string | `start`(默认)/ `end`——取轮次开始还是结束检查点 | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ content: { version: number, content?: string, binary?: boolean } | null }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `content` | object \| null | `{ version, content?, binary? }`——`version` 为该文件在检查点的版本号;二进制文件只携带 `binary: true` 不携带文本;无记录时为 `null` | +| `content` | `{ version: number, content?: string, binary?: boolean } \| null` | `version` 为该文件在检查点的版本号;二进制文件只携带 `binary: true` 不携带文本;无记录时为 `null` | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "content": { "version": 2, "content": "import ..." } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "content": { "version": 2, "content": "import ..." } }, + "request_id": "01JZX4..." +} ``` **v2 会话。** @@ -1516,7 +1868,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -1535,34 +1887,92 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | `page` | integer | 无状态的 1 起始页码;与 `page_token` 互斥(同传返回 `40001`) | | `page_token` | string | 上一页返回的翻页令牌 | -**返回**:`ResponseType<`[T-V2SessionPage](#t-v2sessionpage)`>`(flat)或 [T-V2SessionGroupPage](#t-v2sessiongrouppage)(`by_workspace`)。每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 +**响应体**:`ResponseType<`[T-V2SessionPage](#t-v2sessionpage)`>`(`view=flat`,默认)或 `ResponseType<`[T-V2SessionGroupPage](#t-v2sessiongrouppage)`>`(`view=by_workspace`)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-V2SessionPage](#t-v2sessionpage) 或 [T-V2SessionGroupPage](#t-v2sessiongrouppage) | 一页结果;字段见类型汇总 | + +每页额外携带 `total`(过滤后的集合大小);翻页令牌绑定首页查询条件(含投影),中途改条件返回 `40922`;`page` 模式每次请求都是独立快照,不签发令牌,`next_page_token` 恒为 `null`。`by_workspace` 时每组携带该工作区按 `sort` 排序的前 `group.page_size` 条会话及其匹配总数 `total`;只有至少一条匹配会话的工作区才会出现,组间按组内首条会话的 sort key 排序(相同则按工作区 id)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知 `include` / `fields`、组合非法)、`40922`。 +**非零 code**:`40001`(未知 `include` / `fields`、组合非法;`details` 为 `{ path, message }[]`)、`40922`。 -**示例**(`view=by_workspace`): +**响应示例**(`view=by_workspace`): ```json -{ "code": 0, "msg": "success", "data": { "groups": [ { "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "sessions": [ { "id": "session_01JZX4...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ], "total": 42 } ], "total": 7, "has_more": true, "next_page_token": "eyJ2IjoxLCJmIjoi..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "groups": [ + { + "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, + "sessions": [ + { + "id": "session_01JZX4...", + "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, + "meta": { + "title": "Fix the login page", + "last_prompt": "adjust the button spacing", + "created_at": 1787000000000, + "updated_at": 1787000100000, + "archived": false, + "archived_at": null + }, + "activity": { "status": "idle", "model": "kimi-for-coding" } + } + ], + "total": 42 + } + ], + "total": 7, + "has_more": true, + "next_page_token": "eyJ2IjoxLCJmIjoi..." + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/sessions:archive` 与 `POST /api/v2/sessions:restore` 面向会话管理页的批量归档 / 恢复。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回。 -**Body**: +**触发事件**:`:archive` → `event.session.archived`(每个成功归档的会话一条);`:restore` 无 + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `ids` | array | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | +| `ids` | `string[]` | 是 | 会话 id 数组——非空、去重后不超过 5000 条 | -**返回**:`ResponseType<`[T-V2BatchSessionResponse](#t-v2batchsessionresponse)`>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 +**响应体**:`ResponseType<`[T-V2BatchSessionResponse](#t-v2batchsessionresponse)`>`——`results` 保持输入顺序,不存在的 id 在自身条目里报 `40401`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-V2BatchSessionResponse](#t-v2batchsessionresponse) | 批量结果;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "results": [ { "id": "session_a", "ok": true }, { "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } } ], "succeeded": 1, "failed": 1 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "results": [ + { "id": "session_a", "ok": true }, + { + "id": "session_b", + "ok": false, + "error": { "code": 40401, "message": "session session_b does not exist" } + } + ], + "succeeded": 1, + "failed": 1 + }, + "request_id": "01JZX4..." +} ``` ### 对话 From f32c3891f6aa13b3c7372a56fc9abc54014bd92c Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:55:47 +0800 Subject: [PATCH 31/47] docs(zh): normalize the conversation domain to the endpoint format --- docs/zh/reference/server-api.md | 407 ++++++++++++++++++++++++++------ 1 file changed, 331 insertions(+), 76 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 7ec5d3866f3..37d4d682cd3 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -1992,38 +1992,54 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 读取 main agent 的提示词队列快照。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ active: `[T-PromptItem](#t-promptitem)` | null, queued: `[T-PromptItem](#t-promptitem)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `active` | object \| null | 运行中的提示词([T-PromptItem](#t-promptitem)),空闲时为 `null` | -| `queued` | array | 等待中的 [T-PromptItem](#t-promptitem),按顺序 | +| `active` | [T-PromptItem](#t-promptitem) `| null` | 运行中的提示词,空闲时为 `null` | +| `queued` | [T-PromptItem](#t-promptitem)`[]` | 等待中的提示词,按顺序 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "active": { "prompt_id": "prompt_01J...", "user_message_id": "msg_session_..._000007", "status": "running", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "queued": [] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "active": { + "prompt_id": "prompt_01J...", + "user_message_id": "msg_session_..._000007", + "status": "running", + "content": [ { "type": "text", "text": "..." } ], + "created_at": "2026-09-02T08:04:00.000Z" + }, + "queued": [] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/prompts` 向会话提交一条用户提示词。先校验媒体引用,然后把可选的覆盖项应用到目标 Agent——`profile`(与 `model` / `thinking` 一起绑定),接着是 `model`、`thinking`、`permission_mode` 和 `disabled_tools`——随后提示词入队;响应在提示词被接受后立即返回,不等待轮次执行。提供 `skills` 时,提示词以打包的 Skill 激活方式运行,而不是普通用户提示词。 -**Body**: +**触发事件**:`prompt.submitted`(随后进入轮次事件流,见 [agent 事件](#agent-事件))、`session.meta.updated` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `content` | array | 是 | 非空的内容块数组;变体见下 | +| `content` | `{ type: string, … }[]` | 是 | 非空的内容块数组;变体见下 | | `agent_id` | string | 否 | 目标 Agent。默认为 main agent | | `prompt_id` | string | 否 | 客户端选定的提示词 id,用于幂等提交;已被进行中提示词占用的 id 返回 `40927`,已完成的返回 `40903`。不能与 `skills` 同用 | -| `skills` | array | 否 | 打包的 Skill 激活,至少 1 个 `{ name, args? }` 条目;每个 Skill 必须存在且可由用户激活 | +| `skills` | `{ name: string, args?: string }[]` | 否 | 打包的 Skill 激活,至少 1 个条目;每个 Skill 必须存在且可由用户激活 | | `profile` | string | 否 | 提交前要绑定的 Agent 档案 | | `model` | string | 否 | 要切换到的模型别名 | | `thinking` | string | 否 | Thinking 强度等级 | | `permission_mode` | string | 否 | `manual` / `yolo` / `auto` | -| `disabled_tools` | array | 否 | 要为会话禁用的工具名 | +| `disabled_tools` | `string[]` | 否 | 要为会话禁用的工具名 | schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 `goal_control`,但提交路由当前不会应用它们。每个 `content` 内容块是按 `type` 区分的对象: @@ -2035,54 +2051,94 @@ schema 还接受 `metadata`、`plan_mode`、`swarm_mode`、`goal_objective` 和 schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinking` 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 `file_id` 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。 -**返回**:`ResponseType<`[T-PromptItem](#t-promptitem)`>`(被接受的提示词)。 +**响应体**:`ResponseType<`[T-PromptItem](#t-promptitem)`>`(被接受的提示词)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-PromptItem](#t-promptitem) | 被接受的提示词;字段见类型汇总 | **非零 code**(鉴权错误族的 `data` / `details` 形态各异): -- `40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40407`(引用的 `file_id` 不存在或 kind 不匹配)、`40415`(未知的 Skill)、`40901`(会话忙)、`40912`(Skill 无法由用户激活)、`40927`(`prompt_id` 冲突) +- `40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40407`(引用的 `file_id` 不存在或 kind 不匹配)、`40415`(未知的 Skill)、`40901`(会话忙)、`40912`(Skill 无法由用户激活)、`40927`(`prompt_id` 冲突) - `40110`(尚未配置供应商):`data: null`,`details: null` - `40111` / `40112`(供应商没有凭据 / 凭据被拒绝):`data: null`,`details: { provider_id }`(缺 `provider_id` 时降级为 `50001`) - `40113`(模型无法解析):`data: null`,`details: { model_id?, provider_id? }` 或 `null` - `40903`(`prompt_id` 属于已完成的提示词):`data: { "aborted": false }` -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "prompt_id": "prompt_01J...", "user_message_id": "msg_session_..._000008", "status": "running", "content": [ { "type": "text", "text": "用一句话介绍这个仓库" } ], "created_at": "2026-09-02T08:06:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "prompt_id": "prompt_01J...", + "user_message_id": "msg_session_..._000008", + "status": "running", + "content": [ { "type": "text", "text": "用一句话介绍这个仓库" } ], + "created_at": "2026-09-02T08:06:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/prompts:steer` 把排队的提示词插入进行中的轮次,让运行中的轮次立即消费它们,而不是先运行结束。 -**Body**: +**触发事件**:`prompt.steered` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `prompt_ids` | array | 是 | 非空的排队提示词 id 数组 | +| `prompt_ids` | `string[]` | 是 | 非空的排队提示词 id 数组 | -**返回**:`ResponseType<{ "steered": true, "prompt_ids": string[] }>`。 +**响应体**:`ResponseType<{ steered: true, prompt_ids: string[] }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40402`(所列提示词 id 不在队列中)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `steered` | boolean | 恒 `true` | +| `prompt_ids` | `string[]` | 被插入轮次的提示词 id | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40402`(所列提示词 id 不在队列中)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "steered": true, "prompt_ids": [ "prompt_01J..." ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "steered": true, "prompt_ids": [ "prompt_01J..." ] }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:{action}` 单条提示词动作,经 `POST .../prompts/{tail}` 分发:`:abort` 中止运行中的提示词;`:steer` 把单条排队的提示词插入进行中的轮次(集合形式的单提示词版)。无请求体。 -**返回**:`ResponseType`:`:abort` → `{ "aborted": true }`;`:steer` → `{ "steered": true, "prompt_ids": [prompt_id] }`。 +**触发事件**:`:abort` → `prompt.aborted`;`:steer` → `prompt.steered` + +**响应体**:统一 `ResponseType` 信封:`:abort` → `{ aborted: true }`;`:steer` → `{ steered: true, prompt_ids: [prompt_id] }`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `aborted` | boolean | 仅 `:abort`:恒 `true` | +| `steered` | boolean | 仅 `:steer`:恒 `true` | +| `prompt_ids` | `string[]` | 仅 `:steer`:被插入轮次的提示词 id(单条) | **非零 code**:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`、`40402`、`40903`(提示词已完成,`data: { "aborted": false }`)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "aborted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "aborted": true }, + "request_id": "01JZX4..." +} ``` **消息。** @@ -2098,7 +2154,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 分页返回 main agent 的消息历史,最新在前;读取历史会在会话为冷态时将其恢复。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -2107,28 +2163,64 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `page_size` | integer | 1–100。默认 `50` | | `role` | string | 只保留单一角色:`user` / `assistant` / `tool` / `system`。过滤在分页切片之后应用,因此过滤后的一页可能少于 `page_size` 条而 `has_more` 仍为 `true`——持续翻页直到 `has_more` 为 `false` | -**返回**:`ResponseType<{ items: T-Message[], has_more: boolean }>`([T-Message](#t-message))。 +**响应体**:`ResponseType<{ items: `[T-Message](#t-message)`[]`, has_more: boolean }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-Message](#t-message)`[]` | 一页消息,最新在前 | +| `has_more` | boolean | 是否还有更早的消息 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "assistant", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:05:00.000Z" } ], "has_more": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "msg_session_..._000007", + "session_id": "session_01JZX4...", + "role": "assistant", + "content": [ { "type": "text", "text": "..." } ], + "created_at": "2026-09-02T08:05:00.000Z" + } + ], + "has_more": true + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/messages/{message_id}` 按 id 从同一历史中读取单条消息。无参数。 -**返回**:`ResponseType<`[T-Message](#t-message)`>`。 +**响应体**:`ResponseType<`[T-Message](#t-message)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Message](#t-message) | 消息对象;字段见类型汇总 | **非零 code**:`40401`、`40403`(该会话中不存在此 id 的消息)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "msg_session_..._000007", "session_id": "session_01JZX4...", "role": "user", "content": [ { "type": "text", "text": "..." } ], "created_at": "2026-09-02T08:04:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "msg_session_..._000007", + "session_id": "session_01JZX4...", + "role": "user", + "content": [ { "type": "text", "text": "..." } ], + "created_at": "2026-09-02T08:04:00.000Z" + }, + "request_id": "01JZX4..." +} ``` **审批。** @@ -2144,31 +2236,52 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 列出会话待处理的审批请求;读取列表会在会话为冷态时将其恢复。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: `[T-ApprovalRequest](#t-approvalrequest)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-ApprovalRequest](#t-approvalrequest) 数组 | +| `items` | [T-ApprovalRequest](#t-approvalrequest)`[]` | 待处理的审批请求 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "approval_id": "approval_01J...", "session_id": "session_01JZX4...", "turn_id": 3, "tool_call_id": "toolu_01J...", "tool_name": "Bash", "action": "run", "tool_input_display": { "kind": "command", "command": "pnpm test" }, "created_at": "2026-09-02T08:06:30.000Z", "expires_at": "2026-09-03T08:06:30.000Z" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "approval_id": "approval_01J...", + "session_id": "session_01JZX4...", + "turn_id": 3, + "tool_call_id": "toolu_01J...", + "tool_name": "Bash", + "action": "run", + "tool_input_display": { "kind": "command", "command": "pnpm test" }, + "created_at": "2026-09-02T08:06:30.000Z", + "expires_at": "2026-09-03T08:06:30.000Z" + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/approvals/{approval_id}` 答复一个待处理的审批请求,让等待中的工具调用继续执行(或不执行)。 -**Body**: +**触发事件**:`event.approval.resolved` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -2177,14 +2290,24 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `feedback` | string | 否 | 回传给 Agent 的自由文本反馈 | | `selected_label` | string | 否 | 当请求提供了带标签的选项时(例如计划审阅),所选选项的标签 | -**返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 +**响应体**:`ResponseType<{ resolved: true, resolved_at: string }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `resolved` | boolean | 恒 `true` | +| `resolved_at` | string | ISO 8601 时间 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40404`(没有该 id 的待处理审批)、`40902`(已被答复,`data: { "resolved": false }`)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:00.000Z" }, + "request_id": "01JZX4..." +} ``` **提问。** @@ -2201,35 +2324,61 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 列出会话待处理的提问。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `status` | string | **必填。** 必须为 `pending`,缺省或其他值返回 `40001` | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: `[T-QuestionRequest](#t-questionrequest)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-QuestionRequest](#t-questionrequest) 数组 | +| `items` | [T-QuestionRequest](#t-questionrequest)`[]` | 待处理的提问 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "question_id": "question_01J...", "session_id": "session_01JZX4...", "questions": [ { "id": "q_0", "question": "选择部署目标", "options": [ { "id": "opt_0_0", "label": "staging" }, { "id": "opt_0_1", "label": "production" } ], "allow_other": true } ], "created_at": "2026-09-02T08:06:40.000Z" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "question_id": "question_01J...", + "session_id": "session_01JZX4...", + "questions": [ + { + "id": "q_0", + "question": "选择部署目标", + "options": [ + { "id": "opt_0_0", "label": "staging" }, + { "id": "opt_0_1", "label": "production" } + ], + "allow_other": true + } + ], + "created_at": "2026-09-02T08:06:40.000Z" + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/questions/{question_id}` 回答一个待处理的提问。两个提问端点经同一条路由 `POST .../questions/{tail}` 分发:单独的提问 id 表示回答问题,`{question_id}:dismiss` 尾部表示忽略。 -**Body**: +**触发事件**:`event.question.answered` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `answers` | object | 是 | 提问条目 id(`q_0`……)到答案对象的映射;答案变体见下 | +| `answers` | `Record` | 是 | 提问条目 id(`q_0`……)到答案对象的映射;答案变体见下 | | `method` | string | 否 | 答案的产生方式:`enter` / `space` / `number_key` / `click` | | `note` | string | 否 | 附在回答上的自由文本备注 | @@ -2243,28 +2392,50 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `multi_with_other` | `option_ids`、`other_text` | 选项加自由文本 | | `skipped` | — | 跳过了该条目 | -**返回**:`ResponseType<{ "resolved": true, "resolved_at": ISO }>`。 +**响应体**:`ResponseType<{ resolved: true, resolved_at: string }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`details` 逐字段说明)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `resolved` | boolean | 恒 `true` | +| `resolved_at` | string | ISO 8601 时间 | -**示例**: +**非零 code**:`40001`(校验失败,`details` 逐字段说明;`details` 为 `{ path, message }[]`)、`40401`、`40405`(没有该 id 的待处理提问)、`40902`(已被答复,`data: { "resolved": false }`)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:10.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "resolved": true, "resolved_at": "2026-09-02T08:07:10.000Z" }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/questions/{question_id}:dismiss` 忽略一个待处理的提问,不作回答。无请求体。 -**成功形态**:`ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ "dismissed": true, "dismissed_at": ISO }`——客户端必须特殊处理该端点的成功码。 +**触发事件**:`event.question.dismissed` + +**响应体**:成功时 `ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ dismissed: true, dismissed_at: string }`——客户端必须特殊处理该端点的成功码。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `dismissed` | boolean | 恒 `true` | +| `dismissed_at` | string | ISO 8601 时间 | **非零 code**:`40401`、`40405`、`40902`(已被答复,`data: { "resolved": false }`)。 -**示例**: +**响应示例**: ```json -{ "code": 40909, "msg": "question dismissed", "data": { "dismissed": true, "dismissed_at": "2026-09-02T08:07:20.000Z" }, "request_id": "01JZX4..." } +{ + "code": 40909, + "msg": "question dismissed", + "data": { "dismissed": true, "dismissed_at": "2026-09-02T08:07:20.000Z" }, + "request_id": "01JZX4..." +} ``` **转录。** @@ -2282,7 +2453,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 返回某个 Agent 的结构化转录中的一页:轮次(含其步骤与帧)以及轮次之间的标记与任务引用。活跃会话从内存存储应答(先回填所请求 Agent 的持久化历史);冷会话则从持久化的线上记录重建 Agent。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -2291,76 +2462,160 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin | `after_turn` | string | 只保留晚于该轮次 id 的轮次;与 `before_turn` 互斥 | | `page_size` | integer | 1–100 个轮次。默认 `20` | -**返回**:`ResponseType<`[T-TranscriptResponse](#t-transcriptresponse)`>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 +**响应体**:`ResponseType<`[T-TranscriptResponse](#t-transcriptresponse)`>`——分页单位是轮次:不带游标时返回最新的一页,`has_more` 表示还有更早的轮次;`tasks` / `interactions` / `attachments` / `todos` / `meta` / `agents` / `pending_interactions` 是不分页、随每次响应一起返回的全局 Agent 状态;`seq` 是该 Agent 用于恢复流的 op 批次水位(仅活跃会话携带)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-TranscriptResponse](#t-transcriptresponse) | 一页转录;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "items": [ { "kind": "turn", "turnId": 3, "...": "..." } ], "has_more": true, "tasks": [], "interactions": [], "attachments": [], "todos": [], "prompts": [], "meta": { "...": "..." }, "agents": [ { "agentId": "main", "...": "..." } ], "pending_interactions": [], "seq": 42 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "agent_id": "main", + "items": [ { "kind": "turn", "turnId": 3, "...": "..." } ], + "has_more": true, + "tasks": [], + "interactions": [], + "attachments": [], + "todos": [], + "prompts": [], + "meta": { "...": "..." }, + "agents": [ { "agentId": "main", "...": "..." } ], + "pending_interactions": [], + "seq": 42 + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/transcript/ops` 从服务端的 op 日志提供点对点的补漏:某个 Agent 的 `seq > since_seq` 的已记录 op 批次,最旧在前。它是 `transcript_since` 恢复游标的 REST 对应物,共享同一份有界日志,因此适用相同的回退规则。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `since_seq` | integer | **必填。** 调用方已应用的最后一个 op 批次 seq,最小为 `0`;返回其之后的批次 | -**返回**:`ResponseType<`[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)`>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 +**响应体**:`ResponseType<`[T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse)`>`——`complete: true` 表示直到 `latest_seq` 的每个批次都在;`complete: false` 表示日志已不再覆盖到 `since_seq`(或会话根本不是活跃状态),调用方必须回退为一次完整的 `GET .../transcript` 刷新。会话存在但非活跃时固定返回 `{ agent_id, batches: [], latest_seq: 0, complete: false }`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-TranscriptOpsCatchupResponse](#t-transcriptopscatchupresponse) | 补漏批次;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "batches": [ { "seq": 41, "ops": [ { "op": "append", "...": "..." } ] } ], "latest_seq": 42, "complete": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "agent_id": "main", + "batches": [ { "seq": 41, "ops": [ { "op": "append", "...": "..." } ] } ], + "latest_seq": 42, + "complete": true + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/transcript/user-messages` 列出会话中每个开启轮次的输入,按 Agent 分组且不分页:真实用户文本、以斜杠命令形式使用的 Skill 与插件命令、以及 cron 提示词——可通过 `origin` 区分——另有仅含附件的提示词,其 `prompt` 投影为空。所列消息引用的附件实体会随响应一起返回(仅元数据,绝不包含字节内容)。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `agent_id` | string | 只读取一个 Agent(纯文本 id)。默认读取所有在册 Agent(冷会话保证含 main agent) | -**返回**:`ResponseType<`[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)`>`。 +**响应体**:`ResponseType<`[T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-TranscriptUserMessagesResponse](#t-transcriptusermessagesresponse) | 按 Agent 分组的用户输入;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "agents": [ { "agent_id": "main", "messages": [ { "turn_id": 3, "ordinal": 0, "state": "completed", "origin": { "kind": "user" }, "prompt": "adjust the button spacing", "started_at": "2026-09-02T08:04:00.000Z" } ], "attachments": [] } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "agents": [ + { + "agent_id": "main", + "messages": [ + { + "turn_id": 3, + "ordinal": 0, + "state": "completed", + "origin": { "kind": "user" }, + "prompt": "adjust the button spacing", + "started_at": "2026-09-02T08:04:00.000Z" + } + ], + "attachments": [] + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/transcript/plan` 按时间线顺序读取某个 Agent 的 `ExitPlanMode` 工具调用的计划信息——计划内容、计划文件路径、提供的选项以及审阅结果。内容投影自第一个可用的事实来源:关联的审批交互(交互式审阅)、实时工具帧的展示(auto 模式),或工具结果的输出文本;每个条目在 `source` 中记录具体来源。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `agent_id` | string | **必填。** Agent id(纯文本形式) | | `tool_call_id` | string | 将读取范围限定到单次 `ExitPlanMode` 调用;不提供时列出所有可恢复计划内容的调用 | -**返回**:`ResponseType<`[T-TranscriptPlanResponse](#t-transcriptplanresponse)`>`。 +**响应体**:`ResponseType<`[T-TranscriptPlanResponse](#t-transcriptplanresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-TranscriptPlanResponse](#t-transcriptplanresponse) | 计划条目列表;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40416`(提供了 `tool_call_id`,但不存在该 id 的 `ExitPlanMode` 调用)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "agent_id": "main", "plans": [ { "tool_call_id": "toolu_01J...", "turn_id": 2, "source": "interaction", "plan": "# Plan\n ...", "path": "/Users/dev/my-app/.kimi-code/plans/....md", "options": [ { "label": "实施" } ], "review": { "state": "approved", "selected_option": "实施" } } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "agent_id": "main", + "plans": [ + { + "tool_call_id": "toolu_01J...", + "turn_id": 2, + "source": "interaction", + "plan": "# Plan\n ...", + "path": "/Users/dev/my-app/.kimi-code/plans/....md", + "options": [ { "label": "实施" } ], + "review": { "state": "approved", "selected_option": "实施" } + } + ] + }, + "request_id": "01JZX4..." +} ``` ### 任务 From 8f577120654e4eb6e5b440a7e8e04287b6926db1 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:56:34 +0800 Subject: [PATCH 32/47] docs(zh): normalize the task domain to the endpoint format --- docs/zh/reference/server-api.md | 83 +++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 37d4d682cd3..5becefb8d79 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -2634,62 +2634,115 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 列出会话的后台任务。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `status` | string | 只保留单一状态:`running` / `completed` / `failed` / `cancelled` | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: `[T-Task](#t-task)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-Task](#t-task) 数组;冷会话为 `[]` | +| `items` | [T-Task](#t-task)`[]` | 后台任务;冷会话为 `[]` | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(未知的 `status`)、`40401`。 +**非零 code**:`40001`(未知的 `status`;`details` 为 `{ path, message }[]`)、`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "task_01J...", "session_id": "session_01JZX4...", "kind": "bash", "description": "pnpm test", "status": "running", "created_at": "2026-09-02T08:06:00.000Z", "started_at": "2026-09-02T08:06:00.000Z", "command": "pnpm test", "run_in_background": true } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "task_01J...", + "session_id": "session_01JZX4...", + "kind": "bash", + "description": "pnpm test", + "status": "running", + "created_at": "2026-09-02T08:06:00.000Z", + "started_at": "2026-09-02T08:06:00.000Z", + "command": "pnpm test", + "run_in_background": true + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/tasks/{task_id}` 读取单个后台任务,可选携带输出的末尾片段。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `with_output` | boolean | 在响应中包含输出末尾片段。默认 `false` | | `output_bytes` | integer | 请求的输出末尾片段的字节大小,最小 `0`。默认 `32768` | -**返回**:`ResponseType<`[T-Task](#t-task)`>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 +**响应体**:`ResponseType<`[T-Task](#t-task)`>`;`with_output=true` 且输出非空时附加 `output_preview` 与 `output_bytes`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Task](#t-task) | 任务对象;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40406`(没有该 id 的任务;冷会话完全没有实时任务)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "task_01J...", "session_id": "session_01JZX4...", "kind": "bash", "description": "pnpm test", "status": "completed", "created_at": "2026-09-02T08:06:00.000Z", "started_at": "2026-09-02T08:06:00.000Z", "completed_at": "2026-09-02T08:06:40.000Z", "command": "pnpm test", "output_preview": "... tail of output ...", "output_bytes": 4096, "run_in_background": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "task_01J...", + "session_id": "session_01JZX4...", + "kind": "bash", + "description": "pnpm test", + "status": "completed", + "created_at": "2026-09-02T08:06:00.000Z", + "started_at": "2026-09-02T08:06:00.000Z", + "completed_at": "2026-09-02T08:06:40.000Z", + "command": "pnpm test", + "output_preview": "... tail of output ...", + "output_bytes": 4096, + "run_in_background": true + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/tasks/{task_id}:{action}` 任务动作经 `POST .../tasks/{tail}` 分发:`:cancel` 取消运行中的任务;`:detach` 将运行中的前台任务转入后台而不终止它(等待该任务的工具调用立即以后台任务结果返回,轮次继续推进)。已在后台或已结束的任务上 `:detach` 为幂等空操作。无请求体。 -**返回**:`ResponseType`:`:cancel` → `{ "cancelled": true }`;`:detach` → `{ "detached": boolean, "status": string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 +**触发事件**:`:cancel` → `task.terminated`(及派生的 `background.task.terminated`);`:detach` 无 + +**响应体**:统一 `ResponseType` 信封:`:cancel` → `{ cancelled: true }`;`:detach` → `{ detached: boolean, status: string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `cancelled` | boolean | 仅 `:cancel`:恒 `true` | +| `detached` | boolean | 仅 `:detach`:本次确实转入后台时为 `true` | +| `status` | string | 仅 `:detach`:调用后的任务状态 | **非零 code**:`40001`(动作缺失或未知;`details` 为 `{ path, message }[]`)、`40401`、`40406`、`40904`(任务已结束,`data: { "cancelled": false }` 且 `details: { "current_status" }`)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "detached": true, "status": "running" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "detached": true, "status": "running" }, + "request_id": "01JZX4..." +} ``` - ### 终端 **终端。** From 950c8420e8306fde233843b1c7d0b3eeddb5ea5e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:57:11 +0800 Subject: [PATCH 33/47] docs(zh): normalize the terminal domain to the endpoint format --- docs/zh/reference/server-api.md | 95 +++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 5becefb8d79..a4e402fef70 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -2760,25 +2760,43 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出会话的终端;读取列表会在会话为冷态时将其恢复。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ items: `[T-Terminal](#t-terminal)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `items` | array | [T-Terminal](#t-terminal) 数组 | +| `items` | [T-Terminal](#t-terminal)`[]` | 会话的终端 | **非零 code**:`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "running", "created_at": "2026-09-02T08:08:00.000Z" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "id": "term_01J...", + "session_id": "session_01JZX4...", + "cwd": ".", + "shell": "/bin/zsh", + "cols": 80, + "rows": 24, + "status": "running", + "created_at": "2026-09-02T08:08:00.000Z" + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/terminals` 为会话创建一个 PTY 终端。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -2788,42 +2806,89 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 | `cols` | integer | 否 | 终端宽度,正数。默认 `80` | | `rows` | integer | 否 | 终端高度,正数。默认 `24` | -**返回**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 +**响应体**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`details` 逐字段说明)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Terminal](#t-terminal) | 新建的终端;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败,`details` 逐字段说明;`details` 为 `{ path, message }[]`)、`40401`、`41304`(`cwd` 解析后越出会话工作区)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "running", "created_at": "2026-09-02T08:08:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "term_01J...", + "session_id": "session_01JZX4...", + "cwd": ".", + "shell": "/bin/zsh", + "cols": 80, + "rows": 24, + "status": "running", + "created_at": "2026-09-02T08:08:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/terminals/{terminal_id}` 读取单个终端。无参数。 -**返回**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 +**响应体**:`ResponseType<`[T-Terminal](#t-terminal)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-Terminal](#t-terminal) | 终端对象;字段见类型汇总 | **非零 code**:`40401`、`40414`(没有该 id 的终端)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "term_01J...", "session_id": "session_01JZX4...", "cwd": ".", "shell": "/bin/zsh", "cols": 80, "rows": 24, "status": "exited", "created_at": "2026-09-02T08:08:00.000Z", "exited_at": "2026-09-02T08:09:00.000Z", "exit_code": 0 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "term_01J...", + "session_id": "session_01JZX4...", + "cwd": ".", + "shell": "/bin/zsh", + "cols": 80, + "rows": 24, + "status": "exited", + "created_at": "2026-09-02T08:08:00.000Z", + "exited_at": "2026-09-02T08:09:00.000Z", + "exit_code": 0 + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/terminals/{terminal_id}:close` 关闭终端并结束其进程。经 `POST .../terminals/{tail}` 分发,`close` 是唯一动作。无请求体。 -**返回**:`ResponseType<{ "closed": true }>`。 +**响应体**:`ResponseType<{ closed: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `closed` | boolean | 恒 `true` | **非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40401`、`40414`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "closed": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "closed": true }, + "request_id": "01JZX4..." +} ``` ### 扩展 From 2e4c7f06c6ce8b67678e83905c3370b2e4a21953 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 18:59:44 +0800 Subject: [PATCH 34/47] docs(zh): normalize the extension domain to the endpoint format --- docs/zh/reference/server-api.md | 586 ++++++++++++++++++++++++++------ 1 file changed, 480 insertions(+), 106 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index a4e402fef70..a162406e13a 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -2909,53 +2909,92 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出单个会话可用的技能,按会话的优先级合并所有来源(内置、插件、extra、用户、项目);会话处于冷态时读取目录会恢复该会话。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ skills: `[T-SkillDescriptor](#t-skilldescriptor)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `skills` | array | [T-SkillDescriptor](#t-skilldescriptor) 数组 | +| `skills` | [T-SkillDescriptor](#t-skilldescriptor)`[]` | 会话可用的技能 | **非零 code**:`40401`(会话不存在或未激活)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "skills": [ { "name": "review", "description": "...", "path": "/Users/dev/my-app/.agents/skills/review/SKILL.md", "source": "project" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "skills": [ + { + "name": "review", + "description": "...", + "path": "/Users/dev/my-app/.agents/skills/review/SKILL.md", + "source": "project" + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/workspaces/{workspace_id}/skills` 列出该工作区中的会话将看到的技能目录,但不创建或恢复会话。无参数。 -**返回**:同 `GET /api/v1/sessions/{session_id}/skills`。 +**响应体**:`ResponseType<{ skills: `[T-SkillDescriptor](#t-skilldescriptor)`[]` }>`(同 `GET /api/v1/sessions/{session_id}/skills`)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `skills` | [T-SkillDescriptor](#t-skilldescriptor)`[]` | 工作区会话将看到的技能 | **非零 code**:`40410`(工作区不存在)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "skills": [ { "name": "review", "description": "...", "path": "...", "source": "project" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "skills": [ + { "name": "review", "description": "...", "path": "...", "source": "project" } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate` 在会话中激活技能——以技能内容加上 `args` 与附件在 main agent 上开启一个轮次。经 `POST .../skills/{tail}` 分发,`activate` 是唯一动作。 -**Body**: +**触发事件**:`skill.activated`(随后进入轮次事件流,见 [agent 事件](#agent-事件)) + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `args` | string | 否 | 传给技能的自由文本参数,相当于斜杠命令后的文本 | -| `attachments` | array | 否 | 随激活携带的媒体块。`image` / `video` 块带 `source` 对象(`kind` 为 `url` / `base64` / `file` / `session_media`,与提示词内容块同形);`file` 块带顶层 `file_id`、`name`、`media_type`、`size` | +| `attachments` | `{ type: string, … }[]` | 否 | 随激活携带的媒体块。`image` / `video` 块带 `source` 对象(`kind` 为 `url` / `base64` / `file` / `session_media`,与提示词内容块同形);`file` 块带顶层 `file_id`、`name`、`media_type`、`size` | + +**响应体**:`ResponseType<{ activated: true, skill_name: string }>`。 -**返回**:`ResponseType<{ "activated": true, "skill_name": string }>`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `activated` | boolean | 恒 `true` | +| `skill_name` | string | 被激活的技能名 | **非零 code**:`40001`(校验失败或动作后缀不支持;`details` 为 `{ path, message }[]`)、`40401`、`40407`(引用的附件文件不存在)、`40415`(没有该名称的技能)、`40912`(技能类型不允许用户激活)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "activated": true, "skill_name": "review" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "activated": true, "skill_name": "review" }, + "request_id": "01JZX4..." +} ``` **插件。** @@ -2973,68 +3012,140 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出插件市场目录并合并实时安装状态。目录按请求从配置的市场 URL 拉取(超时 10 秒);使用默认目录时,目录中缺少的内置能力会作为条目合并进来(带 `capabilityId`),当前平台不支持的能力对应条目会被剔除。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ entries: `[T-PluginMarketplaceEntry](#t-pluginmarketplaceentry)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `entries` | array | 市场条目(camelCase):`{ id, tier, displayName, description?, homepage?, keywords?, version?, source, installed?, updateAvailable?, capabilityId? }`;`tier` 为 `official` / `curated` / `third-party`;`installed` 为 `{ version?, enabled }`;`source` 即 `POST /api/v1/plugins` 的 `source` 取值 | +| `entries` | [T-PluginMarketplaceEntry](#t-pluginmarketplaceentry)`[]` | 市场条目(camelCase);字段见类型汇总 | **非零 code**:`50001`(市场不可达或返回了非法目录)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "entries": [ { "id": "my-plugin", "tier": "official", "displayName": "My Plugin", "source": "https://github.com/example/my-plugin", "installed": { "version": "1.2.0", "enabled": true }, "updateAvailable": false } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "entries": [ + { + "id": "my-plugin", + "tier": "official", + "displayName": "My Plugin", + "source": "https://github.com/example/my-plugin", + "installed": { "version": "1.2.0", "enabled": true }, + "updateAvailable": false + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/plugins` 列出已安装插件。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ plugins: `[T-PluginSummary](#t-pluginsummary)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `plugins` | array | [T-PluginSummary](#t-pluginsummary) 数组 | +| `plugins` | [T-PluginSummary](#t-pluginsummary)`[]` | 已安装插件摘要(camelCase) | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "plugins": [ { "id": "my-plugin", "displayName": "My Plugin", "version": "1.2.0", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 1, "enabledMcpServerCount": 1, "hookCount": 0, "commandCount": 1, "hasErrors": false, "source": "github" } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "plugins": [ + { + "id": "my-plugin", + "displayName": "My Plugin", + "version": "1.2.0", + "enabled": true, + "state": "ok", + "skillCount": 2, + "mcpServerCount": 1, + "enabledMcpServerCount": 1, + "hookCount": 0, + "commandCount": 1, + "hasErrors": false, + "source": "github" + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/plugins` 安装插件并返回其摘要。 -**Body**: +**触发事件**:`event.plugin.changed` + +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `source` | string | 是 | 安装来源:本地绝对路径、指向 zip 压缩包的 `http(s)` URL,或 GitHub URL——`https://github.com//`,可选地用 `/tree/`、`/releases/tag/` 或 `/commit/` 锁定版本 | -**返回**:`ResponseType<`[T-PluginSummary](#t-pluginsummary)`>`。 +**响应体**:`ResponseType<`[T-PluginSummary](#t-pluginsummary)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-PluginSummary](#t-pluginsummary) | 安装后的插件摘要;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`source` 既不是 URL 也不是绝对路径,或插件加载失败)、`40409`(本地路径不存在)。 +**非零 code**:`40001`(`source` 既不是 URL 也不是绝对路径,或插件加载失败;`details` 为 `{ path, message }[]`)、`40409`(本地路径不存在)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "my-plugin", "displayName": "My Plugin", "enabled": true, "state": "ok", "skillCount": 2, "mcpServerCount": 0, "enabledMcpServerCount": 0, "hookCount": 0, "commandCount": 0, "hasErrors": false, "source": "local-path" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "my-plugin", + "displayName": "My Plugin", + "enabled": true, + "state": "ok", + "skillCount": 2, + "mcpServerCount": 0, + "enabledMcpServerCount": 0, + "hookCount": 0, + "commandCount": 0, + "hasErrors": false, + "source": "local-path" + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/plugins/{plugin_id}:{action}` 插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 -**返回**:`ResponseType<{ "ok": true }>`。 +**触发事件**:`event.plugin.changed` + +**响应体**:`ResponseType<{ ok: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `ok` | boolean | 恒 `true` | **非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40419`(没有该 id 的已安装插件)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "ok": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "ok": true }, + "request_id": "01JZX4..." +} ``` **能力。** @@ -3051,44 +3162,97 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出所有已注册能力及其就绪状态。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ capabilities: `[T-CapabilityStatus](#t-capabilitystatus)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `capabilities` | array | [T-CapabilityStatus](#t-capabilitystatus) 数组 | +| `capabilities` | [T-CapabilityStatus](#t-capabilitystatus)`[]` | 各能力的就绪状态(camelCase) | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "capabilities": [ { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "ready", "steps": [ { "id": "os", "state": "ok" } ], "install": { "running": false } } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "capabilities": [ + { + "id": "kimi-cu", + "displayName": "Kimi Computer Use", + "description": "...", + "supported": true, + "state": "ready", + "steps": [ { "id": "os", "state": "ok" } ], + "install": { "running": false } + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/capabilities/{capability_id}` 读取单个能力的就绪状态——`:install` 动作的轮询对应端点。无参数。 -**返回**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 +**响应体**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-CapabilityStatus](#t-capabilitystatus) | 能力的就绪状态;字段见类型汇总 | **非零 code**:`40418`(没有该 id 的能力)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "partial", "steps": [ { "id": "app", "state": "missing", "optional": true } ], "install": { "running": true, "percent": 40 } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "kimi-cu", + "displayName": "Kimi Computer Use", + "description": "...", + "supported": true, + "state": "partial", + "steps": [ { "id": "app", "state": "missing", "optional": true } ], + "install": { "running": true, "percent": 40 } + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/capabilities/{capability_id}:install` 在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 -**返回**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 +**触发事件**:`event.capability.changed`(安装进度,易失事件) + +**响应体**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-CapabilityStatus](#t-capabilitystatus) | 发起安装后的能力状态;字段见类型汇总 | **非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40418`、`40924`(安装已在进行中)、`40925`(当前平台 / 架构不支持)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "kimi-cu", "displayName": "Kimi Computer Use", "description": "...", "supported": true, "state": "not_installed", "steps": [ "..." ], "install": { "running": true, "step": "download", "percent": 0 } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "kimi-cu", + "displayName": "Kimi Computer Use", + "description": "...", + "supported": true, + "state": "not_installed", + "steps": [ "..." ], + "install": { "running": true, "step": "download", "percent": 0 } + }, + "request_id": "01JZX4..." +} ``` **工具与 MCP(v1)。** @@ -3105,52 +3269,85 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出当前生效 Agent 的工具——即 `session_id` 指定会话的 main agent;省略参数时取最近创建的存活会话。会话不在本服务进程中存活时列表为空。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `session_id` | string | 要查看其 main agent 的会话。默认最近创建的存活会话 | -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ tools: `[T-ToolDescriptor](#t-tooldescriptor)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `tools` | array | [T-ToolDescriptor](#t-tooldescriptor) 数组 | +| `tools` | [T-ToolDescriptor](#t-tooldescriptor)`[]` | 当前生效 Agent 的工具 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "tools": [ { "name": "Bash", "description": "...", "input_schema": null, "source": "builtin", "active": true } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "tools": [ + { + "name": "Bash", + "description": "...", + "input_schema": null, + "source": "builtin", + "active": true + } + ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/mcp/servers` 列出当前生效 Agent 配置的 MCP 服务(与 `GET /api/v1/tools` 相同的会话选取规则);没有存活会话时列表为空。无参数。 -**返回**:`ResponseType`,`data` 字段: +**响应体**:`ResponseType<{ servers: `[T-McpServer](#t-mcpserver)`[]` }>`。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `servers` | array | [T-McpServer](#t-mcpserver) 数组 | +| `servers` | [T-McpServer](#t-mcpserver)`[]` | 当前生效 Agent 的 MCP 服务 | -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "servers": [ { "id": "my-server", "name": "my-server", "transport": "stdio", "status": "connected", "tool_count": 5 } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "servers": [ + { "id": "my-server", "name": "my-server", "transport": "stdio", "status": "connected", "tool_count": 5 } + ] + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/mcp/servers/{mcp_server_id}:restart` 重新连接当前生效 Agent 的某个 MCP 服务。经 `POST /api/v1/mcp/servers/{tail}` 分发,`restart` 是唯一动作。无请求体。 -**返回**:`ResponseType<{ "restarting": true }>`。 +**响应体**:`ResponseType<{ restarting: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `restarting` | boolean | 恒 `true` | **非零 code**:`40001`(缺少动作后缀或动作未知;`details` 为 `{ path, message }[]`)、`40408`(没有该 id 的 MCP 服务;无存活会话时同样返回此错误)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "restarting": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "restarting": true }, + "request_id": "01JZX4..." +} ``` **v2 MCP。** @@ -3180,217 +3377,374 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 列出管理面已知的全部 MCP server。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组。 +**响应体**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`[]>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpManagedServer](#t-mcpmanagedserver)`[]` | 全部已知 server(camelCase);字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ], "envKeys": [ "API_KEY" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true } ], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [ + { + "name": "my-server", + "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ], "envKeys": [ "API_KEY" ] }, + "source": "global", + "origin": "/Users/dev/.kimi-code/mcp.json", + "mutable": true + } + ], + "request_id": "01JZX4..." +} ``` #### `GET /api/v2/mcp/servers/{name}` 按运行时名称获取单个 server。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>`。 +**响应体**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpManagedServer](#t-mcpmanagedserver) | 单个 server;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40408`(不存在该名称的 server)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "name": "my-server", "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ] }, "source": "global", "origin": "/Users/dev/.kimi-code/mcp.json", "mutable": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "name": "my-server", + "config": { "transport": "stdio", "command": "npx", "args": [ "-y", "my-mcp-server" ] }, + "source": "global", + "origin": "/Users/dev/.kimi-code/mcp.json", + "mutable": true + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/servers` 向用户级 `mcp.json` 添加 server。若写入与项目层的同名条目冲突,会因只读被拒绝;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。 -**Body**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 +**请求体**:包含 `name` 的完整 server 配置——`transport`(`stdio` / `http` / `sse`)决定配置形状(见 [T-McpServerConfigView](#t-mcpserverconfigview) 的输入形态)。 + +**响应体**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`[]>`(刷新后的列表)。 -**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpManagedServer](#t-mcpmanagedserver)`[]` | 刷新后的完整列表;字段见类型汇总 | **非零 code**:`40001`(校验失败,或目标条目为只读;`details` 为 `{ path, message }[]`)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "stdio", "command": "npx" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [ + { + "name": "my-server", + "config": { "transport": "stdio", "command": "npx" }, + "source": "global", + "origin": "...", + "mutable": true + } + ], + "request_id": "01JZX4..." +} ``` #### `PUT /api/v2/mcp/servers/{name}` 替换一个用户级条目;身份由路径指定。 -**Body**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 +**请求体**:不含 `name` 的完整 server 配置(形态同 `POST /api/v2/mcp/servers`)。 -**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 +**响应体**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`[]>`(刷新后的列表)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpManagedServer](#t-mcpmanagedserver)`[]` | 刷新后的完整列表;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40408`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "config": { "transport": "http", "url": "https://mcp.example.com" }, "source": "global", "origin": "...", "mutable": true } ], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [ + { + "name": "my-server", + "config": { "transport": "http", "url": "https://mcp.example.com" }, + "source": "global", + "origin": "...", + "mutable": true + } + ], + "request_id": "01JZX4..." +} ``` #### `DELETE /api/v2/mcp/servers/{name}` 删除一个用户级条目。无请求体。 -**返回**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`>` 数组(刷新后的列表)。 +**响应体**:`ResponseType<`[T-McpManagedServer](#t-mcpmanagedserver)`[]>`(刷新后的列表)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpManagedServer](#t-mcpmanagedserver)`[]` | 刷新后的完整列表;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40408`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [], + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/servers:test` 对单个 server 发起真实连接探测,不持久化任何内容。传 `name` 探测注册表条目(含插件与受信任的项目层),或传 `server`(包含 `name` 的完整内联配置)按原样探测;两者都传或都不传会报 `40001`。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `name` | string | 二选一 | 注册表条目的运行时名称 | -| `server` | object | 二选一 | 按原样探测的内联 server 配置(含 `name`) | +| `server` | `{ name: string, transport: string, … }` | 二选一 | 按原样探测的内联 server 配置(含 `name`) | | `cwd` | string | 否 | 项目层并入解析;同时是 stdio 的工作目录 | -**返回**:`ResponseType<{ "success": boolean, "output": string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 +**响应体**:`ResponseType<{ success: boolean, output: string }>`——连接成功时 `output` 列出该 server 的可用工具,否则携带失败信息。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `success` | boolean | 连接是否成功 | +| `output` | string | 成功时列出可用工具,否则为失败信息 | **非零 code**:`40001`(两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用;`details` 为 `{ path, message }[]`)、`40408`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "success": true, "output": "5 tools: search, fetch, ..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "success": true, "output": "5 tools: search, fetch, ..." }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/servers:inspect` locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 `unavailable` 并在 `error` 中给出说明;探测遇到过期授权时,可能刷新或作废已存储的凭据。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `targets` | array | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | +| `targets` | `( { source: 'global', name: string } \| { source: 'plugin', pluginId: string, serverName: string } )[]` | 否 | 缩小目录范围的 locator 数组;不传则检查全部 server | | `cwd` | string | 否 | 并入该(受信任)目录的项目层 | -**返回**:`ResponseType<`[T-McpServerInspection](#t-mcpserverinspection)`>` 数组。 +**响应体**:`ResponseType<`[T-McpServerInspection](#t-mcpserverinspection)`[]>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpServerInspection](#t-mcpserverinspection)`[]` | 检查目录(camelCase);字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40408`(`targets` 中有 locator 未匹配到任何条目)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "serverId": "global:my-server", "locator": { "source": "global", "name": "my-server" }, "runtimeName": "my-server", "origin": "global", "config": { "transport": "http", "url": "https://mcp.example.com" }, "enabled": true, "editable": true, "authStatus": "oauth-authorized", "checkedAt": 1787000000000 } ], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [ + { + "serverId": "global:my-server", + "locator": { "source": "global", "name": "my-server" }, + "runtimeName": "my-server", + "origin": "global", + "config": { "transport": "http", "url": "https://mcp.example.com" }, + "enabled": true, + "editable": true, + "authStatus": "oauth-authorized", + "checkedAt": 1787000000000 + } + ], + "request_id": "01JZX4..." +} ``` #### `GET /api/v2/mcp/auth-statuses` 注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 `servers:inspect` 更轻量的选择。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `cwd` | string | 并入该(受信任)目录的项目层 | | `verify` | string | `true` 对每个 OAuth 候选发起真实连接验证;`false` 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server | -**返回**:`ResponseType<`[T-McpServerAuthStatus](#t-mcpserverauthstatus)`>` 数组。验证探测可能刷新或作废已存储的凭据。 +**响应体**:`ResponseType<`[T-McpServerAuthStatus](#t-mcpserverauthstatus)`[]>`。验证探测可能刷新或作废已存储的凭据。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-McpServerAuthStatus](#t-mcpserverauthstatus)`[]` | 各 server 的授权状态;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": [ { "name": "my-server", "authStatus": "oauth-authorized" } ], "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": [ { "name": "my-server", "authStatus": "oauth-authorized" } ], + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/auth:begin` 开始一次交互式 OAuth 流程。目标 server 必须使用远程传输(`http` / `sse`)且不含静态 bearer token;静态请求头仅当配置显式设置 `auth: "oauth"` 时允许。 -**Body**:locator(`{ "source": "global", "name" }` 或 `{ "source": "plugin", "pluginId", "serverName" }`);另有可选的 `cwd` 查询参数。 +**请求体**:locator——`{ source: 'global', name: string }` 或 `{ source: 'plugin', pluginId: string, serverName: string }`;另有可选的 `cwd` 查询参数。 -**返回**:`ResponseType`:`{ "status": "authorization-required", "flowId": string, "authorizationUrl": string }`(在浏览器中打开该 URL 完成授权),或授权已存在时 `{ "status": "already-authorized" }`。 +**响应体**:`ResponseType<{ status: 'authorization-required', flowId: string, authorizationUrl: string } | { status: 'already-authorized' }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `status` | string | `authorization-required`(需在浏览器中打开 `authorizationUrl` 完成授权)/ `already-authorized`(授权已存在) | +| `flowId` | string | 仅 `authorization-required`:流程 id,传给 `auth:complete` | +| `authorizationUrl` | string | 仅 `authorization-required`:授权页 URL | -**示例**: +**非零 code**:`40001`(server 无法使用 OAuth:stdio 传输、静态 bearer token,或未设置 `auth: "oauth"` 的静态请求头;`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`(OAuth 流程本身失败)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "status": "authorization-required", "flowId": "flow_01J...", "authorizationUrl": "https://mcp.example.com/authorize?..." }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "status": "authorization-required", + "flowId": "flow_01J...", + "authorizationUrl": "https://mcp.example.com/authorize?..." + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/auth:complete` 等待已开始流程的浏览器回调并完成 code 交换。等待默认 15 分钟(`timeoutMs` 可覆盖),空闲流程无论如何都会在 15 分钟后过期;关闭 HTTP 连接会中止等待。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `flowId` | string | 是 | `auth:begin` 返回的流程 id | | `timeoutMs` | integer | 否 | 等待上限(毫秒)。默认 15 分钟 | -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`flowId` 未知)、`40929`。 +**非零 code**:`40001`(`flowId` 未知;`details` 为 `{ path, message }[]`)、`40929`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/auth:cancel` 在未完成的情况下终止已开始的流程;未知流程会被忽略。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `flowId` | string | 是 | 要终止的流程 id | -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` #### `POST /api/v2/mcp/auth:reset` 清除某个 server 已存储的凭据;失效事件会送达存活的会话。 -**Body**:locator(形态同 `auth:begin`)。 +**请求体**:locator(形态同 `auth:begin`)。 -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40408`(locator 未匹配)、`40929`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` ### 文件与其他 @@ -5219,6 +5573,26 @@ type PluginSummary = { }; ``` +### T-PluginMarketplaceEntry + +插件市场条目(camelCase 载荷),服务端正名为 `PluginMarketplaceEntryWire`。 + +```ts +type PluginMarketplaceEntry = { + id: string; + tier: 'official' | 'curated' | 'third-party'; + displayName: string; + description?: string; + homepage?: string; + keywords?: string[]; + version?: string; + source: string; // 同 POST /api/v1/plugins 的 source 取值 + installed?: { version?: string; enabled: boolean }; // 实时安装状态;未安装时缺省 + updateAvailable?: boolean; + capabilityId?: string; // 内置能力合并进来的条目携带 +}; +``` + ### T-ToolDescriptor ```ts From 176614d68a934dd411059f91f0165b8be6c81139 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:02:13 +0800 Subject: [PATCH 35/47] docs(zh): normalize the files-and-misc domain to the endpoint format --- docs/zh/reference/server-api.md | 690 +++++++++++++++++++++++++------- 1 file changed, 544 insertions(+), 146 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index a162406e13a..03dd89854b5 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -3769,7 +3769,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 列出会话工作区目录下的条目,可选递归子目录。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -3778,25 +3778,53 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `limit` | integer | 否 | 最大条目数,1–1000。默认 `200` | | `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -| `exclude_globs` | array | 否 | 额外要跳过的 glob | +| `exclude_globs` | `string[]` | 否 | 额外要跳过的 glob | | `sort` | string | 否 | `type_first`(默认)/ `name_asc` / `name_desc` / `mtime_desc` / `size_desc` | | `include_git_status` | boolean | 否 | 附带每个条目的 git 状态。默认 `false` | -**返回**:`ResponseType<`[T-FsListResponse](#t-fslistresponse)`>`。 +**响应体**:`ResponseType<`[T-FsListResponse](#t-fslistresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsListResponse](#t-fslistresponse) | 目录条目与截断标记;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`(路径不存在或不是目录)、`41304`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src", "name": "src", "kind": "directory", "modified_at": "2026-09-01T10:00:00.000Z", "child_count": 12 }, { "path": "package.json", "name": "package.json", "kind": "file", "size": 1024, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "application/json" } ], "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "path": "src", + "name": "src", + "kind": "directory", + "modified_at": "2026-09-01T10:00:00.000Z", + "child_count": 12 + }, + { + "path": "package.json", + "name": "package.json", + "kind": "file", + "size": 1024, + "modified_at": "2026-09-01T10:00:00.000Z", + "mime": "application/json" + } + ], + "truncated": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:read` 以文本或 base64 读取会话文件的一段内容。`encoding: "auto"` 时文本以 `utf-8` 返回(非 UTF-8 文本会被转码),二进制内容以 `base64` 返回;`encoding: "utf-8"` 强制按文本读取并拒绝二进制文件。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -3805,218 +3833,381 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `length` | integer | 否 | 读取字节数,1–10485760(10 MiB)。默认 `1048576`(1 MiB) | | `encoding` | string | 否 | `auto`(默认)/ `utf-8` / `base64` | -**返回**:`ResponseType<`[T-FsReadResponse](#t-fsreadresponse)`>`。 +**响应体**:`ResponseType<`[T-FsReadResponse](#t-fsreadresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsReadResponse](#t-fsreadresponse) | 文件内容片段;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`40906`(路径是目录)、`40907`(二进制文件却指定 `utf-8`)、`41302`(文件超过 10 MiB 上限)、`41304`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "content": "import ...", "encoding": "utf-8", "size": 20480, "truncated": false, "etag": "...", "mime": "text/typescript", "language_id": "typescript", "line_count": 512, "is_binary": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "path": "src/index.ts", + "content": "import ...", + "encoding": "utf-8", + "size": 20480, + "truncated": false, + "etag": "...", + "mime": "text/typescript", + "language_id": "typescript", + "line_count": 512, + "is_binary": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:list_many` 一次调用列出多个会话目录;失败的路径折进响应里,而不是让整个请求失败。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `paths` | array | 是 | 要列出的目录,1–100 条 | +| `paths` | `string[]` | 是 | 要列出的目录,1–100 条 | 其余字段(`depth`、`limit`、`show_hidden`、`follow_gitignore`、`exclude_globs`、`sort`、`include_git_status`)与 `fs:list` 相同。 -**返回**:`ResponseType<`[T-FsListManyResponse](#t-fslistmanyresponse)`>`。 +**响应体**:`ResponseType<`[T-FsListManyResponse](#t-fslistmanyresponse)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsListManyResponse](#t-fslistmanyresponse) | 每个路径的条目与局部错误;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "results": { "src": [ { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." } ] }, "truncated_paths": [ "src" ], "partial_errors": { "vendor": { "code": 40409, "msg": "path does not exist" } } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "results": { + "src": [ { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." } ] + }, + "truncated_paths": [ "src" ], + "partial_errors": { "vendor": { "code": 40409, "msg": "path does not exist" } } + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:stat` 查询会话工作区内单个路径的元信息。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要查询的路径,相对于会话工作目录 | -**返回**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`。 +**响应体**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsEntry](#t-fsentry) | 路径元信息;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "size": 20480, "modified_at": "2026-09-01T10:00:00.000Z", "mime": "text/typescript", "is_binary": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "path": "src/index.ts", + "name": "index.ts", + "kind": "file", + "size": 20480, + "modified_at": "2026-09-01T10:00:00.000Z", + "mime": "text/typescript", + "is_binary": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:stat_many` 一次调用查询多个会话路径的元信息;不存在的路径返回 `null`,不会让整个请求失败。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `paths` | array | 是 | 要查询的路径,1–1000 条 | +| `paths` | `string[]` | 是 | 要查询的路径,1–1000 条 | + +**响应体**:`ResponseType<`[T-FsStatManyResponse](#t-fsstatmanyresponse)`>`。 -**返回**:`ResponseType<`[T-FsStatManyResponse](#t-fsstatmanyresponse)`>`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsStatManyResponse](#t-fsstatmanyresponse) | 每个路径的条目(不存在时为 `null`);字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "entries": { "src/index.ts": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." }, "vendor": null } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "entries": { + "src/index.ts": { "path": "src/index.ts", "name": "index.ts", "kind": "file", "modified_at": "..." }, + "vendor": null + } + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:mkdir` 在会话工作区内创建目录。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要创建的目录,相对于会话工作目录 | | `recursive` | boolean | 否 | 创建缺失的父目录。默认 `false` | -**返回**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`(所建目录)。 +**响应体**:`ResponseType<`[T-FsEntry](#t-fsentry)`>`(所建目录)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsEntry](#t-fsentry) | 所建目录的元信息;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`(父目录不存在)、`40919`(路径已存在)、`41304`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "docs/api", "name": "api", "kind": "directory", "modified_at": "2026-09-02T08:10:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "path": "docs/api", + "name": "api", + "kind": "directory", + "modified_at": "2026-09-02T08:10:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:search` 在会话工作区内模糊搜索文件与目录名。`query` 为空时改为列出顶层条目。当 `{session_id}` 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 `POST /api/v1/workspace/fs:search`。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | | `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `include_globs` | `string[]` | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | `string[]` | 否 | 跳过匹配这些 glob 的路径 | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | -**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`([T-FsSearchHit](#t-fssearchhit);命中按得分排序,同分按路径)。 +**响应体**:`ResponseType<{ items: `[T-FsSearchHit](#t-fssearchhit)`[]`, truncated: boolean }>`(命中按得分排序,同分按路径)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-FsSearchHit](#t-fssearchhit)`[]` | 搜索命中 | +| `truncated` | boolean | 命中数被 `limit` 截断 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`(该引用既不是会话,也不是可解析的工作区)、`41303`(命中过多)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "path": "src/server-api.ts", + "name": "server-api.ts", + "kind": "file", + "score": 0.92, + "match_positions": [ 4, 5, 6 ] + } + ], + "truncated": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:grep` 在会话工作区内搜索文件内容——默认按字面字符串,`regex: true` 时按正则表达式。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `pattern` | string | 是 | 要搜索的文本或正则 | | `regex` | boolean | 否 | 将 `pattern` 视为正则表达式。默认 `false` | | `case_sensitive` | boolean | 否 | 默认 `true` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的文件 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的文件 | +| `include_globs` | `string[]` | 否 | 只保留匹配这些 glob 之一的文件 | +| `exclude_globs` | `string[]` | 否 | 跳过匹配这些 glob 的文件 | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | | `max_files` | integer | 否 | 最多扫描的文件数,1–10000。默认 `200` | | `max_matches_per_file` | integer | 否 | 每个文件保留的匹配数,1–10000。默认 `50` | | `max_total_matches` | integer | 否 | 总共保留的匹配数,1–100000。默认 `5000` | | `context_lines` | integer | 否 | 每个匹配携带的上下文行数,0–10。默认 `2` | -**返回**:`ResponseType<`[T-FsGrepResponse](#t-fsgrepresponse)`>`。 +**响应体**:`ResponseType<`[T-FsGrepResponse](#t-fsgrepresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsGrepResponse](#t-fsgrepresponse) | 按文件分组的匹配;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`41303`、`41305`(搜索超时)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "files": [ { "path": "src/index.ts", "matches": [ { "line": 12, "col": 8, "text": "const token = ...", "before": [ "..." ], "after": [ "..." ] } ] } ], "files_scanned": 87, "truncated": false, "elapsed_ms": 42 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "files": [ + { + "path": "src/index.ts", + "matches": [ + { + "line": 12, + "col": 8, + "text": "const token = ...", + "before": [ "..." ], + "after": [ "..." ] + } + ] + } + ], + "files_scanned": 87, + "truncated": false, + "elapsed_ms": 42 + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:git_status` 读取会话工作区的 git 状态,可选限定在一组路径内。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `paths` | array | 否 | 将状态限定在这些路径;省略表示整个工作区 | +| `paths` | `string[]` | 否 | 将状态限定在这些路径;省略表示整个工作区 | + +**响应体**:`ResponseType<`[T-FsGitStatusResponse](#t-fsgitstatusresponse)`>`(注意 camelCase `pullRequest`)。 -**返回**:`ResponseType<`[T-FsGitStatusResponse](#t-fsgitstatusresponse)`>`(注意 camelCase `pullRequest`)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsGitStatusResponse](#t-fsgitstatusresponse) | git 状态;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40908`(git 不可用:不是仓库,或没有 git 可执行文件)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "branch": "main", "ahead": 1, "behind": 0, "entries": { "src/index.ts": "modified" }, "additions": 12, "deletions": 3, "pullRequest": { "number": 3451, "state": "open", "url": "https://github.com/example/repo/pull/3451" } }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "branch": "main", + "ahead": 1, + "behind": 0, + "entries": { "src/index.ts": "modified" }, + "additions": 12, + "deletions": 3, + "pullRequest": { "number": 3451, "state": "open", "url": "https://github.com/example/repo/pull/3451" } + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:diff` 返回会话工作区内单个文件的 unified git diff。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要 diff 的文件,相对于会话工作目录 | -**返回**:`ResponseType<`[T-FsDiffResponse](#t-fsdiffresponse)`>`。 +**响应体**:`ResponseType<`[T-FsDiffResponse](#t-fsdiffresponse)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsDiffResponse](#t-fsdiffresponse) | unified diff 文本;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40908`、`41304`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "src/index.ts", "diff": "@@ -1,4 +1,5 @@\n ...", "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "path": "src/index.ts", "diff": "@@ -1,4 +1,5 @@\n ...", "truncated": false }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:open` 用宿主操作系统的默认程序打开会话文件。仅限 local 运行时。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要打开的文件,相对于会话工作目录 | | `line` | integer | 否 | 在处理程序支持时跳转到的行号(正整数) | -**返回**:`ResponseType<{ "opened": true }>`。 +**响应体**:`ResponseType<{ opened: true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `opened` | boolean | 恒 `true` | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "opened": true }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:open-in` 在指定的宿主应用程序中打开会话文件或目录。仅限 local 运行时。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -4024,79 +4215,118 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `path` | string | 是 | 要打开的文件或目录,相对于会话工作目录 | | `line` | integer | 否 | 在应用支持时跳转到的行号(正整数) | -**返回**:`ResponseType<{ "opened": true }>`。 +**响应体**:`ResponseType<{ opened: true }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `opened` | boolean | 恒 `true` | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`、`50001`(应用启动失败)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "opened": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "opened": true }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/sessions/{session_id}/fs:reveal` 在宿主操作系统的文件管理器中显示会话文件。仅限 local 运行时。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 要显示的文件,相对于会话工作目录 | -**返回**:`ResponseType<{ "revealed": true }>`。 +**响应体**:`ResponseType<{ revealed: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `revealed` | boolean | 恒 `true` | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "revealed": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "revealed": true }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/fs/{path}:download` -从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流——见 [二进制与流式端点](#二进制与流式端点)。 +从会话工作区下载文件;`{path}` 是相对于工作区的文件路径,并带字面量 `:download` 后缀。响应为支持 Range 与 ETag 的二进制流,不返回 `ResponseType`——见 [二进制与流式端点](#二进制与流式端点)。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `runtime_id` | string | 从哪个运行时读取。默认 `local` | -**非零 code**(`ResponseType`):`40001`(校验失败,`details` 为 `{ path, message }[]`)(路径缺失或不以 `:download` 结尾)、`40401`、`40409`、`41304`。 +**非零 code**(`ResponseType`):`40001`(路径缺失或不以 `:download` 结尾;`details` 为 `{ path, message }[]`)、`40401`、`40409`、`41304`。 #### `POST /api/v1/workspace/fs:search` `fs:search` 的无会话形式:工作区改由请求体而非 URL 携带。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `workspace` | string | 是 | 已注册工作区 id 或绝对根路径(当场注册) | | `query` | string | 是 | 搜索文本;`""` 表示列出顶层 | | `limit` | integer | 否 | 最大命中数,1–200。默认 `50` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `include_globs` | `string[]` | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | `string[]` | 否 | 跳过匹配这些 glob 的路径 | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | | `runtime_id` | string | 否 | 在哪个运行时上搜索。默认 `local` | -**返回**:`ResponseType<{ items: T-FsSearchHit[], truncated: boolean }>`,命中结构与排序同 `fs:search`。 +**响应体**:`ResponseType<{ items: `[T-FsSearchHit](#t-fssearchhit)`[]`, truncated: boolean }>`(命中结构与排序同 `fs:search`)。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-FsSearchHit](#t-fssearchhit)`[]` | 搜索命中 | +| `truncated` | boolean | 命中数被 `limit` 截断 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40410`(工作区不存在,且不是可用的绝对路径)、`41303`。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.92, "match_positions": [ 4, 5, 6 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "path": "src/server-api.ts", + "name": "server-api.ts", + "kind": "file", + "score": 0.92, + "match_positions": [ 4, 5, 6 ] + } + ], + "truncated": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/workspace/fs:suggest` 在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 `@` 文件提及的后端。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -4105,84 +4335,148 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `limit` | integer | 否 | 最大候选数,1–200。默认 `50` | | `follow_gitignore` | boolean | 否 | 跳过 gitignore 的路径。默认 `true` | | `show_hidden` | boolean | 否 | 包含点文件。默认 `false` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `include_globs` | `string[]` | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | `string[]` | 否 | 跳过匹配这些 glob 的路径 | | `runtime_id` | string | 否 | 在哪个运行时上补全。默认 `local` | -**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`([T-FsSuggestItem](#t-fssuggestitem),结构同搜索命中)。 +**响应体**:`ResponseType<{ items: `[T-FsSuggestItem](#t-fssuggestitem)`[]`, truncated: boolean }>`(结构同搜索命中)。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-FsSuggestItem](#t-fssuggestitem)`[]` | 补全候选 | +| `truncated` | boolean | 候选数被 `limit` 截断 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40410`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40410`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "path": "src/server-api.ts", + "name": "server-api.ts", + "kind": "file", + "score": 0.9, + "match_positions": [ 4, 5 ] + } + ], + "truncated": false + }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/fs:suggest` `fs:suggest` 的工作区无关形式:请求体直接携带绝对 `roots`(1–32 条)。首 root 为主——其候选以相对路径返回,附加 root 的候选为绝对路径;重叠的 root 按 realpath 去重。每个 root 都会先 stat,不存在则整个请求失败。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `roots` | array | 是 | 绝对根路径数组,1–32 条 | +| `roots` | `string[]` | 是 | 绝对根路径数组,1–32 条 | | `query` | string | 是 | 要补全的部分路径文本 | | `limit` | integer | 否 | 最大候选数。默认 `50` | | `follow_gitignore` | boolean | 否 | 默认 `true` | | `show_hidden` | boolean | 否 | 默认 `false` | -| `include_globs` | array | 否 | 只保留匹配这些 glob 之一的路径 | -| `exclude_globs` | array | 否 | 跳过匹配这些 glob 的路径 | +| `include_globs` | `string[]` | 否 | 只保留匹配这些 glob 之一的路径 | +| `exclude_globs` | `string[]` | 否 | 跳过匹配这些 glob 的路径 | | `runtime_id` | string | 否 | 默认 `local` | -**返回**:`ResponseType<{ items: T-FsSuggestItem[], truncated: boolean }>`。 +**响应体**:`ResponseType<{ items: `[T-FsSuggestItem](#t-fssuggestitem)`[]`, truncated: boolean }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `items` | [T-FsSuggestItem](#t-fssuggestitem)`[]` | 补全候选 | +| `truncated` | boolean | 候选数被 `limit` 截断 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(某个 root 不存在)、`40420`、`40926`。 +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40409`(某个 root 不存在)、`40420`、`40926`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "path": "src/server-api.ts", "name": "server-api.ts", "kind": "file", "score": 0.9, "match_positions": [ 4, 5 ] } ], "truncated": false }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "path": "src/server-api.ts", + "name": "server-api.ts", + "kind": "file", + "score": 0.9, + "match_positions": [ 4, 5 ] + } + ], + "truncated": false + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/fs:browse` 列出某个本机目录的子目录——文件夹选择器的后端。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `path` | string | 绝对目录路径。默认用户主目录 | -**返回**:`ResponseType<`[T-FsBrowseResponse](#t-fsbrowseresponse)`>`。 +**响应体**:`ResponseType<`[T-FsBrowseResponse](#t-fsbrowseresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsBrowseResponse](#t-fsbrowseresponse) | 目录列表;字段见类型汇总 | -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(`path` 不是绝对路径)、`40409`、`40411`(权限不足)。 +**非零 code**:`40001`(`path` 不是绝对路径;`details` 为 `{ path, message }[]`)、`40409`、`40411`(权限不足)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "/Users/dev", "parent": "/Users", "entries": [ { "name": "my-app", "path": "/Users/dev/my-app", "is_dir": true } ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "path": "/Users/dev", + "parent": "/Users", + "entries": [ { "name": "my-app", "path": "/Users/dev/my-app", "is_dir": true } ] + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/fs:home` 返回文件夹选择器的落地数据。无参数。 -**返回**:`ResponseType<`[T-FsHomeResponse](#t-fshomeresponse)`>`(`recent_roots` 上限 8)。 +**响应体**:`ResponseType<`[T-FsHomeResponse](#t-fshomeresponse)`>`(`recent_roots` 上限 8)。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FsHomeResponse](#t-fshomeresponse) | 主目录与最近工作区;字段见类型汇总 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "home": "/Users/dev", "recent_roots": [ "/Users/dev/my-app" ] }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "home": "/Users/dev", "recent_roots": [ "/Users/dev/my-app" ] }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/fs:content` -以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 [二进制与流式端点](#二进制与流式端点)。 +以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。响应为二进制流,支持 Range 请求与 ETag 缓存,不返回 `ResponseType`;见 [二进制与流式端点](#二进制与流式端点)。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | @@ -4194,20 +4488,29 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `path` | string | 是 | 绝对目录路径 | -**返回**:`ResponseType<{ "path": string }>`。 +**响应体**:`ResponseType<{ path: string }>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `path` | string | 创建的目录路径 | -**示例**: +**非零 code**:`40001`(校验失败;`details` 为 `{ path, message }[]`)、`40409`(父路径不存在)、`40411`、`40919`(路径已存在)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "path": "/Users/dev/new-project" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "path": "/Users/dev/new-project" }, + "request_id": "01JZX4..." +} ``` **文件上传与媒体。** @@ -4225,7 +4528,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 以 `multipart/form-data` 上传文件,供后续引用(例如作为提示词附件)。 -**Body**(multipart): +**请求体**(multipart): | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | @@ -4233,19 +4536,34 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | `name` | string | 否 | 存储的显示名。默认上传文件名 | | `expires_in_sec` | number | 否 | 文件过期前的秒数(非负)。默认永不过期 | -**返回**:`ResponseType<`[T-FileMeta](#t-filemeta)`>`。 +**响应体**:`ResponseType<`[T-FileMeta](#t-filemeta)`>`。 -**非零 code**:`40001`(校验失败,`details` 为 `{ path, message }[]`)(multipart 未初始化或缺少 `file` 字段)。 +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-FileMeta](#t-filemeta) | 文件元信息;字段见类型汇总 | -**示例**: +**非零 code**:`40001`(multipart 未初始化或缺少 `file` 字段;`details` 为 `{ path, message }[]`)。 + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "id": "f_01JZX4...", "name": "screenshot.png", "media_type": "image/png", "size": 204800, "created_at": "2026-09-02T08:12:00.000Z" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "id": "f_01JZX4...", + "name": "screenshot.png", + "media_type": "image/png", + "size": 204800, + "created_at": "2026-09-02T08:12:00.000Z" + }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/files/{file_id}` -下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 +下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 `If-None-Match`,不返回 `ResponseType`;失败使用真实 HTTP 状态码——见 [二进制与流式端点](#二进制与流式端点)。 **非零 code**:`40407`(HTTP 404:没有该 id 的文件,包括已过期的)、`50001`(HTTP 500)。 @@ -4253,19 +4571,28 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 删除已上传的文件。无请求体。 -**返回**:`ResponseType<{ "deleted": true }>`。 +**响应体**:`ResponseType<{ deleted: true }>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `deleted` | boolean | 恒 `true` | **非零 code**:同下载——`40407`(HTTP 404)、`50001`(HTTP 500)。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "deleted": true }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "deleted": true }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/sessions/{session_id}/media/{file_id}` -按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里返回 `ResponseType` 的端点不同,会话或文件不存在时返回真正的 404 状态码且响应体仍为 `ResponseType`。 +按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range,不返回 `ResponseType`——共享约定见 [二进制与流式端点](#二进制与流式端点);与那里返回 `ResponseType` 的端点不同,会话或文件不存在时返回真正的 404 状态码且响应体仍为 `ResponseType`。 **非零 code**:`40401`(HTTP 404)、`40407`(HTTP 404)。 @@ -4275,14 +4602,14 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。当 `container.session_id` 指向本服务进程中存活的会话时,搜索改为直接扫描该会话的内存转录,响应的 `source` 字段(`index` 或 `live`)会报告本页结果由哪条路径提供。分页遵循 [`page_token`](#分页) 风格。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `query` | string | 是 | 搜索文本 | | `mode` | string | 否 | `terms`(默认)/ `literal`(零误报的精确子串搜索) | | `op` | string | 否 | `terms` 模式下的词项组合符:`AND`(默认)/ `OR` | -| `container` | object | 否 | 将搜索限定在 `{ session_id?, agent_id? }` | +| `container` | `{ session_id?: string, agent_id?: string }` | 否 | 将搜索限定在该容器内 | | `role` | string | 否 | 限定 `user` / `assistant` / `title` 命中 | | `start_time` | integer | 否 | 只看不早于该时间的命中(epoch 毫秒) | | `end_time` | integer | 否 | 只看不晚于该时间的命中(epoch 毫秒) | @@ -4292,14 +4619,40 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 `terms` 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引。 -**返回**:`ResponseType<`[T-SearchResponse](#t-searchresponse)`>`。 +**响应体**:`ResponseType<`[T-SearchResponse](#t-searchresponse)`>`。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | [T-SearchResponse](#t-searchresponse) | 一页命中与索引状态;字段见类型汇总 | **非零 code**:`40001`(校验失败、查询为空或超过 32 个词项、分页令牌非法;`details` 为 `{ path, message }[]`)、`50001`。 -**示例**: +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "items": [ { "session_id": "session_01JZX4...", "workspace_id": "wd_my-app_a1b2c3d4e5f6", "session_title": "Fix the login page", "agent_id": "main", "role": "user", "snippet": "...adjust the button spacing...", "time": 1787000000000, "turn": 3, "score": 2.31 } ], "has_more": false, "index_state": { "state": "ready", "indexed_sessions": 12, "total_sessions": 12, "documents": 340 }, "source": "index" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { + "items": [ + { + "session_id": "session_01JZX4...", + "workspace_id": "wd_my-app_a1b2c3d4e5f6", + "session_title": "Fix the login page", + "agent_id": "main", + "role": "user", + "snippet": "...adjust the button spacing...", + "time": 1787000000000, + "turn": 3, + "score": 2.31 + } + ], + "has_more": false, + "index_state": { "state": "ready", "indexed_sessions": 12, "total_sessions": 12, "documents": 340 }, + "source": "index" + }, + "request_id": "01JZX4..." +} ``` **GUI 存储。** @@ -4320,79 +4673,124 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 返回已存键的数量(对齐 `localStorage.length`)。无参数。 -**返回**:`ResponseType<{ "length": number }>`。 +**响应体**:`ResponseType<{ length: number }>`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `length` | number | 已存键的数量 | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "length": 3 }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "length": 3 }, + "request_id": "01JZX4..." +} ``` #### `GET /api/v1/gui/store/getItem` 读取一个值(对齐 `localStorage.getItem`)。 -**Query**: +**查询参数**: | 参数 | 类型 | 说明 | | --- | --- | --- | | `key` | string | **必填。** 要读取的键,1–256 个字符 | -**返回**:`ResponseType<{ "value": string | null }>`——键不存在时为 `null`。 +**响应体**:`ResponseType<{ value: string | null }>`——键不存在时为 `null`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `value` | string `| null` | 存储的值;键不存在时为 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": { "value": "{ \"sidebar\": \"collapsed\" }" }, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": { "value": "{ \"sidebar\": \"collapsed\" }" }, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/gui/store/setItem` 写入一个值(对齐 `localStorage.setItem`)。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `key` | string | 是 | 要写入的键,1–256 个字符 | | `value` | string | 是 | 要存储的值 | -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/gui/store/removeItem` 删除一个值(对齐 `localStorage.removeItem`)。 -**Body**: +**请求体**: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `key` | string | 是 | 要删除的键,1–256 个字符 | -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` #### `POST /api/v1/gui/store/clear` 删除所有已存值(对齐 `localStorage.clear`)。无请求体。 -**返回**:`ResponseType`。 +**响应体**:`ResponseType`。 -**示例**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `data` | null | 恒 `null` | + +**响应示例**: ```json -{ "code": 0, "msg": "success", "data": null, "request_id": "01JZX4..." } +{ + "code": 0, + "msg": "success", + "data": null, + "request_id": "01JZX4..." +} ``` ## WebSocket 帧 From c8db35901c9b0585b067188957b3ac223a551848 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:03:47 +0800 Subject: [PATCH 36/47] docs(zh): promote transcript family members to headings and state the providers action response envelope --- docs/zh/reference/server-api.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 03dd89854b5..92254528202 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -548,6 +548,8 @@ HTTP 状态码例外(非 200): **触发事件**:`:refresh` / `:refresh_oauth` → `event.model_catalog.changed`(至少一个供应商的别名发生变化时;配置写入同时触发 `event.config.changed`);`:import_catalog` / `:import_registry` → `event.config.changed` +**响应体**:统一 `ResponseType` 信封,`data` 形态随动作(见下表)。 + | 动作 | 请求体 | `data`(code = 0) | HTTP 状态 | | --- | --- | --- | --- | | `:refresh` | 可选,被忽略 | [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)(刷新每个供应商) | 200 | @@ -6279,7 +6281,7 @@ type KimiError = { 转录载荷的类型正本是共享包 `@moonshot-ai/transcript` 的契约(客户端经同一依赖消费),`TranscriptItem` / `TranscriptOperation` 等嵌套类型均定义于该包。 -**T-TranscriptResponse**: +#### T-TranscriptResponse ```ts type TranscriptResponse = { @@ -6298,7 +6300,7 @@ type TranscriptResponse = { }; ``` -**T-TranscriptOpsCatchupResponse**: +#### T-TranscriptOpsCatchupResponse ```ts type TranscriptOpsCatchupResponse = { @@ -6311,7 +6313,7 @@ type TranscriptOpsCatchupResponse = { `TranscriptOperation` 全集(判别字段为 `op`):reset / turn.upsert / step.upsert / frame.upsert / append / marker.upsert / taskref.upsert / task.upsert / interaction.upsert / attachment.upsert / todo.upsert / prompt.upsert / meta.merge / items.remove。 -**T-TranscriptUserMessagesResponse**: +#### T-TranscriptUserMessagesResponse ```ts type TranscriptUserMessagesResponse = { @@ -6331,7 +6333,7 @@ type TranscriptUserMessagesResponse = { }; ``` -**T-TranscriptPlanResponse**: +#### T-TranscriptPlanResponse ```ts type TranscriptPlanResponse = { From 34e150ea1a25dfa6a6e5ddddbfcbab9002218c68 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:05:07 +0800 Subject: [PATCH 37/47] docs(zh): escape pipes inside table cells --- docs/zh/reference/server-api.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 92254528202..2d320a203fc 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -751,7 +751,7 @@ HTTP 状态码例外(非 200): | 字段 | 类型 | 说明 | | --- | --- | --- | -| `data` | [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) `| null` | 流程状态快照;未发起过流程时为 `null` | +| `data` | [T-OAuthFlowSnapshot](#t-oauthflowsnapshot) \| null | 流程状态快照;未发起过流程时为 `null` | **响应示例**: @@ -1597,7 +1597,7 @@ main agent 的实时状态汇总;读取它会在会话为冷态时将其恢复 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `data` | [T-GoalSnapshot](#t-goalsnapshot) `| null` | 目标快照(camelCase);无活跃目标时为 `null` | +| `data` | [T-GoalSnapshot](#t-goalsnapshot) \| null | 目标快照(camelCase);无活跃目标时为 `null` | **非零 code**:`40401`。 @@ -1998,7 +1998,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `active` | [T-PromptItem](#t-promptitem) `| null` | 运行中的提示词,空闲时为 `null` | +| `active` | [T-PromptItem](#t-promptitem) \| null | 运行中的提示词,空闲时为 `null` | | `queued` | [T-PromptItem](#t-promptitem)`[]` | 等待中的提示词,按顺序 | **非零 code**:`40401`。 @@ -4706,7 +4706,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | 字段 | 类型 | 说明 | | --- | --- | --- | -| `value` | string `| null` | 存储的值;键不存在时为 `null` | +| `value` | string \| null | 存储的值;键不存在时为 `null` | **响应示例**: From 8920f8b0c41cec222e9224c43d48a06917ca8001 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:46:28 +0800 Subject: [PATCH 38/47] docs(zh): add a format sample for the WebSocket frame chapter --- docs/zh/reference/server-api.md | 192 ++++++++++++++++++++++++++++++-- 1 file changed, 183 insertions(+), 9 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 2d320a203fc..124081bf079 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4797,20 +4797,194 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 ## WebSocket 帧 -事件流端点为 `/api/v1/ws`。服务端到客户端的帧分五路: +事件流端点为 `/api/v1/ws`,鉴权见 [基础约定](#鉴权)。帧为双向 JSON 消息:下行(服务端→客户端)分控制帧、event.\* 事件帧、agent 事件帧、transcript 帧四路;上行(客户端→服务端)只有控制帧。 -| 路由 | type 值 | 说明 | -| --- | --- | --- | -| 控制帧 | `server_hello` / `ping` / `ack` / `resync_required`(`error` 已声明但从不产出) | 连接管理,见 [控制帧](#控制帧) | -| 事件帧 | `event.*` 协议事件与裸 agent 事件 | 共享事件信封,见 [事件信封](#事件信封)、[event.\* 协议事件](#event-协议事件)、[agent 事件](#agent-事件) | -| transcript 帧 | `transcript.reset` / `transcript.ops` | 结构化转录流,见 [transcript 帧](#transcript-帧) | -| terminal 帧 | `terminal_output` / `terminal_exit` | 死协议,见 [terminal 帧](#terminal-帧) | +### 帧总览 + +```ts +// 服务端 → 客户端 +type ServerFrame = + | ControlFrame // server_hello | ack | ping | resync_required(error 为死声明) + | EventFrame // event.* 19 型 + | AgentEventFrame // agent 事件 51 型 + | TranscriptFrame; // transcript.reset | transcript.ops + +// 客户端 → 服务端 +type ClientFrame = + | ClientHello + | Subscribe + | Unsubscribe + | SubscribeV2 + | UnsubscribeV2 + | WatchFsAdd + | WatchFsRemove + | Pong; +// 死声明(服务端不处理、静默丢弃):abort、terminal_attach、terminal_detach、 +// terminal_input、terminal_resize、terminal_close +``` + +| 分类 | 方向 | 帧数 | 用途 | +| --- | --- | --- | --- | +| [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | 握手、订阅、心跳与恢复 | +| [event.\* 事件帧](#event-协议事件) | S→C | 19 | 工作区 / 会话 / 配置等状态同步 | +| [agent 事件帧](#agent-事件) | S→C | 51 | 轮次生命周期、状态与 subagent 内容 | +| [transcript 帧](#transcript-帧) | S→C | 2 | 主会话内容的结构化流(新实现) | +| [terminal 帧](#terminal-帧) | S→C | 2 | 死协议 | + +事件帧共享外层信封 `EventEnvelope`;`payload` 为各事件自己的载荷: + +```ts +type EventEnvelope = { + type: string; // 与 payload 内事件 type 重复一次 + seq: number; // 语义随产出形态,见下表 + epoch?: string; + volatile?: true; + offset?: number; // 仅主 agent 的 assistant.delta / thinking.delta 携带 + session_id?: string; + timestamp: string; // ISO 8601 + payload: object; +}; +``` -入站(客户端→服务端)控制帧按到达顺序串行处理;未知 `type` 被静默忽略。出站事件先进批量队列(16 毫秒或 64 条 flush,1 MB 高水位背压);相邻同轮次的 `assistant.delta` / `thinking.delta` 帧在 flush 时会合并 `delta` 字符串——客户端不能把 delta 帧当不可变日志。 +| 形态 | `seq` | `epoch` | `volatile` | `offset` | +| --- | --- | --- | --- | --- | +| durable | journal 递增,落日志可回放 | 有 | — | — | +| volatile | 当前 journal seq(不递增),不落日志不回放 | 有 | `true` | delta 帧携带 | +| transcript | 外层为当前 journal seq;transcript seq 在 `payload.seq` | 有 | `true` | — | +| `event.fs.changed` | watch 作用域自增(与 journal 无关) | 无 | — | — | + +volatile 类型全集:`assistant.delta` / `thinking.delta` / `tool.call.delta` / `tool.progress` / `shell.started` / `shell.output` / `shell.completed` / `agent.status.updated` / `event.di.unit_changed` / `event.capability.changed`;transcript 两型恒 volatile。 ### 控制帧 -客户端发送 JSON 帧 `{ "type", "id"?, "payload" }`;每个带 `id` 的入站帧都会收到一个 `ack` 应答。 +握手与保活:连接建立后服务端立即发 `server_hello`;客户端回 `client_hello`(可带初始订阅与断线游标),再按需发订阅帧;每个带 `id` 的入站帧收到一个 `ack`。服务端每 `heartbeat_ms`(默认 10000)发 `ping`,客户端回 `pong`;连续两个周期无任何入站帧,服务端以 `close(1001, "heartbeat timeout")` 断连。 + +#### `server_hello`(S→C) + +连接建立后服务端立即发送的首帧,不等任何入站。 + +```ts +{ + type: 'server_hello'; + timestamp: string; // ISO 8601 + payload: { + ws_connection_id: string; // conn_ + protocol_version: 2; + heartbeat_ms: number; // 默认 10000 + max_event_buffer_size: number; // 默认 1000 + capabilities: { event_batching: boolean; compression: boolean }; + }; +} +``` + +**帧示例**: + +```json +{ + "type": "server_hello", + "timestamp": "2026-09-02T08:00:00.000Z", + "payload": { + "ws_connection_id": "conn_01JZX4...", + "protocol_version": 2, + "heartbeat_ms": 10000, + "max_event_buffer_size": 1000, + "capabilities": { "event_batching": false, "compression": false } + } +} +``` + +#### `client_hello`(C→S → ack) + +声明客户端身份;可一次性携带初始订阅与断线游标。`payload.token` 是冗余第二鉴权通道——upgrade 已鉴权时可缺省;校验失败回 `ack` code `40112` 并关闭连接。 + +```ts +{ + type: 'client_hello'; + id?: string; // 回显进 ack + payload: { + client_id: string; // kimi-inspect 时本连接加入 DI 事件目标集 + subscriptions?: string[]; // 建连即订阅的 session id + cursors?: Record; // 逐会话事件续传水位 + agent_filter?: Record; // 逐会话 agent 过滤 + token?: string; // wire schema 未声明但服务端实际读取 + }; +} +``` + +ack payload:`{ accepted_subscriptions: string[], resync_required: string[], cursors: Record }`。 + +#### `subscribe`(C→S → ack) + +订阅会话事件;带 `cursors` 时服务端先回放缺口再回 ack(回放完成以该 ack 为信号)。 + +```ts +{ + type: 'subscribe'; + id?: string; + payload: { + session_ids: string[]; + cursors?: Record; + agent_filter?: Record; + watch_fs?: Record; // schema 声明,服务端当前不读 + }; +} +``` + +ack payload:`{ accepted: string[], not_found: string[], resync_required: string[], cursors: Record }`。 + +### event.\* 事件帧 + +(以下为格式样例,19 型全量待写入) + +#### `event.workspace.created`(S→C) + +新工作区注册时广播。投递范围:全局(所有连接)。durable。 + +```ts +{ + type: 'event.workspace.created'; + payload: { + sessionId: '__global__'; + agentId: 'main'; + workspace: { + id: string; + root: string; + name: string; + createdAt: string; // ISO 8601;camelCase,与 REST T-Workspace 的 snake_case 不同 + lastOpenedAt: string; // ISO 8601 + }; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +### agent 事件帧 + +(以下为格式样例,51 型全量待写入) + +#### `assistant.delta`(S→C) + +流式文本增量。投递范围:会话订阅。volatile;相邻同轮次帧 flush 时可能被服务端合并(合并保留首帧 `offset`),客户端不能把 delta 帧当不可变日志。主会话内容渲染走 [transcript 帧](#transcript-帧);本帧仍承载 subagent 内容(subagent 的 delta 不带 `offset`)。 + +```ts +{ + type: 'assistant.delta'; + offset?: number; // 该轮次内累计文本长度,仅主 agent 携带 + payload: { + turnId: number; + delta: string; + agentId: string; + sessionId: string; + }; +} +``` + +--- + +(以下为旧格式内容,待全量按新格式替换后删除) + +### 控制帧(旧格式,待替换) #### server_hello(服务端→客户端) From 1b180e2e966027c0fa87fc3ead394b8a679e3f6d Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:53:44 +0800 Subject: [PATCH 39/47] docs(zh): use the server's own union names in the WS frame overview --- docs/zh/reference/server-api.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 124081bf079..c11a49171a3 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4804,12 +4804,13 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 ```ts // 服务端 → 客户端 type ServerFrame = - | ControlFrame // server_hello | ack | ping | resync_required(error 为死声明) + | ServerSystemMessage // server_hello | ping | resync_required | error(死声明) + | Ack // 每个带 id 入站帧的应答 | EventFrame // event.* 19 型 | AgentEventFrame // agent 事件 51 型 | TranscriptFrame; // transcript.reset | transcript.ops -// 客户端 → 服务端 +// 客户端 → 服务端(服务端正名 ClientControlMessage) type ClientFrame = | ClientHello | Subscribe @@ -4823,6 +4824,8 @@ type ClientFrame = // terminal_input、terminal_resize、terminal_close ``` +命名对照:`ServerSystemMessage` 与 `ClientControlMessage` 是服务端 protocol 层的正名 union(`protocol/ws-control.ts`),`AgentEvent` 为 agent 事件的系统正名(`transport/ws/v1/events.ts`);`ServerFrame` / `ClientFrame` / `EventFrame` / `AgentEventFrame` / `TranscriptFrame` 是文档总览用的汇总名(transcript 帧的 payload 契约由 `@moonshot-ai/transcript` 持有)。注意 `ack` 不在 `ServerSystemMessage` 内——服务端把 ack 当应答帧独立处理。 + | 分类 | 方向 | 帧数 | 用途 | | --- | --- | --- | --- | | [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | 握手、订阅、心跳与恢复 | From 3ff1d7fea0966001a10d36e63d951cbcf3db7dd2 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 19:59:52 +0800 Subject: [PATCH 40/47] docs(zh): use only real system type names in the WS frame overview --- docs/zh/reference/server-api.md | 63 +++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index c11a49171a3..cd2c4d83776 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4803,28 +4803,47 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 ```ts // 服务端 → 客户端 -type ServerFrame = - | ServerSystemMessage // server_hello | ping | resync_required | error(死声明) - | Ack // 每个带 id 入站帧的应答 - | EventFrame // event.* 19 型 - | AgentEventFrame // agent 事件 51 型 - | TranscriptFrame; // transcript.reset | transcript.ops - -// 客户端 → 服务端(服务端正名 ClientControlMessage) -type ClientFrame = - | ClientHello - | Subscribe - | Unsubscribe - | SubscribeV2 - | UnsubscribeV2 - | WatchFsAdd - | WatchFsRemove - | Pong; -// 死声明(服务端不处理、静默丢弃):abort、terminal_attach、terminal_detach、 -// terminal_input、terminal_resize、terminal_close -``` - -命名对照:`ServerSystemMessage` 与 `ClientControlMessage` 是服务端 protocol 层的正名 union(`protocol/ws-control.ts`),`AgentEvent` 为 agent 事件的系统正名(`transport/ws/v1/events.ts`);`ServerFrame` / `ClientFrame` / `EventFrame` / `AgentEventFrame` / `TranscriptFrame` 是文档总览用的汇总名(transcript 帧的 payload 契约由 `@moonshot-ai/transcript` 持有)。注意 `ack` 不在 `ServerSystemMessage` 内——服务端把 ack 当应答帧独立处理。 + +// 控制帧(正名 union) +type ServerSystemMessage = + | ServerHelloMessage + | PingMessage + | ResyncRequiredMessage + | WsErrorMessage; // 死声明,无产出 +// ack 应答帧:wsAckEnvelope 按请求一一对应 +// (ClientHelloAckMessage / SubscribeAckMessage / SubscribeV2AckMessage / …) + +// event.* 协议事件(19 型,无 union) +SessionCreatedEvent | SessionArchivedEvent | SessionWorkChangedEvent | SessionStatusChangedEvent +| WorkspaceCreatedEvent | WorkspaceUpdatedEvent | WorkspaceDeletedEvent +| ConfigChangedEvent | ConfigWarningEvent +| ModelCatalogChangedEvent | PluginChangedEvent | CapabilityChangedEvent | DiUnitChangedEvent +// 以下 6 型系统内未命名(broadcaster 内联构造): +// event.question.requested / answered / dismissed、event.approval.requested / resolved、event.fs.changed + +// agent 事件(正名 union,51 型) +type AgentEvent = TurnStartedEvent | AssistantDeltaEvent | …; +// wire 上的形态:Event = AgentEvent & { agentId, sessionId, time? } + +// transcript 帧(正名) +TranscriptResetEvent | TranscriptOpsEvent + +// 客户端 → 服务端(正名 union) +type ClientControlMessage = + | ClientHelloMessage + | SubscribeMessage + | SubscribeV2Message + | UnsubscribeMessage + | UnsubscribeV2Message + | WatchFsAddMessage + | WatchFsRemoveMessage + | PongMessage; +// 死声明(服务端不处理、静默丢弃): +// AbortMessage、TerminalAttachMessage、TerminalDetachMessage、 +// TerminalInputMessage、TerminalResizeMessage、TerminalCloseMessage +``` + +命名一律取系统正名:`ServerSystemMessage` / `ClientControlMessage` / `AgentEvent` / `Event`(kap-server `protocol/ws-control.ts`、`transport/ws/v1/events.ts`),`TranscriptResetEvent` / `TranscriptOpsEvent`(`@moonshot-ai/transcript` 契约)。注意 `ack` 不在 `ServerSystemMessage` 内——服务端把 ack 当应答帧独立处理;`event.question.*` / `event.approval.*` / `event.fs.changed` 在系统内没有命名类型,本文以 `type` 字符串指代。 | 分类 | 方向 | 帧数 | 用途 | | --- | --- | --- | --- | From 4bbdd85466c730a4aa2c1347bde673f67f4b9f1e Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:02:34 +0800 Subject: [PATCH 41/47] docs(zh): move the frame unions from the overview into their own sections --- docs/zh/reference/server-api.md | 85 +++++++++++++++------------------ 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index cd2c4d83776..08f6b276c62 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4801,57 +4801,17 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 ### 帧总览 -```ts -// 服务端 → 客户端 - -// 控制帧(正名 union) -type ServerSystemMessage = - | ServerHelloMessage - | PingMessage - | ResyncRequiredMessage - | WsErrorMessage; // 死声明,无产出 -// ack 应答帧:wsAckEnvelope 按请求一一对应 -// (ClientHelloAckMessage / SubscribeAckMessage / SubscribeV2AckMessage / …) -// event.* 协议事件(19 型,无 union) -SessionCreatedEvent | SessionArchivedEvent | SessionWorkChangedEvent | SessionStatusChangedEvent -| WorkspaceCreatedEvent | WorkspaceUpdatedEvent | WorkspaceDeletedEvent -| ConfigChangedEvent | ConfigWarningEvent -| ModelCatalogChangedEvent | PluginChangedEvent | CapabilityChangedEvent | DiUnitChangedEvent -// 以下 6 型系统内未命名(broadcaster 内联构造): -// event.question.requested / answered / dismissed、event.approval.requested / resolved、event.fs.changed -// agent 事件(正名 union,51 型) -type AgentEvent = TurnStartedEvent | AssistantDeltaEvent | …; -// wire 上的形态:Event = AgentEvent & { agentId, sessionId, time? } - -// transcript 帧(正名) -TranscriptResetEvent | TranscriptOpsEvent - -// 客户端 → 服务端(正名 union) -type ClientControlMessage = - | ClientHelloMessage - | SubscribeMessage - | SubscribeV2Message - | UnsubscribeMessage - | UnsubscribeV2Message - | WatchFsAddMessage - | WatchFsRemoveMessage - | PongMessage; -// 死声明(服务端不处理、静默丢弃): -// AbortMessage、TerminalAttachMessage、TerminalDetachMessage、 -// TerminalInputMessage、TerminalResizeMessage、TerminalCloseMessage -``` -命名一律取系统正名:`ServerSystemMessage` / `ClientControlMessage` / `AgentEvent` / `Event`(kap-server `protocol/ws-control.ts`、`transport/ws/v1/events.ts`),`TranscriptResetEvent` / `TranscriptOpsEvent`(`@moonshot-ai/transcript` 契约)。注意 `ack` 不在 `ServerSystemMessage` 内——服务端把 ack 当应答帧独立处理;`event.question.*` / `event.approval.*` / `event.fs.changed` 在系统内没有命名类型,本文以 `type` 字符串指代。 -| 分类 | 方向 | 帧数 | 用途 | -| --- | --- | --- | --- | -| [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | 握手、订阅、心跳与恢复 | -| [event.\* 事件帧](#event-协议事件) | S→C | 19 | 工作区 / 会话 / 配置等状态同步 | -| [agent 事件帧](#agent-事件) | S→C | 51 | 轮次生命周期、状态与 subagent 内容 | -| [transcript 帧](#transcript-帧) | S→C | 2 | 主会话内容的结构化流(新实现) | -| [terminal 帧](#terminal-帧) | S→C | 2 | 死协议 | +| 分类 | 方向 | 帧数 | 类型正名 | 用途 | +| --- | --- | --- | --- | --- | +| [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | `ServerSystemMessage`(下行)/ `ClientControlMessage`(上行) | 握手、订阅、心跳与恢复 | +| [event.\* 事件帧](#event-协议事件) | S→C | 19 | 13 型有接口正名,6 型未命名 | 工作区 / 会话 / 配置等状态同步 | +| [agent 事件帧](#agent-事件) | S→C | 51 | `AgentEvent` | 轮次生命周期、状态与 subagent 内容 | +| [transcript 帧](#transcript-帧) | S→C | 2 | `TranscriptResetEvent` / `TranscriptOpsEvent` | 主会话内容的结构化流(新实现) | +| [terminal 帧](#terminal-帧) | S→C | 2 | — | 死协议 | 事件帧共享外层信封 `EventEnvelope`;`payload` 为各事件自己的载荷: @@ -4881,6 +4841,33 @@ volatile 类型全集:`assistant.delta` / `thinking.delta` / `tool.call.delta` 握手与保活:连接建立后服务端立即发 `server_hello`;客户端回 `client_hello`(可带初始订阅与断线游标),再按需发订阅帧;每个带 `id` 的入站帧收到一个 `ack`。服务端每 `heartbeat_ms`(默认 10000)发 `ping`,客户端回 `pong`;连续两个周期无任何入站帧,服务端以 `close(1001, "heartbeat timeout")` 断连。 +下行控制帧的正名 union(ack 不在内——每个带 `id` 入站帧的应答帧按请求一一对应,如 `ClientHelloAckMessage` / `SubscribeAckMessage`): + +```ts +type ServerSystemMessage = + | ServerHelloMessage + | PingMessage + | ResyncRequiredMessage + | WsErrorMessage; // 死声明,无产出 +``` + +上行控制帧的正名 union: + +```ts +type ClientControlMessage = + | ClientHelloMessage + | SubscribeMessage + | SubscribeV2Message + | UnsubscribeMessage + | UnsubscribeV2Message + | WatchFsAddMessage + | WatchFsRemoveMessage + | PongMessage; +// 死声明(服务端不处理、静默丢弃): +// AbortMessage、TerminalAttachMessage、TerminalDetachMessage、 +// TerminalInputMessage、TerminalResizeMessage、TerminalCloseMessage +``` + #### `server_hello`(S→C) 连接建立后服务端立即发送的首帧,不等任何入站。 @@ -4956,6 +4943,8 @@ ack payload:`{ accepted: string[], not_found: string[], resync_required: strin ### event.\* 事件帧 +19 型,系统内无 union。13 型有接口正名:`SessionCreatedEvent` / `SessionArchivedEvent` / `SessionWorkChangedEvent` / `SessionStatusChangedEvent` / `WorkspaceCreatedEvent` / `WorkspaceUpdatedEvent` / `WorkspaceDeletedEvent` / `ConfigChangedEvent` / `ConfigWarningEvent` / `ModelCatalogChangedEvent` / `PluginChangedEvent` / `CapabilityChangedEvent` / `DiUnitChangedEvent`;6 型未命名(broadcaster 内联构造,以 `type` 字符串指代):`event.question.requested` / `event.question.answered` / `event.question.dismissed` / `event.approval.requested` / `event.approval.resolved` / `event.fs.changed`。 + (以下为格式样例,19 型全量待写入) #### `event.workspace.created`(S→C) @@ -4983,6 +4972,8 @@ ack payload:`{ accepted: string[], not_found: string[], resync_required: strin ### agent 事件帧 +51 型,正名 union 为 `AgentEvent`(`transport/ws/v1/events.ts`);wire 上的形态为 `Event = AgentEvent & { agentId, sessionId, time? }`(广播器补全 `agentId` / `sessionId`)。主会话内容渲染走 [transcript 帧](#transcript-帧);本流承载状态 / 生命周期与 subagent 内容。 + (以下为格式样例,51 型全量待写入) #### `assistant.delta`(S→C) From 8047b759307679bd618ef7f38969bd05d871dd2d Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:16:20 +0800 Subject: [PATCH 42/47] docs(zh): complete the control frame entries in the server API reference --- docs/zh/reference/server-api.md | 160 ++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 08f6b276c62..1015eddf0d0 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4941,6 +4941,166 @@ ack payload:`{ accepted_subscriptions: string[], resync_required: string[], cu ack payload:`{ accepted: string[], not_found: string[], resync_required: string[], cursors: Record }`。 +#### `unsubscribe`(C→S → ack) + +逐会话退订(含该会话 transcript 订阅状态的清理)。 + +```ts +{ + type: 'unsubscribe'; + id?: string; + payload: { + session_ids: string[]; + }; +} +``` + +ack payload:`{ accepted: [], not_found: [], resync_required: [] }`——三个数组恒空,不回报实际退订结果。 + +#### `subscribe_v2`(C→S → ack) + +订阅 transcript 流(粒度订阅,见 [transcript 帧](#transcript-帧))。只携带 transcript 续传水位,事件续传游标走 `subscribe`。payload 经 zod 校验,失败回 `ack` code `1`。 + +```ts +{ + type: 'subscribe_v2'; + id?: string; + payload: { + session_id: string; // 单会话 + transcript: Record; // 逐 agent 粒度,'*' 为通配档 + transcript_since?: Record; // 逐 agent 的 transcript seq 续传水位 + }; +} +``` + +ack payload:同 `subscribe`(`accepted` / `not_found` / `resync_required` / `cursors`)。 + +#### `unsubscribe_v2`(C→S → ack) + +退订 transcript 流。payload 经 zod 校验,失败回 `ack` code `1`。 + +```ts +{ + type: 'unsubscribe_v2'; + id?: string; + payload: { + session_id: string; + agent_ids?: string[]; // 缺省 = 摘掉该会话全部 transcript 订阅;给定 = 这些 agent 置 'off' + }; +} +``` + +ack payload:`{ accepted: [session_id], not_found: [], resync_required: [] }`——无 `cursors` 键。 + +#### `watch_fs_add`(C→S → ack) + +为会话登记文件监听,变更经 [`event.fs.changed`](#event-fs-changed-s→c) 送达。 + +```ts +{ + type: 'watch_fs_add'; + id?: string; + payload: { + session_id: string; + paths: string[]; // 相对工作区根;''、'/'、绝对路径、含 '..' 段均被拒 + runtime_id?: string; // 缺省 'local' + recursive?: boolean; // schema 声明,服务端当前不读 + }; +} +``` + +ack payload:`{ watched_paths: string[], current_count: number }`(本连接当前监听的路径与总数);watch bridge 缺失或内部异常时 code `1`。 + +#### `watch_fs_remove`(C→S → ack) + +移除文件监听。 + +```ts +{ + type: 'watch_fs_remove'; + id?: string; + payload: { + session_id: string; + paths: string[]; + runtime_id?: string; + }; +} +``` + +ack payload:同 `watch_fs_add`。 + +#### `ack`(S→C) + +每个带 `id` 的入站控制帧一个应答(`pong` 除外)。 + +```ts +{ + type: 'ack'; + id: string; // 回显入站帧 id;入站缺 id 时为 '' + code: number; // 0 成功;1 参数或内部错误;40112 鉴权失败 + msg: string; // 'success' 或错误描述 + payload: object; // 按请求帧定形,见各入站帧条目 +} +``` + +#### `ping`(S→C) + +心跳帧,每 `heartbeat_ms`(默认 10000)一个。 + +```ts +{ + type: 'ping'; + timestamp: string; // ISO 8601 + payload: { nonce: string }; +} +``` + +#### `pong`(C→S) + +心跳应答,服务端不回 `ack`。任何合法入站帧(含未知 `type`)都会重置心跳计时。 + +```ts +{ + type: 'pong'; + payload: { nonce: string }; +} +``` + +#### `resync_required`(S→C) + +带游标订阅的回放无法覆盖缺口时下发:会话已重建(`session_recreated`)、游标 epoch 不符或游标超前于当前水位(`epoch_changed`)、缺口超出事件缓冲容量(`buffer_overflow`)。发送后该会话同时列入对应 `ack` 的 `resync_required` 数组;游标等于当前水位(空回放)不触发。 + +```ts +{ + type: 'resync_required'; + timestamp: string; // ISO 8601 + payload: { + session_id: string; + reason: 'buffer_overflow' | 'session_recreated' | 'epoch_changed'; + current_seq: number; // 服务端当前 journal seq + epoch?: string; + }; +} +``` + +#### `error`(S→C,死声明) + +schema 声明的控制帧形态错误帧,服务端无任何产出点。事件流中出现的 `type: 'error'` 帧均为裸 agent [`error`](#error-s→c) 事件(带 `session_id` / `seq` 信封,见 [agent 事件帧](#agent-事件帧)),客户端按有无 `session_id` 分流。 + +```ts +{ + type: 'error'; + timestamp: string; + payload: { + code: number; + msg: string; + fatal: boolean; + request_id?: string; + details?: unknown; + }; +} +``` + ### event.\* 事件帧 19 型,系统内无 union。13 型有接口正名:`SessionCreatedEvent` / `SessionArchivedEvent` / `SessionWorkChangedEvent` / `SessionStatusChangedEvent` / `WorkspaceCreatedEvent` / `WorkspaceUpdatedEvent` / `WorkspaceDeletedEvent` / `ConfigChangedEvent` / `ConfigWarningEvent` / `ModelCatalogChangedEvent` / `PluginChangedEvent` / `CapabilityChangedEvent` / `DiUnitChangedEvent`;6 型未命名(broadcaster 内联构造,以 `type` 字符串指代):`event.question.requested` / `event.question.answered` / `event.question.dismissed` / `event.approval.requested` / `event.approval.resolved` / `event.fs.changed`。 From 7d8dd0ed7eb13242013666f2ab56c80d03fe0b88 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:17:29 +0800 Subject: [PATCH 43/47] docs(zh): write out all 19 event.* frame entries --- docs/zh/reference/server-api.md | 396 +++++++++++++++++++++++++++++++- 1 file changed, 395 insertions(+), 1 deletion(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 1015eddf0d0..5ba9a800f69 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -5105,7 +5105,102 @@ schema 声明的控制帧形态错误帧,服务端无任何产出点。事件 19 型,系统内无 union。13 型有接口正名:`SessionCreatedEvent` / `SessionArchivedEvent` / `SessionWorkChangedEvent` / `SessionStatusChangedEvent` / `WorkspaceCreatedEvent` / `WorkspaceUpdatedEvent` / `WorkspaceDeletedEvent` / `ConfigChangedEvent` / `ConfigWarningEvent` / `ModelCatalogChangedEvent` / `PluginChangedEvent` / `CapabilityChangedEvent` / `DiUnitChangedEvent`;6 型未命名(broadcaster 内联构造,以 `type` 字符串指代):`event.question.requested` / `event.question.answered` / `event.question.dismissed` / `event.approval.requested` / `event.approval.resolved` / `event.fs.changed`。 -(以下为格式样例,19 型全量待写入) +投递范围分三类:**全局广播**(发往所有连接,含未订阅该会话的)——`event.session.*` / `event.workspace.*` / `event.config.*` / `event.model_catalog.*` / `event.plugin.*` / `event.capability.*`,另有 `event.di.*` 门控到仅以 `client_id: 'kimi-inspect'` 握手的连接;**会话订阅**(受 `agent_filter` 过滤)——`event.question.*` 与 `event.approval.*`;**监听命中**——`event.fs.changed` 只发往经 [`watch_fs_add`](#watch-fs-add-c→s-→-ack) 登记且路径命中的连接。journal 归属决定游标回放范围:`event.session.created` / `event.session.work_changed` 与 question / approval 交互事件落真实会话的 journal,其余全局事件落 `__global__` journal;信封 `session_id` 即 journal 归属(真实会话 id 或 `__global__`)。 + +广播器产出的 payload 统一补 `agentId` 与 `sessionId`(camelCase;全局事件为 `'main'` / `'__global__'`,交互事件为发起交互的 agent 与真实会话 id),与 payload 既有的 snake_case 字段混存;`event.fs.changed` 不经广播器,不补这两个字段。这些事件只覆盖本服务进程内的变更——其他进程(例如写同一 home 目录的 CLI)的变更要等索引 reconcile(约一分钟)才可见,概览客户端应保留低频兜底轮询;目前没有会话删除事件。 + +**会话。** + +#### `event.session.created`(S→C) + +新会话创建时广播(创建、fork、创建子会话都会发出);`session` 为 [T-Session](#t-session) 全量。投递范围:全局。durable,落该会话 journal。正名 `SessionCreatedEvent`。 + +```ts +{ + type: 'event.session.created'; + payload: { + session: T-Session; // 会话对象全量 + agentId: 'main'; + sessionId: string; // 真实会话 id + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.session.archived`(S→C) + +会话归档时广播(在线与冷归档两条路径都会发出)。投递范围:全局。durable,落 `__global__` journal。正名 `SessionArchivedEvent`。 + +```ts +{ + type: 'event.session.archived'; + payload: { + workspace_id: string; + agentId: 'main'; + sessionId: string; // camelCase,真实会话 id + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.session.work_changed`(S→C) + +会话工作聚合状态变化时广播;轮次结束起因的变化经 microtask 延后合流,保证终态先落地。投递范围:全局。durable,落该会话 journal。正名 `SessionWorkChangedEvent`。 + +```ts +{ + type: 'event.session.work_changed'; + payload: { + busy: boolean; + main_turn_active: boolean; // schema 标可缺省,产出恒带 + pending_interaction: 'none' | 'approval' | 'question'; // 同上 + last_turn_reason?: 'completed' | 'cancelled' | 'failed'; + agentId: 'main'; + sessionId: string; // 真实会话 id + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**帧示例**: + +```json +{ + "type": "event.session.work_changed", + "seq": 129, + "epoch": "01JZX4...", + "session_id": "session_01JZX4...", + "timestamp": "2026-09-02T08:06:00.000Z", + "payload": { + "type": "event.session.work_changed", + "busy": true, + "main_turn_active": true, + "pending_interaction": "none", + "agentId": "main", + "sessionId": "session_01JZX4..." + } +} +``` + +#### `event.session.status_changed`(S→C,无产出声明) + +schema 已声明但当前服务端无产出点;旧版本 journal 回放时可能出现。正名 `SessionStatusChangedEvent`。 + +```ts +{ + type: 'event.session.status_changed'; + payload: { + status: string; + previous_status: 'idle' | 'running' | 'awaiting_approval' | 'awaiting_question' | 'aborted'; + current_prompt_id?: string; + }; +} +``` + +**工作区。** #### `event.workspace.created`(S→C) @@ -5130,6 +5225,305 @@ schema 声明的控制帧形态错误帧,服务端无任何产出点。事件 外层为 durable 信封(见 [帧总览](#帧总览))。 +#### `event.workspace.updated`(S→C) + +工作区重命名、重新注册或会话创建触碰时广播。投递范围:全局。durable,落 `__global__` journal。正名 `WorkspaceUpdatedEvent`。 + +```ts +{ + type: 'event.workspace.updated'; + payload: { + sessionId: '__global__'; + agentId: 'main'; + workspace: { + id: string; + root: string; + name: string; + createdAt: string; // ISO 8601 + lastOpenedAt: string; // ISO 8601 + }; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.workspace.deleted`(S→C) + +工作区注销时广播。投递范围:全局。durable,落 `__global__` journal。正名 `WorkspaceDeletedEvent`。 + +```ts +{ + type: 'event.workspace.deleted'; + payload: { + workspace_id: string; + root: string; + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**配置。** + +#### `event.config.changed`(S→C) + +任何来源的配置变更,短时间窗内多次变更合并为一个事件;`config` 为 [T-ConfigResponse](#t-configresponse) 全量快照。投递范围:全局。durable,落 `__global__` journal。正名 `ConfigChangedEvent`。 + +```ts +{ + type: 'event.config.changed'; + payload: { + changedFields: string[]; // camelCase 域名 + config: T-ConfigResponse; // 全量配置快照 + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.config.warning`(S→C) + +配置告警。投递范围:全局。durable,落 `__global__` journal。正名 `ConfigWarningEvent`。 + +```ts +{ + type: 'event.config.warning'; + payload: { + warnings: { domain?: string; message: string }[]; + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**模型目录。** + +#### `event.model_catalog.changed`(S→C) + +至少一个供应商的模型别名变化时广播;`changed` / `unchanged` / `failed` 与 [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse) 同构。投递范围:全局。durable,落 `__global__` journal。正名 `ModelCatalogChangedEvent`。 + +```ts +{ + type: 'event.model_catalog.changed'; + payload: { + changed: { provider_id: string; provider_name: string; added: number; removed: number }[]; + unchanged: string[]; // provider id + failed: { provider: string; reason: string }[]; + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**插件。** + +#### `event.plugin.changed`(S→C) + +插件安装、启用、停用或移除时广播,无附加字段。投递范围:全局。durable,落 `__global__` journal。正名 `PluginChangedEvent`。 + +```ts +{ + type: 'event.plugin.changed'; + payload: { + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**能力。** + +#### `event.capability.changed`(S→C) + +能力安装进度。投递范围:全局。volatile(`seq` 不递增,不落 journal、不回放)。正名 `CapabilityChangedEvent`。 + +```ts +{ + type: 'event.capability.changed'; + payload: { + capability_id: string; + install: { + running: boolean; + step?: string; + percent?: number; + error?: string; + note?: string; + }; + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 volatile 信封(见 [帧总览](#帧总览))。 + +**DI。** + +#### `event.di.unit_changed`(S→C) + +DI unit 状态变化;`state` 取值同 meta `features[].state`,枚举非封闭。投递范围:仅以 `client_id: 'kimi-inspect'` 握手的连接。volatile。正名 `DiUnitChangedEvent`。 + +```ts +{ + type: 'event.di.unit_changed'; + payload: { + scope: string; + token: string; // DI token + state: 'Pending' | 'Activating' | 'Active' | 'Unloading' | 'Failed'; // PascalCase + error?: string; + agentId: 'main'; + sessionId: '__global__'; + }; +} +``` + +外层为 volatile 信封(见 [帧总览](#帧总览))。 + +**提问。** + +#### `event.question.requested`(S→C) + +agent 向用户发起的提问到达;payload 即 [T-QuestionRequest](#t-questionrequest) 全字段外加 `agentId` / `sessionId`。投递范围:会话订阅。durable,落该会话 journal。 + +```ts +{ + type: 'event.question.requested'; + payload: { + question_id: string; // 交互 id + session_id: string; + turn_id?: number; + tool_call_id?: string; + questions: QuestionItem[]; // 1–4 个,见 T-QuestionRequest + created_at: string; // ISO 8601 + agentId: string; // 发起交互的 agent(缺省 'main') + sessionId: string; // 真实会话 id + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.question.answered`(S→C) + +提问被应答。投递范围:会话订阅。durable,落该会话 journal。 + +```ts +{ + type: 'event.question.answered'; + payload: { + question_id: string; + answers: Record; // 拍平的文本 map,与 REST 的结构化 answers 形态不同 + resolved_at: string; // ISO 8601,服务端解决时刻 + agentId: string; + sessionId: string; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.question.dismissed`(S→C) + +提问被忽略。投递范围:会话订阅。durable,落该会话 journal。 + +```ts +{ + type: 'event.question.dismissed'; + payload: { + question_id: string; + dismissed_at: string; // ISO 8601 + agentId: string; + sessionId: string; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**审批。** + +#### `event.approval.requested`(S→C) + +工具调用等动作的审批请求到达;payload 即 [T-ApprovalRequest](#t-approvalrequest) 全字段外加 `agentId` / `sessionId`。投递范围:会话订阅。durable,落该会话 journal。 + +```ts +{ + type: 'event.approval.requested'; + payload: { + approval_id: string; // 交互 id + session_id: string; + turn_id?: number; + tool_call_id: string; // 缺省时回退为交互 id + tool_name: string; + action: string; + tool_input_display: ToolInputDisplay; + created_at: string; // ISO 8601 + expires_at: string; // ISO 8601,created_at 之后 24 小时 + agentId: string; // 发起交互的 agent + sessionId: string; // 真实会话 id + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +#### `event.approval.resolved`(S→C) + +审批被处理(无 `resolved_by` 字段)。投递范围:会话订阅。durable,落该会话 journal。 + +```ts +{ + type: 'event.approval.resolved'; + payload: { + approval_id: string; + decision?: string; + scope?: string; + feedback?: string; + selected_label?: string; + resolved_at: string; // ISO 8601 + agentId: string; + sessionId: string; + }; +} +``` + +外层为 durable 信封(见 [帧总览](#帧总览))。 + +**文件监听。** + +#### `event.fs.changed`(S→C) + +监听路径下的文件变更(按合并窗口合批)。投递范围:经 [`watch_fs_add`](#watch-fs-add-c→s-→-ack) 登记且路径命中的连接。信封特殊:无 `epoch`,`seq` 为监听作用域自增计数(每连接每会话独立,与 journal 无关、不可经游标回放);payload 不补 `agentId` / `sessionId`。 + +```ts +{ + type: 'event.fs.changed'; + payload: { + changes: { + path: string; + change: 'created' | 'modified' | 'deleted'; + kind: 'file' | 'directory' | 'symlink'; + size_delta?: number; + etag?: string; + }[]; // truncated 时为空数组 + coalesced_window_ms: number; // 合并窗口 + truncated?: true; // 溢出截断标记 + count?: number; // 截断时被丢弃的变更数 + }; +} +``` + ### agent 事件帧 51 型,正名 union 为 `AgentEvent`(`transport/ws/v1/events.ts`);wire 上的形态为 `Event = AgentEvent & { agentId, sessionId, time? }`(广播器补全 `agentId` / `sessionId`)。主会话内容渲染走 [transcript 帧](#transcript-帧);本流承载状态 / 生命周期与 subagent 内容。 From 396cbc9103823b4b81ae68a2f5984c663b702516 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:19:08 +0800 Subject: [PATCH 44/47] docs(zh): write out all 51 agent event frame entries --- docs/zh/reference/server-api.md | 983 +++++++++++++++++++++++++++++++- 1 file changed, 982 insertions(+), 1 deletion(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 5ba9a800f69..20a6e0d7b88 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -5528,7 +5528,268 @@ agent 向用户发起的提问到达;payload 即 [T-QuestionRequest](#t-questi 51 型,正名 union 为 `AgentEvent`(`transport/ws/v1/events.ts`);wire 上的形态为 `Event = AgentEvent & { agentId, sessionId, time? }`(广播器补全 `agentId` / `sessionId`)。主会话内容渲染走 [transcript 帧](#transcript-帧);本流承载状态 / 生命周期与 subagent 内容。 -(以下为格式样例,51 型全量待写入) +投递范围:会话订阅,受 `agent_filter` 过滤(`agent.created` / `agent.disposed` 生命周期事件对过滤器放行);例外为 [`session.meta.updated`](#session-meta-updated-s→c),全局投递。连接对某 agent 订阅了非 `off` 的 transcript 粒度后,该 agent 已被 transcript 投影的事件在同一连接上被抑制(未投影型如 `tool.list.updated` / `mcp.server.status` / `prompt.queued` 与生命周期事件始终走本流)。 + +广播器特判: + +- `prompt.accepted` 被过滤,不广播。 +- `turn.started` 的 `promptAttachments` 被显式剥离(schema 声明,wire 上不出现)。 +- `prompt.submitted` / `prompt.queued` / `prompt.steered` 的 `content` 从核心内容块投影为 [T-MessageContent](#t-messagecontent) 数组。 +- `agent.activity.updated` 转换为 `agent.status.updated`(仅 `phase` 字段);`agent.status.updated` 合并 legacy 状态(`usage` / `contextTokens` / `maxContextTokens` / `model`),schema 声明的 `permission` / `contextUsage` 无产出路径。 +- `task.started` / `task.terminated` 各自额外派生一条 `background.task.*` 帧(同 payload 改 type,紧随原帧)。 +- 主 agent 的 `context.spliced` 额外触发一次 `agent.status.updated` 重发。 +- `task.notified` / `prompt.queued` / `prompt.started` / `turn.steer` / `plan.revision` / `context.spliced` 6 型不在 `agentEventSchema` 联合中(schema 盲区)。 + +消费 volatile 文本流时用 `offset` 与本地累计文本比对:小于本地长度为重复帧,大于为有缺漏、需走快照恢复。 + +**轮次。** + +#### `turn.started`(S→C) + +一轮开始;`origin` 为 [T-PromptOrigin](#t-promptorigin)。durable。 + +```ts +{ + type: 'turn.started'; + payload: { + turnId: number; + origin: PromptOrigin; + prompt?: string; + promptId?: string; // promptAttachments 被广播器剥离,wire 上不出现 + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.ended`(S→C) + +一轮结束;`error` 为 [T-KimiError](#t-kimierror)。durable。 + +```ts +{ + type: 'turn.ended'; + payload: { + turnId: number; + reason: 'completed' | 'cancelled' | 'failed' | 'blocked'; + error?: KimiError; + durationMs?: number; + interruptReason?: 'user_cancelled' | 'aborted' | 'max_steps' | 'error' | 'filtered' | 'blocked'; + time?: number; // 事件自带时刻,外层 timestamp 取之 + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.step.started`(S→C) + +step(一次 LLM 调用)开始。durable。 + +```ts +{ + type: 'turn.step.started'; + payload: { + turnId: number; + step: number; + stepId?: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.step.completed`(S→C) + +step 完成(含 token 与时延遥测);`usage` 为 [T-TokenUsage](#t-tokenusage)。durable。 + +```ts +{ + type: 'turn.step.completed'; + payload: { + turnId: number; + step: number; + stepId?: string; + usage?: TokenUsage; + finishReason?: string; + llmFirstTokenLatencyMs?: number; // 本行起六个为时延组 + llmStreamDurationMs?: number; + llmRequestBuildMs?: number; + llmServerFirstTokenMs?: number; + llmServerDecodeMs?: number; + llmClientConsumeMs?: number; + providerFinishReason?: 'completed' | 'tool_calls' | 'truncated' | 'filtered' | 'paused' | 'other'; + rawFinishReason?: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.step.retrying`(S→C) + +step 失败后等待重试。durable。 + +```ts +{ + type: 'turn.step.retrying'; + payload: { + turnId: number; + step: number; + stepId?: string; + failedAttempt: number; + nextAttempt: number; + maxAttempts: number; + delayMs: number; + errorName: string; + errorMessage: string; + statusCode?: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.step.interrupted`(S→C) + +step 被中断。durable。 + +```ts +{ + type: 'turn.step.interrupted'; + payload: { + turnId: number; + step: number; + stepId?: string; + reason: string; + message?: string; + agentId: string; + sessionId: string; + }; +} +``` + +**prompt。** + +#### `prompt.submitted`(S→C) + +prompt 提交入队或立即运行(如 [POST .../prompts](#post-api-v1-sessions-session-id-prompts) 触发);`content` 为投影后的 [T-MessageContent](#t-messagecontent) 数组。durable。 + +```ts +{ + type: 'prompt.submitted'; + payload: { + promptId: string; + userMessageId: string; + status: 'running' | 'queued'; // schema 声称含 'blocked' 三态,产出无 + content: MessageContent[]; // 已投影 + createdAt: string; // ISO 8601 + agentId: string; + sessionId: string; + }; +} +``` + +#### `prompt.queued`(S→C) + +prompt 进入队列。未被 transcript 投影,订阅 transcript 后仍走本流。durable。 + +```ts +{ + type: 'prompt.queued'; + payload: { + promptId: string; + content: MessageContent[]; // 已投影 + queueLength: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `prompt.started`(S→C) + +prompt 开始执行。durable。 + +```ts +{ + type: 'prompt.started'; + payload: { + promptId: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `prompt.completed`(S→C) + +prompt 执行结束。durable。 + +```ts +{ + type: 'prompt.completed'; + payload: { + promptId: string; + finishedAt: string; // ISO 8601 + reason: 'completed' | 'failed' | 'blocked'; // schema 标可缺省,产出恒带 + agentId: string; + sessionId: string; + }; +} +``` + +#### `prompt.aborted`(S→C) + +prompt 被中止。durable。 + +```ts +{ + type: 'prompt.aborted'; + payload: { + promptId: string; + abortedAt: string; // ISO 8601 + agentId: string; + sessionId: string; + }; +} +``` + +#### `prompt.steered`(S→C) + +运行中的 prompt 被追加 steer 内容;`content` 为投影后的 [T-MessageContent](#t-messagecontent) 数组。durable。 + +```ts +{ + type: 'prompt.steered'; + payload: { + activePromptId: string; + promptIds: string[]; // 被 steer 合并的 prompt + content: MessageContent[]; // 已投影 + steeredAt: string; // ISO 8601 + agentId: string; + sessionId: string; + }; +} +``` + +#### `turn.steer`(S→C) + +steer 触发的轮次级输入记录;`origin` 为 [T-PromptOrigin](#t-promptorigin)。durable。 + +```ts +{ + type: 'turn.steer'; + payload: { + input: ContentPart[]; // 核心内容块,未投影(与 prompt.steered.content 不对称) + origin: PromptOrigin; + agentId: string; + sessionId: string; + }; +} +``` + +**流式增量。** #### `assistant.delta`(S→C) @@ -5547,6 +5808,726 @@ agent 向用户发起的提问到达;payload 即 [T-QuestionRequest](#t-questi } ``` +#### `thinking.delta`(S→C) + +流式思考增量。volatile;`offset`、合并行为与 subagent 差异同 [`assistant.delta`](#assistant-delta-s→c)。 + +```ts +{ + type: 'thinking.delta'; + offset?: number; // 仅主 agent 携带 + payload: { + turnId: number; + delta: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `tool.call.delta`(S→C) + +工具调用参数的流式增量。volatile;不参与 delta 合并,无 `offset`。 + +```ts +{ + type: 'tool.call.delta'; + payload: { + turnId: number; + toolCallId: string; + name?: string; + argumentsPart?: string; + agentId: string; + sessionId: string; + }; +} +``` + +**工具调用。** + +#### `tool.call.started`(S→C) + +工具调用开始;`display` 为 [T-ToolInputDisplay](#t-toolinputdisplay) 展示投影。durable。 + +```ts +{ + type: 'tool.call.started'; + payload: { + turnId: number; + toolCallId: string; + name: string; + args: unknown; + description?: string; + display?: ToolInputDisplay; + agentId: string; + sessionId: string; + }; +} +``` + +**帧示例**: + +```json +{ + "type": "tool.call.started", + "seq": 131, + "epoch": "01JZX4...", + "session_id": "session_01JZX4...", + "timestamp": "2026-09-02T08:06:05.000Z", + "payload": { + "type": "tool.call.started", + "turnId": 3, + "toolCallId": "toolu_01J...", + "name": "Bash", + "args": { "command": "pnpm test" }, + "display": { "kind": "command", "command": "pnpm test" }, + "agentId": "main", + "sessionId": "session_01JZX4..." + } +} +``` + +#### `tool.progress`(S→C) + +工具执行过程输出。volatile。 + +```ts +{ + type: 'tool.progress'; + payload: { + turnId: number; + toolCallId: string; + update: { + kind: 'stdout' | 'stderr' | 'progress' | 'status' | 'custom'; + text?: string; + percent?: number; + customKind?: string; // kind = 'custom' 时 + customData?: unknown; // 同上 + replace?: boolean; // 覆盖式更新 + }; + agentId: string; + sessionId: string; + }; +} +``` + +#### `tool.result`(S→C) + +工具调用结束。durable。 + +```ts +{ + type: 'tool.result'; + payload: { + turnId: number; + toolCallId: string; + output: unknown; + isError?: boolean; + synthetic?: boolean; // 合成结果(如中断补齐) + agentId: string; + sessionId: string; + }; +} +``` + +#### `tool.list.updated`(S→C) + +工具清单因 MCP 连接状态变化。未被 transcript 投影,恒走本流。durable。 + +```ts +{ + type: 'tool.list.updated'; + payload: { + reason: 'mcp.connected' | 'mcp.disconnected' | 'mcp.failed'; + serverName: string; + agentId: string; + sessionId: string; + }; +} +``` + +**Shell。** + +#### `shell.started`(S→C) + +`!` 前缀 shell 命令开始。volatile。 + +```ts +{ + type: 'shell.started'; + payload: { + commandId: string; + taskId: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `shell.output`(S→C) + +shell 命令输出增量;`update` 形态同 [`tool.progress`](#tool-progress-s→c)。volatile。 + +```ts +{ + type: 'shell.output'; + payload: { + commandId: string; + update: ToolUpdate; + taskId?: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `shell.completed`(S→C) + +shell 命令结束。volatile。 + +```ts +{ + type: 'shell.completed'; + payload: { + commandId: string; + isError: boolean; + taskId?: string; + agentId: string; + sessionId: string; + }; +} +``` + +**后台任务。** + +#### `task.started`(S→C) + +后台任务开始。每帧随后紧跟一条派生的 [`background.task.started`](#background-task-started-s→c)(同 payload 改 type)。durable。 + +```ts +{ + type: 'task.started'; + payload: { + info: { + kind: 'process' | 'agent' | 'question'; + taskId: string; + description: string; + status: 'running' | 'completed' | 'failed' | 'timed_out' | 'killed' | 'lost'; + detached?: boolean; + startedAt: number; + endedAt: number | null; + stopReason?: string; + terminalNotificationSuppressed?: boolean; + timeoutMs?: number; + // kind = 'process' 另有:command: string; pid: number; exitCode: number | null + // kind = 'agent' 另有:agentId?: string; subagentType?: string; model?: string; thinkingEffort?: string + // kind = 'question' 另有:questionCount: number; toolCallId?: string + }; + agentId: string; + sessionId: string; + }; +} +``` + +#### `task.terminated`(S→C) + +后台任务终止,`info` 同 [`task.started`](#task-started-s→c)。每帧随后紧跟一条派生的 [`background.task.terminated`](#background-task-terminated-s→c)。durable。 + +```ts +{ + type: 'task.terminated'; + payload: { + info: TaskInfo; // 同 task.started + agentId: string; + sessionId: string; + }; +} +``` + +#### `background.task.started`(S→C) + +[`task.started`](#task-started-s→c) 的派生兼容帧,同 payload 改 type,紧随源帧。durable。 + +```ts +{ + type: 'background.task.started'; + payload: { + info: TaskInfo; + agentId: string; + sessionId: string; + }; +} +``` + +#### `background.task.terminated`(S→C) + +[`task.terminated`](#task-terminated-s→c) 的派生兼容帧,同 payload 改 type,紧随源帧。durable。 + +```ts +{ + type: 'background.task.terminated'; + payload: { + info: TaskInfo; + agentId: string; + sessionId: string; + }; +} +``` + +#### `task.notified`(S→C) + +后台任务完成通知(终端通知语义)。durable。 + +```ts +{ + type: 'task.notified'; + payload: { + notificationType: string; + title: string; + body: string; + severity: 'info' | 'warning'; + sourceKind: string; + sourceId: string; + agentId: string; + sessionId: string; + }; +} +``` + +**subagent。** + +#### `subagent.spawned`(S→C) + +subagent 被创建。durable。 + +```ts +{ + type: 'subagent.spawned'; + payload: { + subagentId: string; + subagentName: string; + parentToolCallId: string; + parentToolCallUuid?: string; + parentAgentId?: string; + callerAgentId?: string; + description?: string; + swarmIndex?: number; // swarm 序号 + runInBackground: boolean; + model?: string; + thinkingEffort?: string; + taskId?: string; // 挂为后台任务时 + agentId: string; + sessionId: string; + }; +} +``` + +#### `subagent.started`(S→C) + +subagent 开始运行。durable。 + +```ts +{ + type: 'subagent.started'; + payload: { + subagentId: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `subagent.suspended`(S→C) + +subagent 挂起(swarm 调度)。durable。 + +```ts +{ + type: 'subagent.suspended'; + payload: { + subagentId: string; + reason: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `subagent.completed`(S→C) + +subagent 完成;`usage` 为 [T-TokenUsage](#t-tokenusage)。durable。 + +```ts +{ + type: 'subagent.completed'; + payload: { + subagentId: string; + resultSummary: string; + usage?: TokenUsage; + contextTokens?: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `subagent.failed`(S→C) + +subagent 失败。durable。 + +```ts +{ + type: 'subagent.failed'; + payload: { + subagentId: string; + error: string; + agentId: string; + sessionId: string; + }; +} +``` + +**状态。** + +#### `agent.status.updated`(S→C) + +agent 状态快照增量。volatile。两个来源:核心 `agent.status.updated`(合并 legacy 状态)与 `agent.activity.updated` 转换(仅 `phase`);`phase` 为 [T-AgentPhase](#t-agentphase)。schema 声明的 `permission` / `contextUsage` 无产出路径。 + +```ts +{ + type: 'agent.status.updated'; + payload: { + usage?: { + byModel?: Record; + currentTurn?: TokenUsage; + total?: TokenUsage; + }; + contextTokens?: number; + maxContextTokens?: number; + model?: string; + thinkingEffort?: string; + planMode?: boolean; + swarmMode?: boolean; + towerMode?: boolean; + phase?: AgentPhase; + agentId: string; + sessionId: string; + }; +} +``` + +#### `agent.created`(S→C) + +agent 生命周期事件(创建);`agent_filter` 对该型放行。durable。 + +```ts +{ + type: 'agent.created'; + payload: { + agentId: string; + sessionId: string; + }; +} +``` + +#### `agent.disposed`(S→C) + +agent 生命周期事件(销毁);`agent_filter` 对该型放行。durable。 + +```ts +{ + type: 'agent.disposed'; + payload: { + agentId: string; + sessionId: string; + }; +} +``` + +#### `session.meta.updated`(S→C) + +会话元数据更新;`title` 与 `patch` 至少其一存在。投递范围:全局(虽无 `event.` 前缀)。durable,落该会话 journal。 + +```ts +{ + type: 'session.meta.updated'; + payload: { + title?: string; + patch?: Record; + agentId: 'main'; + sessionId: string; + }; +} +``` + +**compaction。** + +#### `compaction.started`(S→C) + +压缩开始。durable。 + +```ts +{ + type: 'compaction.started'; + payload: { + trigger: 'manual' | 'auto'; + instruction?: string; // 手动指令 + agentId: string; + sessionId: string; + }; +} +``` + +#### `compaction.blocked`(S→C) + +压缩被阻塞(如轮次进行中)。durable。 + +```ts +{ + type: 'compaction.blocked'; + payload: { + turnId?: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `compaction.cancelled`(S→C) + +压缩被取消,无附加字段。durable。 + +```ts +{ + type: 'compaction.cancelled'; + payload: { + agentId: string; + sessionId: string; + }; +} +``` + +#### `compaction.completed`(S→C) + +压缩完成。durable。 + +```ts +{ + type: 'compaction.completed'; + payload: { + result: { + summary: string; + compactedCount: number; + tokensBefore: number; + tokensAfter: number; + keptUserMessageCount?: number; + keptHeadUserMessageCount?: number; + droppedCount?: number; + }; + agentId: string; + sessionId: string; + }; +} +``` + +**其他。** + +#### `context.spliced`(S→C) + +上下文被剪接(undo / fork)。主 agent 上额外触发一次 `agent.status.updated` 重发。durable。 + +```ts +{ + type: 'context.spliced'; + payload: { + start: number; + deleteCount: number; + messages: ContextMessage[]; // 核心消息,未投影 + tokens?: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `goal.updated`(S→C) + +goal 状态变化(`/goal` 模式);`snapshot` 为 [T-GoalSnapshot](#t-goalsnapshot)。durable。 + +```ts +{ + type: 'goal.updated'; + payload: { + snapshot: GoalSnapshot | null; + change?: { + kind: 'lifecycle' | 'completion'; + status?: string; // goalStatus + reason?: string; + stats?: { turnsUsed: number; tokensUsed: number; wallClockMs: number }; + actor?: 'user' | 'model' | 'runtime' | 'system'; + }; + agentId: string; + sessionId: string; + }; +} +``` + +#### `plan.revision`(S→C) + +plan 新修订落盘。durable。 + +```ts +{ + type: 'plan.revision'; + payload: { + id: string; // plan id + version: number; // 单调递增版本 + key: string; // 存储相对键 + sha256: string; + bytes: number; + agentId: string; + sessionId: string; + }; +} +``` + +#### `skill.activated`(S→C) + +Skill 被激活。durable。 + +```ts +{ + type: 'skill.activated'; + payload: { + activationId: string; + skillName: string; + skillArgs?: string; + trigger: 'user-slash' | 'model-tool' | 'nested-skill'; + skillPath?: string; + skillSource?: 'project' | 'user' | 'extra' | 'builtin'; + agentId: string; + sessionId: string; + }; +} +``` + +#### `plugin_command.activated`(S→C) + +插件命令被激活。durable。 + +```ts +{ + type: 'plugin_command.activated'; + payload: { + activationId: string; + pluginId: string; + commandName: string; + commandArgs?: string; + trigger: 'user-slash'; // 恒此值 + agentId: string; + sessionId: string; + }; +} +``` + +#### `error`(S→C) + +agent 级错误事件,payload 为 [T-KimiError](#t-kimierror) 全字段。带事件信封(`session_id` / `seq`),与控制帧 [`error`](#error-s→c-死声明)(死声明)不同。durable。 + +```ts +{ + type: 'error'; + payload: { + code: string; // 核心错误码字符串 + message: string; + name?: string; + details?: unknown; + retryable: boolean; + cause?: unknown; // 递归同构 + agentId: string; + sessionId: string; + }; +} +``` + +#### `warning`(S→C) + +agent 级警告(如 profile 配置告警)。durable。 + +```ts +{ + type: 'warning'; + payload: { + message: string; + code?: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `cron.fired`(S→C) + +cron 任务触发注入。durable。 + +```ts +{ + type: 'cron.fired'; + payload: { + origin: { + kind: 'cron_job'; + jobId: string; + cron: string; + recurring: boolean; + coalescedCount: number; + stale: boolean; + }; + prompt: string; + agentId: string; + sessionId: string; + }; +} +``` + +#### `hook.result`(S→C) + +外部 hook 执行结果注入。durable。 + +```ts +{ + type: 'hook.result'; + payload: { + turnId?: number; + hookEvent: string; + content: string; + blocked?: boolean; + agentId: string; + sessionId: string; + }; +} +``` + +#### `mcp.server.status`(S→C) + +MCP server 状态变化;`status` 透传核心六态,与 REST [T-McpServer](#t-mcpserver) 的四态取值域不同。未被 transcript 投影,恒走本流。durable。 + +```ts +{ + type: 'mcp.server.status'; + payload: { + server: { + name: string; + transport: 'stdio' | 'http'; + status: 'pending' | 'connected' | 'failed' | 'disabled' | 'needs-auth' | 'removed'; + toolCount: number; + error?: string; + }; + agentId: string; + sessionId: string; + }; +} +``` + --- (以下为旧格式内容,待全量按新格式替换后删除) From b2a9946496b68aedcb75833b53fbfd3096b43385 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:20:42 +0800 Subject: [PATCH 45/47] docs(zh): write transcript and terminal frame sections, drop the superseded old-format content --- docs/zh/reference/server-api.md | 306 +++++++------------------------- 1 file changed, 60 insertions(+), 246 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 20a6e0d7b88..68eea3695cd 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4808,8 +4808,8 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | 分类 | 方向 | 帧数 | 类型正名 | 用途 | | --- | --- | --- | --- | --- | | [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | `ServerSystemMessage`(下行)/ `ClientControlMessage`(上行) | 握手、订阅、心跳与恢复 | -| [event.\* 事件帧](#event-协议事件) | S→C | 19 | 13 型有接口正名,6 型未命名 | 工作区 / 会话 / 配置等状态同步 | -| [agent 事件帧](#agent-事件) | S→C | 51 | `AgentEvent` | 轮次生命周期、状态与 subagent 内容 | +| [event.\* 事件帧](#event-事件帧) | S→C | 19 | 13 型有接口正名,6 型未命名 | 工作区 / 会话 / 配置等状态同步 | +| [agent 事件帧](#agent-事件帧) | S→C | 51 | `AgentEvent` | 轮次生命周期、状态与 subagent 内容 | | [transcript 帧](#transcript-帧) | S→C | 2 | `TranscriptResetEvent` / `TranscriptOpsEvent` | 主会话内容的结构化流(新实现) | | [terminal 帧](#terminal-帧) | S→C | 2 | — | 死协议 | @@ -6528,268 +6528,82 @@ MCP server 状态变化;`status` 透传核心六态,与 REST [T-McpServer](# } ``` ---- - -(以下为旧格式内容,待全量按新格式替换后删除) - -### 控制帧(旧格式,待替换) - -#### server_hello(服务端→客户端) - -连接建立后的首帧。 - -**payload**: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `ws_connection_id` | string | 连接 id(`conn_`) | -| `protocol_version` | number | 恒 `2`。当前无任何一侧判定该版本号 | -| `heartbeat_ms` | number | 心跳间隔(默认 `10000`) | -| `max_event_buffer_size` | number | 每会话事件缓冲容量(默认 `1000`),断线回放的上限 | -| `capabilities` | object | 恒 `{ "event_batching": false, "compression": false }` | - -**示例**: - -```json -{ "type": "server_hello", "timestamp": "2026-09-02T08:00:00.000Z", "payload": { "ws_connection_id": "conn_01JZX4...", "protocol_version": 2, "heartbeat_ms": 10000, "max_event_buffer_size": 1000, "capabilities": { "event_batching": false, "compression": false } } } -``` - -#### ping / pong - -- 服务端→客户端:`{ "type": "ping", "timestamp", "payload": { "nonce": number } }`,每 `heartbeat_ms` 一帧。 -- 客户端→服务端:`{ "type": "pong", "payload": { "nonce": number } }`——服务端只重置心跳计时,不回 `ack`。连续两个周期没有任何入站帧,服务端以 `close(1001, 'heartbeat timeout')` 断连。 - -#### ack(服务端→客户端) - -每个带 `id` 的入站控制帧一个应答:`{ "type": "ack", "id", "code", "msg", "payload" }`。`code: 0` 成功;`1` 参数或内部错误;`40112` 鉴权失败(`client_hello.payload.token` 校验失败,随后连接关闭)。 - -各入站帧及其 `ack` 的 payload: - -| 入站帧 | payload(入) | ack payload(出) | -| --- | --- | --- | -| `client_hello` | `{ client_id, subscriptions?, cursors?, agent_filter?, token? }` | `{ accepted_subscriptions, resync_required, cursors }` | -| `subscribe` | `{ session_ids: string[], cursors?, watch_fs?, agent_filter? }` | `{ accepted, not_found, resync_required, cursors }` | -| `subscribe_v2` | `{ session_id, transcript, transcript_since? }`(见 [transcript 帧](#transcript-帧)) | 同 `subscribe` | -| `unsubscribe_v2` | `{ session_id, agent_ids? }` | `{ accepted: [session_id], not_found: [], resync_required: [] }`(无 `cursors` 键) | -| `unsubscribe` | `{ session_ids: string[] }` | `{ accepted: [], not_found: [], resync_required: [] }`(恒空数组) | -| `watch_fs_add` / `watch_fs_remove` | `{ session_id, paths: string[], runtime_id?, recursive? }` | `{ watched_paths, current_count }`;bridge 缺失或异常时 `code: 1` | - -字段说明: - -- `cursors`:`Record`——断线恢复游标,见 [断线恢复](#断线恢复)。带游标订阅时服务端回放缺口事件;无法回放时先发 `resync_required`,并把该会话 id 列入 `ack` 的 `resync_required`。 -- `watch_fs`:`Record`——随订阅一并登记的文件监听(等价于逐会话发 `watch_fs_add`),变更经 `event.fs.changed` 送达。 -- `agent_filter`:`Record`——只接收所列 Agent 的事件。 -- `token`:`client_hello` 的冗余第二鉴权通道(升级请求已鉴权,缺省直接放行)。 -- `client_id === 'kimi-inspect'` 的连接会被加入 DI 事件目标集(`event.di.*` 的门控,见 [event.\* 协议事件](#event-协议事件))。 - -**示例**(`subscribe` 的 `ack`): +### transcript 帧 -```json -{ "type": "ack", "id": "1", "code": 0, "msg": "ok", "payload": { "accepted": [ "session_01JZX4..." ], "not_found": [], "resync_required": [], "cursors": { "session_01JZX4...": { "seq": 128, "epoch": "01JZX4..." } } } } -``` +`subscribe_v2` 是唯一的 transcript 订阅通道:`transcript` 按 agent 指定粒度(`off` / `turn` / `block` / `delta`,键 `"*"` 为通配档),粒度越高推送越细——`turn` 只投递轮次级 op(基线快照中 `steps` 置空数组),`block` 起含 step 与 frame 级 op、仅排除 `append` 增量,`delta` 全量。连接对某 agent 订阅了非 `off` 粒度后,该 agent 的内容改由 transcript 帧承载,其已被 transcript 投影的裸 agent 事件在同一连接上被抑制(见 [agent 事件帧](#agent-事件帧))。payload 内 item 与 op 的类型全集见 [T-Transcript 族](#t-transcript-族)。 -#### resync_required(服务端→客户端) +两型帧的信封均恒 `volatile: true`(见 [帧总览](#帧总览)):外层 `seq` 为会话事件水位(不递增),逐 agent 连续递增的 transcript seq 在 `payload.seq`。 -订阅游标无法回放时下发:事件缓冲溢出(`buffer_overflow`)、会话被重建(`session_recreated`)或 `epoch` 不符(`epoch_changed`)。处理方式见 [断线恢复](#断线恢复)。 +#### `transcript.reset`(S→C) -**payload**: +基线快照,按订阅粒度裁剪。触发:订阅、粒度升级(仅升级时重发,降级不重发)或新 agent 上名册。 -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `session_id` | string | 需要重新同步的会话 | -| `reason` | string | `buffer_overflow` / `session_recreated` / `epoch_changed` | -| `current_seq` | integer | 当前事件水位 | -| `epoch` | string | 可缺省:当前 epoch | - -**示例**: - -```json -{ "type": "resync_required", "timestamp": "2026-09-02T08:10:00.000Z", "payload": { "session_id": "session_01JZX4...", "reason": "buffer_overflow", "current_seq": 1420, "epoch": "01JZX4..." } } +```ts +{ + type: 'transcript.reset'; + volatile: true; // 外层恒 volatile;外层 seq 为会话事件水位 + payload: { + type: 'transcript.reset'; // payload 内重复 type + agent_id: string; + snapshot: AgentTranscriptSnapshot; // 见 T-Transcript 族 + has_more_older: boolean; // 存在更早历史,经 REST 分页回读 + seq?: number; // transcript seq 水位 + }; +} ``` -#### error(控制帧,死声明) - -控制帧形态的 `error`(`{ type: "error", timestamp, payload: { code, msg, fatal, request_id?, details? } }`)在 AsyncAPI 中声明,但服务端没有任何产出点。事件流中出现的 `type: "error"` 帧均为裸 agent `error` 事件(带 `session_id` / `seq` 事件信封,见 [agent 事件](#agent-事件)),客户端可按有无 `session_id` 分流。 - -### 事件信封 - -所有事件帧共享外层 `{ "type", "seq", "epoch"?, "volatile"?, "offset"?, "session_id", "timestamp", "payload" }`:`type` 与 `payload` 内事件的 `type` 重复一次;`session_id` 在全局事件上为 `__global__`;`timestamp` 为 ISO 8601(事件自带时间时取之)。`seq` / `epoch` / `volatile` / `offset` 的语义随产出器分四种形态: - -| 形态 | `seq` | `epoch` | `volatile` | `offset` | -| --- | --- | --- | --- | --- | -| 持久(durable)事件 | 事件日志水位,严格递增并落盘 | 有 | 缺省 | 缺省 | -| 易失(volatile)事件 | 当前水位(不递增,与前后持久帧同 `seq`) | 有 | `true` | delta 类携带(该轮次内累计文本长度) | -| transcript 帧 | 外层为会话事件水位(非 transcript seq);transcript seq 在 `payload.seq` | 有 | `true` | 缺省 | -| `event.fs.changed` | 文件监听作用域自增计数(与事件日志无关) | **无** | 缺省 | 缺省 | - -易失类型全集:`assistant.delta` / `thinking.delta` / `tool.call.delta` / `tool.progress` / `shell.started` / `shell.output` / `shell.completed` / `agent.status.updated`,另有 `event.di.unit_changed` 与 `event.capability.changed`。易失事件不落盘、不回放;消费易失文本流时用 `offset` 与本地已累积文本比对:小于本地长度说明是重复帧,大于说明有缺漏、需走快照恢复。 - -投递范围分两类:**全局事件**广播给每个已建立连接(含未订阅该会话的)——`session.meta.updated`、`event.session.*`、`event.workspace.*`、`event.config.*`、`event.model_catalog.*`、`event.plugin.*`、`event.capability.*`、`event.di.*`(仅发往 `client_id: "kimi-inspect"` 的连接);**会话事件**只发给订阅了该会话的连接,受 `agent_filter` 过滤——`event.question.*`、`event.approval.*` 与全部裸 agent 事件。`event.fs.changed` 单独一路:仅发往经 `watch_fs_add`(或 `subscribe` 的 `watch_fs`)登记了对应路径监听的连接。这些事件只覆盖本服务进程内的变更;其他进程(例如写同一 home 目录的 CLI)的变更要等索引 reconcile(约一分钟)才可见,因此概览客户端应保留低频兜底轮询。目前没有会话删除事件。 +#### `transcript.ops`(S→C) -### event.* 协议事件 - -payload 内统一带 `agentId: "main"` 与 `sessionId`(全局事件为 `__global__` 或真实会话 id)。除标注外均为持久事件;各族的投递范围见 [事件信封](#事件信封)。 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `event.session.created` | `session: T-Session` | 创建会话 / fork / 创建子会话时 | -| `event.session.archived` | `workspace_id`(另有 `agentId` 与 camelCase `sessionId`) | 在线与冷归档两条路径都会发出;概览免轮询 | -| `event.session.work_changed` | `busy, main_turn_active, pending_interaction, last_turn_reason?` | 会话工作聚合变化时 | -| `event.session.status_changed` | — | schema 已声明但**无产出点** | -| `event.workspace.created` | `workspace: T-Workspace` | 注册工作区时 | -| `event.workspace.updated` | `workspace: T-Workspace` | 重命名 / 重新注册 / 会话创建触碰工作区时 | -| `event.workspace.deleted` | `workspace_id, root` | 注销工作区时 | -| `event.config.changed` | `changedFields: string[]`(camelCase 域名)、`config: T-ConfigResponse` | 任何来源的配置变更;短时间窗内多次变更合并为一个事件 | -| `event.config.warning` | `warnings: { domain?, message }[]` | 配置告警 | -| `event.model_catalog.changed` | `changed, unchanged, failed`(同 [T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)) | 至少一个供应商的别名变化时 | -| `event.plugin.changed` | (无附加字段) | 插件安装 / 启用 / 停用 / 移除时 | -| `event.capability.changed` | `capability_id, install: { running, step?, percent?, error?, note? }` | 易失;能力安装进度 | -| `event.di.unit_changed` | `scope, token, state, error?` | 易失;仅发往 `client_id: "kimi-inspect"` 的连接;`state` 取值同 meta `features[].state`,枚举非封闭 | -| `event.question.requested` | [T-QuestionRequest](#t-questionrequest) 全字段 | 提问到达 | -| `event.question.answered` | `question_id, answers, resolved_at` | `answers` 为拍平的文本 map(`Record<条目 id, 文本>`),与 REST 的结构化 answers 形态不同 | -| `event.question.dismissed` | `question_id, dismissed_at` | | -| `event.approval.requested` | [T-ApprovalRequest](#t-approvalrequest) 全字段 | 审批到达 | -| `event.approval.resolved` | `approval_id, decision?, scope?, feedback?, selected_label?, resolved_at` | | -| `event.fs.changed` | `changes: { path, change, kind, size_delta?, etag? }[], coalesced_window_ms, truncated?, count?` | `change` 为 `created` / `modified` / `deleted`,`kind` 为 `file` / `directory` / `symlink`;`truncated: true` 时 `changes` 为空数组。信封特殊(见 [事件信封](#事件信封)) | +op 批次,按订阅粒度过滤。触发:transcript store 产生 op(批量投递),或 `transcript_since` 游标回放。 -**示例**(`event.session.work_changed`): - -```json -{ "type": "event.session.work_changed", "seq": 129, "epoch": "01JZX4...", "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:00.000Z", "payload": { "type": "event.session.work_changed", "busy": true, "main_turn_active": true, "pending_interaction": "none", "agentId": "main", "sessionId": "session_01JZX4..." } } +```ts +{ + type: 'transcript.ops'; + volatile: true; + payload: { + type: 'transcript.ops'; + agent_id: string; + ops: TranscriptOperation[]; // 14 型,见 T-Transcript 族 + seq?: number; // 该批的 transcript seq + }; +} ``` -### agent 事件 - -裸 agent 事件的 `payload` 为核心事件对象字段外加广播器补充的 `{ agentId, sessionId }`(camelCase);除标注外均为持久事件。广播器的特判: - -- `prompt.accepted` 被过滤,不广播。 -- `turn.started` 的 `promptAttachments` 被显式剥离(schema 声明但 wire 上不出现)。 -- `prompt.submitted` / `prompt.queued` / `prompt.steered` 的 `content` 从核心内容块投影为 [T-MessageContent](#t-messagecontent) 数组。 -- `task.started` / `task.terminated` 各自额外派生一条 `background.task.started` / `background.task.terminated`(同 payload 改 type,随后发出)。 -- `context.spliced` 触发一次 main agent 的 `agent.status.updated` 重发。 - -#### 轮次族 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `turn.started` | `turnId, origin, prompt?, promptId?` | `origin` 为 [T-PromptOrigin](#t-promptorigin);无 `promptAttachments` | -| `turn.ended` | `turnId, reason, error?, durationMs?, interruptReason?, time?` | `reason` 为 `completed` / `cancelled` / `failed` / `blocked`;`error` 为 [T-KimiError](#t-kimierror) | -| `turn.step.started` | `turnId, step, stepId?` | | -| `turn.step.completed` | `turnId, step, stepId?, usage?, finishReason?, providerFinishReason?, rawFinishReason?` 及时延组字段 | `usage` 为 [T-TokenUsage](#t-tokenusage) | -| `turn.step.retrying` | `turnId, step, stepId?, failedAttempt, nextAttempt, maxAttempts, delayMs, errorName, errorMessage, statusCode?` | | -| `turn.step.interrupted` | `turnId, step, stepId?, reason, message?` | | - -#### 流式文本族(易失) - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `assistant.delta` | `turnId, delta` | 带 `offset`;相邻同轮次帧可能被合并 | -| `thinking.delta` | `turnId, delta` | 同上 | - -#### 工具调用族 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `tool.call.delta` | `turnId, toolCallId, name?, argumentsPart?` | 易失 | -| `tool.call.started` | `turnId, toolCallId, name, args, description?, display?` | `display` 为 [T-ToolInputDisplay](#t-toolinputdisplay) | -| `tool.progress` | `turnId, toolCallId, update` | 易失;`update` 为 `{ kind: "stdout" \| "stderr" \| "progress" \| "status" \| "custom", text?, percent?, customKind?, customData?, replace? }` | -| `tool.result` | `turnId, toolCallId, output, isError?, synthetic?` | | -| `tool.list.updated` | `reason, serverName` | `reason` 为 `mcp.connected` / `mcp.disconnected` / `mcp.failed` | - -#### Shell 族(易失) - -| type | payload 字段 | -| --- | --- | -| `shell.started` | `commandId, taskId` | -| `shell.output` | `commandId, update, taskId?`(`update` 形态同 `tool.progress`) | -| `shell.completed` | `commandId, isError, taskId?` | - -#### 任务族 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `task.started` | `info` | `info` 为 T-TaskInfo(camelCase:`taskId, description, status, detached?, startedAt, endedAt?, stopReason?, timeoutMs?` 及 process / agent / question 三态各自扩展) | -| `task.terminated` | `info` | 同上 | -| `background.task.started` | 同 `task.started` | 派生帧 | -| `background.task.terminated` | 同 `task.terminated` | 派生帧 | -| `task.notified` | `notificationType, title, body, severity, sourceKind, sourceId` | `severity` 为 `info` / `warning` | - -#### subagent 族 - -| type | payload 字段 | -| --- | --- | -| `subagent.spawned` | `subagentId, subagentName, parentToolCallId, parentToolCallUuid?, parentAgentId?, callerAgentId?, description?, swarmIndex?, runInBackground, model?, thinkingEffort?, taskId?` | -| `subagent.started` | `subagentId` | -| `subagent.suspended` | `subagentId, reason` | -| `subagent.completed` | `subagentId, resultSummary, usage?, contextTokens?` | -| `subagent.failed` | `subagentId, error` | - -#### prompt 族 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `prompt.submitted` | `promptId, userMessageId, status, content, createdAt` | `status` 为 `running` / `queued`;`content` 为投影后的 [T-MessageContent](#t-messagecontent) 数组 | -| `prompt.queued` | `promptId, content, queueLength` | | -| `prompt.started` | `promptId` | | -| `prompt.completed` | `promptId, finishedAt, reason` | `reason` 恒产出,为 `completed` / `failed` / `blocked` | -| `prompt.aborted` | `promptId, abortedAt` | | -| `prompt.steered` | `activePromptId, promptIds, content, steeredAt` | | -| `turn.steer` | `input, origin` | `input` 为核心内容块数组(**未投影**);`origin` 为 [T-PromptOrigin](#t-promptorigin) | - -#### compaction 族 - -| type | payload 字段 | -| --- | --- | -| `compaction.started` | `trigger?`(`manual` / `auto`)、`instruction?` | -| `compaction.blocked` | `turnId?` | -| `compaction.cancelled` | — | -| `compaction.completed` | `result: { summary, compactedCount, tokensBefore, tokensAfter, keptUserMessageCount?, keptHeadUserMessageCount?, droppedCount? }` | -| `context.spliced` | `start, deleteCount, messages, tokens?`(`messages` 为核心 ContextMessage 数组,**未投影**) | - -#### 其他 agent 事件 - -| type | payload 字段 | 备注 | -| --- | --- | --- | -| `goal.updated` | `snapshot, change?` | `snapshot` 为 [T-GoalSnapshot](#t-goalsnapshot) 或 `null`;`change` 为 `{ kind: "lifecycle" \| "completion", status?, reason?, stats?, actor? }` | -| `plan.revision` | `id, version, path, sha256, bytes` | | -| `skill.activated` | `activationId, skillName, skillArgs?, trigger, skillPath?, skillSource?` | `trigger` 为 `user-slash` / `model-tool` / `nested-skill` | -| `plugin_command.activated` | `activationId, pluginId, commandName, commandArgs?, trigger` | `trigger` 恒 `user-slash` | -| `agent.status.updated` | `usage?, swarmMode?, towerMode?, planMode?, model?, thinkingEffort?, maxContextTokens?, contextTokens?` 合并 legacy 状态(`usage?, contextTokens, maxContextTokens?, model`),外加 `phase?` | 易失;`phase` 为 [T-AgentPhase](#t-agentphase)。schema 声明的 `permission` / `contextUsage` 无产出路径 | -| `agent.created` | (仅 `agentId` / `sessionId`) | | -| `agent.disposed` | (仅 `agentId` / `sessionId`) | | -| `session.meta.updated` | `title?, patch?` | 全局事件(广播给所有连接) | -| `error` | [T-KimiError](#t-kimierror) | 带事件信封;与控制帧 `error`(死声明)不同 | -| `warning` | `message, code?` | | -| `cron.fired` | `origin, prompt` | `origin` 为 T-CronJobOrigin | -| `hook.result` | `turnId?, hookEvent, content, blocked?` | | -| `mcp.server.status` | `server: { name, transport, status, toolCount, error? }` | `status` 直接透传核心六态:`pending` / `connected` / `failed` / `disabled` / `needs-auth` / `removed`——与 REST [T-McpServer](#t-mcpserver) 的四态取值域不同 | - -**示例**(`tool.call.started`): +**帧示例**(`transcript.ops`): ```json -{ "type": "tool.call.started", "seq": 131, "epoch": "01JZX4...", "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:05.000Z", "payload": { "type": "tool.call.started", "turnId": 3, "toolCallId": "toolu_01J...", "name": "Bash", "args": { "command": "pnpm test" }, "display": { "kind": "command", "command": "pnpm test" }, "agentId": "main", "sessionId": "session_01JZX4..." } } +{ + "type": "transcript.ops", + "seq": 132, + "epoch": "01JZX4...", + "volatile": true, + "session_id": "session_01JZX4...", + "timestamp": "2026-09-02T08:06:06.000Z", + "payload": { + "type": "transcript.ops", + "agent_id": "main", + "ops": [ { "op": "append", "...": "..." } ], + "seq": 43 + } +} ``` -### transcript 帧 - -`subscribe_v2` 是唯一的转录订阅通道:其 `transcript` 按 Agent 指定粒度(`off` / `turn` / `block` / `delta`,键 `"*"` 表示默认粒度),粒度越高推送越细。粒度非 `off` 的 Agent 改由转录帧承载,该 Agent 的旧式事件在同一连接上被抑制(其他连接不受影响)。两种帧型: - -| type | payload | 触发 | -| --- | --- | --- | -| `transcript.reset` | `{ type, agent_id, snapshot, has_more_older, seq? }` | 订阅、粒度升级或新 Agent 上名册时发送基线快照(`snapshot` 按订阅粒度裁剪,items 为空、仅全局状态与水位;历史经 REST 分页回读) | -| `transcript.ops` | `{ type, agent_id, ops, seq? }` | 转录存储产生 op 批次,或 `transcript_since` 游标回放 | - -两帧的信封均为 `volatile: true`,外层 `seq` 为会话事件水位;每个 Agent 连续递增的 transcript seq 在 `payload.seq`。断线时用 `subscribe_v2` 的 `transcript_since`(`Record`)续传:服务端批次日志完整覆盖缺口时走 `transcript.ops` 回放,否则重发 `transcript.reset`;REST 侧对应 `GET .../transcript/ops?since_seq=`(补漏返回 `complete: false` 时需全量刷新)。粒度升降是否重发 reset 由转录契约的粒度规则决定。 - -**示例**(`transcript.ops`): - -```json -{ "type": "transcript.ops", "seq": 132, "epoch": "01JZX4...", "volatile": true, "session_id": "session_01JZX4...", "timestamp": "2026-09-02T08:06:06.000Z", "payload": { "type": "transcript.ops", "agent_id": "main", "ops": [ { "op": "append", "...": "..." } ], "seq": 43 } } -``` +续传与补漏:断线后用 `subscribe_v2` 的 `transcript_since`(逐 agent 或 `'*'` 的 seq 水位)续传——服务端 op 日志完整覆盖缺口时走 `transcript.ops` 回放,覆盖不到或无水位时重发 `transcript.reset`;`subscribe` 的事件游标与 transcript 水位是两套独立续传。REST 侧对应补漏端点 [`GET .../transcript/ops`](#get-api-v1-sessions-session-id-transcript-ops):返回 `complete: false`(会话不活跃或日志回溯不到)时,调用方须回退为一次全量 `GET .../transcript` 刷新。 ### terminal 帧 -`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close` 及其 `ack`、以及服务端到客户端的 `terminal_output` / `terminal_exit` 在 AsyncAPI(`/asyncapi.json`)中完整声明,但**当前是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。REST 的终端生命周期端点见 [终端](#终端) 域。 +`terminal_attach` / `terminal_detach` / `terminal_input` / `terminal_resize` / `terminal_close`(C→S,各带 ack schema)与 `terminal_output` / `terminal_exit`(S→C)在 AsyncAPI(`/asyncapi.json`)中完整声明,`abort`(C→S,带 ack schema)同样声明在案,但**当前都是死协议**:服务端不处理这些入站帧(按未知 `type` 静默丢弃),也没有任何 `terminal_output` / `terminal_exit` 的产出点。中止 prompt 走 REST 的 [`:abort`](#post-api-v1-sessions-session-id-prompts-prompt-id-action) 动作;REST 的终端生命周期端点见 [终端](#终端) 域。 + +| 帧 | 方向 | schema 要点 | 现状 | +| --- | --- | --- | --- | +| `terminal_attach` | C→S | `{ session_id, terminal_id, since_seq? }`;ack `{ attached: true, replayed: number }` | 静默丢弃 | +| `terminal_detach` | C→S | `{ session_id, terminal_id }`;ack `{ detached: true }` | 静默丢弃 | +| `terminal_input` | C→S | `{ session_id, terminal_id, data }`;ack `{ accepted: true }` | 静默丢弃 | +| `terminal_resize` | C→S | `{ session_id, terminal_id, cols, rows }`;ack `{ resized: true }` | 静默丢弃 | +| `terminal_close` | C→S | `{ session_id, terminal_id }`;ack `{ closed: true }` | 静默丢弃 | +| `terminal_output` | S→C | `{ seq, session_id, terminal_id, timestamp, payload: { data } }` | 无产出 | +| `terminal_exit` | S→C | `{ session_id, terminal_id, timestamp, payload: { exit_code?: number \| null } }` | 无产出 | +| `abort` | C→S | `{ session_id, prompt_id }`;ack `{ aborted?, at_seq? }` | 静默丢弃 | ## 完整错误码 From 27b851806808565776cc61d8d05cb70a2e847fa8 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 20:25:05 +0800 Subject: [PATCH 46/47] docs(zh): link REST trigger-event names to their WS frame entries --- docs/zh/reference/server-api.md | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index 68eea3695cd..f7281b5f1a0 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -244,7 +244,7 @@ HTTP 状态码例外(非 200): 合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现的域保持不动。把 `yolo` 设为 `true` 是 `default_permission_mode: "yolo"` 的简写(`false` 被忽略)。每一次配置变更——经本端点、在进程外编辑 `config.toml`,或服务端内部写入——都会广播全局 `event.config.changed` 事件。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **请求体**:部分配置对象——[T-ConfigResponse](#t-configresponse) 中除 `raw` 外的任意子集,均为可选。 @@ -323,7 +323,7 @@ HTTP 状态码例外(非 200): 把全局 `default_model` 设为一个已存在的别名。`model_id` 是配置中的别名键原样——裸键如 `POST /api/v1/models/turbo:set_default`;id 含 `/` 时需 URL 编码,如 `POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default`。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **响应体**:`ResponseType<{ default_model: string, model: `[T-ModelCatalogItem](#t-modelcatalogitem)` }>` @@ -384,7 +384,7 @@ HTTP 状态码例外(非 200): 一次保存创建供应商及其模型别名;响应为 HTTP 201 加 `ResponseType`。当全局 `default_model` 完全未配置时,会以新供应商的 `default_model`(或第一个模型)播种;已有默认值绝不被修改。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **请求体**: @@ -469,7 +469,7 @@ HTTP 状态码例外(非 200): 一次保存整体替换供应商:`type`、`base_url` 与模型列表被重写,不再列出的别名从 `config.toml` 中消失。`api_key` 是三态的:省略表示保留已存密钥,`""` 表示清除,其他值表示替换。除 `new_id` 重命名迁移外,全局默认指针绝不被修改。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **请求体**: @@ -507,7 +507,7 @@ HTTP 状态码例外(非 200): 删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 `default_provider` / `default_model` 指针保持不动,即使它们指向被删的供应商。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **响应体**:HTTP 204 空体——状态行本身即表示删除成功,无 `ResponseType`。 @@ -517,7 +517,7 @@ HTTP 状态码例外(非 200): 从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名;模型来源为静态的供应商不经网络调用直接报告 `unchanged`。 -**触发事件**:`event.model_catalog.changed`(至少一个供应商的别名发生变化时;配置写入同时触发 `event.config.changed`) +**触发事件**:[`event.model_catalog.changed`](#event-model-catalog-changed-s→c)(至少一个供应商的别名发生变化时;配置写入同时触发 [`event.config.changed`](#event-config-changed-s→c)) **响应体**:`ResponseType<`[T-RefreshProviderModelsResponse](#t-refreshprovidermodelsresponse)`>`。 @@ -546,7 +546,7 @@ HTTP 状态码例外(非 200): 集合级动作路由;请求体按动作校验。四个动作: -**触发事件**:`:refresh` / `:refresh_oauth` → `event.model_catalog.changed`(至少一个供应商的别名发生变化时;配置写入同时触发 `event.config.changed`);`:import_catalog` / `:import_registry` → `event.config.changed` +**触发事件**:`:refresh` / `:refresh_oauth` → [`event.model_catalog.changed`](#event-model-catalog-changed-s→c)(至少一个供应商的别名发生变化时;配置写入同时触发 [`event.config.changed`](#event-config-changed-s→c));`:import_catalog` / `:import_registry` → [`event.config.changed`](#event-config-changed-s→c) **响应体**:统一 `ResponseType` 信封,`data` 形态随动作(见下表)。 @@ -807,7 +807,7 @@ HTTP 状态码例外(非 200): 登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除,因此要移除它需先登出。 -**触发事件**:`event.config.changed` +**触发事件**:[`event.config.changed`](#event-config-changed-s→c) **请求体**: @@ -986,7 +986,7 @@ HTTP 状态码例外(非 200): 注册工作区并返回它。注册按根路径幂等:重复注册同一根路径会返回已存在的工作区,仅刷新 `last_opened_at`(保留已存名称),并广播 `event.workspace.updated` 而非 `event.workspace.created`。 -**触发事件**:`event.workspace.created`(根路径首次注册)或 `event.workspace.updated`(重复注册同一根路径) +**触发事件**:[`event.workspace.created`](#event-workspace-created-s→c)(根路径首次注册)或 [`event.workspace.updated`](#event-workspace-updated-s→c)(重复注册同一根路径) **请求体**: @@ -1025,7 +1025,7 @@ HTTP 状态码例外(非 200): 重命名工作区——仅修改显示名,根路径不变。 -**触发事件**:`event.workspace.updated` +**触发事件**:[`event.workspace.updated`](#event-workspace-updated-s→c) **请求体**: @@ -1063,7 +1063,7 @@ HTTP 状态码例外(非 200): 注销工作区。只移除注册表条目——磁盘上的目录不受影响。无请求体。 -**触发事件**:`event.workspace.deleted` +**触发事件**:[`event.workspace.deleted`](#event-workspace-deleted-s→c) **响应体**:`ResponseType<{ deleted: true }>`。 @@ -1214,7 +1214,7 @@ HTTP 状态码例外(非 200): 创建会话并返回。目标目录来自 `workspace_id`(已注册的工作区)或 `metadata.cwd`(首次使用时注册该工作区);两者同时提供时必须一致。 -**触发事件**:`event.session.created`;触碰工作区另触发 `event.workspace.updated`(首次经 `metadata.cwd` 注册时为 `event.workspace.created`) +**触发事件**:[`event.session.created`](#event-session-created-s→c);触碰工作区另触发 [`event.workspace.updated`](#event-workspace-updated-s→c)(首次经 `metadata.cwd` 注册时为 [`event.workspace.created`](#event-workspace-created-s→c)) **请求体**: @@ -1373,7 +1373,7 @@ HTTP 状态码例外(非 200): 更新会话档案:标题、自定义元数据以及 main agent 的配置。设置的标题会成为自定义标题,优先级高于生成的标题。 -**触发事件**:`session.meta.updated`(设置标题时)、`goal.updated`(`goal_objective` / `goal_control` 变更目标时) +**触发事件**:[`session.meta.updated`](#session-meta-updated-s→c)(设置标题时)、[`goal.updated`](#goal-updated-s→c)(`goal_objective` / `goal_control` 变更目标时) **请求体**: @@ -1423,7 +1423,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` 通过托管供应商的 `chat_title` 工具根据会话的提示词生成标题并应用。生成需要托管 OAuth 登录和 `auto_session_title` 实验开关;未提供 `force` 时,已有自定义标题或已生成标题的会话会上报为不可用。 -**触发事件**:`session.meta.updated` +**触发事件**:[`session.meta.updated`](#session-meta-updated-s→c) **请求体**: @@ -1455,7 +1455,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` 会话动作经同一条路由分发:路径尾部解析为 `{session_id}:{action}`,请求体按动作的 schema 校验。每个动作都会先解析会话,因此会话未知时都可能返回 `40401`。 -**触发事件**:`:fork` → `event.session.created`;`:compact` → `compaction.started`(随后进入 compaction 事件流,见 [agent 事件](#agent-事件));`:undo` → `session.meta.updated`;`:btw` → `agent.created`;`:archive` → `event.session.archived`;`:abort` / `:restore` 无 +**触发事件**:`:fork` → [`event.session.created`](#event-session-created-s→c);`:compact` → [`compaction.started`](#compaction-started-s→c)(随后进入 compaction 事件流,见 [agent 事件](#agent-事件帧));`:undo` → [`session.meta.updated`](#session-meta-updated-s→c);`:btw` → [`agent.created`](#agent-created-s→c);`:archive` → [`event.session.archived`](#event-session-archived-s→c);`:abort` / `:restore` 无 **响应体**:统一 `ResponseType` 信封,`data` 形态随动作(见下表)。 @@ -1527,7 +1527,7 @@ schema 还接受 `agent_config` 内的 `system_prompt`、`tools`、`mcp_servers` 创建子会话:fork 当前会话并记录为其子会话。适用与 `:fork` 相同的进行中轮次限制。 -**触发事件**:`event.session.created` +**触发事件**:[`event.session.created`](#event-session-created-s→c) **请求体**: @@ -1939,7 +1939,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 面向会话管理页的批量归档 / 恢复。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。只有请求体校验失败才会让整个请求失败(`40001`);其余情况按条返回。 -**触发事件**:`:archive` → `event.session.archived`(每个成功归档的会话一条);`:restore` 无 +**触发事件**:`:archive` → [`event.session.archived`](#event-session-archived-s→c)(每个成功归档的会话一条);`:restore` 无 **请求体**: @@ -2027,7 +2027,7 @@ main agent 的 Agent 循环运行在哪个运行时上的读取与切换。 向会话提交一条用户提示词。先校验媒体引用,然后把可选的覆盖项应用到目标 Agent——`profile`(与 `model` / `thinking` 一起绑定),接着是 `model`、`thinking`、`permission_mode` 和 `disabled_tools`——随后提示词入队;响应在提示词被接受后立即返回,不等待轮次执行。提供 `skills` 时,提示词以打包的 Skill 激活方式运行,而不是普通用户提示词。 -**触发事件**:`prompt.submitted`(随后进入轮次事件流,见 [agent 事件](#agent-事件))、`session.meta.updated` +**触发事件**:[`prompt.submitted`](#prompt-submitted-s→c)(随后进入轮次事件流,见 [agent 事件](#agent-事件帧))、[`session.meta.updated`](#session-meta-updated-s→c) **请求体**: @@ -2088,7 +2088,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 把排队的提示词插入进行中的轮次,让运行中的轮次立即消费它们,而不是先运行结束。 -**触发事件**:`prompt.steered` +**触发事件**:[`prompt.steered`](#prompt-steered-s→c) **请求体**: @@ -2120,7 +2120,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 单条提示词动作,经 `POST .../prompts/{tail}` 分发:`:abort` 中止运行中的提示词;`:steer` 把单条排队的提示词插入进行中的轮次(集合形式的单提示词版)。无请求体。 -**触发事件**:`:abort` → `prompt.aborted`;`:steer` → `prompt.steered` +**触发事件**:`:abort` → [`prompt.aborted`](#prompt-aborted-s→c);`:steer` → [`prompt.steered`](#prompt-steered-s→c) **响应体**:统一 `ResponseType` 信封:`:abort` → `{ aborted: true }`;`:steer` → `{ steered: true, prompt_ids: [prompt_id] }`。 @@ -2281,7 +2281,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 答复一个待处理的审批请求,让等待中的工具调用继续执行(或不执行)。 -**触发事件**:`event.approval.resolved` +**触发事件**:[`event.approval.resolved`](#event-approval-resolved-s→c) **请求体**: @@ -2374,7 +2374,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 回答一个待处理的提问。两个提问端点经同一条路由 `POST .../questions/{tail}` 分发:单独的提问 id 表示回答问题,`{question_id}:dismiss` 尾部表示忽略。 -**触发事件**:`event.question.answered` +**触发事件**:[`event.question.answered`](#event-question-answered-s→c) **请求体**: @@ -2418,7 +2418,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 忽略一个待处理的提问,不作回答。无请求体。 -**触发事件**:`event.question.dismissed` +**触发事件**:[`event.question.dismissed`](#event-question-dismissed-s→c) **响应体**:成功时 `ResponseType` 的 `code` 是 `40909` 而不是 `0`,`data` 为 `{ dismissed: true, dismissed_at: string }`——客户端必须特殊处理该端点的成功码。 @@ -2722,7 +2722,7 @@ schema 还接受共享消息格式中的 `tool_use`、`tool_result` 和 `thinkin 任务动作经 `POST .../tasks/{tail}` 分发:`:cancel` 取消运行中的任务;`:detach` 将运行中的前台任务转入后台而不终止它(等待该任务的工具调用立即以后台任务结果返回,轮次继续推进)。已在后台或已结束的任务上 `:detach` 为幂等空操作。无请求体。 -**触发事件**:`:cancel` → `task.terminated`(及派生的 `background.task.terminated`);`:detach` 无 +**触发事件**:`:cancel` → [`task.terminated`](#task-terminated-s→c)(及派生的 [`background.task.terminated`](#background-task-terminated-s→c));`:detach` 无 **响应体**:统一 `ResponseType` 信封:`:cancel` → `{ cancelled: true }`;`:detach` → `{ detached: boolean, status: string }`(本次确实转入后台时 `detached` 为 `true`,`status` 为调用后的任务状态)。 @@ -2970,7 +2970,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 在会话中激活技能——以技能内容加上 `args` 与附件在 main agent 上开启一个轮次。经 `POST .../skills/{tail}` 分发,`activate` 是唯一动作。 -**触发事件**:`skill.activated`(随后进入轮次事件流,见 [agent 事件](#agent-事件)) +**触发事件**:[`skill.activated`](#skill-activated-s→c)(随后进入轮次事件流,见 [agent 事件](#agent-事件帧)) **请求体**: @@ -3086,7 +3086,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 安装插件并返回其摘要。 -**触发事件**:`event.plugin.changed` +**触发事件**:[`event.plugin.changed`](#event-plugin-changed-s→c) **请求体**: @@ -3129,7 +3129,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 插件动作经单一路由分发:尾部按 `{plugin_id}:{action}` 解析,动作为 `enable`(启用)/ `disable`(停用但不移除)/ `remove`(移除)。无请求体。 -**触发事件**:`event.plugin.changed` +**触发事件**:[`event.plugin.changed`](#event-plugin-changed-s→c) **响应体**:`ResponseType<{ ok: true }>`。 @@ -3228,7 +3228,7 @@ PTY(伪终端)接口;仅在 loopback 绑定时挂载(非 loopback 绑定 在后台开始安装能力并立即返回当前状态(`install.running` 为 `true`);轮询 `GET /api/v1/capabilities/{capability_id}` 查看进度。幂等。经 `POST /api/v1/capabilities/{tail}` 分发,`install` 是唯一动作。无请求体。 -**触发事件**:`event.capability.changed`(安装进度,易失事件) +**触发事件**:[`event.capability.changed`](#event-capability-changed-s→c)(安装进度,易失事件) **响应体**:`ResponseType<`[T-CapabilityStatus](#t-capabilitystatus)`>`。 From 7056aebe88db3b3adc9decc2c01e7a7fc7a55353 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 2 Sep 2026 21:11:38 +0800 Subject: [PATCH 47/47] docs(zh): drop the stale new-implementation label on transcript frames --- docs/zh/reference/server-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/reference/server-api.md b/docs/zh/reference/server-api.md index f7281b5f1a0..75c7677ea61 100644 --- a/docs/zh/reference/server-api.md +++ b/docs/zh/reference/server-api.md @@ -4810,7 +4810,7 @@ locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批 | [控制帧](#控制帧) | 双向 | 12 活跃 + 7 死声明 | `ServerSystemMessage`(下行)/ `ClientControlMessage`(上行) | 握手、订阅、心跳与恢复 | | [event.\* 事件帧](#event-事件帧) | S→C | 19 | 13 型有接口正名,6 型未命名 | 工作区 / 会话 / 配置等状态同步 | | [agent 事件帧](#agent-事件帧) | S→C | 51 | `AgentEvent` | 轮次生命周期、状态与 subagent 内容 | -| [transcript 帧](#transcript-帧) | S→C | 2 | `TranscriptResetEvent` / `TranscriptOpsEvent` | 主会话内容的结构化流(新实现) | +| [transcript 帧](#transcript-帧) | S→C | 2 | `TranscriptResetEvent` / `TranscriptOpsEvent` | 会话时间线的结构化投影(聊天渲染数据源) | | [terminal 帧](#terminal-帧) | S→C | 2 | — | 死协议 | 事件帧共享外层信封 `EventEnvelope`;`payload` 为各事件自己的载荷: