vskill 1.0.14 → 1.0.16
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 +61 -0
- package/agents.json +1 -1
- package/dist/agents/agents-registry.d.ts +8 -3
- package/dist/agents/agents-registry.js.map +1 -1
- package/dist/bin.js +0 -0
- package/dist/clone/github-scaffold.d.ts +38 -0
- package/dist/clone/github-scaffold.js +108 -0
- package/dist/clone/github-scaffold.js.map +1 -0
- package/dist/clone/provenance-fork.d.ts +34 -0
- package/dist/clone/provenance-fork.js +97 -0
- package/dist/clone/provenance-fork.js.map +1 -0
- package/dist/clone/reference-scanner.d.ts +19 -0
- package/dist/clone/reference-scanner.js +144 -0
- package/dist/clone/reference-scanner.js.map +1 -0
- package/dist/clone/skill-locator.d.ts +26 -0
- package/dist/clone/skill-locator.js +248 -0
- package/dist/clone/skill-locator.js.map +1 -0
- package/dist/clone/target-router.d.ts +73 -0
- package/dist/clone/target-router.js +200 -0
- package/dist/clone/target-router.js.map +1 -0
- package/dist/clone/types.d.ts +82 -0
- package/dist/clone/types.js +11 -0
- package/dist/clone/types.js.map +1 -0
- package/dist/commands/add.js +96 -32
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/auth.d.ts +23 -0
- package/dist/commands/auth.js +273 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/clone-prompts.d.ts +13 -0
- package/dist/commands/clone-prompts.js +67 -0
- package/dist/commands/clone-prompts.js.map +1 -0
- package/dist/commands/clone.d.ts +70 -0
- package/dist/commands/clone.js +649 -0
- package/dist/commands/clone.js.map +1 -0
- package/dist/commands/eval/serve.js +8 -1
- package/dist/commands/eval/serve.js.map +1 -1
- package/dist/commands/keys.js +54 -2
- package/dist/commands/keys.js.map +1 -1
- package/dist/eval/skill-scanner.d.ts +2 -12
- package/dist/eval/skill-scanner.js +27 -5
- package/dist/eval/skill-scanner.js.map +1 -1
- package/dist/eval-server/api-routes.js +527 -35
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/data-events.d.ts +1 -1
- package/dist/eval-server/data-events.js.map +1 -1
- package/dist/eval-server/eval-server.js +8 -1
- package/dist/eval-server/eval-server.js.map +1 -1
- package/dist/eval-server/install-engine-routes-helpers.d.ts +1 -3
- package/dist/eval-server/install-engine-routes-helpers.js +6 -14
- package/dist/eval-server/install-engine-routes-helpers.js.map +1 -1
- package/dist/eval-server/install-state-routes.d.ts +21 -0
- package/dist/eval-server/install-state-routes.js +111 -0
- package/dist/eval-server/install-state-routes.js.map +1 -0
- package/dist/eval-server/origin-resolver.d.ts +42 -0
- package/dist/eval-server/origin-resolver.js +168 -0
- package/dist/eval-server/origin-resolver.js.map +1 -0
- package/dist/eval-server/platform-proxy.d.ts +10 -0
- package/dist/eval-server/platform-proxy.js +58 -2
- package/dist/eval-server/platform-proxy.js.map +1 -1
- package/dist/eval-server/skill-resolver.js +40 -0
- package/dist/eval-server/skill-resolver.js.map +1 -1
- package/dist/eval-server/utils/resolve-editor.d.ts +6 -1
- package/dist/eval-server/utils/resolve-editor.js +11 -26
- package/dist/eval-server/utils/resolve-editor.js.map +1 -1
- package/dist/eval-server/utils/scan-install-locations.d.ts +7 -0
- package/dist/eval-server/utils/scan-install-locations.js +20 -0
- package/dist/eval-server/utils/scan-install-locations.js.map +1 -1
- package/dist/eval-server/utils/which.d.ts +15 -0
- package/dist/eval-server/utils/which.js +76 -0
- package/dist/eval-server/utils/which.js.map +1 -0
- package/dist/eval-ui/assets/{CreateSkillPage-CKvqAya0.js → CreateSkillPage-CvdYq8Rr.js} +5 -5
- package/dist/eval-ui/assets/{FindSkillsPalette-B8pTa5NP.js → FindSkillsPalette-DsSgotS9.js} +2 -2
- package/dist/eval-ui/assets/{SearchPaletteCore-CkVRvaZk.js → SearchPaletteCore-Bf3PBC64.js} +2 -2
- package/dist/eval-ui/assets/SkillDetailPanel-DAD2yJO-.js +1 -0
- package/dist/eval-ui/assets/{UpdateDropdown-DA7OktXO.js → UpdateDropdown-h5Hg3h7Z.js} +1 -1
- package/dist/eval-ui/assets/{index-BKAvJDDF.css → index-CKLqBL52.css} +1 -1
- package/dist/eval-ui/assets/index-JaDg6FlU.js +124 -0
- package/dist/eval-ui/index.html +2 -2
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -1
- package/dist/installer/canonical.js +2 -11
- package/dist/installer/canonical.js.map +1 -1
- package/dist/installer/frontmatter.d.ts +26 -0
- package/dist/installer/frontmatter.js +91 -1
- package/dist/installer/frontmatter.js.map +1 -1
- package/dist/lib/github-fetch.d.ts +22 -0
- package/dist/lib/github-fetch.js +152 -0
- package/dist/lib/github-fetch.js.map +1 -0
- package/dist/lib/keychain.d.ts +41 -0
- package/dist/lib/keychain.js +232 -0
- package/dist/lib/keychain.js.map +1 -0
- package/dist/studio/lib/provenance.js +3 -2
- package/dist/studio/lib/provenance.js.map +1 -1
- package/dist/studio/lib/query.d.ts +1 -0
- package/dist/studio/lib/query.js +7 -0
- package/dist/studio/lib/query.js.map +1 -0
- package/dist/studio/lib/scope-transfer.d.ts +6 -0
- package/dist/studio/lib/scope-transfer.js +5 -2
- package/dist/studio/lib/scope-transfer.js.map +1 -1
- package/dist/studio/routes/index.js +3 -0
- package/dist/studio/routes/index.js.map +1 -1
- package/dist/studio/routes/ops.js +1 -3
- package/dist/studio/routes/ops.js.map +1 -1
- package/dist/studio/routes/promote.js +1 -3
- package/dist/studio/routes/promote.js.map +1 -1
- package/dist/studio/routes/revert.js +2 -17
- package/dist/studio/routes/revert.js.map +1 -1
- package/dist/studio/routes/test-install.js +1 -3
- package/dist/studio/routes/test-install.js.map +1 -1
- package/dist/studio/types.d.ts +13 -0
- package/dist/utils/claude-plugin.d.ts +26 -0
- package/dist/utils/claude-plugin.js +60 -0
- package/dist/utils/claude-plugin.js.map +1 -1
- package/dist/utils/skill-builder-detection.d.ts +14 -1
- package/dist/utils/skill-builder-detection.js +20 -8
- package/dist/utils/skill-builder-detection.js.map +1 -1
- package/dist/utils/skill-creator-detection.d.ts +10 -2
- package/dist/utils/skill-creator-detection.js +12 -43
- package/dist/utils/skill-creator-detection.js.map +1 -1
- package/package.json +2 -1
- package/dist/eval-ui/assets/SkillDetailPanel-d4_LquVH.js +0 -1
- package/dist/eval-ui/assets/index-DCbohW6l.js +0 -122
|
@@ -120,7 +120,14 @@ export async function startEvalServer(opts) {
|
|
|
120
120
|
// to free the port before restarting in-place. Replies before closing so
|
|
121
121
|
// the caller sees a clean 200 instead of a connection reset. Registered
|
|
122
122
|
// here (after `server` is constructed) so the handler can close it.
|
|
123
|
-
|
|
123
|
+
// Loopback-only: the same CSRF gate the install/state routes use, since
|
|
124
|
+
// any same-origin tab on a developer box could otherwise terminate studio.
|
|
125
|
+
router.post("/api/shutdown", async (req, res) => {
|
|
126
|
+
const addr = req.socket.remoteAddress ?? "";
|
|
127
|
+
if (addr !== "127.0.0.1" && addr !== "::1" && addr !== "::ffff:127.0.0.1") {
|
|
128
|
+
sendJson(res, { ok: false, error: "loopback-only" }, 403, req);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
124
131
|
sendJson(res, { ok: true, shuttingDown: true });
|
|
125
132
|
setTimeout(() => {
|
|
126
133
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-server.js","sourceRoot":"","sources":["../../src/eval-server/eval-server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"eval-server.js","sourceRoot":"","sources":["../../src/eval-server/eval-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Returns true when `cmd` resolves to an executable on PATH.
|
|
3
|
-
*
|
|
4
|
-
* Uses `which` (POSIX) / `where` (Windows). Pure best-effort: any failure to
|
|
5
|
-
* spawn the lookup process is treated as "not available".
|
|
3
|
+
* Uses `which` / `where` under the hood with metacharacter guard + cache.
|
|
6
4
|
*/
|
|
7
5
|
export declare function isCliAvailable(cmd: string): boolean;
|
|
@@ -2,24 +2,16 @@
|
|
|
2
2
|
// install-engine-routes-helpers.ts — extracted prerequisite-CLI lookup so it
|
|
3
3
|
// can be mocked independently of node:child_process in unit tests.
|
|
4
4
|
// Ref: 0734 AC-US5-02
|
|
5
|
+
//
|
|
6
|
+
// Now a thin re-export of the shared `whichSync` helper; the previous
|
|
7
|
+
// inline `spawnSync`-based implementation lives in utils/which.ts.
|
|
5
8
|
// ---------------------------------------------------------------------------
|
|
6
|
-
import {
|
|
9
|
+
import { whichSync } from "./utils/which.js";
|
|
7
10
|
/**
|
|
8
11
|
* Returns true when `cmd` resolves to an executable on PATH.
|
|
9
|
-
*
|
|
10
|
-
* Uses `which` (POSIX) / `where` (Windows). Pure best-effort: any failure to
|
|
11
|
-
* spawn the lookup process is treated as "not available".
|
|
12
|
+
* Uses `which` / `where` under the hood with metacharacter guard + cache.
|
|
12
13
|
*/
|
|
13
14
|
export function isCliAvailable(cmd) {
|
|
14
|
-
|
|
15
|
-
return false; // hard guard against shell metacharacters
|
|
16
|
-
const lookup = process.platform === "win32" ? "where" : "which";
|
|
17
|
-
try {
|
|
18
|
-
const res = spawnSync(lookup, [cmd], { stdio: "ignore" });
|
|
19
|
-
return res.status === 0;
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
15
|
+
return whichSync(cmd);
|
|
24
16
|
}
|
|
25
17
|
//# sourceMappingURL=install-engine-routes-helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-engine-routes-helpers.js","sourceRoot":"","sources":["../../src/eval-server/install-engine-routes-helpers.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,mEAAmE;AACnE,sBAAsB;AACtB,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"install-engine-routes-helpers.js","sourceRoot":"","sources":["../../src/eval-server/install-engine-routes-helpers.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,mEAAmE;AACnE,sBAAsB;AACtB,EAAE;AACF,sEAAsE;AACtE,mEAAmE;AACnE,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Router } from "./router.js";
|
|
2
|
+
export interface DetectedAgentTool {
|
|
3
|
+
id: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
localDir: string;
|
|
6
|
+
globalDir: string;
|
|
7
|
+
}
|
|
8
|
+
export interface InstallStateForScope {
|
|
9
|
+
installed: boolean;
|
|
10
|
+
installedAgentTools: string[];
|
|
11
|
+
version: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface InstallStateResponse {
|
|
14
|
+
skill: string;
|
|
15
|
+
detectedAgentTools: DetectedAgentTool[];
|
|
16
|
+
scopes: {
|
|
17
|
+
project: InstallStateForScope;
|
|
18
|
+
user: InstallStateForScope;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export declare function registerInstallStateRoutes(router: Router, root: string): void;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// 0827 — GET /api/studio/install-state?skill=<publisher>/<slug>
|
|
2
|
+
//
|
|
3
|
+
// Reports per-scope install state (project, user) for a single skill, plus the
|
|
4
|
+
// list of agent tools detected on the host. Drives the SkillDetailPanel's
|
|
5
|
+
// installed-state-aware buttons (US-001, US-002).
|
|
6
|
+
//
|
|
7
|
+
// Design decisions (see .specweave/increments/0827.../plan.md §A and ADRs):
|
|
8
|
+
// - Lockfile (vskill.lock) is the single source of truth for install state.
|
|
9
|
+
// Project lockfile = project-scope; ~/.agents/vskill.lock = user-scope.
|
|
10
|
+
// - detectInstalledAgents() (agents-registry.ts:853) drives the
|
|
11
|
+
// `detectedAgentTools` list — same heuristic used by `vskill install`,
|
|
12
|
+
// so the studio's tooltips list exactly the destinations the CLI would
|
|
13
|
+
// touch.
|
|
14
|
+
// - Localhost-only (mirrors install-skill-routes.ts:49). No auth, no
|
|
15
|
+
// platform-proxy involvement.
|
|
16
|
+
// - SAFE_NAME validation (mirrors install-skill-routes.ts:29) — rejects
|
|
17
|
+
// paths starting with --, shell metacharacters, etc., before the
|
|
18
|
+
// identifier touches any filesystem code.
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { sendJson } from "./router.js";
|
|
22
|
+
import { readLockfile } from "../lockfile/lockfile.js";
|
|
23
|
+
import { detectInstalledAgents } from "../agents/agents-registry.js";
|
|
24
|
+
const SAFE_NAME = /^[a-zA-Z0-9._@/\-]+$/;
|
|
25
|
+
const PLACEHOLDER_VERSION = "0.0.0";
|
|
26
|
+
function isLocalhost(req) {
|
|
27
|
+
const addr = req.socket.remoteAddress ?? "";
|
|
28
|
+
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
29
|
+
}
|
|
30
|
+
function userLockDir() {
|
|
31
|
+
return join(homedir(), ".agents");
|
|
32
|
+
}
|
|
33
|
+
function lastSegment(name) {
|
|
34
|
+
const idx = name.lastIndexOf("/");
|
|
35
|
+
return idx === -1 ? name : name.slice(idx + 1);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Look up a skill in a lockfile by either the full publisher/slug name or its
|
|
39
|
+
* last segment. The lockfile keys skills by short name (e.g. "postiz"), but
|
|
40
|
+
* the studio passes full names ("gitroomhq/postiz-agent/postiz"). When two
|
|
41
|
+
* skills collide on the same short name, the `source` field disambiguates —
|
|
42
|
+
* we accept the entry only if `source` references the publisher path.
|
|
43
|
+
*/
|
|
44
|
+
function findSkillEntry(lock, fullName) {
|
|
45
|
+
if (!lock?.skills)
|
|
46
|
+
return null;
|
|
47
|
+
const short = lastSegment(fullName);
|
|
48
|
+
const entry = lock.skills[short];
|
|
49
|
+
if (!entry)
|
|
50
|
+
return null;
|
|
51
|
+
// Disambiguate by `source` when present. Format: "marketplace:<owner>/<repo>#<skill>"
|
|
52
|
+
// or "github:<owner>/<repo>". If we recognize the format, require the publisher
|
|
53
|
+
// path to be a prefix of the requested fullName. Unknown formats pass through.
|
|
54
|
+
if (entry.source && fullName.includes("/")) {
|
|
55
|
+
const ownerRepoMatch = entry.source.match(/(?:marketplace|github):([^#]+?)(?:#|$)/);
|
|
56
|
+
if (ownerRepoMatch) {
|
|
57
|
+
const ownerRepo = ownerRepoMatch[1];
|
|
58
|
+
// fullName is `<owner>/<repo>/<slug>`; ownerRepo is `<owner>/<repo>`.
|
|
59
|
+
const expectedPrefix = `${ownerRepo}/`;
|
|
60
|
+
if (!fullName.startsWith(expectedPrefix))
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return entry;
|
|
65
|
+
}
|
|
66
|
+
function buildScopeState(lock, fullName) {
|
|
67
|
+
const entry = findSkillEntry(lock, fullName);
|
|
68
|
+
if (!entry) {
|
|
69
|
+
return { installed: false, installedAgentTools: [], version: null };
|
|
70
|
+
}
|
|
71
|
+
const installedAgentTools = Array.isArray(lock?.agents) ? [...lock.agents] : [];
|
|
72
|
+
const rawVersion = typeof entry.version === "string" ? entry.version : "";
|
|
73
|
+
const version = rawVersion && rawVersion !== PLACEHOLDER_VERSION ? rawVersion : null;
|
|
74
|
+
return { installed: true, installedAgentTools, version };
|
|
75
|
+
}
|
|
76
|
+
export function registerInstallStateRoutes(router, root) {
|
|
77
|
+
router.get("/api/studio/install-state", async (req, res) => {
|
|
78
|
+
if (!isLocalhost(req)) {
|
|
79
|
+
sendJson(res, { error: "localhost-only endpoint" }, 403, req);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const url = new URL(req.url ?? "/", `http://${req.headers.host || "localhost"}`);
|
|
83
|
+
const skill = url.searchParams.get("skill")?.trim() ?? "";
|
|
84
|
+
// Reject leading "-" in addition to the regex check so identifiers can't
|
|
85
|
+
// be confused with CLI flags downstream (defense-in-depth even though
|
|
86
|
+
// this handler doesn't spawn a process).
|
|
87
|
+
if (!skill || skill.startsWith("-") || !SAFE_NAME.test(skill)) {
|
|
88
|
+
sendJson(res, { error: "invalid skill identifier" }, 400, req);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const detectedAgents = await detectInstalledAgents();
|
|
92
|
+
const detectedAgentTools = detectedAgents.map((a) => ({
|
|
93
|
+
id: a.id,
|
|
94
|
+
displayName: a.displayName,
|
|
95
|
+
localDir: a.localSkillsDir,
|
|
96
|
+
globalDir: a.globalSkillsDir,
|
|
97
|
+
}));
|
|
98
|
+
const projectLock = readLockfile(root);
|
|
99
|
+
const userLock = readLockfile(userLockDir());
|
|
100
|
+
const body = {
|
|
101
|
+
skill,
|
|
102
|
+
detectedAgentTools,
|
|
103
|
+
scopes: {
|
|
104
|
+
project: buildScopeState(projectLock, skill),
|
|
105
|
+
user: buildScopeState(userLock, skill),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
sendJson(res, body, 200, req);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=install-state-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-state-routes.js","sourceRoot":"","sources":["../../src/eval-server/install-state-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type OriginSource = "platform" | "anthropic-registry" | "local";
|
|
2
|
+
export type OriginProvider = "vskill" | "anthropic" | "local";
|
|
3
|
+
export interface OriginEnvelope {
|
|
4
|
+
source: OriginSource;
|
|
5
|
+
owner: string | null;
|
|
6
|
+
repo: string | null;
|
|
7
|
+
provider: OriginProvider;
|
|
8
|
+
trackedForUpdates: boolean;
|
|
9
|
+
/** Lockfile dir that produced the hit (for debugging). */
|
|
10
|
+
lockfilePath?: string;
|
|
11
|
+
/** Frontmatter source string when Tier 3 hits (debug). */
|
|
12
|
+
frontmatterSource?: string;
|
|
13
|
+
/** Registry key when Tier 4 hits (debug). */
|
|
14
|
+
registryMatch?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Well-known Anthropic-shipped skills. Mapped to their canonical
|
|
18
|
+
* `anthropics/skills/<name>` upstream (the verified-skill.com URL pattern
|
|
19
|
+
* for skills published from the `anthropics/skills` GitHub repo) so the
|
|
20
|
+
* Versions tab can fetch upstream history even when the skill arrived
|
|
21
|
+
* without a vskill lockfile entry.
|
|
22
|
+
*
|
|
23
|
+
* Verified live (2026-05-01): `https://verified-skill.com/api/v1/skills/anthropics/skills/pptx/versions`
|
|
24
|
+
* returns `{ versions, count, unversioned, currentVersion }` JSON. The
|
|
25
|
+
* `anthropic-skills/<name>` pattern (with hyphen) returns 404.
|
|
26
|
+
*
|
|
27
|
+
* Maintained as a hand-curated list. Add new names as Anthropic ships them.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ANTHROPIC_SKILL_REGISTRY: Record<string, {
|
|
30
|
+
owner: string;
|
|
31
|
+
repo: string;
|
|
32
|
+
}>;
|
|
33
|
+
/** Test-only: clear the in-process cache between cases. */
|
|
34
|
+
export declare function resetOriginResolverCache(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a skill's full provenance envelope.
|
|
37
|
+
*
|
|
38
|
+
* @param skill — bare skill slug (e.g. "slack-messaging")
|
|
39
|
+
* @param plugin — the plugin/agent dir the skill is mounted under (e.g. ".claude")
|
|
40
|
+
* @param root — the studio process cwd (project root)
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveSkillOrigin(skill: string, plugin: string | null, root: string): Promise<OriginEnvelope>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// 0823 — Comprehensive Origin Resolver for Skill Provenance.
|
|
2
|
+
//
|
|
3
|
+
// Determines where a skill came from so the Versions tab + rescan can fetch
|
|
4
|
+
// upstream version history. Walks five tiers; first hit wins.
|
|
5
|
+
//
|
|
6
|
+
// (1) project lockfile `<root>/vskill.lock`
|
|
7
|
+
// (2) user-global lockfile `~/.agents/vskill.lock`
|
|
8
|
+
// (3) frontmatter `source:` field in SKILL.md (deferred — present in interface,
|
|
9
|
+
// wired in a follow-up; today this tier is reserved and falls through.)
|
|
10
|
+
// (4) Anthropic-skill registry (well-known names → anthropics/skills/<name>)
|
|
11
|
+
// — see ANTHROPIC_SKILL_REGISTRY below. Verified-live URL pattern.
|
|
12
|
+
// (5) bare-name fallback / unknown (provider="local", no upstream)
|
|
13
|
+
//
|
|
14
|
+
// IMPORTANT: cache resolved envelopes to avoid repeated lockfile reads, but
|
|
15
|
+
// DO NOT cache the "local" fallback — a future install would otherwise be
|
|
16
|
+
// invisible until studio restart.
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { readLockfile } from "../lockfile/lockfile.js";
|
|
20
|
+
import { parseSource } from "../resolvers/source-resolver.js";
|
|
21
|
+
/**
|
|
22
|
+
* Well-known Anthropic-shipped skills. Mapped to their canonical
|
|
23
|
+
* `anthropics/skills/<name>` upstream (the verified-skill.com URL pattern
|
|
24
|
+
* for skills published from the `anthropics/skills` GitHub repo) so the
|
|
25
|
+
* Versions tab can fetch upstream history even when the skill arrived
|
|
26
|
+
* without a vskill lockfile entry.
|
|
27
|
+
*
|
|
28
|
+
* Verified live (2026-05-01): `https://verified-skill.com/api/v1/skills/anthropics/skills/pptx/versions`
|
|
29
|
+
* returns `{ versions, count, unversioned, currentVersion }` JSON. The
|
|
30
|
+
* `anthropic-skills/<name>` pattern (with hyphen) returns 404.
|
|
31
|
+
*
|
|
32
|
+
* Maintained as a hand-curated list. Add new names as Anthropic ships them.
|
|
33
|
+
*/
|
|
34
|
+
export const ANTHROPIC_SKILL_REGISTRY = {
|
|
35
|
+
"slack-messaging": { owner: "anthropics", repo: "skills" },
|
|
36
|
+
pptx: { owner: "anthropics", repo: "skills" },
|
|
37
|
+
"excalidraw-diagram-generator": { owner: "anthropics", repo: "skills" },
|
|
38
|
+
"excalidraw-skill": { owner: "anthropics", repo: "skills" },
|
|
39
|
+
"frontend-design": { owner: "anthropics", repo: "skills" },
|
|
40
|
+
gws: { owner: "anthropics", repo: "skills" },
|
|
41
|
+
"remotion-best-practices": { owner: "anthropics", repo: "skills" },
|
|
42
|
+
"social-media-posting": { owner: "anthropics", repo: "skills" },
|
|
43
|
+
"webapp-testing": { owner: "anthropics", repo: "skills" },
|
|
44
|
+
"obsidian-brain": { owner: "anthropics", repo: "skills" },
|
|
45
|
+
nanobanana: { owner: "anthropics", repo: "skills" },
|
|
46
|
+
pdf: { owner: "anthropics", repo: "skills" },
|
|
47
|
+
docx: { owner: "anthropics", repo: "skills" },
|
|
48
|
+
xlsx: { owner: "anthropics", repo: "skills" },
|
|
49
|
+
"skill-creator": { owner: "anthropics", repo: "skills" },
|
|
50
|
+
};
|
|
51
|
+
// 0823 simplify: cap the cache so a long-lived studio process polling many
|
|
52
|
+
// distinct (plugin, skill) combinations doesn't grow unboundedly. The Map's
|
|
53
|
+
// insertion-order semantics give us cheap LRU-ish eviction: when we exceed
|
|
54
|
+
// MAX_CACHE_ENTRIES, drop the oldest entries until under the soft limit.
|
|
55
|
+
const MAX_CACHE_ENTRIES = 1000;
|
|
56
|
+
const PRUNE_TARGET = 500;
|
|
57
|
+
const cache = new Map();
|
|
58
|
+
function setCacheEntry(key, value) {
|
|
59
|
+
cache.set(key, value);
|
|
60
|
+
if (cache.size > MAX_CACHE_ENTRIES) {
|
|
61
|
+
const dropCount = cache.size - PRUNE_TARGET;
|
|
62
|
+
let i = 0;
|
|
63
|
+
for (const k of cache.keys()) {
|
|
64
|
+
if (i++ >= dropCount)
|
|
65
|
+
break;
|
|
66
|
+
cache.delete(k);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Test-only: clear the in-process cache between cases. */
|
|
71
|
+
export function resetOriginResolverCache() {
|
|
72
|
+
cache.clear();
|
|
73
|
+
}
|
|
74
|
+
function tryLockfileTier(skill, dir) {
|
|
75
|
+
let lock;
|
|
76
|
+
try {
|
|
77
|
+
lock = readLockfile(dir);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const entry = lock?.skills?.[skill];
|
|
83
|
+
if (!entry?.source)
|
|
84
|
+
return null;
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = parseSource(entry.source);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
if ((parsed.type === "github" ||
|
|
93
|
+
parsed.type === "github-plugin" ||
|
|
94
|
+
parsed.type === "marketplace") &&
|
|
95
|
+
parsed.owner &&
|
|
96
|
+
parsed.repo) {
|
|
97
|
+
return { owner: parsed.owner, repo: parsed.repo };
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve a skill's full provenance envelope.
|
|
103
|
+
*
|
|
104
|
+
* @param skill — bare skill slug (e.g. "slack-messaging")
|
|
105
|
+
* @param plugin — the plugin/agent dir the skill is mounted under (e.g. ".claude")
|
|
106
|
+
* @param root — the studio process cwd (project root)
|
|
107
|
+
*/
|
|
108
|
+
export async function resolveSkillOrigin(skill, plugin, root) {
|
|
109
|
+
const cacheKey = `${plugin ?? ""}::${skill}`;
|
|
110
|
+
const cached = cache.get(cacheKey);
|
|
111
|
+
if (cached)
|
|
112
|
+
return cached;
|
|
113
|
+
// Tier 1 — project lockfile
|
|
114
|
+
const projectHit = tryLockfileTier(skill, root);
|
|
115
|
+
if (projectHit) {
|
|
116
|
+
const env = {
|
|
117
|
+
source: "platform",
|
|
118
|
+
owner: projectHit.owner,
|
|
119
|
+
repo: projectHit.repo,
|
|
120
|
+
provider: "vskill",
|
|
121
|
+
trackedForUpdates: true,
|
|
122
|
+
lockfilePath: root,
|
|
123
|
+
};
|
|
124
|
+
setCacheEntry(cacheKey, env);
|
|
125
|
+
return env;
|
|
126
|
+
}
|
|
127
|
+
// Tier 2 — user-global lockfile (~/.agents/vskill.lock)
|
|
128
|
+
const globalDir = join(homedir(), ".agents");
|
|
129
|
+
const globalHit = tryLockfileTier(skill, globalDir);
|
|
130
|
+
if (globalHit) {
|
|
131
|
+
const env = {
|
|
132
|
+
source: "platform",
|
|
133
|
+
owner: globalHit.owner,
|
|
134
|
+
repo: globalHit.repo,
|
|
135
|
+
provider: "vskill",
|
|
136
|
+
trackedForUpdates: true,
|
|
137
|
+
lockfilePath: globalDir,
|
|
138
|
+
};
|
|
139
|
+
setCacheEntry(cacheKey, env);
|
|
140
|
+
return env;
|
|
141
|
+
}
|
|
142
|
+
// Tier 3 — frontmatter `source:` field. Reserved; not yet wired (no
|
|
143
|
+
// installed-skill writes a frontmatter origin today). Tier-skipped silently.
|
|
144
|
+
// Tier 4 — Anthropic-skill registry
|
|
145
|
+
const registryHit = ANTHROPIC_SKILL_REGISTRY[skill];
|
|
146
|
+
if (registryHit) {
|
|
147
|
+
const env = {
|
|
148
|
+
source: "anthropic-registry",
|
|
149
|
+
owner: registryHit.owner,
|
|
150
|
+
repo: registryHit.repo,
|
|
151
|
+
provider: "anthropic",
|
|
152
|
+
trackedForUpdates: true,
|
|
153
|
+
registryMatch: skill,
|
|
154
|
+
};
|
|
155
|
+
setCacheEntry(cacheKey, env);
|
|
156
|
+
return env;
|
|
157
|
+
}
|
|
158
|
+
// Tier 5 — local / unknown. NOT cached so a future install becomes visible
|
|
159
|
+
// without a studio restart.
|
|
160
|
+
return {
|
|
161
|
+
source: "local",
|
|
162
|
+
owner: null,
|
|
163
|
+
repo: null,
|
|
164
|
+
provider: "local",
|
|
165
|
+
trackedForUpdates: false,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=origin-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin-resolver.js","sourceRoot":"","sources":["../../src/eval-server/origin-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import * as http from "node:http";
|
|
2
2
|
export declare function getPlatformBaseUrl(): string;
|
|
3
3
|
export declare function shouldProxyToPlatform(url: string | undefined): boolean;
|
|
4
|
+
export declare function shouldInjectAuth(url: string | undefined): boolean;
|
|
5
|
+
/** Test-only reset hook. */
|
|
6
|
+
export declare function _resetPlatformProxyAuthCacheForTests(): void;
|
|
7
|
+
export interface PickHeadersOptions {
|
|
8
|
+
/** Request path (e.g. "/api/v1/tenants/abc/skills"). */
|
|
9
|
+
path?: string;
|
|
10
|
+
/** Token provider override; defaults to in-process cached keychain read. */
|
|
11
|
+
tokenProvider?: () => string | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function pickHeadersForUpstream(src: http.IncomingHttpHeaders, opts?: PickHeadersOptions): Record<string, string>;
|
|
4
14
|
/**
|
|
5
15
|
* Proxy a single HTTP request from the studio to the platform.
|
|
6
16
|
* SSE-safe: streams the upstream body chunks directly to the response so
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
import * as http from "node:http";
|
|
51
51
|
import * as https from "node:https";
|
|
52
52
|
import { randomUUID } from "node:crypto";
|
|
53
|
+
import { getDefaultKeychain } from "../lib/keychain.js";
|
|
53
54
|
const DEFAULT_PLATFORM_URL = "https://verified-skill.com";
|
|
54
55
|
// Hop-by-hop headers per RFC 2616 §13.5.1 — never forward these on a proxy.
|
|
55
56
|
const HOP_BY_HOP = new Set([
|
|
@@ -88,24 +89,79 @@ const PROXY_PREFIXES = [
|
|
|
88
89
|
"/api/v1/studio/search",
|
|
89
90
|
"/api/v1/studio/telemetry/",
|
|
90
91
|
"/api/v1/stats",
|
|
92
|
+
// Private (org-scoped) routes that must carry the user's GitHub bearer token
|
|
93
|
+
// to the platform. The browser never sees this token; injection happens here.
|
|
94
|
+
"/api/v1/private/",
|
|
95
|
+
"/api/v1/tenants/",
|
|
96
|
+
];
|
|
97
|
+
/**
|
|
98
|
+
* Path prefixes that require an `Authorization: Bearer <github-token>` header
|
|
99
|
+
* to be injected at the proxy boundary. Public skill routes are intentionally
|
|
100
|
+
* excluded — they must remain anonymous so unauthenticated tabs continue to
|
|
101
|
+
* function in the public skill catalog.
|
|
102
|
+
*/
|
|
103
|
+
const AUTH_REQUIRED_PREFIXES = [
|
|
104
|
+
"/api/v1/private/",
|
|
105
|
+
"/api/v1/tenants/",
|
|
91
106
|
];
|
|
92
107
|
export function shouldProxyToPlatform(url) {
|
|
93
108
|
if (!url)
|
|
94
109
|
return false;
|
|
95
110
|
return PROXY_PREFIXES.some((p) => url.startsWith(p));
|
|
96
111
|
}
|
|
97
|
-
function
|
|
112
|
+
export function shouldInjectAuth(url) {
|
|
113
|
+
if (!url)
|
|
114
|
+
return false;
|
|
115
|
+
return AUTH_REQUIRED_PREFIXES.some((p) => url.startsWith(p));
|
|
116
|
+
}
|
|
117
|
+
// In-process token cache so a burst of proxy requests doesn't repeatedly hit
|
|
118
|
+
// the OS keychain. The keychain itself is fast on macOS but can be slower on
|
|
119
|
+
// Linux libsecret. 60s aligns with how stale a manual `vskill auth login`
|
|
120
|
+
// → `vskill studio refresh` loop would feel.
|
|
121
|
+
let _cachedToken = null;
|
|
122
|
+
const TOKEN_CACHE_MS = 60_000;
|
|
123
|
+
function readTokenForProxy(now = Date.now()) {
|
|
124
|
+
if (_cachedToken && _cachedToken.expiresAt > now)
|
|
125
|
+
return _cachedToken.value;
|
|
126
|
+
let token = null;
|
|
127
|
+
try {
|
|
128
|
+
token = getDefaultKeychain().getGitHubToken();
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
token = null;
|
|
132
|
+
}
|
|
133
|
+
_cachedToken = { value: token, expiresAt: now + TOKEN_CACHE_MS };
|
|
134
|
+
return token;
|
|
135
|
+
}
|
|
136
|
+
/** Test-only reset hook. */
|
|
137
|
+
export function _resetPlatformProxyAuthCacheForTests() {
|
|
138
|
+
_cachedToken = null;
|
|
139
|
+
}
|
|
140
|
+
export function pickHeadersForUpstream(src, opts = {}) {
|
|
98
141
|
const out = {};
|
|
99
142
|
for (const [k, v] of Object.entries(src)) {
|
|
100
143
|
if (typeof v === "undefined")
|
|
101
144
|
continue;
|
|
102
145
|
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
103
146
|
continue;
|
|
147
|
+
// Strip any client-supplied Authorization on private/tenant paths — we
|
|
148
|
+
// mint our own from the keychain. On other paths we pass through (the
|
|
149
|
+
// existing public proxy never carried Authorization, so this is a no-op).
|
|
150
|
+
if (k.toLowerCase() === "authorization" && opts.path && shouldInjectAuth(opts.path)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
104
153
|
out[k] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
105
154
|
}
|
|
106
155
|
// Preserve client-IP intent for any future platform-side observability.
|
|
107
156
|
const xff = out["x-forwarded-for"];
|
|
108
157
|
out["x-forwarded-for"] = xff ? `${xff}, 127.0.0.1` : "127.0.0.1";
|
|
158
|
+
if (opts.path && shouldInjectAuth(opts.path)) {
|
|
159
|
+
const tokenProvider = opts.tokenProvider ?? (() => readTokenForProxy());
|
|
160
|
+
const token = tokenProvider();
|
|
161
|
+
if (token) {
|
|
162
|
+
out["authorization"] = `Bearer ${token}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
109
165
|
return out;
|
|
110
166
|
}
|
|
111
167
|
function pickHeadersForDownstream(src) {
|
|
@@ -138,7 +194,7 @@ export function proxyToPlatform(req, res, baseUrl = getPlatformBaseUrl()) {
|
|
|
138
194
|
port: target.port || (target.protocol === "https:" ? 443 : 80),
|
|
139
195
|
path: `${target.pathname}${target.search}`,
|
|
140
196
|
method: req.method,
|
|
141
|
-
headers: pickHeadersForUpstream(req.headers),
|
|
197
|
+
headers: pickHeadersForUpstream(req.headers, { path: target.pathname }),
|
|
142
198
|
}, (upstreamRes) => {
|
|
143
199
|
const status = upstreamRes.statusCode ?? 502;
|
|
144
200
|
const headers = pickHeadersForDownstream(upstreamRes.headers);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-proxy.js","sourceRoot":"","sources":["../../src/eval-server/platform-proxy.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,gDAAgD;AAChD,EAAE;AACF,iFAAiF;AACjF,wEAAwE;AACxE,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,4BAA4B;AAC5B,EAAE;AACF,gBAAgB;AAChB,wEAAwE;AACxE,2EAA2E;AAC3E,kFAAkF;AAClF,4DAA4D;AAC5D,yEAAyE;AACzE,wEAAwE;AACxE,0EAA0E;AAC1E,oCAAoC;AACpC,oEAAoE;AACpE,4CAA4C;AAC5C,mEAAmE;AACnE,qEAAqE;AACrE,0CAA0C;AAC1C,EAAE;AACF,yDAAyD;AACzD,0DAA0D;AAC1D,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,qEAAqE;AACrE,EAAE;AACF,2EAA2E;AAC3E,0EAA0E;AAC1E,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,EAAE;AACF,0EAA0E;AAC1E,sEAAsE;AACtE,yEAAyE;AACzE,8EAA8E;AAE9E,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-proxy.js","sourceRoot":"","sources":["../../src/eval-server/platform-proxy.ts"],"names":[],"mappings":"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"}
|