skills 1.4.1 → 1.4.3
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/README.md +1 -2
- package/dist/_chunks/libs/@clack/prompts.mjs +60 -1
- package/dist/cli.mjs +206 -671
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -214,7 +214,7 @@ Skills can be installed to any of these agents:
|
|
|
214
214
|
| Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
|
|
215
215
|
| Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
|
|
216
216
|
| OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
|
|
217
|
-
| Cline | `cline` | `.
|
|
217
|
+
| Cline | `cline` | `.agents/skills/` | `~/.agents/skills/` |
|
|
218
218
|
| CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
|
|
219
219
|
| Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
|
|
220
220
|
| Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
|
|
@@ -321,7 +321,6 @@ The CLI searches for skills in these locations within a repository:
|
|
|
321
321
|
- `.augment/skills/`
|
|
322
322
|
- `.claude/skills/`
|
|
323
323
|
- `./skills/`
|
|
324
|
-
- `.cline/skills/`
|
|
325
324
|
- `.codebuddy/skills/`
|
|
326
325
|
- `.commandcode/skills/`
|
|
327
326
|
- `.continue/skills/`
|
|
@@ -129,6 +129,65 @@ ${s}
|
|
|
129
129
|
}).join(`
|
|
130
130
|
${import_picocolors.default.cyan(o)} `)}
|
|
131
131
|
${import_picocolors.default.cyan(d)}
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}).prompt();
|
|
136
|
+
}, be = (t) => {
|
|
137
|
+
const { selectableGroups: n = !0 } = t, r = (i, s, c = []) => {
|
|
138
|
+
const a = i.label ?? String(i.value), l = typeof i.group == "string", $ = l && (c[c.indexOf(i) + 1] ?? { group: !0 }), g = l && $.group === !0, p = l ? n ? `${g ? d : o} ` : " " : "";
|
|
139
|
+
if (s === "active") return `${import_picocolors.default.dim(p)}${import_picocolors.default.cyan(A)} ${a} ${i.hint ? import_picocolors.default.dim(`(${i.hint})`) : ""}`;
|
|
140
|
+
if (s === "group-active") return `${p}${import_picocolors.default.cyan(A)} ${import_picocolors.default.dim(a)}`;
|
|
141
|
+
if (s === "group-active-selected") return `${p}${import_picocolors.default.green(T)} ${import_picocolors.default.dim(a)}`;
|
|
142
|
+
if (s === "selected") {
|
|
143
|
+
const f = l || n ? import_picocolors.default.green(T) : "";
|
|
144
|
+
return `${import_picocolors.default.dim(p)}${f} ${import_picocolors.default.dim(a)} ${i.hint ? import_picocolors.default.dim(`(${i.hint})`) : ""}`;
|
|
145
|
+
}
|
|
146
|
+
if (s === "cancelled") return `${import_picocolors.default.strikethrough(import_picocolors.default.dim(a))}`;
|
|
147
|
+
if (s === "active-selected") return `${import_picocolors.default.dim(p)}${import_picocolors.default.green(T)} ${a} ${i.hint ? import_picocolors.default.dim(`(${i.hint})`) : ""}`;
|
|
148
|
+
if (s === "submitted") return `${import_picocolors.default.dim(a)}`;
|
|
149
|
+
const v = l || n ? import_picocolors.default.dim(F) : "";
|
|
150
|
+
return `${import_picocolors.default.dim(p)}${v} ${import_picocolors.default.dim(a)}`;
|
|
151
|
+
};
|
|
152
|
+
return new _D({
|
|
153
|
+
options: t.options,
|
|
154
|
+
initialValues: t.initialValues,
|
|
155
|
+
required: t.required ?? !0,
|
|
156
|
+
cursorAt: t.cursorAt,
|
|
157
|
+
selectableGroups: n,
|
|
158
|
+
validate(i) {
|
|
159
|
+
if (this.required && i.length === 0) return `Please select at least one option.
|
|
160
|
+
${import_picocolors.default.reset(import_picocolors.default.dim(`Press ${import_picocolors.default.gray(import_picocolors.default.bgWhite(import_picocolors.default.inverse(" space ")))} to select, ${import_picocolors.default.gray(import_picocolors.default.bgWhite(import_picocolors.default.inverse(" enter ")))} to submit`))}`;
|
|
161
|
+
},
|
|
162
|
+
render() {
|
|
163
|
+
const i = `${import_picocolors.default.gray(o)}
|
|
164
|
+
${b(this.state)} ${t.message}
|
|
165
|
+
`;
|
|
166
|
+
switch (this.state) {
|
|
167
|
+
case "submit": return `${i}${import_picocolors.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => r(s, "submitted")).join(import_picocolors.default.dim(", "))}`;
|
|
168
|
+
case "cancel": {
|
|
169
|
+
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => r(c, "cancelled")).join(import_picocolors.default.dim(", "));
|
|
170
|
+
return `${i}${import_picocolors.default.gray(o)} ${s.trim() ? `${s}
|
|
171
|
+
${import_picocolors.default.gray(o)}` : ""}`;
|
|
172
|
+
}
|
|
173
|
+
case "error": {
|
|
174
|
+
const s = this.error.split(`
|
|
175
|
+
`).map((c, a) => a === 0 ? `${import_picocolors.default.yellow(d)} ${import_picocolors.default.yellow(c)}` : ` ${c}`).join(`
|
|
176
|
+
`);
|
|
177
|
+
return `${i}${import_picocolors.default.yellow(o)} ${this.options.map((c, a, l) => {
|
|
178
|
+
const $ = this.value.includes(c.value) || c.group === !0 && this.isGroupSelected(`${c.value}`), g = a === this.cursor;
|
|
179
|
+
return !g && typeof c.group == "string" && this.options[this.cursor].value === c.group ? r(c, $ ? "group-active-selected" : "group-active", l) : g && $ ? r(c, "active-selected", l) : $ ? r(c, "selected", l) : r(c, g ? "active" : "inactive", l);
|
|
180
|
+
}).join(`
|
|
181
|
+
${import_picocolors.default.yellow(o)} `)}
|
|
182
|
+
${s}
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
default: return `${i}${import_picocolors.default.cyan(o)} ${this.options.map((s, c, a) => {
|
|
186
|
+
const l = this.value.includes(s.value) || s.group === !0 && this.isGroupSelected(`${s.value}`), $ = c === this.cursor;
|
|
187
|
+
return !$ && typeof s.group == "string" && this.options[this.cursor].value === s.group ? r(s, l ? "group-active-selected" : "group-active", a) : $ && l ? r(s, "active-selected", a) : l ? r(s, "selected", a) : r(s, $ ? "active" : "inactive", a);
|
|
188
|
+
}).join(`
|
|
189
|
+
${import_picocolors.default.cyan(o)} `)}
|
|
190
|
+
${import_picocolors.default.cyan(d)}
|
|
132
191
|
`;
|
|
133
192
|
}
|
|
134
193
|
}
|
|
@@ -272,4 +331,4 @@ ${J}${i.trimStart()}`), r = 3 + stripVTControlCharacters(i.trimStart()).length);
|
|
|
272
331
|
}
|
|
273
332
|
};
|
|
274
333
|
};
|
|
275
|
-
export { Y as a,
|
|
334
|
+
export { Y as a, ve as c, Se as i, xe as l, M as n, be as o, Me as r, fe as s, Ie as t, ye as u };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { r as __toESM } from "./_chunks/rolldown-runtime.mjs";
|
|
3
3
|
import { l as pD, u as require_picocolors } from "./_chunks/libs/@clack/core.mjs";
|
|
4
|
-
import { a as Y, c as
|
|
4
|
+
import { a as Y, c as ve, i as Se, l as xe, n as M, o as be, r as Me, s as fe, t as Ie, u as ye } from "./_chunks/libs/@clack/prompts.mjs";
|
|
5
5
|
import "./_chunks/libs/@kwsites/file-exists.mjs";
|
|
6
6
|
import "./_chunks/libs/@kwsites/promise-deferred.mjs";
|
|
7
7
|
import { t as esm_default } from "./_chunks/libs/simple-git.mjs";
|
|
@@ -49,15 +49,6 @@ async function isRepoPrivate(owner, repo) {
|
|
|
49
49
|
function isLocalPath(input) {
|
|
50
50
|
return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
51
51
|
}
|
|
52
|
-
function isDirectSkillUrl(input) {
|
|
53
|
-
if (!input.startsWith("http://") && !input.startsWith("https://")) return false;
|
|
54
|
-
if (!input.toLowerCase().endsWith("/skill.md")) return false;
|
|
55
|
-
if (input.includes("github.com/") && !input.includes("raw.githubusercontent.com")) {
|
|
56
|
-
if (!input.includes("/blob/") && !input.includes("/raw/")) return false;
|
|
57
|
-
}
|
|
58
|
-
if (input.includes("gitlab.com/") && !input.includes("/-/raw/")) return false;
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
52
|
const SOURCE_ALIASES = { "coinbase/agentWallet": "coinbase/agentic-wallet-skills" };
|
|
62
53
|
function parseSource(input) {
|
|
63
54
|
const alias = SOURCE_ALIASES[input];
|
|
@@ -70,10 +61,6 @@ function parseSource(input) {
|
|
|
70
61
|
localPath: resolvedPath
|
|
71
62
|
};
|
|
72
63
|
}
|
|
73
|
-
if (isDirectSkillUrl(input)) return {
|
|
74
|
-
type: "direct-url",
|
|
75
|
-
url: input
|
|
76
|
-
};
|
|
77
64
|
const githubTreeWithPathMatch = input.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/);
|
|
78
65
|
if (githubTreeWithPathMatch) {
|
|
79
66
|
const [, owner, repo, ref, subpath] = githubTreeWithPathMatch;
|
|
@@ -162,10 +149,8 @@ function isWellKnownUrl(input) {
|
|
|
162
149
|
if ([
|
|
163
150
|
"github.com",
|
|
164
151
|
"gitlab.com",
|
|
165
|
-
"huggingface.co",
|
|
166
152
|
"raw.githubusercontent.com"
|
|
167
153
|
].includes(parsed.hostname)) return false;
|
|
168
|
-
if (input.toLowerCase().endsWith("/skill.md")) return false;
|
|
169
154
|
if (input.endsWith(".git")) return false;
|
|
170
155
|
return true;
|
|
171
156
|
} catch {
|
|
@@ -424,6 +409,36 @@ async function getPluginSkillPaths(basePath) {
|
|
|
424
409
|
} catch {}
|
|
425
410
|
return searchDirs;
|
|
426
411
|
}
|
|
412
|
+
async function getPluginGroupings(basePath) {
|
|
413
|
+
const groupings = /* @__PURE__ */ new Map();
|
|
414
|
+
try {
|
|
415
|
+
const content = await readFile(join(basePath, ".claude-plugin/marketplace.json"), "utf-8");
|
|
416
|
+
const manifest = JSON.parse(content);
|
|
417
|
+
const pluginRoot = manifest.metadata?.pluginRoot;
|
|
418
|
+
if (pluginRoot === void 0 || isValidRelativePath(pluginRoot)) for (const plugin of manifest.plugins ?? []) {
|
|
419
|
+
if (!plugin.name) continue;
|
|
420
|
+
if (typeof plugin.source !== "string" && plugin.source !== void 0) continue;
|
|
421
|
+
if (plugin.source !== void 0 && !isValidRelativePath(plugin.source)) continue;
|
|
422
|
+
const pluginBase = join(basePath, pluginRoot ?? "", plugin.source ?? "");
|
|
423
|
+
if (!isContainedIn(pluginBase, basePath)) continue;
|
|
424
|
+
if (plugin.skills && plugin.skills.length > 0) for (const skillPath of plugin.skills) {
|
|
425
|
+
if (!isValidRelativePath(skillPath)) continue;
|
|
426
|
+
const skillDir = join(pluginBase, skillPath);
|
|
427
|
+
if (isContainedIn(skillDir, basePath)) groupings.set(resolve(skillDir), plugin.name);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} catch {}
|
|
431
|
+
try {
|
|
432
|
+
const content = await readFile(join(basePath, ".claude-plugin/plugin.json"), "utf-8");
|
|
433
|
+
const manifest = JSON.parse(content);
|
|
434
|
+
if (manifest.name && manifest.skills && manifest.skills.length > 0) for (const skillPath of manifest.skills) {
|
|
435
|
+
if (!isValidRelativePath(skillPath)) continue;
|
|
436
|
+
const skillDir = join(basePath, skillPath);
|
|
437
|
+
if (isContainedIn(skillDir, basePath)) groupings.set(resolve(skillDir), manifest.name);
|
|
438
|
+
}
|
|
439
|
+
} catch {}
|
|
440
|
+
return groupings;
|
|
441
|
+
}
|
|
427
442
|
const SKIP_DIRS = [
|
|
428
443
|
"node_modules",
|
|
429
444
|
".git",
|
|
@@ -475,9 +490,16 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
475
490
|
const skills = [];
|
|
476
491
|
const seenNames = /* @__PURE__ */ new Set();
|
|
477
492
|
const searchPath = subpath ? join(basePath, subpath) : basePath;
|
|
493
|
+
const pluginGroupings = await getPluginGroupings(searchPath);
|
|
494
|
+
const enhanceSkill = (skill) => {
|
|
495
|
+
const resolvedPath = resolve(skill.path);
|
|
496
|
+
if (pluginGroupings.has(resolvedPath)) skill.pluginName = pluginGroupings.get(resolvedPath);
|
|
497
|
+
return skill;
|
|
498
|
+
};
|
|
478
499
|
if (await hasSkillMd(searchPath)) {
|
|
479
|
-
|
|
500
|
+
let skill = await parseSkillMd(join(searchPath, "SKILL.md"), options);
|
|
480
501
|
if (skill) {
|
|
502
|
+
skill = enhanceSkill(skill);
|
|
481
503
|
skills.push(skill);
|
|
482
504
|
seenNames.add(skill.name);
|
|
483
505
|
if (!options?.fullDepth) return skills;
|
|
@@ -520,8 +542,9 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
520
542
|
for (const entry of entries) if (entry.isDirectory()) {
|
|
521
543
|
const skillDir = join(dir, entry.name);
|
|
522
544
|
if (await hasSkillMd(skillDir)) {
|
|
523
|
-
|
|
545
|
+
let skill = await parseSkillMd(join(skillDir, "SKILL.md"), options);
|
|
524
546
|
if (skill && !seenNames.has(skill.name)) {
|
|
547
|
+
skill = enhanceSkill(skill);
|
|
525
548
|
skills.push(skill);
|
|
526
549
|
seenNames.add(skill.name);
|
|
527
550
|
}
|
|
@@ -531,8 +554,9 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
531
554
|
if (skills.length === 0 || options?.fullDepth) {
|
|
532
555
|
const allSkillDirs = await findSkillDirs(searchPath);
|
|
533
556
|
for (const skillDir of allSkillDirs) {
|
|
534
|
-
|
|
557
|
+
let skill = await parseSkillMd(join(skillDir, "SKILL.md"), options);
|
|
535
558
|
if (skill && !seenNames.has(skill.name)) {
|
|
559
|
+
skill = enhanceSkill(skill);
|
|
536
560
|
skills.push(skill);
|
|
537
561
|
seenNames.add(skill.name);
|
|
538
562
|
}
|
|
@@ -610,8 +634,8 @@ const agents = {
|
|
|
610
634
|
cline: {
|
|
611
635
|
name: "cline",
|
|
612
636
|
displayName: "Cline",
|
|
613
|
-
skillsDir: ".
|
|
614
|
-
globalSkillsDir: join(home, ".
|
|
637
|
+
skillsDir: ".agents/skills",
|
|
638
|
+
globalSkillsDir: join(home, ".agents", "skills"),
|
|
615
639
|
detectInstalled: async () => {
|
|
616
640
|
return existsSync(join(home, ".cline"));
|
|
617
641
|
}
|
|
@@ -1140,78 +1164,6 @@ function getCanonicalPath(skillName, options = {}) {
|
|
|
1140
1164
|
if (!isPathSafe(canonicalBase, canonicalPath)) throw new Error("Invalid skill name: potential path traversal detected");
|
|
1141
1165
|
return canonicalPath;
|
|
1142
1166
|
}
|
|
1143
|
-
async function installRemoteSkillForAgent(skill, agentType, options = {}) {
|
|
1144
|
-
const agent = agents[agentType];
|
|
1145
|
-
const isGlobal = options.global ?? false;
|
|
1146
|
-
const cwd = options.cwd || process.cwd();
|
|
1147
|
-
const installMode = options.mode ?? "symlink";
|
|
1148
|
-
if (isGlobal && agent.globalSkillsDir === void 0) return {
|
|
1149
|
-
success: false,
|
|
1150
|
-
path: "",
|
|
1151
|
-
mode: installMode,
|
|
1152
|
-
error: `${agent.displayName} does not support global skill installation`
|
|
1153
|
-
};
|
|
1154
|
-
const skillName = sanitizeName(skill.installName);
|
|
1155
|
-
const canonicalBase = getCanonicalSkillsDir(isGlobal, cwd);
|
|
1156
|
-
const canonicalDir = join(canonicalBase, skillName);
|
|
1157
|
-
const agentBase = getAgentBaseDir(agentType, isGlobal, cwd);
|
|
1158
|
-
const agentDir = join(agentBase, skillName);
|
|
1159
|
-
if (!isPathSafe(canonicalBase, canonicalDir)) return {
|
|
1160
|
-
success: false,
|
|
1161
|
-
path: agentDir,
|
|
1162
|
-
mode: installMode,
|
|
1163
|
-
error: "Invalid skill name: potential path traversal detected"
|
|
1164
|
-
};
|
|
1165
|
-
if (!isPathSafe(agentBase, agentDir)) return {
|
|
1166
|
-
success: false,
|
|
1167
|
-
path: agentDir,
|
|
1168
|
-
mode: installMode,
|
|
1169
|
-
error: "Invalid skill name: potential path traversal detected"
|
|
1170
|
-
};
|
|
1171
|
-
try {
|
|
1172
|
-
if (installMode === "copy") {
|
|
1173
|
-
await cleanAndCreateDirectory(agentDir);
|
|
1174
|
-
await writeFile(join(agentDir, "SKILL.md"), skill.content, "utf-8");
|
|
1175
|
-
return {
|
|
1176
|
-
success: true,
|
|
1177
|
-
path: agentDir,
|
|
1178
|
-
mode: "copy"
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
await cleanAndCreateDirectory(canonicalDir);
|
|
1182
|
-
await writeFile(join(canonicalDir, "SKILL.md"), skill.content, "utf-8");
|
|
1183
|
-
if (isGlobal && isUniversalAgent(agentType)) return {
|
|
1184
|
-
success: true,
|
|
1185
|
-
path: canonicalDir,
|
|
1186
|
-
canonicalPath: canonicalDir,
|
|
1187
|
-
mode: "symlink"
|
|
1188
|
-
};
|
|
1189
|
-
if (!await createSymlink(canonicalDir, agentDir)) {
|
|
1190
|
-
await cleanAndCreateDirectory(agentDir);
|
|
1191
|
-
await writeFile(join(agentDir, "SKILL.md"), skill.content, "utf-8");
|
|
1192
|
-
return {
|
|
1193
|
-
success: true,
|
|
1194
|
-
path: agentDir,
|
|
1195
|
-
canonicalPath: canonicalDir,
|
|
1196
|
-
mode: "symlink",
|
|
1197
|
-
symlinkFailed: true
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
return {
|
|
1201
|
-
success: true,
|
|
1202
|
-
path: agentDir,
|
|
1203
|
-
canonicalPath: canonicalDir,
|
|
1204
|
-
mode: "symlink"
|
|
1205
|
-
};
|
|
1206
|
-
} catch (error) {
|
|
1207
|
-
return {
|
|
1208
|
-
success: false,
|
|
1209
|
-
path: agentDir,
|
|
1210
|
-
mode: installMode,
|
|
1211
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
1167
|
async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
1216
1168
|
const agent = agents[agentType];
|
|
1217
1169
|
const isGlobal = options.global ?? false;
|
|
@@ -1456,108 +1408,7 @@ var ProviderRegistryImpl = class {
|
|
|
1456
1408
|
return [...this.providers];
|
|
1457
1409
|
}
|
|
1458
1410
|
};
|
|
1459
|
-
|
|
1460
|
-
function registerProvider(provider) {
|
|
1461
|
-
registry.register(provider);
|
|
1462
|
-
}
|
|
1463
|
-
function findProvider(url) {
|
|
1464
|
-
return registry.findProvider(url);
|
|
1465
|
-
}
|
|
1466
|
-
var MintlifyProvider = class {
|
|
1467
|
-
id = "mintlify";
|
|
1468
|
-
displayName = "Mintlify";
|
|
1469
|
-
match(url) {
|
|
1470
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) return { matches: false };
|
|
1471
|
-
if (!url.toLowerCase().endsWith("/skill.md")) return { matches: false };
|
|
1472
|
-
if (url.includes("github.com") || url.includes("gitlab.com")) return { matches: false };
|
|
1473
|
-
if (url.includes("huggingface.co")) return { matches: false };
|
|
1474
|
-
return { matches: true };
|
|
1475
|
-
}
|
|
1476
|
-
async fetchSkill(url) {
|
|
1477
|
-
try {
|
|
1478
|
-
const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
1479
|
-
if (!response.ok) return null;
|
|
1480
|
-
const content = await response.text();
|
|
1481
|
-
const { data } = (0, import_gray_matter.default)(content);
|
|
1482
|
-
const mintlifySite = data.metadata?.["mintlify-proj"];
|
|
1483
|
-
if (!mintlifySite) return null;
|
|
1484
|
-
if (!data.name || !data.description) return null;
|
|
1485
|
-
return {
|
|
1486
|
-
name: data.name,
|
|
1487
|
-
description: data.description,
|
|
1488
|
-
content,
|
|
1489
|
-
installName: mintlifySite,
|
|
1490
|
-
sourceUrl: url,
|
|
1491
|
-
metadata: data.metadata
|
|
1492
|
-
};
|
|
1493
|
-
} catch {
|
|
1494
|
-
return null;
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
toRawUrl(url) {
|
|
1498
|
-
return url;
|
|
1499
|
-
}
|
|
1500
|
-
getSourceIdentifier(url) {
|
|
1501
|
-
return "mintlify/com";
|
|
1502
|
-
}
|
|
1503
|
-
};
|
|
1504
|
-
const mintlifyProvider = new MintlifyProvider();
|
|
1505
|
-
var HuggingFaceProvider = class {
|
|
1506
|
-
id = "huggingface";
|
|
1507
|
-
displayName = "HuggingFace";
|
|
1508
|
-
HOST = "huggingface.co";
|
|
1509
|
-
match(url) {
|
|
1510
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) return { matches: false };
|
|
1511
|
-
try {
|
|
1512
|
-
if (new URL(url).hostname !== this.HOST) return { matches: false };
|
|
1513
|
-
} catch {
|
|
1514
|
-
return { matches: false };
|
|
1515
|
-
}
|
|
1516
|
-
if (!url.toLowerCase().endsWith("/skill.md")) return { matches: false };
|
|
1517
|
-
if (!url.includes("/spaces/")) return { matches: false };
|
|
1518
|
-
return { matches: true };
|
|
1519
|
-
}
|
|
1520
|
-
async fetchSkill(url) {
|
|
1521
|
-
try {
|
|
1522
|
-
const rawUrl = this.toRawUrl(url);
|
|
1523
|
-
const response = await fetch(rawUrl, { signal: AbortSignal.timeout(3e4) });
|
|
1524
|
-
if (!response.ok) return null;
|
|
1525
|
-
const content = await response.text();
|
|
1526
|
-
const { data } = (0, import_gray_matter.default)(content);
|
|
1527
|
-
if (!data.name || !data.description) return null;
|
|
1528
|
-
const parsed = this.parseUrl(url);
|
|
1529
|
-
if (!parsed) return null;
|
|
1530
|
-
const installName = data.metadata?.["install-name"] || parsed.repo;
|
|
1531
|
-
return {
|
|
1532
|
-
name: data.name,
|
|
1533
|
-
description: data.description,
|
|
1534
|
-
content,
|
|
1535
|
-
installName,
|
|
1536
|
-
sourceUrl: url,
|
|
1537
|
-
metadata: data.metadata
|
|
1538
|
-
};
|
|
1539
|
-
} catch {
|
|
1540
|
-
return null;
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
toRawUrl(url) {
|
|
1544
|
-
return url.replace("/blob/", "/raw/");
|
|
1545
|
-
}
|
|
1546
|
-
getSourceIdentifier(url) {
|
|
1547
|
-
const parsed = this.parseUrl(url);
|
|
1548
|
-
if (!parsed) return "huggingface/unknown";
|
|
1549
|
-
return `huggingface/${parsed.owner}/${parsed.repo}`;
|
|
1550
|
-
}
|
|
1551
|
-
parseUrl(url) {
|
|
1552
|
-
const match = url.match(/\/spaces\/([^/]+)\/([^/]+)/);
|
|
1553
|
-
if (!match || !match[1] || !match[2]) return null;
|
|
1554
|
-
return {
|
|
1555
|
-
owner: match[1],
|
|
1556
|
-
repo: match[2]
|
|
1557
|
-
};
|
|
1558
|
-
}
|
|
1559
|
-
};
|
|
1560
|
-
const huggingFaceProvider = new HuggingFaceProvider();
|
|
1411
|
+
new ProviderRegistryImpl();
|
|
1561
1412
|
var WellKnownProvider = class {
|
|
1562
1413
|
id = "well-known";
|
|
1563
1414
|
displayName = "Well-Known Skills";
|
|
@@ -1714,15 +1565,9 @@ var WellKnownProvider = class {
|
|
|
1714
1565
|
}
|
|
1715
1566
|
getSourceIdentifier(url) {
|
|
1716
1567
|
try {
|
|
1717
|
-
|
|
1718
|
-
const hostParts = parsed.hostname.split(".");
|
|
1719
|
-
if (hostParts.length >= 2) {
|
|
1720
|
-
const tld = hostParts[hostParts.length - 1];
|
|
1721
|
-
return `${hostParts[hostParts.length - 2]}/${tld}`;
|
|
1722
|
-
}
|
|
1723
|
-
return parsed.hostname.replace(".", "/");
|
|
1568
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
1724
1569
|
} catch {
|
|
1725
|
-
return "unknown
|
|
1570
|
+
return "unknown";
|
|
1726
1571
|
}
|
|
1727
1572
|
}
|
|
1728
1573
|
async hasSkillsIndex(url) {
|
|
@@ -1730,28 +1575,6 @@ var WellKnownProvider = class {
|
|
|
1730
1575
|
}
|
|
1731
1576
|
};
|
|
1732
1577
|
const wellKnownProvider = new WellKnownProvider();
|
|
1733
|
-
registerProvider(mintlifyProvider);
|
|
1734
|
-
registerProvider(huggingFaceProvider);
|
|
1735
|
-
async function fetchMintlifySkill(url) {
|
|
1736
|
-
try {
|
|
1737
|
-
const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
1738
|
-
if (!response.ok) return null;
|
|
1739
|
-
const content = await response.text();
|
|
1740
|
-
const { data } = (0, import_gray_matter.default)(content);
|
|
1741
|
-
const mintlifySite = data.metadata?.["mintlify-proj"];
|
|
1742
|
-
if (!mintlifySite) return null;
|
|
1743
|
-
if (!data.name || !data.description) return null;
|
|
1744
|
-
return {
|
|
1745
|
-
name: data.name,
|
|
1746
|
-
description: data.description,
|
|
1747
|
-
content,
|
|
1748
|
-
mintlifySite,
|
|
1749
|
-
sourceUrl: url
|
|
1750
|
-
};
|
|
1751
|
-
} catch {
|
|
1752
|
-
return null;
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
1578
|
const AGENTS_DIR$1 = ".agents";
|
|
1756
1579
|
const LOCK_FILE$1 = ".skill-lock.json";
|
|
1757
1580
|
const CURRENT_VERSION$1 = 3;
|
|
@@ -1835,6 +1658,9 @@ async function removeSkillFromLock(skillName) {
|
|
|
1835
1658
|
async function getSkillFromLock(skillName) {
|
|
1836
1659
|
return (await readSkillLock$1()).skills[skillName] ?? null;
|
|
1837
1660
|
}
|
|
1661
|
+
async function getAllLockedSkills() {
|
|
1662
|
+
return (await readSkillLock$1()).skills;
|
|
1663
|
+
}
|
|
1838
1664
|
function createEmptyLockFile() {
|
|
1839
1665
|
return {
|
|
1840
1666
|
version: CURRENT_VERSION$1,
|
|
@@ -1925,7 +1751,7 @@ function createEmptyLocalLock() {
|
|
|
1925
1751
|
skills: {}
|
|
1926
1752
|
};
|
|
1927
1753
|
}
|
|
1928
|
-
var version$1 = "1.4.
|
|
1754
|
+
var version$1 = "1.4.3";
|
|
1929
1755
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
1930
1756
|
async function isSourcePrivate(source) {
|
|
1931
1757
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2091,232 +1917,6 @@ async function selectAgentsInteractive(options) {
|
|
|
2091
1917
|
return selected;
|
|
2092
1918
|
}
|
|
2093
1919
|
setVersion(version$1);
|
|
2094
|
-
async function handleRemoteSkill(source, url, options, spinner) {
|
|
2095
|
-
const provider = findProvider(url);
|
|
2096
|
-
if (!provider) {
|
|
2097
|
-
await handleDirectUrlSkillLegacy(source, url, options, spinner);
|
|
2098
|
-
return;
|
|
2099
|
-
}
|
|
2100
|
-
spinner.start(`Fetching skill.md from ${provider.displayName}...`);
|
|
2101
|
-
const providerSkill = await provider.fetchSkill(url);
|
|
2102
|
-
if (!providerSkill) {
|
|
2103
|
-
spinner.stop(import_picocolors.default.red("Invalid skill"));
|
|
2104
|
-
Se(import_picocolors.default.red("Could not fetch skill.md or missing required frontmatter (name, description)."));
|
|
2105
|
-
process.exit(1);
|
|
2106
|
-
}
|
|
2107
|
-
const remoteSkill = {
|
|
2108
|
-
name: providerSkill.name,
|
|
2109
|
-
description: providerSkill.description,
|
|
2110
|
-
content: providerSkill.content,
|
|
2111
|
-
installName: providerSkill.installName,
|
|
2112
|
-
sourceUrl: providerSkill.sourceUrl,
|
|
2113
|
-
providerId: provider.id,
|
|
2114
|
-
sourceIdentifier: provider.getSourceIdentifier(url),
|
|
2115
|
-
metadata: providerSkill.metadata
|
|
2116
|
-
};
|
|
2117
|
-
spinner.stop(`Found skill: ${import_picocolors.default.cyan(remoteSkill.installName)}`);
|
|
2118
|
-
M.info(`Skill: ${import_picocolors.default.cyan(remoteSkill.name)}`);
|
|
2119
|
-
M.message(import_picocolors.default.dim(remoteSkill.description));
|
|
2120
|
-
M.message(import_picocolors.default.dim(`Source: ${remoteSkill.sourceIdentifier}`));
|
|
2121
|
-
if (options.list) {
|
|
2122
|
-
console.log();
|
|
2123
|
-
M.step(import_picocolors.default.bold("Skill Details"));
|
|
2124
|
-
M.message(` ${import_picocolors.default.cyan("Name:")} ${remoteSkill.name}`);
|
|
2125
|
-
M.message(` ${import_picocolors.default.cyan("Install as:")} ${remoteSkill.installName}`);
|
|
2126
|
-
M.message(` ${import_picocolors.default.cyan("Provider:")} ${provider.displayName}`);
|
|
2127
|
-
M.message(` ${import_picocolors.default.cyan("Description:")} ${remoteSkill.description}`);
|
|
2128
|
-
console.log();
|
|
2129
|
-
Se("Run without --list to install");
|
|
2130
|
-
process.exit(0);
|
|
2131
|
-
}
|
|
2132
|
-
let targetAgents;
|
|
2133
|
-
const validAgents = Object.keys(agents);
|
|
2134
|
-
const universalAgents = getUniversalAgents();
|
|
2135
|
-
if (options.agent?.includes("*")) {
|
|
2136
|
-
targetAgents = validAgents;
|
|
2137
|
-
M.info(`Installing to all ${targetAgents.length} agents`);
|
|
2138
|
-
} else if (options.agent && options.agent.length > 0) {
|
|
2139
|
-
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
2140
|
-
if (invalidAgents.length > 0) {
|
|
2141
|
-
M.error(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
2142
|
-
M.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
2143
|
-
process.exit(1);
|
|
2144
|
-
}
|
|
2145
|
-
targetAgents = options.agent;
|
|
2146
|
-
} else {
|
|
2147
|
-
spinner.start("Loading agents...");
|
|
2148
|
-
const installedAgents = await detectInstalledAgents();
|
|
2149
|
-
const totalAgents = Object.keys(agents).length;
|
|
2150
|
-
spinner.stop(`${totalAgents} agents`);
|
|
2151
|
-
if (installedAgents.length === 0) if (options.yes) {
|
|
2152
|
-
targetAgents = universalAgents;
|
|
2153
|
-
M.info(`Installing to universal agents`);
|
|
2154
|
-
} else {
|
|
2155
|
-
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2156
|
-
if (pD(selected)) {
|
|
2157
|
-
xe("Installation cancelled");
|
|
2158
|
-
process.exit(0);
|
|
2159
|
-
}
|
|
2160
|
-
targetAgents = selected;
|
|
2161
|
-
}
|
|
2162
|
-
else if (installedAgents.length === 1 || options.yes) {
|
|
2163
|
-
targetAgents = ensureUniversalAgents(installedAgents);
|
|
2164
|
-
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
2165
|
-
if (symlinked.length > 0) M.info(`Installing to: ${import_picocolors.default.green("universal")} + ${symlinked.map((a) => import_picocolors.default.cyan(a)).join(", ")}`);
|
|
2166
|
-
else M.info(`Installing to: ${import_picocolors.default.green("universal agents")}`);
|
|
2167
|
-
} else {
|
|
2168
|
-
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2169
|
-
if (pD(selected)) {
|
|
2170
|
-
xe("Installation cancelled");
|
|
2171
|
-
process.exit(0);
|
|
2172
|
-
}
|
|
2173
|
-
targetAgents = selected;
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
let installGlobally = options.global ?? false;
|
|
2177
|
-
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
2178
|
-
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
2179
|
-
const scope = await ve({
|
|
2180
|
-
message: "Installation scope",
|
|
2181
|
-
options: [{
|
|
2182
|
-
value: false,
|
|
2183
|
-
label: "Project",
|
|
2184
|
-
hint: "Install in current directory (committed with your project)"
|
|
2185
|
-
}, {
|
|
2186
|
-
value: true,
|
|
2187
|
-
label: "Global",
|
|
2188
|
-
hint: "Install in home directory (available across all projects)"
|
|
2189
|
-
}]
|
|
2190
|
-
});
|
|
2191
|
-
if (pD(scope)) {
|
|
2192
|
-
xe("Installation cancelled");
|
|
2193
|
-
process.exit(0);
|
|
2194
|
-
}
|
|
2195
|
-
installGlobally = scope;
|
|
2196
|
-
}
|
|
2197
|
-
let installMode = options.copy ? "copy" : "symlink";
|
|
2198
|
-
if (!options.copy && !options.yes) {
|
|
2199
|
-
const modeChoice = await ve({
|
|
2200
|
-
message: "Installation method",
|
|
2201
|
-
options: [{
|
|
2202
|
-
value: "symlink",
|
|
2203
|
-
label: "Symlink (Recommended)",
|
|
2204
|
-
hint: "Single source of truth, easy updates"
|
|
2205
|
-
}, {
|
|
2206
|
-
value: "copy",
|
|
2207
|
-
label: "Copy to all agents",
|
|
2208
|
-
hint: "Independent copies for each agent"
|
|
2209
|
-
}]
|
|
2210
|
-
});
|
|
2211
|
-
if (pD(modeChoice)) {
|
|
2212
|
-
xe("Installation cancelled");
|
|
2213
|
-
process.exit(0);
|
|
2214
|
-
}
|
|
2215
|
-
installMode = modeChoice;
|
|
2216
|
-
}
|
|
2217
|
-
const cwd = process.cwd();
|
|
2218
|
-
const overwriteChecks = await Promise.all(targetAgents.map(async (agent) => ({
|
|
2219
|
-
agent,
|
|
2220
|
-
installed: await isSkillInstalled(remoteSkill.installName, agent, { global: installGlobally })
|
|
2221
|
-
})));
|
|
2222
|
-
const overwriteStatus = new Map(overwriteChecks.map(({ agent, installed }) => [agent, installed]));
|
|
2223
|
-
const summaryLines = [];
|
|
2224
|
-
const shortCanonical = shortenPath$2(getCanonicalPath(remoteSkill.installName, { global: installGlobally }), cwd);
|
|
2225
|
-
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2226
|
-
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2227
|
-
const overwriteAgents = targetAgents.filter((a) => overwriteStatus.get(a)).map((a) => agents[a].displayName);
|
|
2228
|
-
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
2229
|
-
console.log();
|
|
2230
|
-
Me(summaryLines.join("\n"), "Installation Summary");
|
|
2231
|
-
if (!options.yes) {
|
|
2232
|
-
const confirmed = await ye({ message: "Proceed with installation?" });
|
|
2233
|
-
if (pD(confirmed) || !confirmed) {
|
|
2234
|
-
xe("Installation cancelled");
|
|
2235
|
-
process.exit(0);
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
spinner.start("Installing skill...");
|
|
2239
|
-
const results = [];
|
|
2240
|
-
for (const agent of targetAgents) {
|
|
2241
|
-
const result = await installRemoteSkillForAgent(remoteSkill, agent, {
|
|
2242
|
-
global: installGlobally,
|
|
2243
|
-
mode: installMode
|
|
2244
|
-
});
|
|
2245
|
-
results.push({
|
|
2246
|
-
skill: remoteSkill.installName,
|
|
2247
|
-
agent: agents[agent].displayName,
|
|
2248
|
-
...result
|
|
2249
|
-
});
|
|
2250
|
-
}
|
|
2251
|
-
spinner.stop("Installation complete");
|
|
2252
|
-
console.log();
|
|
2253
|
-
const successful = results.filter((r) => r.success);
|
|
2254
|
-
const failed = results.filter((r) => !r.success);
|
|
2255
|
-
if (await isSourcePrivate(remoteSkill.sourceIdentifier) !== true) track({
|
|
2256
|
-
event: "install",
|
|
2257
|
-
source: remoteSkill.sourceIdentifier,
|
|
2258
|
-
skills: remoteSkill.installName,
|
|
2259
|
-
agents: targetAgents.join(","),
|
|
2260
|
-
...installGlobally && { global: "1" },
|
|
2261
|
-
skillFiles: JSON.stringify({ [remoteSkill.installName]: url }),
|
|
2262
|
-
sourceType: remoteSkill.providerId
|
|
2263
|
-
});
|
|
2264
|
-
if (successful.length > 0 && installGlobally) try {
|
|
2265
|
-
let skillFolderHash = "";
|
|
2266
|
-
if (remoteSkill.providerId === "github") {
|
|
2267
|
-
const hash = await fetchSkillFolderHash(remoteSkill.sourceIdentifier, url);
|
|
2268
|
-
if (hash) skillFolderHash = hash;
|
|
2269
|
-
}
|
|
2270
|
-
await addSkillToLock(remoteSkill.installName, {
|
|
2271
|
-
source: remoteSkill.sourceIdentifier,
|
|
2272
|
-
sourceType: remoteSkill.providerId,
|
|
2273
|
-
sourceUrl: url,
|
|
2274
|
-
skillFolderHash
|
|
2275
|
-
});
|
|
2276
|
-
} catch {}
|
|
2277
|
-
if (successful.length > 0 && !installGlobally) try {
|
|
2278
|
-
const firstResult = successful[0];
|
|
2279
|
-
const computedHash = await computeSkillFolderHash(firstResult.canonicalPath || firstResult.path);
|
|
2280
|
-
await addSkillToLocalLock(remoteSkill.installName, {
|
|
2281
|
-
source: remoteSkill.sourceIdentifier,
|
|
2282
|
-
sourceType: remoteSkill.providerId,
|
|
2283
|
-
computedHash
|
|
2284
|
-
}, cwd);
|
|
2285
|
-
} catch {}
|
|
2286
|
-
if (successful.length > 0) {
|
|
2287
|
-
const resultLines = [];
|
|
2288
|
-
const firstResult = successful[0];
|
|
2289
|
-
if (firstResult.mode === "copy") {
|
|
2290
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${remoteSkill.installName} ${import_picocolors.default.dim("(copied)")}`);
|
|
2291
|
-
for (const r of successful) {
|
|
2292
|
-
const shortPath = shortenPath$2(r.path, cwd);
|
|
2293
|
-
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
2294
|
-
}
|
|
2295
|
-
} else {
|
|
2296
|
-
if (firstResult.canonicalPath) {
|
|
2297
|
-
const shortPath = shortenPath$2(firstResult.canonicalPath, cwd);
|
|
2298
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2299
|
-
} else resultLines.push(`${import_picocolors.default.green("✓")} ${remoteSkill.installName}`);
|
|
2300
|
-
resultLines.push(...buildResultLines(successful, targetAgents));
|
|
2301
|
-
}
|
|
2302
|
-
const title = import_picocolors.default.green("Installed 1 skill");
|
|
2303
|
-
Me(resultLines.join("\n"), title);
|
|
2304
|
-
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2305
|
-
if (symlinkFailures.length > 0) {
|
|
2306
|
-
const copiedAgentNames = symlinkFailures.map((r) => r.agent);
|
|
2307
|
-
M.warn(import_picocolors.default.yellow(`Symlinks failed for: ${formatList$1(copiedAgentNames)}`));
|
|
2308
|
-
M.message(import_picocolors.default.dim(" Files were copied instead. On Windows, enable Developer Mode for symlink support."));
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
if (failed.length > 0) {
|
|
2312
|
-
console.log();
|
|
2313
|
-
M.error(import_picocolors.default.red(`Failed to install ${failed.length}`));
|
|
2314
|
-
for (const r of failed) M.message(` ${import_picocolors.default.red("✗")} ${r.skill} → ${r.agent}: ${import_picocolors.default.dim(r.error)}`);
|
|
2315
|
-
}
|
|
2316
|
-
console.log();
|
|
2317
|
-
Se(import_picocolors.default.green("Done!") + import_picocolors.default.dim(" Review skills before use; they run with full agent permissions."));
|
|
2318
|
-
await promptForFindSkills(options, targetAgents);
|
|
2319
|
-
}
|
|
2320
1920
|
async function handleWellKnownSkills(source, url, options, spinner) {
|
|
2321
1921
|
spinner.start("Discovering skills from well-known endpoint...");
|
|
2322
1922
|
const skills = await wellKnownProvider.fetchAllSkills(url);
|
|
@@ -2355,7 +1955,6 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2355
1955
|
for (const s of skills) M.message(` - ${s.installName}`);
|
|
2356
1956
|
process.exit(1);
|
|
2357
1957
|
}
|
|
2358
|
-
M.info(`Selected ${selectedSkills.length} skill${selectedSkills.length !== 1 ? "s" : ""}: ${selectedSkills.map((s) => import_picocolors.default.cyan(s.installName)).join(", ")}`);
|
|
2359
1958
|
} else if (skills.length === 1) {
|
|
2360
1959
|
selectedSkills = skills;
|
|
2361
1960
|
const firstSkill = skills[0];
|
|
@@ -2598,188 +2197,6 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2598
2197
|
Se(import_picocolors.default.green("Done!") + import_picocolors.default.dim(" Review skills before use; they run with full agent permissions."));
|
|
2599
2198
|
await promptForFindSkills(options, targetAgents);
|
|
2600
2199
|
}
|
|
2601
|
-
async function handleDirectUrlSkillLegacy(source, url, options, spinner) {
|
|
2602
|
-
spinner.start("Fetching skill.md...");
|
|
2603
|
-
const mintlifySkill = await fetchMintlifySkill(url);
|
|
2604
|
-
if (!mintlifySkill) {
|
|
2605
|
-
spinner.stop(import_picocolors.default.red("Invalid skill"));
|
|
2606
|
-
Se(import_picocolors.default.red("Could not fetch skill.md or missing required frontmatter (name, description, mintlify-proj)."));
|
|
2607
|
-
process.exit(1);
|
|
2608
|
-
}
|
|
2609
|
-
const remoteSkill = {
|
|
2610
|
-
name: mintlifySkill.name,
|
|
2611
|
-
description: mintlifySkill.description,
|
|
2612
|
-
content: mintlifySkill.content,
|
|
2613
|
-
installName: mintlifySkill.mintlifySite,
|
|
2614
|
-
sourceUrl: mintlifySkill.sourceUrl,
|
|
2615
|
-
providerId: "mintlify",
|
|
2616
|
-
sourceIdentifier: "mintlify/com"
|
|
2617
|
-
};
|
|
2618
|
-
spinner.stop(`Found skill: ${import_picocolors.default.cyan(remoteSkill.installName)}`);
|
|
2619
|
-
M.info(`Skill: ${import_picocolors.default.cyan(remoteSkill.name)}`);
|
|
2620
|
-
M.message(import_picocolors.default.dim(remoteSkill.description));
|
|
2621
|
-
if (options.list) {
|
|
2622
|
-
console.log();
|
|
2623
|
-
M.step(import_picocolors.default.bold("Skill Details"));
|
|
2624
|
-
M.message(` ${import_picocolors.default.cyan("Name:")} ${remoteSkill.name}`);
|
|
2625
|
-
M.message(` ${import_picocolors.default.cyan("Site:")} ${remoteSkill.installName}`);
|
|
2626
|
-
M.message(` ${import_picocolors.default.cyan("Description:")} ${remoteSkill.description}`);
|
|
2627
|
-
console.log();
|
|
2628
|
-
Se("Run without --list to install");
|
|
2629
|
-
process.exit(0);
|
|
2630
|
-
}
|
|
2631
|
-
let targetAgents;
|
|
2632
|
-
const validAgents = Object.keys(agents);
|
|
2633
|
-
if (options.agent?.includes("*")) {
|
|
2634
|
-
targetAgents = validAgents;
|
|
2635
|
-
M.info(`Installing to all ${targetAgents.length} agents`);
|
|
2636
|
-
} else if (options.agent && options.agent.length > 0) {
|
|
2637
|
-
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
2638
|
-
if (invalidAgents.length > 0) {
|
|
2639
|
-
M.error(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
2640
|
-
M.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
2641
|
-
process.exit(1);
|
|
2642
|
-
}
|
|
2643
|
-
targetAgents = options.agent;
|
|
2644
|
-
} else {
|
|
2645
|
-
spinner.start("Loading agents...");
|
|
2646
|
-
const installedAgents = await detectInstalledAgents();
|
|
2647
|
-
const totalAgents = Object.keys(agents).length;
|
|
2648
|
-
spinner.stop(`${totalAgents} agents`);
|
|
2649
|
-
if (installedAgents.length === 0) if (options.yes) {
|
|
2650
|
-
targetAgents = validAgents;
|
|
2651
|
-
M.info("Installing to all agents");
|
|
2652
|
-
} else {
|
|
2653
|
-
M.info("Select agents to install skills to");
|
|
2654
|
-
const selected = await promptForAgents("Which agents do you want to install to?", Object.entries(agents).map(([key, config]) => ({
|
|
2655
|
-
value: key,
|
|
2656
|
-
label: config.displayName
|
|
2657
|
-
})));
|
|
2658
|
-
if (pD(selected)) {
|
|
2659
|
-
xe("Installation cancelled");
|
|
2660
|
-
process.exit(0);
|
|
2661
|
-
}
|
|
2662
|
-
targetAgents = selected;
|
|
2663
|
-
}
|
|
2664
|
-
else if (installedAgents.length === 1 || options.yes) {
|
|
2665
|
-
targetAgents = ensureUniversalAgents(installedAgents);
|
|
2666
|
-
if (installedAgents.length === 1) {
|
|
2667
|
-
const firstAgent = installedAgents[0];
|
|
2668
|
-
M.info(`Installing to: ${import_picocolors.default.cyan(agents[firstAgent].displayName)}`);
|
|
2669
|
-
} else M.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
|
|
2670
|
-
} else {
|
|
2671
|
-
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2672
|
-
if (pD(selected)) {
|
|
2673
|
-
xe("Installation cancelled");
|
|
2674
|
-
process.exit(0);
|
|
2675
|
-
}
|
|
2676
|
-
targetAgents = selected;
|
|
2677
|
-
}
|
|
2678
|
-
}
|
|
2679
|
-
let installGlobally = options.global ?? false;
|
|
2680
|
-
const supportsGlobal = targetAgents.some((a) => agents[a].globalSkillsDir !== void 0);
|
|
2681
|
-
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
2682
|
-
const scope = await ve({
|
|
2683
|
-
message: "Installation scope",
|
|
2684
|
-
options: [{
|
|
2685
|
-
value: false,
|
|
2686
|
-
label: "Project",
|
|
2687
|
-
hint: "Install in current directory (committed with your project)"
|
|
2688
|
-
}, {
|
|
2689
|
-
value: true,
|
|
2690
|
-
label: "Global",
|
|
2691
|
-
hint: "Install in home directory (available across all projects)"
|
|
2692
|
-
}]
|
|
2693
|
-
});
|
|
2694
|
-
if (pD(scope)) {
|
|
2695
|
-
xe("Installation cancelled");
|
|
2696
|
-
process.exit(0);
|
|
2697
|
-
}
|
|
2698
|
-
installGlobally = scope;
|
|
2699
|
-
}
|
|
2700
|
-
const installMode = "symlink";
|
|
2701
|
-
const cwd = process.cwd();
|
|
2702
|
-
const overwriteChecks = await Promise.all(targetAgents.map(async (agent) => ({
|
|
2703
|
-
agent,
|
|
2704
|
-
installed: await isSkillInstalled(remoteSkill.installName, agent, { global: installGlobally })
|
|
2705
|
-
})));
|
|
2706
|
-
const overwriteStatus = new Map(overwriteChecks.map(({ agent, installed }) => [agent, installed]));
|
|
2707
|
-
const summaryLines = [];
|
|
2708
|
-
targetAgents.map((a) => agents[a].displayName);
|
|
2709
|
-
const shortCanonical = shortenPath$2(getCanonicalPath(remoteSkill.installName, { global: installGlobally }), cwd);
|
|
2710
|
-
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2711
|
-
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2712
|
-
const overwriteAgents = targetAgents.filter((a) => overwriteStatus.get(a)).map((a) => agents[a].displayName);
|
|
2713
|
-
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
2714
|
-
console.log();
|
|
2715
|
-
Me(summaryLines.join("\n"), "Installation Summary");
|
|
2716
|
-
if (!options.yes) {
|
|
2717
|
-
const confirmed = await ye({ message: "Proceed with installation?" });
|
|
2718
|
-
if (pD(confirmed) || !confirmed) {
|
|
2719
|
-
xe("Installation cancelled");
|
|
2720
|
-
process.exit(0);
|
|
2721
|
-
}
|
|
2722
|
-
}
|
|
2723
|
-
spinner.start("Installing skill...");
|
|
2724
|
-
const results = [];
|
|
2725
|
-
for (const agent of targetAgents) {
|
|
2726
|
-
const result = await installRemoteSkillForAgent(remoteSkill, agent, {
|
|
2727
|
-
global: installGlobally,
|
|
2728
|
-
mode: installMode
|
|
2729
|
-
});
|
|
2730
|
-
results.push({
|
|
2731
|
-
skill: remoteSkill.installName,
|
|
2732
|
-
agent: agents[agent].displayName,
|
|
2733
|
-
...result
|
|
2734
|
-
});
|
|
2735
|
-
}
|
|
2736
|
-
spinner.stop("Installation complete");
|
|
2737
|
-
console.log();
|
|
2738
|
-
const successful = results.filter((r) => r.success);
|
|
2739
|
-
const failed = results.filter((r) => !r.success);
|
|
2740
|
-
track({
|
|
2741
|
-
event: "install",
|
|
2742
|
-
source: "mintlify/com",
|
|
2743
|
-
skills: remoteSkill.installName,
|
|
2744
|
-
agents: targetAgents.join(","),
|
|
2745
|
-
...installGlobally && { global: "1" },
|
|
2746
|
-
skillFiles: JSON.stringify({ [remoteSkill.installName]: url }),
|
|
2747
|
-
sourceType: "mintlify"
|
|
2748
|
-
});
|
|
2749
|
-
if (successful.length > 0 && installGlobally) try {
|
|
2750
|
-
await addSkillToLock(remoteSkill.installName, {
|
|
2751
|
-
source: `mintlify/${remoteSkill.installName}`,
|
|
2752
|
-
sourceType: "mintlify",
|
|
2753
|
-
sourceUrl: url,
|
|
2754
|
-
skillFolderHash: ""
|
|
2755
|
-
});
|
|
2756
|
-
} catch {}
|
|
2757
|
-
if (successful.length > 0) {
|
|
2758
|
-
const resultLines = [];
|
|
2759
|
-
const firstResult = successful[0];
|
|
2760
|
-
if (firstResult.canonicalPath) {
|
|
2761
|
-
const shortPath = shortenPath$2(firstResult.canonicalPath, cwd);
|
|
2762
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2763
|
-
} else resultLines.push(`${import_picocolors.default.green("✓")} ${remoteSkill.installName}`);
|
|
2764
|
-
resultLines.push(...buildResultLines(successful, targetAgents));
|
|
2765
|
-
const title = import_picocolors.default.green("Installed 1 skill");
|
|
2766
|
-
Me(resultLines.join("\n"), title);
|
|
2767
|
-
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2768
|
-
if (symlinkFailures.length > 0) {
|
|
2769
|
-
const copiedAgentNames = symlinkFailures.map((r) => r.agent);
|
|
2770
|
-
M.warn(import_picocolors.default.yellow(`Symlinks failed for: ${formatList$1(copiedAgentNames)}`));
|
|
2771
|
-
M.message(import_picocolors.default.dim(" Files were copied instead. On Windows, enable Developer Mode for symlink support."));
|
|
2772
|
-
}
|
|
2773
|
-
}
|
|
2774
|
-
if (failed.length > 0) {
|
|
2775
|
-
console.log();
|
|
2776
|
-
M.error(import_picocolors.default.red(`Failed to install ${failed.length}`));
|
|
2777
|
-
for (const r of failed) M.message(` ${import_picocolors.default.red("✗")} ${r.skill} → ${r.agent}: ${import_picocolors.default.dim(r.error)}`);
|
|
2778
|
-
}
|
|
2779
|
-
console.log();
|
|
2780
|
-
Se(import_picocolors.default.green("Done!") + import_picocolors.default.dim(" Review skills before use; they run with full agent permissions."));
|
|
2781
|
-
await promptForFindSkills(options, targetAgents);
|
|
2782
|
-
}
|
|
2783
2200
|
async function runAdd(args, options = {}) {
|
|
2784
2201
|
const source = args[0];
|
|
2785
2202
|
let installTipShown = false;
|
|
@@ -2814,10 +2231,6 @@ async function runAdd(args, options = {}) {
|
|
|
2814
2231
|
spinner.start("Parsing source...");
|
|
2815
2232
|
const parsed = parseSource(source);
|
|
2816
2233
|
spinner.stop(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
|
|
2817
|
-
if (parsed.type === "direct-url") {
|
|
2818
|
-
await handleRemoteSkill(source, parsed.url, options, spinner);
|
|
2819
|
-
return;
|
|
2820
|
-
}
|
|
2821
2234
|
if (parsed.type === "well-known") {
|
|
2822
2235
|
await handleWellKnownSkills(source, parsed.url, options, spinner);
|
|
2823
2236
|
return;
|
|
@@ -2858,9 +2271,29 @@ async function runAdd(args, options = {}) {
|
|
|
2858
2271
|
if (options.list) {
|
|
2859
2272
|
console.log();
|
|
2860
2273
|
M.step(import_picocolors.default.bold("Available Skills"));
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2274
|
+
const groupedSkills = {};
|
|
2275
|
+
const ungroupedSkills = [];
|
|
2276
|
+
for (const skill of skills) if (skill.pluginName) {
|
|
2277
|
+
const group = skill.pluginName;
|
|
2278
|
+
if (!groupedSkills[group]) groupedSkills[group] = [];
|
|
2279
|
+
groupedSkills[group].push(skill);
|
|
2280
|
+
} else ungroupedSkills.push(skill);
|
|
2281
|
+
const sortedGroups = Object.keys(groupedSkills).sort();
|
|
2282
|
+
for (const group of sortedGroups) {
|
|
2283
|
+
const title = group.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2284
|
+
console.log(import_picocolors.default.bold(title));
|
|
2285
|
+
for (const skill of groupedSkills[group]) {
|
|
2286
|
+
M.message(` ${import_picocolors.default.cyan(getSkillDisplayName(skill))}`);
|
|
2287
|
+
M.message(` ${import_picocolors.default.dim(skill.description)}`);
|
|
2288
|
+
}
|
|
2289
|
+
console.log();
|
|
2290
|
+
}
|
|
2291
|
+
if (ungroupedSkills.length > 0) {
|
|
2292
|
+
if (sortedGroups.length > 0) console.log(import_picocolors.default.bold("General"));
|
|
2293
|
+
for (const skill of ungroupedSkills) {
|
|
2294
|
+
M.message(` ${import_picocolors.default.cyan(getSkillDisplayName(skill))}`);
|
|
2295
|
+
M.message(` ${import_picocolors.default.dim(skill.description)}`);
|
|
2296
|
+
}
|
|
2864
2297
|
}
|
|
2865
2298
|
console.log();
|
|
2866
2299
|
Se("Use --skill <name> to install specific skills");
|
|
@@ -2890,9 +2323,34 @@ async function runAdd(args, options = {}) {
|
|
|
2890
2323
|
selectedSkills = skills;
|
|
2891
2324
|
M.info(`Installing all ${skills.length} skills`);
|
|
2892
2325
|
} else {
|
|
2893
|
-
const
|
|
2326
|
+
const sortedSkills = [...skills].sort((a, b) => {
|
|
2327
|
+
if (a.pluginName && !b.pluginName) return -1;
|
|
2328
|
+
if (!a.pluginName && b.pluginName) return 1;
|
|
2329
|
+
if (a.pluginName && b.pluginName && a.pluginName !== b.pluginName) return a.pluginName.localeCompare(b.pluginName);
|
|
2330
|
+
return getSkillDisplayName(a).localeCompare(getSkillDisplayName(b));
|
|
2331
|
+
});
|
|
2332
|
+
const hasGroups = sortedSkills.some((s) => s.pluginName);
|
|
2333
|
+
let selected;
|
|
2334
|
+
if (hasGroups) {
|
|
2335
|
+
const kebabToTitle = (s) => s.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2336
|
+
const grouped = {};
|
|
2337
|
+
for (const s of sortedSkills) {
|
|
2338
|
+
const groupName = s.pluginName ? kebabToTitle(s.pluginName) : "Other";
|
|
2339
|
+
if (!grouped[groupName]) grouped[groupName] = [];
|
|
2340
|
+
grouped[groupName].push({
|
|
2341
|
+
value: s,
|
|
2342
|
+
label: getSkillDisplayName(s),
|
|
2343
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
2344
|
+
});
|
|
2345
|
+
}
|
|
2346
|
+
selected = await be({
|
|
2347
|
+
message: `Select skills to install ${import_picocolors.default.dim("(space to toggle)")}`,
|
|
2348
|
+
options: grouped,
|
|
2349
|
+
required: true
|
|
2350
|
+
});
|
|
2351
|
+
} else selected = await multiselect({
|
|
2894
2352
|
message: "Select skills to install",
|
|
2895
|
-
options:
|
|
2353
|
+
options: sortedSkills.map((s) => ({
|
|
2896
2354
|
value: s,
|
|
2897
2355
|
label: getSkillDisplayName(s),
|
|
2898
2356
|
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
@@ -3015,14 +2473,37 @@ async function runAdd(args, options = {}) {
|
|
|
3015
2473
|
if (!overwriteStatus.has(skillName)) overwriteStatus.set(skillName, /* @__PURE__ */ new Map());
|
|
3016
2474
|
overwriteStatus.get(skillName).set(agent, installed);
|
|
3017
2475
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
2476
|
+
const groupedSummary = {};
|
|
2477
|
+
const ungroupedSummary = [];
|
|
2478
|
+
for (const skill of selectedSkills) if (skill.pluginName) {
|
|
2479
|
+
const group = skill.pluginName;
|
|
2480
|
+
if (!groupedSummary[group]) groupedSummary[group] = [];
|
|
2481
|
+
groupedSummary[group].push(skill);
|
|
2482
|
+
} else ungroupedSummary.push(skill);
|
|
2483
|
+
const printSkillSummary = (skills) => {
|
|
2484
|
+
for (const skill of skills) {
|
|
2485
|
+
if (summaryLines.length > 0) summaryLines.push("");
|
|
2486
|
+
const shortCanonical = shortenPath$2(getCanonicalPath(skill.name, { global: installGlobally }), cwd);
|
|
2487
|
+
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2488
|
+
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2489
|
+
const skillOverwrites = overwriteStatus.get(skill.name);
|
|
2490
|
+
const overwriteAgents = targetAgents.filter((a) => skillOverwrites?.get(a)).map((a) => agents[a].displayName);
|
|
2491
|
+
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2494
|
+
const sortedGroups = Object.keys(groupedSummary).sort();
|
|
2495
|
+
for (const group of sortedGroups) {
|
|
2496
|
+
const title = group.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2497
|
+
summaryLines.push("");
|
|
2498
|
+
summaryLines.push(import_picocolors.default.bold(title));
|
|
2499
|
+
printSkillSummary(groupedSummary[group]);
|
|
2500
|
+
}
|
|
2501
|
+
if (ungroupedSummary.length > 0) {
|
|
2502
|
+
if (sortedGroups.length > 0) {
|
|
2503
|
+
summaryLines.push("");
|
|
2504
|
+
summaryLines.push(import_picocolors.default.bold("General"));
|
|
2505
|
+
}
|
|
2506
|
+
printSkillSummary(ungroupedSummary);
|
|
3026
2507
|
}
|
|
3027
2508
|
console.log();
|
|
3028
2509
|
Me(summaryLines.join("\n"), "Installation Summary");
|
|
@@ -3054,6 +2535,7 @@ async function runAdd(args, options = {}) {
|
|
|
3054
2535
|
results.push({
|
|
3055
2536
|
skill: getSkillDisplayName(skill),
|
|
3056
2537
|
agent: agents[agent].displayName,
|
|
2538
|
+
pluginName: skill.pluginName,
|
|
3057
2539
|
...result
|
|
3058
2540
|
});
|
|
3059
2541
|
}
|
|
@@ -3106,7 +2588,8 @@ async function runAdd(args, options = {}) {
|
|
|
3106
2588
|
sourceType: parsed.type,
|
|
3107
2589
|
sourceUrl: parsed.url,
|
|
3108
2590
|
skillPath: skillPathValue,
|
|
3109
|
-
skillFolderHash
|
|
2591
|
+
skillFolderHash,
|
|
2592
|
+
pluginName: skill.pluginName
|
|
3110
2593
|
});
|
|
3111
2594
|
} catch {}
|
|
3112
2595
|
}
|
|
@@ -3127,30 +2610,54 @@ async function runAdd(args, options = {}) {
|
|
|
3127
2610
|
}
|
|
3128
2611
|
if (successful.length > 0) {
|
|
3129
2612
|
const bySkill = /* @__PURE__ */ new Map();
|
|
2613
|
+
const groupedResults = {};
|
|
2614
|
+
const ungroupedResults = [];
|
|
3130
2615
|
for (const r of successful) {
|
|
3131
2616
|
const skillResults = bySkill.get(r.skill) || [];
|
|
3132
2617
|
skillResults.push(r);
|
|
3133
2618
|
bySkill.set(r.skill, skillResults);
|
|
2619
|
+
if (skillResults.length === 1) if (r.pluginName) {
|
|
2620
|
+
const group = r.pluginName;
|
|
2621
|
+
if (!groupedResults[group]) groupedResults[group] = [];
|
|
2622
|
+
groupedResults[group].push(r);
|
|
2623
|
+
} else ungroupedResults.push(r);
|
|
3134
2624
|
}
|
|
3135
2625
|
const skillCount = bySkill.size;
|
|
3136
2626
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
3137
2627
|
const copiedAgents = symlinkFailures.map((r) => r.agent);
|
|
3138
2628
|
const resultLines = [];
|
|
3139
|
-
|
|
3140
|
-
const
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
2629
|
+
const printSkillResults = (entries) => {
|
|
2630
|
+
for (const entry of entries) {
|
|
2631
|
+
const skillResults = bySkill.get(entry.skill) || [];
|
|
2632
|
+
const firstResult = skillResults[0];
|
|
2633
|
+
if (firstResult.mode === "copy") {
|
|
2634
|
+
resultLines.push(`${import_picocolors.default.green("✓")} ${entry.skill} ${import_picocolors.default.dim("(copied)")}`);
|
|
2635
|
+
for (const r of skillResults) {
|
|
2636
|
+
const shortPath = shortenPath$2(r.path, cwd);
|
|
2637
|
+
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
2638
|
+
}
|
|
2639
|
+
} else {
|
|
2640
|
+
if (firstResult.canonicalPath) {
|
|
2641
|
+
const shortPath = shortenPath$2(firstResult.canonicalPath, cwd);
|
|
2642
|
+
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2643
|
+
} else resultLines.push(`${import_picocolors.default.green("✓")} ${entry.skill}`);
|
|
2644
|
+
resultLines.push(...buildResultLines(skillResults, targetAgents));
|
|
3146
2645
|
}
|
|
3147
|
-
} else {
|
|
3148
|
-
if (firstResult.canonicalPath) {
|
|
3149
|
-
const shortPath = shortenPath$2(firstResult.canonicalPath, cwd);
|
|
3150
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
3151
|
-
} else resultLines.push(`${import_picocolors.default.green("✓")} ${skillName}`);
|
|
3152
|
-
resultLines.push(...buildResultLines(skillResults, targetAgents));
|
|
3153
2646
|
}
|
|
2647
|
+
};
|
|
2648
|
+
const sortedResultGroups = Object.keys(groupedResults).sort();
|
|
2649
|
+
for (const group of sortedResultGroups) {
|
|
2650
|
+
const title = group.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2651
|
+
resultLines.push("");
|
|
2652
|
+
resultLines.push(import_picocolors.default.bold(title));
|
|
2653
|
+
printSkillResults(groupedResults[group]);
|
|
2654
|
+
}
|
|
2655
|
+
if (ungroupedResults.length > 0) {
|
|
2656
|
+
if (sortedResultGroups.length > 0) {
|
|
2657
|
+
resultLines.push("");
|
|
2658
|
+
resultLines.push(import_picocolors.default.bold("General"));
|
|
2659
|
+
}
|
|
2660
|
+
printSkillResults(ungroupedResults);
|
|
3154
2661
|
}
|
|
3155
2662
|
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}`);
|
|
3156
2663
|
Me(resultLines.join("\n"), title);
|
|
@@ -3864,6 +3371,7 @@ async function runList(args) {
|
|
|
3864
3371
|
global: scope,
|
|
3865
3372
|
agentFilter
|
|
3866
3373
|
});
|
|
3374
|
+
const lockedSkills = await getAllLockedSkills();
|
|
3867
3375
|
const cwd = process.cwd();
|
|
3868
3376
|
const scopeLabel = scope ? "Global" : "Project";
|
|
3869
3377
|
if (installedSkills.length === 0) {
|
|
@@ -3872,17 +3380,44 @@ async function runList(args) {
|
|
|
3872
3380
|
else console.log(`${DIM$1}Try listing global skills with -g${RESET$1}`);
|
|
3873
3381
|
return;
|
|
3874
3382
|
}
|
|
3875
|
-
function printSkill(skill) {
|
|
3383
|
+
function printSkill(skill, indent = false) {
|
|
3384
|
+
const prefix = indent ? " " : "";
|
|
3876
3385
|
const shortPath = shortenPath(skill.canonicalPath, cwd);
|
|
3877
3386
|
const agentNames = skill.agents.map((a) => agents[a].displayName);
|
|
3878
3387
|
const agentInfo = skill.agents.length > 0 ? formatList(agentNames) : `${YELLOW}not linked${RESET$1}`;
|
|
3879
|
-
console.log(`${CYAN}${skill.name}${RESET$1} ${DIM$1}${shortPath}${RESET$1}`);
|
|
3880
|
-
console.log(
|
|
3388
|
+
console.log(`${prefix}${CYAN}${skill.name}${RESET$1} ${DIM$1}${shortPath}${RESET$1}`);
|
|
3389
|
+
console.log(`${prefix} ${DIM$1}Agents:${RESET$1} ${agentInfo}`);
|
|
3881
3390
|
}
|
|
3882
3391
|
console.log(`${BOLD$1}${scopeLabel} Skills${RESET$1}`);
|
|
3883
3392
|
console.log();
|
|
3884
|
-
|
|
3885
|
-
|
|
3393
|
+
const groupedSkills = {};
|
|
3394
|
+
const ungroupedSkills = [];
|
|
3395
|
+
for (const skill of installedSkills) {
|
|
3396
|
+
const lockEntry = lockedSkills[skill.name];
|
|
3397
|
+
if (lockEntry?.pluginName) {
|
|
3398
|
+
const group = lockEntry.pluginName;
|
|
3399
|
+
if (!groupedSkills[group]) groupedSkills[group] = [];
|
|
3400
|
+
groupedSkills[group].push(skill);
|
|
3401
|
+
} else ungroupedSkills.push(skill);
|
|
3402
|
+
}
|
|
3403
|
+
if (Object.keys(groupedSkills).length > 0) {
|
|
3404
|
+
const sortedGroups = Object.keys(groupedSkills).sort();
|
|
3405
|
+
for (const group of sortedGroups) {
|
|
3406
|
+
const title = group.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
3407
|
+
console.log(`${BOLD$1}${title}${RESET$1}`);
|
|
3408
|
+
const skills = groupedSkills[group];
|
|
3409
|
+
if (skills) for (const skill of skills) printSkill(skill, true);
|
|
3410
|
+
console.log();
|
|
3411
|
+
}
|
|
3412
|
+
if (ungroupedSkills.length > 0) {
|
|
3413
|
+
console.log(`${BOLD$1}General${RESET$1}`);
|
|
3414
|
+
for (const skill of ungroupedSkills) printSkill(skill, true);
|
|
3415
|
+
console.log();
|
|
3416
|
+
}
|
|
3417
|
+
} else {
|
|
3418
|
+
for (const skill of installedSkills) printSkill(skill);
|
|
3419
|
+
console.log();
|
|
3420
|
+
}
|
|
3886
3421
|
}
|
|
3887
3422
|
async function removeCommand(skillNames, options) {
|
|
3888
3423
|
const isGlobal = options.global ?? false;
|