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/ 收录设计文档、前后端协同事项与细化方案。
12 KiB
12 KiB
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
登记规范(开发过程中持续维护)
触发条件——开发 / 联调中遇到以下任一情况,当场追加到本文并立即向主人反馈,不攒到最后:
- 调用后端直接失败(501 / 404 / 500 / 字段缺失导致功能做不了);
- 契约或设计文档写了、但实现没做(例如
mode不落库、voice_input不落库)——即「理论上应该支持但没有」; - 后端行为与文档不符,导致客户端必须绕行。
每条要写清:
- 现象:可复现的请求 / 响应或代码位置(
文件:行); - 客户端为什么要:不补会怎样;
- 后端建议方案:客户端期望的接口 / 字段 / 语义;
- 当前绕行:客户端现在怎么扛过去(没有就写「无,功能阻塞」);
- 优先级:阻塞 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转写 → WSchat(落库 + 流式 + 编排)→REST /audio/speech播放。 - 优先级:中
C2. 语音降级到 silent 时客户端无法感知
- 现状:cloud 档已接阿里百炼(STT
qwen-audio-3.0-asr-flash/ TTScosyvoice-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 可达性 |
待确认 | 低 |