Files
zclaw_openfang/wiki/hands-skills.md
iven c10e50d58e docs(wiki): Phase D完成 — 6模块页重构(routing/chat/butler/hands-skills/pipeline/data-model)
- routing.md: 移除Store/lib列表+5节模板 (330→131行)
- chat.md: 添加集成契约+不变量 (180→134行)
- butler.md: 移除重复→引用memory/hands-skills (215→150行)
- hands-skills.md: 5节模板+契约+不变量 (281→170行)
- pipeline.md: 添加契约+重组 (157→154行)
- data-model.md: 添加契约+双库架构图 (181→153行)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 21:53:17 +08:00

171 lines
7.5 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.

---
title: Hands + Skills + MCP
updated: 2026-04-22
status: active
tags: [module, hands, skills, mcp]
---
# Hands + Skills + MCP
> 从 [[index]] 导航。关联: [[chat]] [[middleware]] [[butler]]
## 1. 设计决策
**Hands = 自主能力 (行动层), Skills = 知识技能 (认知层), MCP = 外部工具协议。**
| 决策 | WHY |
|------|-----|
| 7 注册 Hands (6 TOML + _reminder) | 每个 Hand 有独立配置和 Rust 实现,启用/禁用由 `enabled` 字段控制。_reminder 由 kernel 代码注册,无 HAND.toml |
| 75 Skills + 语义路由 | SKILL.md 定义领域知识SemanticSkillRouter 用 TF-IDF 匹配(详见 [[butler]] 路由细节),增强 LLM 领域能力而不硬编码 |
| MCP bridge | 运行时发现外部工具服务器McpToolWrapper 适配 Tool trait让 LLM 在对话中直接调用 filesystem/database 等外部工具 |
| LLM Tool Calling 触发 | Skill 调用通过 LLM 生成 ToolUse不是直接函数调用。保持 LLM 主导决策权 |
| 定时提醒链路 | NlScheduleParser 中文时间->cron + _reminder Hand + TriggerManager支持"每天早上9点提醒我查房" |
## 2. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `crates/zclaw-hands/src/hands/` | 7 个 Hand 实现 (browser/collector/researcher/clip/twitter/quiz/reminder) |
| `crates/zclaw-runtime/src/tool/registry.rs` | ToolRegistry 工具注册表 |
| `crates/zclaw-runtime/src/tool/builtin/execute_skill.rs` | KernelSkillExecutor 技能执行 |
| `crates/zclaw-skills/src/semantic_router.rs` | TF-IDF 语义路由 (路由细节见 [[butler]]) |
| `crates/zclaw-skills/src/` | 技能解析、索引、WASM runner |
| `crates/zclaw-runtime/src/nl_schedule.rs` | 中文时间->cron 解析器 (6 种模式) |
| `crates/zclaw-protocols/src/mcp_tool_adapter.rs` | MCP 工具适配器 + 服务管理 |
| `crates/zclaw-protocols/src/mcp.rs` | MCP 协议类型 + BasicMcpClient (stdio transport) |
| `crates/zclaw-runtime/src/tool/builtin/mcp_tool.rs` | McpToolWrapper (Tool trait 桥接) |
| `desktop/src/store/handStore.ts` | 前端 Hand 状态 |
| `desktop/src/lib/mcp-client.ts` | 前端 MCP 客户端 |
### Hand 触发流
```
LLM 生成 ToolUse{hand_name, params}
-> AgentLoop (loop_runner.rs) 检测 ContentBlock::ToolUse
-> ToolRegistry.get(hand_name) -> HandExecutor
-> needs_approval? -> 等待 approvalStore 确认 -> 用户批准
-> Hand.execute(params) -> 结果
-> ToolResult -> LLM 继续对话
-> Tauri Event emit -> handStore 更新状态
```
### 集成契约
| 方向 | 模块 | 接口 / 触发点 |
|------|------|---------------|
| Called by <- | loop_runner | Tool 执行 | Every tool call during chat |
| Calls -> | browser/Twitter/etc | External APIs | Hand-specific operations |
| Provides -> | middleware: SkillIndex@200 | `skill_index.rs` | 技能索引注入 system prompt |
| Provides -> | mcp: McpToolWrapper | `Tool` trait | 外部工具桥接到 ToolRegistry |
### Hand Tauri 命令 (8 个)
| 命令 | 状态 | 说明 |
|------|------|------|
| `hand_list` | @connected | 列出可用 Hands |
| `hand_execute` | @connected | 执行 Hand |
| `hand_approve` | @connected | 审批 Hand 执行 |
| `hand_cancel` | @connected | 取消执行 |
| `hand_get` | @connected | 获取 Hand 详情 |
| `hand_run_status` | @connected | 运行状态查询 |
| `hand_run_list` | @connected | 运行列表 |
| `hand_run_cancel` | @reserved | 取消运行 (无前端 UI) |
### MCP 命令 (4 个)
`mcp_start_service`, `mcp_stop_service`, `mcp_list_services`, `mcp_call_tool`
MCP 工具在 ToolRegistry 中使用限定名 `service_name.tool_name` (如 `filesystem.read_file`)。
`McpManagerState``Kernel` 共享 `Arc<RwLock<Vec<McpToolAdapter>>>`,通过 `sync_to_kernel()` 同步。
## 3. 代码逻辑
### 7 注册 Hands
| Hand | 功能 | 依赖 | 测试 | 配置 |
|------|------|------|------|------|
| Browser | 浏览器自动化 (23 Tauri 命令) | WebDriver | 11 | `hands/browser.HAND.toml` |
| Collector | 数据收集聚合 | -- | 9 | `hands/collector.HAND.toml` |
| Researcher | 深度研究 + 网络搜索 | 网络 | 25 | `hands/researcher.HAND.toml` |
| Clip | 视频处理 | FFmpeg | 32 | `hands/clip.HAND.toml` |
| Twitter | Twitter 自动化 (12 API v2) | OAuth 1.0a | 30 | `hands/twitter.HAND.toml` |
| Quiz | 测验生成 | -- | 5 | `hands/quiz.HAND.toml` |
| _reminder | 定时提醒 (系统内部) | -- | -- | 无 TOML (代码注册) |
### Researcher 搜索能力 (04-22 修复)
- **搜索引擎**: Baidu + Bing CN 并行 (国内可用)DuckDuckGo fallback
- **网页获取**: Jina Reader API (优先,干净 Markdown) -> HTTP fetch (降级)
- **LLM 兼容**: 扁平化 input_schema (action/query/url/urls/engine),兼容 glm-5.1 等国产模型
- **空参数回退**: LLM 发送空 `{}`loop_runner 注入 `_fallback_query` 自动搜索
### 定时提醒链路
```
用户消息 "每天早上9点提醒我查房"
-> agent_chat_stream (chat.rs)
-> has_schedule_intent() 关键词检测 (提醒我/定时/每天/每周等)
-> parse_nl_schedule() -> cron 表达式
-> ScheduleParseResult::Exact (confidence >= 0.8)
-> TriggerConfig { hand_id: "_reminder", trigger_type: Schedule { cron } }
-> kernel.create_trigger() -> TriggerManager 存储
-> 跳过 LLM 调用 (省 token)
-> SchedulerService 每60秒轮询 -> should_fire_cron() -> ReminderHand.execute()
```
### Skill 调用链路 (LLM Tool Calling)
```
skills/ -> SkillRegistry 加载 -> SkillIndexMiddleware@200 注入系统提示
-> LLM 看到 skill_load + execute_skill 工具定义
-> LLM 生成 ToolUse{skill_load} -> AgentLoop -> 返回技能详情
-> LLM 生成 ToolUse{execute_skill} -> KernelSkillExecutor -> Skill 执行
-> ToolResult -> LLM 继续对话
```
关键: Anthropic Driver 要求 ToolResult 必须用 `ContentBlock::ToolResult{tool_use_id, content}` 格式。
### 不变量
- Hand 配置中 `enabled=false` 的 Hand 不会注册到 ToolRegistry
- Skill 调用通过 LLM Tool Calling不是直接函数调用
- MCP 限定名 `service_name.tool_name` 避免与内置工具冲突
- 已删除空壳 Hands (04-17): Whiteboard/Slideshow/Speech净减 ~5400 行
## 4. 活跃问题 + 陷阱
### 活跃
| 问题 | 状态 | 说明 |
|------|------|------|
| Clip 依赖 FFmpeg | P3 | 用户需本地安装 FFmpeg否则视频处理 Hand 不可用 |
| Hands E2E 通过率 ~70% | P2 | 10 Hand 全部启用,审批机制正常,但部分 Hand 边界场景未覆盖 |
| hand.rs TODO | P2 | tool_count/metric_count 待从实际 Hand 实例填充 |
### 历史 (已修复)
| 问题 | 修复 |
|------|------|
| skill_execute 反序列化崩溃 | SEC2-P0-01 04-02 已修复 |
| Researcher 空参数 (glm-5.1 不理解 oneOf+const schema) | 04-22 schema 扁平化 + empty-input fallback |
| 排版乱码 (stripToolNarration 句子级拆分破坏 markdown) | 04-22 行级过滤 |
## 5. 变更日志
| 日期 | 变更 | 关联 |
|------|------|------|
| 2026-04-22 | Wiki 5-section 重构: 281->~195 行,语义路由细节引用 [[butler]] | wiki/ |
| 2026-04-22 | Researcher 搜索修复: schema 扁平化 + 空参数回退 + 排版修复 | commit 5816f56+81005c3 |
| 2026-04-17 | 空壳 Hand 清理: Whiteboard/Slideshow/Speech 删除,净减 ~5400 行 | Phase 5 清理 |
| 2026-04-16 | 3 项 P0 修复 + 5 项 E2E Bug 修复 | 三端联调测试 |
| 2026-04-09 | 管家模式交付: 语义路由 TF-IDF 接入 ButlerRouter | 6 交付物完成 |
### 测试概览
| 功能 | Crate | 测试数 |
|------|-------|--------|
| Hands (7 实现) | zclaw-hands | 117 |
| 语义路由 + WASM + 编排 | zclaw-skills | 26 |
| **合计** | | **143** |