vskill 0.5.75 → 0.5.77
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/dist/agents/agents-registry.d.ts +24 -0
- package/dist/agents/agents-registry.js +55 -0
- package/dist/agents/agents-registry.js.map +1 -1
- package/dist/api/client.d.ts +13 -1
- package/dist/api/client.js +10 -1
- package/dist/api/client.js.map +1 -1
- package/dist/commands/add.js +15 -7
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/outdated.js +27 -4
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/pin.d.ts +2 -0
- package/dist/commands/pin.js +62 -0
- package/dist/commands/pin.js.map +1 -0
- package/dist/commands/submit.d.ts +2 -0
- package/dist/commands/submit.js +68 -26
- package/dist/commands/submit.js.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +30 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/versions.d.ts +8 -1
- package/dist/commands/versions.js +82 -4
- package/dist/commands/versions.js.map +1 -1
- package/dist/eval-server/api-routes.d.ts +17 -0
- package/dist/eval-server/api-routes.js +167 -0
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/skill-create-routes.d.ts +8 -0
- package/dist/eval-server/skill-create-routes.js +60 -2
- package/dist/eval-server/skill-create-routes.js.map +1 -1
- package/dist/eval-ui/assets/index-D2OKy2AG.js +74 -0
- package/dist/eval-ui/assets/index-tEmr_c8l.css +1 -0
- package/dist/eval-ui/index.html +2 -2
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -1
- package/dist/installer/canonical.d.ts +6 -0
- package/dist/installer/canonical.js +11 -0
- package/dist/installer/canonical.js.map +1 -1
- package/dist/installer/frontmatter.d.ts +7 -1
- package/dist/installer/frontmatter.js +34 -2
- package/dist/installer/frontmatter.js.map +1 -1
- package/dist/lockfile/migration.js +4 -1
- package/dist/lockfile/migration.js.map +1 -1
- package/dist/lockfile/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/eval-ui/assets/index-AdzCp67B.js +0 -73
- package/dist/eval-ui/assets/index-CGNHEtf7.css +0 -1
package/dist/commands/submit.js
CHANGED
|
@@ -1,44 +1,86 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// vskill submit --
|
|
2
|
+
// vskill submit -- submit skill for verification via API or browser fallback
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { openBrowser } from "../utils/browser.js";
|
|
5
|
-
import {
|
|
5
|
+
import { submitSkill } from "../api/client.js";
|
|
6
|
+
import { bold, green, red, dim, cyan, yellow } from "../utils/output.js";
|
|
6
7
|
import { parseGitHubSource, validateSkillName } from "../utils/validation.js";
|
|
7
8
|
export async function submitCommand(source, opts) {
|
|
8
9
|
if (opts.skill && !validateSkillName(opts.skill)) {
|
|
9
10
|
console.error(red("Invalid skill name. ") + dim("Path traversal patterns are not allowed."));
|
|
10
11
|
process.exit(1);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!parsed) {
|
|
16
|
-
console.error(red("Invalid source. Use: ") + cyan("owner/repo") + dim(" or ") + cyan("https://github.com/owner/repo"));
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
const { owner, repo } = parsed;
|
|
20
|
-
submitUrl.searchParams.set("repo", `${owner}/${repo}`);
|
|
21
|
-
console.log(dim(`Opening browser to submit ${bold(`${owner}/${repo}`)} for verification...\n`));
|
|
13
|
+
if (!source) {
|
|
14
|
+
console.error(red("Source required. ") + dim("Use: vskill submit owner/repo --skill name"));
|
|
15
|
+
process.exit(1);
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
const parsed = parseGitHubSource(source);
|
|
18
|
+
if (!parsed) {
|
|
19
|
+
console.error(red("Invalid source. Use: ") + cyan("owner/repo") + dim(" or ") + cyan("https://github.com/owner/repo"));
|
|
20
|
+
process.exit(1);
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const { owner, repo } = parsed;
|
|
23
|
+
const repoUrl = `https://github.com/${owner}/${repo}`;
|
|
24
|
+
// --browser flag: use browser-based OAuth flow
|
|
25
|
+
if (opts.browser) {
|
|
26
|
+
const submitUrl = new URL("https://verified-skill.com/submit");
|
|
27
|
+
submitUrl.searchParams.set("repo", `${owner}/${repo}`);
|
|
28
|
+
if (opts.skill)
|
|
29
|
+
submitUrl.searchParams.set("skill", opts.skill);
|
|
30
|
+
const url = submitUrl.toString();
|
|
31
|
+
console.log(dim(`Opening browser to submit ${bold(`${owner}/${repo}`)} for verification...\n`));
|
|
32
|
+
try {
|
|
33
|
+
await openBrowser(url);
|
|
34
|
+
console.log(green("Browser opened!\n"));
|
|
35
|
+
console.log(`Complete your submission in the browser at:`);
|
|
36
|
+
console.log(cyan(url));
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.error(red("Could not open browser: ") + dim(err.message));
|
|
40
|
+
console.log(`\nOpen this URL manually:\n${cyan(url)}`);
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
28
43
|
}
|
|
29
|
-
|
|
44
|
+
// Default: programmatic API submission (no browser needed)
|
|
45
|
+
console.log(dim(`Submitting ${bold(opts.skill || repo)} from ${owner}/${repo}...\n`));
|
|
30
46
|
try {
|
|
31
|
-
await
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
const response = await submitSkill({
|
|
48
|
+
repoUrl,
|
|
49
|
+
skillName: opts.skill,
|
|
50
|
+
skillPath: opts.path,
|
|
51
|
+
source: "cli-auto",
|
|
52
|
+
});
|
|
53
|
+
if (response.blocked) {
|
|
54
|
+
console.error(red("Blocked: ") + dim("This skill is on the blocklist."));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
if (response.alreadyVerified) {
|
|
58
|
+
console.log(green("Already verified! ") + dim("Skill is up-to-date in the registry."));
|
|
59
|
+
if (response.id)
|
|
60
|
+
console.log(dim(`Submission: ${response.id}`));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (response.duplicate) {
|
|
64
|
+
console.log(yellow("Duplicate: ") + dim("An identical submission is already pending."));
|
|
65
|
+
if (response.submissionId)
|
|
66
|
+
console.log(dim(`Existing submission: ${response.submissionId}`));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log(green("Submitted! ") + dim(`ID: ${response.id}`));
|
|
70
|
+
console.log(dim(`State: ${response.state}`));
|
|
71
|
+
console.log(dim("\nThe skill will go through tier-1 and tier-2 scanning."));
|
|
72
|
+
console.log(dim(`Check status: vskill info ${opts.skill || repo}`));
|
|
36
73
|
}
|
|
37
74
|
catch (err) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
75
|
+
const msg = err.message;
|
|
76
|
+
if (msg.includes("429") || msg.includes("rate")) {
|
|
77
|
+
console.error(red("Rate limited. ") + dim("Try again in a few minutes, or use --browser for OAuth."));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.error(red("Submission failed: ") + dim(msg));
|
|
81
|
+
console.log(dim("\nFallback: use --browser to submit via GitHub OAuth."));
|
|
82
|
+
}
|
|
83
|
+
process.exit(1);
|
|
42
84
|
}
|
|
43
85
|
}
|
|
44
86
|
//# sourceMappingURL=submit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,
|
|
1
|
+
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/update.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// vskill update -- update installed skills
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
-
import { unlinkSync } from "node:fs";
|
|
4
|
+
import { unlinkSync, rmdirSync, readdirSync } from "node:fs";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
import { readLockfile, writeLockfile } from "../lockfile/index.js";
|
|
7
7
|
import { ensureSkillMdNaming } from "../installer/migrate.js";
|
|
@@ -37,6 +37,29 @@ function cleanupGhostFiles(skillDir, oldFiles, newFiles) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
+
// Clean up empty directories left behind
|
|
41
|
+
const dirsToCheck = new Set();
|
|
42
|
+
for (const file of oldFiles) {
|
|
43
|
+
if (!newSet.has(file)) {
|
|
44
|
+
const dir = resolve(skillDir, file, "..");
|
|
45
|
+
if (dir !== resolvedBase && dir.startsWith(resolvedBase + "/")) {
|
|
46
|
+
dirsToCheck.add(dir);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Remove empty dirs bottom-up
|
|
51
|
+
const sortedDirs = [...dirsToCheck].sort((a, b) => b.length - a.length);
|
|
52
|
+
for (const dir of sortedDirs) {
|
|
53
|
+
try {
|
|
54
|
+
const entries = readdirSync(dir);
|
|
55
|
+
if (entries.length === 0) {
|
|
56
|
+
rmdirSync(dir);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Directory may already be removed — ignore
|
|
61
|
+
}
|
|
62
|
+
}
|
|
40
63
|
}
|
|
41
64
|
export async function updateCommand(skill, opts) {
|
|
42
65
|
const lock = readLockfile();
|
|
@@ -84,6 +107,11 @@ export async function updateCommand(skill, opts) {
|
|
|
84
107
|
let updated = 0;
|
|
85
108
|
for (const name of toUpdate) {
|
|
86
109
|
const entry = lock.skills[name];
|
|
110
|
+
// Skip pinned skills unless --force is used
|
|
111
|
+
if (entry.pinnedVersion && !opts.force) {
|
|
112
|
+
console.log(dim(`${name}: pinned at ${entry.pinnedVersion} — skipping`));
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
87
115
|
const parsed = parseSource(entry.source ?? "");
|
|
88
116
|
const spin = spinner(`Checking ${name}`);
|
|
89
117
|
try {
|
|
@@ -135,7 +163,7 @@ export async function updateCommand(skill, opts) {
|
|
|
135
163
|
}
|
|
136
164
|
// 6. Resolve version
|
|
137
165
|
const newVersion = resolveVersion({
|
|
138
|
-
serverVersion: result.version,
|
|
166
|
+
serverVersion: parsed.type === "registry" ? result.version : undefined,
|
|
139
167
|
frontmatterVersion: extractFrontmatterVersion(result.content),
|
|
140
168
|
currentVersion: entry.version,
|
|
141
169
|
hashChanged: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,IAAI,EACJ,KAAK,EACL,GAAG,EACH,MAAM,EACN,GAAG,EACH,IAAI,EACJ,OAAO,GACR,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,SAAS,iBAAiB,CACxB,QAAgB,EAChB,QAA8B,EAC9B,QAAkB;IAElB,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACvC,kDAAkD;YAClD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,GAAG,GAAG,CAAC,IAAI,MAAM,KAAK,YAAY;gBAAE,SAAS;YAChF,IAAI,CAAC;gBACH,UAAU,CAAC,MAAM,CAAC,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,uCAAuC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,yCAAyC;IACzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1C,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC;gBAC/D,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IACD,8BAA8B;IAC9B,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACxE,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,4CAA4C;QAC9C,CAAC;IACH,CAAC;AACH,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAyB,EACzB,IAAmB;IAEnB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CACX,MAAM,CAAC,4BAA4B,CAAC;YAClC,IAAI,CAAC,gBAAgB,CAAC;YACtB,MAAM,CAAC,SAAS,CAAC,CACpB,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO,CAAC,+BAA+B;IACzC,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,mCAAmC;IACnC,IAAI,QAAkB,CAAC;IACvB,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,qBAAqB,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QACD,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,+DAA+D;QAC/D,QAAQ,GAAG,UAAU,CAAC;IACxB,CAAC;IAED,IAAI,MAAM,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IACD,iDAAiD;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,GAAG,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEhC,4CAA4C;QAC5C,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,eAAe,KAAK,CAAC,aAAa,aAAa,CAAC,CAAC,CAAC;YACzE,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,kCAAkC;YAClC,IAAI,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAExD,sDAAsD;YACtD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACpC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;wBACnB,MAAM,KAAK,GAA2B,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;wBACrE,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;wBAC9B,MAAM,GAAG;4BACP,OAAO,EAAE,MAAM,CAAC,OAAO;4BACvB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;4BACxC,GAAG;4BACH,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI;4BAC/B,KAAK;yBACN,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,uBAAuB;gBACzB,CAAC;YACH,CAAC;YAED,IAAI,CAAC,IAAI,EAAE,CAAC;YAEZ,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CACT,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC;oBACnB,GAAG,CAAC,wCAAwC,CAAC,CAChD,CAAC;gBACF,SAAS;YACX,CAAC;YAED,wCAAwC;YACxC,IAAI,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAC,CAAC;gBAChD,SAAS;YACX,CAAC;YAED,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAC3G,CAAC;YAEF,mBAAmB;YACnB,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM,YAAY,GAChB,UAAU,CAAC,OAAO,KAAK,MAAM;gBAC3B,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,UAAU,CAAC,OAAO,KAAK,UAAU;oBACjC,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,GAAG,CAAC;YACZ,OAAO,CAAC,GAAG,CACT,WAAW,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC,KAAK,OAAO,CACxE,CAAC;YAEF,IAAI,UAAU,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBAClC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,wBAAwB,IAAI,eAAe,CAAC,CAAC,CAAC;gBAC9D,SAAS;YACX,CAAC;YAED,qBAAqB;YACrB,MAAM,UAAU,GAAG,cAAc,CAAC;gBAChC,aAAa,EAAE,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACtE,kBAAkB,EAAE,yBAAyB,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC7D,cAAc,EAAE,KAAK,CAAC,OAAO;gBAC7B,WAAW,EAAE,IAAI;gBACjB,cAAc,EAAE,KAAK;aACtB,CAAC,CAAC;YAEH,iCAAiC;YACjC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK;gBAC9B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;gBAClC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAEjB,0DAA0D;YAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;gBAC/D,IAAI,CAAC;oBACH,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;gBACxD,CAAC;gBAAC,MAAM,CAAC;oBACP,oCAAoC;gBACtC,CAAC;YACH,CAAC;YACD,0CAA0C;YAC1C,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACvE,IAAI,CAAC;gBACH,iBAAiB,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;YACjE,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YAED,6DAA6D;YAC7D,IAAI,UAA8C,CAAC;YACnD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,KAAK,GAA2B,EAAE,CAAC;gBACzC,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClE,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;wBAC3B,KAAK,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;oBAC/B,CAAC;gBACH,CAAC;gBACD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClC,UAAU,GAAG,KAAK,CAAC;gBACrB,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,cAAc,CACZ,IAAI,EACJ,MAAM,CAAC,OAAO,EACd,MAAM,EACN,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAC9B,UAAU,CACX,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,4CAA4C;YAC9C,CAAC;YAED,yDAAyD;YACzD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;gBAC1D,mBAAmB,CAAC,SAAS,CAAC,CAAC;YACjC,CAAC;YAED,qEAAqE;YACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;gBAClB,GAAG,KAAK;gBACR,OAAO,EAAE,UAAU;gBACnB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACrC,KAAK,EAAE,WAAW;aACnB,CAAC;YAEF,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CACT,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC;gBACnB,GAAG,CAAC,kBAAmB,GAAa,CAAC,OAAO,GAAG,CAAC,CACnD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,OAAO,CAAC,GAAG,CACT,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,SAAS,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAChH,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
interface VersionsOptions {
|
|
2
|
+
diff?: boolean;
|
|
3
|
+
from?: string;
|
|
4
|
+
to?: string;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function versionsCommand(skillName: string, opts: VersionsOptions): Promise<void>;
|
|
8
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// vskill versions -- list published versions for a skill
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
-
import { getVersions } from "../api/client.js";
|
|
4
|
+
import { getVersions, getVersionDiff } from "../api/client.js";
|
|
5
5
|
import { readLockfile } from "../lockfile/lockfile.js";
|
|
6
6
|
import { parseSource } from "../resolvers/source-resolver.js";
|
|
7
7
|
import { bold, dim, cyan, red, green, yellow, table } from "../utils/output.js";
|
|
@@ -25,26 +25,57 @@ function resolveFullName(name) {
|
|
|
25
25
|
}
|
|
26
26
|
return name;
|
|
27
27
|
}
|
|
28
|
-
export async function versionsCommand(skillName) {
|
|
28
|
+
export async function versionsCommand(skillName, opts) {
|
|
29
29
|
try {
|
|
30
30
|
const resolved = resolveFullName(skillName);
|
|
31
|
+
// --diff mode: show unified diff between two versions
|
|
32
|
+
if (opts.diff) {
|
|
33
|
+
await handleDiff(skillName, resolved, opts);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
31
36
|
const versions = await getVersions(resolved);
|
|
32
37
|
if (versions.length === 0) {
|
|
33
|
-
|
|
38
|
+
if (opts.json) {
|
|
39
|
+
console.log(JSON.stringify([]));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(dim("No versions found for ") + cyan(resolved));
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Determine installed version from lockfile
|
|
47
|
+
const lock = readLockfile();
|
|
48
|
+
const lockEntry = lock?.skills[skillName];
|
|
49
|
+
const installedVersion = lockEntry?.version;
|
|
50
|
+
// --json mode
|
|
51
|
+
if (opts.json) {
|
|
52
|
+
const jsonOut = versions.map((v) => ({
|
|
53
|
+
version: v.version,
|
|
54
|
+
certTier: v.certTier,
|
|
55
|
+
createdAt: v.createdAt,
|
|
56
|
+
diffSummary: v.diffSummary ?? null,
|
|
57
|
+
installed: v.version === installedVersion,
|
|
58
|
+
}));
|
|
59
|
+
console.log(JSON.stringify(jsonOut, null, 2));
|
|
34
60
|
return;
|
|
35
61
|
}
|
|
62
|
+
// Table mode
|
|
36
63
|
console.log(bold(`Versions for ${resolved}\n`));
|
|
37
|
-
const headers = ["Version", "Tier", "Date"];
|
|
64
|
+
const headers = ["Version", "Tier", "Date", "Installed", "Changes"];
|
|
38
65
|
const rows = versions.map((v) => {
|
|
39
66
|
const tierColor = v.certTier === "CERTIFIED"
|
|
40
67
|
? yellow
|
|
41
68
|
: v.certTier === "VERIFIED"
|
|
42
69
|
? green
|
|
43
70
|
: dim;
|
|
71
|
+
const marker = v.version === installedVersion ? "►" : "";
|
|
72
|
+
const summary = truncate(v.diffSummary ?? "", 60);
|
|
44
73
|
return [
|
|
45
74
|
bold(v.version),
|
|
46
75
|
tierColor(v.certTier),
|
|
47
76
|
dim(new Date(v.createdAt).toLocaleDateString()),
|
|
77
|
+
marker ? cyan(marker) : "",
|
|
78
|
+
summary ? dim(summary) : "",
|
|
48
79
|
];
|
|
49
80
|
});
|
|
50
81
|
console.log(table(headers, rows));
|
|
@@ -55,4 +86,51 @@ export async function versionsCommand(skillName) {
|
|
|
55
86
|
process.exit(1);
|
|
56
87
|
}
|
|
57
88
|
}
|
|
89
|
+
async function handleDiff(skillName, resolved, opts) {
|
|
90
|
+
let fromVersion = opts.from;
|
|
91
|
+
let toVersion = opts.to;
|
|
92
|
+
// If --from/--to not provided, derive from lockfile
|
|
93
|
+
if (!fromVersion || !toVersion) {
|
|
94
|
+
const lock = readLockfile();
|
|
95
|
+
const lockEntry = lock?.skills[skillName];
|
|
96
|
+
if (!lockEntry) {
|
|
97
|
+
console.log(dim("Skill not installed. Use --from and --to to compare specific versions."));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!fromVersion)
|
|
101
|
+
fromVersion = lockEntry.version;
|
|
102
|
+
// Find latest from versions list
|
|
103
|
+
if (!toVersion) {
|
|
104
|
+
const versions = await getVersions(resolved);
|
|
105
|
+
if (versions.length === 0) {
|
|
106
|
+
console.log(dim("No versions available."));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
toVersion = versions[0].version;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const diff = await getVersionDiff(resolved, fromVersion, toVersion);
|
|
113
|
+
console.log(bold(`Diff: ${fromVersion} → ${toVersion}`));
|
|
114
|
+
if (diff.diffSummary) {
|
|
115
|
+
console.log(dim(diff.diffSummary));
|
|
116
|
+
}
|
|
117
|
+
console.log("");
|
|
118
|
+
// Print colorized diff
|
|
119
|
+
for (const line of diff.contentDiff.split("\n")) {
|
|
120
|
+
if (line.startsWith("+")) {
|
|
121
|
+
console.log(green(line));
|
|
122
|
+
}
|
|
123
|
+
else if (line.startsWith("-")) {
|
|
124
|
+
console.log(red(line));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.log(line);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function truncate(str, max) {
|
|
132
|
+
if (str.length <= max)
|
|
133
|
+
return str;
|
|
134
|
+
return str.slice(0, max) + "…";
|
|
135
|
+
}
|
|
58
136
|
//# sourceMappingURL=versions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yDAAyD;AACzD,8EAA8E;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/
|
|
1
|
+
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
1
|
import type { Router } from "./router.js";
|
|
2
|
+
import type { AgentDefinition } from "../agents/agents-registry.js";
|
|
3
|
+
export interface InstalledAgentEntry {
|
|
4
|
+
id: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
featureSupport: AgentDefinition["featureSupport"];
|
|
7
|
+
isUniversal: boolean;
|
|
8
|
+
installed: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface InstalledAgentsResponse {
|
|
11
|
+
agents: InstalledAgentEntry[];
|
|
12
|
+
suggested: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build the response for GET /api/agents/installed.
|
|
16
|
+
* Returns all known agents with installed flag based on detected agents.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildInstalledAgentsResponse(detectedAgents: AgentDefinition[]): InstalledAgentsResponse;
|
|
2
19
|
export declare function extractDescription(skillContent: string): string;
|
|
3
20
|
export declare function registerRoutes(router: Router, root: string, projectName?: string): void;
|
|
@@ -8,6 +8,8 @@ import { sendJson, readBody } from "./router.js";
|
|
|
8
8
|
import { initSSE, sendSSE, sendSSEDone, withHeartbeat, startDynamicHeartbeat } from "./sse-helpers.js";
|
|
9
9
|
import { dataEventBus, emitDataEvent } from "./data-events.js";
|
|
10
10
|
import { classifyError } from "./error-classifier.js";
|
|
11
|
+
import { readLockfile } from "../lockfile/lockfile.js";
|
|
12
|
+
import { parseSource } from "../resolvers/source-resolver.js";
|
|
11
13
|
import { runBenchmarkSSE, runSingleCaseSSE } from "./benchmark-runner.js";
|
|
12
14
|
import { getSkillSemaphore } from "./concurrency.js";
|
|
13
15
|
import { resolveSkillDir } from "./skill-resolver.js";
|
|
@@ -25,6 +27,30 @@ import { buildEvalInitPrompt, parseGeneratedEvals, buildIntegrationEvalPrompt, p
|
|
|
25
27
|
import { testActivation } from "../eval/activation-tester.js";
|
|
26
28
|
import { detectMcpDependencies, detectSkillDependencies } from "../eval/mcp-detector.js";
|
|
27
29
|
import { writeActivationRun, listActivationRuns, getActivationRun } from "../eval/activation-history.js";
|
|
30
|
+
import { AGENTS_REGISTRY, detectInstalledAgents } from "../agents/agents-registry.js";
|
|
31
|
+
/**
|
|
32
|
+
* Build the response for GET /api/agents/installed.
|
|
33
|
+
* Returns all known agents with installed flag based on detected agents.
|
|
34
|
+
*/
|
|
35
|
+
export function buildInstalledAgentsResponse(detectedAgents) {
|
|
36
|
+
const detectedIds = new Set(detectedAgents.map((a) => a.id));
|
|
37
|
+
const agents = AGENTS_REGISTRY.map((agent) => ({
|
|
38
|
+
id: agent.id,
|
|
39
|
+
displayName: agent.displayName,
|
|
40
|
+
featureSupport: agent.featureSupport,
|
|
41
|
+
isUniversal: agent.isUniversal,
|
|
42
|
+
installed: detectedIds.has(agent.id),
|
|
43
|
+
}));
|
|
44
|
+
// Suggest claude-code if installed, otherwise first installed alphabetically, fallback to claude-code
|
|
45
|
+
let suggested = "claude-code";
|
|
46
|
+
if (detectedIds.has("claude-code")) {
|
|
47
|
+
suggested = "claude-code";
|
|
48
|
+
}
|
|
49
|
+
else if (detectedAgents.length > 0) {
|
|
50
|
+
suggested = detectedAgents[0].id;
|
|
51
|
+
}
|
|
52
|
+
return { agents, suggested };
|
|
53
|
+
}
|
|
28
54
|
// ---------------------------------------------------------------------------
|
|
29
55
|
// Shared helpers
|
|
30
56
|
// ---------------------------------------------------------------------------
|
|
@@ -163,6 +189,16 @@ export function registerRoutes(router, root, projectName) {
|
|
|
163
189
|
router.get("/api/health", (_req, res) => {
|
|
164
190
|
sendJson(res, { ok: true });
|
|
165
191
|
});
|
|
192
|
+
// Installed agents — returns all 49 known agents with installed flag
|
|
193
|
+
router.get("/api/agents/installed", async (_req, res) => {
|
|
194
|
+
try {
|
|
195
|
+
const detected = await detectInstalledAgents();
|
|
196
|
+
sendJson(res, buildInstalledAgentsResponse(detected), 200, _req);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
sendJson(res, { error: err.message }, 500, _req);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
166
202
|
// Server-Sent Events endpoint for data change notifications
|
|
167
203
|
// Clients subscribe here to receive push updates when benchmarks complete,
|
|
168
204
|
// history is written, or leaderboard is updated.
|
|
@@ -304,6 +340,137 @@ export function registerRoutes(router, root, projectName) {
|
|
|
304
340
|
sendJson(res, [], 200, req);
|
|
305
341
|
}
|
|
306
342
|
});
|
|
343
|
+
// -------------------------------------------------------------------------
|
|
344
|
+
// Version proxy, diff, update, and batch-update routes (Phase 2)
|
|
345
|
+
// MUST be registered BEFORE the /:plugin/:skill catch-all below.
|
|
346
|
+
// -------------------------------------------------------------------------
|
|
347
|
+
const PLATFORM_BASE = "https://verified-skill.com";
|
|
348
|
+
/** Resolve plugin/skill to full hierarchical API name using lockfile source. */
|
|
349
|
+
function resolveSkillApiName(skill) {
|
|
350
|
+
const lock = readLockfile();
|
|
351
|
+
if (!lock)
|
|
352
|
+
return skill;
|
|
353
|
+
const entry = lock.skills[skill];
|
|
354
|
+
if (!entry?.source)
|
|
355
|
+
return skill;
|
|
356
|
+
const parsed = parseSource(entry.source);
|
|
357
|
+
if (parsed.type === "github" || parsed.type === "github-plugin" || parsed.type === "marketplace") {
|
|
358
|
+
return `${parsed.owner}/${parsed.repo}/${skill}`;
|
|
359
|
+
}
|
|
360
|
+
return skill;
|
|
361
|
+
}
|
|
362
|
+
// T-009: Versions proxy route
|
|
363
|
+
router.get("/api/skills/:plugin/:skill/versions", async (req, res, params) => {
|
|
364
|
+
const fullName = resolveSkillApiName(params.skill);
|
|
365
|
+
const parts = fullName.split("/");
|
|
366
|
+
const apiPath = parts.length === 3
|
|
367
|
+
? `/api/v1/skills/${parts.map(encodeURIComponent).join("/")}/versions`
|
|
368
|
+
: `/api/v1/skills/${encodeURIComponent(fullName)}/versions`;
|
|
369
|
+
try {
|
|
370
|
+
const resp = await fetch(`${PLATFORM_BASE}${apiPath}`, {
|
|
371
|
+
signal: AbortSignal.timeout(10_000),
|
|
372
|
+
});
|
|
373
|
+
if (!resp.ok) {
|
|
374
|
+
sendJson(res, { error: "Platform API unavailable" }, 502, req);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const data = (await resp.json());
|
|
378
|
+
const versions = Array.isArray(data.versions) ? data.versions : [];
|
|
379
|
+
// Enrich with isInstalled from lockfile
|
|
380
|
+
const lock = readLockfile();
|
|
381
|
+
const installedVersion = lock?.skills[params.skill]?.version;
|
|
382
|
+
const enriched = versions.map((v) => ({
|
|
383
|
+
...v,
|
|
384
|
+
isInstalled: installedVersion ? v.version === installedVersion : undefined,
|
|
385
|
+
}));
|
|
386
|
+
sendJson(res, enriched, 200, req);
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
sendJson(res, { error: "Platform API unavailable" }, 502, req);
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
// T-010: Diff proxy route
|
|
393
|
+
router.get("/api/skills/:plugin/:skill/versions/diff", async (req, res, params) => {
|
|
394
|
+
const url = new URL(req.url ?? "", "http://localhost");
|
|
395
|
+
const from = url.searchParams.get("from");
|
|
396
|
+
const to = url.searchParams.get("to");
|
|
397
|
+
if (!from || !to) {
|
|
398
|
+
sendJson(res, { error: "Missing required query params: from and to" }, 400, req);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const fullName = resolveSkillApiName(params.skill);
|
|
402
|
+
const parts = fullName.split("/");
|
|
403
|
+
const basePath = parts.length === 3
|
|
404
|
+
? `/api/v1/skills/${parts.map(encodeURIComponent).join("/")}/versions`
|
|
405
|
+
: `/api/v1/skills/${encodeURIComponent(fullName)}/versions`;
|
|
406
|
+
try {
|
|
407
|
+
const resp = await fetch(`${PLATFORM_BASE}${basePath}?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`, { signal: AbortSignal.timeout(10_000) });
|
|
408
|
+
if (!resp.ok) {
|
|
409
|
+
sendJson(res, { error: "Platform API unavailable" }, 502, req);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const data = await resp.json();
|
|
413
|
+
sendJson(res, data, 200, req);
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
sendJson(res, { error: "Platform API unavailable" }, 502, req);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
// T-011: Single-skill update SSE endpoint
|
|
420
|
+
router.post("/api/skills/:plugin/:skill/update", async (req, res, params) => {
|
|
421
|
+
initSSE(res, req);
|
|
422
|
+
const skillName = params.skill;
|
|
423
|
+
sendSSE(res, "progress", { status: "updating", skill: skillName });
|
|
424
|
+
try {
|
|
425
|
+
execSync(`vskill update ${skillName}`, {
|
|
426
|
+
timeout: 60_000,
|
|
427
|
+
encoding: "utf-8",
|
|
428
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
429
|
+
});
|
|
430
|
+
sendSSE(res, "progress", { status: "done", skill: skillName });
|
|
431
|
+
sendSSEDone(res, { status: "done", skill: skillName });
|
|
432
|
+
}
|
|
433
|
+
catch (err) {
|
|
434
|
+
sendSSE(res, "error", { error: err.message, skill: skillName });
|
|
435
|
+
sendSSEDone(res, { status: "error", skill: skillName });
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
// T-012: Batch update SSE + 409 conflict guard
|
|
439
|
+
let batchUpdateInProgress = false;
|
|
440
|
+
router.post("/api/skills/batch-update", async (req, res) => {
|
|
441
|
+
if (batchUpdateInProgress) {
|
|
442
|
+
sendJson(res, { error: "Update already in progress" }, 409, req);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
batchUpdateInProgress = true;
|
|
446
|
+
const body = (await readBody(req));
|
|
447
|
+
const skills = Array.isArray(body.skills) ? body.skills : [];
|
|
448
|
+
initSSE(res, req);
|
|
449
|
+
let updated = 0;
|
|
450
|
+
let failed = 0;
|
|
451
|
+
try {
|
|
452
|
+
for (const skill of skills) {
|
|
453
|
+
sendSSE(res, "skill:start", { skill });
|
|
454
|
+
try {
|
|
455
|
+
execSync(`vskill update ${skill}`, {
|
|
456
|
+
timeout: 60_000,
|
|
457
|
+
encoding: "utf-8",
|
|
458
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
459
|
+
});
|
|
460
|
+
sendSSE(res, "skill:done", { skill });
|
|
461
|
+
updated++;
|
|
462
|
+
}
|
|
463
|
+
catch (err) {
|
|
464
|
+
sendSSE(res, "skill:error", { skill, error: err.message });
|
|
465
|
+
failed++;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
sendSSEDone(res, { updated, failed, skipped: 0 });
|
|
469
|
+
}
|
|
470
|
+
finally {
|
|
471
|
+
batchUpdateInProgress = false;
|
|
472
|
+
}
|
|
473
|
+
});
|
|
307
474
|
// Get skill detail
|
|
308
475
|
router.get("/api/skills/:plugin/:skill", async (req, res, params) => {
|
|
309
476
|
const skillDir = resolveSkillDir(root, params.plugin, params.skill);
|