Files
Cyrene_v2/Docs/api-client.md
T
Aska 1bf60c1ae4
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat: IM式跨端实时同步——message_persisted 广播 + 前端按id去重追加
- history.Store 新增 AppendFull(返回含 id/createdAt 的完整消息),Append 签名不变
- session_orchestrator 加可空 OnPersisted;persistUserMessages/persistAssistantReply 落库后回调广播
- server.go newOrchestrator 接 OnPersisted → hub.broadcast message_persisted(thinking 剥除)
- 前端 ws.ts 加 message_persisted case(仅 activeSessionId 匹配才处理);appendOrUpdateMessage 升级为 id 精确upsert+内容/时间归一
- 实测:双 WS,A stream 发消息,B 免刷新收到 user+assistant 各1条(count=2 PASS)
- 红线: 身份仍靠 actor 元数据,不靠提示词;用户/助手消息、本端/异端统一路径
2026-09-07 04:16:29 +08:00

22 KiB
Raw Blame History

Cyrene v2 客户端 API 文档(用户侧)

面向: Web 前端 / 移动端原生客户端 / IM 桥接等跨平台客户端开发者。 维护铁律: 每实现/变更一个 API(REST 端点、WS 事件、admin API)立即更新本文件;契约变更必须版本化,不破坏既有客户端。 状态: gateway 已在 M8 落地核心端点;M9 前端按此开发。✅ = 已实现,🕐 = 规划。


0. 基础约定

  • Base URL: http://<host>:8080(网关唯一对外端口;生产一般经反代/HTTPS)。
  • 版本: REST 全部挂在 /api/v1/{resource};未来破坏性变更升 v2。
  • 认证: Authorization: Bearer <JWT>(RBAC:owner/admin/viewer);管理端另支持 X-API-Key。
  • 响应统一: {"data": ...} / {"error": {"code": <string>, "message": <string>}};状态码 200/201/204/400/401/403/404/429/500。
  • 错误码:业务错误带 code 字符串(如 unauthorized / not_found),便于客户端分支。

1. REST 端点(公开)

# 端点 方法 认证 状态 说明
1 /api/v1/auth/login POST 否 ✅ {username,password} → {data:{token,jwt}}(24h,owner)
2 /api/v1/health GET 否 ✅ 健康检查 {data:{status:"ok"}}
3 /api/v1/chat POST JWT ✅ {text,image?,stream?} → {data:{reply}};stream:true 时经 WS 触发流式。image 为 base64 data: URI 或 http(s) URL,入视觉真推理(design/06)。会话编排(design/15):非流式且该会话「正忙」时不阻塞,返回 202 {data:{queued:true,queueDepth}}(稍后按上下文续接);待处理队列满时返回 409 {error:{code:"chat_busy"}}
4 /api/v1/sessions GET JWT ✅ {data:[session...]}。会话持久化(design/16):注入 HistoryStore 后返回持久化会话元数据 `{data:[{id,type("main"
5 /api/v1/sessions POST JWT(owner/admin) ✅ 新建次级会话 → 201 {data:{sessionId}}(sessionId="web:<uuid>");未注入 HistoryStore 回 501 not_implemented
6 /api/v1/sessions/{id}/messages GET JWT(owner/admin) ✅ 热分页拉历史:?limit=&before= 默认 limit=50(上限 200)、before=上一页最旧 createdAt(毫秒),按时间倒序 {data:[{id,sessionId,role,content,mode?,mood?,image?,thinking?,createdAt}]};非法 limit/before 回 400;未注入 HistoryStore 回 501
7 /api/v1/sessions/{id} DELETE JWT(owner/admin) ✅ 删除次级会话及其消息 → {data:{deleted:<id>}};主会话不可删回 403 forbidden;未注入 HistoryStore 回 501
8 /api/v1/personas GET JWT ✅ {data:[persona...]}

2. REST 端点(管理,/api/v1/admin/*)

仅供管理面板与授权客户端;RBAC:owner/admin/viewer(viewer 只读、写 403);写操作全程审计。

# 端点 方法 状态 说明
1 /api/v1/admin/personas GET ✅ 人格列表
2 /api/v1/admin/sessions GET ✅ 会话列表
3 /api/v1/admin/memories GET ✅ 记忆列表(检索/编辑随 M10 扩展)
4 /api/v1/admin/plugins GET ✅ 插件/能力列表(含 MCP/渠道)
5 /api/v1/admin/plugins/policy POST ✅ 写工具策略(owner-only,审计)
6 /api/v1/admin/channels GET ✅ 渠道列表/健康
7 /api/v1/admin/iot GET ✅ IoT 设备列表
8 /api/v1/admin/users GET/POST ✅(GET) 用户/角色/API key(GET 已实现;POST 创建用户/签发 key 随 M10 落地)
9 /api/v1/admin/llm GET/PUT ✅(GET) LLM 模型/路由/降级(GET 已实现,APIKey 脱敏;PUT 热重载 M10)
10 /api/v1/admin/automations GET/POST ✅(GET) 自动化与提醒(GET 已实现;POST 创建 M10)
11 /api/v1/admin/backthink GET ✅ 后台思考记录
12 /api/v1/admin/rag GET ✅ 知识库文档列表(分块/嵌入状态);带 ?query= 时并入检索结果
13 /api/v1/admin/rag/query POST ✅ 知识库检索(真实检索;配置向量增强走语义路径)
14 /api/v1/admin/rag/delete POST 🕐(写) 删除知识库文档;写操作 M10,当前返回 501 not_implemented
15 /api/v1/admin/observability/metrics GET ✅ 网关请求指标(总数/QPS/延迟/方法·路径·状态计数/LLM·子代理计数)
16 /api/v1/admin/observability/trace GET ✅ 最近 trace span(环形缓冲,默认 512 条)
17 /api/v1/admin/observability/audit GET ✅ 审计记录(who/what/when/result,SQLite 持久化)

M10 前端契约补充(管理面板):GET /api/v1/admin/users · GET /api/v1/admin/llm · GET /api/v1/admin/automations · GET /api/v1/admin/backthink · GET /api/v1/admin/rag · POST /api/v1/admin/rag/query · GET /api/v1/admin/observability/metrics · GET /api/v1/admin/observability/trace · GET /api/v1/admin/observability/audit 已实现,返回真实数据;GET /api/v1/admin/logs · GET /api/v1/admin/system 仍🕐未实现(前端按契约封装、后端 404 时显示"待实现"壳,不报错)。写操作已补齐(见下方「管理面板写操作契约」):人格/API key/设备控制/自动化/LLM 测试/渠道连接与识别测试/记忆检索/会话导出/插件卸载真实持久化或真实生效;仍为后置 M10:新增用户、IoT 场景与规则、插件安装(需源码清单)、主人档案保存、系统设置、知识库上传/删除——后端如实返回 501 not_implemented,不伪造成功。

管理面板写操作契约(POST/PUT/DELETE /api/v1/admin/*,均 owner-only,读为 owner/admin;写操作经 audit 落 audit_logs;成功 {data} / 失败 {error:{code,message}}):

  • POST /admin/personas body {id,name,role,systemPrompt?,characterRef?,modes?/mode?,memoryNamespace?} → 201 {data:{id,name,character,isDefault,mode,memoryNamespace}}(注册进 persona registry + 持久化到 configs/personas/<id>.yaml);id 已存在回 409 duplicate。
  • PUT /admin/personas/{id} body 同上(不含 id)→ 200 {data:PersonaSummary};不存在回 404。
  • POST /admin/users → 501 not_implemented(无持久用户表,当前为单 admin + APIKey 现状)。
  • POST /admin/users/apikey body {role:"owner|admin|viewer"} → 201 {data:{id:<掩码>, key:<明文·仅此一次>, role}}。key 仅此响应出现一次。
  • DELETE /admin/users/apikey/{id}(id=列表掩码)→ 200 {data:{id,revoked:true}};未命中 404。
  • POST /admin/iot/{id}/control body {action,params?} → 200 {data:{id,name,type,state,online}}(真实下发到 IoT provider);404 设备不存在 / 400 动作不支持或参数错 / 409 设备离线。
  • POST /admin/iot/scenarios、POST /admin/iot/rules → 501 not_implemented(IoT 无场景/规则存储)。
  • POST /admin/automations body {name,kind:"cron|event",expression} → 201 {data:{id,name,kind}}(真实注册规则);无效 cron/规则回 400 invalid_cron|invalid_rule。
  • POST /admin/automations/{id}/run → 200 {data:{id,output}}(手动触发);404。
  • DELETE /admin/automations/{id} → 200 {data:{id,deleted:true}};404。
  • POST /admin/llm body {name,model,baseUrl?,multimodal?,fallback?} → 201 {data:{provider,temporary:true}}。临时,进程生命周期,不入 config、不绑定模型路由。
  • POST /admin/llm/test body {provider?,baseUrl,model,apiKey?,prompt?} → 200 {data:{ok,provider,model,reply,tokens}}(真实模型调用);无效/失败回 400 invalid_provider / 500 llm_test_failed。API key 仅本次请求内使用,不落库、不进 wire。
  • POST /admin/channels/open、POST /admin/channels/close body {name} → 200 {data:{name,connected}}(真实 Connect/Disconnect);404(未注册渠道)/500(凭据缺失等连接失败)。
  • POST /admin/channels/test body {platform?,accountId,isGroup} → 200 {data:{role,owner,isGroup,env,verdict}}。结构性判定:channel 层 actor 元数据 × configs/users/owner.yaml 白名单,绝不靠提示词。
  • POST /admin/plugins/install → 501 not_implemented(需插件源码清单)。
  • POST /admin/plugins/uninstall body {name} → 200 {data:{name,uninstalled:true}}(真实从 registry 移除);404。
  • POST /admin/memories/search body {query,personaId?,topK?} → 200 {data:{query,personaId,semantic,hits:[{id,scope,text,score}]}}。真实检索(keyword×衰减);语义/向量路径需主会话注入 vector index(semantic 当前恒 false,诚实反映未接向量器)。
  • GET /admin/sessions/{id}/export → 200 {data:{session:{platform,channelId,sessionId,actorRole,owner,isGroup,memWritable}}};404。当前导出会话身份元数据(完整消息转录由 M10 提供)。

知识库 RAG 契约:

  • GET /admin/rag → {"data":{"documents":[{id,name,desc?,chunks,embedded}],"hits"?:[{docId,docName,chapter?,text,score,semantic}]}}。hits 仅在携带 ?query= 时出现;embedded 反映部署是否配置向量增强(未配置为待嵌入)。
  • POST /admin/rag/query body {"query":"..."} → {"data":{"query":"...","hits":[{docId,docName,chapter?,text,score,semantic}]}}。检索走项目索引关键词+行上下文;配置 pgvector/向量增强时并入语义/向量命中(semantic:true)。
  • POST /admin/rag/delete body {"id":"..."} → 写操作 M10,返回 501 {"error":{"code":"not_implemented",...}}。

可观测性契约(GET /api/v1/admin/observability/*,均需 owner/admin,?limit=N 缺省 50、上限 500):

  • GET /metrics → {"data":{"totalRequests","qps","avgLatencyMs","maxLatencyMs","perMethod{}","perPath{}","statusCounts{}","llmCalls","subagentEvents"}}。qps 为近 1 秒窗口计数;llmCalls/subagentEvents 由实际观测到的 trace span 按 kind 累计(Tracer 未注入时为 0)。Token/成本后端不统计、不返回(不伪造指标)。
  • GET /trace?limit=100 → {"data":[{id,parentId?,name,kind,status,startedAt,endedAt?,durationNs,props?,events?]}。kind ∈ llm_call|tool_call|orchestration|state_transition|subagent|memory|guardrail;durationNs 为纳秒;events 为 [{time,type,props?}]。
  • GET /audit?limit=100 → {"data":[{id,who,what,when,result}]}。id 为整数自增;when 为 RFC3339;来源为 SQLite audit_logs 表(未注入 AuditStore 时退化为进程内存)。

3. WebSocket /ws/chat(实时)

  • 握手: ws://<host>:8080/ws/chat?token=<JWT> 或 Authorization: Bearer;未认证在握手前回 401 JSON。

  • 下行(服务端→客户端): 经 bus 广播 {type:"<event>", data:..., turnId?, seq?, sessionId?}(turnId/seq 为流式关联字段,见 §3.1;sessionId 为会话持久化(design/16)新增,能确定会话的事件带上,供客户端按激活会话过滤)——message.start/delta/end / thinking.start/delta/end / tool_call.start/delta/end / tool_execution.update(结构化流,design/04 §1.1),以及向后兼容的 stream_chunk / stream_end / thinking(思维链) / mood / reminder / device_update / tool_used(工具回显) / subagent_event / graph_update / message_persisted(会话持久化增量,见 §3.3)。会话编排状态(design/15,均为广播,data.sessionId 区分会话):session_busy / pending_ack / pending_drain / session_idle / session_interrupted / pending_full(见 §3.2)。语音回复走 voice_output(定向回请求连接,非广播)。

    history 回放事件(design/16,新增):WS 握手升级成功后、该连接下一帧即收到 {type:"history", sessionId:"web", data:{messages:[{id,sessionId,role,content,mode?,mood?,image?,createdAt}]}}——回放主会话最新 50 条(thinking 已剥离,不泄给非 owner;默认主会话,次级会话由客户端按激活会话走 GET /sessions/{id}/messages 拉取)。客户端据此在重连/新开连接后补全上下文。

3.1 结构化流事件(message.* / thinking.* / tool_call.* / tool_execution.*)

  • 事件壳:{type, turnId?, seq?, data}, data 为类型化结构(非 any)。seq 为 hub 级单调递增序号,供客户端将一次突发的流式事件排序关联。
  • message.start({index}) / message.delta({delta, index}) / message.end({index}):正文段。delta 为正文 token 增量;客户端对 message.delta 累加到当前消息正文;message.start/end 划定正文段边界,不结束整轮(结束由 stream_end 负责)。
  • thinking.start({index}) / thinking.delta({delta, index}) / thinking.end({index}):思维链段(前端折叠块)。thinking.delta 累加增量。
  • tool_call.start({id, index}) / tool_call.delta({id, index, delta}) / tool_call.end({id, index}):工具调用中间态;tool_call.delta 携带参数增量(如 Anthropic input_json_delta)。
  • tool_execution.update({id, index, delta}):工具执行进度/局部输出(保留,工具循环 §1.2 后置实现)。
  • 向后兼容:未映射/无法确定的事件仍走 stream_chunk + stream_end(非流式回退路径)。
  • 上行(客户端→服务端): mode_switch / chat(跑 loop 并广播流式) / voice_input / subagent_ask / task_output_query / interrupt。
  • interrupt(上行,客户端→服务端):{sessionId} → 会话编排器中断(design/15 §3)——取消该会话当前在跑的任务(context cancel)、清空其待处理队列、回 session_interrupted;用户说「停下/算了/换个话题」时发。命中空闲会话为 no-op。
  • voice_input(上行,客户端→服务端):_{audio?, format?, text?, sessionId?}。audio 为 base64(或 data: URI)音频,format 为其编码(wav/mp3/ogg);text 为已转写文本时跳过 STT。服务端走 STT→agent 聊天→TTS(design/06 §1),回复经 voice_output 定向回该连接。无注入语音服务时回 error 帧(voice unavailable)。
  • voice_output(下行,服务端→客户端):{audio, format, text, reply}。audio 为 base64 合成音频,format 为其编码,text 为识别文本,reply 为助手回复文本。
  • 向后兼容:未映射/无法确定的事件仍走 stream_chunk + stream_end(非流式回退路径)。

3.2 会话编排状态事件(design/15)

  • 触发:同一会话内,chat 到达时若「她忙」(正在跑 loop/工具循环/子代理/长回复)→ 新消息不阻塞、入该会话 pending;这一层的状态经以下事件推给前端,供「正在做 xx… 有新消息稍后回」轻状态展示。
  • session_busy:会话进入忙碌态({sessionId, mode},mode ∈ idle|thinking|executing|subagent)。
  • pending_ack:忙时新消息已入队({sessionId, mode, queueDepth})——「收到,稍后回」。
  • pending_drain:忙完开始消费下一待处理消息({sessionId, mode, queueDepth})。
  • session_idle:会话回到空闲、队列清空({sessionId, mode})。
  • session_interrupted:用户 interrupt 中断,当前任务取消、pending 清空({sessionId, mode, dropped})。
  • pending_full:单会话 pending 达上限(默认 5)拒绝入队({sessionId, mode, max})——防无限积压(design/15 §4)。
  • 上下文续接:忙完重开时新回合带上一轮上下文({mode, queueDepth} 之外的续接由服务端完成),非清空重来(design/15 §2.2)。

3.3 消息持久化增量事件(message_persisted,design/16)

  • 触发:每一条 user / assistant 消息落库后由编排层广播(persistUserMessages 在提交时写用户消息、persistAssistantReply 在回合落定时写助手消息)。
  • 载荷:{type:"message_persisted", sessionId, data:{message:{id, sessionId, role, content, mode?, mood?, image?, createdAt}}}——role ∈ user|assistant;id 为后端生成的消息 id(客户端据此去重);thinking 已剥离(design/16 §6)。
  • 客户端处理:仅当 data.message.sessionId === activeSessionId(激活会话)时处理;按 id upsert——本端已预建的同 role 乐观气泡(本地 uid 无后端 id)被归一(uid → 后端 id),异端无本地气泡则直接追加,两者最终收敛为同一条 id 相同的消息,「A 发消息、A 与 B 都无需刷新且各出现一次」。

4. 客户端接入指引

  • 认证: 先 POST /api/v1/auth/login 取 JWT → WS 握手(?token=)注入。
  • 版本: 客户端请求头声明 X-API-Version: 1。
  • 离线: PWA / 原生端建议缓存 sessions/personas 列表。

5. 变更记录

  • v0.11(跨端实时同步,design/16 §4.2):WS 下行新增 message_persisted 事件——每条 user/assistant 消息落库后广播 {type, sessionId, data:{message:{id,sessionId,role,content,mode?,mood?,image?,createdAt}}}(id 为后端生成,thinking 已剥离)。客户端按 sessionId === activeSessionId 过滤 + 按 id upsert(含本端乐观气泡 uid→后端 id 归一)去重,实现「A 发消息、A 与 B 都无需刷新且各出现一次」。后端 history.Store 新增 AppendFull 供编排层取含 id 的落库消息。
  • v0.10(会话消息持久化 — WS 契约,design/16,后端-2):WS 下行帧新增可选 sessionId 字段(能确定会话的事件带上);新增 history 回放事件——WS 握手成功即回放主会话最新 50 条({type:"history", sessionId:"web", data:{messages:[...]}},thinking 已剥离)。stream_end/stream_chunk/会话编排状态帧(session_busy 等)在能确定 session 时带 sessionId;message.delta 等结构化流帧因 model.StreamEvent 无 session 上下文不带(即"若知道就带上"边界)。
  • v0.9(会话消息持久化 + 主/次级会话,design/16,后端-1):新增 POST /api/v1/sessions(新建次级会话)、GET /api/v1/sessions/{id}/messages?limit=&before=(游标热分页拉历史,时间倒序)、DELETE /api/v1/sessions/{id}(删次级会话及其消息);GET /api/v1/sessions 在注入 HistoryStore 后改返回持久化会话元数据数组(主 + 次级,type 区分),未注入时保持原渠道会话列表向后兼容。读消息/写会话为 owner/admin(用户侧私有历史,thinking 不达 viewer);会话元数据列表保持任意认证角色可读。
  • v0.8(管理面板写操作 CRUD):补齐管理面板写端点(见 §2「管理面板写操作契约」,均 owner-only + 审计)——POST/PUT /admin/personas(真实注册 + 持久化 configs/personas/<id>.yaml)、POST /admin/users/apikey + DELETE /admin/users/apikey/{id}(真实签发/撤销)、POST /admin/iot/{id}/control(真实设备控制)、POST /admin/automations + /run + DELETE(真实注册/触发/移除规则)、POST /admin/llm(临时记录)+ /admin/llm/test(真实模型调用)、POST /admin/channels/{open,close,test}(真实连接/断开 + 结构性身份识别)、POST /admin/plugins/uninstall(真实 registry 移除)、POST /admin/memories/search(真实检索)、GET /admin/sessions/{id}/export。无存储的写(新增用户 / IoT 场景·规则 / 插件安装)如实返回 501 not_implemented。
  • v0.7(会话消息编排 design/15):POST /api/v1/chat 非流式且会话「正忙」时改回 202 {data:{queued:true,queueDepth}}(原同步 {data:{reply}} 仍为空闲时返回);pending 满回 409 chat_busy。WS 上行新增 interrupt({sessionId},中断当前任务+清 pending);WS 下行新增会话编排状态事件 session_busy / pending_ack / pending_drain / session_idle / session_interrupted / pending_full(见 §3.2)。既有 stream_chunk/stream_end 与结构化流事件不变,契约向后兼容。
  • v0.6(可观测性):新增 GET /api/v1/admin/observability/{metrics,trace,audit}(owner/admin)——metrics 返回网关实时请求计数/QPS/延迟/方法·路径·状态分布 + LLM/子代理 span 计数;trace 返回 gateway 环形缓冲里的最近 span(经 TraceSink 对接 runtime tracer,映射为 AdminTraceSpan);audit 返回持久化审计(SQLite audit_logs,未注入时退化为内存)。llmCalls/subagentEvents 由实际观测 span 累计;Token/成本后端不统计、不返回(不伪造指标)。
  • v0.5(批次B·视觉真推理 + 语音端):POST /api/v1/chat 增 image 字段(base64 data: URI 或 URL),入 loop 视觉路由(vision/OCR 工具或主模型多模态,design/06 §0「先看图再对话」);WS 上行 voice_input 接 STT→聊天→TTS 管道,下行新增 voice_output(定向回请求连接,含合成音频 + 识别文本 + 回复文本)。
  • v0.4(结构化流):WS 下行新增 message.* / thinking.* / tool_call.* / tool_execution.update 结构化流事件(event shell 补 turnId/seq,data 类型化),对齐 OpenClaw AssistantMessageEvent;保留 stream_chunk/stream_end 向后兼容。
  • v0.3(M10):管理面板 /admin 落地——按 §2 契约封装 admin 只读端点(personas/sessions/memories/plugins/channels/iot)+ owner-only plugins/policy 写;其余 M10 端点以契约路径封装、后端未实现时前端显式"待实现"壳。
  • v0.2(M8):gateway 落地——登录/health/chat/sessions/personas + admin 只读端点 + plugins/policy 写 + WS /ws/chat(JWT + bus 广播)。
  • v0.1(契约先行):骨架 + 端点登记表。