# 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 refresh,Skills 页也已经接到这类变化 - 但聊天 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 冲突 D:provider 能力和 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 冲突 E:skill 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`