@yottameta/yotta-skills 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +16 -6
- package/README.zh-CN.md +18 -7
- package/SKILL.md +42 -8
- package/assets/banner.png +0 -0
- package/bin/yotta-skills.js +95 -7
- package/lib/route.js +160 -0
- package/lib/skills-scan.js +1 -1
- package/package.json +2 -2
- package/references/install-flow.md +10 -0
- package/references/orchestration.md +16 -0
- package/references/tutorial.md +25 -0
- package/scripts/yotta-skills-mcp.py +27 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## v0.4.0 (2026-08-31)
|
|
4
|
+
|
|
5
|
+
阶段 C(O1 静态编排 playbook + 路由指引):从「知道装了什么」升级为「给出该用哪几个、什么顺序」。
|
|
6
|
+
|
|
7
|
+
- 新增静态编排 playbook(7 个场景组合):输出呈现、长生命周期、交付质量门、装前安全门、造技能发版、安全事件响应、入口安装。
|
|
8
|
+
- 新增 CLI `--route "<需求摘要>"`:先更新本地注册表,再输出候选组合、调用顺序、技能角色、置信度、命中依据、已装/缺失状态、安装命令与应用模式提醒;支持 `--json`。
|
|
9
|
+
- 新增 MCP `route_request` 工具,与 CLI 复用同一套路由核心;MCP 工具扩展为四个。
|
|
10
|
+
- 缺失技能只建议安装,不自动安装;安装命令需用户确认并先执行装前安全扫描。应用模式默认显式调用,切换为按场景自动调用需用户确认。
|
|
11
|
+
- 文档:SKILL.md / README 中英 / orchestration.md / tutorial.md 同步「编排路由」层与边界;banner 同步升级为编排层定位。
|
|
12
|
+
- 测试:新增路由核心(playbook 完整性 / 命中顺序 / 缺失建议 / 无匹配兜底 / 应用模式)、CLI JSON 与文本输出、MCP e2e 用例。
|
|
13
|
+
- 版本升至 0.4.0。
|
|
14
|
+
|
|
15
|
+
## v0.3.0 (2026-08-31)
|
|
16
|
+
|
|
17
|
+
阶段 B(D2 re-index 自动钩子):新装技能自动被发现。
|
|
18
|
+
|
|
19
|
+
- 新增 CLI `--reindex`:重扫所有技能目录并增量合并注册表,变化聚焦输出(文本 / `--json` 机器可读),供会话开工与钩子调用;`--rescan` 为同义别名。
|
|
20
|
+
- 装技能后自动 re-index:`install` / `update` 完成后自动重扫注册表,把本次落位结果反映进 `~/.yottaskills/registry.json`(新增 / 更新 / 消失随输出列出);`--no-reindex` 可关闭。
|
|
21
|
+
- 会话开工 re-scan:SKILL.md「使用须知」护栏补「会话开工先跑一次 `yotta-skills --reindex`」;注册表 `note` 口径同步 `--inventory / --reindex`。
|
|
22
|
+
- MCP `reindex` 工具改走 `--reindex --json`(同一套扫描核心);CLI 等价命令注明。
|
|
23
|
+
- 文档:SKILL.md / README 中英 / references/install-flow.md / tutorial.md 同步 re-index 用法。
|
|
24
|
+
- 测试:新增 `--reindex`(含幂等)与装后自动 re-index(含 `--no-reindex` 关闭)用例;全量用例全绿。
|
|
25
|
+
- 版本升至 0.3.0。
|
|
26
|
+
|
|
3
27
|
## v0.2.1 (2026-08-31)
|
|
4
28
|
|
|
5
29
|
MCP 配置说明补全(按需加载口径)。
|
package/README.md
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
<h1 align="center">yotta-skills · 元阁 (YuanGe)</h1>
|
|
8
8
|
|
|
9
|
-
<p align="center">YottaMeta's skill-family <b>orchestration
|
|
10
|
-
<p align="center">List the family, install everything, incrementally update, preview with <code>--dry-run</code>, pin exact versions
|
|
9
|
+
<p align="center">YottaMeta's skill-family <b>orchestration router, inventory, and one-command installer</b>: route which skills to combine for a task, then one <code>npx</code> line installs the published <code>yotta-*</code> skills (currently <b>22</b>) into any agent or directory.</p>
|
|
10
|
+
<p align="center">List the family, route a task, install everything, incrementally update, preview with <code>--dry-run</code>, pin exact versions - idempotent and zero-dependency (Node.js 18+), pure npm ecosystem.</p>
|
|
11
11
|
<p align="center">This package contains <b>no skill bodies</b> — only a manifest, a downloader, a placer and a summary. Each skill still comes from its own npm package.</p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
@@ -25,12 +25,13 @@ Installing the whole YottaMeta family used to mean running <code>npx</code> for
|
|
|
25
25
|
|
|
26
26
|
元阁 is also the **family orchestration planner**: given a task, check the orchestration table first — which skills to combine, in what order, and why — then install exactly those. The decision table ships in the package as <code>references/orchestration.md</code> and is summarized in <code>SKILL.md</code>.
|
|
27
27
|
|
|
28
|
-
- **List**
|
|
28
|
+
- **List** - see the whole family: slug, Chinese name, package, version and a one-line description.
|
|
29
|
+
- **Orchestration routing** - <code>--route</code> turns a task summary into a candidate combination, call order, per-skill roles, confidence, evidence, installed/missing status, and an install command; it only suggests installation and never installs automatically.
|
|
29
30
|
- **Install** — install everything (or a subset) into an agent's default user-level directory or any directory.
|
|
30
31
|
- **Update** — incremental update: add missing skills, upgrade version-skewed ones.
|
|
31
32
|
- **Idempotent** — a skill already at the manifest version is skipped; re-running is safe.
|
|
32
33
|
- **Pre-install summary** — if yotta-verify (元信) is available, each skill is scanned first; the verdict is informational only.
|
|
33
|
-
- **Inventory**
|
|
34
|
+
- **Inventory / re-index** - scan the skill directories on this machine and keep a local registry (<code>~/.yottaskills/registry.json</code>); self-contained, no other skills required. Newly installed skills are discovered automatically: <code>install</code> / <code>update</code> re-index the registry afterwards, and <code>--reindex</code> re-scans on demand (e.g. at session start). An optional <code>yotta-skills</code> MCP (on-demand, not resident) exposes <code>list_installed_skills</code> / <code>describe_skill</code> / <code>reindex</code> / <code>route_request</code>; see <code>SKILL.md</code> for the config.
|
|
34
35
|
|
|
35
36
|
Boundaries: it only downloads, places and summarizes — it does **not** develop skill content, does **not** bundle any skill body, and does **not** use <code>-g</code> global installs. It never writes outside the target you specify.
|
|
36
37
|
|
|
@@ -55,8 +56,14 @@ npx -y @yottameta/yotta-skills update --agent codex
|
|
|
55
56
|
# Preview what would be installed (no network, no changes)
|
|
56
57
|
npx -y @yottameta/yotta-skills --dry-run
|
|
57
58
|
|
|
59
|
+
# Route a task to a combination, call order, and missing-skill install suggestion
|
|
60
|
+
npx -y @yottameta/yotta-skills --route "Review this code carefully before release"
|
|
61
|
+
|
|
58
62
|
# Inventory installed skills on this machine (self-contained scan, no other skills needed)
|
|
59
63
|
npx -y @yottameta/yotta-skills --inventory
|
|
64
|
+
|
|
65
|
+
# Re-index the registry (session start / after installing skills; incremental)
|
|
66
|
+
npx -y @yottameta/yotta-skills --reindex
|
|
60
67
|
```
|
|
61
68
|
|
|
62
69
|
Requirements: Node.js 18+, npm, and system <code>tar</code> (built into Windows 10+ / macOS / most Linux distributions).
|
|
@@ -71,6 +78,9 @@ Requirements: Node.js 18+, npm, and system <code>tar</code> (built into Windows
|
|
|
71
78
|
| `install <skill>... [--agent <name> \| --dir <path>]` | Install only the given skills |
|
|
72
79
|
| `update [--agent <name> \| --dir <path>]` | Incremental update: add missing, upgrade version-skewed |
|
|
73
80
|
| `--inventory` | Inventory installed skills: scan skill directories and update the local registry (self-contained); `--json` for JSON, `--project` adds project-level dirs |
|
|
81
|
+
| `--reindex` | Re-index the registry: re-scan skill directories and merge changes incrementally (session start / after installing skills; `--rescan` is a synonym); `--json` for JSON |
|
|
82
|
+
| `--route <task-summary>` | Static orchestration routing: return a combination, call order, per-skill roles, confidence, evidence, installed/missing status, and an install suggestion; `--json` for JSON, `--project` adds project-level dirs |
|
|
83
|
+
| `--no-reindex` | Do not re-index the registry automatically after `install` / `update` |
|
|
74
84
|
| `--dry-run` | Preview the install / update list; no network, no changes |
|
|
75
85
|
| `--pin` | Lock the exact manifest versions (default: range, latest patch of the same major) |
|
|
76
86
|
| `--force` | Reinstall even when already at the latest version |
|
|
@@ -141,12 +151,12 @@ The full 22-skill manifest with Chinese names, package names, versions and descr
|
|
|
141
151
|
|
|
142
152
|
## How it works
|
|
143
153
|
|
|
144
|
-
For each skill in the manifest: `npm pack <pkg>@<spec>` into a temp directory → `tar -xzf` → optional yotta-verify pre-install summary → replace `<dest>/<slug>` → summary report. Details: `references/install-flow.md`; beginner tutorial (Chinese): `references/tutorial.md`.
|
|
154
|
+
For each skill in the manifest: `npm pack <pkg>@<spec>` into a temp directory → `tar -xzf` → optional yotta-verify pre-install summary → replace `<dest>/<slug>` → summary report. After `install` / `update` finishes, the local skill registry is re-indexed automatically so newly installed skills show up in `--inventory` / `--reindex` (disable with `--no-reindex`). Details: `references/install-flow.md`; beginner tutorial (Chinese): `references/tutorial.md`.
|
|
145
155
|
|
|
146
156
|
## Development & validation
|
|
147
157
|
|
|
148
158
|
```bash
|
|
149
|
-
# Run the test suite
|
|
159
|
+
# Run the test suite from the skill directory
|
|
150
160
|
npm test
|
|
151
161
|
```
|
|
152
162
|
|
package/README.zh-CN.md
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
<h1 align="center">yotta-skills · 元阁 (YuanGe)</h1>
|
|
8
8
|
|
|
9
|
-
<p align="center">YottaMeta 的<b
|
|
9
|
+
<p align="center">YottaMeta 的<b>技能生态编排路由 + 全家一键安装器 + 技能盘点</b>:先按需求路由该组合哪几个技能,再一条 <code>npx</code> 命令把已发布的全部
|
|
10
10
|
<code>yotta-*</code> 技能(当前 <b>22</b> 个)装进指定智能体或目录。</p>
|
|
11
|
-
<p align="center"
|
|
11
|
+
<p align="center">看清单、路由组合、装全家、增量更新、<code>--dry-run</code> 预览、<code>--pin</code> 锁版本--
|
|
12
12
|
幂等、零依赖(Node.js 18+)、纯 npm 生态。</p>
|
|
13
13
|
<p align="center">本包<b>不含任何技能本体</b>——只做「清单 + 下载 + 落位 + 汇总」;每个技能仍走各自 npm 包。</p>
|
|
14
14
|
|
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
|
|
29
29
|
元阁也是全家的**编排策划层**:接到需求先查「编排策划」组合表——该组合哪几个技能、按什么顺序、各自强在哪——再按需安装恰好那几个。决策表随包提供(<code>references/orchestration.md</code>),<code>SKILL.md</code> 中有摘要。
|
|
30
30
|
|
|
31
|
-
-
|
|
31
|
+
- **看清单**--全家技能一览:slug / 中文名 / 包名 / 版本 / 一句话说明。
|
|
32
|
+
- **编排路由**--`--route` 按需求摘要输出候选组合、调用顺序、技能角色、置信度、依据、已装/缺失状态与安装命令;只建议安装,不自动安装。
|
|
32
33
|
- **安装**——装全家(或指定技能)到智能体默认用户级目录或任意目录。
|
|
33
34
|
- **更新**——增量更新:补齐缺失技能、升级版本不一致的技能。
|
|
34
35
|
- **幂等**——已在清单版本的技能跳过;重复运行安全。
|
|
35
36
|
- **装前摘要**——若装了元信(yotta-verify),先对每个待装技能做一次装前扫描;verdict 仅提示、不拦截。
|
|
36
|
-
-
|
|
37
|
+
- **盘点 / re-index**--扫描本机各智能体技能目录,维护本地注册表(<code>~/.yottaskills/registry.json</code>);自包含,不需要任何其他技能。新装技能自动被发现:<code>install</code> / <code>update</code> 完成后自动重扫注册表,<code>--reindex</code> 可随时手动重扫(如会话开工)。可选 <code>yotta-skills</code> MCP(按需加载、不常驻)提供 <code>list_installed_skills</code> / <code>describe_skill</code> / <code>reindex</code> / <code>route_request</code> 四工具,配置见 <code>SKILL.md</code>。
|
|
37
38
|
|
|
38
39
|
边界:只做「下载 + 落位 + 汇总」——**不**开发技能内容、**不**内置任何技能本体、**不**用 <code>-g</code>
|
|
39
40
|
全局安装;只在你指定的目标内写文件。
|
|
@@ -59,8 +60,14 @@ npx -y @yottameta/yotta-skills update --agent codex
|
|
|
59
60
|
# 预览将安装清单(不联网、不改动)
|
|
60
61
|
npx -y @yottameta/yotta-skills --dry-run
|
|
61
62
|
|
|
63
|
+
# 按需求摘要给出组合、顺序与缺失技能安装建议
|
|
64
|
+
npx -y @yottameta/yotta-skills --route "检查代码质量,别糊弄"
|
|
65
|
+
|
|
62
66
|
# 盘点本机已装技能(自包含扫描,不依赖任何元技能)
|
|
63
67
|
npx -y @yottameta/yotta-skills --inventory
|
|
68
|
+
|
|
69
|
+
# 重扫注册表(会话开工 / 新装技能后,增量合并变化)
|
|
70
|
+
npx -y @yottameta/yotta-skills --reindex
|
|
64
71
|
```
|
|
65
72
|
|
|
66
73
|
前置:Node.js 18+、npm、系统 tar(Windows 10+ / macOS / 多数 Linux 自带)。
|
|
@@ -75,6 +82,9 @@ npx -y @yottameta/yotta-skills --inventory
|
|
|
75
82
|
| `install <skill>... [--agent <name> \| --dir <path>]` | 只装指定的一个或多个技能 |
|
|
76
83
|
| `update [--agent <name> \| --dir <path>]` | 增量更新:补齐缺失、升级版本不一致的技能 |
|
|
77
84
|
| `--inventory` | 盘点已装技能:扫描技能目录并更新本地注册表(自包含);`--json` 输出 JSON、`--project` 附扫项目级目录 |
|
|
85
|
+
| `--reindex` | 重扫注册表:扫描技能目录并增量合并变化(会话开工 / 装技能后自动调用;`--rescan` 同义);`--json` 输出 JSON |
|
|
86
|
+
| `--route <需求摘要>` | 静态编排路由:输出组合、调用顺序、技能角色、置信度、依据、已装/缺失状态与安装建议;`--json` 输出 JSON、`--project` 附扫项目级目录 |
|
|
87
|
+
| `--no-reindex` | 安装 / 更新后不自动重扫注册表 |
|
|
78
88
|
| `--dry-run` | 预览将执行的安装 / 更新清单;不联网、不改动 |
|
|
79
89
|
| `--pin` | 锁死清单精确版本(默认 range:跟随同 major 最新 patch) |
|
|
80
90
|
| `--force` | 已是最新也重新安装 |
|
|
@@ -150,13 +160,14 @@ bash install.sh --list # 列出智能体 -> 默认目录
|
|
|
150
160
|
## 工作原理
|
|
151
161
|
|
|
152
162
|
对清单里每个技能:`npm pack <pkg>@<spec>` 到临时目录 → `tar -xzf` 解压 → 可选元信装前摘要 →
|
|
153
|
-
替换 `<dest>/<slug>` →
|
|
154
|
-
`
|
|
163
|
+
替换 `<dest>/<slug>` → 汇总报告。`install` / `update` 完成后自动重扫本地技能注册表,
|
|
164
|
+
新装技能随即出现在 `--inventory` / `--reindex` 里(可用 `--no-reindex` 关闭)。
|
|
165
|
+
细节见 `references/install-flow.md`;新手中文教程见 `references/tutorial.md`。
|
|
155
166
|
|
|
156
167
|
## 开发与校验
|
|
157
168
|
|
|
158
169
|
```bash
|
|
159
|
-
#
|
|
170
|
+
# 在技能目录内跑测试
|
|
160
171
|
npm test
|
|
161
172
|
```
|
|
162
173
|
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-skills
|
|
3
|
-
version: 0.
|
|
4
|
-
description: 元阁
|
|
3
|
+
version: 0.4.0
|
|
4
|
+
description: 元阁 -- 元阁全家技能的总编排策划 + 编排路由 + 一键安装器 + 技能盘点。路由层:--route / route_request 按需求摘要给出候选组合、调用顺序、角色、置信度、依据、已装/缺失状态与安装命令,只建议不自动安装;策划层:按场景给出「该组合哪几个元技能、组合强在哪、怎么自动装+自动用」;安装层:一条命令把 YottaMeta 已发布的全部 yotta-* 技能装进指定智能体或目录;盘点层:--inventory / --reindex 扫描本机已装技能生成/更新注册表,新装技能自动被发现(install/update 后自动 re-index,会话开工可先跑 --reindex;自包含零依赖,不依赖任何元技能);MCP 按需加载(可选:list_installed_skills/describe_skill/reindex/route_request,不常驻,未加载降级 CLI)。支持 --list 清单 / --route 路由 / install / update / --inventory / --reindex / --dry-run 预览 / --pin 锁版本。触发:需要批量安装或更新元阁全家技能、按场景组合多个元技能、路由或判断该用哪些技能、盘点或查看本机已装技能、重扫技能注册表、给某个智能体或目录一次性铺齐 yotta-* 技能、预览安装清单、锁版本安装、或用户说 元阁/装全家/一次装齐/yotta-skills/install-all/更新全家/该用哪个技能/路由技能/盘点技能/查看已装技能 等。边界(Do NOT trigger):只做「组合策划 + 静态路由建议 + 清单 + 下载 + 落位 + 汇总 + 盘点 + re-index」,不含技能本体、不做技能内容开发、不 -g 污染全局、不自动安装缺失技能;装前摘要仅供参考,安装决策由用户确认。
|
|
5
5
|
license: MIT
|
|
6
6
|
metadata:
|
|
7
7
|
zh_name: 元阁
|
|
@@ -15,7 +15,8 @@ metadata:
|
|
|
15
15
|
|
|
16
16
|
**写入内容(逐字)**:
|
|
17
17
|
|
|
18
|
-
>
|
|
18
|
+
> **元阁编排**:单技能是零件,组合才是系统。会话开工先跑一次 `yotta-skills --reindex`
|
|
19
|
+
> (重扫本机技能注册表,新装技能自动被看见)。接到需求,先查「元阁编排策划」命中哪个组合
|
|
19
20
|
> (输出呈现标准 / 长生命周期 / 交付质量门 / 装前安全门 / 造技能发版 / 安全事件响应 / 入口安装),
|
|
20
21
|
> 再按需自动安装并应用。完整决策表见技能 `yotta-skills/references/orchestration.md`。
|
|
21
22
|
|
|
@@ -26,11 +27,12 @@ metadata:
|
|
|
26
27
|
|
|
27
28
|
# 元阁(yotta-skills)
|
|
28
29
|
|
|
29
|
-
**元阁全家的总编排策划 + 一键安装 +
|
|
30
|
+
**元阁全家的总编排策划 + 编排路由 + 一键安装 + 技能盘点**,一句话四层:
|
|
30
31
|
|
|
32
|
+
- **路由层(该用哪几个)**:`--route "<需求摘要>"` / MCP `route_request` 查本地注册表与静态编排 playbook,输出候选组合、调用顺序、每个技能角色、置信度、依据、已装/缺失状态与安装命令;只建议安装,不自动安装。
|
|
31
33
|
- **策划层(怎么用)**:接到需求,先按「编排策划」定位命中哪个组合——哪些元技能搭配起来最强、适合什么场景、AI 该怎么自动装并自动用起来。
|
|
32
34
|
- **安装层(怎么装)**:一条 `npx -y @yottameta/yotta-skills` 把组合/全家装进指定智能体或目录——`--list` 看清单、`install` 装、`update` 增量更新、`--dry-run` 预览、`--pin` 锁版本。
|
|
33
|
-
- **盘点层(已装了什么)**:`--inventory`
|
|
35
|
+
- **盘点层(已装了什么)**:`--inventory` / `--reindex` 扫描本机各智能体技能目录,生成/更新本地注册表;装技能后自动 re-index,新装技能自动被发现——自包含扫描,不依赖任何元技能。
|
|
34
36
|
|
|
35
37
|
每个技能仍走各自独立的 npm 包(版本源唯一);本包只做「清单 + 下载 + 落位 + 汇总」,**不内置任何技能本体**。
|
|
36
38
|
> **本包不含技能本体**:拿到它只代表有了「编排策划 + 安装工具」;真正装齐需运行 `install`。
|
|
@@ -100,6 +102,9 @@ npx -y @yottameta/yotta-skills --dry-run
|
|
|
100
102
|
|
|
101
103
|
# 盘点本机已装技能(自包含扫描,不依赖任何元技能)
|
|
102
104
|
npx -y @yottameta/yotta-skills --inventory
|
|
105
|
+
|
|
106
|
+
# 重扫注册表(会话开工 / 新装技能后,增量合并变化)
|
|
107
|
+
npx -y @yottameta/yotta-skills --reindex
|
|
103
108
|
```
|
|
104
109
|
|
|
105
110
|
## 命令与选项
|
|
@@ -112,6 +117,9 @@ npx -y @yottameta/yotta-skills --inventory
|
|
|
112
117
|
| `install <skill>... [--agent <name> \| --dir <path>]` | 只装指定的一个或多个技能 |
|
|
113
118
|
| `update [--agent <name> \| --dir <path>]` | 增量更新:补齐缺失技能、升级版本不一致的技能 |
|
|
114
119
|
| `--inventory` | 盘点本机已装技能:扫描技能目录生成/更新注册表(自包含,不依赖元技能);`--json` 输出 JSON、`--project` 附扫项目级目录 |
|
|
120
|
+
| `--reindex` | 重扫注册表:扫描技能目录并增量合并变化(会话开工 / 装技能后自动调用);`--json` 输出 JSON、`--project` 附扫项目级目录;`--rescan` 同义 |
|
|
121
|
+
| `--route <需求摘要>` | 静态编排路由:输出组合、调用顺序、技能角色、置信度、依据、已装/缺失状态与安装建议;`--json` 输出 JSON、`--project` 附扫项目级目录 |
|
|
122
|
+
| `--no-reindex` | 安装 / 更新后不自动重扫注册表 |
|
|
115
123
|
| `--dry-run` | 预览将执行的安装 / 更新清单;不联网、不改动 |
|
|
116
124
|
| `--pin` | 锁死清单精确版本(默认 range:跟随同 major 最新 patch) |
|
|
117
125
|
| `--force` | 已是最新也重新安装 |
|
|
@@ -142,10 +150,36 @@ npx -y @yottameta/yotta-skills --inventory --dir ~/my-skills --project
|
|
|
142
150
|
|
|
143
151
|
注册表增量合并:新增(added)/ 更新(updated)/ 消失(gone)随输出列出;同名技能来自多个目录时合并来源,版本不一致记录冲突。
|
|
144
152
|
|
|
153
|
+
### re-index:新装技能自动被发现
|
|
154
|
+
|
|
155
|
+
- **装技能后自动**:`install` / `update` 完成后自动重扫注册表,把本次落位结果反映进
|
|
156
|
+
`~/.yottaskills/registry.json`(新增 / 更新 / 消失随输出列出);`--no-reindex` 可关闭。
|
|
157
|
+
- **会话开工**:建议每会话开工先跑一次 `yotta-skills --reindex`(快速增量,只合并变化),
|
|
158
|
+
让新装 / 更新的技能自动进入注册表。
|
|
159
|
+
- **手动**:`yotta-skills --reindex`(`--rescan` 同义);`--json` 机器可读、`--project` 附扫项目级目录。
|
|
160
|
+
|
|
161
|
+
## 编排路由(--route)
|
|
162
|
+
|
|
163
|
+
把需求摘要交给静态编排 playbook 和本地注册表,得到一组可执行建议:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# 文本输出:组合、调用顺序、角色、置信度、依据、缺失技能安装命令
|
|
167
|
+
npx -y @yottameta/yotta-skills --route "帮我润色输出,要规范可复制,别有 AI 味"
|
|
168
|
+
|
|
169
|
+
# 机器可读(JSON)
|
|
170
|
+
npx -y @yottameta/yotta-skills --route "检查代码质量,别糊弄" --json
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
- **输出**:候选组合、调用顺序、每个技能的角色、置信度、命中依据、已装/缺失状态、安装命令与应用模式提醒。
|
|
174
|
+
- **缺失技能**:只给安装命令,不自动安装;安装前应先做装前安全扫描,决定权在用户。
|
|
175
|
+
- **应用模式**:默认用户显式调用;切换为「按场景自动调用」需要用户确认。
|
|
176
|
+
- **无明确匹配**:低置信度回退到「入口 + 安装」组合,先澄清需求再继续。
|
|
177
|
+
- **边界**:路由是建议,不保证完全正确;关键动作由用户确认,数据不出本机。
|
|
178
|
+
|
|
145
179
|
### MCP:按需加载(可选)
|
|
146
180
|
|
|
147
181
|
本技能自带一个 MCP server:`yotta-skills`(`scripts/yotta-skills-mcp.py`,零依赖、数据不出本机),
|
|
148
|
-
提供 `list_installed_skills`(盘点)/ `describe_skill`(单技能详情)/ `reindex
|
|
182
|
+
提供 `list_installed_skills`(盘点)/ `describe_skill`(单技能详情)/ `reindex`(强制重扫)/ `route_request`(静态编排路由)四个工具。
|
|
149
183
|
|
|
150
184
|
**按需加载,不走常驻**:本技能与 MCP 均为按需触发。默认以 CLI 为主
|
|
151
185
|
(`npx -y @yottameta/yotta-skills --inventory`);需要让 AI 通过工具直接调用时,再按下面配置启用:
|
|
@@ -164,9 +198,9 @@ npx -y @yottameta/yotta-skills --inventory --dir ~/my-skills --project
|
|
|
164
198
|
```
|
|
165
199
|
> `<技能目录>` = 本技能实际安装目录,**不要写死盘符路径**;Windows 用 `python`,Linux/macOS 用 `python3`。
|
|
166
200
|
3. **提醒用户**:改 `mcpServers` 后多数客户端需**重启 / 重载一次** MCP server 才生效;加载后应看到
|
|
167
|
-
`list_installed_skills` / `describe_skill` / `reindex`
|
|
201
|
+
`list_installed_skills` / `describe_skill` / `reindex` / `route_request` 四个工具。
|
|
168
202
|
4. **降级兜底(重要)**:若客户端未暴露 MCP 工具 / 无法改配置 / server 未加载,**自动降级 CLI**
|
|
169
|
-
|
|
203
|
+
(同一套扫描与路由核心、结果一致):`npx -y @yottameta/yotta-skills --inventory / --reindex / --route ...`。
|
|
170
204
|
|
|
171
205
|
## 版本策略
|
|
172
206
|
|
package/assets/banner.png
CHANGED
|
Binary file
|
package/bin/yotta-skills.js
CHANGED
|
@@ -131,7 +131,7 @@ function parseArgs(argv) {
|
|
|
131
131
|
list: false, dryRun: false, pin: false, skipScan: false, force: false,
|
|
132
132
|
help: false, version: false, agent: null, dir: null, npm: null,
|
|
133
133
|
python: null, verify: null, command: null, skill: null, rest: [],
|
|
134
|
-
inventory: false,
|
|
134
|
+
inventory: false, reindex: false, noReindex: false, json: false, project: false, route: null,
|
|
135
135
|
};
|
|
136
136
|
const positionals = [];
|
|
137
137
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -145,7 +145,14 @@ function parseArgs(argv) {
|
|
|
145
145
|
else if (a === '--help' || a === '-h') opts.help = true;
|
|
146
146
|
else if (a === '--version' || a === '-v') opts.version = true;
|
|
147
147
|
else if (a === '--inventory' || a === '--inv') opts.inventory = true;
|
|
148
|
-
else if (a === '--
|
|
148
|
+
else if (a === '--route') {
|
|
149
|
+
const value = argv[i + 1];
|
|
150
|
+
if (value === undefined || value.startsWith('--')) die('--route 缺少需求摘要');
|
|
151
|
+
opts.route = value;
|
|
152
|
+
i++;
|
|
153
|
+
}
|
|
154
|
+
else if (a === '--reindex' || a === '--rescan') opts.reindex = true;
|
|
155
|
+
else if (a === '--no-reindex') opts.noReindex = true;
|
|
149
156
|
else if (a === '--json') opts.json = true;
|
|
150
157
|
else if (a === '--project') opts.project = true;
|
|
151
158
|
else if (a === '--agent') opts.agent = take('--agent').toLowerCase();
|
|
@@ -437,6 +444,8 @@ function printHelp() {
|
|
|
437
444
|
out(' yotta-skills update --agent <name> 增量更新已装技能(补齐缺失 / 版本不一致)');
|
|
438
445
|
out(' yotta-skills --dry-run 预览将安装清单(不联网、不改动)');
|
|
439
446
|
out(' yotta-skills --inventory 盘点本机已装技能(自研扫描,不依赖任何元技能)');
|
|
447
|
+
out(' yotta-skills --reindex 重扫注册表(会话开工 / 装技能后自动调用;增量合并)');
|
|
448
|
+
out(' yotta-skills --route "<需求摘要>" 给出场景组合、调用顺序、缺失技能安装建议');
|
|
440
449
|
out('');
|
|
441
450
|
out('选项:');
|
|
442
451
|
out(' --agent <name> 智能体键名(--list 可查看;未知智能体请用 --dir)');
|
|
@@ -447,8 +456,10 @@ function printHelp() {
|
|
|
447
456
|
out(' --npm <path> 指定 npm 可执行文件(默认 npm / npm.cmd)');
|
|
448
457
|
out(' --python <path> 指定 python 可执行文件(元信 scan 用)');
|
|
449
458
|
out(' --verify <path> 指定 yotta_verify.py 路径(默认找目标目录已装的元信)');
|
|
450
|
-
out(' --json inventory 时输出 JSON');
|
|
451
|
-
out(' --
|
|
459
|
+
out(' --json inventory / reindex / route 时输出 JSON');
|
|
460
|
+
out(' --route <需求> 静态编排路由(输出组合 / 顺序 / 依据 / 缺失技能建议)');
|
|
461
|
+
out(' --project inventory / reindex 时附加扫描当前项目 .agents/skills / .codex/skills');
|
|
462
|
+
out(' --no-reindex 安装 / 更新后不自动重扫注册表');
|
|
452
463
|
out(' -h, --help 帮助');
|
|
453
464
|
out(' -v, --version 版本');
|
|
454
465
|
out('');
|
|
@@ -458,8 +469,9 @@ function printHelp() {
|
|
|
458
469
|
|
|
459
470
|
|
|
460
471
|
|
|
461
|
-
// ──
|
|
462
|
-
|
|
472
|
+
// ── 技能盘点 / re-index(自研零依赖扫描核心) ────────────────────────────────
|
|
473
|
+
/** 重扫所有技能根目录并增量合并进注册表;返回 { result, registry, changes }。 */
|
|
474
|
+
function reindexRegistry(opts) {
|
|
463
475
|
const scan = require('../lib/skills-scan');
|
|
464
476
|
const extraDirs = opts.dir ? [opts.dir] : [];
|
|
465
477
|
const roots = scan.defaultRoots({ extraDirs: extraDirs, project: opts.project });
|
|
@@ -467,6 +479,12 @@ function runInventory(opts) {
|
|
|
467
479
|
const prev = scan.readRegistry();
|
|
468
480
|
const { registry, changes } = scan.mergeRegistry(result, prev);
|
|
469
481
|
scan.saveRegistry(registry);
|
|
482
|
+
return { result, registry, changes };
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function runInventory(opts) {
|
|
486
|
+
const scan = require('../lib/skills-scan');
|
|
487
|
+
const { result, registry, changes } = reindexRegistry(opts);
|
|
470
488
|
if (opts.json) {
|
|
471
489
|
out(JSON.stringify({
|
|
472
490
|
generated_at: registry.updated,
|
|
@@ -486,13 +504,82 @@ function runInventory(opts) {
|
|
|
486
504
|
}
|
|
487
505
|
}
|
|
488
506
|
|
|
507
|
+
/** --reindex:重扫 + 增量合并,变化聚焦输出(供会话开工 / 钩子使用)。 */
|
|
508
|
+
function runReindex(opts) {
|
|
509
|
+
const scan = require('../lib/skills-scan');
|
|
510
|
+
const { result, registry, changes } = reindexRegistry(opts);
|
|
511
|
+
if (opts.json) {
|
|
512
|
+
out(JSON.stringify({
|
|
513
|
+
reindexed_at: registry.updated,
|
|
514
|
+
note: registry.note,
|
|
515
|
+
count: Object.values(registry.skills).filter((s) => s.status !== 'gone').length,
|
|
516
|
+
changes: changes,
|
|
517
|
+
errors: result.errors,
|
|
518
|
+
scanned: result.scanned,
|
|
519
|
+
}, null, 2));
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
out('re-index 完成: 新增 ' + changes.added.length + ' / 更新 ' + changes.updated.length + ' / 消失 ' + changes.gone.length);
|
|
523
|
+
for (const slug of changes.added) out(' + ' + slug);
|
|
524
|
+
for (const slug of changes.updated) out(' ~ ' + slug);
|
|
525
|
+
for (const slug of changes.gone) out(' - ' + slug);
|
|
526
|
+
if (result.errors.length) {
|
|
527
|
+
out('跳过不存在目录 ' + result.errors.length + ' 个');
|
|
528
|
+
}
|
|
529
|
+
out('注册表: ' + scan.registryPath());
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/** --route:静态编排路由,输出组合、顺序、角色与缺失技能建议。 */
|
|
533
|
+
function runRoute(opts) {
|
|
534
|
+
const { routeRequest } = require('../lib/route');
|
|
535
|
+
const { registry } = reindexRegistry(opts);
|
|
536
|
+
const result = routeRequest(opts.route, { registry });
|
|
537
|
+
if (opts.json) {
|
|
538
|
+
out(JSON.stringify(result, null, 2));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
out('路由结果: ' + result.playbook.name + '(置信度: ' + result.confidence + ')');
|
|
542
|
+
out('适配意图: ' + result.playbook.intent);
|
|
543
|
+
out('依据: ' + (result.matched_keywords.length ? result.matched_keywords.join('、') : '无明确匹配,回退到入口澄清'));
|
|
544
|
+
out('');
|
|
545
|
+
out('调用顺序:');
|
|
546
|
+
for (const skill of result.skills) {
|
|
547
|
+
out(' ' + skill.order + '. ' + skill.slug + ' [' + (skill.installed ? '已装' : '缺失') + '] - ' + skill.role);
|
|
548
|
+
}
|
|
549
|
+
if (result.missing_skills.length) {
|
|
550
|
+
out('');
|
|
551
|
+
out('缺失技能: ' + result.missing_skills.map((skill) => skill.slug).join(', '));
|
|
552
|
+
out('安装命令: ' + result.install_command);
|
|
553
|
+
out('安全提示: 安装前请先执行装前安全扫描;本命令不会自动安装。');
|
|
554
|
+
}
|
|
555
|
+
out('');
|
|
556
|
+
out('应用模式: 显式调用(可经用户确认后切换为按场景自动调用)');
|
|
557
|
+
out('说明: ' + result.disclaimer);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/** 装技能后自动 re-index(--no-reindex 关闭):把本次落位结果反映进注册表。best-effort:失败不阻断安装。 */
|
|
561
|
+
function maybeAutoReindex(opts, dest) {
|
|
562
|
+
if (opts.noReindex || opts.dryRun || !dest) return;
|
|
563
|
+
const scan = require('../lib/skills-scan');
|
|
564
|
+
try {
|
|
565
|
+
const { changes } = reindexRegistry({ ...opts, dir: dest });
|
|
566
|
+
out('');
|
|
567
|
+
out('已自动 re-index 注册表(新增 ' + changes.added.length + ' / 更新 ' + changes.updated.length + ' / 消失 ' + changes.gone.length + ';注册表: ' + scan.registryPath() + ')');
|
|
568
|
+
} catch (e) {
|
|
569
|
+
out('');
|
|
570
|
+
out('提示: 自动 re-index 跳过(' + e.message + ');稍后可手动 --reindex 重扫');
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
489
574
|
// ── main ───────────────────────────────────────────────────────────────────
|
|
490
575
|
function main() {
|
|
491
576
|
const opts = parseArgs(process.argv.slice(2));
|
|
492
577
|
if (opts.help) { printHelp(); return; }
|
|
493
578
|
if (opts.version) { out('yotta-skills v' + VERSION); return; }
|
|
494
579
|
if (opts.list) { printList(opts); return; }
|
|
495
|
-
if (opts.inventory) { runInventory(opts); return; }
|
|
580
|
+
if (opts.inventory && !opts.command) { runInventory(opts); return; }
|
|
581
|
+
if (opts.reindex && !opts.command) { runReindex(opts); return; }
|
|
582
|
+
if (opts.route && !opts.command) { runRoute(opts); return; }
|
|
496
583
|
|
|
497
584
|
const command = opts.command || 'install';
|
|
498
585
|
let dest = resolveTargetDir(opts);
|
|
@@ -518,6 +605,7 @@ function main() {
|
|
|
518
605
|
|
|
519
606
|
if (command === 'update') runUpdate(opts, dest);
|
|
520
607
|
else runInstall(opts, dest);
|
|
608
|
+
maybeAutoReindex(opts, dest);
|
|
521
609
|
}
|
|
522
610
|
|
|
523
611
|
main();
|
package/lib/route.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const PLAYBOOKS = [
|
|
4
|
+
{
|
|
5
|
+
id: 'output-standard',
|
|
6
|
+
name: '输出呈现标准',
|
|
7
|
+
intent: '让输出先判型渲染为可复制格式,再去除 AI 味。',
|
|
8
|
+
keywords: ['输出', '呈现', '渲染', '排版', '可复制', 'AI味', 'AI 味', '润色', '文档', '报告'],
|
|
9
|
+
skills: [
|
|
10
|
+
{ slug: 'yotta-present', order: 1, role: '判断内容形态并渲染为可复制 Markdown / 纯文本。' },
|
|
11
|
+
{ slug: 'yotta-humanize', order: 2, role: '检测中文 AI 腔,并按用户原意做确定性改写。' },
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 'long-lived-agent',
|
|
16
|
+
name: '长生命周期智能体',
|
|
17
|
+
intent: '让智能体跨会话恢复状态、记忆、经验与历史。',
|
|
18
|
+
keywords: ['长期', '跨会话', '忘了我', '别忘了我', '记忆', '上下文', '状态', '历史'],
|
|
19
|
+
skills: [
|
|
20
|
+
{ slug: 'yotta-workflow', order: 1, role: '开工读取项目状态,会话结束更新状态并留下次接续记录。' },
|
|
21
|
+
{ slug: 'yotta-memory', order: 2, role: '按权限边界保存与恢复跨会话记忆。' },
|
|
22
|
+
{ slug: 'yotta-learn', order: 3, role: '沉淀错误、纠正与洞见,供后续会话复用。' },
|
|
23
|
+
{ slug: 'yotta-logs', order: 4, role: '按需检索历史会话与日志记录。' },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'delivery-quality-gate',
|
|
28
|
+
name: '交付质量门',
|
|
29
|
+
intent: '交付前做防敷衍、代码质量与发布守门检查。',
|
|
30
|
+
keywords: ['检查', '代码', '质量', '别糊弄', '敷衍', '评审', '发布', '守门', '交付'],
|
|
31
|
+
skills: [
|
|
32
|
+
{ slug: 'yotta-anti-shallow', order: 1, role: '强制先分析、再执行、后自检,防止表面化交付。' },
|
|
33
|
+
{ slug: 'yotta-code-quality', order: 2, role: '按十二类腐化风险做结对式代码质量评审。' },
|
|
34
|
+
{ slug: 'yotta-publish-guard', order: 3, role: '发布前校验版本、发布件与分发通道一致性。' },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'preinstall-security-gate',
|
|
39
|
+
name: '装前安全门',
|
|
40
|
+
intent: '安装其他来源技能、插件或 MCP 前做安全判定。',
|
|
41
|
+
keywords: ['安装', '装前', '其他来源', '技能', '插件', 'MCP', '安全扫描'],
|
|
42
|
+
skills: [
|
|
43
|
+
{ slug: 'yotta-verify', order: 1, role: '执行确定性装前扫描并给出安全判定。' },
|
|
44
|
+
{ slug: 'yotta-vetter', order: 2, role: '按四阶段协议审查来源、代码、权限与风险。' },
|
|
45
|
+
{ slug: 'yotta-security-audit', order: 3, role: '做深度静态检测与安全基线兜底。' },
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'skill-build-publish',
|
|
50
|
+
name: '造技能 / 发版',
|
|
51
|
+
intent: '创建合规技能包,并在发布前完成守门检查。',
|
|
52
|
+
keywords: ['造一个', '新 skill', '新技能', '脚手架', '发版', '发布技能', '技能包'],
|
|
53
|
+
skills: [
|
|
54
|
+
{ slug: 'yotta-skill-creator', order: 1, role: '生成符合规范的技能目录与发布件结构。' },
|
|
55
|
+
{ slug: 'yotta-publish-guard', order: 2, role: '校验版本四件、发布件与分发通道。' },
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'security-incident-response',
|
|
60
|
+
name: '安全事件响应',
|
|
61
|
+
intent: '从日志、情报、样本、密钥、供应链与资产侦察看清事件链路。',
|
|
62
|
+
keywords: ['日志', '攻击', '安全事件', '入侵', 'IOC', '威胁情报', '样本', '密钥泄露', '供应链', '资产', '侦察'],
|
|
63
|
+
skills: [
|
|
64
|
+
{ slug: 'yotta-logwatch', order: 1, role: '分析安全日志并识别攻击链与告警聚合。' },
|
|
65
|
+
{ slug: 'yotta-intel', order: 2, role: '提取、去武器化并规范化威胁情报 IOC。' },
|
|
66
|
+
{ slug: 'yotta-triage', order: 3, role: '对可疑样本做静态初筛。' },
|
|
67
|
+
{ slug: 'yotta-secret', order: 4, role: '扫描密钥与凭据泄露源头。' },
|
|
68
|
+
{ slug: 'yotta-chain', order: 5, role: '校验依赖供应链与 lockfile 一致性。' },
|
|
69
|
+
{ slug: 'yotta-recon', order: 6, role: '在授权范围内做端口、服务与版本指纹侦察。' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'entry-install',
|
|
74
|
+
name: '入口 + 安装',
|
|
75
|
+
intent: '需求方向不明确时先澄清意图,再按需安装合适技能。',
|
|
76
|
+
keywords: ['不知道用哪个', '需求模糊', '该用哪个', '怎么说', '技能该用哪个'],
|
|
77
|
+
skills: [
|
|
78
|
+
{ slug: 'yotta-prompt', order: 1, role: '澄清需求意图并串联到合适的技能方向。' },
|
|
79
|
+
{ slug: 'yotta-skills', order: 2, role: '按场景组合安装所需技能,不默认安装全家。' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
function normalizeText(text) {
|
|
85
|
+
return String(text || '').toLowerCase().replace(/\s+/g, '');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function scorePlaybook(request, playbook) {
|
|
89
|
+
const text = normalizeText(request);
|
|
90
|
+
const matchedKeywords = [];
|
|
91
|
+
let score = 0;
|
|
92
|
+
for (const keyword of playbook.keywords) {
|
|
93
|
+
if (text.includes(normalizeText(keyword))) {
|
|
94
|
+
matchedKeywords.push(keyword);
|
|
95
|
+
score += normalizeText(keyword).length >= 3 ? 2 : 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { score, matchedKeywords };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function routeRequest(request, options) {
|
|
102
|
+
const registry = (options && options.registry) || { skills: {} };
|
|
103
|
+
const installed = registry.skills || {};
|
|
104
|
+
const ranked = PLAYBOOKS
|
|
105
|
+
.map((playbook) => ({ playbook, ...scorePlaybook(request, playbook) }))
|
|
106
|
+
.sort((a, b) => b.score - a.score || a.playbook.id.localeCompare(b.playbook.id));
|
|
107
|
+
const best = ranked[0];
|
|
108
|
+
const runnerUp = ranked[1];
|
|
109
|
+
const fallback = !best || best.score === 0;
|
|
110
|
+
const playbook = fallback
|
|
111
|
+
? PLAYBOOKS.find((item) => item.id === 'entry-install')
|
|
112
|
+
: best.playbook;
|
|
113
|
+
const matchedKeywords = fallback ? [] : best.matchedKeywords;
|
|
114
|
+
const margin = fallback ? 0 : best.score - (runnerUp ? runnerUp.score : 0);
|
|
115
|
+
const confidence = !fallback && best.score >= 3 && margin >= 1
|
|
116
|
+
? 'high'
|
|
117
|
+
: (!fallback && best.score >= 1 ? 'medium' : 'low');
|
|
118
|
+
|
|
119
|
+
const skills = playbook.skills.map((skill) => {
|
|
120
|
+
const record = installed[skill.slug];
|
|
121
|
+
const isInstalled = Boolean(record && record.status !== 'gone');
|
|
122
|
+
return {
|
|
123
|
+
...skill,
|
|
124
|
+
installed: isInstalled,
|
|
125
|
+
version: isInstalled ? record.version || '' : '',
|
|
126
|
+
sources: isInstalled ? record.sources || [] : [],
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
const missingSkills = skills
|
|
130
|
+
.filter((skill) => !skill.installed)
|
|
131
|
+
.map((skill) => ({ slug: skill.slug, scan_required: true }));
|
|
132
|
+
const installCommand = missingSkills.length
|
|
133
|
+
? 'npx -y @yottameta/yotta-skills install '
|
|
134
|
+
+ missingSkills.map((skill) => skill.slug).join(' ')
|
|
135
|
+
+ ' --dir <skills-dir>'
|
|
136
|
+
: null;
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
request,
|
|
140
|
+
playbook: {
|
|
141
|
+
id: playbook.id,
|
|
142
|
+
name: playbook.name,
|
|
143
|
+
intent: playbook.intent,
|
|
144
|
+
},
|
|
145
|
+
confidence,
|
|
146
|
+
matched_keywords: matchedKeywords,
|
|
147
|
+
skills,
|
|
148
|
+
missing_skills: missingSkills,
|
|
149
|
+
install_command: installCommand,
|
|
150
|
+
auto_install: false,
|
|
151
|
+
application_mode: {
|
|
152
|
+
default: 'explicit',
|
|
153
|
+
options: ['explicit', 'scene-auto'],
|
|
154
|
+
note: '默认用户显式调用;切换为按场景自动调用需要用户确认。',
|
|
155
|
+
},
|
|
156
|
+
disclaimer: '路由建议不保证完全正确;关键动作应由用户确认,数据不出本机。',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = { PLAYBOOKS, routeRequest };
|
package/lib/skills-scan.js
CHANGED
|
@@ -267,7 +267,7 @@ function mergeRegistry(scanResult, previous) {
|
|
|
267
267
|
}
|
|
268
268
|
const registry = {
|
|
269
269
|
updated: now,
|
|
270
|
-
note: '本地技能注册表(yotta-skills --inventory 生成)。数据不出本机。',
|
|
270
|
+
note: '本地技能注册表(yotta-skills --inventory / --reindex 生成)。数据不出本机。',
|
|
271
271
|
skills: next,
|
|
272
272
|
};
|
|
273
273
|
return { registry, changes };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-skills",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "YuanGe (元阁)
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "YuanGe (元阁) - orchestration routing, inventory, and one-command installer for the YottaMeta skill family (zero dependencies, Node.js only).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent-skills",
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
4. 元信装前摘要(若引擎可用;`--skip-scan` 关闭);
|
|
14
14
|
5. 删除目标 `<dest>/<slug>` 后重新复制(跳过规则见下);
|
|
15
15
|
6. 汇总报告:✔ 成功 / - 跳过(已是最新)/ ✘ 失败;有失败项时退出码 1。
|
|
16
|
+
7. 全部完成后自动 re-index 本地技能注册表(`~/.yottaskills/registry.json`):重扫技能根目录并增量合并,
|
|
17
|
+
新装 / 更新的技能随即进入注册表(`--no-reindex` 可关闭;`--dry-run` 不触发)。
|
|
16
18
|
|
|
17
19
|
## 复制跳过规则
|
|
18
20
|
|
|
@@ -22,6 +24,14 @@
|
|
|
22
24
|
因此装进技能目录的是「技能本体」(SKILL.md / references / scripts 等),不含 npm
|
|
23
25
|
安装器自身、测试夹具与 Python 字节码缓存。
|
|
24
26
|
|
|
27
|
+
## re-index(装技能后自动重扫注册表)
|
|
28
|
+
|
|
29
|
+
- `install` / `update` 完成后,CLI 自动调用 `--reindex`(同一套 `lib/skills-scan.js` 扫描核心):
|
|
30
|
+
重扫技能根目录 → 增量合并进 `~/.yottaskills/registry.json`(新增 / 更新 / 消失)。
|
|
31
|
+
- `--no-reindex` 关闭自动重扫;`--reindex` 也可单独手动执行(会话开工 / 新装技能后)。
|
|
32
|
+
- 与 `--inventory` 的区别:`--inventory` 侧重「盘点展示」(文本表格 / JSON 全量),
|
|
33
|
+
`--reindex` 侧重「变化合并」(增量、输出聚焦新增 / 更新 / 消失,适合钩子与脚本)。
|
|
34
|
+
|
|
25
35
|
## 幂等与版本判断
|
|
26
36
|
|
|
27
37
|
- 读取目标 `<dest>/<slug>/SKILL.md` 的 frontmatter `version`;
|
|
@@ -6,6 +6,22 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## 〇、编排路由(--route / route_request)
|
|
10
|
+
|
|
11
|
+
把需求摘要交给静态 playbook 与本地注册表,得到一组建议:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx -y @yottameta/yotta-skills --route "帮我润色输出,要规范可复制,别有 AI 味"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **输出**:候选组合、调用顺序、每个技能的角色、置信度、命中依据、已装/缺失状态、安装命令与应用模式提醒。
|
|
18
|
+
- **缺失技能**:只给安装命令,不自动安装;安装前先做装前安全扫描,决定权在用户。
|
|
19
|
+
- **应用模式**:默认用户显式调用;切换为「按场景自动调用」需要用户确认。
|
|
20
|
+
- **无明确匹配**:低置信度回退到「入口 + 安装」组合,先澄清需求再继续。
|
|
21
|
+
- **边界**:路由是建议,不保证完全正确;关键动作由用户确认,数据不出本机。
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
9
25
|
## 一、技能家族全景(24 技能 / 8 家族)
|
|
10
26
|
|
|
11
27
|
| 家族 | 技能(中文名 / slug) | 一句话能力 |
|
package/references/tutorial.md
CHANGED
|
@@ -104,3 +104,28 @@ npx -y @yottameta/yotta-skills install --agent codex --skip-scan # 跳过装前
|
|
|
104
104
|
- **目标未指定**:当前目录没有项目级技能目录时报错(退出码 4),加 `--agent` 或
|
|
105
105
|
`--dir`。
|
|
106
106
|
- **已有旧版本**:默认按 range 覆盖升级到最新 patch;`--pin` 则锁定清单版本。
|
|
107
|
+
|
|
108
|
+
## 11. 盘点已装技能与 re-index(新装技能自动被发现)
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# 盘点本机已装技能(文本表格)
|
|
112
|
+
npx -y @yottameta/yotta-skills --inventory
|
|
113
|
+
|
|
114
|
+
# 重扫注册表(会话开工 / 新装技能后,增量合并变化)
|
|
115
|
+
npx -y @yottameta/yotta-skills --reindex
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
- `install` / `update` 完成后会自动重扫注册表(`~/.yottaskills/registry.json`),新装 / 更新的
|
|
119
|
+
技能随即出现在 `--inventory` / `--reindex` 里;`--no-reindex` 可关闭自动重扫。
|
|
120
|
+
- 建议每会话开工先跑一次 `--reindex`(快速增量,只合并变化),让后装的技能自动被看见。
|
|
121
|
+
|
|
122
|
+
## 编排路由(--route)
|
|
123
|
+
|
|
124
|
+
当你不知道「这个需求该用哪几个技能」,可以先把需求摘要交给元阁:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx -y @yottameta/yotta-skills --route "检查代码质量,别糊弄"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
输出会告诉你命中哪个组合、按什么顺序调用、每个技能负责什么、哪些已装、哪些缺失,以及缺失技能的安装命令。元阁只给建议,不会自动安装;安装前请先做装前安全扫描,并由用户确认。
|
|
131
|
+
- `--json` 输出机器可读结果(含新增 / 更新 / 消失),适合脚本与钩子。
|
|
@@ -6,8 +6,9 @@ stdio MCP server(JSON-RPC 2.0,换行分隔),把元阁技能扫描核心
|
|
|
6
6
|
list_installed_skills 盘点本机已装技能(读本地注册表;未生成则先扫描一次)
|
|
7
7
|
describe_skill 查看单个技能详情(slug / 版本 / 功能 / 来源)
|
|
8
8
|
reindex 强制重新扫描并更新注册表
|
|
9
|
+
route_request 按需求摘要给出静态编排路由建议
|
|
9
10
|
|
|
10
|
-
自包含原则:扫描由元阁自带核心(bin/yotta-skills.js --inventory)完成,
|
|
11
|
+
自包含原则:扫描由元阁自带核心(bin/yotta-skills.js --inventory / --reindex)完成,
|
|
11
12
|
不依赖任何元技能;数据只写本机 ~/.yottaskills/registry.json,不出本机。
|
|
12
13
|
|
|
13
14
|
运行:python scripts/yotta-skills-mcp.py
|
|
@@ -23,7 +24,7 @@ import subprocess
|
|
|
23
24
|
import sys
|
|
24
25
|
from pathlib import Path
|
|
25
26
|
|
|
26
|
-
VERSION = "0.
|
|
27
|
+
VERSION = "0.4.0"
|
|
27
28
|
TOOL_NAME = "yotta-skills"
|
|
28
29
|
CN_NAME = "元阁"
|
|
29
30
|
MCP_PROTOCOL = "2025-03-26"
|
|
@@ -123,13 +124,13 @@ def _tool_describe(arguments):
|
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
def _tool_reindex(arguments): # noqa: ARG001
|
|
126
|
-
stdout = _run_cli(["--
|
|
127
|
+
stdout = _run_cli(["--reindex", "--json"])
|
|
127
128
|
try:
|
|
128
129
|
data = json.loads(stdout)
|
|
129
130
|
except json.JSONDecodeError as e:
|
|
130
131
|
return _tool_error("reindex 输出解析失败:%s" % e)
|
|
131
132
|
payload = {
|
|
132
|
-
"count": len(data.get("skills", [])),
|
|
133
|
+
"count": data.get("count", len(data.get("skills", []))),
|
|
133
134
|
"changes": data.get("changes"),
|
|
134
135
|
"errors": data.get("errors"),
|
|
135
136
|
"registry": str(REGISTRY_FILE),
|
|
@@ -138,10 +139,24 @@ def _tool_reindex(arguments): # noqa: ARG001
|
|
|
138
139
|
"isError": False}
|
|
139
140
|
|
|
140
141
|
|
|
142
|
+
def _tool_route(arguments):
|
|
143
|
+
request = str(arguments.get("request") or "").strip()
|
|
144
|
+
if not request:
|
|
145
|
+
return _tool_error("route_request 需要 request 参数")
|
|
146
|
+
stdout = _run_cli(["--route", request, "--json"])
|
|
147
|
+
try:
|
|
148
|
+
payload = json.loads(stdout)
|
|
149
|
+
except json.JSONDecodeError as e:
|
|
150
|
+
return _tool_error("route_request 输出解析失败:%s" % e)
|
|
151
|
+
return {"content": [{"type": "text", "text": json.dumps(payload, ensure_ascii=False, indent=2)}],
|
|
152
|
+
"isError": False}
|
|
153
|
+
|
|
154
|
+
|
|
141
155
|
TOOL_HANDLERS = {
|
|
142
156
|
"list_installed_skills": _tool_list,
|
|
143
157
|
"describe_skill": _tool_describe,
|
|
144
158
|
"reindex": _tool_reindex,
|
|
159
|
+
"route_request": _tool_route,
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
|
|
@@ -163,10 +178,17 @@ def mcp_tools():
|
|
|
163
178
|
),
|
|
164
179
|
_tool_spec(
|
|
165
180
|
"reindex",
|
|
166
|
-
"强制重新扫描所有技能目录并更新本地注册表,返回本次变化(新增 / 更新 /
|
|
181
|
+
"强制重新扫描所有技能目录并更新本地注册表,返回本次变化(新增 / 更新 / 消失);CLI 等价命令:yotta-skills --reindex。",
|
|
167
182
|
{},
|
|
168
183
|
[],
|
|
169
184
|
),
|
|
185
|
+
_tool_spec(
|
|
186
|
+
"route_request",
|
|
187
|
+
"按需求摘要给出静态编排路由建议:候选组合、调用顺序、每个技能角色、置信度、依据、已装/缺失状态与安装命令。"
|
|
188
|
+
"只建议安装,不自动安装;数据不出本机。",
|
|
189
|
+
{"request": {"type": "string", "description": "用户需求摘要"}},
|
|
190
|
+
["request"],
|
|
191
|
+
),
|
|
170
192
|
]
|
|
171
193
|
|
|
172
194
|
|