Files
Cyrene-For-Android/devdocs/02-前后端协同事项.md
T
AskaEth 84de51c7b7 feat: 初始化 Android 客户端(M0 骨架 + M1 登录 + M2 基础模块)
M0:Gradle 9.7.1 / AGP 9.2.1 / Kotlin 2.4 / Miuix 0.9.3,minSdk 33,compileSdk 37。
M1:登录页(服务器地址可配、服务端/本地错误分流、EncryptedSharedPreferences、自动登录与静默重登、401 登出)。
M2 基础模块:消息内容解析器(<p>/<action>/<narration> + 流式增量)、WebSocket 客户端、REST 数据层与分页去重。
45 个单元测试全绿,真机验证通过(登录页 + 启动图标)。
devdocs/ 收录设计文档、前后端协同事项与细化方案。
2026-09-08 20:40:58 +08:00

12 KiB
Raw Blame History

02 — 前后端协同事项(Cyrene-For-Android ⇄ Cyrene v2)

用途:Android 端「要做/想做」,但后端当前不支持、或契约未明确的事项统一登记在这里。主人(AskaEth)按此去后端做适配与开发。 状态机:待确认 → 已确认 → 已排期 → 已完成 / 不采纳 依据:Cyrene_v2/Docs/api-reference.md、Docs/api-client.md、DevDocs/design/12,14,15,16,21(调研中发现多处文档与实现不一致,见 §E2) 最后更新:2026-09-08


登记规范(开发过程中持续维护)

触发条件——开发 / 联调中遇到以下任一情况,当场追加到本文并立即向主人反馈,不攒到最后:

  1. 调用后端直接失败(501 / 404 / 500 / 字段缺失导致功能做不了);
  2. 契约或设计文档写了、但实现没做(例如 mode 不落库、voice_input 不落库)——即「理论上应该支持但没有」;
  3. 后端行为与文档不符,导致客户端必须绕行。

每条要写清:

  • 现象:可复现的请求 / 响应或代码位置(文件:行);
  • 客户端为什么要:不补会怎样;
  • 后端建议方案:客户端期望的接口 / 字段 / 语义;
  • 当前绕行:客户端现在怎么扛过去(没有就写「无,功能阻塞」);
  • 优先级:阻塞 P0 / 影响体验 / P1 / P2 / 文档治理。

流程:待确认 → 主人确认 → 已排期 → 后端完成 → 已完成(注明后端版本 / commit);不做的标 不采纳 并写明理由。

反馈节奏:每轮开发结束时,在对话里列「本轮新增协同事项」(编号 + 一句话),主人直接照着修后端。


A. 阻塞 P0 的(不解决就得改客户端设计)

A1. 结构化流帧不带 sessionId → 多会话流式无法归属

  • 现象:message.start/delta/end、thinking.*、tool_call.*、tool_execution.update 的 payload 只有 {index} / {id,index,delta},没有 sessionId(model.StreamEvent 无会话上下文)。
  • 客户端为什么要:WS 是全局一条连接,多会话同时流式时无法判断 delta 属于哪个会话,切会话会串台。
  • 后端建议:这些帧补 sessionId,或至少补 turnId(客户端用 turnId 反查会话)。
  • 当前绕行:客户端硬约束「同一时刻只有一个会话在流式」(已拍板接受)。
  • 优先级:中高(有绕行,不阻塞 P0)

A2. interrupt 清空 pending → 「打断」模式连发丢消息

  • 现象:interrupt {sessionId} 取消在跑 turn 并清空 pending,下行 session_interrupted{dropped}。
  • 客户端为什么要:S1.4 定了「追加队列 / 打断」两种模式;用户选「打断」时连发多条会被静默丢弃。
  • 后端建议:interrupt 增加 scope(current = 只取消当前 turn / all = 连 pending 一起清),默认维持现状。
  • 当前绕行:打断模式下 UI 限制一次只能发一条 + 明确提示。
  • 优先级:中

A3. 消息 mode 不落库 → 渲染形态丢失

  • 现象:design/16 §5.1 写「消息体带 mode」,但 Web 路径(session_persist.go)与 IM 路径(channelbridge/persist.go)都不写 Mode,字段 omitempty → 实际恒缺。
  • 客户端为什么要:9 值渲染 mode(chat/code/home/work/docs/voice/vision/agents/settings)决定气泡/卡片形态,且「只有 chat 才解析 <p>」这条规则依赖它。
  • 后端建议:持久化时写入 mode(design/16 已约定,属实现缺失)。
  • 当前绕行:客户端一律回落 chat。
  • 优先级:中

A4. 会话 title 恒空 → 列表没名字

  • 现象:historySessionSummary.title 有字段,但 store.go 恒写 "",无生成规则/接口。
  • 后端建议:后端生成(截首条用户消息),或提供 PATCH /sessions/{id} 让客户端改名。
  • 当前绕行:客户端本地生成「会话 N」+ 序号持久化。
  • 优先级:低

A5. WS 断线无补发 / 无 resume cursor

  • 现象:无 since / lastEventId;seq 只用于排序,未规定可续传;重连仅有 history 回放主会话最近 50 条。
  • 客户端为什么要:断线期间超过 50 条就永久丢失,只能整页重拉。
  • 后端建议:/ws/chat?since=<seq 或 createdAt> 补发,或提供 GET /sessions/{id}/messages?after=<ms> 正序增量接口。
  • 当前绕行:重连后 REST 按 before 补差 + 按 id 去重。
  • 优先级:中

B. 影响体验 / 客户端需绕行

B1. 无图片上传端点 → 大图只能 base64 塞进 chat.image

  • 现象:无 /upload;image 只接受 base64 data URI 或 http(s) URL;WS 上行帧限 4096 字节。
  • 客户端为什么要:主人已定「发图先做着」,但没有上传端点就只能把压缩后的 base64 走 REST,大图会撑大请求体(WS 完全走不通)。
  • 后端建议:POST /api/v1/upload(multipart)→ 返回 URL;chat.image 收 URL。
  • 当前绕行:客户端压缩后再 base64,限制单图尺寸。
  • 优先级:中高(主人已要求做发图)

B2. token 24h 且无 refresh 端点

  • 现象:tokenTTL=24h,无 refresh/renew;rotate-jwt 让全部 token 立即失效。
  • 客户端为什么要:主人选了「静默重登」,但静默重登需要长期保存账号密码。
  • 后端建议:提供 refresh token,或拉长 TTL + 支持「记住登录」的长期凭据。
  • 当前绕行:存密码做静默重登(安全上不理想)。
  • 优先级:中高

B3. GET /sessions 信息太少(无未读、无最后一条预览)

  • 现象:只有 {id,type,title?,createdAt}。
  • 客户端为什么要:会话列表做不了预览和未读红点;多端同步时无法标记已读。
  • 后端建议:补 lastMessage{content,role,createdAt}、unreadCount,或提供已读游标接口。
  • 优先级:低(P0 按序号展示即可)

B4. platform / mood / mode 取值未穷举

  • 现象:文档只给示例(web/telegram/weixin-ilink/qq-obv11/kook;calm;normal)。
  • 客户端为什么要:来源角标和情绪标签需要稳定映射(显示「来自微信」而不是原始字符串)。
  • 后端建议:给出权威枚举表 + 未知值回落约定。
  • 当前绕行:客户端维护映射表 + 未知值原样显示。
  • 优先级:低

B5. 管理员端点 5 个返回 501

  • 清单:POST /admin/users、POST /admin/iot/scenarios、POST /admin/iot/rules、POST /admin/plugins/install、POST /admin/rag/delete。
  • 客户端为什么要:管理员页面要决定这些入口做不做、做了怎么降级。
  • 当前绕行:客户端硬编码「已知未实现」清单,入口置灰。
  • 优先级:低

B6. proactive_message 只在 api-reference.md 有,api-client.md 摘要缺失

  • 后端建议:补进 Docs/api-client.md。
  • 优先级:低(文档治理)

C. P1 语音相关

C1. voice_input 轮次不落库、不过编排器

  • 现象:runVoiceTurn 直调 runner.Run,无 history.AppendFull、不经 session_orchestrator → 无 message_persisted、无 busy/pending、不跨端同步;与 api-client.md §3.1「随语音轮次落库」不符。
  • 客户端为什么要:语音问过的事必须进历史、跨端可见,否则在 Web 上查不到。
  • 后端建议:把语音轮次接入编排器与持久化(与文本轮次同一路径),或在文档里明确「语音不留痕」。
  • 当前绕行(客户端已定):不用 voice_input 提交对话,改为 REST /audio/transcribe 转写 → WS chat(落库 + 流式 + 编排)→ REST /audio/speech 播放。
  • 优先级:中

C2. 语音降级到 silent 时客户端无法感知

  • 现状:cloud 档已接阿里百炼(STT qwen-audio-3.0-asr-flash / TTS cosyvoice-v3-flash,需 DASHSCOPE_API_KEY);edge-tts/espeak 未实现;local 默认不注入;silent 兜底返回空音频。
  • 客户端为什么要:没有 key 时语音会「静默成功但没声音」,客户端无法提示。
  • 后端建议:降级到 silent 时给出可识别信号(响应头 X-Voice-Provider: silent 或专门错误码)。
  • 优先级:中

C3. voice_output 是否带 sessionId / deviceId 未规定

  • 客户端为什么要:多端同时说话时无法区分归属。
  • 优先级:低

D. P2 / 路线缺失(客户端想做,后端尚无能力)

D1. 移动端推送通道(系统通知)—— 最大缺口

  • 现象:主动推送只有 WS proactive_message(仅 owner/admin 连接收到),App 不在前台就收不到。
  • 客户端为什么要:design/21 §5 的 P2 明确要「主动推送 → 系统通知」,目前没有任何移动推送通道。
  • 后端建议:接 FCM / 个推 / 自建长连接保活,并在 WS 之外提供推送投递。
  • 优先级:P2,但属路线级缺失,建议早登记。

D2. 消息搜索 / 会话搜索

  • 现象:无搜索接口(/admin/memories/search 是记忆,不是消息)。
  • 优先级:P2

D3. 消息编辑 / 删除 / 重发

  • 现象:无接口。
  • 优先级:P2

D4. 未读状态 / 已读游标

  • 见 B3。
  • 优先级:P2

D5. 会话改名 / 置顶 / 排序

  • 见 A4;GET /sessions 次级按 created_at ASC,改名/置顶需要新接口。
  • 优先级:P2

E. 文档与契约治理

E1. X-API-Version 形同虚设

  • 现象:服务端不校验该头;CORS Allow-Headers 只有 Authorization, Content-Type(未放开 X-API-Version)。
  • 建议:要么真正校验,要么从契约里去掉,避免客户端误以为存在版本协商。

E2. 文档与实现不一致(调研发现)

事项 文档说法 实现
真实 ASR/TTS design/21 §4「未接通」 已接百炼并实测
voice_input.deviceId design/21「待补」 已有
REST 语音端点 design/21「待新增」 已有
语音轮次落库 api-client「随轮次落库」 未落库(见 C1)
消息 mode design/16 §5.1「消息体带 mode」 不落库(见 A3)
来源标识注入 design/16 §4.6.1「文本前缀」 独立 system 消息 + 结构化 SenderName
  • 建议:以 api-reference.md + 代码为准,api-client.md 随实现同步(AGENTS.md 已有此红线)。

E3. thinking 可达性确认

  • 现状:WS 实时/回放已剥离,只有 GET /sessions/{id}/messages(owner/admin)返回。
  • 客户端影响:历史消息的思维链需要额外请求。
  • 待确认:这是有意为之(隐私)还是可优化?

附:状态一览

编号 事项 状态 优先级
A1 流帧缺 sessionId 待确认 中高
A2 interrupt 清 pending 待确认 中
A3 mode 不落库 待确认 中
A4 title 恒空 待确认 低
A5 无 resume cursor 待确认 中
B1 无图片上传端点 待确认 中高
B2 无 token refresh 待确认 中高
B3 sessions 信息少 待确认 低
B4 枚举未穷举 待确认 低
B5 admin 501 清单 待确认 低
B6 proactive_message 文档缺失 待确认 低
C1 语音轮次不落库 待确认 中
C2 语音降级无信号 待确认 中
C3 voice_output 字段 待确认 低
D1 无移动推送通道 待确认 P2(路线缺失)
D2 无消息搜索 待确认 P2
D3 无编辑/删除/重发 待确认 P2
D4 无未读状态 待确认 P2
D5 会话改名/置顶 待确认 P2
E1 X-API-Version 虚设 待确认 低
E2 文档与实现不一致 待确认 中
E3 thinking 可达性 待确认 低