#SSE v2 协议
客户端向聊天、反馈和 resume 请求发送 X-iGraph-Stream-Version: 2,无需用户身份头。浏览器使用 fetch 流读取器;原生 EventSource 无法直接发送这些 POST 请求及自定义协议头。服务端返回 text/event-stream。
X-iGraph-Stream-Version: 2
Accept-Language: zh-CN
Content-Type: application/json| 聊天字段 | 类型 | 说明 |
|---|---|---|
| message | string | 必填用户消息。 |
| start_request_id | UUID | null | 为每个新请求生成 UUID;重试同一请求时保留。 |
| attachments | array | null | 附件引用包含 file_token 和可选 filename。 |
| output_format | chat | report | json | 默认 chat。 |
Backend 使用原生后台流式 Run。stream/background 是前端发送的兼容字段;ChatReq 的核心契约以上述字段和 reasoning_mode / planning_mode 等模型字段为准。
v2 的每个 SSE data 帧包含 protocol_version、session_id、run_id、event_index 和 events。一个原始事件产生的多个界面事件放在同一 events 数组中,客户端必须完整应用该数组后才推进游标。event_index 为 null 的观察状态事件不推进原始事件游标;心跳是 SSE 注释,不是业务消息。收到 EOF 时未以空行结束的残缺帧不能当成完整事件应用。
data: {"protocol_version":2,"session_id":"SESSION_ID","run_id":"RUN_ID","event_index":12,"events":[{"type":"tool_progress","tool":"train","call_id":"JOB_ID","progress":{"epoch":2,"epochs":10}}]}
聊天请求通过 Accept-Language 传递发送时的界面语言,并记录为本轮 response_language。切换中文或英文影响下一次发送的回复语言,不会重写已有消息。
#断线恢复
- 同页面断流:保留已有消息,从最后完整应用的 event_index 续接。消息、工具、计划与游标应在同一状态事务提交。
- 刷新或消息内存丢失:从 last_event_index=-1 暂存重建当前 Run,追平后发布,保留其他历史消息。
- HTTP 409 REPLAY_UNAVAILABLE 或 stream_recovery_required:保留内容,轮询 snapshot,直到 snapshot_complete=true 后原子替换阶段消息。
- 快照 resume_cursor 当前为 null,不能将快照消息与旧游标后的原始增量拼接。使用快照恢复暂停阶段后,该 Run 保持快照模式。
curl -N -X POST \
"http://localhost:21108/api/sessions/SESSION_ID/runs/RUN_ID/resume?last_event_index=12" \
-H "X-iGraph-Stream-Version: 2"原始事件缓存依赖运行进程。服务重启或缓存裁剪后,可从已保存消息与完整快照恢复可见结果,但这不代表业务计算从断点重新启动。快照未完整时保留当前内容并显示恢复状态,避免把中间结果当成最终回答。
#取消与状态确认
/api/sessions/{session_id}/runs/cancel先调用 GET /api/capabilities。最新 .env.example 启用 IGRAPH_RUN_CANCEL_ENABLED;环境未设置时回退 false,Backend 还会检查运行服务与图服务的能力。run_cancel_v1 为 true 时才启用运行停止,job_cancel_v1 为 true 时才启用作业停止,edit_latest_turn_v1 决定最新一轮编辑是否可用。取消请求携带 target.run_id 或 target.start_request_id 二选一,并提供 cancel_request_id;这些字段必须是合法 UUID。同一次取消重试保留相同 cancel_request_id。
{
"target": {
"run_id": "4d227ea8-c8ca-4f0d-b5e4-81a44de7bd4c"
},
"cancel_request_id": "f186c422-5eed-4d0c-a4b9-e7d459124fd0"
}取消后查询 GET /api/sessions/{sid}/runs/control?run_id={rid}。execution_stopped 表示执行已停止,terminal_persisted 表示最终状态已保存;只有两者都满足且服务端允许发送时才恢复编辑。AbortController 只断开观察连接,不等于取消服务器任务。
取消接口返回 200 只说明 execution_stopped 已为 true;未停止时返回 202。仍需同时确认 terminal_persisted 和 can_send,才能认定客户端已可以继续。
作业停止使用 POST /api/sessions/{sid}/jobs/{jid}/cancel,正文包含 cancel_request_id;随后读取同一作业的 /control。运行停止和单个作业停止的目标范围不同,不应相互替代。
#人工审批
/api/sessions/{session_id}/feedback/stream当前界面提供批准与拒绝。API 的 decision 还支持 modify,可同时提交 patched_args。请求包含 run_id、request_id、decision_id,并可附 tool_call_id、tool_name、comment;标识和工具信息应来自当前暂停请求,不应从旧卡片猜测。普通 approve 使用服务端保存的原始参数,modify 才采用替换参数。
反馈继续原 run_id,不创建新聊天请求。前端在等待或提交审批时阻止发送新消息,接收确认后再恢复观察。过期、不匹配或已处理的暂停请求可能返回冲突;响应丢失时先读取权威状态,避免重复提交图修改。工具执行审批与技能候选批准使用不同接口。