主题
Skill 技能系统集成
本文引用的源码文件
本文引用的文件
- agent/src/skill/loader.js
- agent/src/skill/markdown-loader.js
- agent/src/skill/executor.js
- agent/src/skill/template.js
- agent/src/skill/registry.js
- agent/src/server.js
- src/side_panel/skill-selector.js
- src/options/toolbox-skills.js
- src/background/local-agent-client.js
- agent/test/skills/code-review/SKILL.md
- agent/test/skills/hello-world/SKILL.md
目录
引言
本文件系统性梳理 Agent 端的 Skill 技能系统,覆盖 Markdown 技能加载、模板引擎支持、执行框架、注册表管理、HTTP/WebSocket 接口暴露,以及扩展端侧面板与管理页的技能集成。文档同时说明技能的分类(Workflow 与 Agent)、SKILL.md 元数据解析、依赖与资源组织、执行生命周期(加载验证、参数绑定、调度执行、结果处理),并给出全局开关 skillsEnabled 的状态管理与权限控制要点。
项目结构
Skill 系统由 Agent 端与扩展端两部分组成:
- Agent 端负责技能发现、解析、注册、执行与 HTTP API 暴露。
- 扩展端提供技能选择器、运行参数弹窗、结果展示、导入导出等界面能力。
graph TB subgraph "Agent 端" L["loader.js<br/>扫描 JSON/YAML + SKILL.md"] M["markdown-loader.js<br/>解析 frontmatter / 资源 / 安全导入"] T["template.js<br/>变量替换与条件渲染"] E["executor.js<br/>DAG 拓扑执行 / 工具映射 / 超时清理"] R["registry.js<br/>注册表 / 启用状态持久化 / 列表与提示词"] S["server.js<br/>HTTP 路由 / WebSocket 桥接"] end subgraph "扩展端" SP["side_panel/skill-selector.js<br/>技能下拉选择 / 注入上下文"] OP["options/toolbox-skills.js<br/>管理页增删改查 / 运行 / 导入"] LC["background/local-agent-client.js<br/>本地代理客户端封装"] end L --> R M --> R T --> E E --> R R --> S SP --> LC OP --> LC LC --> S
图表来源
- agent/src/skill/loader.js#L173-L209
- agent/src/skill/markdown-loader.js#L181-L250
- agent/src/skill/executor.js#L179-L308
- agent/src/skill/template.js#L10-L96
- agent/src/skill/registry.js#L134-L189
- agent/src/server.js#L38-L54
- src/side_panel/skill-selector.js#L78-L157
- src/options/toolbox-skills.js#L17-L25
- src/background/local-agent-client.js#L850-L989
章节来源
- agent/src/skill/loader.js#L173-L209
- agent/src/skill/markdown-loader.js#L181-L250
- agent/src/skill/executor.js#L179-L308
- agent/src/skill/template.js#L10-L96
- agent/src/skill/registry.js#L134-L189
- agent/src/server.js#L38-L54
- src/side_panel/skill-selector.js#L78-L157
- src/options/toolbox-skills.js#L17-L25
- src/background/local-agent-client.js#L850-L989
核心组件
- 加载器 loader.js:扫描 ~/.ai-helper-agent/skills 目录,加载 Workflow(JSON/YAML)与 Agent(SKILL.md)两类技能,统一输出到注册表。
- Markdown 加载器 markdown-loader.js:解析 SKILL.md 的 YAML frontmatter 与正文,扫描 scripts/templates/assets/references 等资源,提供 ZIP/URL 安全导入。
- 模板引擎 template.js:支持 {{var}} 变量替换与 {{#if var}}...{{/if}} 条件渲染,用于步骤参数与条件判断。
- 执行器 executor.js:将 Skill 步骤构建为 DAG,按拓扑排序并行执行;内置 agent_file/agent_exec/agent_search 等工具映射与安全校验;维护执行上下文、超时与清理。
- 注册表 registry.js:内存 Map 管理所有已加载技能,提供列表、查询、执行、导入、删除、启用/停用切换、Agent 提示词生成等能力;持久化用户停用与内置技能状态。
- 服务器 server.js:暴露 /api/skill/* 路由,桥接扩展端请求到注册表与执行器。
- 扩展端 side_panel/skill-selector.js:技能下拉选择、多选指示器、注入系统提示词上下文。
- 扩展端 options/toolbox-skills.js:管理页技能列表、参数弹窗、运行结果展示、导入导出。
- 扩展端 background/local-agent-client.js:本地代理客户端封装,统一调用 Agent 技能相关 API。
章节来源
- agent/src/skill/loader.js#L126-L209
- agent/src/skill/markdown-loader.js#L40-L217
- agent/src/skill/template.js#L10-L96
- agent/src/skill/executor.js#L68-L173
- agent/src/skill/registry.js#L191-L302
- agent/src/server.js#L38-L54
- src/side_panel/skill-selector.js#L78-L157
- src/options/toolbox-skills.js#L17-L25
- src/background/local-agent-client.js#L850-L989
架构总览
Skill 系统采用“加载-注册-执行”三段式架构,并通过 HTTP API 向扩展端暴露能力。
sequenceDiagram
participant UI as "扩展端界面"
participant BG as "Background 客户端"
participant AG as "Agent 服务器"
participant REG as "注册表 registry.js"
participant EXE as "执行器 executor.js"
participant LD as "加载器 loader.js"
participant MD as "Markdown 加载器 markdown-loader.js"
UI->>BG : 打开管理页/选择技能
BG->>AG : GET /api/skill/list
AG->>REG : getSkillList()
REG->>LD : loadAllSkills()
LD->>MD : loadAllMarkdownSkills()
MD-->>LD : Agent 技能数组
LD-->>REG : 合并 Workflow + Agent 列表
REG-->>AG : {success, skills}
AG-->>BG : 返回技能列表
BG-->>UI : 渲染技能卡片/下拉框
UI->>BG : 运行 Workflow 技能
BG->>AG : POST /api/skill/run
AG->>REG : runSkill(name, params)
REG->>EXE : executeSkill(skill, params)
EXE-->>AG : {success, execId, results}
AG-->>BG : 返回执行结果
BG-->>UI : 展示步骤结果
图表来源
- agent/src/skill/registry.js#L191-L256
- agent/src/skill/loader.js#L173-L209
- agent/src/skill/markdown-loader.js#L224-L250
- agent/src/skill/executor.js#L317-L401
- agent/src/server.js#L38-L54
- src/background/local-agent-client.js#L850-L989
详细组件分析
技能加载与分类
- Workflow 技能:以 JSON/YAML 文件形式存放于 skills 根目录,包含 name/description/version/steps/parameters 等字段,经 validateWorkflowSkill 校验后标记 type=workflow。
- Agent 技能:每个子目录一个 SKILL.md,frontmatter 定义 name/description/version/enabled 等,正文为 Prompt 指令,附带 resources 资源清单。
flowchart TD
Start(["启动加载"]) --> ScanDir["扫描 skills 根目录"]
ScanDir --> ForFile{"是否为 .json/.yaml/.yml?"}
ForFile --> |是| LoadWF["解析 Workflow 定义并校验"]
ForFile --> |否| NextEntry["继续遍历"]
LoadWF --> MarkWF["标记 type=workflow"]
MarkWF --> Merge["合并到全部技能集合"]
NextEntry --> ScanSubdirs["扫描子目录"]
ScanSubdirs --> HasMd{"是否存在 SKILL.md?"}
HasMd --> |是| ParseFM["解析 frontmatter 与正文"]
ParseFM --> CollectRes["扫描 scripts/templates/assets/references"]
CollectRes --> MarkAgent["标记 type=agent"]
MarkAgent --> Merge
HasMd --> |否| NextEntry
Merge --> End(["完成"])
图表来源
章节来源
- agent/src/skill/loader.js#L40-L65
- agent/src/skill/loader.js#L130-L167
- agent/src/skill/loader.js#L173-L209
- agent/src/skill/markdown-loader.js#L40-L94
- agent/src/skill/markdown-loader.js#L181-L217
模板引擎与参数绑定
- 模板引擎支持变量替换与条件渲染,用于步骤参数与 when 条件。
- 执行时先合并默认参数与用户参数,再对每个步骤的参数进行模板渲染,并将前序步骤结果注入变量上下文 step.{id}、step.{id}.success、step.{id}.content。
flowchart TD
A["接收 skill.parameters 与用户 params"] --> B["合并默认值与用户值"]
B --> C["遍历步骤参数"]
C --> D{"值为字符串?"}
D --> |是| E["render(value, variables)"]
D --> |否| F["保持原值"]
E --> G["写入 renderedParams"]
F --> G
G --> H["执行工具调用"]
H --> I["保存 step.{id} 结果到 variables"]
图表来源
章节来源
执行框架与 DAG 调度
- 将 steps 构建为有向无环图,计算入度,初始就绪队列入队 inDegree=0 的步骤。
- 每批并行执行 ready 队列中的步骤,完成后更新 completed 集合,重新扫描依赖满足的新就绪步骤。
- 支持 when 条件跳过步骤;失败步骤记录 error;整体支持部分成功 partial 返回。
- 执行上下文 activeExecutions 维护 execId → 执行记录,支持超时与定期清理。
flowchart TD
S["开始执行"] --> BuildDag["构建 DAG 与 inDegree"]
BuildDag --> InitReady["收集 inDegree=0 的步骤"]
InitReady --> Loop{"ready 是否为空?"}
Loop --> |否| Batch["并行执行当前批次"]
Batch --> UpdateVars["渲染参数并执行工具"]
UpdateVars --> SaveResults["保存 step 结果到 variables"]
SaveResults --> MarkDone["标记 completed"]
MarkDone --> NextBatch["查找新的就绪步骤"]
NextBatch --> Loop
Loop --> |是| Done["返回结果集"]
图表来源
章节来源
工具映射与安全校验
- 内置工具映射:
- agent_file/agent_read_file/agent_write_file/agent_list_dir/agent_delete_file/agent_download_file:通过 checkPath 校验路径,实现读/写/列/删/下载。
- agent_exec:通过 checkCommand 校验命令级别,灰名单直接拒绝,白名单走统一命令执行器。
- agent_search/agent_search_files/agent_search_content:调用 searchFiles/searchContent。
- 安全策略:
- 路径检查与命令级别检查在 executor 中强制执行。
- URL/ZIP 导入在 markdown-loader 中进行主机白名单、DNS 重绑定防护、大小限制与路径穿越防护。
章节来源
- agent/src/skill/executor.js#L68-L173
- agent/src/skill/markdown-loader.js#L314-L384
- agent/src/skill/markdown-loader.js#L484-L558
- agent/src/skill/markdown-loader.js#L566-L652
注册表与全局启用状态
- 初始化流程:种子写入内置 skill-creator → 加载文件系统技能 → 加载代码内置技能(不覆盖同名)→ 标记内置属性 → 恢复内置启用状态 → 恢复用户停用状态。
- 列表与提示词:getSkillList 返回精简信息;getAgentSkillPrompts 生成注入 AI 的轻量描述;getAgentSkillPrompt 按需加载完整 Prompt。
- 启用/停用:toggleSkill 优先持久化 disabled_skills.json,内置技能额外写入 builtin_skills_state.json,并尝试回写源文件(best-effort)。
classDiagram
class Registry {
+initializeSkillRegistry() number
+getSkillList(type) Object
+getSkill(name) Object
+runSkill(name, params, onStepUpdate) Promise
+getAgentSkillPrompts() string
+getAgentSkillPrompt(name) Object
+importSkill(skillDef) Object
+removeSkill(name) Object
+toggleSkill(name) Object
+reloadSkills() number
+getSkillsDir() string
}
class Loader {
+loadAllSkills() Object[]
+saveSkillFile(skill) Object
+deleteSkillFile(name, type) Object
+seedSkillCreator() boolean
}
class MarkdownLoader {
+parseFrontmatter(content) Object
+scanResources(skillDir) Object[]
+loadMarkdownSkill(skillDir) Object
+loadAllMarkdownSkills(skillsDir) Object[]
+saveMarkdownSkill(skillsDir, skillDef) Object
+deleteMarkdownSkillDir(skillsDir, name) Object
+importMarkdownSkillFromZip(skillsDir, zipBuffer, skillName) Promise
+importMarkdownSkillFromUrl(skillsDir, url) Promise
}
class Executor {
+executeSkill(skill, params, onStepUpdate) Promise
+getSkillExecutionStatus(execId) Object
}
Registry --> Loader : "加载技能"
Registry --> MarkdownLoader : "加载 Agent 技能"
Registry --> Executor : "执行 Workflow 技能"
图表来源
- agent/src/skill/registry.js#L134-L189
- agent/src/skill/registry.js#L191-L433
- agent/src/skill/loader.js#L173-L327
- agent/src/skill/markdown-loader.js#L181-L652
- agent/src/skill/executor.js#L317-L419
章节来源
技能面板集成与结果输出
- 侧面板技能选择器:
- 获取技能列表并缓存,过滤 enabled=false 显示未启用角标。
- 多选支持,选中后渲染 chip 指示器,可单独移除。
- 注入上下文:Agent 技能直接加载完整 Prompt 拼接至用户消息;Workflow 技能提示使用 agent_skill(action=run) 执行,并附带参数定义。
- 管理页:
- 列表区分 Workflow/Agent,支持搜索与状态筛选。
- Workflow 支持参数弹窗、运行按钮、启用/停用、删除。
- Agent 支持编辑/查看 SKILL.md、启用/停用、删除。
- 导入支持 JSON、Markdown、ZIP、URL,URL 导入触发安全校验。
- 运行结果弹窗展示步骤状态、输出截断与统计摘要。
章节来源
- src/side_panel/skill-selector.js#L78-L157
- src/side_panel/skill-selector.js#L163-L219
- src/side_panel/skill-selector.js#L260-L343
- src/side_panel/skill-selector.js#L484-L539
- src/options/toolbox-skills.js#L30-L172
- src/options/toolbox-skills.js#L244-L420
- src/options/toolbox-skills.js#L548-L758
全局开关 skillsEnabled 与权限控制
- 扩展端多处读取 chrome.storage.local.skillsEnabled:
- 侧面板 shouldShowSkillsTab 在未连接或关闭时隐藏技能 Tab。
- 工具执行器 tool-executor 在工具选择阶段根据 skillsEnabled 决定是否允许 agent_skill 工具。
- 选项页 toolbox-config 加载与设置全局开关。
- Agent 端 toggleSkill 仅控制单个技能的启用状态,不影响全局开关;全局开关由扩展端控制,Agent 端不直接读写该键。
章节来源
- src/side_panel/skill-selector.js#L102-L123
- src/background/tool-executor.js#L1206-L1228
- src/background/tool-executor.js#L1324-L1326
- src/options/toolbox-config.js#L275-L298
- agent/src/skill/registry.js#L381-L433
依赖关系分析
- 模块耦合:
- registry.js 依赖 loader.js 与 markdown-loader.js 完成技能发现,依赖 executor.js 执行 Workflow 技能。
- executor.js 依赖 template.js 进行参数渲染,依赖 security.js 进行路径与命令安全检查。
- server.js 作为 HTTP 入口,集中引入 registry 与 loader/executor 的语言设置函数。
- 外部依赖:
- fs/fs/promises/path/os/crypto/zlib/dns/http/https 等 Node 标准库。
- archiver 用于 ZIP 打包(server.js)。
- 循环依赖规避:
- 侧面板 prompt-manager 与 skill-selector 存在反向依赖,通过 hoisted 函数声明避免运行时错误。
graph LR Server["server.js"] --> Registry["registry.js"] Registry --> Loader["loader.js"] Registry --> Markdown["markdown-loader.js"] Registry --> Executor["executor.js"] Executor --> Template["template.js"] Executor --> Security["security.js"] SidePanel["skill-selector.js"] --> LocalClient["local-agent-client.js"] Options["toolbox-skills.js"] --> LocalClient LocalClient --> Server
图表来源
- agent/src/server.js#L38-L54
- agent/src/skill/registry.js#L1-L8
- agent/src/skill/executor.js#L1-L7
- src/side_panel/skill-selector.js#L1-L8
- src/options/toolbox-skills.js#L1-L7
- src/background/local-agent-client.js#L850-L989
章节来源
- agent/src/server.js#L38-L54
- agent/src/skill/registry.js#L1-L8
- agent/src/skill/executor.js#L1-L7
- src/side_panel/skill-selector.js#L1-L8
- src/options/toolbox-skills.js#L1-L7
- src/background/local-agent-client.js#L850-L989
性能与可扩展性
- 执行并发:executor.js 对同一批 ready 步骤使用 Promise.all 并行执行,提升吞吐。
- 资源清理:activeExecutions 定时清理已完成/错误记录,防止内存泄漏。
- 列表缓存:侧面板与本地客户端对技能列表与 Agent 名称集合进行短期缓存,减少重复请求。
- 可扩展点:
- 新增内置工具映射可在 executor.js 的 executeToolCall 中添加分支。
- 新增导入方式可在 markdown-loader.js 中扩展 URL/ZIP 校验与解压逻辑。
- 注册表可新增更多持久化策略或审计日志。
[本节为通用指导,无需具体文件引用]
故障排查指南
- 技能未显示:
- 检查扩展端 skillsEnabled 是否被关闭。
- 确认 Agent 已连接且 /api/skill/list 返回非空。
- 执行失败:
- 查看 executor.js 的工具映射与安全校验(checkPath/checkCommand)。
- 检查步骤 when 条件与参数模板是否正确。
- 导入失败:
- URL 导入需公网可达且非内网地址,注意 DNS 解析与重定向限制。
- ZIP 导入需包含 SKILL.md,名称需符合安全规则。
- 状态不同步:
- toggleSkill 会优先写入 disabled_skills.json,若源文件写入失败,状态仍保存在该文件中。
章节来源
- agent/src/skill/executor.js#L68-L173
- agent/src/skill/markdown-loader.js#L566-L652
- agent/src/skill/registry.js#L381-L433
结论
Skill 系统通过清晰的加载-注册-执行分层,结合模板引擎与 DAG 调度,实现了 Workflow 与 Agent 两类技能的统一管理。扩展端提供完整的可视化操作体验,Agent 端保证安全与性能。全局开关与单技能启用状态分离,便于灵活控制。建议后续持续完善工具映射、导入校验与审计日志,以提升系统健壮性与可观测性。
[本节为总结性内容,无需具体文件引用]
附录:自定义技能编写示例
Workflow 技能(JSON)
- 基本结构:name、description、version、enabled、parameters、steps。
- parameters 支持 JSON Schema 风格 properties 与 required。
- steps 支持 id、tool、args/params、dependsOn、when。
参考路径:
Agent 技能(SKILL.md)
- frontmatter 至少包含 name、description、version,可选 enabled。
- 正文为 Prompt 指令,描述何时使用、执行步骤、输出格式。
- 可附带 scripts/templates/assets/references 资源目录。
参考示例:
章节来源