docs(api): api-client → v0.57 补登 steer_ack(13.4.5 漏登记,Android 端 diff 版本号时发现)
- §3 下行帧清单 + 角色门第 ② 档加入 steer_ack;新增 **§3.14**(触发/载荷/语义「已吃进·未正面回答 ⇒ 灰态」/ 回合内边界/与 pending_ack·session_busy 的分工/不发的四种情形/只吃本编排器排队过的消息/兼容性/ **客户端现状=Web 前端尚无 handler** 的诚实边界/经 hub 广播不经 bus) - §5 新增 v0.57 条目:I1/I2/I3 不变量、注入范围(只进本轮视图,不进 checkpoint 与记忆面)、失败让路、 `graph_update` input 节点 `steered:true` 增量键、实现落点、兼容性与变异验证 - api-reference §6.4 角色门与下行表补 steer_ack(指向 api-client §3.14,不复制第二份契约); §6.5 补一句「回合内 steer」(否则 pending 语义会被读成「只能等下一个回合」) - 核对方式:逐行「文档口径 ↔ 代码依据」表(帧名/载荷/atStep 1 基/角色门/不经 bus/注入不写回/未接线逐字不变) - 登记待补:§3.5 的 props 清单缺 `steered`;design/15 的接口表写 HistoryReader 而实现是 SteerSource(已滞后)
This commit is contained in:
1 parent
3dc1232bc2
commit
6c164f920b
2 files changed
+25
-5
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Cyrene v2 后端 API 参考(api-reference.md)
|
||||
|
||||
> **权威归属(先读这条)**:**契约以 `Docs/api-client.md` 为准**——那是版本化的跨平台客户端契约,每个端点的形状 / 语义 / 版本变更都记在那里(当前 `v0.56`)。**本文件是内部与运维参考**:端点全集索引 + 示例 + 部署细节。**凡是与 api-client 重复的契约性描述,一律以 api-client 为准(本文件不再维护第二份契约);发现两者不一致时,改本文件而不是改 api-client。**
|
||||
> **权威归属(先读这条)**:**契约以 `Docs/api-client.md` 为准**——那是版本化的跨平台客户端契约,每个端点的形状 / 语义 / 版本变更都记在那里(当前 `v0.57`)。**本文件是内部与运维参考**:端点全集索引 + 示例 + 部署细节。**凡是与 api-client 重复的契约性描述,一律以 api-client 为准(本文件不再维护第二份契约);发现两者不一致时,改本文件而不是改 api-client。**
|
||||
> **本文件的正确用法**:查「有哪些端点、大致形状、错误码、部署注意事项」可以;**写客户端代码时请以 `Docs/api-client.md` 为准**,本文件的字段表 / 示例可能滞后。
|
||||
> **历史包袱(如实)**:本文件长期自称「全部后端 API 的唯一详细参考 / 超详细主文档 / 每变更必同步」,但实际**系统性滞后于实现与 api-client**(2026-10-03 的 16 路 design-vs-code 审计结论)。本次已修正与实现**直接矛盾**的陈述、并把若干复述型段落改为引用 api-client;**§1 的 REST 端点表已于 2026-10-04 按 `internal/services/gateway/routes.go` 逐条核对并补登记**(补上此前缺失的 `POST /auth/refresh`、`POST /auth/logout`、`POST /upload`、`GET /files/{name}`、三支 `/audio/*`、`GET /admin/llm/catalog`、`GET /admin/observability/logs`、`GET /admin/notifications`、`GET /admin/plugins/installed`、`GET|PUT /admin/owner-profile`、`POST /admin/automations/reminders`)。**仍未补全的是 WS 事件帧清单**:§6.4 自述「并非全表」,`DevDocs/audit/00-总览.md` §4④ 列出的 `session_read` / `message_edited` / `message_deleted` 等仍未逐行登记。
|
||||
> **其余仍成立**:所有字段名、取值、鉴权规则、状态码最终**以代码为准**(`internal/services/gateway/*.go`);契约变更版本化(REST 走 `/api/v1`,破坏性变更升 v2),不得破坏既有客户端(版本化承诺本身记在 api-client §5)。
|
||||
@@ -1138,7 +1138,7 @@ curl -s -X POST http://<host>:8080/api/v1/admin/system/restore \
|
||||
|
||||
### 6.4 下行事件全表
|
||||
|
||||
> **角色门(design/11 §7.1,fail-closed)**:下行帧按类型分档,收口在 `internal/services/gateway/ws_frame_scope.go` 的 `frameReachesAll`(**唯一一处判定**,各调用点不自行决定可见性)。**只有 7 个不含内容的状态机信号**发给**所有已认证连接**(含 `viewer`):`session_busy` / `pending_ack` / `pending_drain` / `session_idle` / `session_interrupted` / `pending_full` / **`session_read`**。**其余全部只发 `owner`+`admin`**:流式内容(`message.*` / `thinking.*` / `tool_call.*` / `tool_execution.update` / `stream_chunk` / `stream_end`)、持久化(`message_persisted` / `message_edited` / `message_deleted` / `channel_persisted`)、系统内部(`graph_update` / `subagent_event` / `task_output` / `task_done` / `tool_used` / `capacity_awaken` / `mode_switch`)、私有状态(`mood` / `device_update` / `reminder` / `proactive_message`)、**可观测推送(`observability_log` / `observability_trace` / `observability_metrics`,v0.55)**、**`chat_duplicate`(v0.56/G4:虽由编排器状态通道下发,但未进白名单)**;**未登记的新帧类型默认只发 owner/admin**。**本表并非全表**:`session_read` / `message_edited` / `message_deleted` 等已实现事件尚未逐行登记于此;**权威清单与逐帧口径见 `Docs/api-client.md` §3**。
|
||||
> **角色门(design/11 §7.1,fail-closed)**:下行帧按类型分档,收口在 `internal/services/gateway/ws_frame_scope.go` 的 `frameReachesAll`(**唯一一处判定**,各调用点不自行决定可见性)。**只有 7 个不含内容的状态机信号**发给**所有已认证连接**(含 `viewer`):`session_busy` / `pending_ack` / `pending_drain` / `session_idle` / `session_interrupted` / `pending_full` / **`session_read`**。**其余全部只发 `owner`+`admin`**:流式内容(`message.*` / `thinking.*` / `tool_call.*` / `tool_execution.update` / `stream_chunk` / `stream_end`)、持久化(`message_persisted` / `message_edited` / `message_deleted` / `channel_persisted`)、系统内部(`graph_update` / `subagent_event` / `task_output` / `task_done` / `tool_used` / `capacity_awaken` / `mode_switch`)、私有状态(`mood` / `device_update` / `reminder` / `proactive_message`)、**可观测推送(`observability_log` / `observability_trace` / `observability_metrics`,v0.55)**、**`chat_duplicate`(v0.56/G4:虽由编排器状态通道下发,但未进白名单)**、**`steer_ack`(v0.57:忙时排队消息被在飞回合吃进同一回合的回执,携 `messageId`/`atStep`,未进白名单 ⇒ fail-closed 只发 `owner`+`admin`;帧壳带 `sessionId`、不带 `turnId`/`seq`,经 hub 直接广播、不经 bus)**;**未登记的新帧类型默认只发 owner/admin**。**本表并非全表**:`session_read` / `message_edited` / `message_deleted` 等已实现事件尚未逐行登记于此;**权威清单与逐帧口径见 `Docs/api-client.md` §3**。
|
||||
>
|
||||
> **来源标记**:`[direct]` 网关直接 emit;`[relay]` hub 从 bus `ws.>` 规范化(任意 `ws.X` 主题 → 类型 `X`);`[bridge]` 桥接 producer 主题;`[target]` 仅定向特定连接。
|
||||
|
||||
@@ -1164,6 +1164,7 @@ curl -s -X POST http://<host>:8080/api/v1/admin/system/restore \
|
||||
| `session_interrupted` | direct(编排) | `{sessionId, mode, dropped}` | 用户 `interrupt`。**v0.56/A2**:帧形状零变化——`scope:"all"`(省略 / 空串同义)= 任务取消 + pending 清空(`mode=idle`、`dropped`=清空条数);`scope:"current"` = **只取消任务、保留 pending**(`dropped` 恒 `0`、`mode` 为当时忙碌通道) |
|
||||
| `pending_full` | direct(编排) | `{sessionId, mode, max}` | 单会话 pending 达上限(默认 5)拒绝入队 |
|
||||
| `chat_duplicate` | direct(编排) | `{sessionId, clientMsgId, messageId}` | **v0.56/G4(新增帧)**:同一会话内**重复到达**的 `clientMsgId` 的明确回执——**不落库、不起回合、不发任何内容帧**。帧壳带 `sessionId`;**未进 7 个状态机信号白名单 ⇒ fail-closed 只发 `owner`+`admin`**(发过该 `clientMsgId` 的客户端用它把本地乐观气泡对齐到既有 `messageId`,其它客户端按值自行忽略) |
|
||||
| `steer_ack` | direct(编排) | `{messageId, atStep}`(帧壳带 `sessionId`,`data` 内不重复该键) | **v0.57(新增帧)**:忙时会话里新到的用户消息**已被在飞回合吃进同一回合**(已从 pending 移除、**尚未被正面回答**)——`messageId` = 那条用户消息的**权威 id**(与 `message_persisted` 的 `data.message.id` 同源)、`atStep` = 吃进它的**模型步序号(1 基)**;一批吃进 N 条发 N 帧(不合并)。客户端把对应气泡渲染为「已读、未答」的**灰态**,直到该回合的 `message.*`/`turn.end` 到达(不需要第二个确认帧)。**只在回合内边界**产生(一次模型步与其工具批次都已结束、下一次模型调用尚未开始;无匹配消息则一帧不发);**不带** `turnId`/`seq`,经 hub 直接广播、**不经 bus**;**未进 7 个状态机信号白名单 ⇒ fail-closed 只发 `owner`+`admin`**(`viewer` 收不到)。详见 api-client §3.14 |
|
||||
| `message_persisted` | direct | `{message:historyMessage}`(sessionId 设) | 每条 user/assistant 消息落库后广播(主会话 `web`/`web:<uuid>`),thinking 剥离 |
|
||||
| `channel_persisted` | direct | `{message:historyMessage}`(sessionId=`sess-xxx`) | 群聊/陌生人(非主人)消息落库后广播,供 IM 适配器日志页 |
|
||||
| `voice_output` | direct/target | `{audio, format, text, reply}` | 语音合成回复(定向回请求连接) |
|
||||
@@ -1209,6 +1210,7 @@ curl -s -X POST http://<host>:8080/api/v1/admin/system/restore \
|
||||
### 6.5 会话编排状态(design/15,`data.sessionId` 区分)
|
||||
|
||||
- **语义**:同一会话 `chat` 到达时若「她忙」(跑 loop/工具/子代理/长回复)→ 新消息**不阻塞**、入该会话 pending(上限默认 5);状态经上述 `session_busy`/`pending_ack`/`pending_drain`/`session_idle`/`session_interrupted`/`pending_full` 推给前端,供「正在做 xx… 有新消息稍后回」轻状态展示。
|
||||
- **回合内 steer(v0.57)**:pending 里的消息**不是只能等下一个回合**——在飞回合会在**回合内边界**(上一次模型步与它那一批工具调用都已结束、下一次模型调用尚未开始)把它那批已落库的消息**注入同一回合**(**绝不新开第二个回合**),并逐条下发 `steer_ack`(§6.4)告知「**队列里哪一条已被本回合吃进**」(`messageId` 级;吃进=已从 pending 移除,但**尚未被正面回答** ⇒ 前端呈灰态)。`pending_ack`/`session_busy` 描述**队列深度与忙闲**,`steer_ack` 描述**哪一条被吃进**;无可注入消息的边界不发任何帧。详见 api-client §3.14。
|
||||
- **续接**:忙完重开时新回合**带上上一轮上下文**(`tail` 默认 20 条),非清空重来。
|
||||
- **mode** 取值:`idle` / `thinking` / `executing` / `subagent`。
|
||||
- REST 同步路径(§3.1)在忙时返回 `202 queued` / 满 `409 chat_busy`,与这些 WS 状态事件一致。
|
||||
|
||||
Reference in new issue
Block a user