Skip to content

【已审核】feat(agent): Bash 工具输出实时终端化显示 - #1439

Open
climashscape wants to merge 1 commit into
proma-ai:mainfrom
climashscape:feat/bash-streaming-terminal
Open

【已审核】feat(agent): Bash 工具输出实时终端化显示#1439
climashscape wants to merge 1 commit into
proma-ai:mainfrom
climashscape:feat/bash-streaming-terminal

Conversation

@climashscape

@climashscape climashscape commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

概述

Agent 模式下执行长命令(npm run build、python train.py 等)时,Bash 工具结果此前是静态渲染:执行期间无任何输出,结束后超过 3000 字符自动折叠仅显示前 15 行,无流式、无 ANSI 颜色、无实时滚动。本 PR 将其升级为真实终端体验。

核心思路:Pi SDK 的 Bash 工具在执行期间本来就通过 onUpdate 每 100ms 推送累计输出快照(tool_execution_update 事件),但主进程此前只转发心跳、丢弃了输出内容。本 PR 把这部分内容捡回来,建立完整的事件流 → 状态 → 渲染链路。

改动

数据链路(主进程 → 渲染进程)

  • packages/shared/src/types/agent.ts:新增 SDKToolOutputMessagetool_output)消息类型 + tool_output AgentEvent,扩展 SDKMessage 联合类型
  • apps/electron/src/main/lib/adapters/pi-agent-adapter.ts:从 Pi tool_execution_update 事件提取 partialResult 文本,按 Bash 白名单过滤,计算增量(首帧/截断重置用 replace 标记)后透传为 tool_output 消息;tool_execution_end 时清理缓冲防泄漏
  • apps/electron/src/renderer/hooks/useGlobalAgentListeners.tstool_output 转 AgentEvent,且不写入 liveMessages 转录(避免高频数据污染消息列表)
  • apps/electron/src/renderer/atoms/agent-atoms.tsToolActivity.streamingOutput 缓冲 + applyAgentEvent 增量拼接/replace 重置(引用稳定优化,无变化时返回原引用)

前端终端化渲染

  • bash-result.tsx:重写为固定高度终端块(max-h-320px + 内部滚动),运行中/结束后高度一致。支持实时逐行追加、自动滚动跟随、暂停/恢复滚动、回到底部、ANSI SGR 颜色解析(16/256/truecolor)、stderr 红色高亮、超长输出尾部渲染(500 行)、复制
  • ContentBlock.tsx:按 toolUseId 切片订阅流式输出(atomFamily,避免任意 session 的 Bash tick 污染消息树);单层折叠交互(展开 = 完整输出块,折叠 = 无输出块)
  • tool-result-renderers/index.tsx:透传 streamingOutput/isStreamingOutput

测试

  • agent-atoms.test.ts:tool_output 状态机 5 项(增量/首帧/replace/空增量/不匹配)
  • bash-result.test.ts:ANSI 解析器 10 项(16/256/truecolor、样式、重置)
  • pi-agent-bash.test.ts:partialResult 提取 7 项

测试

  • bun run --filter='@proma/electron' typecheck
  • bun test 相关单测 40 pass / 0 fail ✅
  • build:main + build:renderer 通过 ✅
  • bun run dev 真机验证(两轮):短输出 / 60 行长耗时流式滚动 / stderr 高亮 / ANSI 彩色保留 / 800 行超长输出 / 50KB 截断 / 混合错误场景 / 无输出兜底,全部符合预期
  • BDD 自审查两轮(独立子会话):P1 性能问题(atomFamily 切片、引用守卫)与 P2 体验问题(结束跳变、折叠)均已修复

紧急度

常规

常规:无紧急性的常规改动

备注

无对应 upstream issue,未关联 Closes。

- 主进程透传 Pi Bash onUpdate 累计输出为 tool_output SDKMessage(增量计算 + 截断重置)
- 渲染进程接收 tool_output 事件并维护 ToolActivity.streamingOutput 缓冲
- BashResultRenderer 新增流式终端模式:实时追加、自动滚动跟随、暂停/恢复、
  ANSI SGR 颜色解析、stderr 红色高亮、复制、超长输出尾部渲染
- 流式期间 tool_output 不进入 liveMessages,避免污染消息转录
- 新增 tool_output 状态机、ANSI 解析、partialResult 提取单元测试

BDD 自审查修复:
- 流式输出按 toolUseId 切片订阅(atomFamily),避免任意 session 的 Bash tick 污染消息树
- store 层引用守卫,no-op 事件不新建 Map 触发整树重渲染
- 流式结束后 CollapsibleResult 默认展开,避免从实时 tail 跳回折叠头部
- 复制按钮 title 明确为可见输出;补充 focus-visible a11y
- 主进程按 Bash 白名单过滤 onUpdate;partialResult 提取与 ANSI 解析补充单测
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant