apps/web/components/chat/messages/ 与 app/styles/chat/。tool-presentation.ts:命令绿(终端)、文件修改琥珀(笔)、读取蓝(文件)、搜索青(放大镜)、网页与浏览器靛(地球或指针)、子代理绿(机器人)、记忆品红、规划石板灰、媒体玫红、系统暖灰、其他函数橙(锤子);思考保持紫、LLM 保持青。失败 = 红色方块加 ✗;运行中 = 正常图标外加一圈绕方块旋转的锥形扫光。行文字:动词标题(运行、修改、网页搜索…)字重 500,随后是标识参数的等宽小标签,再是结果首行的淡色文字。行内不出现原始 JSON;完整参数与输出仍在右栏。FunctionInvocation { name, kwargs } 的两种编辑方式。表单点“运行”直接提交 typed kwargs;普通输入框中的整段文本若精确匹配一个已注册函数及其命名参数,也在创建 user message 之前转换成同一个对象并提交。两者都只产生下面这一条 ProgramRun,不创建 UserBubble,也不经过一次额外的 Agent 文本回合。带前后说明文字、反引号或代码围栏的函数片段仍是普通消息,避免把讨论代码误执行。| 输入 | 入口判定 | 持久化与显示 |
|---|---|---|
gui_agent(task="…", surface="browser") | 整段精确匹配、函数已注册、仅命名字面量参数 | POST /api/function/gui_agent → 单条 ProgramRun |
| Favorite Programs 的 gui_agent 表单 | 表单 schema 生成同一个 typed kwargs | POST /api/function/gui_agent → 单条 ProgramRun |
请解释 gui_agent(...) 或 `gui_agent(...)` | 不是整段函数表达式 | 普通 UserMessage → Agent |
sendChatMessage,不得写 pending user text。附件、运行中排队和系统 decision 不隐式变成函数参数。function-invocation.test.mjs 覆盖直接调用、普通文本边界、typed kwargs、成功绑定、导航与失败回滚,GUI 不可执行结果和 metadata 由对应 Python 回归覆盖,并已通过独立规格审查。attachCards 或 contextTree 中;用户展开后可查看同一条持续更新的时间线记录。const [open, setOpen] = useState(false),流式状态不参与初始展开值。card_id 对应的行改为“已完成/出错”,不追加副本,也不删除。running 只影响摘要状态动画 和步骤状态,不决定外层展开状态。收起不会删除记录;用户展开后,原记录仍按时间线行显示。| 调用路径 | 实时数据 | 页面节点 | 共同的可见性控制 |
|---|---|---|---|
聊天中的 agent() | sub_agent 事件按稳定 card_id 更新 attachCards | SubAgentStep | ExecutionStripconst [open, setOpen] = useState(false) |
auto_workflow 内部 selection agent | tree_update 更新 contextTree | TreeStep 子节点 |
ExecutionStrip 以 false 作为流式和历史消息的共同默认状态,手动切换优先。相关入口:execution-strip.tsx、chat-stream.ts、runtime-block.tsx、check-spawn-cards.mjs。callerId;父分支在该消息之后的继续内容不显示。auto_workflow 内只有 TreeStep 而没有 attach 指针的节点,仍只能打开右栏详情,不显示这组分支导航。FileTypeIcon:@pierre/trees 内置图标集,以内联 SVG 渲染,15px 图标置于 16px 框内),按文件类型着色,浅色与深色主题各有一套配色,.ts、.md、.json、.py 一眼可辨;标题区保留铅笔图标。标题计数取本轮 file_count,列表不得与它无声地不一致。折叠时显示三行,并用“再显示 N 个文件”展开其余已加载行(最多 20 行)。计数中卡片未列出的文件——超过 20 个,或有界摘要尚未加载完整列表——在列表末尾合并为一行“还有 N 个文件 — 在审阅中查看”,点击与 Review 按钮相同,打开 Review 标签。持久化摘要最多保存 20 行;摘要计数多于所列行时,卡片通过 review_scope 请求完整列表,服务端此时读取完整变更日志而不是有界摘要。--font-sans,标题、路径、统计、状态与按钮不切换独立 monospace 字体,数字只保留 tabular alignment。header 固定 40px,左侧内边距为 12px,FeatherIcon—标题与标题—统计均使用 12px 间距;左侧使用用户指定的 19px FeatherIcon,并以一条横线分隔摘要与文件列表。深色主题中,header 和 footer 使用 --bg-tertiary,文件列表使用 --bg-primary;浅色主题中,整张卡、header、Review 按钮和 footer 全部使用 --bg-primary,不使用阴影或深色上下色块,只由外框和分隔线建立边界。所有主题的文件行默认透明,只有 hover 时叠加 --bg-hover;footer hover 同样只叠加 --bg-hover。FeatherIcon 表示本轮包含直接文件编辑,不使用网站 logo;hover 使用组件定义的 1.6 秒位移与旋转序列,reduced motion 下停用。header 的 FeatherIcon、14px 标题、统计区、13px Undo/Redo 与 Review 按钮必须按同一垂直中心线对齐,不使用 baseline 对齐;方向图标使用 1em 与按钮文字等高。总增删数字始终同时显示,包括 +0 或 −0;统计字号为 12px,其下 2.5px 双色比例条只编码 additions / deletions 的真实占比,不增加分类 chips 或装饰性数字。卡片以自身 inline size 建立 container;卡片宽度 ≤420px 时标题从 “3 files changed” 缩写为 “3 files”,FeatherIcon、统计和操作保持可见,并恢复 6px / 5px 的紧凑间距;viewport media query 只作为兼容路径。历史操作预检未通过时,header 不显示 Undo/Revert/Redo/Reapply,而是在 Review 左侧显示一条 12px 主题强调色状态提示;提示单行省略,title 保留全文,窄卡片限制为 92px。该状态不再在文件列表或 footer 下追加独立提示行。成功 Undo 后显示 重做;历史 Revert 的反向操作显示 重新应用。两者都调用同一安全 reapply transaction 并重新预检,不维护独立线性 redo 栈。Review 使用中性色描边按钮;Undo / Revert 使用文字加回退图标,不使用强调色。Code / Tests / Docs / Large 分类只在 Review 中出现。文件列表到文件行的四边间距统一为 4px;文件行固定 28px,行内左右内边距为 6px,文件路径使用 13px 产品 sans,增删统计使用 12px 产品 sans 并固定列宽;整行导航,不放展开箭头或 hover 操作组。唯一的展开控制属于 Show more footer;展开后 footer 只显示 13px 折叠,完整 Review 始终由 header 的 Review 按钮进入,不再追加 “Review all” footer。| 系统 | 本轮 / checkpoint | 审查 | 撤销 / 回退 |
|---|---|---|---|
| Codex | 开源 TurnDiffTracker 只消费 committed apply_patch 精确 delta,不重读 workspace;delta 不精确时清空本轮 diff。 | /diff 单独使用 Git:tracked 走 git diff,untracked 走 git ls-files --others --exclude-standard。 | 开源 thread/revert 明确只回退对话历史;Codex App 文件 Undo 的客户端实现未在当前开源仓库中确认,不推断。 |
| Claude Code | 每个 user prompt 建 checkpoint;只跟踪 Write、Edit、NotebookEdit 等直接文件编辑工具。保留最近 100 个 checkpoint。 | Desktop/Web 使用 session 级增删统计入口;打开后左侧文件列表、右侧单文件 diff,支持行级评论和再次交给 Agent 修改。 | 代码与对话可分别恢复;Bash、一般后台 sub-agent、外部并发修改、symlink/hardlink 不保证恢复,没有 tracked edits 时不显示代码恢复选项。 |
| OpenProgram 当前实现 | 直接工具 checkpoint 之外,还在每次 Bash 前后递归扫描最多 20,000 个文件并预复制不超过 5 MiB 的候选内容。 | 聊天卡内请求完整 diff;历史消息逐条请求文件列表;shadow Git 和当前磁盘 fallback 混用。 | 大文件没有 baseline 时被记录为 pre_existing=false;Undo 可能删除原有文件,且部分失败后仍可写入 reverted 状态。 |
| 结论 | 设计项 | OpenProgram 处理 |
|---|---|---|
| 采用 | Codex 的精确增量归因 | 本轮统计只来自 committed file mutation event;没有精确 before/after 就不进入本轮卡。 |
| 采用 | Claude/Codex 的独立审查面 | 聊天只保留摘要;Review 使用左侧文件导航、右侧单文件内容,并支持行级评论。 |
| 调整 | Claude 的 session diff 与 Codex 的 turn/repo diff | 放进同一个 Review tab 的三个 scope:This turn、Current branch、Workspace;切换 scope 不改变术语含义。 |
| 调整 | Claude 的 checkpoint 恢复 | 保留 turn 级快速 Undo,但必须先完成全量冲突预检;恢复记录作为新的不可变 journal transaction 保存。 |
| 拒绝 | Bash 目录扫描归因 | 删除 Bash 前后 cwd 遍历与候选文件预复制。普通 Bash、后台进程和外部修改不计入本轮,也不能由本轮 Undo。 |
| 拒绝 | 近似本轮 diff 与静默部分恢复 | 无法证明来源时只进入 Workspace Review;Undo 预检失败时不修改任何文件,并列出冲突路径。 |
| 调整 | 参考产品的 header 操作层级 | 采用“文字 Undo + 中性描边 Review”的主次关系;左侧使用 FeatherIcon 表示直接文件编辑,尺寸、间距、颜色和 Review 页面继续沿用 OpenProgram 视觉系统。 |
| 范围 | 权威数据源 | 包含 | 撤销 |
|---|---|---|---|
This turn | 当前 turn 的精确 mutation journal | 主 change set;关联 child change set 按真实 producer 保留,并通过 origin 分组,不复制 mutation。 | 仅当全部记录为 recoverable 且 current digest 等于记录的 after digest。 |
Current branch | 当前 active lineage 的 mutation projection | 所有已完成 turn 与显式 revert/restore/reapply;不包含 sibling branch、普通 Bash 和外部写入。 | 从具体 turn/checkpoint 发起,不提供无范围的一键 branch Undo。 |
Workspace | Git 跟踪差异 + ls-files --others --exclude-standard | 当前未提交 tracked/untracked 文件;遵循 .gitignore。非 Git 工作区显示 unavailable,不使用目录扫描替代。 | 无。Workspace 变化可能来自用户、其他 session 或后台进程。 |
直接编辑工具在写入前记录规范路径、文件类型、before_digest 与可恢复 baseline。无法安全保存 baseline 时标记 recoverability=unavailable,绝不写成“原文件不存在”。
写入成功后记录 after_digest、operation、行数、binary/large、turn_id 和 actor_id;失败不产生 committed mutation。
turn finalize 只归并本轮 mutation,生成净文件列表和增删统计并随 transcript 持久化。复杂度只与 changed paths 有关,不扫描 cwd。
Review 先读取摘要;选择文件后才请求一个有界 diff。切换文件取消旧请求;聊天 DOM 永远不挂载 diff。
agent_loop._snapshot_cwd、_walk_scan 与 _checkpoint_changed_files 不能继续参与文件归因。特别是“超过 5 MiB 未暂存 → 使用不存在路径 → pre_existing=false”必须消失;baseline 缺失只能表示不可恢复,不能表示新建文件。| 阶段 / 状态 | 规则 | 可见结果 |
|---|---|---|
| 适用条件 | 每个文件必须有精确 operation、before/after digest;普通文件才可恢复,symlink/hardlink 与缺失 baseline 标记 unavailable。 | 任一文件 unavailable,卡片不显示可执行 Undo;Review 解释具体原因。 |
| 预检 | 恢复前重新读取所有 current digest。新建文件只有仍等于 after digest 才可删除;修改/删除/rename 同样要求未被后来编辑。 | 任一冲突则整次 Undo 不写磁盘,状态为 blocked-conflict,列出冲突路径。 |
| 应用 | 全部预检通过后,将恢复内容写入同目录临时文件并原子替换;多文件操作保留回滚 staging。 | 意外 I/O 失败时回滚已应用项,不能把部分成功标为 Reverted。 |
| 记录 | 成功恢复追加 revert_of=<turn_id> transaction;原 turn 状态由 journal 推导。 | 聊天与 Review 显示 Reverted,历史文件列表仍可审查;不修改原对话内容。 |
| 路径 | 目标上限 | 降级 |
|---|---|---|
| 轮次收尾 | 不遍历 workspace;只归并 mutation journal 中的 changed paths。 | 单条 mutation 缺少精确信息就排除并记录诊断,不生成近似统计。 |
| 对话记录 | 摘要随消息返回;首屏最多 3 个文件,不再为每条历史消息发送 list_turn_files。 | legacy 消息只在进入视口或主动 Review 时查询。 |
| 文件列表 | 服务端每页 100 个文件;前端只保留相邻页并支持键盘导航。 | 分类统计来自 summary,不要求先加载全部行。 |
| 选定差异 | 同时只挂载一个 diff;每批最多 200 行或 256 KiB,按 hunk/page 继续加载。 | binary 或超大单 hunk 显示统计、原因与 Open file,不把不完整内容冒充完整 diff。 |
| 渲染预算 | diff 计算有明确时间预算;超预算返回 metadata,Review 不阻塞聊天和 Agent 完成。 | 允许稍后重试或打开原文件,绝不回退到“before 与当前磁盘”的跨轮近似 diff。 |
| 动作或状态 | 结果 | 边界 |
|---|---|---|
| Review / 文件行 | 打开同一确定性 r:<sessionId>:<assistantMsgId> center tab;文件行同时选择路径。 | 不加载聊天内 diff;重复点击只聚焦或更新 selection。 |
| 布局 | 未分屏时复用现有 group,把 Review 放到聊天右侧;满员 split 时作为普通 active tab。 | 不替换已有 peer,不增加第三 pane,不新增第二套 tab store。 |
| Scope 切换 | This turn、Current branch、Workspace 保持同一左 rail / 右 diff 构图,标题和来源标签同步变化。 | Workspace 不显示 Undo;ignored 文件不出现;非 Git 明确 unavailable。 |
| 行级评论 | 点击 diff 行添加评论;多条评论在下一条 prompt 中作为结构化文件位置一起发送。 | 评论不直接修改文件,不假装 code review 已执行。 |
| 大文件 / 二进制 | 显示精确统计、diff unavailable 原因和 Open file。 | 不渲染完整大文件,不把日志自动归类为 Agent 修改。 |
| 撤销冲突 | 卡片显示 Review conflict;Review 定位冲突文件。 | 没有 Force undo 快捷按钮,避免覆盖用户或其他 session 的后续编辑。 |
| 范围 | 首选位置 | 明确排除 |
|---|---|---|
| 精确 mutation 与恢复 | programs/tools/files/、store/snapshot/checkpoint/、turn context/finalize 与 agent/internals/_revert.py。 | 不再给 Bash 增加目录 watcher,不更改用户 Git,不从当前磁盘反推本轮。 |
| Review 协议 | ws_actions/turn_files.py、消息 metadata、现有 Git helper;新增分页 summary/diff 请求。 | 不返回无界字符串,不保留 approximate fallback。 |
| 中心审查标签页 | center-tab-ids.ts、center-tabs-store.ts、center-tab-groups.ts 与最小 Review pane。 | 不实现新窗口、modal、第三 pane 或参考产品品牌元素。 |
| 聊天卡 | turn-files-chips.tsx、用户提供的 FeatherIcon 与现有 CSS。 | FeatherIcon 只标识直接文件编辑,不放网站 logo;不保留 inline diff、文件行箭头、hover 操作组或参考产品品牌元素。 |
--bg-input 底色(浅色主题为白色,深色主题按主题取值)加 --composer-shadow。助手回复平铺在页面上,没有气泡。把鼠标移到下面的消息上查看操作行,按钮停留后显示提示。pyproject.toml 一致。--user-msg-bg,每个主题都等于 var(--bg-input);阴影是静止的 --composer-shadow——已发送的消息不是控件,悬停不加深阴影。气泡内的代码块和粘贴折叠块用 --bg-primary 内嵌底色,与气泡表面拉开。输入框上方的排队消息是尚未发送的用户消息,使用同一表面(10px 圆角)。--bg-input 底色、23px 圆角,静止时 --composer-shadow,悬停或内部聚焦时过渡(180ms)到 --composer-shadow-focus;宽度占满整列。框内依次是保留的附件(可移除)、新加附件条、与主输入框相同的输入行(支持 @ 文件提及),底部一行为:左侧官方 ghost 圆形图标按钮(icon-sm)中的 Solar 回形针,提示“添加图片或文件”;右侧“取消”(elevated sm)与“保存并重新发送”(默认主按钮 sm)。Esc 取消,⌘/Ctrl+Enter 保存;可把文件拖到框内。编辑期间隐藏操作行。流式、已完成与恢复后的助手消息共用 ExecutionStrip、ThinkingStep 和 FunctionStep 组件。缺少有序内容块时,按已有思考与工具记录的存储顺序适配展示;此回退不重建缺失的交错顺序,也不编造工具记录。工具结果、错误状态、标识符和完整输出引用保持完整。完成后不切换到旧版带边框的 ToolsBlock 表格。
实现验收:完成包含工具调用的一轮,展开执行摘要,再重新加载对话;仍可使用相同的共享行与详情交互。
聊天 Markdown 已在 $$/$/\[/\( 之前暂存完整内容块;处理顺序对应 marked 并在清洗后将其还原为转义文本。React 消息气泡仍需运行 KaTeX: MarkdownText 在绘制后排版,聊天区域固定路径则在观察到的消息列上调用 typesetMath 。未闭合的流式公式不构成完整暂存对;收到闭合符后的下一次绘制才排版。清洗、代码、链接和普通转义行为保持不变,不引入新数学库。
验收:示例 \(d_t\) / \(v_t = (d_t - d_{t+1}) / d_t\) 在助手气泡中生成 KaTeX HTML;块级 \[/$$ 以及行内 $ 也如此。无公式正文和未闭合起始符不排版;无效公式不抛出异常。
助手回复不显示 token 与服务档位用量页脚。当前执行片段使用原有文字扫光与运行小点;正文页脚不添加加载标识。
对话记录使用双向、带字节预算的分页。每条连接持有一个小型 LRU,存储带消息 ID 索引、磁盘支持的不可变快照。分页请求只读取选定展示组,保留工具后代节点和压缩元数据。快照 token 限定于连接、会话及捕获的分支 head。替换快照或断开连接时释放临时文件。
浏览器目标缓存四个对话,允许正在显示的分栏和在途请求暂时超过限制;删除对话时释放分页引用。每个已加载对话记录最多保留六个普通分页,内容预算为 8 MiB;为保留单个大轮次,允许一个不可拆分分页。淘汰从阅读位置的相反方向进行,绝不删除持久化记录,并保留活跃更新。向任一方向回滚时自动取回被淘汰分页。视口外已测量行卸载但保留高度;被淘汰行的高度记录删除。
预取距离随滚动方向与速度调整,并有最大值。同一时刻只运行一个分页请求,失败时指数退避重试。不可见分栏停止请求,过期响应不能覆盖新代次。插入或淘汰分页时,在绘制前恢复可见消息及其偏移。恢复依据消息 ID,而非旧窗口中的像素偏移。“跳到最新”直接获取最新窗口。
验收使用30万条消息的合成来源:反复双向分页时,缓存分页、渲染行与测量记录保持有界;延迟下快速滚动仍保留可见消息;过期响应、重连、分支变化与实时更新不能破坏窗口。索引建立后,后端分页读取不得扫描或解析完整快照。冷启动快照构建单独测量。
协议 v2 将完整图延迟到视图可见时请求;普通分支元数据请求不包含图正文。冷启动快照构建只读取并补全权威分支一次;之后的索引分页避免完整恢复。
| 模块 | 职责 |
|---|---|
| message-list.tsx | 消息组合与已测量行渲染 |
| use-chat-area-stick / use-message-viewport / use-history-window | 跟随、视口测量与活跃历史生命周期 |
| history-window / history-viewport | 有界分页存储与消息锚点操作 |
| session-history-loader | 网络请求、代次检查与状态协调 |
| session_history.py | 磁盘快照索引与有界分页读取 |
交互契约:中间历史窗口的底部不是对话最新位置。主分栏与拆分分栏共用跟随、自适应渲染和跳转行为。存在更新历史或请求失败后,跳转仍可使用;重复点击共享一个待处理意图。滚轮、指针和键盘交互在待处理跳转或已保存位置恢复改变窗口前取消它们。普通分页仍补偿当前阅读位置新增的行。分栏卸载保存最终阅读锚点。连接恢复后继续自动加载,不保留过期重试延迟。
交互验收:浏览器测试覆盖中间窗口底部、失败与重复跳转、被打断的延迟恢复、独立拆分分栏及卸载/重新挂载。这些交互优化已实现并通过独立规格与质量审查。浏览器验收还检查卸载后排队动画帧不会破坏已保存锚点。
性能契约:捕获消息既无压缩覆盖、也无需要图注解的 spawn/attach 关系时,有界聊天加载跳过图构建。需要注解时,共享图构建器执行相同语义过滤但不计算视口几何;打开 DAG 仍请求完整布局。首次持久化恢复的复杂度仍随存储节点数线性增长。Markdown 缓存使用256项 LRU 和 8 MiB 预算,按 UTF-16 源文与清洗输出长度估算;单项超预算时仍渲染但不缓存。缓存策略绝不绕过清洗。
性能验收通过公开加载处理器与生产浏览器组件使用已持久化合成消息,分别记录耗时、帧间隔与保留堆内存。稳定回归检查断言跳过的工作、语义等价、缓存淘汰和有界保留,不断言特定机器计时。性能优化已实现并通过独立规格与质量审查。公开处理器回归验证跳过图工作与压缩等价;浏览器回归验证字节预算淘汰、LRU 提升和超大条目不缓存。耗时与保留堆比较属于合成测量,不保证完整 App 工作负载的性能。
实现状态:已实现。30万条消息合成来源的浏览器测试验证有界双向分页、延迟传输下快速反向滚动、已保存消息恢复、实时行保留和加载期间跳转。后端索引读取、快照清理与 Web 回归测试集通过。冷构建仍读取权威分支一次;合成测量不能证明真实大型附件或工具输出的延迟。
仅将原有空回复 thinking… 提示旁的加载标识替换为新版 18px 开口双环。双环反向旋转并交替改变半径和线宽,颜色跟随主题;减少动态效果时保持静止,强制颜色模式使用系统文字色。
执行摘要、思考步骤、函数步骤、嵌套调用、分栏标题、重试提示和正文页脚不使用此标识。不再按照工具、思考或正文阶段增加标识位置。函数时间线恢复原有布局、文字扫光、运行小点、展开结构与详情交互。
验收:空回复加载提示显示一个新版标识;函数调用、思考内容和正文到达后,不在时间线或页脚添加双环。审批与终态不显示加载标识。保留独立的历史加载、嵌套进度和消息稳定性修复。实现与验收证据记录在 generation-motion-layout 任务报告中。
消息 ID 和有序 blocks 决定聊天内容。执行树补充所属回复,不通过状态树重新生成聊天。历史快照按同一消息合并已收到的进度:运行中的旧快照不能删除函数调用、缩短文字或将已结束回复恢复为运行中。终态快照更新状态与元数据,未携带执行记录时保留已收到的记录。切换分支和历史窗口仍删除窗口以外的行。
调用树保留持久化 path。同一函数的多次调用保持独立,在所有被文字分隔的执行组之间,每棵调用树只匹配一次。函数结束后保留原来的执行摘要;直接执行函数继续显示独立卡片。验收通过实际 reducer 和组件覆盖流式更新、部分历史、结束、迟到的调用树、错误、取消与重新加载。
实现状态:待验证。
排队消息在当前轮结束后按顺序发送;补充消息在执行器确认接收后,显示在接收前后的回复内容之间。补充记录保留独立用户节点,回复的有序内容保存边界引用,实时流、取消和历史加载使用相同边界。旧记录缺少边界时只按已持久化的前驱关系把补充放到所属回复前,不猜测文本分割点。
轮询只确认同一命令,不改变可见等待提示。等待确认期间不能重复发送、编辑或移除。明确拒绝后保留为排队消息;连接异常保持待确认,不作为新一轮重发。附件保持普通排队语义。每个会话独立,排队中编辑保持顺序。
流式 steer:普通文本或思考生成期间接收的补充指令会结束当前模型请求,保留已生成内容,在已有的模型请求完成边界持久化应用指令,然后启动下一次请求。旧请求关闭后才继续。工具参数生成、运行中的工具和结构化输出继续使用原有安全点;steer 不取消或重复工具调用。定时检查也覆盖模型暂时没有输出的情况。
等待 steer 时停止:保留部分回复及其当前历史位置。因停止而被拒绝的补充消息保留为未发送草稿,通过明确的发送按钮重试,不自动转成下一轮。取消状态投影仅以比较并交换方式将当前顶层轮次从自身用户节点推进到已有回复节点,不改变后续消息或用户选择的其他分支。
实现状态:流式中断与停止保留已通过独立规格及质量审查、相关测试和完整验证;已安装 App 验收独立记录于发布证据。
失败回复保留已生成正文及有序的思考和函数记录。终止提示位于这些内容之后、消息操作之前。简短标题说明失败原因,技术详情默认折叠并按纯文本显示。不增加自动重试。
正文块与错误详情分别存储。节点 output 保留旧有错误文本语义,供模型上下文及非 Web 调用方读取;Web 映射从有序正文块中恢复已生成内容。失败节点在最终事件发出前保存详情、分类、可重试性和重试等待时间。刷新后恢复相同提示。兼容旧记录中的错误正文,不修改历史,不在错误提示中重复回复内容。
范围为主聊天错误、共享助手气泡及历史映射。取消、审批、嵌套函数详情、重试分支和 Goal 报告保持现有语义。沿用既有提供商错误分类设计,只补充持久化展示,不新增错误存储或第三方 UI 依赖。
验收:通过真实回合入口先产生正文和工具再失败;流式和冷启动历史均显示正文、记录及一条末尾错误。空回复和旧失败记录可见,成功和取消状态不新增错误提示。窄屏和深色主题中可展开详情。
发布回归继续验证浏览器权限继承和高层 agent 委派。已绑定页面的测试显式提供绑定,并验证现有的同一观察连续失败三次后停止及具体失败原因。这些测试不改变浏览器工作流和权限策略。
实现状态:实现、独立规格与质量审查及完整声明验证集均通过。浏览器回归测试与现有绑定页面路径及失败次数限制一致。已安装 App 验收独立记录于发布证据。