vskill 0.5.74 → 0.5.76
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 +31 -0
- package/dist/api/client.js +40 -5
- package/dist/api/client.js.map +1 -1
- package/dist/commands/add.js +21 -7
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/outdated.d.ts +13 -0
- package/dist/commands/outdated.js +143 -0
- package/dist/commands/outdated.js.map +1 -0
- package/dist/commands/pin.d.ts +2 -0
- package/dist/commands/pin.js +58 -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 +5 -0
- 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 +183 -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-CqoYdu16.js +74 -0
- package/dist/eval-ui/assets/index-DjZu6HH0.css +1 -0
- package/dist/eval-ui/index.html +2 -2
- package/dist/index.js +31 -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/types.d.ts +4 -0
- package/package.json +1 -1
- package/dist/eval-ui/assets/index-BjKaIypp.js +0 -73
- package/dist/eval-ui/assets/index-CGNHEtf7.css +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// vskill pin / unpin -- version pinning for installed skills
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { readLockfile, writeLockfile } from "../lockfile/lockfile.js";
|
|
5
|
+
import { getVersions } from "../api/client.js";
|
|
6
|
+
import { parseSource } from "../resolvers/source-resolver.js";
|
|
7
|
+
import { bold, cyan, red, green } from "../utils/output.js";
|
|
8
|
+
function resolveFullName(name, source) {
|
|
9
|
+
if (name.includes("/"))
|
|
10
|
+
return name;
|
|
11
|
+
const parsed = parseSource(source);
|
|
12
|
+
if (parsed.type === "github" || parsed.type === "github-plugin" || parsed.type === "marketplace") {
|
|
13
|
+
return `${parsed.owner}/${parsed.repo}/${name}`;
|
|
14
|
+
}
|
|
15
|
+
return name;
|
|
16
|
+
}
|
|
17
|
+
export async function pinCommand(skill, version) {
|
|
18
|
+
const lock = readLockfile();
|
|
19
|
+
if (!lock) {
|
|
20
|
+
console.error(red("No vskill.lock found. Run ") + cyan("vskill install") + red(" first."));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const entry = lock.skills[skill];
|
|
24
|
+
if (!entry) {
|
|
25
|
+
console.error(red(`Skill ${skill} is not installed.`));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const pinVersion = version ?? entry.version;
|
|
29
|
+
// If a specific version is requested, validate it exists
|
|
30
|
+
if (version) {
|
|
31
|
+
const resolved = resolveFullName(skill, entry.source);
|
|
32
|
+
const versions = await getVersions(resolved);
|
|
33
|
+
const exists = versions.some((v) => v.version === version);
|
|
34
|
+
if (!exists) {
|
|
35
|
+
console.error(red(`Version ${version} not found for ${skill}.`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
entry.pinnedVersion = pinVersion;
|
|
40
|
+
writeLockfile(lock);
|
|
41
|
+
console.log(green(`Pinned ${bold(skill)} at ${bold(pinVersion)}`));
|
|
42
|
+
}
|
|
43
|
+
export async function unpinCommand(skill) {
|
|
44
|
+
const lock = readLockfile();
|
|
45
|
+
if (!lock) {
|
|
46
|
+
console.error(red("No vskill.lock found."));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const entry = lock.skills[skill];
|
|
50
|
+
if (!entry) {
|
|
51
|
+
console.error(red(`Skill ${skill} is not installed.`));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
delete entry.pinnedVersion;
|
|
55
|
+
writeLockfile(lock);
|
|
56
|
+
console.log(green(`Unpinned ${bold(skill)}`));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=pin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pin.js","sourceRoot":"","sources":["../../src/commands/pin.ts"],"names":[],"mappings":"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"}
|
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
|
@@ -84,6 +84,11 @@ export async function updateCommand(skill, opts) {
|
|
|
84
84
|
let updated = 0;
|
|
85
85
|
for (const name of toUpdate) {
|
|
86
86
|
const entry = lock.skills[name];
|
|
87
|
+
// Skip pinned skills unless --force is used
|
|
88
|
+
if (entry.pinnedVersion && !opts.force) {
|
|
89
|
+
console.log(dim(`${name}: pinned at ${entry.pinnedVersion} — skipping`));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
87
92
|
const parsed = parseSource(entry.source ?? "");
|
|
88
93
|
const spin = spinner(`Checking ${name}`);
|
|
89
94
|
try {
|
|
@@ -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;AACrC,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;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
// api-routes.ts -- REST API route handlers for the eval UI
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync, readdirSync, statSync } from "node:fs";
|
|
5
|
+
import { execSync } from "node:child_process";
|
|
5
6
|
import { join, resolve, dirname } from "node:path";
|
|
6
7
|
import { sendJson, readBody } from "./router.js";
|
|
7
8
|
import { initSSE, sendSSE, sendSSEDone, withHeartbeat, startDynamicHeartbeat } from "./sse-helpers.js";
|
|
8
9
|
import { dataEventBus, emitDataEvent } from "./data-events.js";
|
|
9
10
|
import { classifyError } from "./error-classifier.js";
|
|
11
|
+
import { readLockfile } from "../lockfile/lockfile.js";
|
|
12
|
+
import { parseSource } from "../resolvers/source-resolver.js";
|
|
10
13
|
import { runBenchmarkSSE, runSingleCaseSSE } from "./benchmark-runner.js";
|
|
11
14
|
import { getSkillSemaphore } from "./concurrency.js";
|
|
12
15
|
import { resolveSkillDir } from "./skill-resolver.js";
|
|
@@ -24,6 +27,30 @@ import { buildEvalInitPrompt, parseGeneratedEvals, buildIntegrationEvalPrompt, p
|
|
|
24
27
|
import { testActivation } from "../eval/activation-tester.js";
|
|
25
28
|
import { detectMcpDependencies, detectSkillDependencies } from "../eval/mcp-detector.js";
|
|
26
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
|
+
}
|
|
27
54
|
// ---------------------------------------------------------------------------
|
|
28
55
|
// Shared helpers
|
|
29
56
|
// ---------------------------------------------------------------------------
|
|
@@ -162,6 +189,16 @@ export function registerRoutes(router, root, projectName) {
|
|
|
162
189
|
router.get("/api/health", (_req, res) => {
|
|
163
190
|
sendJson(res, { ok: true });
|
|
164
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
|
+
});
|
|
165
202
|
// Server-Sent Events endpoint for data change notifications
|
|
166
203
|
// Clients subscribe here to receive push updates when benchmarks complete,
|
|
167
204
|
// history is written, or leaderboard is updated.
|
|
@@ -288,6 +325,152 @@ export function registerRoutes(router, root, projectName) {
|
|
|
288
325
|
}));
|
|
289
326
|
sendJson(res, enriched, 200, req);
|
|
290
327
|
});
|
|
328
|
+
// Check for skill updates via `vskill outdated --json`
|
|
329
|
+
router.get("/api/skills/updates", async (req, res) => {
|
|
330
|
+
try {
|
|
331
|
+
const raw = execSync("vskill outdated --json", {
|
|
332
|
+
timeout: 15_000,
|
|
333
|
+
encoding: "utf-8",
|
|
334
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
335
|
+
});
|
|
336
|
+
const parsed = JSON.parse(raw);
|
|
337
|
+
sendJson(res, Array.isArray(parsed) ? parsed : [], 200, req);
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
sendJson(res, [], 200, req);
|
|
341
|
+
}
|
|
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
|
+
});
|
|
291
474
|
// Get skill detail
|
|
292
475
|
router.get("/api/skills/:plugin/:skill", async (req, res, params) => {
|
|
293
476
|
const skillDir = resolveSkillDir(root, params.plugin, params.skill);
|