Repository navigation
新对话草稿无法跨「新对话」保留
#10528
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
this.design==Bug?bug:design;
新对话草稿无法跨「新对话」保留
现象
在新对话里输入的草稿,切到别的对话后,再点「新对话」就没了。
Web 端和桌面端共用同一份客户端代码(
packages/client/*),两端都能复现。复现
hello此时 localStorage 里:
每开一次新对话都写了自己的 key,而下一次新对话读的是一个从未被写过的 key。草稿确实存下来了,只是没人再读它。
根因
草稿持久化以 Session id 为 key(
dsh.conversation.<sessionId>),而新对话在用户输入任何内容之前就已经是真实 Session——选定 workspace 时就物化了(hub.ts里sink()的注释:materialized when its workspace was picked)。于是每次进入都拿到新的 id,也就拿到新的存储槽位——上一次的草稿留在旧槽里,成为不可达数据。缺的概念是草稿槽:一个在消息产生之前就能让草稿归属的身份,第一条提交的消息再把它转换成 Session。
提案,以及一个想确认的约束
理想解法是把 Session 物化推迟到第一条消息提交时:新对话先作为客户端状态存在,草稿按槽位(而不是 Session id)索引,晋升之后再绑定
session.projections。但这里有个硬约束:模型选择、权限模式、Agent preset 全部从
session.projections读取,没有SessionBinding时这些控件无法渲染。所以想确认:这大概正是当前把物化提前到选 workspace 这一步的原因吗?后续有没有可能给「新对话」一个独立身份?
如果短期内不做,那各端客户端只能自己补一个固定草稿槽,语义就会散落在各端实现里。
附:一份本地验证过的修复
在不触碰 session controller 的前提下,用「未发送消息的 Session 共用一个草稿槽」恢复用户可见行为。三处关键改动:
1. 存储键抽出来,允许
null表示共享槽(stores.ts)2. 未发送消息的 Session 从共享槽读取,输入变化时镜像写回(
hub.ts的shellFor)actx.effect保证订阅随 Session 销毁解除。3. 首条消息发出后,退役两个槽(
hub.ts的sink)关键点是:只改读取没用,写入端也必须指向同一个槽,否则读
__pending__、写session-xxx,等于没改。测试:在
conversation-store.client.spec.ts补了 6 条用例——共享槽读写、共享槽与 Session 槽互相隔离、分别清理、清理从未写入的槽不抛错、localStorage 缺失、localStorage 拒绝写入。验证:
tsc -b tsconfig.client.json通过,oxlint无告警,vitest28/28 通过。完整补丁(3 个文件、144 行新增)已通过反向应用校验,已作为附件。
范围说明
这个补丁只修「草稿丢失」。它没有消除另一件事:未发送消息的 Session 期间,scope 内的 store 依旧会往自己的 key 持久化一份草稿,也就是上面那些
dsh.conversation.<临时 id>。那是存储垃圾问题,不影响正确性,我会单独开一条 issue 说。fix-new-conversation-draft.patch
All reactions