Files
llm-wiki/docs/spark/2026-06-15-omp-tool-status-events-design.md
2026-07-12 21:26:08 +08:00

6.9 KiB
Raw Permalink Blame History

OMP 风格动态工具状态设计

日期:2026-06-15

背景

当前工作台已经能接收 agent 的工具开始和工具结束事件,但前端会把每次工具调用都追加到当前回复里。复杂任务一多,聊天区会变成工具流水账,用户很难看清“agent 此刻到底在做什么”。

目标不是做一个简陋的工具提示,而是对齐 omp 的体验:当前动作始终以彩色动态状态呈现,历史动作沉淀为可折叠摘要。

已确认方向

  • 动态工具条放在当前 assistant 回复内部,跟着当前回复走。
  • 工具条是彩色、动态、持续刷新的“跑马灯”状态,而不是普通灰色文本。
  • 工具结束后不再把所有动作摊开显示,改为丰富但折叠的历史摘要。
  • 不走 MVP 思维,优先做完整体验。
  • 采用“升级项目内 pi-agent 依赖 + 对齐新版 omp 事件模型”的路线。
  • 升级对象是本项目的依赖,不是用户本机全局安装的 omppi-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 项”。
  • 用户展开后可以看到完整工具清单。

摘要示例:

工具摘要
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_deltaassistant 正文增量。
  • 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 应用里的静态日志。