Repository navigation
feat(ui): group turn process activity like the Astryx chat template #5796
Description
English
Part of #5793. Supersedes #4773. Relates to #4863. Scope reviewed against upstream main 7c90bac2d on 2026-10-04; completed behavior is listed separately below.
Problem
A reader who opens a finished turn sees its process region as a log table rather than as a conversation.
- Tool calls are split into many single-call cards. Tool merging in
materialize.tscurrently combines adjacent tool entries only, so intermediate commentary or reasoning splits the group;foldTimelinepreserves that sequence in the process region. Each group then holds one call and renders as its ownChatToolCalls. - Each single-call card is 800px wide. Its chevron sits at the right edge, about 400px from its content, so a turn shows a column of chevrons.
- Three text styles alternate in one column: 12px muted process rows, 14px commentary, and the 12px status row with a full-width divider above the process body.
- When a group does hold many calls, expanding it replaces several screens of the conversation. feat(desktop): bound expanded tool activity in the conversation #4773 describes the long-group problem. The former transcript-level sticky header defect from fix(ui): reading-column polish — balanced density, conversation radius, flush sticky #3375 was addressed by fix(desktop): keep expanded tool calls in flow #5158 and is not remaining work here.
Astryx already provides the grouping this needs. ChatToolCalls renders one call inline and renders several calls under a collapsible summary, collapsed by default for multi-call groups in the current Astryx 0.6.3 implementation. The official ai-chat template passes each step's calls to one ChatToolCalls, and shows commentary as ghost bubble text around it.
Already available on upstream
- Settled process regions default to collapsed; running regions remain open and cannot be collapsed (fix(ui): unify live process activity and settled disclosures #5301).
- Commentary uses ghost bubble text.
- Semantic entry identity and disclosure reconciliation are present (perf(desktop): publish session state at the granularity of change #5532); preserve them during regrouping.
- Tool groups no longer use the former transcript-level sticky header (fix(desktop): keep expanded tool calls in flow #5158).
Desired outcome
The process region follows the template's composition:
- A settled turn shows one compact summary line for its process region. Running turns stay expanded and cannot be collapsed, as today.
- Inside the region, commentary renders as ghost bubble text. The tool calls of each step render as one
ChatToolCallsgroup. Reasoning no longer splits a tool group. - Long groups are bounded instead of pushing the answer away. These requirements carry over from feat(desktop): bound expanded tool activity in the conversation #4773:
- Keep multi-call groups collapsed by default. Show the call count and a failure signal in the summary.
- Bound long expanded groups with a viewport-aware height, and scroll only the inner list with a contained scroll chain.
- Keep the group header outside the new inner scroll area. Preserve the removal of transcript-level sticky behavior from fix(desktop): keep expanded tool calls in flow #5158.
- Keep row details closed until the reader opens them.
- Keep running and failed states visible without hover.
- While a group streams, follow new rows only while the reader stays at the list tail.
Constraints
- A running process region stays open. A reader's open or closed choice on a settled region survives appended events.
- Entry keys stay semantic, so inserting an entry mid-timeline does not remount disclosures.
- Order inside a step stays chronological. Do not regroup calls by tool type. Define how a shared tool group retains intervening reasoning/commentary before implementation; do not silently reorder content. Keep steering boundaries explicit and use a conservative fallback for legacy entries without
stepId. ChatReasoning(astryx-chat-reasoning.tsx) stays a Maka component. Astryx has no reasoning primitive, and the template shows none.- Tool result detail content is feat(desktop): tailor tool result rendering to the content #4863 and is out of scope.
Implement step grouping and aggregate failure signals first, then long-group height/inner-scroll/tail-follow behavior. A0 (#5794 / #5847) is available. Coordinate scrolling changes with #5942 and use dynamic scrolling checks in addition to frozen pixel captures. Base turn layout on #5911 and coordinate shared files with open PR #5928.
Acceptance criteria
-
timeline-fold.test.tscovers the new grouping, including reasoning between tool calls, steering messages, and identity reconciliation. - Stories show a settled multi-step turn, a running turn, a turn with a failed tool, and a 45-call group. Each has a
// Real path:comment. - Before and after captures in light and dark, produced by the A0 loop, are attached to the PR.
- The CSS for
.maka-processing-*and the tool activity card shrinks, and the PR reports the net change. - feat(desktop): bound expanded tool activity in the conversation #4773 is closed with a link to this issue.
Open questions
- Whether a settled turn restores the template's identity anchors: a persistent timestamp in the metadata row (hover-only since style(desktop): reveal turn metadata on hover and separate turns #5715) and an assistant avatar (removed in feat(ui): subtract permanent chrome toward the Paseo visual benchmark #1433).
中文
属于 #5793。取代 #4773。与 #4863 相关。2026-10-04 已按 upstream main 7c90bac2d 核对范围;已有行为在下方单独列出。
问题
读者打开一轮已结束的对话时,过程区看起来像一张日志表,而不像对话。
- 工具调用被切成许多只含一个调用的卡片。
materialize.ts当前只合并相邻的工具条目,因此中间说明或思考会切断工具组;foldTimeline在过程区保留这一顺序。每组于是只剩一个调用,各自渲染成一个ChatToolCalls。 - 每张单调用卡片 800px 宽,展开箭头在最右端,离内容约 400px,一轮里会出现一列箭头。
- 同一栏里交替出现三种文字样式:12px 灰色的过程行、14px 的说明文字,以及过程区上方带满宽分隔线的 12px 状态行。
- 当某一组确实包含很多调用时,展开它会让对话被好几屏的工具行取代。feat(desktop): bound expanded tool activity in the conversation #4773 描述了长工具组问题。fix(ui): reading-column polish — balanced density, conversation radius, flush sticky #3375 提到的旧对话流级吸顶标题缺陷已由 fix(desktop): keep expanded tool calls in flow #5158 处理,不再属于本 issue 的剩余工作。
Astryx 已经提供了所需的分组能力。ChatToolCalls 在只有一个调用时单行显示,有多个调用时显示在可折叠的摘要下,当前 Astryx 0.6.3 实现中多调用组默认折叠。官方 ai-chat 模板把每一步的调用传给同一个 ChatToolCalls,并在其前后用 ghost 气泡文字显示说明。
上游已具备
- 已结束的过程区默认折叠;运行中的过程区保持展开且不可折叠(fix(ui): unify live process activity and settled disclosures #5301)。
- 说明文字使用 ghost 气泡。
- 已有语义化条目身份及折叠组件身份复用(perf(desktop): publish session state at the granularity of change #5532);重新分组时保留。
- 工具组已不再使用旧的对话流级吸顶标题(fix(desktop): keep expanded tool calls in flow #5158)。
期望结果
过程区采用模板的组合方式:
- 已结束的轮次,过程区只显示一行紧凑的摘要。运行中的轮次保持展开且不可折叠,与现在一致。
- 过程区内部,说明文字以 ghost 气泡文字显示,每一步的工具调用合成一个
ChatToolCalls组,思考不再切断工具组。 - 长工具组有高度上限,不再把回答推远。以下要求沿用 feat(desktop): bound expanded tool activity in the conversation #4773:
- 多调用组默认折叠,摘要中显示调用数和失败信号。
- 展开后的长工具组使用随视口变化的高度上限,只滚动内部列表,并阻止滚动传递到外层。
- 组标题放在新的内部滚动区之外,保留 fix(desktop): keep expanded tool calls in flow #5158 已移除对话流级吸顶行为的结果。
- 每一行的详情保持关闭,直到读者主动打开。
- 运行中和失败状态无需悬停即可看到。
- 工具组流式追加时,只有读者停留在列表末尾才跟随新行。
约束
- 运行中的过程区保持展开。读者对已结束过程区的展开或折叠选择,在后续事件追加后仍然保留。
- 条目的 key 保持语义化,在时间线中间插入条目不会让折叠组件重新挂载。
- 每一步内部保持时间顺序,不按工具类型重新分组。实现前先定义共享工具组如何保留穿插的思考/说明,不静默重排内容。明确保留用户引导消息的边界,并为缺少
stepId的旧条目采用保守回退。 ChatReasoning(astryx-chat-reasoning.tsx)继续作为 Maka 自己的组件。Astryx 没有思考过程原语,模板里也没有展示。- 工具结果详情的内容属于 feat(desktop): tailor tool result rendering to the content #4863,不在范围内。
先实现步骤分组和聚合失败信号,再实现长组限高、内部滚动及停留末尾时跟随新内容。A0(#5794 / #5847)已可用。滚动变更与 #5942 协调,除冻结像素截图外还需动态滚动检查。轮次布局基于 #5911,并与开放中的 PR #5928 协调共享文件。
验收标准
-
timeline-fold.test.ts覆盖新的分组方式,包括工具调用之间的思考、插入的引导消息和身份复用。 - 故事覆盖:已结束的多步骤轮次、运行中的轮次、含失败工具的轮次,以及 45 个调用的工具组。每个故事都有
// Real path:注释。 - PR 附上 A0 流程产出的浅色和深色模式前后对比截图。
-
.maka-processing-*和工具活动卡片的 CSS 减少,PR 报告净变化行数。 - 关闭 feat(desktop): bound expanded tool activity in the conversation #4773,并链接到本 issue。
待定问题
- 已结束的轮次是否恢复模板中的身份锚点:元数据行中常显的时间戳(自 style(desktop): reveal turn metadata on hover and separate turns #5715 起改为悬停才显示),以及助手头像(在 feat(ui): subtract permanent chrome toward the Paseo visual benchmark #1433 中移除)。
Activity