diff --git a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.i18n.yaml b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.i18n.yaml index c45ef1fc30..20a912b5f3 100644 --- a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-09-14-step-process-disclosures.md -2026-09-14-step-process-disclosures.md: cf2a6d4a3017d3a8e25180b482a0262569190f26 -2026-09-14-step-process-disclosures.zh.md: c5380c56acff7a098e72530ede625d35ca7a8739 +2026-09-14-step-process-disclosures.md: 127556fc68d6c345041ab4c475994c1636a80887 +2026-09-14-step-process-disclosures.zh.md: d1e11d6c792ce2e13b8b100e3c37a4ce2c05e59e diff --git a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.md b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.md index cf2a6d4a30..127556fc68 100644 --- a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.md +++ b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.md @@ -26,7 +26,7 @@ Whole-turn folding checks each Turn independently: while history is paginated, i The whole-turn control appears at the start event and remains expanded and disabled during execution. Compact uses it as the sole turn-level activity label, displaying `Deep diving for …` (Chinese `深度求索中,用时…`) with a minimum of 1s and no leading icon; running, completed, stopped, and failed whole-Turn labels all use tertiary text at one pixel below the normal status size; Compact, Detailed, and Expanded use this whole-Turn control as the only turn-level running label. Its live clock refreshes once per second, shows whole seconds without padding single-digit seconds, and changes from minutes to hours at exactly 60 minutes. Normal completion fixes the clock, displays `Took …`, and defaults to collapsed. Cancellation and failure display `Stopped` and `Failed` respectively and remain expanded with a disabled control. -Work details provides Compact, Detailed, and Expanded defaults for the two disclosure levels. Legacy normal settings resolve to Expanded on read; new choices persist only current values. +Work details provides Compact, Detailed, and Expanded defaults for the two disclosure levels. Legacy compact settings remain Compact and normal settings resolve to Detailed on read; Expanded is a new option; new choices persist only current values. ## Consequences diff --git a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.zh.md b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.zh.md index c5380c56ac..d1e11d6c79 100644 --- a/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.zh.md +++ b/.agents/notes/implemented/feature/2026-09-14-step-process-disclosures.zh.md @@ -26,7 +26,7 @@ Status: implemented 整轮控件在起点事件出现,执行期间始终展开且不可点击。简洁模式将它作为唯一的轮次运行状态,显示「深度求索中,用时…」,用时最少为 1 秒且不带前置图标;运行、完成、停止和失败的整轮状态文案均使用 tertiary 灰度,字号比普通状态小 1px;简洁、详细和完全展开均只使用该整轮控件显示轮次运行状态。其运行时钟每秒更新,显示整数秒且个位秒不补零,满 60 分钟切换为小时。正常完成后固定时钟,显示「用时…」,默认收起。取消和失败分别显示「已停止」与「处理失败」,始终展开且不可点击。 -工作过程展示通过简洁、详细、完全展开三档控制两级分组的默认状态。旧 normal 设置读取为完全展开;新选择仅保存当前三档值。 +工作过程展示通过简洁、详细、完全展开三档控制两级分组的默认状态。旧 compact 设置保持简洁,normal 设置读取为详细;完全展开是新增选项;新选择仅保存当前三档值。 ## Consequences diff --git a/packages/client/ui-chat/README.i18n.yaml b/packages/client/ui-chat/README.i18n.yaml index bdf97867d5..3228790123 100644 --- a/packages/client/ui-chat/README.i18n.yaml +++ b/packages/client/ui-chat/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/client/ui-chat/README.md -README.md: 429f4d43b834e42a6f43c61edbc7f2a022ed7fa5 -README.zh.md: 68f0f1f55c5616846c8e4edea5dbeed08728b048 +README.md: b434e547f1930f9be2d4323b90a023cca7cb5188 +README.zh.md: 2f2546e23c2c1b45af84e40b04a19fa1d2c85657 diff --git a/packages/client/ui-chat/README.md b/packages/client/ui-chat/README.md index 429f4d43b8..b434e547f1 100644 --- a/packages/client/ui-chat/README.md +++ b/packages/client/ui-chat/README.md @@ -57,7 +57,7 @@ The completed-turn action footer sits at the bottom of its Turn, 20px below the Each reasoning row starts collapsed, including during streaming and in reasoning-only replies. Clicking the row opens or closes its complete Markdown; incoming answer text, Tool calls, and stream completion preserve that choice. Expanded reasoning uses compact secondary typography: headings add bold weight without changing text size, line height, or color. During streaming, the collapsed preview advances only after a paragraph's first line completes; an unfinished first line does not replace the current preview. The preview starts at its left edge and fades under a right-edge mask when it exceeds the available width. After settlement, Compact shows only `Think`, while Detailed and Expanded preview the first line. -Settings → General exposes the persisted `Work details` preference in the `ui-chat` namespace: `Compact` (default), `Detailed`, and `Expanded`. All three modes retain the whole-Turn disclosure and default completed Turns to collapsed. Detailed defaults step groups to collapsed and allows manual toggles. Expanded renders steps directly inside the whole-Turn disclosure, without secondary titles, disclosure controls, or bounded group scroll areas. Each secondary title starts with its matching existing Tool icon; the command category uses Bash's `IconApiOutlineRegular`. Hover or keyboard focus replaces that leading icon in place with a down chevron while collapsed; an expanded title keeps an up chevron visible, with no trailing chevron. Hovering an enabled whole-Turn or secondary disclosure title darkens its text. A collapsed secondary title has no vertical padding and sits 16px from adjacent Assistant messages; an expanded title sits 16px above its first process row, and adjacent process rows are 8px apart. The saved `transcriptView` field accepts legacy `normal`, which the client reads as `expanded` without rewriting storage; explicit choices save only the three current values. System prompts, ordinary context injections, and permission commands have no Chat row in any Work details mode. Non-human turn-trigger notices remain visible above the whole-Turn control; hidden metadata does not create process groups or collapse arrows. In Compact and Detailed, consecutive process rows between Assistant responses default to collapsed, including reasoning preceding response text in the same node. The live title reports the latest running tool category, otherwise analysis activity, and carries a repeating ease-in-out text shimmer with a 500ms pause after each pass until the process range closes. Each displayed live title remains for at least 150ms; changes during that interval coalesce to the latest title instead of queuing intermediate tools. Detailed places a concise current-call detail to the right of the category, preferring an authored title, description, objective, task, question, command, query, URL, or path and falling back to the exact tool name. While no tool is running, it shows the latest live reasoning paragraph instead. Details are whitespace-normalized and capped at 160 characters; completed titles omit them. Retry rows remain independent of secondary process groups. A following Assistant response closes the range as soon as visible reply content starts. Completed titles aggregate distinct calls by category, including repeated paths, and show the three most frequent categories without counts; ties retain first appearance order. Two categories use “and” (Chinese “并”, sharing an initial “已” only when both phrases have it); three use commas, and more than three add “etc.” (Chinese “等”). English continuation phrases start lowercase. With no tool statistics, completion uses the analysis fallback. System prompts, context injection, and permission metadata never contribute categories. Secondary expanded ranges scroll within the smaller of 400px and half the viewport height; a 24px fade marks each direction with hidden overflow and disappears independently at the corresponding scroll edge. Wheel and touchpad scrolling stays with the range while it can move, then continues the conversation when the range is too short to scroll or reaches either edge. At `turn/end`, its latest Step becomes the final-answer boundary only when it contains non-blank text, an image, or an unknown visible block—and no Tool-call block; preceding reasoning, earlier Assistant material, Tool rows, and Retry rows then collapse by default. The control appears at `turn/start` and stays expanded and disabled during execution. It displays `Deep diving for …` (Chinese `深度求索中,用时…`) with a minimum of 1s and no leading icon. Running, completed, stopped, and failed whole-Turn labels all use tertiary text at one pixel below the normal status size. The live clock refreshes once per second, shows whole seconds without padding single-digit seconds, and changes from minutes to hours at exactly 60 minutes. Compact, Detailed, and Expanded use this whole-Turn control as the only turn-level running label. Normal completion fixes the duration at a minimum of 1s, displays `Took …` (Chinese `用时…`), and defaults to collapsed. Cancellation displays `Stopped` (Chinese `已停止`); failure displays `Failed` (Chinese `处理失败`). Running, cancelled, and failed Turns stay expanded with a disabled control and no chevron. Missing start timestamps omit the duration. A Turn with no process rows or inline reasoning keeps the elapsed label but hides its chevron and disables disclosure. A full-width divider below the summary separates it from the answer or expanded process rows. User and steering messages, error, max-token, and turn-tail rows stay outside, and a closed Turn with no final answer folds all process rows while keeping independent rows visible. A newly available process control is inserted without changing the relative order of existing rows: opening human input precedes the control and process rows from their first projection; System prompt rows are not rendered. While older history remains available through Load earlier, closed Turns whose `turn/start` is loaded can fold independently, including Turns awakened by context injection. A Turn missing its start waits until pagination supplies it or exhausts history; unrelated unloaded Turns do not block folding. Stable Chat Node Seats preserve row placement, hidden members add no flow spacing, and a closed control sits 8px above its answer only when no independent input intervenes. Completion collapse does not depend on tail-follow position, so a reader above the tail may see the transcript reflow. An automatic collapse that would hide keyboard focus keeps the group open and leaves focus in place; a manual close focuses the process control before hiding its members. Closing a whole Turn resets its nested groups and tool details to collapsed; hidden process renderers remount while their seats stay stable. The session-scoped store records expanded completed answer generations; different answer generations start collapsed. +Settings → General exposes the persisted `Work details` preference in the `ui-chat` namespace: `Compact` (default), `Detailed`, and `Expanded`. All three modes retain the whole-Turn disclosure and default completed Turns to collapsed. Detailed defaults step groups to collapsed and allows manual toggles. Expanded renders steps directly inside the whole-Turn disclosure, without secondary titles, disclosure controls, or bounded group scroll areas. Each secondary title starts with its matching existing Tool icon; the command category uses Bash's `IconApiOutlineRegular`. Hover or keyboard focus replaces that leading icon in place with a down chevron while collapsed; an expanded title keeps an up chevron visible, with no trailing chevron. Hovering an enabled whole-Turn or secondary disclosure title darkens its text. A collapsed secondary title has no vertical padding and sits 16px from adjacent Assistant messages; an expanded title sits 16px above its first process row, and adjacent process rows are 8px apart. The saved `transcriptView` field accepts legacy `normal`, which the client reads as `detailed` without rewriting storage; explicit choices save only the three current values. System prompts, ordinary context injections, and permission commands have no Chat row in any Work details mode. Non-human turn-trigger notices remain visible above the whole-Turn control; hidden metadata does not create process groups or collapse arrows. In Compact and Detailed, consecutive process rows between Assistant responses default to collapsed, including reasoning preceding response text in the same node. The live title reports the latest running tool category, otherwise analysis activity, and carries a repeating ease-in-out text shimmer with a 500ms pause after each pass until the process range closes. Each displayed live title remains for at least 150ms; changes during that interval coalesce to the latest title instead of queuing intermediate tools. Detailed places a concise current-call detail to the right of the category, preferring an authored title, description, objective, task, question, command, query, URL, or path and falling back to the exact tool name. While no tool is running, it shows the latest live reasoning paragraph instead. Details are whitespace-normalized and capped at 160 characters; completed titles omit them. Retry rows remain independent of secondary process groups. A following Assistant response closes the range as soon as visible reply content starts. Completed titles aggregate distinct calls by category, including repeated paths, and show the three most frequent categories without counts; ties retain first appearance order. Two categories use “and” (Chinese “并”, sharing an initial “已” only when both phrases have it); three use commas, and more than three add “etc.” (Chinese “等”). English continuation phrases start lowercase. With no tool statistics, completion uses the analysis fallback. System prompts, context injection, and permission metadata never contribute categories. Secondary expanded ranges scroll within the smaller of 400px and half the viewport height; a 24px fade marks each direction with hidden overflow and disappears independently at the corresponding scroll edge. Wheel and touchpad scrolling stays with the range while it can move, then continues the conversation when the range is too short to scroll or reaches either edge. At `turn/end`, its latest Step becomes the final-answer boundary only when it contains non-blank text, an image, or an unknown visible block—and no Tool-call block; preceding reasoning, earlier Assistant material, Tool rows, and Retry rows then collapse by default. The control appears at `turn/start` and stays expanded and disabled during execution. It displays `Deep diving for …` (Chinese `深度求索中,用时…`) with a minimum of 1s and no leading icon. Running, completed, stopped, and failed whole-Turn labels all use tertiary text at one pixel below the normal status size. The live clock refreshes once per second, shows whole seconds without padding single-digit seconds, and changes from minutes to hours at exactly 60 minutes. Compact, Detailed, and Expanded use this whole-Turn control as the only turn-level running label. Normal completion fixes the duration at a minimum of 1s, displays `Took …` (Chinese `用时…`), and defaults to collapsed. Cancellation displays `Stopped` (Chinese `已停止`); failure displays `Failed` (Chinese `处理失败`). Running, cancelled, and failed Turns stay expanded with a disabled control and no chevron. Missing start timestamps omit the duration. A Turn with no process rows or inline reasoning keeps the elapsed label but hides its chevron and disables disclosure. A full-width divider below the summary separates it from the answer or expanded process rows. User and steering messages, error, max-token, and turn-tail rows stay outside, and a closed Turn with no final answer folds all process rows while keeping independent rows visible. A newly available process control is inserted without changing the relative order of existing rows: opening human input precedes the control and process rows from their first projection; System prompt rows are not rendered. While older history remains available through Load earlier, closed Turns whose `turn/start` is loaded can fold independently, including Turns awakened by context injection. A Turn missing its start waits until pagination supplies it or exhausts history; unrelated unloaded Turns do not block folding. Stable Chat Node Seats preserve row placement, hidden members add no flow spacing, and a closed control sits 8px above its answer only when no independent input intervenes. Completion collapse does not depend on tail-follow position, so a reader above the tail may see the transcript reflow. An automatic collapse that would hide keyboard focus keeps the group open and leaves focus in place; a manual close focuses the process control before hiding its members. Closing a whole Turn resets its nested groups and tool details to collapsed; hidden process renderers remount while their seats stay stable. The session-scoped store records expanded completed answer generations; different answer generations start collapsed. ----- diff --git a/packages/client/ui-chat/README.zh.md b/packages/client/ui-chat/README.zh.md index 68f0f1f55c..2f2546e23c 100644 --- a/packages/client/ui-chat/README.zh.md +++ b/packages/client/ui-chat/README.zh.md @@ -59,7 +59,7 @@ kind: "package-reference" 每个思考行初始都折叠,包括流式输出期间和仅含思考的回复。点击该行可展开或收起完整 Markdown;后续回答文本、工具调用和流结束都保留用户的选择。展开的思考采用紧凑的次级排版:标题只加粗,不改变字号、行高或颜色。流式生成期间,收起预览仅在某段第一行结束后切换;尚未结束的第一行不会替换当前预览。预览从左侧起始,超出可用宽度的内容在右缘渐隐。结算后,简洁模式只显示「思考」,详细和完全展开模式显示首行预览。 -「设置 → 通用设置」提供持久化到 `ui-chat` 命名空间的「工作过程展示」偏好:简洁(默认)、详细、完全展开。三种模式均保留一级整轮折叠,已完成轮次默认收起。详细默认收起步骤组,允许手动切换;完全展开在一级折叠内直接平铺步骤,不显示二级标题、折叠控件或限高的组内滚动区。每个二级标题默认以前置的现有工具图标表示类别,其中命令类别使用 Bash 的 `IconApiOutlineRegular`。收起时,悬停或键盘聚焦会把前置图标原位替换为向下箭头;展开后持续显示向上箭头,标题尾部不再显示箭头。悬停可用的整轮或二级折叠标题时,文字颜色加深。收起的二级标题不带垂直内边距,与相邻 Assistant 消息相隔 16px;展开标题与首个过程行相隔 16px,相邻过程行相隔 8px。持久化字段 `transcriptView` 接受旧值 `normal`,客户端将其读取为 `expanded`,不主动改写存储;用户选择后仅保存三个新值。所有工作过程展示模式均不显示系统提示词、普通上下文注入和 permission 命令行。非人工轮次发起提示仍独立显示在一级折叠上方;隐藏的元数据不产生过程组或折叠箭头。简洁与详细模式下,Assistant 回复之间的连续过程行都默认收起,同一节点内正文之前的推理也归入过程组。进行中的标题显示最新运行工具的类别,没有运行工具时显示分析阶段,并在过程组关闭前循环显示采用 ease-in-out 曲线、每轮结束后停顿 500ms 的文字扫光。每个已显示的进行中标题至少保留 150ms;这段时间内的变化只保留最新标题,不排队补播中间工具。详细模式在类别右侧显示简短的当前调用详情,优先采用调用方给出的标题、描述、目标、任务、问题、命令、查询词、URL 或路径,没有可用详情时回退到原始工具名;没有工具运行时改为显示最新的实时思考段落。详情会合并空白并截断到 160 个字符;完成标题不保留进行中详情。重试行独立展示,不归入二级过程组。下一条 Assistant 回复开始输出可见正文时,该组转为完成。完成标题按类别统计不同调用,同一路径的多次调用分别计数,显示调用最多的前三类但不显示数量;次数相同按首次出现顺序排列。两类用「并」(英文为 “and”)连接,仅当两项均以「已」开头时共享首个「已」;三类用逗号连接,超过三类追加「等」(英文为 “etc.”)。英文后续动作短语首字母小写。没有工具统计时,使用分析完成的回退文案。系统提示词、上下文注入与权限元数据不计入类别。二级展开区在 400px 与视口高度的一半之中取较小值作为最大高度;存在隐藏内容的方向显示 24px 渐隐遮罩,到达对应滚动边缘时该侧遮罩消失。滚轮和触控板滚动会在区内仍可滚动时留在该区域;区域无需滚动或到达任一边界后,滚动继续作用于整个对话。到 `turn/end` 时,最后一个步骤只有在包含非空文本、图片或未知可见块且不含工具调用块时才成为最终答案边界;边界之前的推理、较早 Assistant 内容、工具行与重试行随后默认收起。控件在 `turn/start` 时出现,执行期间始终展开且不可点击。标题文案为「深度求索中,用时…」(英文为 `Deep diving for …`),最少显示 1 秒且不带前置图标。运行、完成、停止和失败的整轮状态文案均使用 tertiary 灰度,字号比普通状态小 1px。运行时钟每秒更新,显示整数秒且个位秒不补零,满 60 分钟切换为小时。简洁、详细和完全展开均只使用该整轮控件显示轮次运行状态。正常完成后固定时长,最少显示 1 秒,显示「用时…」(英文为 `Took …`),默认收起。取消后显示「已停止」(英文为 `Stopped`);失败后显示「处理失败」(英文为 `Failed`)。进行中、取消或失败的轮次始终展开,控件不可点击且不显示箭头。缺少起点时间戳时省略时长。没有过程行或内联推理的轮次保留用时标题,但隐藏箭头并禁用折叠。摘要下方的通栏分隔线将其与正文或展开后的过程行隔开。用户与 steering 消息、错误、最大 token 与 turn-tail 行留在过程组外;关闭时没有最终答案的轮次会收起所有过程行,独立行保持可见。新的过程控件插入时不会改变既有行的相对顺序:开场人工输入从首次投影起便位于控件和过程行之前,系统提示词行不显示。仍可通过「加载更早」获取历史时,已加载 `turn/start` 的已关闭轮次可以独立折叠,包括由上下文注入唤起的轮次。缺少起点的轮次会等待分页补齐起点或加载完历史;其他尚未加载的轮次不会阻止折叠。稳定 Chat Node Seat 保持行的位置,隐藏成员不产生消息流间距;只有中间没有独立输入时,收起控件才与正文相隔 8px。完成后的收起不依赖是否跟随尾部,因此正在上方阅读的用户可能看到 transcript 重排。若自动收起会隐藏当前键盘焦点,则过程组保持展开且焦点留在原处;手动收起会先把焦点移到过程控件,再隐藏成员。收起整轮会把内部过程组和工具详情重置为折叠;隐藏的过程 renderer 重新挂载,seat 保持稳定。会话作用域存储记录完成后的手动展开正文 generation;不同正文 generation 均默认收起。 +「设置 → 通用设置」提供持久化到 `ui-chat` 命名空间的「工作过程展示」偏好:简洁(默认)、详细、完全展开。三种模式均保留一级整轮折叠,已完成轮次默认收起。详细默认收起步骤组,允许手动切换;完全展开在一级折叠内直接平铺步骤,不显示二级标题、折叠控件或限高的组内滚动区。每个二级标题默认以前置的现有工具图标表示类别,其中命令类别使用 Bash 的 `IconApiOutlineRegular`。收起时,悬停或键盘聚焦会把前置图标原位替换为向下箭头;展开后持续显示向上箭头,标题尾部不再显示箭头。悬停可用的整轮或二级折叠标题时,文字颜色加深。收起的二级标题不带垂直内边距,与相邻 Assistant 消息相隔 16px;展开标题与首个过程行相隔 16px,相邻过程行相隔 8px。持久化字段 `transcriptView` 接受旧值 `normal`,客户端将其读取为 `detailed`,不主动改写存储;用户选择后仅保存三个新值。所有工作过程展示模式均不显示系统提示词、普通上下文注入和 permission 命令行。非人工轮次发起提示仍独立显示在一级折叠上方;隐藏的元数据不产生过程组或折叠箭头。简洁与详细模式下,Assistant 回复之间的连续过程行都默认收起,同一节点内正文之前的推理也归入过程组。进行中的标题显示最新运行工具的类别,没有运行工具时显示分析阶段,并在过程组关闭前循环显示采用 ease-in-out 曲线、每轮结束后停顿 500ms 的文字扫光。每个已显示的进行中标题至少保留 150ms;这段时间内的变化只保留最新标题,不排队补播中间工具。详细模式在类别右侧显示简短的当前调用详情,优先采用调用方给出的标题、描述、目标、任务、问题、命令、查询词、URL 或路径,没有可用详情时回退到原始工具名;没有工具运行时改为显示最新的实时思考段落。详情会合并空白并截断到 160 个字符;完成标题不保留进行中详情。重试行独立展示,不归入二级过程组。下一条 Assistant 回复开始输出可见正文时,该组转为完成。完成标题按类别统计不同调用,同一路径的多次调用分别计数,显示调用最多的前三类但不显示数量;次数相同按首次出现顺序排列。两类用「并」(英文为 “and”)连接,仅当两项均以「已」开头时共享首个「已」;三类用逗号连接,超过三类追加「等」(英文为 “etc.”)。英文后续动作短语首字母小写。没有工具统计时,使用分析完成的回退文案。系统提示词、上下文注入与权限元数据不计入类别。二级展开区在 400px 与视口高度的一半之中取较小值作为最大高度;存在隐藏内容的方向显示 24px 渐隐遮罩,到达对应滚动边缘时该侧遮罩消失。滚轮和触控板滚动会在区内仍可滚动时留在该区域;区域无需滚动或到达任一边界后,滚动继续作用于整个对话。到 `turn/end` 时,最后一个步骤只有在包含非空文本、图片或未知可见块且不含工具调用块时才成为最终答案边界;边界之前的推理、较早 Assistant 内容、工具行与重试行随后默认收起。控件在 `turn/start` 时出现,执行期间始终展开且不可点击。标题文案为「深度求索中,用时…」(英文为 `Deep diving for …`),最少显示 1 秒且不带前置图标。运行、完成、停止和失败的整轮状态文案均使用 tertiary 灰度,字号比普通状态小 1px。运行时钟每秒更新,显示整数秒且个位秒不补零,满 60 分钟切换为小时。简洁、详细和完全展开均只使用该整轮控件显示轮次运行状态。正常完成后固定时长,最少显示 1 秒,显示「用时…」(英文为 `Took …`),默认收起。取消后显示「已停止」(英文为 `Stopped`);失败后显示「处理失败」(英文为 `Failed`)。进行中、取消或失败的轮次始终展开,控件不可点击且不显示箭头。缺少起点时间戳时省略时长。没有过程行或内联推理的轮次保留用时标题,但隐藏箭头并禁用折叠。摘要下方的通栏分隔线将其与正文或展开后的过程行隔开。用户与 steering 消息、错误、最大 token 与 turn-tail 行留在过程组外;关闭时没有最终答案的轮次会收起所有过程行,独立行保持可见。新的过程控件插入时不会改变既有行的相对顺序:开场人工输入从首次投影起便位于控件和过程行之前,系统提示词行不显示。仍可通过「加载更早」获取历史时,已加载 `turn/start` 的已关闭轮次可以独立折叠,包括由上下文注入唤起的轮次。缺少起点的轮次会等待分页补齐起点或加载完历史;其他尚未加载的轮次不会阻止折叠。稳定 Chat Node Seat 保持行的位置,隐藏成员不产生消息流间距;只有中间没有独立输入时,收起控件才与正文相隔 8px。完成后的收起不依赖是否跟随尾部,因此正在上方阅读的用户可能看到 transcript 重排。若自动收起会隐藏当前键盘焦点,则过程组保持展开且焦点留在原处;手动收起会先把焦点移到过程控件,再隐藏成员。收起整轮会把内部过程组和工具详情重置为折叠;隐藏的过程 renderer 重新挂载,seat 保持稳定。会话作用域存储记录完成后的手动展开正文 generation;不同正文 generation 均默认收起。 ----- diff --git a/packages/client/ui-chat/src/client/transcript-view.ts b/packages/client/ui-chat/src/client/transcript-view.ts index 1ef5b90c0e..4ee2be8215 100644 --- a/packages/client/ui-chat/src/client/transcript-view.ts +++ b/packages/client/ui-chat/src/client/transcript-view.ts @@ -34,7 +34,7 @@ export class TranscriptViewPolicy { private adopt(): void { const section = this.host.getSnapshot().value if (section === undefined) return - const mode = section.transcriptView === 'normal' ? 'expanded' : section.transcriptView + const mode = section.transcriptView === 'normal' ? 'detailed' : section.transcriptView if (this.mode.getSnapshot() !== mode) this.mode.set(mode) } } diff --git a/packages/client/ui-chat/tests/transcript-view-policy.client.spec.ts b/packages/client/ui-chat/tests/transcript-view-policy.client.spec.ts index 43f521b170..2e7ca24df5 100644 --- a/packages/client/ui-chat/tests/transcript-view-policy.client.spec.ts +++ b/packages/client/ui-chat/tests/transcript-view-policy.client.spec.ts @@ -44,14 +44,25 @@ describe('TranscriptViewPolicy', () => { host.publish({ status: 'ready', value: { transcriptView: 'expanded', performanceUsage: 'detailed' }, revision: 1, writable: true }) expect(new TranscriptViewPolicy(host.scope).mode.getSnapshot()).toBe('expanded') }) - it('reads legacy normal as expanded without rewriting saved settings', () => { + it.each([ + ['compact', 'compact'], + ['normal', 'detailed'], + ['detailed', 'detailed'], + ['expanded', 'expanded'], + ] as const)('reads saved %s as %s without rewriting settings', (saved, resolved) => { + const host = stubSettingsScope() + host.publish({ status: 'ready', value: { transcriptView: saved }, revision: 1, writable: true }) + const policy = new TranscriptViewPolicy(host.scope) + expect(policy.mode.getSnapshot()).toBe(resolved) + expect(host.set).not.toHaveBeenCalled() + }) + + it('persists Expanded only when explicitly selected after legacy Normal', () => { const host = stubSettingsScope() host.publish({ status: 'ready', value: { transcriptView: 'normal', performanceUsage: 'detailed' }, revision: 1, writable: true }) const policy = new TranscriptViewPolicy(host.scope) + policy.setMode('expanded') expect(policy.mode.getSnapshot()).toBe('expanded') - expect(host.set).not.toHaveBeenCalled() - policy.setMode('detailed') - expect(host.set).toHaveBeenCalledWith('transcriptView', 'detailed') + expect(host.set).toHaveBeenCalledWith('transcriptView', 'expanded') }) - })