# OMP 风格动态工具状态设计 日期:2026-06-15 ## 背景 当前工作台已经能接收 agent 的工具开始和工具结束事件,但前端会把每次工具调用都追加到当前回复里。复杂任务一多,聊天区会变成工具流水账,用户很难看清“agent 此刻到底在做什么”。 目标不是做一个简陋的工具提示,而是对齐 `omp` 的体验:当前动作始终以彩色动态状态呈现,历史动作沉淀为可折叠摘要。 ## 已确认方向 - 动态工具条放在当前 assistant 回复内部,跟着当前回复走。 - 工具条是彩色、动态、持续刷新的“跑马灯”状态,而不是普通灰色文本。 - 工具结束后不再把所有动作摊开显示,改为丰富但折叠的历史摘要。 - 不走 MVP 思维,优先做完整体验。 - 采用“升级项目内 pi-agent 依赖 + 对齐新版 `omp` 事件模型”的路线。 - 升级对象是本项目的依赖,不是用户本机全局安装的 `omp` 或 `pi-agent`。 ## 目标体验 当 agent 开始调用工具时,当前 assistant 回复内部、正文之前出现一条动态工具条。它显示当前正在执行的动作,例如: - Reading `workbench/PRODUCT.md` - Writing `wiki/topics/agent-tools.md` - Running `npm run typecheck` - Searching current knowledge base 同一轮回复里,如果工具连续切换,工具条只显示当前正在进行的一项,之前完成的动作进入折叠摘要。 当 agent 开始输出正文时,工具条仍留在同一条回复内,固定在正文上方,不抢正文阅读。当前工具全部结束后,工具条消失或变为短暂完成态,历史摘要保留。 ## 历史摘要 历史摘要默认折叠,但不是只显示一个数字。它要像 `omp` 一样让用户快速判断 agent 做过什么: - 按工具类型分组:Read、Write、Bash、Search、Skill 等。 - 每组显示数量。 - 每组显示少量关键目标,例如文件名、页面名、命令摘要。 - 超过展示上限时显示“还有 N 项”。 - 用户展开后可以看到完整工具清单。 摘要示例: ```text 工具摘要 Read (6) ✓ SKILL.md:1-80 ✓ README.md:1-80 ✓ workbench/PRODUCT.md Write (4) ✓ wiki/sources/... Bash (2) ✓ npm run typecheck ``` ## 底层升级策略 先开分支验证项目内 `pi-agent` 依赖升级,而不是直接改功能。 验证目标: 1. 项目能安装成功。 2. 后端能启动。 3. 前端能连接后端。 4. 基础对话能跑通。 5. 当前知识库上下文仍能注入。 6. Skill 调用仍能工作。 7. 会话历史仍能读取。 8. 新版事件里能拿到工具名、工具参数、工具状态、必要时的运行中更新。 如果新版依赖改了包名、导出路径或事件格式,后端要增加一个适配层,把新版事件统一整理成前端使用的稳定事件。 如果升级验证失败,不应退回到简陋前端方案;应记录失败点,并决定是补适配层、锁定可用版本,还是分阶段迁移。 ## 事件设计 前端不直接依赖底层 `pi-agent` 原始事件。后端提供工作台自己的稳定事件: - `assistant_text_delta`:assistant 正文增量。 - `tool_status_start`:一个工具开始或当前工具切换。 - `tool_status_update`:工具参数、目标、运行中描述更新。 - `tool_status_end`:工具完成、失败或取消。 - `tool_status_summary`:一轮回复的工具摘要更新。 - `assistant_done`:本轮回复完成。 - `assistant_error`:本轮回复异常。 每个工具事件至少包含: - 工具调用 ID。 - 工具名。 - 面向用户的动作标签。 - 目标对象,例如文件名、页面名、命令摘要。 - 状态:运行中、完成、失败、取消。 - 分组类型。 - 是否可放入折叠摘要。 面向用户的动作标签优先来自新版事件里的自然语言意图;如果没有,就由后端根据工具名和参数生成。 ## 前端结构 当前 `ChatPanel` 已经同时承担消息流、工具流、输入框、命令菜单、引用菜单等职责。实现时应把工具状态拆成独立小模块,而不是继续把逻辑塞进消息数组。 建议拆分: - `ToolStatusRunway`:当前动态工具条。 - `ToolHistorySummary`:折叠工具摘要。 - `tool-status-model`:把 start/update/end 事件归并成当前状态和历史摘要。 - `formatToolStatus`:把工具名和参数转成人能看懂的短句。 消息对象里不再存一长串实时工具标记。工具状态应作为当前 assistant 回复的附属状态存在;历史消息只保留完成后的摘要数据。 ## 视觉设计 动态工具条应满足: - 彩色流动背景或流动边框。 - 有明确的当前动作动词。 - 目标文字可截断,不撑破布局。 - 工具切换时有轻微过渡。 - 深色和浅色主题都可读。 - 在手机宽度下不遮挡正文,不横向溢出。 折叠摘要应满足: - 默认占用空间小。 - 能一眼看出做过哪些类型的事。 - 展开后清单结构清楚。 - 不和正文 Markdown 表格、列表样式混在一起。 ## 错误和边界状态 - 工具失败:当前工具条变为失败态,摘要中该项标红或标记失败。 - 工具取消:当前工具条显示取消态,摘要保留已完成部分。 - 工具事件缺参数:显示工具名和通用动作,不显示空目标。 - 多个工具并行:工具条显示最近活跃工具,摘要中保留所有工具;如新版事件能提供并行状态,可显示“另有 N 项运行中”。 - 长文件路径:中间截断,保留文件名或末尾路径。 - 长命令:保留主命令和关键参数,展开后看完整命令。 - 会话恢复:历史消息显示折叠摘要,不恢复动态跑马灯。 ## 验证方式 升级依赖后先做底层验证: - 安装依赖。 - 类型检查。 - 启动后端和前端。 - 发送普通对话。 - 发送会触发知识库检索的问题。 - 发送会触发 read/write/bash 的任务。 - 检查 Skill 调用是否仍可用。 界面实现后做体验验证: - 打开本地页面实际跑一次长任务。 - 确认屏幕上始终只有一个当前工具条,而不是一长串工具。 - 确认工具结束后出现折叠摘要。 - 展开摘要,确认分组和明细正确。 - 在深色和浅色主题下检查可读性。 - 在窄屏尺寸下检查不溢出、不遮挡输入框。 ## 不做的事 - 不改用户本机全局 `omp`。 - 不直接修改 `node_modules`。 - 不为了工具条重做整个聊天系统。 - 不把完整工具输出全部展示在主聊天区。 - 不把这次升级扩展成桌面打包或新知识库能力。 ## 成功标准 用户给 agent 一个复杂任务时,聊天区不再被工具流水账占满。用户始终能看到 agent 当前正在做什么;任务结束后,也能通过折叠摘要快速确认 agent 读了什么、写了什么、跑了什么。 最终观感应接近 `omp`:活、清楚、有节奏,而不是普通 Web 应用里的静态日志。