Files
zn-ai/docs/ClawX-Chat-Skill-Runtime-Migration-Checklist.md
DEV_DSW 4c61e93c3e Add unit tests for skill capabilities, skill planner, and UV setup
- Implement tests for random ID generation, ensuring preference for crypto.randomUUID.
- Create tests for runtime context capabilities, validating the injection of enabled skill capabilities.
- Add tests for skill capability parsing, including classification and command example extraction.
- Introduce tests for the skill planner, verifying tool call planning based on user requests and attachment requirements.
- Establish tests for UV setup, ensuring proper handling of Python installation scenarios and environment checks.
2026-04-24 17:02:59 +08:00

1387 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# zn-ai 对齐 ClawX 的聊天 Skill 运行时迁移清单
## 1. 目标
`zn-ai` 的聊天运行时具备与 `ClawX` 同方向的能力:
- 用户在聊天中提到某个已启用的 skill 时,模型能把它当成可规划、可调用、可回传结果的运行时能力,而不是只把它当成设置页里的开关。
- 用户上传文件、引用网页、请求执行动作时,运行时能根据当前已启用 skills 自动规划合适的 skill/tool 链路。
- 聊天链路能产生真实的 `thinking / tool_use / tool_result / final answer`
- 用户能在 UI 中看到执行过程、失败原因和最终结果。
首个样板场景仍然是:
- 用户发送:`使用 minimax-xlsx 这个 skill帮我分析下`
- 如果会话里已有 `.xlsx/.csv/.tsv` 附件,运行时能识别并把文件交给表格类 skill
但这份文档的目标已经调整为:
- 架构上按“所有已启用 skills 都能接入聊天运行时”来设计
- `xlsx/minimax-xlsx` 只是第一条落地样板,不再作为唯一目标
## 2. 范围定义
### 2.1 最终目标范围
最终目标不是只支持 `minimax-xlsx`,而是支持:
- 所有已启用 skills 在聊天时可见
- 所有已启用 skills 可被模型规划
- 所有已启用 skills 可被运行时调用
- 所有已启用 skills 的结果可回传给模型并写入会话历史
- 所有已启用 skills 的执行结果可被 renderer 展示
### 2.2 首批交付范围
首批交付不要求把每一个 skill 都逐个深度适配,但要求:
- 运行时架构必须按“全量 skills 通用接入”设计
- 第一批用 `xlsx/minimax-xlsx` 完成端到端验收
- 第二批逐步覆盖其他 skill 类型,而不是继续新增特判分支
### 2.3 明确不再采用的方向
不采用下面这种方案:
- 只为 `minimax-xlsx` 单独写一条聊天特判链路
- 只为少数 skill 手工写 prompt 注入和执行代码
- 让不同 skill 分别走不同的 ad-hoc 执行协议
## 3. 全量 skills 通用接入边界与阶段化策略
这一节单独回答一个关键问题:
- 这次迁移是不是要把“所有 skills 都接进聊天运行时”考虑进去?
答案是:
- 要考虑进去
- 但不是要求第一批把每一个 skill 都做成同等质量的深度适配
- 而是要求从第一天起,架构必须按“全量 skills 可接入”来设计
### 3.1 通用接入边界
本次迁移的“全量 skills 通用接入”边界如下:
- 所有已启用 skills 都必须能进入聊天运行时的 capability 列表
- 所有已启用 skills 都必须能被 planner 看见并参与候选规划
- 所有已启用 skills 都必须能映射到统一 executor 协议
- 所有 skills 的执行结果都必须能落入统一的 `tool_result` 结构
- 所有 skills 的执行过程都必须能被 transcript 和 renderer 消费
本次迁移不承诺的边界如下:
- 不承诺首批就为每一个 skill 做专门的高质量 UI 定制
- 不承诺首批就为每一个 skill 做类型专属优化
- 不承诺首批就覆盖所有外部依赖复杂、权限要求高的 skills
换句话说:
- 首批必须做到“都能接”
- 但不要求首批“都接得一样深、一样好看、一样聪明”
### 3.2 `SKILL.md -> runtime capability` 通用抽取规则
这是第一项必须补进文档的内容。
目标:
- 不能把 `SKILL.md` 原文直接塞给模型
- 需要抽成稳定、短小、可规划的 runtime capability
通用抽取规则建议如下:
1. 基础身份字段
- `skillKey`
- `displayName`
- `description`
2. 能力字段
- `inputKinds`
- `outputKinds`
- `triggerHints`
- `supportedFileTypes`
3. 约束字段
- `requiresFiles`
- `requiresEnv`
- `requiresRuntime`
- `riskLevel`
4. 执行字段
- `defaultEntrypoint`
- `callPattern`
- `resultShape`
抽取优先级建议:
1. 先读显式元数据
2. 再读 `SKILL.md` 的标题、description、usage、limitations
3. 最后使用默认推断规则兜底
兜底策略:
- 如果 skill 没有足够结构化信息,也必须能生成最小 capability
- 不能因为 metadata 不完整就把 skill 排除出聊天运行时
### 3.3 Skill 分类分层策略
这是第二项必须补进文档的内容。
目标:
- 不同 skill 的输入输出模式不同
- 不能要求所有 skill 共用完全相同的 planner 提示和 executor 适配方式
首版推荐分层如下:
1. 文档/文件类
- 例:`xlsx``minimax-xlsx``pdf``docx`
- 典型输入文件、路径、sheet、段落、页码
- 典型输出:结构化数据、文件、摘要
2. 浏览器/网页类
-browser automation、web browse
- 典型输入URL、页面元素、交互动作
- 典型输出页面快照、DOM 结果、提取数据
3. 搜索/检索类
-web search、knowledge search
- 典型输入query、filters、time range
- 典型输出:候选结果、摘要、来源
4. 命令/脚本类
-shell、uv、脚本执行型 skill
- 典型输入:命令参数、工作目录、文件引用
- 典型输出stdout、stderr、产物文件、退出状态
5. 外部 API / 服务类
- 例:需要第三方 API key 的 skill
- 典型输入:结构化参数、凭据引用、速率限制
- 典型输出API 响应、结构化记录、失败状态
分层原则:
- planner 先按 skill type 缩小候选范围
- executor 再按该 type 的 adapter 执行
- UI 先展示通用结果,再逐步补 skill type 专属展示
### 3.4 Skill 前置检查策略
这是第三项必须补进文档的内容。
目标:
- 不是 skill 已启用就一定可执行
- 聊天运行时必须在规划前或执行前做前置检查
每个 skill 的前置检查至少包括:
1. 依赖检查
- 本地二进制是否存在
- Python/Node/uv 运行时是否可用
- 所需脚本是否存在
2. 环境变量检查
- 必需 env 是否已配置
- API key 是否存在
- 敏感变量是否允许在当前运行环境使用
3. 权限检查
- 是否需要文件访问
- 是否需要网络访问
- 是否需要 shell/命令执行权限
- 是否需要浏览器自动化权限
4. 输入检查
- 文件是否存在
- 文件类型是否受支持
- 参数是否齐全
前置检查的输出必须标准化为:
- `ready`
- `blocked_missing_dependency`
- `blocked_missing_env`
- `blocked_missing_permission`
- `blocked_invalid_input`
这一步的意义是:
- 避免模型盲目调用 skill
- 避免把“权限没给”误判成“skill 不会用”
- 避免用户只看到一句模糊失败文案
### 3.5 通用 `tool_result` 标准化与 UI 渲染协议
这是第四项必须补进文档的内容。
目标:
- 所有 skill 返回结果必须进入统一 `tool_result`
- renderer 先消费统一协议,再渐进增强不同 skill 类型的展示
建议统一结果结构:
- `ok`
- `summary`
- `structuredData`
- `artifacts`
- `logs`
- `error`
- `retryable`
- `skillType`
- `renderHints`
其中:
- `structuredData` 用于模型继续推理
- `artifacts` 用于文件、图片、表格结果回传
- `logs` 用于调试和错误诊断
- `renderHints` 用于 UI 做轻量差异化展示
UI 渲染协议建议分两层:
1. 通用层
- 所有 skills 都显示状态、摘要、错误、耗时、输入概览
2. 类型增强层
- 文档类显示文件、sheet、提取结果摘要
- 搜索类显示来源列表和摘要
- 浏览器类显示页面结果与操作轨迹
- 命令类显示输出日志与产物
原则:
- 没有类型增强时,通用层也必须完整可用
- UI 不得依赖某个单 skill 的私有字段才能渲染
### 3.6 阶段化策略
“全量 skills 通用接入”建议按 4 个阶段推进:
#### Phase A通用协议冻结
目标:
- 冻结 capability schema
- 冻结 skill type taxonomy
- 冻结 preflight check 输出
- 冻结 `tool_result` 标准结构
产出:
- skill registry 契约
- planner 输入输出契约
- renderer 消费契约
#### Phase B样板链路落地
目标:
-`xlsx/minimax-xlsx` 跑通文件类样板
- 验证“启用 -> 可见 -> 可规划 -> 可执行 -> 可回传 -> 可展示”
要求:
- 代码实现必须走通用协议
- 不允许新增只服务于 `minimax-xlsx` 的永久特判
#### Phase C扩展到多 skill 类型
目标:
- 选至少 1 个搜索类 skill
- 选至少 1 个浏览器或命令类 skill
- 验证通用架构不是只对文件类有效
要求:
- 不改聊天主链路,只增加 registry/parser/adapter 配置
#### Phase D规模化接入与收敛
目标:
- 把更多已启用 skills 纳入 capability 列表
- 补前置检查、错误模型、UI 增强
- 补自动化回归
验收口径:
- 新增 skill 时,原则上不需要再改 `chat.send` 主编排
- 如果新增 skill 还需要改主编排,说明架构仍未真正通用
## 4. 当前主结论
当前 `zn-ai` 的主阻塞不是 `minimax-xlsx` 没启用,而是:
- 聊天运行时没有把已启用 skills 注入成可用能力
- 聊天主链路仍是“文本 provider 直连”,不是通用 tool/skill runtime
- 附件虽然能进入聊天,但没有稳定进入“技能可消费输入链路”
- renderer 能显示少量工具状态,但没有完整执行闭环
- 现有设计更接近“个别功能特判”,还不是“所有 skills 通用接入聊天运行时”
## 5. 验收标准
迁移完成后,至少要通过这 6 个场景:
1. 已启用 `minimax-xlsx`,用户发送 `使用 minimax-xlsx 这个 skill帮我分析下`,模型不会只返回空泛文本,而会进入 skill/tool 执行链路。
2. 用户上传 `.xlsx/.csv/.tsv` 后发送同一句话,运行时能把附件作为分析输入,而不是只把文件路径当普通文本。
3. 用户启用任意其他文档类或搜索类 skill 后,聊天运行时能把该 skill 暴露为能力,而不是只在 Skills 页显示“已启用”。
4. 聊天中能看到工具执行状态、结果摘要、失败信息;失败时能明确是“文件缺失 / skill 不可见 / provider 不支持 / runtime 执行失败 / skill 依赖未满足”。
5. 多轮对话里tool 结果能回灌到后续推理,不会出现“执行过了但模型下一轮不知道结果”。
6. 新增一个符合规范的 skill 时,不需要再给聊天链路补新的特判代码,只需通过注册/抽取机制接入。
## 6. 通用接入原则
这一节是本次调整的核心。
### 5.1 所有 skills 都必须经过同一条能力链路
统一链路:
1. Skill 发现
2. Skill 元数据抽取
3. Runtime capability 注入
4. Planner 选择 skill/tool
5. Executor 调用 skill/tool
6. Tool result 标准化
7. Transcript 写回
8. Renderer 展示
任何 skill 都不应该绕过这条链路单独接入聊天。
### 5.2 `xlsx/minimax-xlsx` 只是样板,不是特例
首批先用它验收,是因为它最能暴露当前缺口:
- 附件输入
- 文件访问
- tool loop
- 结果回灌
- UI 展示
但一旦链路建好,其他 skills 也必须复用同一套机制。
### 5.3 先做“通用协议”,再做“具体 skill 适配”
顺序必须是:
1. 先冻结通用 skill capability schema
2. 先冻结通用 planner/executor/tool_result 协议
3. 再做 `xlsx/minimax-xlsx` 样板接入
4. 再扩展到更多 skills
不能反过来先做某一个 skill 的特例实现,再倒推通用架构。
## 7. 通用能力模型
### 6.1 Skill capability schema
每个已启用 skill 在聊天运行时至少要暴露这些字段:
- `skillKey`
- `displayName`
- `description`
- `inputKinds`
- `outputKinds`
- `triggerHints`
- `requiresFiles`
- `supportedFileTypes`
- `requiresEnv`
- `requiresRuntime`
- `riskLevel`
说明:
- 这里不是把整个 `SKILL.md` 原样塞给模型
- 而是把它抽成稳定的、可规划的最小能力描述
### 6.2 Tool execution schema
所有 skills 在执行层至少统一到这些结构:
- `toolName`
- `toolCallId`
- `input`
- `status`
- `result`
- `error`
- `artifacts`
- `summary`
### 6.3 Tool result schema
所有 skill/tool 返回结果都要能映射成统一结构:
- `ok`
- `summary`
- `structuredData`
- `files`
- `logs`
- `error`
- `retryable`
### 6.4 Transcript schema
所有 skills 的执行都要进入统一会话记录:
- `thinking`
- `tool_use`
- `tool_result`
- `assistant final`
### 6.5 Skills 通用接入数据流图
下面这张文字版流程图,定义的是 `registry -> planner -> executor -> tool_result -> transcript -> renderer` 的标准主链路:
```text
[已启用 skills / 内建 tools / SKILL.md metadata / adapter manifest]
|
v
[Registry]
产出统一 capability list / tool registry entries / preflight metadata
|
v
[用户消息 / 附件 / 会话历史 / runtime context / capability list]
|
v
[Planner]
选择 skill/tool产出 thinking + tool_use plan
如果当前无需调用 tool则直接走 assistant final
|
v
[Executor]
执行 preflight check
把附件、参数、上下文转成 adapter 可消费输入
调用具体 skill/tool adapter拿到 raw result / artifacts / logs / error
|
v
[tool_result Normalize]
统一映射成 ok / summary / structuredData / files / logs / error / retryable / renderHints
|
+-------------+-------------+
| |
v v
[Transcript] [模型续推]
写回 thinking / tool_use / 把 tool_result 回灌给模型,
tool_result / assistant final 决定继续下一次 tool_use 或输出 final
|
v
[Renderer]
渲染执行状态、结果卡片、错误原因、产物入口、最终回答
```
实现约束:
- `registry` 只负责暴露能力,不负责替模型做最终决策
- `planner` 只负责选什么能力、传什么输入,不直接承担具体执行
- `executor` 只负责执行与标准化,不负责私自改写会话历史
- `tool_result` 必须同时服务两条链路:一条给模型续推,一条给 transcript / renderer 展示
- `transcript` 是多轮续接的唯一可信记录,不能只在 UI 本地保留工具结果
- `renderer` 优先消费统一协议,再按 skill type 做渐进增强
落地时最容易漏掉的环节:
- 只做了 `registry -> planner -> executor`,但没有把 `tool_result` 回灌模型
- 只做了 `tool_result -> renderer`,但没有把 `tool_use / tool_result` 写回 transcript
- 只让 `minimax-xlsx` 走这条链路,其他 enabled skills 仍然走特判分支
- 让 provider 直接内嵌 planner / executor 逻辑,导致通用 runtime 无法复用
### 6.6 Skills 通用接入代码文件映射图
下面这张图把上一节的数据流,直接映射到当前 `zn-ai` 里已经存在或建议新增的关键文件:
```text
[Registry capability 装配入口]
runtime-context.ts
说明:当前这里是 runtime capability 注入边界;
后续可把真正的 registry 生成下沉到 skill-capability-registry.ts
但对 chat.send 的上游入口仍然是这里。
|
v
[聊天主编排入口]
handlers/chat.ts
说明:接收用户消息、附件、会话历史,串联 planner / executor / transcript
|
+---------+---------+
| |
v v
[规划层] [执行层]
skill-planner.ts tool-runtime.ts
说明: 说明:
- 消费 message - 执行 preflight check
/ attachments - 调用 skill/tool adapter
/ history - 生成标准化 tool_result
/ runtime context - 产出 tool status / artifacts / logs
- 产出 thinking
/ tool_use plan
/ no-tool decision
| |
+---------+---------+
|
v
[共享协议层]
chat-model.ts
说明:定义 thinking / tool_use / tool_result / assistant final
的 transcript schema 与共享消息结构
|
v
[渲染层]
ChatMessageList.tsx
说明:消费 transcript、toolStatuses、attachments、tool_result
渲染执行状态、结果摘要、错误信息和最终回答
```
按职责拆到文件后的推荐边界如下:
- `runtime-context.ts`
- 负责把当前 enabled skills、内建 tools、session 信息装配成模型可见的 runtime context
- 不负责直接决定“这次该调用哪个 skill”
- 不负责写死某个 skill 的执行分支
- `handlers/chat.ts`
- 负责主编排,是 `chat.send` 的唯一入口
- 负责把用户消息、附件、历史、runtime context 串起来
- 负责调用 `skill-planner.ts``tool-runtime.ts`
- 负责把 `thinking / tool_use / tool_result / final` 写回 transcript
- 不负责继续堆 `if user says x then call y` 的特判
- `skill-planner.ts`
- 负责根据 capability list、附件类型、用户意图、历史上下文决定是否调用 skill/tool
- 输出统一的 planner decision而不是直接在这里执行 tool
- 如果模型无需调 tool也要能明确返回 `assistant-final-only` 这类决策
- `tool-runtime.ts`
- 负责 preflight check、adapter dispatch、错误归一化、`tool_result` 标准化
- 负责把 raw result 转成 transcript 和 renderer 都能消费的结构
- 不负责挑选哪个 tool那是 planner 的职责
- `chat-model.ts`
- 负责冻结共享协议,避免 gateway 和 renderer 各自维护一套 message shape
- 这里必须成为 `thinking / tool_use / tool_result / tool status / attachments` 的统一来源
- 如果协议扩展,不应该只改 UI 或只改 gateway 单边
- `ChatMessageList.tsx`
- 负责把通用 transcript 协议渲染出来
- 先支持通用 `tool_result` 卡片,再渐进增强不同 skill type 的专属展示
- 不应该依赖某个 skill 的私有字段才能完成基础渲染
这张映射图对应的实施顺序建议是:
1. 先冻结 `chat-model.ts` 的共享 schema
2. 再补 `skill-planner.ts``tool-runtime.ts`
3. 然后让 `handlers/chat.ts` 接管主编排
4. 再把 `runtime-context.ts` 从“固定两三个 tool 描述”升级成“全量 enabled skills capability 注入”
5. 最后让 `ChatMessageList.tsx` 完整消费新的 transcript / tool_result 协议
如果后面要继续往下拆实现任务,这 6 个文件基本就能直接映射成 6 条主工作流,不容易再把 registry、planner、executor、renderer 的职责混到一起。
## 8. 优先级清单
状态回填基线2026-04-24
- 已完成:当前阶段目标已经落地,后续只做增强,不再影响本阶段是否达标
- 部分完成:主链路已接入或已有样板,但仍有明显缺口,暂不能视为该项收口
- 未开始:还停留在文档/设计层,或尚未形成有效实现
### P0 阻塞项
这些必须先补,不补就很难达到目标效果。
#### P0-1 建立“全量 enabled skills -> runtime capabilities”注入机制
状态:部分完成
现状:
- 已有 capability registry 和 runtime context 注入链路,首批样板能把已启用 skill 暴露给聊天运行时
- 但“依赖/环境不满足”的统一降级提示还没有完全收口,新增 skill 也还没有做到真正零补丁接入
目标:
- 聊天发送前,运行时拿到当前所有已启用 skills 的能力描述
- 不是只暴露 `browser.open_url``skills.install`
- 首批先验证 `xlsx/minimax-xlsx`,但实现必须支持所有 skills
当前涉及文件:
- `zn-ai/electron/gateway/runtime-context.ts`
- `zn-ai/electron/gateway/handlers/chat.ts`
- `zn-ai/electron/gateway/handlers/skills.ts`
清单:
- [ ] 在聊天发送前读取当前 enabled skills
- [ ] 为 enabled skills 生成通用 runtime capability 描述
- [ ] 首批先支持 `xlsx/minimax-xlsx` 样板注入
- [ ] 确保后续 skill 接入不需要再改聊天主链路
- [ ] 明确“已启用但依赖/环境不满足”时的降级提示
#### P0-2 建立通用 skill metadata 抽取机制
状态:已完成
现状:
- capability schema、默认抽取规则、`SKILL.md` 降级抽取和 registry 入口都已落地
- 更细的 skill type 扩展仍会继续增强,但不影响这一阶段的 metadata 抽取主目标
目标:
- 从 skill 配置和 `SKILL.md` 提取统一 capability schema
- 为所有 skills 提供同一套抽取入口
当前涉及文件:
- `zn-ai/electron/gateway/handlers/skills.ts`
- 新增建议文件:`zn-ai/electron/gateway/skill-capability-registry.ts`
- 新增建议文件:`zn-ai/electron/gateway/skill-capability-parser.ts`
清单:
- [ ] 定义 capability schema
- [ ] 定义默认抽取规则
- [ ] 为缺少结构化元数据的 skill 提供降级抽取策略
- [ ] 支持后续按 skill 类型扩展抽取器
#### P0-3 从“文本 provider”升级到“可执行 tool 的聊天运行时”
状态:部分完成
现状:
- tool-capable provider/runtime 契约和 planner-first 执行链路已接入,`tool_result` 也能回灌后续回答
- 但 provider 原生 tool loop 还没有完整打通,`tools/toolChoice` 仍未成为统一主路径
目标:
- 聊天主链路不能只调用 `provider.chat(messages, model)`
- 必须支持模型发起工具调用,运行时执行后再把结果回给模型
当前涉及文件:
- `zn-ai/electron/providers/BaseProvider.ts`
- `zn-ai/electron/providers/OpenAIProvider.ts`
- `zn-ai/electron/gateway/handlers/chat.ts`
清单:
- [ ] 设计统一 tool-capable provider/runtime 接口
- [ ] 支持模型输出 `tool_use` 或等价调用结构
- [ ] 运行时执行 skill/tool 后生成 `tool_result`
- [ ]`tool_result` 回灌给模型,继续完成最终回答
- [ ] 保留现有文本流式输出作为降级路径
#### P0-4 建立通用 planner / registry而不是继续堆特判
状态:部分完成
现状:
- tool registry、planner、tool runtime 已建立统一入口,`skills.install`、浏览器、`xlsx/minimax-xlsx` 已纳入同一条链路
- 但新增 skill 仍需要补 adapter尚未做到“任意已启用 skill 都能直接执行”
目标:
- skill 调用不能再靠“遇到某句提示词就手工分支”
- 所有 skills 和内建 tools 都通过统一 registry 暴露给 planner
当前涉及文件:
- `zn-ai/electron/gateway/handlers/chat.ts`
- 新增建议文件:`zn-ai/electron/gateway/tool-runtime.ts`
- 新增建议文件:`zn-ai/electron/gateway/tool-registry.ts`
- 新增建议文件:`zn-ai/electron/gateway/skill-planner.ts`
清单:
- [ ] 抽象通用 tool registry
- [ ] skill/tool 共用一套注册与调度模型
- [ ]`skills.install`、浏览器、`xlsx/minimax-xlsx` 纳入统一 planner
- [ ] 后续 skill 不再新增聊天特判
#### P0-5 把附件真正接入“通用 skill 输入链路”
状态:部分完成
现状:
- 文件类样板已能把附件作为结构化输入交给表格分析链路,`.xls` 也已补上本地 fallback
- 但附件输入 schema 还没有沉淀成所有文件类 skill 共用的公共层
目标:
-`.xlsx/.csv/.tsv`,不能只把 `[media attached: ...]` 拼到文本里
- 附件要变成 planner/executor 可消费的标准输入
- 设计要对所有“需要文件输入”的 skills 通用
当前涉及文件:
- `zn-ai/src/stores/chat.ts`
- `zn-ai/electron/api/routes/files.ts`
- `zn-ai/electron/gateway/handlers/chat.ts`
清单:
- [ ] 为文件类 skill 建立统一附件输入 schema
- [ ] 首批先验证表格类输入
- [ ] tool/skill 执行时能拿到稳定文件路径或句柄信息
- [ ] 附件缺失、路径失效时返回结构化错误
#### P0-6 把 tool 结果写回会话历史
状态:部分完成
现状:
- `tool_use / tool_result` 已写回 transcript并能参与后续轮次的推理
- 但大结果摘要、上下文膨胀控制和进一步的历史裁剪策略还没有完全收口
目标:
- 执行过的 skill 结果必须成为会话上下文的一部分
- 下一轮问“继续分析第 2 个 sheet”时模型能接上
当前涉及文件:
- `zn-ai/electron/gateway/handlers/chat.ts`
- `zn-ai/src/stores/chat.ts`
- `zn-ai/runtime-shared/shared/chat-model.ts`
清单:
- [ ] 在 transcript/session history 中保留 `tool_use / tool_result`
- [ ] 重新定义发送下一轮时的 history flatten 规则
- [ ] 避免把关键 tool 结果过滤掉
- [ ] 对大结果做摘要,避免上下文膨胀
### P1 重要项
这些不一定是第一批 blocker但会直接影响可用性和稳定性。
#### P1-1 建立“聊天 runtime 与 Skills 页”的同步机制
状态:部分完成
现状:
- `skills.update/install` 后已能广播 runtime refreshSkills 页也已经接到这类变化
- 但聊天 runtime/store 侧还没有完整消费这些变更,热更新边界仍不够清晰
当前涉及文件:
- `zn-ai/electron/gateway/handlers/skills.ts`
- `zn-ai/electron/gateway/types.ts`
- `zn-ai/src/lib/skills-api.ts`
清单:
- [ ] `skills.update` 后广播 runtime refresh
- [ ] 聊天 runtime 监听 skills 变化并刷新能力缓存
- [ ] 明确“需要重启 gateway”与“可热更新”的边界
#### P1-2 补齐聊天 UI 的执行可视化
状态:部分完成
现状:
- 通用 tool-only 消息和结果卡片已经具备,`browser.open_url``skills.install` 有专项展示
- 但表格分析专项卡片、失败重试和查看详情入口还没有补齐
当前涉及文件:
- `zn-ai/src/stores/chat.ts`
- `zn-ai/src/components/chat/ChatMessageList.tsx`
- `zn-ai/src/pages/Home/index.tsx`
清单:
- [ ] 区分普通 assistant 文本和 tool-only 消息
- [ ] 增加通用 tool 结果展示结构
- [ ] 首批先做好表格分析类结果卡片
- [ ] 为失败结果增加重试或查看详情入口
#### P1-3 对齐 ClawX 的 workspace/context 注入机制
状态:未开始
现状:
- 目前仍以现有 runtime context 注入为主
- workspace/context 资源目录、统一说明文件和启动期上下文装配还没有正式开工
当前参考文件:
- `ClawX/electron/utils/openclaw-workspace.ts`
- `ClawX/resources/context/AGENTS.clawx.md`
- `ClawX/resources/context/TOOLS.clawx.md`
清单:
- [ ]`zn-ai` 增加运行时 context 资源目录
- [ ] 定义 skill/tool 使用约束说明
- [ ] 让 agent/workspace 在 gateway 启动后获得一致上下文
#### P1-4 明确 provider 能力矩阵
状态:未开始
现状:
- provider 契约已经开始具备 tool-capable 方向的定义
- 但支持矩阵、白名单和成体系的降级策略还没有形成可执行结果
清单:
- [ ] 列出支持 tool loop 的 provider/model 白名单
- [ ] 不支持时给出明确降级策略
- [ ] 区分“模型不支持”与“skill 执行失败”
### P2 增强项
这些会提高稳定性、可维护性和长期对齐度。
#### P2-1 Skill 类型分层
状态:部分完成
现状:
- capability parser 已有轻量分类能力
- 但 taxonomy 冻结、分类专属 adapter 和跨类型接入标准还没有全部完成
目标:
- 不是所有 skill 都有相同输入输出模式
- 需要按类型建立统一接入层
推荐分类:
- 文档/文件类
- 浏览器/网页类
- 搜索/检索类
- 命令/脚本类
- 外部 API 类
清单:
- [ ] 定义 skill type taxonomy
- [ ] 为每类定义默认 input/output adapter
- [ ] 首批至少覆盖文档类与浏览器类
#### P2-2 回归测试与 smoke
状态:部分完成
现状:
- 已有 runtime context、planner、shortcut、chat-tooling 等聚焦单测
- 但非 `xlsx` skill 回归、`tool_use -> tool_result -> final` 集成测试,以及开发态/打包态 smoke 还未补齐
清单:
- [ ] 单测:已启用 skill 会出现在 runtime context
- [ ] 单测:上传 `.xlsx` 后进入表格分析链路
- [ ] 单测:新增一个非 `xlsx` skill 也能进入通用 registry
- [ ] 集成测试:`tool_use -> tool_result -> final`
- [ ] smoke开发态和打包态都验证一次
#### P2-3 错误模型和日志分层
状态:部分完成
现状:
- shared schema 已具备基础的 tool error/result 结构
- 但授权、provider、tool、skill、附件的统一错误模型和 UI 提示映射仍未收口
清单:
- [ ] 区分授权错误、provider 错误、tool 错误、skill 错误、附件错误
- [ ] transcript 中保留最小必要诊断字段
- [ ] UI 侧映射成用户能理解的提示
## 9. 推荐推进顺序
当前进度判断:
- 第一阶段:已基本完成
- 第二阶段:部分完成
- 第三阶段:未完成
### 第一阶段
- P0-1 全量 enabled skills 注入 runtime
- P0-2 通用 skill metadata 抽取
- P0-3 tool-capable 聊天运行时
- P0-4 通用 planner / registry
- P0-5 附件进入通用 skill 输入链路
完成标志:
- 架构上已经不再依赖单个 skill 特判
- `xlsx/minimax-xlsx` 成为第一条跑通的样板链路
### 第二阶段
- P0-6 tool 结果回灌历史
- P1-1 runtime 与 Skills 页同步
- P1-2 聊天 UI 执行可视化
完成标志:
- 用户能稳定看到执行过程,且多轮能接续
### 第三阶段
- P1-3 workspace/context 对齐
- P1-4 provider 能力矩阵
- P2 全部增强项
完成标志:
- 新增 skill 时,聊天运行时不再需要新增 ad-hoc 接入代码
## 10. 推荐 sub-agent 编制
### 9.1 推荐数量
- 推荐:`7` 个 sub-agent
- 最小可行:`5` 个 sub-agent
- 稳妥完整:`8` 个 sub-agent
解释:
- 因为这次目标已经从“单个 skill 样板”升级为“全量 skills 通用接入架构”
- 需要单独有人负责 skill metadata/registry不适合继续塞进原有分工里
默认建议采用:
- `7 个 worker sub-agent + 1 个主协调 agent`
说明:
- 主协调 agent 不计入上面的 `sub-agent` 数量
- 主协调 agent 负责冻结接口、安排波次、收敛冲突、做最终集成
### 9.2 7 个 sub-agent 分工
#### SA-1 Skill Capability Registry
职责:
- 把所有 enabled skills 注入聊天 runtime context
- 定义通用 capability schema
- 负责 skill metadata 抽取与 registry
主要文件归属:
- `zn-ai/electron/gateway/runtime-context.ts`
- `zn-ai/electron/gateway/handlers/skills.ts`
- `zn-ai/electron/gateway/types.ts`
- 新增 `zn-ai/electron/gateway/skill-capability-registry.ts`
- 新增 `zn-ai/electron/gateway/skill-capability-parser.ts`
验收:
- 任何已启用 skill 都能进入 runtime capability 列表
#### SA-2 Provider 与 Tool Runtime
职责:
- 把文本 provider 升级为可执行 tool 的聊天运行时
- 定义 tool call / tool result / resume 推理接口
主要文件归属:
- `zn-ai/electron/providers/BaseProvider.ts`
- `zn-ai/electron/providers/OpenAIProvider.ts`
- 新增 `zn-ai/electron/gateway/tool-runtime.ts`
验收:
- 模型能发起真实 tool 调用,不再只有文本流
#### SA-3 Planner / Tool Registry
职责:
- 设计通用 planner
- 统一 skill/tool 注册与调度
- 去掉继续堆特判的趋势
主要文件归属:
- 新增 `zn-ai/electron/gateway/tool-registry.ts`
- 新增 `zn-ai/electron/gateway/skill-planner.ts`
- 必要时补 `zn-ai/electron/gateway/types.ts`
验收:
- `skills.install`、浏览器、`xlsx/minimax-xlsx` 都通过统一 registry 接入
#### SA-4 Chat Orchestration / Transcript
职责:
- 负责 `chat.send` 主编排
-`tool_use / tool_result / final` 写回会话历史
- 处理 history flatten 和多轮续接
主要文件归属:
- `zn-ai/electron/gateway/handlers/chat.ts`
- `zn-ai/electron/gateway/session-store.ts`
- `zn-ai/runtime-shared/shared/chat-model.ts`
验收:
- 多轮对话能接上前一轮 tool 结果
#### SA-5 Attachment / File Skill Input
职责:
-`.xlsx/.csv/.tsv` 等文件变成通用 skill 输入
- 先打通文件类 skill 输入适配层
主要文件归属:
- `zn-ai/src/stores/chat.ts`
- `zn-ai/electron/api/routes/files.ts`
验收:
- 文件类 skill 拿到稳定输入,不再只依赖文本路径猜测
#### SA-6 Renderer Tool UI
职责:
- 聊天 UI 展示 tool 卡片、状态、结果摘要、失败详情
- 对齐 `pendingFinal`、tool-only 消息和分析过程可视化
主要文件归属:
- `zn-ai/src/components/chat/ChatMessageList.tsx`
- `zn-ai/src/pages/Home/index.tsx`
- 新增聊天执行可视化组件时归此 agent
验收:
- 用户能在聊天页看清楚“何时开始分析、分析了什么、结果是什么”
#### SA-7 Testing / Smoke / Rollout
职责:
- 为前 6 个 agent 的改动补回归测试
- 增加最小集成测试和开发态 smoke
- 记录“新增 skill 是否零特判接入”的验收结果
主要文件归属:
- `zn-ai/tests/chat-runtime-context.test.ts`
- `zn-ai/tests/gateway-rpc-dispatch.test.ts`
- 新增与 skill registry、planner、tool_result 相关测试
- 需要时补充 `docs/` 中的验收记录
验收:
- 至少有 1 条覆盖“已启用 skill + planner + tool_result + final”的集成链路
- 至少有 1 条覆盖“新增非 xlsx skill 无需新增聊天特判”的回归验证
### 9.3 6 个核心文件实施任务拆解表
这张表只聚焦最容易互相卡住的 6 个核心文件。
- 辅助文件仍然跟随主责 `sub-agent` 所在分支推进
- 任何辅助文件的改动,都不应绕开对应核心文件的 owner
- `chat-model.ts` 虽然归 `SA-4` 主责,但必须以“共享契约先冻结”方式提前进入 Wave 1
| 核心文件 | 主要实施任务 | 主责 sub-agent | 主要协作方 | 前置冻结 / 依赖 | 推荐合并顺序 |
| --- | --- | --- | --- | --- | --- |
| `zn-ai/runtime-shared/shared/chat-model.ts` | 冻结 `thinking / tool_use / tool_result / assistant final / tool status / attachments` 的共享 schema统一 gateway、store、UI 的消息结构 | `SA-4` | `SA-1` `SA-2` `SA-6` | 先评审 schema再允许其他链路接入这是后续 `handlers/chat.ts``ChatMessageList.tsx` 的共同前置 | `0` |
| `zn-ai/electron/gateway/runtime-context.ts` | 把当前 enabled skills、内建 tools、session 信息装配成 runtime capability 注入入口;从“固定工具说明”升级成“全量能力注入” | `SA-1` | `SA-3` `SA-4` | 依赖 capability schema 冻结;与 `skill-capability-registry.ts``skill-capability-parser.ts` 一起推进 | `1` |
| `zn-ai/electron/gateway/tool-runtime.ts` | 定义 preflight check、adapter dispatch、raw result -> `tool_result` 标准化、resume 推理接口 | `SA-2` | `SA-3` `SA-4` | 依赖 `chat-model.ts``tool_result` 结构;需要先冻结 provider / runtime contract | `2` |
| `zn-ai/electron/gateway/skill-planner.ts` | 根据 capability list、附件、历史、用户意图产出统一 planner decision去掉继续堆特判的趋势 | `SA-3` | `SA-1` `SA-2` `SA-4` | 依赖 runtime capability shape 与 tool runtime contract`tool-registry.ts` 同分支推进 | `3` |
| `zn-ai/electron/gateway/handlers/chat.ts` | 接管 `chat.send` 主编排,串联 runtime context、planner、executor、transcript 写回与多轮续接 | `SA-4` | `SA-2` `SA-3` `SA-5` | 必须等 `runtime-context.ts``tool-runtime.ts``skill-planner.ts` 的契约稳定后再合并;其他 agent 不直接改这个文件 | `4` |
| `zn-ai/src/components/chat/ChatMessageList.tsx` | 消费统一 transcript / `tool_result` / `toolStatuses`,渲染 tool 卡片、错误、摘要、最终回答 | `SA-6` | `SA-4` `SA-7` | 必须等 `chat-model.ts``handlers/chat.ts` 稳定后接入;优先做通用渲染,再做类型增强 | `5` |
推荐按下面的节奏合并:
1. 先合并 `chat-model.ts` 的 schema 冻结 PR。
2. 再并行推进 `runtime-context.ts``tool-runtime.ts``skill-planner.ts`,但以契约评审通过为合并门槛。
3. 然后由 `SA-4` 合并 `handlers/chat.ts`,把前三者正式编排进主链路。
4. 最后由 `SA-6` 合并 `ChatMessageList.tsx`,避免 UI 反向驱动协议。
这 6 个文件对应的辅助文件跟随关系建议如下:
- `runtime-context.ts`
对应辅助文件:`skill-capability-registry.ts``skill-capability-parser.ts`、必要时 `handlers/skills.ts`
- `tool-runtime.ts`
对应辅助文件:`BaseProvider.ts``OpenAIProvider.ts`
- `skill-planner.ts`
对应辅助文件:`tool-registry.ts`、必要时 `gateway/types.ts`
- `handlers/chat.ts`
对应辅助文件:`session-store.ts`、必要时 `src/stores/chat.ts`
- `ChatMessageList.tsx`
对应辅助文件:`src/pages/Home/index.tsx`、新增 tool result 展示组件
如果要把冲突降到最低,可以把这张表当成 branch / PR 边界:
- `SA-1` 不直接改 `handlers/chat.ts`,而是通过 capability schema 和 registry 模块接入
- `SA-2` 不在 provider 内重做 planner而是只冻结 runtime contract
- `SA-3` 不直接改 UI只输出 planner decision 与 registry 结构
- `SA-4` 只在前三项契约稳定后改 `handlers/chat.ts`
- `SA-6` 只消费共享协议,不反向决定 gateway 数据结构
## 11. 波次安排
### Wave 1
当前状态:已完成
现状:
- 核心契约、registry、planner 和 tool runtime 已经冻结并落地
- 第一条样板链路已经跑通,不再停留在纯设计阶段
- `SA-1` Skill Capability Registry
- `SA-2` Provider 与 Tool Runtime
- `SA-3` Planner / Tool Registry
目标:
- 先冻结最核心接口skill capability schema、tool runtime contract、planner contract
### Wave 2
当前状态:部分完成
现状:
- transcript 回写和样板附件链路已经进入主聊天编排
- 但 runtime 与 Skills 页的同步,以及表格专项 UI 可视化还没有全部完成
- `SA-5` Attachment / File Skill Input
- `SA-4` Chat Orchestration / Transcript
目标:
- 在已冻结契约上,把样板链路接入主聊天编排
### Wave 3
当前状态:部分完成
现状:
- 通用 tool UI 和一部分回归验证已经启动
- 但 provider 能力矩阵、完整 smoke 和 rollout 收口还没有完成
- `SA-6` Renderer Tool UI
- `SA-7` Testing / Smoke / Rollout
目标:
- 把用户体验和回归验证补齐
## 12. 协作约束
为避免冲突,建议遵守这 5 条:
1. 每个 sub-agent 只改自己负责的文件,不跨写别人的主文件。
2. `zn-ai/electron/gateway/handlers/chat.ts` 只归 `SA-4`,其他人不要直接改。
3. `zn-ai/src/stores/chat.ts` 只归 `SA-5`UI agent 不要同时改这个文件。
4. `zn-ai/electron/gateway/types.ts``SA-1` 牵头冻结,其他 agent 只在评审后接入。
5. 主协调 agent 统一做接口冻结、合并、回归验证,不让多个 agent 反复改同一入口。
## 13. 功能交叉与冲突清单
这一节把真正会互相卡住的交叉点单独列出来。
### 12.1 冲突 A`chat.send` 是所有能力的汇合点
交叉功能:
- skill 可见性
- planner 结果接入
- tool runtime 执行
- 附件输入
- transcript 写回
- final answer 回传
核心文件:
- `zn-ai/electron/gateway/handlers/chat.ts`
处理规则:
- 只允许 `SA-4` 直接修改
- `SA-1``SA-2``SA-3``SA-5` 通过契约和辅助模块接入
### 12.2 冲突 B`src/stores/chat.ts` 同时承担“附件状态”和“聊天执行状态”
交叉功能:
- 附件 staging
- tool 状态消费
- pendingFinal 状态
- UI 展示状态
核心文件:
- `zn-ai/src/stores/chat.ts`
处理规则:
- `SA-5` 主责 store shape
- `SA-6` 尽量通过 selector 和 helper 消费,不重写 store 结构
### 12.3 冲突 C事件协议同时影响 runtime、store、UI
交叉功能:
- `tool:status`
- `chat:final`
- 未来的 `tool_use / tool_result / thinking`
- runtime refresh
核心文件:
- `zn-ai/electron/gateway/types.ts`
- `zn-ai/runtime-shared/shared/chat-model.ts`
处理规则:
- 先冻结 gateway event contract
- 再冻结 transcript/chat-model contract
- UI 最后接入,不反向驱动协议改名
### 12.4 冲突 Dprovider 能力和 planner/runtime 边界容易混淆
交叉功能:
- provider 是否支持 tool loop
- runtime 如何继续二次调用模型
- planner 与 executor 谁负责决策
核心文件:
- `zn-ai/electron/providers/BaseProvider.ts`
- `zn-ai/electron/providers/OpenAIProvider.ts`
- `zn-ai/electron/gateway/tool-runtime.ts`
- `zn-ai/electron/gateway/skill-planner.ts`
处理规则:
- `SA-2` 先冻结 provider/runtime 边界
- `SA-3` 再实现 planner不在 provider 内重复做编排
### 12.5 冲突 Eskill metadata 抽取与 renderer 展示不要耦合
交叉功能:
- `SKILL.md` 抽取
- capability schema
- UI 上如何显示 skill 名称、说明、输入输出
处理规则:
- `SA-1` 负责 runtime capability schema
- `SA-6` 只能消费 schema不反过来决定抽取字段
## 14. 最小落地建议
如果本轮只做最小可行闭环,优先只做这 6 件事:
1. 聊天发送前读取 enabled skills并把它们注入 runtime context。
2. 建立通用 skill capability registry而不是只处理 `minimax-xlsx`
3. 为聊天 runtime 增加最小 tool loop不再只走纯文本 provider。
4. 让文件类附件进入统一 skill 输入链路。
5.`tool_result` 写回 session history保证多轮可续接。
6. 在聊天 UI 里把执行过程展示成 tool 卡片,而不是只显示最终一句话。
## 15. 非目标
这一版清单默认不把下面内容作为首批阻塞项:
- skill 市场页样式优化
- 为每一个 skill 都单独做精细化 UI 定制
- 完整复刻 ClawX 的所有 execution graph 细节
- 与 skill 运行时无关的 channel/plugin 改造
注意:
- “所有 skills 一次性通用化接入聊天运行时”不再是非目标
- 但“所有 skills 一次性都达到同等体验质量”仍然不是首批目标
## 16. 建议先开工的代码入口
- `zn-ai/electron/gateway/handlers/chat.ts`
- `zn-ai/electron/gateway/runtime-context.ts`
- `zn-ai/electron/gateway/handlers/skills.ts`
- `zn-ai/electron/providers/BaseProvider.ts`
- `zn-ai/electron/providers/OpenAIProvider.ts`
- `zn-ai/src/stores/chat.ts`
- `zn-ai/src/components/chat/ChatMessageList.tsx`
- `zn-ai/electron/api/routes/files.ts`
- 新增 `zn-ai/electron/gateway/skill-capability-registry.ts`
- 新增 `zn-ai/electron/gateway/skill-capability-parser.ts`
- 新增 `zn-ai/electron/gateway/tool-registry.ts`
- 新增 `zn-ai/electron/gateway/skill-planner.ts`
## 17. Progress Update (2026-04-24)
This checkpoint extends the "first batch of real generic skill execution adapters"
beyond `xlsx/minimax-xlsx` and lands the first reusable document-family,
search-family, browser-family, and command-family runtimes.
Completed in this round:
- `zn-ai/electron/gateway/chat-tooling.ts`
- Added a real document adapter for enabled `docx`, `pptx`, and `pdf` skills.
- Added Node-side analyzers for `.docx`, `.pptx`, and `.pdf`.
- Added real search adapters for `brave-web-search` and `tavily-search`.
- Added a browser-category adapter so browser-capable skills can reuse the managed `browser.open_url` runtime.
- Added a command-category adapter that keeps `find-skills` on the safe ClawHub path and also executes generic command-style skills from safe manifest command templates or a single local `scripts/` entrypoint.
- Reads skill credentials from saved skill config (`apiKey` / `env`) instead of relying only on process env.
- Normalizes Brave and Tavily responses into shared `search-results` payloads and URL artifacts.
- Reused the same `tool_runtime -> tool_result -> transcript` path as spreadsheet analysis.
- Kept unsupported generic skills on capability-aware blocked results instead of silently falling through.
- `zn-ai/src/components/chat/ChatMessageList.tsx`
- Added a dedicated search-result card for query, provider, answer, ranked results, and install commands.
- Reused the same card for command-style discovery results such as `find-skills`.
- `zn-ai/electron/gateway/skill-capability-parser.ts`
- Tightened file-extension inference so URL-like fragments such as `.search` or `.results` no longer become fake input extensions.
- Tightened auth detection to prefer explicit auth/env signals and avoid substring false positives.
- Promoted office-style document skills into the shared `document-analysis` render shape.
- `zn-ai/tests/chat-tooling.test.ts`
- Added execution regressions for `.docx`, `.pptx`, and `.pdf`.
- Added execution regressions for `brave-web-search` and `tavily-search`.
- Added execution regressions for browser-capable skills, `find-skills`, and generic command-style skills that run from manifest command templates or local script entrypoints.
- Kept `.xls` fallback coverage and generic blocked-state coverage.
- `zn-ai/tests/chat-message-list.test.tsx`
- Added UI regressions for dedicated search cards and command-style install-command rendering.
- `zn-ai/tests/skill-capability-parser.test.ts`
- Added parser regressions for document capability classification, URL-like extension filtering, and auth detection.
Current first-batch runtime coverage:
- Spreadsheet execution: `.xls`, `.xlsx`, `.xlsm`, `.csv`, `.tsv`
- Document execution: `.docx`, `.pptx`, `.pdf`
- Search execution: `brave-web-search`, `tavily-search`
- Browser execution: browser-capable skills that map to explicit URL open flows
- Command execution: `find-skills` through ClawHub search, plus generic command-style skills that expose a safe single-command template or one local `scripts/` entrypoint
- Generic non-document skills without a real adapter: still blocked with explicit reasons such as `missing_required_env`, `user_authorization_required`, or `skill_runtime_not_implemented`
What is still not done:
- Browser/search/command category executors now exist, but multi-step shell flows, install/login/setup commands, and other unsafe command patterns are still intentionally blocked. Generic command execution is limited to safe single-command templates and local script entrypoints.
- Cross-type adapter manifesting and large-scale skill onboarding are still follow-up work after this checkpoint.
Verification for this checkpoint:
- `pnpm typecheck`
- `pnpm exec vitest run tests/skill-capability-parser.test.ts tests/chat-tooling.test.ts`
- `pnpm exec vitest run tests/chat-provider-tool-loop.test.ts tests/chat-store-runtime-refresh.test.ts tests/chat-runtime-context.test.ts tests/runtime-context-capabilities.test.ts tests/skill-planner.test.ts tests/chat-tooling.test.ts tests/skill-capability-parser.test.ts tests/chat-message-list.test.tsx`