ADR turn-process-and-thinking-display:回合过程与思考展示
英文源 ADR 是状态与决策内容的最终依据。
- 状态:已接受
- 日期:2026-09-17
- 修订:2026-10-22
- Issues:#510、#461
- 修订对象:D071、ADR 0242
背景
模型在回答一次用户请求之前,可能多次交替输出推理、工具调用和进度文字。仅使用分散 的活动组,会让进度文字与最终回答处于同一视觉层级;仅使用一个扁平的过程容器,又会 让较长的工具或搜索序列难以浏览。部分用户还需要稳定的思考状态提示,而不是快速变化 的推理正文。
决策
所有已加载的助手回合条目都使用同一套回合过程展示:投影为一个可折叠的过程披露, 以及其后的最终回答。思考、工具、中间进度文字以及该回合的 Bash 命令行都按转录顺序 保留在这个披露内。流式输出时,暂定为回答的末尾助手文字保持可见;如果随后出现工具或 思考活动,该文字会移入过程,但不会改写已存消息。UiMessage 没有语义化的最终回答标记, 因此渲染器不根据措辞猜测。用户消息、系统消息和压缩分隔线继续保留原有回合边界。
每个回合只渲染一个过程披露。回合在给出答案之前产生的所有行都位于其中——活动组与 Bash 命令行同样如此——因此长回合可以用一次操作收起,而不会在答案上方留下一列并列披露。答案本身 位于披露之外。未操作的过程在回合完成时收起,因此只剩最终回答;若回合没有产出最终文字, 过程标题及其错误或待处理操作面仍会保留。
在该披露内部,活动如何分组由显示模式决定。AppSettings.transcriptDisplayMode 取值为 flat、command-first 或 fully-folded;缺失或无效值解析为 fully-folded,即 v0.20.0 发布的布局。三种模式都只渲染一个外层披露。
fully-folded中,连续活动形成普通活动组:普通助手进度段落之间的一段连续工具、搜索、 思考或Bash/run 活动。Bash/run 行留在其周围的组内,命令读起来就是该组的另一行。 现有 Task 拓扑仍是其片段的容器,不会在普通活动组中重复渲染。command-first中,普通活动组仍会渲染,但每个Bash/run 别名都会提取为组旁的独立行: 相邻调用保持分离,详情在用户打开前保持收起。普通助手进度消息和命令都会结束当前组。flat不渲染任何嵌套活动组。外层披露按转录顺序列出活动工具、命令、思考和进度行,工具 详情保持收起。
在 command-first 与 fully-folded 中,只有在当前思考偏好下至少有两个可见项时才显示组。 单项活动直接使用自身披露,被隐藏的思考不会制造多余的组包装。
keepCommandsExpanded 已弃用:仅为使已持久化的设置仍可加载而保留,不再在设置中暴露, 也不再参与渲染读取;新的写入保存 transcriptDisplayMode。
组折叠默认值在各模式间统一,且不依赖思考偏好。凡渲染组时,拥有当前执行片段的组默认展开, 仅在用户未操作时于完成后收起;其他已完成组默认收起。只要活动组中记录过失败或被拒工具, 尚未被用户接管的活动组就会在后续恢复期间保持展开,并在回合完成后收起。关闭回合披露会一并 关闭其下的组,重新展开则恢复用户此前展开过的组。
2026-11-04 修正(#2094)替换上述已结算默认值。回合结束后其下两层默认都收起:活动组,以及 不再流式输出的思考行,因此展开一个已完成回合读到的是一串标题。两个可关开关承载读者的选择: autoCollapseSettledGroups(已完成小组自动收起)对任意大小的已结算组都生效,关闭后已结算组 全部展开——「四条以内保持展开」的旧档位随之取消,因为名为自动收起的开关不应仍然收起任何东西; autoCollapseThinking(已完成思考自动收起)收起已完成的思考行,关闭后所有会被渲染的思考行都 展开。两者各自作为其前置设置(显示思考、非平铺的 过程显示)的缩进子项出现,隐藏子项从不 写入任何值,所以在切换父项或布局后仍保留读者已选的值。组不再因为内部含有可见思考而强制展开: 收起组会遮住组内已展开的思考,重新展开则恢复各行自己的答案,两层互不抵消。进行中的工作永不 自动收起。组收起后只剩一行,因此组标题改为陈述构成:该组包含的动作(按语言自身的列举写法连接, 最多三项,超出以「等」收尾),其后是作为独立标记的调用次数,且最后才被省略号截断 (搜索并读取文件 · 12 次操作);思考会被命名但不计入操作数,只有思考的组改数段数。组标题不再 渲染问题计数:失败由失败的那一行自己报告,在组上重复只是噪音。
回合披露的标题陈述回合结果,并只保留有界元数据:状态、已记录的耗时与直接工具/搜索数。 它绝不回显正在处理的具体项,因为一条 shell 命令或搜索词可能任意长。其取值优先级依次为 失败、已停止、执行中、已完成:已记录的失败优先于停止,因为该回合没有产出答案,而看起来 正常的标题会掩盖这一点。停止取自被中止的消息,这是运行时唯一记录的信号——回合结果只区分 完成与失败。工具或思考仍在执行时,被中止的活动行同样记录停止;委派子任务的行不决定父回合 结果。执行期间,用户可能长时间停留的阶段(压缩上下文、恢复)会各自命名;当前步骤为推理时 显示 Thinking,瞬时阶段则显示为普通执行中。转录未记录时间时不显示时长,而不是显示为零; 此层不重复问题计数,失败已由状态本身表明。标题是一条由细线分隔的整行:状态、耗时、工具数 与折叠指示组成一个左对齐序列,指示器紧跟在工具数之后。悬停只加深文字颜色,不绘制背景。
披露与其组标题共用同一条左边缘。嵌套活动组沿用已发布的 v0.20.1 层级:组正文将子行缩进 12px,组的折叠栏位于该沟槽中——静息时不可见,悬停或聚焦时显示 2px 竖条,点击即收起该组。 外部回合折叠不会额外增加层级;由审核快照支撑的 Write/Edit 始终只有一层工具行,唯一标题 就是文件标题,其下紧接 diff 正文。
思考偏好是一个布尔值 showThinking。开启时,flat 与 command-first 中的每个思考行 默认展开,用户可将其收起;展开时显示完整推理 Markdown,收起时只显示 Thinking 指示器, 不显示摘要或摘录。fully-folded 保留已发布的例外:较早的思考行保持收起,最后一个活动 思考行仅在其为当前步骤时自动展开,完成后收起。关闭时不再渲染任何已完成的推理行,仅在推理 正在流式输出时保留整段运行的 TextShimmer Thinking 指示器。该微光为 1.2 秒线性扫过、 220 毫秒淡出,不使用转圈、脉冲圆点或逐字符动画;减少动态效果时保持静态。已存推理仍会 保留,因此重新打开该偏好会恢复这些行。被隐藏的思考不会制造空的组包装。
本决策早先引入的叶子默认值后来被移除。除上文的显示模式思考默认值外,条目载荷都不会自动 展开:工具调用、托管搜索或计划行在用户打开之前始终只是标题行,无论它位于活动组的哪一项, 且与思考偏好无关。组默认值不变,打开一个已收起的祖先仍会恢复已保留的条目选择,不会展开 所有后代。
每个标题只切换自己的层级。父子状态彼此独立:收起父级会保留后代选择,重新展开会恢复 这些选择,同级组不是互斥手风琴。用户操作某个条目时,会把所属组标记为用户接管,但不会 切换该组;完成事件不得收起包含用户已展开、聚焦或选择内容的容器。只要所属的保留会话 窗格仍存在,手动选择就跨流式更新、完成、偏好切换、单项变组和行重新挂载保留。窗格淘汰、 会话删除或渲染器重启会释放这些展示状态;它们不写入消息或宿主设置。
搜索和导航只展开目标所需的祖先路径:拥有该消息的回合过程,以及存在时的活动组。条目级 精确定位不在本次范围内,各行详情仍由各自的折叠控制。同一请求重新渲染时,不会反复覆盖 用户之后的手动收起。被偏好隐藏的推理会保持隐藏,直到用户打开 showThinking。助手错误、 中止后的末尾部分回答、权限/提问/计划/目标决策及其他待处理操作面必须位于隐藏过程之外, 无需展开过程即可操作。
“设置 -> AI -> 默认项”提供一个 Show thinking 布尔开关,以可选的 showThinkingAppSettings 字段持久化;并在其后提供「过程显示」分段控件,标签为「平铺显示」 「命令工具优先」与「全折叠显示」,以可选的 transcriptDisplayMode 字段持久化。缺失或 无效的 transcriptDisplayMode 在渲染层与主进程设置规范化中都解析为 fully-folded。 showThinking 缺失或非布尔值会回退到旧版 thinkingDisplayMode 字段:显式 compact 隐藏推理,而 detailed、未知值或缺失值都显示推理。旧版 thinkingDisplayMode 与已弃用的 keepCommandsExpanded 仅为持久化设置兼容性保留,不再在界面中暴露; keepCommandsExpanded 也不再参与渲染读取。这些偏好只改变展示,不改变提供商思考级别、 运行时或模型上下文、已存推理、导出、权限、执行或复制载荷,思考偏好也不控制回合过程或 活动组的折叠。过程标题使用已记录的计时、直接工具/搜索计数和运行状态;不会 重复计算委派子任务,也不会把单个失败工具误报为整个助手回合失败。顶层折叠不重复显示 问题计数;活动组标题同样不再显示问题计数,只陈述构成与操作数。
结果
- 每个回合一个披露,让最终回答与待处理操作保持可达,并使长回合可以用一次操作收起。
- 活动组的折叠默认值在各显示模式间统一:运行中的工作保持可见,未操作的已完成组默认收起, 无论思考偏好如何都保留用户明确的披露选择。关闭回合披露会关闭其下的组,重新展开则恢复 用户此前展开过的组。
- 已结算回合默认收起其活动组与已结束的思考行,两个新开关是唯一让它们保持展开的方式; 「四条以内保持展开」与「含可见思考即展开组」两条规则取消,两层不再彼此抵消;组标题改为 陈述构成与操作数,组上不再显示问题计数。
- 当
showThinking关闭时,不再渲染任何已完成的推理行,仅在推理流式输出期间保留整段运行的 TextShimmerThinking指示器。已存推理仍会保留,重新打开偏好时重新出现。 transcriptDisplayMode保留三种布局,并默认使用已发布的fully-folded布局。flat移除嵌套组,command-first将命令提升为独立行,fully-folded让命令留在 所属组内;三者都只渲染一个披露,且模式在渲染时读取,因此切换后立即重绘,而无需等待 新消息。showThinking开启时,flat与command-first中的思考行默认展开;fully-folded保留仅活动行自动展开的例外。- 标题用一行说明回合的结果,并只保留状态、已记录的耗时与直接工具/搜索数。标题行由细线 分隔,折叠指示紧跟工具数,悬停只改变文字颜色。回显当前命令的做法已被移除:它会把计数 挤出该行,并且与打开该项已经能看到的内容重复。
- 披露记忆是以稳定回合、组和条目标识为键的窗格展示状态,不是持久化转录契约,也不 属于中央工作流 store。
- 只对已加载的转录条目分组;不会重建未加载历史,也不会跨压缩边界合并回合。
验证
2026-09-20 的修订按本次请求仅进行静态检查和编译。关联的 E2E 场景用于描述源码与设计 审查中的预期行为;本次修订不新增或运行单元、组件、集成、浏览器、Electron 或 E2E 测试。同步后的场景文本见 E2E-CHAT-turn-process-and-thinking-display。 2026-09-27 修订由 apps/desktop/test/turn-process.test.mjs 覆盖默认选择,并由 pnpm test:e2e:transcript-disclosure 在真实 Chromium 中验证运行中到完成时的自动收起和 用户展开状态保留。 2026-10-16 修订由 apps/desktop/test/thinking-visibility.test.mjs 覆盖 showThinking/旧版 thinkingDisplayMode 的解析优先级,并由 i18n 目录测试覆盖新增的 settings.showThinking 文案。界面、解析器与 E2E 场景在集成候选上验证;同步后的场景文本见 E2E-CHAT-turn-process-and-thinking-display。 2026-10-21 修订由 apps/desktop/test/turn-process.test.mjs 覆盖模式分段(包括 flat、command-first 与 fully-folded)及标题阶段优先级; apps/desktop/test/transcript-display-modes-ui.test.mjs 覆盖渲染层的模式分段接线、 思考行默认值以及收起或隐藏思考指示器使用的整段运行 TextShimmer; apps/desktop/test/transcript-display-mode-settings.test.mjs 覆盖设置行标签与搜索索引; apps/desktop/test/settings-roundtrip.test.mjs 覆盖规范化、写入校验与 fully-folded 默认值。同步后的场景文本见 E2E-CHAT-turn-process-and-thinking-display。 2026-10-22 修订由 apps/desktop/test/turn-process-header.test.mjs 渲染顶层标题,覆盖 状态、耗时、工具数、内联指示顺序,以及完成与失败回合都不显示问题计数; apps/desktop/test/turn-process-header-style.test.mjs 覆盖整行细线、仅文字变色的悬停 与内联指示位置;turn-process.test.mjs 与 transcript-style.test.mjs 继续覆盖阶段 优先级与共享标题几何。同步后的场景文本见 E2E-CHAT-turn-process-and-thinking-display。