Files
Cyrene-For-Android/devdocs/07-给后端会话的交接.md
T
AskaEth 2369dd2115 meta(docs): devdocs/ 纳入版本库 —— 交接与协同文档不再只存在于本机
主人 2026-10-04 指示「项目仓库也可以写进去」。因此把 devdocs/ 从 .gitignore 移除并首次入库:

- `05-开发进度与交接.md` —— 跨会话交接锚点:当前状态、易忘的实现约定、踩过的坑、实机验收方法
- `02-前后端协同事项.md` —— 与后端会话的**交换文档**(两边都会读写:我们登记缺口,对面写回执)
- `01/03/04/06/07` + `DESIGN.md` —— 路线、客户端细化方案、构建环境、迁移说明、给后端会话的交接

**凭据扫描已过**:无账号口令、无 token/refreshToken 明文、无 API key 或私钥。
文档里只记「登录凭据不写进文档,问主人」这条口径本身。

(此前忽略它的理由已不成立:文档现在承担跨会话交接与前后端协同两件正事,
只留在本机磁盘会随机器丢失,而这批内容的价值恰恰在「后来人读得到」。)
2026-10-04 19:00:18 +08:00

8.0 KiB
Raw Blame History

给后端会话的交接(2026-10-04)

来自 Android 客户端会话。我们共享 Cyrene-For-Android/devdocs/02-前后端协同事项.md 作为交换登记处。 你在 v0.56 里逐条落地了 A2 / G1 / G2 / G3 / G4 / F3,并在 changelog 里点名引用编号——这套流程运转得很好。 本文件是接续:把我复核到的现状、仍未闭环的项、我接下来要做的客户端改动一次交代清。


一、你已落地的(我复核过代码/测试,不是听说的)

编号 提交 我核到的证据
G2 REST stream:true 不再静默失败 7512d59 改为直达编排器;响应面 200 / 202+queueDepth / 409 / 500 / 503
G4 clientMsgId 幂等 7512d59 internal/services/gateway/chat_idempotency_test.go 有去重断言
G3 chat.image 上限 v0.56 rest.go 的 chatImageTooLargeCode(文案指路 /upload)
F3 视觉链路 URL 取回 v0.56 internal/runtime/multimodal/vision/resolver.go:81-85 的 inlineImageSrc
A2 interrupt scope 5494c31 —
G1 帧壳陈述更正 8c6c796 api-reference.md §6.2 / §6.6

另注意到你多做了 3d8822c(回合内 steer + steer_ack 帧)——客户端尚未接,先记下。


二、最要紧的一件:multimodal: false 是设计还是漏配?

实测的生效配置:provider: anthropic / model: deepseek-flash / multimodal: false。

问题:你自己那份 DevDocs/reference/deepseek/guides-vision.md(2026-10-03 抓取)首句就写着 「deepseek-flash 模型支持在文本之外输入图片」。若该标志并非有意:

  1. 图像被降级走视觉工具,而 resolveImages 每回合都跑(loop/run.go:70,入参由 loadCheckpoint 重建), MessageResolver 无缓存、解析结果不落库 ⇒ 同一张图每个回合被重新解析一次(见 02/H1)。
  2. 模型只拿到一段文字描述,不是图本身 —— 这不只是「贵」,是有损。

若置为 multimodal: true:走 KindMain(resolver.go:75-85),不调任何工具 ⇒ H1 结构上消失,且模型真看到图。 这是「改一个配置项」与「写缓存代码」的差别。

顺带更正我自己的两处夸大(已写进 02/H1,别按错的账做设计)

  • 图像 token 有硬上限:文档「Token 用量」节——进模型前自动缩放(缩到约相当于 1300×1300 像素), 每张图最多 1024 token,原文举例「2000×2000 与 5000×5000 经缩放后消耗的 token 数相同」。 所以不是「大图吃一大块预算」。
  • 据此,KindMain 比 KindVisionTool 更省:≤1024 输入 token/回合、零额外调用 vs 每回合多一次完整模型调用(那次调用自身还要带图 + prompt + 输出)。

请回答:该标志是设计选择还是漏配?若是后者,欢迎直接改,我这边无需改动。


三、仍未闭环的(按优先级)

  1. 02/H1 的剩余部分(即使改了 multimodal 仍值得看) inlineImageSrc 对 data: 短路、对 URL 则每回合重新取回 (internal/runtime/multimodal/vision/image.go:142-163)⇒ URL 存储带来「每回合一次网络 I/O」, 且来源一旦失效,该回合解析失败(loop 保留原消息、不中断回合 ⇒ 模型这轮静默看不到图)。 建议:把「取回 + 内联」的结果按内容哈希 memo。

  2. 02/F1 + F2 —— 非图片文件进不了对话(缺三件) ① 表示:模型层只有 text/image_url/tool_call/tool_result(runtime/model/model.go),没有 document 类型; ② 存储:POST /upload 只收光栅图(嗅探白名单,其余 415); ③ 摄取:对话路径没有任何环节 fetch URL 并抽正文送进上下文。 旁证:IM 适配器层已有 adapter.ContentFile / MediaFile 且各渠道都在填, 但 channelbridge 从不读 msg.Media(inbound.go 只取 msg.Content,还丢弃无文本消息),所以IM 侧也无先例可抄。 ⇒ 主人提的「分享到 App,超限走文件」现在就卡在这里。

  3. 02/F4(约定问题,动手前必须先定) 把 [用户分享] 这类标记拼进 content 违反项目红线(design/11 §10.2「用户内容永远只进 user 角色消息」), 也与已实现的约定相悖:来源走独立 system 消息(channelbridge/source.go:25-35),身份走结构化 SenderName, 源码注释原话「文本标签既含糊,又构成提示词注入面」。 建议:来源走来源 system 消息或已有的 deviceId / platform 元数据;人类可见标记放客户端渲染层。

  4. 02/F5(小) PATCH /sessions/{id} 在 title 存在但空白时回 title is required,读起来像「缺字段」。 建议区分「字段缺失」与「值非法」两种情况。

  5. 02/E4 / E5(文档漂移,低优) /auth/logout 的响应形状文档 vs 文档 vs 代码三处互相打架;api-reference.md §3.2 的会话字段已过时, 且 PATCH / read 没有 §3.x 详情章节。(§6.6 那处你已在 G1 修掉。)

  6. 02/D4(未读) unreadCount 已实现,但已读游标 POST /sessions/{id}/read 客户端尚未接, 所以「红点只增不减」。客户端侧待排,暂不需要你做什么。


四、来自你那套 DeepSeek 视觉文档的三条提醒(与新链路有交互,值得自查)

  1. 图片只能出现在 user 消息里;system / assistant 带图回 400。 ⇒ 历史重装配时若把图像部件落到非 user 角色,整个回合会挂。
  2. provider 的限额都比 Cyrene 自己的宽:请求体 48 MiB、单图 base64/URL 32 MiB、URL ≤8192 字符、 单边 ≤8192 px(单请求 ≥15 张图时降 4096)。 ⇒ Cyrene 自己的 5 MiB(G3)才是真正的瓶颈;要支持更大图,放宽这边比适配 provider 更直接。
  3. detail: low(缩到 512×512、更省 token)是现成旋钮,但由服务端构造内容块时决定,客户端设不了。

五、我接下来要做的客户端改动(便于你预判冲突)

  1. tool_execution 三事件(进行中) 客户端此前只映射了 .update——恰好是你没有生产者的那一帧;真正发出的 .start / .end 落进未知类型被静默丢弃 ⇒ 工具执行状态从未到过界面。 (ws_bridge.go:191-194 已写明 id 可关联 tool_call.*,我会按 id 关联,不按 index。)
  2. REST POST /chat(stream:true):长文 + 图片;按你的状态码响应面分支; 带 clientMsgId(重试终于安全),并用回填的 clientMsgId 替掉客户端 「靠文本完全相等对齐乐观气泡」的脆弱匹配。
  3. 接入 interrupt 的 scope(A2 的客户端半边)。
  4. 图片策略:小图 base64、大图走 /upload + URL(F3 修好后这条路才真正可用)。
  5. 客户端遗留(无需你参与,仅告知):每个 ChatScreen 各建一条 WS 连接、旧连接不回收 (连接所有权重构待排);ChatSocket.sendInterrupt 至今零调用方。

六、协作方式上的两个请求

  1. 改帧 / 字段形状时,请同步 api-client.md 并升契约版本号——我 diff 的就是那个版本号。 两次漂移(E4 / E5)都是「代码对了、文档没跟」,我照文档做就会做错。
  2. devdocs/ 不进 git(已 gitignore),是磁盘上的共享文件。你的回复直接写进 02 对应条目即可,我读得到; 若某项你要拒绝或改口径,也写进同一条目,别静默不实现。

本文件由 Android 客户端会话生成;对面可直接在 02-前后端协同事项.md 里逐条回。