完善 skill_manager 的技能维护能力

This commit is contained in:
2026-06-05 13:03:39 +08:00
parent fc0e76439d
commit ad31956f53
9 changed files with 392 additions and 41 deletions
+5 -1
View File
@@ -49,7 +49,11 @@ Skills 树是**动态生长的**——工作流不是预置的,而是从实际
- 可被未来同类任务复用
- 非一次性/临时/猜测
**写入位置**`skills/workflow/<name>/`,包含 SKILL.md(步骤说明)和 scripts/*.py(分析脚本)。
**写入位置**`skills/workflow/<name>/`,包含 SKILL.md(步骤说明)、references/*.md(参考材料)和 scripts/*.py(分析脚本)。
**工具动作**`write_skill / remove_skill` 维护主 SKILL.md`append_pattern / remove_pattern` 维护 `## Learned Patterns``write_reference / remove_reference` 维护 references/*.md`write_script / remove_script` 维护 scripts/*.py。`write_skill` 可创建或覆盖完整 SKILL.md。
目录入口也通过 `skill_manager` 维护:更新 `skills/workflow/SKILL.md` 时使用 `write_skill(skill_path="workflow", ...)`,更新根入口 `skills/SKILL.md` 时使用 `write_skill(skill_path="__root__", ...)`
**脚本编写要求——优先用 pipe 串联**
+4 -1
View File
@@ -39,9 +39,12 @@ Skills 树是动态生长的——没有预置的 workflow,所有工作流从
1. **查已有** — 先检查 `skills/workflow/` 下是否有匹配的 workflow skill
2. **从零拼装** — 无匹配时,Agent 自行组合 `tjwater_cli` 命令 + Python 脚本完成
3. **沉淀复用** — 任务完成后复盘,如果流程稳定可复用,用 `skill_manager` 保存到 `skills/workflow/<name>/`(含 SKILL.md + scripts/*.py
3. **沉淀复用** — 任务完成后复盘,如果流程稳定可复用,用 `skill_manager` 保存到 `skills/workflow/<name>/`(含 SKILL.md、references/*.md、scripts/*.py
4. **原子操作** — 简单查询直接调用 `tjwater_cli`,不走 skill
`skill_manager` 可维护主 SKILL.md、`## Learned Patterns`、references/*.md 和 scripts/*.py;完整写入 SKILL.md 时需包含 `name``description` frontmatter。
目录入口也通过 `skill_manager` 维护:`skill_path="workflow"` 对应 `skills/workflow/SKILL.md``skill_path="__root__"` 对应 `skills/SKILL.md`
## Workflow 脚本编写规范
**原则:尽量用 pipe 串联 CLI 调用,减少 tool calling 次数。**
+3 -2
View File
@@ -50,9 +50,10 @@ SSE 事件:
- 所有学习类工具必须带 `reason`
- `memory_manager``add / list / replace / remove`
- `skill_manager``list / append_pattern / remove_pattern / write_reference / remove_reference / write_script / remove_script`
- `skill_manager``list / write_skill / remove_skill / append_pattern / remove_pattern / write_reference / remove_reference / write_script / remove_script`
- `session_search`:只搜索当前用户 + 当前项目作用域
- `skill_manager` 写入落到:`## Learned Patterns``references/*.md``scripts/*.py`
- `skill_manager` 写入落到:`SKILL.md``## Learned Patterns``references/*.md``scripts/*.py`
- 目录入口同样走 `skill_manager``skill_path="workflow"` 维护 `skills/workflow/SKILL.md``skill_path="__root__"` 维护 `skills/SKILL.md`
## 6) 用户上下文注入
+2 -1
View File
@@ -26,4 +26,5 @@ description: 供水管网分析工作流目录,描述可复用的分析流程
- 每个工作流子目录包含独立的 `SKILL.md`,描述目的、步骤、参数与判定阈值
- 所有数据获取均通过 `tjwater-cli` 命令族(见 `tjwater-cli` skill
- 流程中若涉及仿真,遵循"先查结果后触发"原则
- 新工作流由 `skill_manager` 在线追加,若子目录不存在则无对应工作流
- 新工作流由 `skill_manager` 在线写入或更新,若子目录不存在则无对应工作流
- 新增工作流后,如需更新本目录索引,使用 `skill_manager.write_skill(skill_path="workflow", ...)`
+31 -23
View File
@@ -3,17 +3,19 @@ import { tool } from "@opencode-ai/plugin";
import { SkillStore } from "../../src/skills/store.js";
import { SessionRuntimeContextStore } from "../../src/sessions/runtimeContextStore.js";
const toolContextStore = new SessionRuntimeContextStore();
const initializePromise = toolContextStore.initialize();
const skillStore = new SkillStore();
export default tool({
export const createSkillManagerTool = (
skillStore = new SkillStore(),
toolContextStore = new SessionRuntimeContextStore(),
initializePromise: Promise<unknown> = toolContextStore.initialize(),
) => tool({
description:
"维护已验证、可复用、非敏感的 workflow 或方法模式。支持 list、append_pattern、remove_pattern、write_reference、remove_reference、write_script、remove_script。",
"维护已验证、可复用、非敏感的 workflow 或方法模式。支持 list、write_skill、remove_skill、append_pattern、remove_pattern、write_reference、remove_reference、write_script、remove_script。",
args: {
action: tool.schema
.enum([
"list",
"write_skill",
"remove_skill",
"append_pattern",
"remove_pattern",
"write_reference",
@@ -30,7 +32,7 @@ export default tool({
skill_path: tool.schema
.string()
.describe(
"Target skill directory path relative to .opencode/skills.",
"Target skill directory path relative to .opencode/skills. Use 'workflow' for the workflow index, or '__root__' for the root skills index.",
),
pattern: tool.schema
.string()
@@ -47,7 +49,7 @@ export default tool({
content: tool.schema
.string()
.optional()
.describe("Asset content used by write_reference or write_script."),
.describe("Content used by write_skill, write_reference, or write_script."),
},
async execute(args, context) {
await initializePromise;
@@ -84,25 +86,29 @@ export default tool({
}
const result =
args.action === "append_pattern"
? await skillStore.appendPattern(args.skill_path, args.pattern ?? "")
: args.action === "remove_pattern"
? await skillStore.removePattern(args.skill_path, args.target_id ?? "")
: args.action === "write_reference"
? await skillStore.writeReference(
args.skill_path,
args.file_path ?? "",
args.content ?? "",
)
: args.action === "remove_reference"
? await skillStore.removeReference(args.skill_path, args.file_path ?? "")
: args.action === "write_script"
? await skillStore.writeScript(
args.action === "write_skill"
? await skillStore.writeSkill(args.skill_path, args.content ?? "")
: args.action === "remove_skill"
? await skillStore.removeSkill(args.skill_path)
: args.action === "append_pattern"
? await skillStore.appendPattern(args.skill_path, args.pattern ?? "")
: args.action === "remove_pattern"
? await skillStore.removePattern(args.skill_path, args.target_id ?? "")
: args.action === "write_reference"
? await skillStore.writeReference(
args.skill_path,
args.file_path ?? "",
args.content ?? "",
)
: await skillStore.removeScript(args.skill_path, args.file_path ?? "");
: args.action === "remove_reference"
? await skillStore.removeReference(args.skill_path, args.file_path ?? "")
: args.action === "write_script"
? await skillStore.writeScript(
args.skill_path,
args.file_path ?? "",
args.content ?? "",
)
: await skillStore.removeScript(args.skill_path, args.file_path ?? "");
return JSON.stringify({
ok: true,
@@ -113,3 +119,5 @@ export default tool({
});
},
});
export default createSkillManagerTool();