Generated by sparticle-toolkit feature-memory-sync Co-authored-by: Denya0529 <217564326+Denya0529@users.noreply.github.com>
179 lines
13 KiB
Markdown
179 lines
13 KiB
Markdown
# Skill 功能
|
||
|
||
> 负责范围:技能包管理服务 - 核心实现
|
||
> 最后更新:2026-05-26
|
||
> 最后更新:2026-05-23
|
||
> 最后更新:2026-04-20
|
||
|
||
> 最后更新:2026-05-20
|
||
|
||
## 当前状态
|
||
|
||
Skill 系统支持两种来源:官方 skills (`./skills/`) 和用户 skills (`projects/uploads/{bot_id}/skills/`)。支持 Hook 系统和 MCP 服务器配置,通过 SKILL.md 或 plugin.json 定义元数据。
|
||
|
||
2026-04 起 skill 包可在 `agents/*.md` 下定义子 agent(由 `SubAgentMiddleware` 加载);启用 Daytona 沙箱时 skill 加载路径变为沙箱内的 `/workspace/skills`。
|
||
|
||
MCP UI 类 skill 已按 MCP Apps 模式改造:工具返回数据,静态 HTML App 由 host 加载后通过 postMessage 接收数据渲染。
|
||
|
||
目前已新增一批**纯 `SKILL.md` 型业务 skill MVP**,用于研究、摘要、报告和情报编排,底层文件处理与外部检索能力继续复用既有 skill。
|
||
|
||
## 核心文件
|
||
|
||
- `routes/skill_manager.py` - Skill 上传/删除/列表 API
|
||
- `agent/plugin_hook_loader.py` - Hook 系统实现
|
||
- `agent/deep_assistant.py` - `CustomSkillsMiddleware`
|
||
- `agent/prompt_loader.py` - PrePrompt hooks + MCP 配置合并
|
||
- `routes/mcp_resources.py` - MCP App 静态 HTML resource REST 入口
|
||
- `skills/` - 官方 skills 目录
|
||
- `skills_developing/` - 开发中 skills
|
||
- `agent/subagent_loader.py` - 扫描 skill `agents/*.md` 加载子 agent(2026-05 引入)
|
||
- `agent/mcp_trace_meta.py` - 对 `ClientSession.call_tool` 做 monkey-patch,向 `rag_retrieve` / `table_rag_retrieve` 的 MCP `_meta` 注入 `trace_id`(2026-05 引入)
|
||
|
||
## 最近重要事项
|
||
|
||
- [2026-05-26](changelog/2026-Q2.md): skill 引入 `category` 字段——`routes/skill_manager.py` 在 `SkillItem` / `SkillValidationResult` 增加 `category`,从 `plugin.json` 与 `SKILL.md` frontmatter 解析,official skill 默认 `"other"`、user skill 默认 `"custom"`;并通过 batch 给 common/developing/onprem/support 路径下大量 skill 元数据补 `category`,`data-dashboard` / `mcp-ui` 归类 `Interactive UI`(`203dcf4`, `3ada55a`, `9658588`)
|
||
- [2026-05-26](changelog/2026-Q2.md): developing 分支大合并新增多个 skill:`ai-ppt-generator`(百度 AI PPT)、`nfc-medicine-lookup`(NFC 药品检索)、`ppt-outline`(PPT 大纲 / HTML 演示文稿)、`z-card-image`(配图 / 卡片图),同时 `skills/linggan/*` 系列 skill 经合并回归(`3ada55a`)
|
||
- [2026-05-23](changelog/2026-Q2.md): 新增 MCP App 型 `skills/developing/ecommerce-storefront/`——含 `product-list` / `order-confirm` 两个 HTML App + 自带 `ecommerce_server.py` MCP server;同时落地 `docs/mcp-app-training.md`(约 1063 行)作为 MCP App 培训材料(`9d001c8`)
|
||
- [2026-05-21](changelog/2026-Q2.md): Daytona 沙箱模式下 `init_agent` 在沙箱内写入 `BASH_ENV` 文件,注入 `ASSISTANT_ID` / `USER_IDENTIFIER` / `TRACE_ID` / `ENABLE_SELF_KNOWLEDGE` 与 `config.shell_env` 的 shell 环境变量(`776acc2`)
|
||
- [2026-05-12](changelog/2026-Q2.md): 跨 6→10 个 skill 变体批量精修 `retrieval-policy*.md`,统一 onprem/support/autoload 各路径下的 policy 口径(`be96f24`, `7b4f03d`)
|
||
- [2026-05-11](changelog/2026-Q2.md): 新增子 agent (SubAgent) 支持——skill 包通过 `agents/*.md` 暴露子 agent,由 `SubAgentMiddleware` 加载;附 `pmda-drug-info` skill 示例(`5b634bc`)
|
||
- [2026-05-11](changelog/2026-Q2.md): `pmda-drug-info` 的 `pmda_server.py` 大改为 mock 实现(`a92096a`)
|
||
- [2026-05-11](changelog/2026-Q2.md): `retrieval-policy.md` 跨 4 个 skill 变体内容同步更新(`e6d1698`)
|
||
- [2026-05-08](changelog/2026-Q2.md): 通过 monkey-patch `ClientSession.call_tool`,把 trace_id 透传到 `rag_retrieve` / `table_rag_retrieve` 的 MCP `_meta`(`1f06450`)
|
||
- [2026-05-06](changelog/2026-Q2.md): support 分支新增 `kfs-answer` skill(`a9227b8`)
|
||
- [2026-05-06](changelog/2026-Q2.md): 修复 Daytona 沙箱增量同步漏掉符号链接的问题——`find -type f` 不覆盖 symlink、`tar.add` 默认不 dereference 导致悬空软链;并统一 dataset 路径为复数 `datasets/`(`3c0fa49`)
|
||
- [2026-04-24](changelog/2026-Q2.md): 非流式响应路径上 `_execute_post_agent_hooks` 改为 `asyncio.create_task` 非阻塞执行;同时临时注释停用 `ToolOutputLengthMiddleware`(`45a9494`)
|
||
- [2026-04-23](changelog/2026-Q2.md): PrePrompt hook 内容改为通过 `{hook_content}` 占位符注入系统提示词模板,不再在 prompt 末尾追加(`51fbf01`)
|
||
- [2026-04-23](changelog/2026-Q2.md): Daytona 沙箱接入——`init_agent` 并行加载 + 返回元组增加 `sandbox` 字段;`skills_sources` 在沙箱模式下变为 `/workspace/skills`,`agent_dir_path` 变为 `/workspace`(`c9e0789`, `8446dab`)
|
||
- [2026-04-22](changelog/2026-Q2.md): `skills/developing/` 下新增 `rag-retrieve-no-citation` 与 `novare-context` 两个开发中 skill(`7a30e52`)
|
||
|
||
- 2026-05-20: `mcp-ui` 和 `data-dashboard` 改为 MCP Apps 标准模式,App HTML 放在 skill 的 `apps/` 目录,由 host 加载后 postMessage 数据
|
||
|
||
- 2026-04-20: 为 `rag-retrieve` 新增 `retrieval-policy-forbidden-self-knowledge.md`,禁止知识问答场景使用模型自身知识补全答案,要求严格基于检索证据作答
|
||
- 2026-04-19: 环境变量 `SKILLS_SUBDIR` 重命名为 `PROJECT_NAME`,用于选择 `skills/{PROJECT_NAME}` 和 `skills/autoload/{PROJECT_NAME}` 目录
|
||
- 2026-04-19: `create_robot_project` 的 autoload 去重和 stale 清理补强,autoload 目录也纳入 managed 清理,避免 `rag-retrieve-only` 场景下旧的 `rag-retrieve` 残留
|
||
- 2026-04-18: `/api/v1/skill/list` 的官方库改为同时读取 `skills/common` 和 `skills/{PROJECT_NAME}`,并按目录顺序去重
|
||
- 2026-04-18: `_extract_skills_to_robot` 改为通过环境变量 `PROJECT_NAME` 选择官方 skills 子目录,默认使用 `skills/common`
|
||
- 2025-02-11: 初始化 skill 功能 memory
|
||
|
||
## Gotchas(开发必读)
|
||
|
||
- ⚠️ MCP App resource REST 读取路径是 `projects/robot/{bot_id}/skills/{server_name}/apps/{resource_name}.html`,前端 bot_id 应由 `ChatView` 从当前 bot 传给 `ChatMessage`,不要在子组件里重新调用 `useBotManager()`
|
||
- ⚠️ `langchain-mcp-adapters` 会丢失 `EmbeddedResource` 的 uri/_meta;MCP App payload 需作为 text JSON 传递给前端识别
|
||
|
||
- ⚠️ 纯 `SKILL.md` 型业务 skill 适合先承载 workflow、输入模板、输出模板;需要稳定文件产出或自动化时再补 `scripts/`
|
||
- ⚠️ 新业务 skill 应复用既有基础能力 skill(如 `baidu-search`、`xlsx`、`docx`、`pdf`、`schedule-job`、`imap-smtp-email`),避免重复定义底层工具能力
|
||
- ⚠️ 新增脚本优先采用 `Python + argparse + JSON stdout`,比 `argv[1] JSON` 更适合自动化链路
|
||
- ⚠️ `auto-daily-summary` 需要特别注意中文分句、action 边界截断、risk 窗口裁剪,否则容易把整句/整段吞进去
|
||
- ⚠️ `competitor-news-intel` 的 payload 校验应按命令拆分(collect/analyze/run),不要共用一套最小校验
|
||
- ⚠️ `competitor-news-intel` 的 `collect/run` 依赖 `BAIDU_API_KEY`;无该环境变量时应返回稳定错误 JSON,不要静默降级
|
||
>>>>>>> Stashed changes
|
||
- ⚠️ `create_robot_project` 的 autoload 去重是“包含匹配”,只要传入的 skill 字符串里包含 autoload skill 名,就不会重复自动加载
|
||
- ⚠️ `_extract_skills_to_robot` 只会从 `skills/{PROJECT_NAME}` 读取官方 skills,默认是 `common`
|
||
- ⚠️ 执行脚本必须使用绝对路径
|
||
- ⚠️ MCP 配置优先级:Skill MCP > 默认 MCP > 用户参数
|
||
- ⚠️ 上传大小限制:50MB(ZIP),解压后最大 500MB
|
||
- ⚠️ 压缩比例检查:最大 100:1(防止 zip 炸弹)
|
||
- ⚠️ 符号链接检查:禁止解压包含符号链接的文件
|
||
- ⚠️ **子 agent 同名静默 last-wins**:`subagent_loader._parse_agent_md` 跨 skill 扫描 `agents/*.md` 时,按 `name` 字段去重,**后扫描到的覆盖先扫描的**,只打 warning 不报错。多 skill 都暴露子 agent 时需自觉错开命名。
|
||
- ⚠️ **`SubAgentMiddleware` 中间件顺序**:必须插在 `CustomFilesystemMiddleware` 之后、`AnthropicPromptCachingMiddleware` 之前——这是匹配 `deepagents.create_deep_agent` 的官方顺序,调整 `create_custom_cli_agent` 中的中间件顺序时不能随意挪动这一段。
|
||
- ⚠️ **Daytona 模式下 skill 路径不同**:`DAYTONA_ENABLED=true` 时 `enable_skills` 的 `skills_sources` 是 `/workspace/skills`(沙箱内),同时 system prompt 的 `agent_dir_path` 是 `/workspace`;写死本地路径的 hook / 脚本需要兼容两种环境。
|
||
- ⚠️ **PostAgent hook 非流式分支已 fire-and-forget**:`routes/chat.py` 用 `asyncio.create_task` 启动 hook,调用方不会等待也不会感知到 hook 的异常——hook 失败只会被自己的 logger 捕获。
|
||
- ⚠️ **MCP `_meta.trace_id` 是全局 monkey-patch 注入**:`agent/mcp_trace_meta.patch_mcp_client_session_trace_meta()` 在 `get_tools_from_mcp()` 入口调用一次后,会把 `mcp.ClientSession.call_tool` 永久包装;仅对工具名在 `{"rag_retrieve", "table_rag_retrieve"}` 集合内的调用注入 `_meta.trace_id`,扩展白名单要直接改 `_TRACE_META_TOOL_NAMES` 常量。
|
||
- ⚠️ **PrePrompt hook 内容位置由模板决定**:自 2026-04-23 起 hook 产出通过 `{hook_content}` 占位符注入 `prompt/system_prompt.md`,不再追加在 prompt 末尾;自定义模板必须包含 `{hook_content}` 占位符否则 hook 内容会丢失。
|
||
- ⚠️ **`init_agent` 返回值已变 3 元素**:Daytona 改造后 `init_agent` 返回 `(agent, checkpointer, sandbox)`;调用方解构必须更新。
|
||
- ⚠️ **skill `category` 默认值**:API 返回的 `SkillItem.category`——official skill fallback 为 `"other"`、user skill fallback 为 `"custom"`;前端做分类视图时需要同时识别这两个 sentinel,不要假设官方/用户 skill 用同一套缺省值。
|
||
- ⚠️ **`category` 字段双入口**:同一 skill 可以同时在 `.claude-plugin/plugin.json` 和 `SKILL.md` frontmatter 写 `category`;`get_skill_metadata` 优先走 `parse_plugin_json`,若 skill 包没有 plugin.json 才回落到 `parse_skill_frontmatter`——两者写不一致时以 plugin.json 为准。
|
||
- ⚠️ **Daytona shell_env 是文件注入而非 process env**:`init_agent` 通过 `cat > $REMOTE_BASH_ENV_PATH` 写入 `export VAR=...` 行,沙箱内必须由 shell(bash)的 `BASH_ENV` 加载才能生效;非 daytona 模式或不走 bash 启动的脚本拿不到这些变量。扩展注入项需直接改 `init_agent` 里的 `_shell_env` 字典。
|
||
|
||
## Skill 目录结构
|
||
|
||
```
|
||
skill-name/
|
||
├── SKILL.md # 核心指令文档(必需)
|
||
├── skill.yaml # 元数据配置(可选)
|
||
├── .claude-plugin/
|
||
│ └── plugin.json # Hook 和 MCP 配置(可选)
|
||
└── scripts/ # 可执行脚本(可选)
|
||
└── script.py
|
||
```
|
||
|
||
## Hook 系统
|
||
|
||
| Hook 类型 | 执行时机 | 用途 |
|
||
|-----------|---------|------|
|
||
| `PrePrompt` | system_prompt 加载时 | 动态注入用户上下文 |
|
||
| `PostAgent` | agent 执行后 | 处理响应结果 |
|
||
| `PreSave` | 保存消息前 | 内容过滤/修改 |
|
||
|
||
## API 接口
|
||
|
||
| 端点 | 方法 | 功能 |
|
||
|------|------|------|
|
||
| `GET /api/v1/skill/list` | - | 返回官方 + 用户 skills |
|
||
| `POST /api/v1/skill/upload` | - | ZIP 上传,解压到用户目录 |
|
||
| `DELETE /api/v1/skill/remove` | - | 删除用户 skill |
|
||
|
||
## 内置 Skills
|
||
|
||
| Skill 名称 | 功能描述 |
|
||
|-----------|---------|
|
||
| `excel-analysis` | Excel 数据分析、透视表、图表 |
|
||
| `managing-scripts` | 管理可复用脚本库 |
|
||
| `rag-retrieve` | RAG 知识库检索 |
|
||
| `jina-ai` | Jina AI Reader/Search |
|
||
| `user-context-loader` | Hook 机制示例 |
|
||
|
||
## plugin.json 格式
|
||
|
||
```json
|
||
{
|
||
"name": "skill-name",
|
||
"description": "描述",
|
||
"hooks": {
|
||
"PrePrompt": [{"type": "command", "command": "python hooks/pre_prompt.py"}],
|
||
"PostAgent": [...],
|
||
"PreSave": [...]
|
||
},
|
||
"mcpServers": {
|
||
"server-name": {
|
||
"command": "...",
|
||
"args": [...]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## Skill 加载优先级
|
||
|
||
1. Skill MCP 配置
|
||
2. 用户传入参数(覆盖已有同名配置)
|
||
|
||
## 安全措施
|
||
|
||
- ZipSlip 防护:检查解压路径
|
||
- 路径遍历防护:验证 `bot_id` 和 `skill_name` 格式
|
||
- 大小限制:上传 50MB,解压后 500MB
|
||
- 压缩比限制:最大 100:1
|
||
|
||
## 设计原则
|
||
|
||
- **渐进式加载**:按需加载,避免一次性读取所有
|
||
- **绝对路径优先**:执行脚本必须使用绝对路径
|
||
- **通用化设计**:脚本应参数化,解决一类问题
|
||
- **安全优先**:完整的上传验证链
|
||
|
||
## 配置项
|
||
|
||
```bash
|
||
SKILLS_DIR=./skills # 官方 skills 目录
|
||
BACKEND_HOST=xxx # RAG API 主机
|
||
MASTERKEY=xxx # 认证密钥
|
||
```
|
||
|
||
## 索引
|
||
|
||
- 设计决策:`decisions/`
|
||
- 变更历史:`changelog/`
|
||
- 相关文档:`docs/`
|