fix(chat): make waiting visible and keep conversations readable - #5309
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
aee7880 to
b42dc14
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
English verdict: APPROVE - head b42dc14
未发现这份完整差异的阻塞问题。这是可独立验收的 App 对话呈现增量;原生执行器持续恢复与团队采用仍未验收,不能据此宣布整个管家旅程完成。
动机
用户发出普通问题后,执行器连接可能很慢,原先必须等连接结束才出现答复占位,消息容易让人感觉丢了。此次目标是让一次发送立即可见,等待、纠偏和中断都有明确对象,同时保留输入、部分答复和阅读位置。普通问题直接发送,不增加必经确认步骤。
改动思路
沿既有发送入口补上准备阶段,再把活动与当前回合控制收敛到共用组件。管家、Goal 和总览中的答复使用同一套呈现;真正的执行状态、会话、回合和幂等操作仍由现有 Chat API 负责。单独加转圈无法解释是否已送到执行器,另外搭进度服务又会引入重复状态,因此这个边界与现有所有者更合适。
具体改动
关键代码讲解
sendManagerQuestion在创建或恢复 Session 之前写入本地接收状态。准备期间取消只中止连接请求;真正提交开始后移除这个取消入口,转而等待服务器给出回合身份,不把已提交工作说成未发送。MessageActivity共用于完整时间线与总览回执,呈现实际报告的最近活动、耗时和无新活动的等待。追加指令在响应不确定时保留原操作标识和草稿,明确未送达后才允许新的标识;回合结束仍保留未发送文字。interruptManagerTurn复用既有会话与当前回合校验。拒绝、错误回执或晚到回执不能中止另一轮;部分输出继续可读。输入框只保留一个高度调整 effect,向上阅读时新输出不再抢走滚动位置。
整份差异包含八个产品文件、七个浏览器验证文件和两份双语 RFC,没有生成资源、私有运行记录或新队列。最后一次修订删除了重复输入框高度逻辑,并针对退役的快捷提示更新测试入口。
验证:最终源码的 TypeScript 构建和交付资源验证通过;打包浏览器的全部 25 个场景通过,覆盖延迟连接、发送前取消、失败重试、纠偏回执不确定、中断错配、结束竞态、手机宽度及保留阅读位置。相同连接等待反例在不可变基线 350f0f3 上因接收状态缺失而失败,在本次 head 上通过。16 项风险选择检查与三项直接差异检查通过,精确差异质量回执有效。已有证据的源码、基线、依赖和声明范围复核后未失效,没有重新调用付费模型。
对主干的风险
浏览器场景使用真实增量 HTTP/SSE 传输和合成执行器事件,因此证明的是打包 UI 的生命周期、回执和操作行为,不能证明原生 Provider 的取消、启动或持续恢复。历史消息缺少计时字段时不伪造耗时;本轮计时是浏览器投影,刷新后的持续计时不在此范围。桌面和 390 像素宽手机整屏已经检查,当前答复、等待说明和作用于本轮的按钮可以一起理解。
有两项原有本地失败,已分别在基线和当前 head 用同一命令复现,身份和错误细节一致:生成双运行时检查在 test_turn_contract_generation.py:263 预期一个生成对却看到两个;开发者书首页缺少 v1.2.3 发布锚点,后者由 #5318 跟进。此差异没有触及两者的因果路径,修改的不变量有独立通过证据。它们作为独立合并就绪问题保留,没有缩小扫描、提高限额或隐藏失败;本审查也不声明全仓检查全绿。
我的整体评价
我同意这个有界增量进入维护者合并决策:它解决真实可复现的等待不可见问题,复用通用组件,且保持执行权和回传归属。剩余重点是合并后安装真实 App,继续验证原生启动、恢复和原入口结果回传;团队独立验收与采用仍沿已有路线推进。产品运行路径按仓库规则留给维护者合并,本次审查不自动合并。



Goal And Delivered Outcome
A message could appear submitted while executor startup showed no reply or progress. The overview receipt also hid activity and turn controls available in the full conversation. This change shows a receipt before session preparation, then observed activity and elapsed time, with cancellation before dispatch and existing exact-turn controls after acceptance.
The shared manager/Goal conversation also preserves upward reading during streaming, provides a return-to-latest action, expands multiline drafts, and removes the suggestion strip from an established conversation. The existing App conversation RFC records the research and observable acceptance boundaries.
Intended base:
main. Owner: the existing TypeScript conversation presentation and Chat transport; no new capability, provider, scheduler or backend decision owner.Scope And Continuation
Complete within this presentation slice. It does not claim to cure provider startup timeouts, implement completion notifications, persist browser elapsed time across restarts, or complete delegated work. CLI/Lark behavior is unchanged because the affected path is the App/browser conversation renderer and session-preparation fetch.
A real read-only goal-wording request succeeded after repairing an installed CLI selection. An earlier live request still timed out before executor turn acknowledgement; sustained startup/recovery remains part of the existing App conversation acceptance, not certified by this UI change.
Validation
b42dc14d45f086a6b72d13a6193488f034ff10f0python scripts/chat_bundle.py build; source/delivery verification.conversation-startup: delayed connection, immediate receipt, cancellation without turn dispatch, retry and failure.conversation-activity: incremental SSE, stable elapsed across views, quiet wait, steering/interruption races, mobile/keyboard and preserved reading position.conversation-input: multiline draft growth, newline without submission, Goal/manager routing, explicit preview and retained drafts.Initial validation caught and corrected EOF whitespace, missing root TypeScript dependencies and a concurrent-edit guard. CI then exposed stale tests that used a suggestion button to infer turn completion after that button was removed from established conversations. The follow-up observes pending replies directly and opens configuration from the overview; the complete packaged browser suite now passes. The final branch is rebased on main 350f0f3 and removes a duplicate composer height effect. The same startup regression fails on that base and passes on this head. Local architecture replay found two unchanged baseline failures: generated-twin census expects one generated pair but sees two, and the developer book lacks its v1.2.3 release anchor (tracked by #5318). Both fail with the same identity and detail on base and head, outside this presentation path. Merge readiness must resolve these separately; neither failure is hidden or weakened. The prior live Sol result is reused because its executor path is unchanged by the rebase/refinement; a new paid model call was not made. Generated assets and live evidence remain outside Git.
Frontend / Visual Evidence
UI impact: changed. Synthetic screenshots are attached in the conversation: before startup receipt, after overview waiting, desktop conversation and narrow conversation. The before image uses the previously installed release renderer with a synthetic request; after images use the candidate packaged renderer and synthetic SSE.
Attention review: one observed activity line plus elapsed time; details expand on demand. Quiet waiting is explicit, not a fake percentage or changing phase. Controls remain scoped to the actual turn. Drafts grow within 120px, active conversations lose a redundant suggestion strip, and streaming no longer steals the reader's position.
Type of Change
LoopX Area
Boundary Checklist