# Skill 功能

> 负责范围：技能包管理服务 - 核心实现
> 最后更新：2026-04-20

## 当前状态

Skill 系统支持两种来源：官方 skills (`./skills/`) 和用户 skills (`projects/uploads/{bot_id}/skills/`)。支持 Hook 系统和 MCP 服务器配置，通过 SKILL.md 或 plugin.json 定义元数据。

## 核心文件

- `routes/skill_manager.py` - Skill 上传/删除/列表 API
- `agent/plugin_hook_loader.py` - Hook 系统实现
- `agent/deep_assistant.py` - `CustomSkillsMiddleware`
- `agent/prompt_loader.py` - PrePrompt hooks + MCP 配置合并
- `skills/` - 官方 skills 目录
- `skills_developing/` - 开发中 skills

## 最近重要事项

- 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（开发必读）

- ⚠️ `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 炸弹）
- ⚠️ 符号链接检查：禁止解压包含符号链接的文件

## 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/`
