Repository navigation
[Bug] 编辑(撤回)排队中的消息丢失对话引用,并把 userselect 原始尾块内联进正文(重发后引用提示条也不再显示) #871
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
对话 / Agent 交互 · Agent chat
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
影响体验 · Major (功能可用但体验受损 / works but degraded)
复现频率 · Reproducibility
必现 · Always
问题描述 · Description
编辑(撤回)一条带「对话引用」的排队消息时,引用 chip 不会恢复,输入框里反而多出一串 # userselect: 原始 JSON 尾块;这条消息再次发出后,气泡也不再显示正常情况下应有的引用内容提示条。尾块长这样:
# userselect:
```userselect
[{"text":"被引用的文字","path":"..."}]
```
根因定位(源码 + 安装版 bundle 双重核对,v3.14.4 渲染 bundle styles-Qlp0Bew7.js 与仓库 HEAD 一致):
对话引用没有协议级独立字段。发送时 composer 把四类外部上下文(对话引用 / 代码评论 / 网页元素 / PPTX 元素)按固定顺序序列化成正文尾块,这是模型可见的传输契约(packages/ui/src/v4/composer/composerPromptContexts.ts 的 serializeComposerPromptContexts;引用格式见 packages/ui/src/lib/conversationSelectionReference.ts 的 buildPromptWithConversationSelections)。因此消息入队时,ConversationInputIntent.text 存的就是含尾块的完整序列化 prompt。
而队列项「编辑」是撤回语义(deleteQueueItem ACK 后恢复到 composer),恢复链路把 item.text 原样 setText 回输入框,整条链路没有调用 parseComposerPromptContexts 把尾块拆回上下文状态:
SessionPane.handleEditQueueItem→resolveQueuedComposerRestore(SessionPane.tsx:453,text: v4QueuedCommandText(item.kind, item.text)原样取用)- →
ConversationComposer.applyComposerRestoreRequestToComposer(ConversationComposer.tsx:304,inputApi.setText(request.text))
于是引用 chip 状态不恢复(引用 UI 消失),# userselect: JSON 尾块成为输入框可见正文。
重发后提示条消失的机制:气泡侧 UserInputRowView 依赖尾锚定正则识别并隐藏尾块、渲染引用提示条:
/(?:\n\n)?# userselect:\n```userselect\n([\s\S]*?)\n```\s*$/
撤回后的文本经编辑(光标通常在末尾,新输入落在块之后)后块不再位于末尾,解析失败 → 裸块按正文渲染、提示条不出现。
影响面:同一根因也影响代码评论 / 网页元素 / PPTX 元素三类尾块——撤回编辑都会把它们原样内联为正文,不只对话引用。
复现步骤 · Steps to reproduce
- 让 agent 处于忙碌状态(turn 进行中),使后续发送的消息进入队列。
- 选中此前某条消息的一段文字 → 点「添加到会话中」,输入框出现引用 chip。
- 输入文字并发送 → 消息连引用一起进入队列(队列行只显示截断文本,引用此时不可见)。
- 点该队列项的「编辑」(铅笔)按钮,把消息撤回到输入框。
- 观察输入框:引用 chip 消失,正文末尾出现
# userselect:+userselect [...]原始 JSON 块。 - 把修改文字打在末尾后再次发送 → 消息气泡显示裸 JSON 块作为正文,且没有引用内容提示条。
期望表现 · Expected behavior
撤回编辑后引用 chip 应恢复原样,输入框正文不含任何序列化尾块;再次发送后气泡正常显示引用内容提示条。
实际表现 · Actual behavior
撤回后引用 chip 丢失,# userselect: JSON 块成为可见正文;重发后气泡不显示引用提示条(当编辑文字落在块之后时,裸块会永久显示在气泡正文里)。
ZCode 版本 · ZCode version
v3.14.4(Desktop)
设备 / 系统 / 浏览器 · Device / OS / Browser
Windows 11 x64(10.0.22631)
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
纯文本即可稳定复现。修复建议:
- 方案 A(最小修复,纯反解析):
resolveQueuedComposerRestore对item.text执行parseComposerPromptContexts,text恢复为visibleContent,解析出的四类上下文随ComposerRestoreRequest传回 composer 一并恢复。代码评论 / 网页元素 / PPTX 元素可完整还原;对话引用尾块只含{text, path}(发送契约有意剥离内部元数据),而ConversationSelectionReferenceChip本就支持展示型引用,可降级渲染(无来源行、不支持单条删除)。 - 方案 B(完全保真):入队成功时 renderer 按
queueItemId快照完整引用状态(队列本身即非持久态,生命周期一致),撤回时优先用快照恢复完整 chip;快照缺失(renderer 重载)时回退方案 A。
临时规避:撤回后手动删除输入框中的 userselect 尾块,再重新选中原消息文字点「添加到会话中」。
Activity
github-actions commentedon Sep 29, 2026
👋 感谢你的反馈,我们已经收到。
status: 待评估,你可以随时补充信息。needs: 更多信息标签并 @ 你。👋 Thanks — we've received your issue.
status: 待评估(Triage); feel free to add context.needs: 更多信息and ping you.