Repository navigation
fix(chat): recover drafts and keep one native reply - #8121
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
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)
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max
Reviewed head: 0a761b43cfffa670353dd41db9c814962eb0abc0; base: 2c24d5d102dc35c417b3ce49e25096aa37e1642b.
动机 / Motivation
编辑待处理消息的使用者,会在原消息开始执行时遇到草稿入口消失的问题。 同一条排队消息出队后,base 的本地存储仍有 6,968 字草稿,但页面没有可见入口;本头在输入框上方提供折叠入口,展开后可以完整选择原文。 这次恢复保留主输入框的另一份草稿;核对原操作、读取和清除保留稿均没有增加原生消息派发。 本提案不让已开始的消息重新进入编辑,不自动重发,也不认证已安装 App、原生输入法或 Lark。
这是已存草稿可用性的修复。仅保留磁盘字节不足以让使用者继续工作;保留已出队的假队列行又会误报状态。当前方案沿原会话找回未发送的文字,让使用者主动选择或核对原请求,不需要重新说明任务或增加确认轮次。采用本次经验提示的“恢复后能继续有用工作”判断;不把目录、回执或测试数量当作效果证明。
改动思路 / Approach
草稿是尚未提交的用户意图;队列成员资格仍来自原 Session,公共 helper 只读取和清理原恢复记录,不增加派发或权限 owner。 当前 PR 仅恢复已出队消息的本地编辑稿,并复用原操作核对;后端协议、原生执行器和 installed-host 资格没有扩大。
队列成功读回后,将当前成员与本地恢复记录比较;当前行继续使用原编辑器,已出队记录移入折叠的保留修改。核对操作仍经过原 HTTP owner 的身份、修订和开始状态检查。队列或存储不可读时显示错误,恢复展示不把失败解释为成功的空队列。这个数据流足够直接,无需新增后端接口、设置或第二套队列。
具体改动 / Changes
完整差异为10文件 +252/−16,已检查全部 diff、原组件调用方和原后端队列测试。主要新增是57行 helper、72行恢复组件及针对性的回归;history 场景只把等待改为 DOM ready,以免初始化等待它自己故意挂起的请求,没有放宽原历史断言。
规范为 docs/integrations/session-runtime-control-plane-adapter.md,spec_revision 2c24d5d102dc35c417b3ce49e25096aa37e1642b,criterion_id Conversation presentation example:按 Session/Turn 保留草稿和未确认操作,核对沿用原请求,已开始回合拒绝晚编辑。本头已通过下列实际调用验证这组义务。
retireQueueInputRequest先比较原请求,再按文本与修订清理。旧响应不能删除另一个页面较新的草稿或操作;清理失败仍保留重试身份。RetainedQueueInputs只列当前 Session 中已不属于队列的恢复记录;展开可读全文,选择仅选中文字,核对仅重试原 operation。useConversationQueue提供派生的 readReady;页面仅在成功观察后显示恢复内容,错误不会成为“消息已经消失”的证据。
对主干的风险 / Risks
没有发现阻塞本次产品改动的问题。最强反例是出队同时丢失编辑入口、晚响应误删新稿,以及读取失败时展示可能已不可访问的内容。本轮在精确 base/head 各跑完整真实 HTTP 模块:各25项通过,覆盖原生 stdio、消息修订、领取竞争、原回执重放和跨会话/权限拒绝;两版 desktop 和来源校验后的 Chat 构建通过,head helper smoke 通过。
实际浏览器使用两版打包资产及同一个隔离 HTTP/store。消费消息、刷新、选择全文、核对被拒绝的原操作、阻断队列 GET、恢复读取、拒绝存储及清除草稿均走到可见结果。6968字逐字相等;主输入框不被覆盖;整个恢复过程 native start 保持1、steer保持0。这里的 stdio 是确定性协议 peer,不能认证真实模型或 installed App。
语义与 CI 对齐
复用既有 ChatQueueInputRequest,没有新增共享状态词汇、Agent 指令或执行权限。本地 standard premerge 的4个 direct 通过,8个 selected 中6通过、1项维护性继承 advisory、1项 Todo read-model 检查失败。后一项在不可变 base/head 独立执行均于 status_module.open_todo_items 抛相同 AttributeError;完整 traceback 仅规范化工作区根路径后相等,失败 owner 和本 PR 的全部 Python 树未变,队列不变性有上述独立通过证据。因此它不构成本 PR 的代码回归;该失败、严格 CQR 和合并门槛继续保留,未改标通过。作者已披露的 loaded-lens 1399.38ms/1000ms 和 Runtime-response 两匹配 CI 问题仍是原因未核的诊断记录;没有查询或等待 CI。
我的整体评价 / Verdict
APPROVE 是此 head 的代码评审结论,GitHub 同账号采用 COMMENTED;它不授予合并权限,也不清除本地预合并/CQR 或远端规则的阻塞。长程工作在反复出队和刷新后保留未发送意图,用户体验有实际改善,未增加必要的意图/确认轮次;自愿展开和复制仍是恢复动作。兼容层保留原存储记录有真实消费者,公共 helper 已完成本域的简化,没有要求额外跟踪任务。
默认只增加一行折叠入口,完整草稿和恢复动作按需展开;长稿、真实失败反馈和主输入框在同一页面可读。 未验证已安装 App、原生输入法和 Lark;浏览器为精确源码打包资产配合隔离 HTTP、真实存储及脚本化 stdio peer。 中文/英文390px展开视图均已目视检查;主文字保持可读,hash/方法信息没有进入主文案。head 窄屏恢复区域为14..376px,没有溢出。默认折叠、展开和失败截图与功能断言分开判断;没有以溢出测试替代构图审阅。
English verdict: APPROVE. Post-dispatch drafts remain usable without another send; the independently reproduced baseline premerge failure remains a separate merge hold.
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEADFor a same-repository clone whose Keep the DCO |
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Self-review after main integration — exact head 02d40c0b493e3839213a39fb9f381f1b8eee957f.
- Merged current
mainb00701cbinto the reviewed chat recovery branch. - The sole conflict was complementary test setup: retained the PR comment and
main’sgotoWaitUntil: "domcontentloaded". git diff --checkpasses; merge commit carries the DCOSigned-off-bytrailer.- Exact-head verification:
smoke:queue-input-recoverypassed; fullnpm run buildpassed with TypeScript checks, dashboard build, and Chat bundle build/verification. - No product behavior was changed by the conflict resolution beyond integrating the latest base.
APPROVE for merge readiness at this exact head.
huangruiteng
left a comment
There was a problem hiding this comment.
Independent approval of exact head 02d40c0 after main integration.
Goal And Delivered Outcome
排队消息在编辑期间开始执行后,原队列行会消失。现在输入框旁的“保留的修改”可找回完整编辑草稿,并沿原 operation 核对未确认的修改,主输入框草稿继续保留。
同时修复原生工作会话的一次回复显示两次的问题。后端始终只有一次 Turn start 和一条已保存回复;历史回读早于发送确认时,前端可能保留历史副本,或额外建立恢复流。现在按原 Session/Turn/message 身份合并,并由尚未返回确认的原发送请求持有观察权。
main,本次核对并集成1b636dee161f5ec0039b2c0121ef7ff7060dcb72。本 PR 只交付这组可独立回退的会话恢复修复。Author Declaration
Written by: model_agent — OpenAI Codex。依据既有原会话、queued input、重试身份和权限契约,不增加后端执行权限。
产品实现使用 TypeScript/TSX/CSS;保留 Enter 忙时排队、Shift+Enter 换行、Command+Enter 显式 steering、IME 合成保护、附件和原权限边界。正文相同的不同消息、不同 Session/Turn 和独立协作回执仍分别显示。
Scope And Continuation
复用原存储键、mutation API、history owner 和事件流,不增加队列或持久状态 owner。恢复入口仅在原队列读取成功后出现;读取失败保留错误和恢复内容。读取、选择和清除草稿不会启动模型。
同域整理共享存储解析/清理和历史行映射。既有历史测试的挂起第二页与 network-idle 死锁改用已有 DOM-ready 入口,451 条分页、长文、失败重试、草稿和零派发断言保留。新增顺序回归只延迟真实后端响应,不伪造消息,不使用 first/last 规避严格匹配,不增加性能预算。
真实宿主和模型采用、安装版 App、macOS 拼音及 Lark 双端仍待独立验收。没有合并、安装、发布、付费模型或新 benchmark 执行。
Validation
Tested final head:
7a0430c016eccb1db1c730ebfd5eb704a540d1e1;14 个 feature paths。上游 main 集成前后逐字节核对产品 patch,打包资产按最终源码构建和校验。Run state:finished;86 场景完整通过。passed · 86 scenariossmoke:demo-readiness;较早 v1 运行因新手动复现而主动停止,不记为通过passed · 5 testsnot passing · CQR fail / quick holdcqr_2a17878d94edfdac41a4decision=fail,verify=invalid_receipt;quick 的 4 direct 和 3 gating selected 通过,另 1 advisory 失败。整体 gate=quality_invalid_receipt,不允许合并。失败观察与结论边界:
当前维护性 ratchet 仍以 exit 1 报告一个 unreviewed oversized function、零 magnitude regressions;native catalog 将其分类为
advisory_inherited_failure。本次 CQR 保留 failed,没有借用旧 head 的基线归因把它记为通过。原 Release Artifacts / build 的严格文本双匹配已在同一真实后端用例稳定复现,并通过两种顺序回归修复。第二种修复前,在原 ACK 返回前已产生两个额外恢复流;修复后为零,随后仅原观察者接管。
原 dashboard-browser (2) 有一次 lens 切换 1399.38 ms,超过冻结 1000 ms。相同 200 项、coverage=1 的本机成对运行,main 与候选各三次均通过,切换最大值分别 338.40 / 317.93 ms;早期依赖软链接造成的 403 样本已排除并保留。macOS / Node 24.21 与 Linux CI 环境不同,这不豁免原失败,也不证明 CI 时延已修复。
原 chat-bundle-browser (3) 的 ZCode Start disabled 在 main
68318d14和候选均复现。真实 API 回读为authority_or_quota_unavailable;其配额子命令返回 progressive reader envelope,调用方却直接读取should_run。这是仍待拥有方修复的传输采用缺口,启动门禁未放宽。独立手动直连状态 fixture 在重新载入后触发原会话绑定门禁;停止发送并保留观察,没有将其声明为 v2 真实宿主执行通过。下方新图为编译版自动化的真实浏览器截图,数据和宿主边界见说明。
早期 head 的 CQR pass、quick premerge pass 及维护性继承归因仅属于各自当时的范围,不能认证本次 head 或覆盖后来 CI 失败。全仓 pytest、最终 Linux CI 和安装采用未由本机聚焦验证替代。
Frontend / Visual Evidence
Primary question: 原消息已开始,刚写的修改还能找回吗;原回合是否只有一份状态和控制?默认保留折叠入口、折叠活动与单一主输入框,完整内容和操作按需展开。
原队列界面布局未变,沿用下列已核对的前后/错误态截图:真实已入库 benchmark display fixture 的 11 条记录用于长会话阅读,原记录为
runner_invalid、仅诊断用途;操作输入与协议响应为 synthetic,没有 score claim。Before 为不可变3c7e0935,原 After 为4f1edbd0;对应界面源码保持相同。编译 assets + 实际 HTTP/store + scripted stdio,不代表已安装 App 或真实模型。English reader
新增活动回合截图:当前修复源码的 packaged Chat UI、既有合成 Goal 状态投影、实际 SQLite/Core/Chat Session 和 scripted stdio。只保留一个活动回复、展开入口及精确中断控件;390px 无页面横向溢出。桌面和窄屏实图均已检查,没有修改图片。
Type of Change
LoopX Area
Technical Direction
S5 原会话、纠偏、重复操作与恢复;不声明整个阶段完成。
Boundary Checklist