Repository navigation
fix(chat): preserve queue edits when dismissing actions - #8150
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
结论:APPROVE。未发现当前 exact head 的 blocking finding;独立 base/head 对照复现并验证了菜单关闭丢稿问题。原始 maintainability 失败仍保留为独立基线债务。
动机 / Motivation
在运行中的 Agent 会话里修改待处理消息、并用键盘关闭操作菜单的用户。 用户写好独立的队列编辑草稿,打开“更多操作”后按 Escape;base 会把草稿一起丢弃,head 只关闭菜单并把焦点交回菜单按钮,用户可以继续编辑。 这不是泛化的保存流程重构:无意按键会删除本地恢复信息,长会话里的用户必须重新输入。独立 base/head 实测确认菜单关闭保留编辑与主输入框草稿,重载可恢复;只有显式保存和取消才修改原排队消息,附件与运行回合身份保持。 不修改的成本是继续保留这个稳定可复现的数据损失;移除 Escape 则损害键盘操作。本 PR 不重写队列协议、后端权限或 native runtime,也不证明 installed desktop、真实模型执行或物理输入法行为。
改动思路 / Approach
保留既有 TypeScript QueuedMessage 对菜单显示的局部责任;未把关闭菜单变成保存、取消、steer 或新的队列状态。 当前 PR 完整交付“菜单关闭不丢编辑”的交互修复,save/cancel、原附件、Session/Turn 绑定及后端 revision owner 继续复用。 已接受的依据是 docs/development/design.md#forms,固定在 faab5f5,criterion_id 为 Forms:菜单开启或关闭应保留草稿且不发送,并可通过键盘操作。这个要求早于本 PR;不是为了匹配测试而改写规范。实现把 menu 层与 editor 层的 Escape 优先级分开,关闭菜单后保留原菜单按钮焦点。用户继续自己的编辑不需要重新授权、重填材料或额外确认;原有明确保存/取消仍是产生 mutation 的动作。
| 触发 | base | head |
|---|---|---|
| 编辑中,菜单打开,Escape | discard,editor 消失 | 仅关闭菜单并聚焦 trigger |
| 菜单关闭,Escape | 放弃本地编辑 | 保留同一行为 |
| IME Escape | composition guard | 保留 guard,不关闭菜单 |
| 显式保存/取消 | 原 mutation owner | 原 operation/revision owner |
这是源代码和实测的简表,未增加全局菜单服务、配置开关、持久标志或并行 Python 决策 owner。
具体改动 / Changes
关键代码讲解
production 只修改 apps/presentation/dashboard/src/features/personal-workspace/conversation-queue.tsx 中 QueuedMessage.onKeyDown(113–128 行)。先检查 composing/isComposing/keyCode229,再保留 busy/unresolved 的限制;117 行在 menu=true 时执行 setMenu(false) 和已有 menuButton focus,else 继续调用 QueuedMessage.discard(85–87 行)。discard 仍只处理本地草稿;Storage.removeItem 失败时保留文本并给出错误。save(78–83 行)及 mutate(50–76 行)仍先保存 operation identity,再调用原后端;取消和 steer 也未换 owner。真实 caller 是 PersonalWorkspacePage:3226 → ConversationQueue:179/189 → QueuedMessage,原 Session/Turn key 和附件不变。
两份已有 browser 场景被扩展,managed-agent-sessions 的 verifyQueuedEditor(9 行)复用运行中的原 Session,带原附件和不同的 composer/editor 草稿,检查菜单、IME、存储故障、reload、显式 save/cancel 和 native starts。这个测试增量保护的是 shipped interaction 与 recovery 边界;没有新建日期专用 smoke 或 runner。相邻代码审视结果是继续复用既有 handler/ref 最清楚,无需在本 PR 做更广泛重构。
对主干的风险 / Risks
独立 Ego 实测使用当前 exact head db5c28d 和 immutable base faab5f5 的打包 Chat,连接隔离真实 SQLite/Core/Chat 与 synthetic native stdio peer。base 按菜单 Escape 后 editor=false、原 revision0、POST=0;head 保留 editor 与独立 composer,focus 返回菜单按钮;IME 不关闭菜单;removeItem 故障时菜单关闭不调用 discard,不产生 alert 或 POST;重载两份草稿仍在。显式 Command+Enter 后原消息 revision1、原附件保持;菜单关闭时 Escape 只放弃新的本地修改;显式取消后 history 读回 revision2/cancelled=true,只有 save/cancel 两个 POST,原 active Turn 身份在这段操作前后保持,native turn/start 数量未增加。
独立后端检查 68 passed;strict TypeScript、base/head Chat build、两份改动 MJS syntax 和 public-boundary 扫描通过。standard premerge 为4个 direct checks 加5个 selected checks,gate passed,包含1项 inherited advisory。原始 maintainability 仍 exit1:未改动的 _admitted_interaction_next_cli_actions 为62 decision points/60,85 statements/90。另在 immutable base/head 执行同一 JSON 报告命令,除 checkout root 外完整 finding/metrics/threshold/policy 一致,tracked Python/metric baseline 与环境 digest 相同,且全部 changed paths 有独立 required passing evidence,因此按现有 baseline-attribution 规则归为 pre_existing_unrelated;未删失败、改阈值或缩小 workload。strict exact-scope CQR 已 pass。现存大 bundle warning 与 dev dependency advisory 为 base/head 共存,不等于已消除。CI 未查询、poll 或等待。
我的整体评价 / Verdict
已目视检查同一真实 Chat 后端上的完整会话页面:运行状态、长历史链接、带附件的队列摘要、展开编辑和独立 composer 同时存在;1200×854 与 390×844 的草稿、焦点和保存/放弃控制可识别,展开编辑没有遮挡主输入框。 本次无密度、详情折叠或响应式布局改动;按受影响操作检查菜单关闭后编辑仍展开的正常页面,不把未改动的完整消息展开另列为必测状态。 未验证 installed desktop、物理 macOS IME 和真实模型;native peer 为隔离的 synthetic stdio fixture,SQLite/Core/Chat 与打包前端是真实入口。 在当前有界目标内,这个修复交付了可用的菜单关闭行为,而非只增加字段或孤立的 smoke。保留既有 TypeScript QueuedMessage 对菜单显示的局部责任;未把关闭菜单变成保存、取消、steer 或新的队列状态。 当前 PR 完整交付“菜单关闭不丢编辑”的交互修复,save/cancel、原附件、Session/Turn 绑定及后端 revision owner 继续复用。 PR description 已包含所测 revision 的 before/after 与 owning-backend desktop/narrow 图,独立观察也验证了 draft 与控制层级;历史滚动方式继续保持。没有证据把本次交互修复推导为长期 benchmark 收益、真实模型理解或已安装桌面验证。
代码结论与合并权限分开:以同账号作者 PR 的 COMMENTED 形式记录 approval;这不是 GitHub formal self-approval。旧阻塞 review/threads 与 native readiness 另行 readback;未授予 merge、dismissal 或安装权限。
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max
English verdict: APPROVE — The exact head preserves queued edits on menu dismissal and retains explicit mutation boundaries, with paired real-backend coverage; the unchanged maintainability failure remains disclosed.
Editing a queued message, opening its More actions menu and pressing Escape currently discards the separate edit draft. Escape now closes the open menu and returns focus to its trigger, preserving the editor and its stored draft. With the menu closed, Escape still discards the local edit.
The change stays in the existing TypeScript queue UI owner. Queue admission, save/cancel/steering authority, attachments and keyboard composition guards retain their existing owners. The real-backend browser case verifies that menu dismissal produces no mutation or native execution, reload preserves both editor and composer drafts, and explicit save/cancel still returns revisions for the original queued Turn.
Validation
faab5f5c291c5359216a0f944fe63fcfbaacdedc: the new packaged assertion fails because the edit draft disappears. The same scenario passes ondb5c28df37d27663ecc1775a26838a25ebecdb97.attached-host-follow-upandmanaged-agent-sessionspass. The latter uses isolated real SQLite/Core/Chat and a synthetic native stdio peer; it covers IME Escape, storage-removal failure, reload, the original attachment, explicit Command+Enter save, cancel readback and unchanged active Turn/native start count._admitted_interaction_next_cli_actionsfunction (62 decision points, limit 60). Strict change-quality qualification remains failed because independent immutable base/head attribution is absent. No threshold or failed result was relaxed.Author work for this bounded fix is complete. CI and independent review remain pending. Installed desktop, live-model execution and physical macOS IME have not been validated. This proposal requires maintainer merge authorization.
Visual evidence
Tested revision:
db5c28df37d27663ecc1775a26838a25ebecdb97. Actual packaged Chat UI. Images contain only public-safe fixture content; no real benchmark logs, credentials or private conversation data. The first pair shows the same attached-host scenario before/after. The final pair was inspected in Ego against the isolated real owning backend, with a running Turn, long history link and queued attachment. Desktop is 1440×900; narrow is 390×844.Primary question: can I dismiss queue actions and continue my edit? Queue summary/count remain near the composer, full source stays on demand, and the independent editor remains visible after dismissal. Both viewports retain draft and controls without horizontal overflow. Existing history scrolling is unchanged.
Before — menu dismissal loses the draft
After — same scenario retains the draft
Owning backend — desktop
Owning backend — narrow