skilld 1.7.4 → 2.0.0
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/_chunks/add.mjs +66 -0
- package/dist/_chunks/add.mjs.map +1 -0
- package/dist/_chunks/agent-prompt.mjs +88 -0
- package/dist/_chunks/agent-prompt.mjs.map +1 -0
- package/dist/_chunks/agent.mjs +81 -57
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/args.mjs +42 -0
- package/dist/_chunks/args.mjs.map +1 -0
- package/dist/_chunks/assemble.mjs +10 -7
- package/dist/_chunks/assemble.mjs.map +1 -1
- package/dist/_chunks/author.mjs +33 -17
- package/dist/_chunks/author.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +143 -183
- package/dist/_chunks/cache.mjs.map +1 -1
- package/dist/_chunks/cache2.mjs +7 -6
- package/dist/_chunks/cache2.mjs.map +1 -1
- package/dist/_chunks/client.mjs +117 -0
- package/dist/_chunks/client.mjs.map +1 -0
- package/dist/_chunks/core.mjs +5 -5
- package/dist/_chunks/detect.mjs +53 -43
- package/dist/_chunks/detect.mjs.map +1 -1
- package/dist/_chunks/eject.mjs +69 -0
- package/dist/_chunks/eject.mjs.map +1 -0
- package/dist/_chunks/embedding-cache2.mjs +1 -1
- package/dist/_chunks/env.mjs +19 -0
- package/dist/_chunks/env.mjs.map +1 -0
- package/dist/_chunks/install-many.mjs +376 -0
- package/dist/_chunks/install-many.mjs.map +1 -0
- package/dist/_chunks/install.mjs +81 -326
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/intro.mjs +63 -0
- package/dist/_chunks/intro.mjs.map +1 -0
- package/dist/_chunks/list.mjs +2 -2
- package/dist/_chunks/list.mjs.map +1 -1
- package/dist/_chunks/lockfile.mjs +3 -2
- package/dist/_chunks/lockfile.mjs.map +1 -1
- package/dist/_chunks/login.mjs +233 -0
- package/dist/_chunks/login.mjs.map +1 -0
- package/dist/_chunks/logout.mjs +27 -0
- package/dist/_chunks/logout.mjs.map +1 -0
- package/dist/_chunks/map.mjs +11 -0
- package/dist/_chunks/map.mjs.map +1 -0
- package/dist/_chunks/markdown.mjs +79 -54
- package/dist/_chunks/markdown.mjs.map +1 -1
- package/dist/_chunks/menu.mjs +33 -0
- package/dist/_chunks/menu.mjs.map +1 -0
- package/dist/_chunks/model-picker.mjs +61 -0
- package/dist/_chunks/model-picker.mjs.map +1 -0
- package/dist/_chunks/monorepo.mjs +4 -2
- package/dist/_chunks/monorepo.mjs.map +1 -1
- package/dist/_chunks/package-json.mjs.map +1 -1
- package/dist/_chunks/paths.mjs +3 -5
- package/dist/_chunks/paths.mjs.map +1 -1
- package/dist/_chunks/{sync-pipeline.mjs → pipeline.mjs} +346 -313
- package/dist/_chunks/pipeline.mjs.map +1 -0
- package/dist/_chunks/pool2.mjs +1 -1
- package/dist/_chunks/portable.mjs +151 -0
- package/dist/_chunks/portable.mjs.map +1 -0
- package/dist/_chunks/prepare-hook.mjs +2 -0
- package/dist/_chunks/prepare-hook2.mjs +61 -0
- package/dist/_chunks/prepare-hook2.mjs.map +1 -0
- package/dist/_chunks/prepare.mjs +47 -3
- package/dist/_chunks/prepare.mjs.map +1 -1
- package/dist/_chunks/prepare2.mjs +7 -6
- package/dist/_chunks/prepare2.mjs.map +1 -1
- package/dist/_chunks/prompts.mjs +484 -74
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/pull.mjs +219 -0
- package/dist/_chunks/pull.mjs.map +1 -0
- package/dist/_chunks/regex.mjs +19 -0
- package/dist/_chunks/regex.mjs.map +1 -0
- package/dist/_chunks/retriv.mjs +2 -171
- package/dist/_chunks/retriv2.mjs +159 -0
- package/dist/_chunks/retriv2.mjs.map +1 -0
- package/dist/_chunks/sanitize.mjs +12 -9
- package/dist/_chunks/sanitize.mjs.map +1 -1
- package/dist/_chunks/search-helpers.mjs +8 -6
- package/dist/_chunks/search-helpers.mjs.map +1 -1
- package/dist/_chunks/search-interactive.mjs +23 -20
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +3 -3
- package/dist/_chunks/search.mjs.map +1 -1
- package/dist/_chunks/semver.mjs +2755 -1
- package/dist/_chunks/semver.mjs.map +1 -1
- package/dist/_chunks/skill-installer2.mjs +10 -11
- package/dist/_chunks/skill-installer2.mjs.map +1 -1
- package/dist/_chunks/skills.mjs +6 -7
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/_chunks/store.mjs +107 -0
- package/dist/_chunks/store.mjs.map +1 -0
- package/dist/_chunks/sync.mjs +411 -910
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/sync2.mjs +2 -5
- package/dist/_chunks/telemetry.mjs +26 -0
- package/dist/_chunks/telemetry.mjs.map +1 -0
- package/dist/_chunks/uninstall.mjs +12 -9
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/update.mjs +171 -0
- package/dist/_chunks/update.mjs.map +1 -0
- package/dist/_chunks/upload.mjs +3 -3
- package/dist/_chunks/validate.mjs +1 -1
- package/dist/_chunks/version.mjs +16 -17
- package/dist/_chunks/version.mjs.map +1 -1
- package/dist/_chunks/whoami.mjs +21 -0
- package/dist/_chunks/whoami.mjs.map +1 -0
- package/dist/_chunks/wizard.mjs +2 -190
- package/dist/_chunks/wizard2.mjs +200 -0
- package/dist/_chunks/wizard2.mjs.map +1 -0
- package/dist/cli.mjs +72 -53
- package/dist/cli.mjs.map +1 -1
- package/dist/prepare.mjs +4 -3
- package/dist/prepare.mjs.map +1 -1
- package/dist/retriv/worker.d.mts +5 -1
- package/dist/retriv/worker.d.mts.map +1 -1
- package/dist/retriv/worker.mjs +1 -1
- package/package.json +19 -28
- package/dist/_chunks/author-group.mjs +0 -17
- package/dist/_chunks/author-group.mjs.map +0 -1
- package/dist/_chunks/cli-helpers.mjs +0 -335
- package/dist/_chunks/cli-helpers.mjs.map +0 -1
- package/dist/_chunks/cli-helpers2.mjs +0 -2
- package/dist/_chunks/index.d.mts +0 -344
- package/dist/_chunks/index.d.mts.map +0 -1
- package/dist/_chunks/index2.d.mts +0 -279
- package/dist/_chunks/index2.d.mts.map +0 -1
- package/dist/_chunks/index3.d.mts +0 -44
- package/dist/_chunks/index3.d.mts.map +0 -1
- package/dist/_chunks/index4.d.mts +0 -553
- package/dist/_chunks/index4.d.mts.map +0 -1
- package/dist/_chunks/package-registry.mjs +0 -465
- package/dist/_chunks/package-registry.mjs.map +0 -1
- package/dist/_chunks/retriv.mjs.map +0 -1
- package/dist/_chunks/setup.mjs +0 -17
- package/dist/_chunks/setup.mjs.map +0 -1
- package/dist/_chunks/sources.mjs +0 -2654
- package/dist/_chunks/sources.mjs.map +0 -1
- package/dist/_chunks/sync-pipeline.mjs.map +0 -1
- package/dist/_chunks/sync-registry.mjs +0 -65
- package/dist/_chunks/sync-registry.mjs.map +0 -1
- package/dist/_chunks/types.d.mts +0 -76
- package/dist/_chunks/types.d.mts.map +0 -1
- package/dist/_chunks/types2.d.mts +0 -88
- package/dist/_chunks/types2.d.mts.map +0 -1
- package/dist/_chunks/wizard.mjs.map +0 -1
- package/dist/agent/index.d.mts +0 -2
- package/dist/agent/index.mjs +0 -4
- package/dist/cache/index.d.mts +0 -2
- package/dist/cache/index.mjs +0 -5
- package/dist/index.d.mts +0 -6
- package/dist/index.mjs +0 -6
- package/dist/retriv/index.d.mts +0 -3
- package/dist/retriv/index.mjs +0 -2
- package/dist/sources/index.d.mts +0 -3
- package/dist/sources/index.mjs +0 -3
- package/dist/types.d.mts +0 -4
- package/dist/types.mjs +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) =>
|
|
1
|
+
{"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) => styleText('gray', s)\n\n const refs = dirEntries(REFERENCES_DIR)\n const repos = dirEntries(REPOS_DIR)\n const llm = dirEntries(LLM_CACHE_DIR)\n const embPath = join(CACHE_DIR, 'embeddings.db')\n const embSize = existsSync(embPath) ? statSync(embPath).size : 0\n\n // Count packages: top-level non-scoped dirs + dirs inside @scope/ dirs\n const packages = refs.filter(e =>\n e.isDirectory()\n && (e.parentPath === REFERENCES_DIR\n ? !e.name.startsWith('@')\n : e.parentPath.startsWith(REFERENCES_DIR)),\n ).length\n\n const llmFiles = llm.filter(e => e.isFile())\n const sizes = { refs: sumFileBytes(refs), repos: sumFileBytes(repos), llm: sumFileBytes(llmFiles), emb: embSize }\n const total = sizes.refs + sizes.repos + sizes.llm + sizes.emb\n\n const lines = [\n `References ${fmtBytes(sizes.refs)} ${dim(`${packages} packages`)}`,\n ...(sizes.repos > 0 ? [`Repos ${fmtBytes(sizes.repos)}`] : []),\n `LLM cache ${fmtBytes(sizes.llm)} ${dim(`${llmFiles.length} entries`)}`,\n ...(sizes.emb > 0 ? [`Embeddings ${fmtBytes(sizes.emb)}`] : []),\n '',\n `Total ${fmtBytes(total)} ${dim(CACHE_DIR)}`,\n ]\n p.log.message(lines.join('\\n'))\n}\n\nexport const cacheCommandDef = defineCommand({\n meta: { name: 'cache', description: 'Cache management', hidden: true },\n args: {\n clean: {\n type: 'boolean',\n alias: 'c',\n description: 'Remove expired enhancement cache entries',\n default: false,\n },\n stats: {\n type: 'boolean',\n alias: 's',\n description: 'Show cache disk usage',\n default: false,\n },\n },\n async run({ args }) {\n if (args.stats) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache stats`)\n cacheStatsCommand()\n return\n }\n if (args.clean) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache clean`)\n await cacheCleanCommand()\n return\n }\n // No flag: show usage\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache`)\n p.log.message('Usage:\\n skilld cache --clean Remove expired cache entries\\n skilld cache --stats Show cache disk usage')\n },\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { m as TRAILING_SLASH_RE } from "./regex.mjs";
|
|
2
|
+
import { ofetch } from "ofetch";
|
|
3
|
+
const DEFAULT_REGISTRY_URL = "https://skilld.dev/api";
|
|
4
|
+
function getRegistryBase() {
|
|
5
|
+
return (process.env.SKILLD_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(TRAILING_SLASH_RE, "");
|
|
6
|
+
}
|
|
7
|
+
function gateInstall(result, opts) {
|
|
8
|
+
switch (result.status) {
|
|
9
|
+
case "pass": return "install";
|
|
10
|
+
case "warn": return "install";
|
|
11
|
+
case "fail": return opts.allowUnsafe ? "install" : "skip";
|
|
12
|
+
case "unaudited":
|
|
13
|
+
if (opts.sourceKind !== "gh") return "install";
|
|
14
|
+
return opts.yes ? "install" : "prompt";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function aggregateAuditStatus(audits) {
|
|
18
|
+
if (audits.length === 0) return "unaudited";
|
|
19
|
+
if (audits.some((a) => a.status === "fail")) return "fail";
|
|
20
|
+
if (audits.some((a) => a.status === "warn")) return "warn";
|
|
21
|
+
return "pass";
|
|
22
|
+
}
|
|
23
|
+
function createRegistryClient(opts = {}) {
|
|
24
|
+
const base = (opts.baseUrl ?? getRegistryBase()).replace(TRAILING_SLASH_RE, "");
|
|
25
|
+
const headers = opts.session ? { Authorization: `Bearer ${opts.session.accessToken}` } : void 0;
|
|
26
|
+
const fetcher = (url, init) => {
|
|
27
|
+
if (!headers && !init) return ofetch(url);
|
|
28
|
+
if (!headers) return ofetch(url, init);
|
|
29
|
+
return ofetch(url, {
|
|
30
|
+
...init,
|
|
31
|
+
headers: {
|
|
32
|
+
...headers,
|
|
33
|
+
...init?.headers
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const requireSession = () => {
|
|
38
|
+
if (!opts.session) throw new Error("auth required");
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
async resolveSkill(packageName, fetchOpts = {}) {
|
|
42
|
+
const hit = (await fetcher(`${base}/skills/resolve`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
body: { items: [{
|
|
45
|
+
packageName,
|
|
46
|
+
owner: fetchOpts.owner
|
|
47
|
+
}] }
|
|
48
|
+
}).catch(() => null))?.[packageName];
|
|
49
|
+
if (!hit) return null;
|
|
50
|
+
const detail = await fetcher(`${base}/skills/${hit.owner}/${hit.repo}/${packageName}`).catch(() => null);
|
|
51
|
+
if (!detail?.raw) return null;
|
|
52
|
+
return {
|
|
53
|
+
name: detail.name,
|
|
54
|
+
packageName,
|
|
55
|
+
content: detail.raw,
|
|
56
|
+
owner: detail.owner,
|
|
57
|
+
repo: `${detail.owner}/${detail.repo}`,
|
|
58
|
+
displayName: detail.displayName,
|
|
59
|
+
installs: detail.installs,
|
|
60
|
+
official: hit.official,
|
|
61
|
+
branch: detail.branch,
|
|
62
|
+
skillPath: detail.skillPath ?? void 0,
|
|
63
|
+
updatedAt: detail.pushedAt ?? void 0
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
async fetchSkillDetail(owner, repo, name) {
|
|
67
|
+
return fetcher(`${base}/skills/${owner}/${repo}/${name}`).catch(() => null);
|
|
68
|
+
},
|
|
69
|
+
async audit({ owner, repo, name }) {
|
|
70
|
+
const res = await fetcher(`${base}/skill-live/${owner}/${repo}/${name}`).catch(() => null);
|
|
71
|
+
if (!res) return {
|
|
72
|
+
status: "unaudited",
|
|
73
|
+
audits: []
|
|
74
|
+
};
|
|
75
|
+
const audits = res.audits ?? [];
|
|
76
|
+
return {
|
|
77
|
+
status: aggregateAuditStatus(audits),
|
|
78
|
+
riskLevel: res.riskLevel,
|
|
79
|
+
summary: res.summary,
|
|
80
|
+
audits
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
async fetchCollection(login, slug) {
|
|
84
|
+
return fetcher(`${base}/collections/by-author/${login}/${slug}/manifest`).catch(() => null);
|
|
85
|
+
},
|
|
86
|
+
async fetchCurator(login) {
|
|
87
|
+
return fetcher(`${base}/curators/${login}`).catch(() => null);
|
|
88
|
+
},
|
|
89
|
+
my: {
|
|
90
|
+
async collections() {
|
|
91
|
+
requireSession();
|
|
92
|
+
return fetcher(`${base}/me/collections`).catch(() => []);
|
|
93
|
+
},
|
|
94
|
+
async subscriptions() {
|
|
95
|
+
requireSession();
|
|
96
|
+
return fetcher(`${base}/me/subscriptions`).catch(() => []);
|
|
97
|
+
},
|
|
98
|
+
async changes({ since }) {
|
|
99
|
+
requireSession();
|
|
100
|
+
return fetcher(`${base}/cli/changes${since != null ? `?since=${since}` : ""}`).catch(() => null);
|
|
101
|
+
},
|
|
102
|
+
async installs(payload) {
|
|
103
|
+
requireSession();
|
|
104
|
+
await fetcher(`${base}/me/installs`, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
body: payload
|
|
107
|
+
}).catch(() => {});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function fetchRegistrySkill(packageName, opts = {}) {
|
|
113
|
+
return createRegistryClient().resolveSkill(packageName, opts);
|
|
114
|
+
}
|
|
115
|
+
export { getRegistryBase as i, fetchRegistrySkill as n, gateInstall as r, createRegistryClient as t };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../../src/registry/client.ts"],"sourcesContent":["/**\n * Registry client for skilld.dev\n *\n * Talks to the public skilld.dev JSON API: resolves an npm package name to a\n * curated skill's owner/repo, then fetches the detail payload which includes\n * the raw SKILL.md. For local development, set SKILLD_REGISTRY_URL (e.g.\n * http://localhost:3000/api) to point at a running Nuxt dev server.\n *\n * Returns null when a skill isn't curated, the API is unreachable, or the\n * skill has no resolvable SKILL.md, so callers fall through to the\n * doc-generation pipeline.\n */\n\nimport type { AuditStatus } from 'skilld-protocol/constants'\nimport type {\n AuditEntry,\n AuthSession,\n ChangeEntry,\n CollectionManifest,\n CollectionManifestItem,\n CollectionSummary,\n CuratorPayload,\n DigestResponse,\n InstallEventPayload,\n SkillDetailResponse,\n SkillsResolveEntry,\n SkillsResolveResponse,\n SubscriptionSummary,\n} from 'skilld-protocol/wire'\nimport { ofetch } from 'ofetch'\nimport { TRAILING_SLASH_RE } from '../core/regex.ts'\n\nexport type { AuditEntry, AuditStatus, AuthSession, ChangeEntry, CollectionManifest, CollectionManifestItem, CollectionSummary, CuratorPayload, DigestResponse, InstallEventPayload, SkillDetailResponse, SkillsResolveResponse, SubscriptionSummary }\n\nconst DEFAULT_REGISTRY_URL = 'https://skilld.dev/api'\n\nexport function getRegistryBase(): string {\n return (process.env.SKILLD_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(TRAILING_SLASH_RE, '')\n}\n\nexport interface RegistrySkill {\n name: string\n packageName: string\n content: string\n owner: string\n repo: string\n displayName?: string\n installs?: number\n official?: boolean\n branch?: string\n skillPath?: string\n updatedAt?: string\n}\n\nexport interface FetchRegistrySkillOptions {\n owner?: string\n}\n\n/**\n * CLI-internal computed shape. Built locally after fetching the wire\n * `SkillLiveResponse`; `status` is computed by `aggregateAuditStatus`.\n */\nexport interface AuditResult {\n status: AuditStatus\n riskLevel?: 'low' | 'medium' | 'high'\n summary?: string\n audits: AuditEntry[]\n}\n\ninterface AuditApiResponse {\n riskLevel?: 'low' | 'medium' | 'high'\n summary?: string\n audits?: AuditEntry[]\n}\n\nexport interface RegistryClient {\n resolveSkill: (packageName: string, opts?: FetchRegistrySkillOptions) => Promise<RegistrySkill | null>\n fetchSkillDetail: (owner: string, repo: string, name: string) => Promise<SkillDetailResponse | null>\n audit: (params: { owner: string, repo: string, name: string }) => Promise<AuditResult>\n fetchCollection: (login: string, slug: string) => Promise<CollectionManifest | null>\n fetchCurator: (login: string) => Promise<CuratorPayload | null>\n my: {\n collections: () => Promise<CollectionSummary[]>\n subscriptions: () => Promise<SubscriptionSummary[]>\n changes: (params: { since?: number }) => Promise<DigestResponse | null>\n installs: (payload: InstallEventPayload) => Promise<void>\n }\n}\n\nexport type GateDecision = 'install' | 'skip' | 'prompt'\n\nexport interface GateOptions {\n allowUnsafe?: boolean\n yes?: boolean\n /** Source kind drives unaudited behaviour: gh → prompt, npm/crate → silent install */\n sourceKind: 'npm' | 'gh' | 'crate' | 'collection'\n}\n\n/**\n * Pure gating rule from an audit result. Caller is responsible for the prompt\n * itself when the decision is `'prompt'`.\n */\nexport function gateInstall(result: AuditResult, opts: GateOptions): GateDecision {\n switch (result.status) {\n case 'pass':\n return 'install'\n case 'warn':\n return 'install'\n case 'fail':\n return opts.allowUnsafe ? 'install' : 'skip'\n case 'unaudited':\n if (opts.sourceKind !== 'gh')\n return 'install'\n return opts.yes ? 'install' : 'prompt'\n }\n}\n\nexport function aggregateAuditStatus(audits: AuditEntry[]): AuditStatus {\n if (audits.length === 0)\n return 'unaudited'\n if (audits.some(a => a.status === 'fail'))\n return 'fail'\n if (audits.some(a => a.status === 'warn'))\n return 'warn'\n return 'pass'\n}\n\nexport function createRegistryClient(opts: { session?: AuthSession, baseUrl?: string } = {}): RegistryClient {\n const base = (opts.baseUrl ?? getRegistryBase()).replace(TRAILING_SLASH_RE, '')\n const headers = opts.session ? { Authorization: `Bearer ${opts.session.accessToken}` } : undefined\n\n const fetcher = <T>(url: string, init?: Parameters<typeof ofetch<T>>[1]): Promise<T> => {\n if (!headers && !init)\n return ofetch<T>(url)\n if (!headers)\n return ofetch<T>(url, init)\n return ofetch<T>(url, { ...init, headers: { ...headers, ...(init?.headers as any) } })\n }\n\n const requireSession = (): void => {\n if (!opts.session)\n throw new Error('auth required')\n }\n\n return {\n async resolveSkill(packageName, fetchOpts = {}) {\n const resolved = await fetcher<Record<string, SkillsResolveEntry>>(`${base}/skills/resolve`, {\n method: 'POST',\n body: { items: [{ packageName, owner: fetchOpts.owner }] },\n }).catch(() => null)\n\n const hit = resolved?.[packageName]\n if (!hit)\n return null\n\n const detail = await fetcher<SkillDetailResponse>(`${base}/skills/${hit.owner}/${hit.repo}/${packageName}`).catch(() => null)\n if (!detail?.raw)\n return null\n\n return {\n name: detail.name,\n packageName,\n content: detail.raw,\n owner: detail.owner,\n repo: `${detail.owner}/${detail.repo}`,\n displayName: detail.displayName,\n installs: detail.installs,\n official: hit.official,\n branch: detail.branch,\n skillPath: detail.skillPath ?? undefined,\n updatedAt: detail.pushedAt ?? undefined,\n }\n },\n\n async fetchSkillDetail(owner, repo, name) {\n return fetcher<SkillDetailResponse>(`${base}/skills/${owner}/${repo}/${name}`).catch(() => null)\n },\n\n async audit({ owner, repo, name }) {\n const res = await fetcher<AuditApiResponse>(`${base}/skill-live/${owner}/${repo}/${name}`).catch(() => null)\n if (!res)\n return { status: 'unaudited', audits: [] }\n const audits = res.audits ?? []\n return {\n status: aggregateAuditStatus(audits),\n riskLevel: res.riskLevel,\n summary: res.summary,\n audits,\n }\n },\n\n async fetchCollection(login, slug) {\n return fetcher<CollectionManifest>(`${base}/collections/by-author/${login}/${slug}/manifest`).catch(() => null)\n },\n\n async fetchCurator(login) {\n return fetcher<CuratorPayload>(`${base}/curators/${login}`).catch(() => null)\n },\n\n my: {\n async collections() {\n requireSession()\n return fetcher<CollectionSummary[]>(`${base}/me/collections`).catch(() => [])\n },\n async subscriptions() {\n requireSession()\n return fetcher<SubscriptionSummary[]>(`${base}/me/subscriptions`).catch(() => [])\n },\n async changes({ since }) {\n requireSession()\n const qs = since != null ? `?since=${since}` : ''\n return fetcher<DigestResponse>(`${base}/cli/changes${qs}`).catch(() => null)\n },\n async installs(payload) {\n requireSession()\n await fetcher<void>(`${base}/me/installs`, { method: 'POST', body: payload }).catch(() => {})\n },\n },\n }\n}\n\n/**\n * Fetch a curated package skill from the registry.\n * Returns null if no curated skill exists, the SKILL.md can't be loaded, or the API is unreachable.\n *\n * Thin wrapper over `createRegistryClient().resolveSkill` for back-compat.\n */\nexport async function fetchRegistrySkill(\n packageName: string,\n opts: FetchRegistrySkillOptions = {},\n): Promise<RegistrySkill | null> {\n return createRegistryClient().resolveSkill(packageName, opts)\n}\n"],"mappings":";;AAkCA,MAAM,uBAAuB;AAE7B,SAAgB,kBAA0B;CACxC,QAAQ,QAAQ,IAAI,uBAAuB,sBAAsB,QAAQ,mBAAmB,GAAG;;;;;EAiEjG,KAAA,QAAgB,OAAY;EAC1B,KAAA,QAAQ,OAAO,KAAf,cAAA,YAAA;EACE,KAAK;GAEL,IAAK,KAAA,eACI,MAAA,OAAA;GACT,OAAK,KACH,MAAA,YAAY;;;SAIZ,qBAAkB,QAAY;;;CAIpC,IAAA,OAAgB,MAAA,MAAA,EAAA,WAAqB,OAAmC,EAAA,OAAA;CACtE,OAAI;;SAIA,qBAAmB,OAAW,EAAA,EAAA;CAElC,MAAA,QAAO,KAAA,WAAA,iBAAA,EAAA,QAAA,mBAAA,GAAA;;CAGT,MAAA,WAAgB,KAAA,SAAqB;EACnC,IAAA,CAAM,WAAQ,CAAA,MAAK,OAAW,OAAA,IAAA;EAC9B,IAAA,CAAM,SAAA,OAAe,OAAA,KAAY,KAAA;EAEjC,OAAM,OAAA,KAAc;GAClB,GAAI;GAEJ,SAAK;IAEL,GAAA;IAAwB,GAAG,MAAA;IAAM;IAAW;;OAAuC,uBAAA;MAAG,CAAA,KAAA,SAAA,MAAA,IAAA,MAAA,gBAAA;;CAGxF,OAAM;EACJ,MAAK,aACH,aAAU,YAAM,EAAA,EAAA;;IAGpB,QAAO;IACL,MAAM,EAAA,OAAA,CAAA;KAMJ;KAJE,OAAQ,UAAA;KACR,CAAA,EAAA;KAAkB,CAAA,YAAA,KAAA,IAAA;OAAa,CAAA,KAAO,OAAA;SAAoB,SAAA,MAAA,QAAA,GAAA,KAAA,UAAA,IAAA,MAAA,GAAA,IAAA,KAAA,GAAA,cAAA,CAAA,YAAA,KAAA;OACzD,CAAA,QAAA,KAAY,OAEQ;GACvB,OAAK;IAGL,MAAM,OAAA;IACN;IAGA,SAAO,OAAA;IACL,OAAM,OAAO;IACb,MAAA,GAAA,OAAA,MAAA,GAAA,OAAA;IACA,aAAS,OAAO;IAChB,UAAO,OAAO;IACd,UAAS,IAAA;IACT,QAAA,OAAa;IACb,WAAU,OAAO,aAAA,KAAA;IACjB,WAAU,OAAI,YAAA,KAAA;IACd;;QAEA,iBAAkB,OAAA,MAAY,MAAA;UAC/B,QAAA,GAAA,KAAA,UAAA,MAAA,GAAA,KAAA,GAAA,OAAA,CAAA,YAAA,KAAA;;EAGH,MAAM,MAAA,EAAA,OAAA,MAAiB,QAAO;GAC5B,MAAA,MAAO,MAAgC,QAAK,GAAA,KAAU,cAAc,MAAG,GAAO,KAAC,GAAA,OAAY,CAAA,YAAK,KAAA;;IAGlG,QAAM;IACJ,QAAM,EAAA;IACN;SACW,SAAQ,IAAA,UAAA,EAAA;UAAa;IAAY,QAAA,qBAAA,OAAA;IAC5C,WAAM,IAAS;IACf,SAAO,IAAA;IACL;IACA;;QAEA,gBAAA,OAAA,MAAA;UACD,QAAA,GAAA,KAAA,yBAAA,MAAA,GAAA,KAAA,WAAA,CAAA,YAAA,KAAA;;EAGH,MAAM,aAAA,OAAgB;GACpB,OAAO,QAA4B,GAAG,KAAK,YAAA,QAAA,CAAA,YAA+B,KAAG;;EAG/E,IAAA;GACE,MAAA,cAAkC;;IAGpC,OAAI,QAAA,GAAA,KAAA,iBAAA,CAAA,YAAA,EAAA,CAAA;;SAEA,gBAAgB;IAChB,gBAAoC;;;SAGpC,QAAA,EAAA,SAAgB;IAChB,gBAAsC;;;SAGtC,SAAA,SAAgB;IAEhB,gBAA+B;;KAEjC,QAAM;KACJ,MAAA;KACA,CAAA,CAAA,YAAoB,GAAG;;;;;eAG5B,mBAAA,aAAA,OAAA,EAAA,EAAA"}
|
package/dist/_chunks/core.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import "./prompts.mjs";
|
|
1
2
|
import "./paths.mjs";
|
|
3
|
+
import "./sanitize.mjs";
|
|
2
4
|
import "./yaml.mjs";
|
|
3
|
-
import "./cache.mjs";
|
|
4
5
|
import "./package-json.mjs";
|
|
5
|
-
import "./
|
|
6
|
+
import "./cache.mjs";
|
|
7
|
+
import "./semver.mjs";
|
|
8
|
+
import "./map.mjs";
|
|
6
9
|
import "./markdown.mjs";
|
|
7
|
-
import "./sources.mjs";
|
|
8
|
-
import "./prompts.mjs";
|
|
9
10
|
import "./lockfile.mjs";
|
|
10
|
-
import "./semver.mjs";
|
|
11
11
|
import "./skills.mjs";
|
|
12
12
|
import "./monorepo.mjs";
|
|
13
13
|
export {};
|
package/dist/_chunks/detect.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
2
|
import { join } from "pathe";
|
|
4
3
|
import { spawnSync } from "node:child_process";
|
|
5
4
|
import { isWindows } from "std-env";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
6
|
const SPEC_FRONTMATTER = {
|
|
7
7
|
"name": {
|
|
8
8
|
name: "name",
|
|
@@ -47,21 +47,29 @@ const BASE_DEFAULTS = {
|
|
|
47
47
|
notes: []
|
|
48
48
|
};
|
|
49
49
|
function defineTarget(target) {
|
|
50
|
+
const { globalSkillsDir, additionalSkillsDirs, ...rest } = target;
|
|
51
|
+
const additional = additionalSkillsDirs ?? BASE_DEFAULTS.additionalSkillsDirs;
|
|
50
52
|
return {
|
|
51
53
|
...BASE_DEFAULTS,
|
|
52
|
-
...
|
|
54
|
+
...rest,
|
|
55
|
+
get globalSkillsDir() {
|
|
56
|
+
return globalSkillsDir();
|
|
57
|
+
},
|
|
58
|
+
get additionalSkillsDirs() {
|
|
59
|
+
return typeof additional === "function" ? additional() : additional;
|
|
60
|
+
}
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
|
-
const configHome$2 = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
63
|
+
const configHome$2 = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
56
64
|
const amp = defineTarget({
|
|
57
65
|
agent: "amp",
|
|
58
66
|
displayName: "Amp",
|
|
59
|
-
detectInstalled: () => existsSync(join(configHome$2, "amp")),
|
|
67
|
+
detectInstalled: () => existsSync(join(configHome$2(), "amp")),
|
|
60
68
|
detectEnv: () => !!process.env.AMP_SESSION,
|
|
61
69
|
detectProject: (cwd) => existsSync(join(cwd, ".agents", "AGENTS.md")),
|
|
62
70
|
instructionFile: "AGENTS.md",
|
|
63
71
|
skillsDir: ".agents/skills",
|
|
64
|
-
globalSkillsDir: join(configHome$2, "agents/skills"),
|
|
72
|
+
globalSkillsDir: () => join(configHome$2(), "agents/skills"),
|
|
65
73
|
additionalSkillsDirs: [
|
|
66
74
|
".claude/skills",
|
|
67
75
|
"~/.config/amp/skills",
|
|
@@ -86,16 +94,16 @@ const amp = defineTarget({
|
|
|
86
94
|
"AGENTS.md files with globs frontmatter are conditionally included only when Amp reads matching files."
|
|
87
95
|
]
|
|
88
96
|
});
|
|
89
|
-
const home$6 = homedir();
|
|
97
|
+
const home$6 = () => homedir();
|
|
90
98
|
const antigravity = defineTarget({
|
|
91
99
|
agent: "antigravity",
|
|
92
100
|
displayName: "Antigravity",
|
|
93
|
-
detectInstalled: () => existsSync(join(home$6, ".gemini/antigravity")),
|
|
101
|
+
detectInstalled: () => existsSync(join(home$6(), ".gemini/antigravity")),
|
|
94
102
|
detectEnv: () => !!process.env.ANTIGRAVITY_CLI_ALIAS,
|
|
95
103
|
detectProject: (cwd) => existsSync(join(cwd, ".agent")),
|
|
96
104
|
instructionFile: "GEMINI.md",
|
|
97
105
|
skillsDir: ".agent/skills",
|
|
98
|
-
globalSkillsDir: join(home$6, ".gemini/antigravity/skills"),
|
|
106
|
+
globalSkillsDir: () => join(home$6(), ".gemini/antigravity/skills"),
|
|
99
107
|
frontmatter: [{
|
|
100
108
|
...SPEC_FRONTMATTER.name,
|
|
101
109
|
description: "Skill identifier. Defaults to directory name if omitted."
|
|
@@ -113,11 +121,11 @@ const antigravity = defineTarget({
|
|
|
113
121
|
"GEMINI.md instruction file is shared with Gemini CLI. .agent/rules/*.md for always-on workspace rules."
|
|
114
122
|
]
|
|
115
123
|
});
|
|
116
|
-
const claudeHome = process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
|
|
124
|
+
const claudeHome = () => process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
|
|
117
125
|
const claudeCode = defineTarget({
|
|
118
126
|
agent: "claude-code",
|
|
119
127
|
displayName: "Claude Code",
|
|
120
|
-
detectInstalled: () => existsSync(claudeHome),
|
|
128
|
+
detectInstalled: () => existsSync(claudeHome()),
|
|
121
129
|
detectEnv: () => !!(process.env.CLAUDE_CODE || process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT || process.env.CLAUDE_CONFIG_DIR),
|
|
122
130
|
detectProject: (cwd) => {
|
|
123
131
|
if (existsSync(join(cwd, ".claude", "settings.json"))) return true;
|
|
@@ -128,7 +136,7 @@ const claudeCode = defineTarget({
|
|
|
128
136
|
cli: "claude",
|
|
129
137
|
instructionFile: "CLAUDE.md",
|
|
130
138
|
skillsDir: ".claude/skills",
|
|
131
|
-
globalSkillsDir: join(claudeHome, "skills"),
|
|
139
|
+
globalSkillsDir: () => join(claudeHome(), "skills"),
|
|
132
140
|
frontmatter: [
|
|
133
141
|
{
|
|
134
142
|
...SPEC_FRONTMATTER.name,
|
|
@@ -200,16 +208,16 @@ const claudeCode = defineTarget({
|
|
|
200
208
|
"Project detection uses weighted signals: .claude/settings.json, .claude/settings.local.json, .claude/skills/ are strong; bare .claude/ is medium; CLAUDE.md alone is not checked (too many false positives from repo conventions)."
|
|
201
209
|
]
|
|
202
210
|
});
|
|
203
|
-
const home$5 = homedir();
|
|
211
|
+
const home$5 = () => homedir();
|
|
204
212
|
const cline = defineTarget({
|
|
205
213
|
agent: "cline",
|
|
206
214
|
displayName: "Cline",
|
|
207
|
-
detectInstalled: () => existsSync(join(home$5, ".cline")),
|
|
215
|
+
detectInstalled: () => existsSync(join(home$5(), ".cline")),
|
|
208
216
|
detectEnv: () => !!(process.env.CLINE_TASK_ID || process.env.CLINE_ACTIVE),
|
|
209
217
|
detectProject: (cwd) => existsSync(join(cwd, ".cline")),
|
|
210
218
|
instructionFile: ".clinerules",
|
|
211
219
|
skillsDir: ".cline/skills",
|
|
212
|
-
globalSkillsDir: join(home$5, ".cline/skills"),
|
|
220
|
+
globalSkillsDir: () => join(home$5(), ".cline/skills"),
|
|
213
221
|
additionalSkillsDirs: [".clinerules/skills", ".claude/skills"],
|
|
214
222
|
frontmatter: [{
|
|
215
223
|
...SPEC_FRONTMATTER.name,
|
|
@@ -230,17 +238,17 @@ const cline = defineTarget({
|
|
|
230
238
|
"Supporting dirs: docs/, scripts/, templates/ alongside SKILL.md."
|
|
231
239
|
]
|
|
232
240
|
});
|
|
233
|
-
const codexHome = process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
241
|
+
const codexHome = () => process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
234
242
|
const codex = defineTarget({
|
|
235
243
|
agent: "codex",
|
|
236
244
|
displayName: "Codex",
|
|
237
|
-
detectInstalled: () => existsSync(codexHome),
|
|
245
|
+
detectInstalled: () => existsSync(codexHome()),
|
|
238
246
|
detectEnv: () => false,
|
|
239
247
|
detectProject: (cwd) => existsSync(join(cwd, ".codex")) || existsSync(join(cwd, "AGENTS.md")) || existsSync(join(cwd, "AGENTS.override.md")) || existsSync(join(cwd, ".agents", "skills")),
|
|
240
248
|
cli: "codex",
|
|
241
249
|
instructionFile: "AGENTS.md",
|
|
242
250
|
skillsDir: ".agents/skills",
|
|
243
|
-
globalSkillsDir: join(homedir(), ".agents/skills"),
|
|
251
|
+
globalSkillsDir: () => join(homedir(), ".agents/skills"),
|
|
244
252
|
additionalSkillsDirs: ["~/.codex/skills", "/etc/codex/skills"],
|
|
245
253
|
frontmatter: [
|
|
246
254
|
{
|
|
@@ -275,16 +283,16 @@ const codex = defineTarget({
|
|
|
275
283
|
"Size limit: 32 KiB default (project_doc_max_bytes), configurable in ~/.codex/config.toml."
|
|
276
284
|
]
|
|
277
285
|
});
|
|
278
|
-
const home$4 = homedir();
|
|
286
|
+
const home$4 = () => homedir();
|
|
279
287
|
const cursor = defineTarget({
|
|
280
288
|
agent: "cursor",
|
|
281
289
|
displayName: "Cursor",
|
|
282
|
-
detectInstalled: () => existsSync(join(home$4, ".cursor")),
|
|
290
|
+
detectInstalled: () => existsSync(join(home$4(), ".cursor")),
|
|
283
291
|
detectEnv: () => !!(process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID),
|
|
284
292
|
detectProject: (cwd) => existsSync(join(cwd, ".cursor")) || existsSync(join(cwd, ".cursorrules")),
|
|
285
293
|
instructionFile: ".cursor/rules/skilld-activation.mdc",
|
|
286
294
|
skillsDir: ".cursor/skills",
|
|
287
|
-
globalSkillsDir: join(home$4, ".cursor/skills"),
|
|
295
|
+
globalSkillsDir: () => join(home$4(), ".cursor/skills"),
|
|
288
296
|
additionalSkillsDirs: [
|
|
289
297
|
".claude/skills",
|
|
290
298
|
".codex/skills",
|
|
@@ -319,18 +327,18 @@ const cursor = defineTarget({
|
|
|
319
327
|
"Supporting dirs: scripts/, references/, assets/ alongside SKILL.md."
|
|
320
328
|
]
|
|
321
329
|
});
|
|
322
|
-
const home$3 = homedir();
|
|
330
|
+
const home$3 = () => homedir();
|
|
323
331
|
const geminiCli = defineTarget({
|
|
324
332
|
agent: "gemini-cli",
|
|
325
333
|
displayName: "Gemini CLI",
|
|
326
|
-
detectInstalled: () => existsSync(join(home$3, ".gemini")),
|
|
334
|
+
detectInstalled: () => existsSync(join(home$3(), ".gemini")),
|
|
327
335
|
detectEnv: () => !!process.env.GEMINI_CLI,
|
|
328
336
|
detectProject: (cwd) => existsSync(join(cwd, ".gemini")),
|
|
329
337
|
cli: "gemini",
|
|
330
338
|
instructionFile: "GEMINI.md",
|
|
331
339
|
skillsDir: ".gemini/skills",
|
|
332
|
-
globalSkillsDir: join(home$3, ".gemini/skills"),
|
|
333
|
-
additionalSkillsDirs: [".agents/skills", join(home$3, ".agents/skills")],
|
|
340
|
+
globalSkillsDir: () => join(home$3(), ".gemini/skills"),
|
|
341
|
+
additionalSkillsDirs: () => [".agents/skills", join(home$3(), ".agents/skills")],
|
|
334
342
|
frontmatter: [
|
|
335
343
|
SPEC_FRONTMATTER.name,
|
|
336
344
|
{
|
|
@@ -355,12 +363,13 @@ const geminiCli = defineTarget({
|
|
|
355
363
|
"Also scans .agents/skills/ (Agent Skills spec standard) - skilld deduplicates to avoid conflicts."
|
|
356
364
|
]
|
|
357
365
|
});
|
|
358
|
-
const home$2 = homedir();
|
|
366
|
+
const home$2 = () => homedir();
|
|
359
367
|
function hasCopilotExtension() {
|
|
368
|
+
const h = home$2();
|
|
360
369
|
const extDirs = [
|
|
361
|
-
join(
|
|
362
|
-
join(
|
|
363
|
-
join(
|
|
370
|
+
join(h, ".vscode", "extensions"),
|
|
371
|
+
join(h, ".vscode-server", "extensions"),
|
|
372
|
+
join(h, ".cursor", "extensions")
|
|
364
373
|
];
|
|
365
374
|
for (const dir of extDirs) {
|
|
366
375
|
if (!existsSync(dir)) continue;
|
|
@@ -373,12 +382,12 @@ function hasCopilotExtension() {
|
|
|
373
382
|
const githubCopilot = defineTarget({
|
|
374
383
|
agent: "github-copilot",
|
|
375
384
|
displayName: "GitHub Copilot",
|
|
376
|
-
detectInstalled: () => existsSync(join(home$2, ".copilot")) || hasCopilotExtension(),
|
|
385
|
+
detectInstalled: () => existsSync(join(home$2(), ".copilot")) || hasCopilotExtension(),
|
|
377
386
|
detectEnv: () => !!process.env.COPILOT_RUN_APP,
|
|
378
387
|
detectProject: (cwd) => existsSync(join(cwd, ".github", "copilot-instructions.md")) || existsSync(join(cwd, ".github", "skills")) || existsSync(join(cwd, "AGENTS.md")) || existsSync(join(cwd, ".github", "instructions")),
|
|
379
388
|
instructionFile: ".github/copilot-instructions.md",
|
|
380
389
|
skillsDir: ".github/skills",
|
|
381
|
-
globalSkillsDir: join(home$2, ".copilot/skills"),
|
|
390
|
+
globalSkillsDir: () => join(home$2(), ".copilot/skills"),
|
|
382
391
|
additionalSkillsDirs: [".claude/skills", "~/.claude/skills"],
|
|
383
392
|
frontmatter: [
|
|
384
393
|
SPEC_FRONTMATTER.name,
|
|
@@ -408,17 +417,17 @@ const githubCopilot = defineTarget({
|
|
|
408
417
|
"Keep SKILL.md under 500 lines / 5000 tokens for optimal loading."
|
|
409
418
|
]
|
|
410
419
|
});
|
|
411
|
-
const configHome$1 = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
420
|
+
const configHome$1 = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
412
421
|
const goose = defineTarget({
|
|
413
422
|
agent: "goose",
|
|
414
423
|
displayName: "Goose",
|
|
415
|
-
detectInstalled: () => existsSync(join(configHome$1, "goose")),
|
|
424
|
+
detectInstalled: () => existsSync(join(configHome$1(), "goose")),
|
|
416
425
|
detectEnv: () => !!(process.env.GOOSE_SESSION || process.env.AGENT_SESSION_ID),
|
|
417
426
|
detectProject: (cwd) => existsSync(join(cwd, ".goose")),
|
|
418
427
|
cli: "goose",
|
|
419
428
|
instructionFile: ".goosehints",
|
|
420
429
|
skillsDir: ".goose/skills",
|
|
421
|
-
globalSkillsDir: join(configHome$1, "goose/skills"),
|
|
430
|
+
globalSkillsDir: () => join(configHome$1(), "goose/skills"),
|
|
422
431
|
additionalSkillsDirs: [
|
|
423
432
|
".claude/skills",
|
|
424
433
|
".agents/skills",
|
|
@@ -442,16 +451,16 @@ const goose = defineTarget({
|
|
|
442
451
|
"Supporting files alongside SKILL.md (scripts, templates, configs) are accessible."
|
|
443
452
|
]
|
|
444
453
|
});
|
|
445
|
-
const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
454
|
+
const configHome = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
446
455
|
const opencode = defineTarget({
|
|
447
456
|
agent: "opencode",
|
|
448
457
|
displayName: "OpenCode",
|
|
449
|
-
detectInstalled: () => existsSync(join(configHome, "opencode")),
|
|
458
|
+
detectInstalled: () => existsSync(join(configHome(), "opencode")),
|
|
450
459
|
detectEnv: () => !!(process.env.OPENCODE_SESSION || process.env.OPENCODE_SESSION_ID),
|
|
451
460
|
detectProject: (cwd) => existsSync(join(cwd, ".opencode")),
|
|
452
461
|
instructionFile: "AGENTS.md",
|
|
453
462
|
skillsDir: ".opencode/skills",
|
|
454
|
-
globalSkillsDir: join(configHome, "opencode/skills"),
|
|
463
|
+
globalSkillsDir: () => join(configHome(), "opencode/skills"),
|
|
455
464
|
additionalSkillsDirs: [
|
|
456
465
|
".claude/skills",
|
|
457
466
|
".agents/skills",
|
|
@@ -483,16 +492,16 @@ const opencode = defineTarget({
|
|
|
483
492
|
"AGENTS.md (or CLAUDE.md fallback) for general instructions."
|
|
484
493
|
]
|
|
485
494
|
});
|
|
486
|
-
const home$1 = homedir();
|
|
495
|
+
const home$1 = () => homedir();
|
|
487
496
|
const roo = defineTarget({
|
|
488
497
|
agent: "roo",
|
|
489
498
|
displayName: "Roo Code",
|
|
490
|
-
detectInstalled: () => existsSync(join(home$1, ".roo")),
|
|
499
|
+
detectInstalled: () => existsSync(join(home$1(), ".roo")),
|
|
491
500
|
detectEnv: () => !!process.env.ROO_SESSION,
|
|
492
501
|
detectProject: (cwd) => existsSync(join(cwd, ".roo")),
|
|
493
502
|
instructionFile: ".roorules",
|
|
494
503
|
skillsDir: ".roo/skills",
|
|
495
|
-
globalSkillsDir: join(home$1, ".roo/skills"),
|
|
504
|
+
globalSkillsDir: () => join(home$1(), ".roo/skills"),
|
|
496
505
|
frontmatter: [{
|
|
497
506
|
...SPEC_FRONTMATTER.name,
|
|
498
507
|
description: "Must exactly match the directory name."
|
|
@@ -515,19 +524,19 @@ const roo = defineTarget({
|
|
|
515
524
|
"Skills manageable from Settings panel (v3.46.0+)."
|
|
516
525
|
]
|
|
517
526
|
});
|
|
518
|
-
const home = homedir();
|
|
527
|
+
const home = () => homedir();
|
|
519
528
|
const targets = {
|
|
520
529
|
"claude-code": claudeCode,
|
|
521
530
|
"cursor": cursor,
|
|
522
531
|
"windsurf": defineTarget({
|
|
523
532
|
agent: "windsurf",
|
|
524
533
|
displayName: "Windsurf",
|
|
525
|
-
detectInstalled: () => existsSync(join(home, ".codeium/windsurf")),
|
|
534
|
+
detectInstalled: () => existsSync(join(home(), ".codeium/windsurf")),
|
|
526
535
|
detectEnv: () => !!process.env.WINDSURF_SESSION,
|
|
527
536
|
detectProject: (cwd) => existsSync(join(cwd, ".windsurf")) || existsSync(join(cwd, ".windsurfrules")),
|
|
528
537
|
instructionFile: ".windsurfrules",
|
|
529
538
|
skillsDir: ".windsurf/skills",
|
|
530
|
-
globalSkillsDir: join(home, ".codeium/windsurf/skills"),
|
|
539
|
+
globalSkillsDir: () => join(home(), ".codeium/windsurf/skills"),
|
|
531
540
|
frontmatter: [{
|
|
532
541
|
...SPEC_FRONTMATTER.name,
|
|
533
542
|
description: "Skill identifier.",
|
|
@@ -558,6 +567,7 @@ const targets = {
|
|
|
558
567
|
"roo": roo,
|
|
559
568
|
"antigravity": antigravity
|
|
560
569
|
};
|
|
570
|
+
const STATIC_REGEX_1 = /v?(\d+\.\d+\.\d+(?:-[a-z0-9.]+)?)/;
|
|
561
571
|
function detectInstalledAgents() {
|
|
562
572
|
return Object.entries(targets).filter(([_, config]) => config.detectInstalled()).map(([type]) => type);
|
|
563
573
|
}
|
|
@@ -588,7 +598,7 @@ function getAgentVersion(agentType) {
|
|
|
588
598
|
});
|
|
589
599
|
if (result.status !== 0) return null;
|
|
590
600
|
const output = (result.stdout || "").trim();
|
|
591
|
-
const match = output.match(
|
|
601
|
+
const match = output.match(STATIC_REGEX_1);
|
|
592
602
|
return match ? match[1] : output.split("\n")[0];
|
|
593
603
|
} catch {
|
|
594
604
|
return null;
|