@yottameta/yotta-skills-plugin 0.24.2 → 0.25.1
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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/skills/yotta-skills/SKILL.md +43 -2
- package/skills/yotta-skills/bin/yotta-skills.js +415 -29
- package/skills/yotta-skills/lib/agent-dirs.js +201 -0
- package/skills/yotta-skills/lib/agent-discovery.js +302 -0
- package/skills/yotta-skills/lib/hub-adopt.js +268 -0
- package/skills/yotta-skills/lib/hub.js +583 -0
- package/skills/yotta-skills/lib/skills-cli-lock.js +52 -0
- package/skills/yotta-skills/lib/skills-scan.js +28 -38
- package/skills/yotta-skills/references/hub.md +66 -0
- package/skills/yotta-skills/references/skill-list.md +1 -1
- package/skills/yotta-skills/scripts/yotta-skills-mcp.py +1 -1
- package/skills/yotta-skills/skills.json +1 -1
|
@@ -17,33 +17,15 @@
|
|
|
17
17
|
const fs = require('fs');
|
|
18
18
|
const os = require('os');
|
|
19
19
|
const path = require('path');
|
|
20
|
+
const agentDirs = require('./agent-dirs');
|
|
20
21
|
|
|
21
22
|
const REGISTRY_DIR_NAME = '.yottaskills';
|
|
22
23
|
const REGISTRY_FILE_NAME = 'registry.json';
|
|
23
24
|
const SKILL_FILE = 'SKILL.md';
|
|
24
25
|
|
|
25
|
-
// 智能体 ->
|
|
26
|
-
//
|
|
27
|
-
const AGENT_DIRS =
|
|
28
|
-
claude: { label: 'Claude Code', dirs: ['.claude/skills'] },
|
|
29
|
-
cursor: { label: 'Cursor', dirs: ['.cursor/skills', '.agents/skills'] },
|
|
30
|
-
codex: { label: 'Codex', dirs: [] }, // 特判:$CODEX_HOME/skills
|
|
31
|
-
gemini: { label: 'Gemini CLI', dirs: ['.gemini/skills', '.agents/skills'] },
|
|
32
|
-
goose: { label: 'Goose', dirs: ['.config/goose/skills', '.agents/skills'] },
|
|
33
|
-
amp: { label: 'Amp', dirs: ['.config/agents/skills', '.agents/skills'] },
|
|
34
|
-
opencode: { label: 'OpenCode', dirs: [] }, // 特判:$XDG_CONFIG_HOME
|
|
35
|
-
windsurf: { label: 'Windsurf', dirs: ['.codeium/windsurf/skills'] },
|
|
36
|
-
workbuddy: { label: 'WorkBuddy', dirs: ['.workbuddy/skills'] },
|
|
37
|
-
kiro: { label: 'Kiro', dirs: ['.kiro/skills'] },
|
|
38
|
-
trae: { label: 'Trae Code CLI', dirs: ['.traecli/skills'] },
|
|
39
|
-
'trae-cn': { label: 'Trae IDE(国内)', dirs: ['.trae-cn/skills'] },
|
|
40
|
-
qwen: { label: 'Qwen Code', dirs: ['.qwen/skills'] },
|
|
41
|
-
comate: { label: 'Comate 文心快码', dirs: ['.comate/skills'] },
|
|
42
|
-
codebuddy: { label: 'CodeBuddy Code', dirs: ['.codebuddy/skills'] },
|
|
43
|
-
kimi: { label: 'Kimi Code CLI', dirs: ['.kimi/skills'] },
|
|
44
|
-
openclaw: { label: 'OpenClaw / QClaw', dirs: ['.openclaw/skills'] }, // 特判:$OPENCLAW_STATE_DIR
|
|
45
|
-
agents: { label: '通用 AGENTS.md', dirs: ['.agents/skills'] },
|
|
46
|
-
};
|
|
26
|
+
// 智能体 -> 用户级默认技能目录。单一真源在 lib/agent-dirs.js
|
|
27
|
+
// (兼容 Vercel Labs `skills` CLI / agentskills.io 的宿主表,MIT)。
|
|
28
|
+
const AGENT_DIRS = agentDirs.AGENT_DIRS;
|
|
47
29
|
|
|
48
30
|
/** 解析 SKILL.md 前部 YAML frontmatter(name/version/description 单行值)。 */
|
|
49
31
|
function parseFrontmatter(text) {
|
|
@@ -153,8 +135,13 @@ function scanSkillDir(dir) {
|
|
|
153
135
|
return results;
|
|
154
136
|
}
|
|
155
137
|
for (const e of entries) {
|
|
156
|
-
if (!e.isDirectory()) continue;
|
|
138
|
+
if (!e.isDirectory() && !e.isSymbolicLink()) continue;
|
|
157
139
|
const skillDir = path.join(dir, e.name);
|
|
140
|
+
try {
|
|
141
|
+
if (!fs.statSync(skillDir).isDirectory()) continue;
|
|
142
|
+
} catch (_) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
158
145
|
let text;
|
|
159
146
|
try {
|
|
160
147
|
text = fs.readFileSync(path.join(skillDir, SKILL_FILE), 'utf8');
|
|
@@ -175,27 +162,21 @@ function scanSkillDir(dir) {
|
|
|
175
162
|
|
|
176
163
|
/** Codex 用户级技能目录:$CODEX_HOME/skills(默认 ~/.codex/skills)。 */
|
|
177
164
|
function codexUserDir() {
|
|
178
|
-
|
|
179
|
-
return path.join(base, 'skills');
|
|
165
|
+
return agentDirs.resolveUserDir('.codex/skills', { homeDir: os.homedir(), env: process.env });
|
|
180
166
|
}
|
|
181
167
|
|
|
182
168
|
/** OpenCode 用户级技能目录:$XDG_CONFIG_HOME/opencode/skills。 */
|
|
183
169
|
function opencodeUserDir() {
|
|
184
|
-
|
|
185
|
-
return path.join(base, 'opencode', 'skills');
|
|
170
|
+
return agentDirs.resolveUserDir('.config/opencode/skills', { homeDir: os.homedir(), env: process.env });
|
|
186
171
|
}
|
|
187
172
|
|
|
188
173
|
/** OpenClaw / QClaw 用户级技能目录:$OPENCLAW_STATE_DIR/skills(默认 ~/.openclaw/skills)。 */
|
|
189
174
|
function openclawUserDir() {
|
|
190
|
-
|
|
191
|
-
return path.join(base, 'skills');
|
|
175
|
+
return agentDirs.resolveUserDir('.openclaw/skills', { homeDir: os.homedir(), env: process.env });
|
|
192
176
|
}
|
|
193
177
|
|
|
194
178
|
function resolveUserDir(rel) {
|
|
195
|
-
|
|
196
|
-
if (rel === '.config/opencode/skills') return opencodeUserDir();
|
|
197
|
-
if (rel === '.openclaw/skills') return openclawUserDir();
|
|
198
|
-
return path.join(os.homedir(), rel);
|
|
179
|
+
return agentDirs.resolveUserDir(rel, { homeDir: os.homedir(), env: process.env });
|
|
199
180
|
}
|
|
200
181
|
|
|
201
182
|
/**
|
|
@@ -216,12 +197,9 @@ function defaultRoots(opts) {
|
|
|
216
197
|
roots.push({ dir: norm, label });
|
|
217
198
|
};
|
|
218
199
|
const home = os.homedir();
|
|
219
|
-
for (const
|
|
220
|
-
|
|
221
|
-
for (const rel of info.dirs) add(resolveUserDir(rel), info.label);
|
|
200
|
+
for (const root of agentDirs.knownRoots({ homeDir: home, env: process.env })) {
|
|
201
|
+
add(root.dir, root.label);
|
|
222
202
|
}
|
|
223
|
-
add(codexUserDir(), 'Codex');
|
|
224
|
-
add(opencodeUserDir(), 'OpenCode');
|
|
225
203
|
if (Array.isArray(opts.extraDirs)) {
|
|
226
204
|
for (const d of opts.extraDirs) add(d, '指定目录');
|
|
227
205
|
}
|
|
@@ -268,6 +246,11 @@ function scanRoots(roots) {
|
|
|
268
246
|
}
|
|
269
247
|
}
|
|
270
248
|
for (const item of map.values()) {
|
|
249
|
+
item.variants.sort((a, b) => {
|
|
250
|
+
const byVersion = compareSemver(a.version, b.version);
|
|
251
|
+
if (byVersion) return byVersion;
|
|
252
|
+
return String(a.source || '').localeCompare(String(b.source || ''));
|
|
253
|
+
});
|
|
271
254
|
const representative = selectRepresentativeVariant(item.variants);
|
|
272
255
|
if (!representative) continue;
|
|
273
256
|
item.version = representative.version || '';
|
|
@@ -282,6 +265,13 @@ function scanRoots(roots) {
|
|
|
282
265
|
}));
|
|
283
266
|
if (conflicts.length) item.conflicts = conflicts;
|
|
284
267
|
else delete item.conflicts;
|
|
268
|
+
if (item.conflicts) {
|
|
269
|
+
item.conflicts.sort((a, b) => {
|
|
270
|
+
const byVersion = compareSemver(a.version, b.version);
|
|
271
|
+
if (byVersion) return byVersion;
|
|
272
|
+
return String(a.source || '').localeCompare(String(b.source || ''));
|
|
273
|
+
});
|
|
274
|
+
}
|
|
285
275
|
}
|
|
286
276
|
return {
|
|
287
277
|
generated_at: new Date().toISOString(),
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Hub(本机单点安装 + 链接分发)
|
|
2
|
+
|
|
3
|
+
## 它解决什么
|
|
4
|
+
|
|
5
|
+
多智能体各自维护技能目录时,同一技能会被复制多份,升级后容易版本漂移。Hub 把
|
|
6
|
+
技能集中到本机一份真源,再按宿主建立链接(Windows junction / macOS·Linux
|
|
7
|
+
symlink),升级只改真源,已链接宿主即时生效。
|
|
8
|
+
|
|
9
|
+
## 默认位置
|
|
10
|
+
|
|
11
|
+
- Hub 真源:`~/.yottaskills/hub`
|
|
12
|
+
- 技能台账:`<hub>/.yotta-hub.json`
|
|
13
|
+
- 链接台账:`<hub>/.yotta-links.json`
|
|
14
|
+
- 覆盖方式:`--hub <dir>` 或 `YOTTA_SKILLS_HUB`
|
|
15
|
+
|
|
16
|
+
## 命令
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 发现本机已装智能体与技能目录(文件系统优先;不读元忆 / 注册表)
|
|
20
|
+
npx -y @yottameta/yotta-skills hub hosts
|
|
21
|
+
|
|
22
|
+
# 安装 / 更新 Hub 真源
|
|
23
|
+
npx -y @yottameta/yotta-skills hub install
|
|
24
|
+
npx -y @yottameta/yotta-skills hub update
|
|
25
|
+
|
|
26
|
+
# 接管各宿主现有技能:先只读预演,再复制收编(原目录保留)
|
|
27
|
+
npx -y @yottameta/yotta-skills hub adopt --scan
|
|
28
|
+
npx -y @yottameta/yotta-skills hub adopt --apply
|
|
29
|
+
|
|
30
|
+
# 非元阁来源技能没有统一更新源:手动从指定目录刷新
|
|
31
|
+
npx -y @yottameta/yotta-skills hub refresh my-skill --from <技能目录>
|
|
32
|
+
|
|
33
|
+
# 分发到全部已发现宿主(默认不覆盖真目录;--force 才备份并替换)
|
|
34
|
+
npx -y @yottameta/yotta-skills hub link --all
|
|
35
|
+
|
|
36
|
+
# 只删除链接,不动 Hub 真源
|
|
37
|
+
npx -y @yottameta/yotta-skills hub unlink --all
|
|
38
|
+
|
|
39
|
+
# 查看来源、版本、链接宿主与异常
|
|
40
|
+
npx -y @yottameta/yotta-skills hub status
|
|
41
|
+
npx -y @yottameta/yotta-skills hub doctor
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 宿主发现口径
|
|
45
|
+
|
|
46
|
+
1. 已收录宿主映射(兼容 Vercel Labs `skills` CLI / SkillCat 的公开宿主表);
|
|
47
|
+
2. 环境变量覆盖(`CODEX_HOME`、`XDG_CONFIG_HOME`、`DSH_HOME`、
|
|
48
|
+
`OPENCLAW_STATE_DIR`、`CLAUDE_CONFIG_DIR` 等);
|
|
49
|
+
3. 常见配置根启发式扫描;
|
|
50
|
+
4. `YOTTA_SKILLS_DISCOVERY_ROOTS` 显式补充;
|
|
51
|
+
5. `--dir <path>` 精确指定非标准宿主。
|
|
52
|
+
|
|
53
|
+
自动发现默认排除临时目录、`.bak`、candidate / staging、插件构建目录等噪声。
|
|
54
|
+
|
|
55
|
+
## 兼容标准
|
|
56
|
+
|
|
57
|
+
- 技能格式:`agentskills.io` Agent Skills(`SKILL.md` + `name` / `description`)。
|
|
58
|
+
- 通用投影:`~/.agents/skills`、`$XDG_CONFIG_HOME/agents/skills`。
|
|
59
|
+
- 官方锁文件:只读兼容 Vercel Labs `skills` CLI 的 `.skill-lock.json` v3
|
|
60
|
+
(`$XDG_STATE_HOME/skills/` 或 `~/.agents/`)。
|
|
61
|
+
|
|
62
|
+
## 安全边界
|
|
63
|
+
|
|
64
|
+
- `unlink` 只删除 lstat 确认为链接、且 readlink 目标位于 Hub 内的路径。
|
|
65
|
+
- 真目录 / 非 Hub 链接一律拒绝删除;`--force` 对真目录先备份再替换。
|
|
66
|
+
- Hub 仅本机使用,不对外分发技能内容。
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| slug | 中文名 | npm 包 | 清单版本 | 家族 | 说明 |
|
|
7
7
|
|---|---|---|---|---|
|
|
8
8
|
| `yotta-anti-shallow` | 元谨 | `@yottameta/yotta-anti-shallow` | 1.4.2 | quality | 防 AI 敷衍规则引擎(深入分析/根因追溯时激活) |
|
|
9
|
-
| `yotta-code-quality` | 元质 | `@yottameta/yotta-code-quality` | 0.4.
|
|
9
|
+
| `yotta-code-quality` | 元质 | `@yottameta/yotta-code-quality` | 0.4.3 | quality | 结对式代码质量评审(十二类腐化风险 + 0-100 健康分) |
|
|
10
10
|
| `yotta-workflow` | 元序 | `@yottameta/yotta-workflow` | 0.4.3 | workflow | 跨会话/跨项目通用工作流协议(状态就近存) |
|
|
11
11
|
| `yotta-memory` | 元忆 | `@yottameta/yotta-memory` | 0.21.1 | memory | 有权限边界的文件式智能体记忆(FACT/PREF/BOUND/COMMIT) |
|
|
12
12
|
| `yotta-learn` | 元习 | `@yottameta/yotta-learn` | 0.2.2 | memory | 学习沉淀 CLI:错误/纠正/洞见沉淀为 .learnings/ 条目 |
|