skilld 1.6.2 → 1.7.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/README.md +29 -20
- package/dist/_chunks/agent.mjs +2 -1
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/assemble.mjs +1 -1
- package/dist/_chunks/author-group.mjs +17 -0
- package/dist/_chunks/author-group.mjs.map +1 -0
- package/dist/_chunks/author.mjs +8 -6
- package/dist/_chunks/author.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +1 -1
- package/dist/_chunks/cache2.mjs +1 -1
- package/dist/_chunks/cli-helpers.mjs +3 -119
- package/dist/_chunks/cli-helpers.mjs.map +1 -1
- package/dist/_chunks/config.mjs +119 -27
- package/dist/_chunks/config.mjs.map +1 -1
- package/dist/_chunks/core.mjs +1 -1
- package/dist/_chunks/embedding-cache2.mjs +1 -1
- package/dist/_chunks/index.d.mts.map +1 -1
- package/dist/_chunks/index3.d.mts +79 -78
- package/dist/_chunks/index3.d.mts.map +1 -1
- package/dist/_chunks/install.mjs +85 -535
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/install2.mjs +554 -0
- package/dist/_chunks/install2.mjs.map +1 -0
- package/dist/_chunks/lockfile.mjs +1 -0
- package/dist/_chunks/lockfile.mjs.map +1 -1
- package/dist/_chunks/package-registry.mjs +465 -0
- package/dist/_chunks/package-registry.mjs.map +1 -0
- package/dist/_chunks/prefix.mjs +108 -0
- package/dist/_chunks/prefix.mjs.map +1 -0
- package/dist/_chunks/prepare.mjs +6 -2
- package/dist/_chunks/prepare.mjs.map +1 -1
- package/dist/_chunks/prepare2.mjs +1 -1
- package/dist/_chunks/prompts.mjs +5 -99
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/search-helpers.mjs +99 -0
- package/dist/_chunks/search-helpers.mjs.map +1 -0
- package/dist/_chunks/search-interactive.mjs +1 -1
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +219 -1
- package/dist/_chunks/search.mjs.map +1 -0
- package/dist/_chunks/shared.mjs +1 -463
- package/dist/_chunks/shared.mjs.map +1 -1
- package/dist/_chunks/skills.mjs +1 -1
- package/dist/_chunks/sources.mjs +1177 -988
- package/dist/_chunks/sources.mjs.map +1 -1
- package/dist/_chunks/sync-registry.mjs +59 -0
- package/dist/_chunks/sync-registry.mjs.map +1 -0
- package/dist/_chunks/sync-shared2.mjs +10 -7
- package/dist/_chunks/sync-shared2.mjs.map +1 -1
- package/dist/_chunks/sync.mjs +208 -99
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/sync2.mjs +1 -1
- package/dist/_chunks/uninstall.mjs +3 -2
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/upload.mjs +152 -0
- package/dist/_chunks/upload.mjs.map +1 -0
- package/dist/_chunks/validate.mjs +1 -1
- package/dist/_chunks/version.mjs +30 -0
- package/dist/_chunks/version.mjs.map +1 -0
- package/dist/_chunks/wizard.mjs +2 -1
- package/dist/_chunks/wizard.mjs.map +1 -1
- package/dist/agent/index.mjs +2 -1
- package/dist/cache/index.mjs +1 -1
- package/dist/cli.mjs +48 -20
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +3 -3
- package/dist/types.d.mts +1 -1
- package/package.json +11 -12
- package/dist/_chunks/search2.mjs +0 -310
- package/dist/_chunks/search2.mjs.map +0 -1
package/dist/_chunks/install.mjs
CHANGED
|
@@ -1,551 +1,101 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const skillsDir = opts.global ? join(homedir(), ".skilld", "skills") : shared || join(cwd, agent.skillsDir);
|
|
28
|
-
const allSkillsDirs = shared ? [shared] : Object.values(targets).map((t) => opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir));
|
|
29
|
-
const allLocks = allSkillsDirs.map((dir) => readLock(dir)).filter((l) => !!l && Object.keys(l.skills).length > 0);
|
|
30
|
-
if (allLocks.length === 0) {
|
|
31
|
-
p.log.warn("No skilld-lock.yaml found. Run `skilld` to sync skills first.");
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const lock = mergeLocks(allLocks);
|
|
35
|
-
const skills = Object.entries(lock.skills);
|
|
36
|
-
const toRestore = [];
|
|
37
|
-
const features = readConfig().features ?? defaultFeatures;
|
|
38
|
-
for (const [name, info] of skills) {
|
|
39
|
-
if (!info.version) continue;
|
|
40
|
-
if (info.source === "shipped") {
|
|
41
|
-
if (!existsSync(join(skillsDir, name))) toRestore.push({
|
|
42
|
-
name,
|
|
43
|
-
info
|
|
1
|
+
import { n as sanitizeMarkdown, t as repairMarkdown } from "./sanitize.mjs";
|
|
2
|
+
import { a as targets, t as detectInstalledAgents } from "./detect.mjs";
|
|
3
|
+
import { join, relative } from "pathe";
|
|
4
|
+
import { existsSync, lstatSync, mkdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
function sanitizeName(name) {
|
|
6
|
+
return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
|
|
7
|
+
}
|
|
8
|
+
function computeSkillDirName(packageName) {
|
|
9
|
+
return `${sanitizeName(packageName)}-skilld`;
|
|
10
|
+
}
|
|
11
|
+
function installSkillForAgents(skillName, skillContent, options = {}) {
|
|
12
|
+
const isGlobal = options.global ?? false;
|
|
13
|
+
const cwd = options.cwd || process.cwd();
|
|
14
|
+
const sanitized = sanitizeName(skillName);
|
|
15
|
+
const explicit = !!options.agents;
|
|
16
|
+
const targetAgents = options.agents || detectInstalledAgents();
|
|
17
|
+
const installed = [];
|
|
18
|
+
const skipped = [];
|
|
19
|
+
const paths = [];
|
|
20
|
+
const writtenDirs = /* @__PURE__ */ new Set();
|
|
21
|
+
for (const agentType of targetAgents) {
|
|
22
|
+
const agent = targets[agentType];
|
|
23
|
+
if (isGlobal && !agent.globalSkillsDir) {
|
|
24
|
+
skipped.push({
|
|
25
|
+
agent: agentType,
|
|
26
|
+
reason: "no global support"
|
|
44
27
|
});
|
|
45
28
|
continue;
|
|
46
29
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
if (toRestore.length === 0) {
|
|
56
|
-
p.log.success("All up to date");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
p.log.info(`Restoring ${toRestore.length} references`);
|
|
60
|
-
ensureCacheDir();
|
|
61
|
-
const allSkillNames = skills.map(([, info]) => info.packageName || "").filter(Boolean);
|
|
62
|
-
const regenerated = [];
|
|
63
|
-
for (const { name, info } of toRestore) {
|
|
64
|
-
const version = info.version;
|
|
65
|
-
const pkgName = info.packageName || unsanitizeName(name, info.source);
|
|
66
|
-
if (info.source === "shipped") {
|
|
67
|
-
const match = getShippedSkills(pkgName, cwd, version).find((s) => s.skillName === name);
|
|
68
|
-
if (match) {
|
|
69
|
-
linkShippedSkill(skillsDir, name, match.skillDir);
|
|
70
|
-
p.log.success(`Linked ${name}`);
|
|
71
|
-
} else p.log.warn(`${name}: package ${pkgName} no longer ships this skill`);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (info.source === "github" || info.source === "gitlab" || info.source === "local") {
|
|
75
|
-
const match = (await fetchGitSkills({
|
|
76
|
-
type: info.source,
|
|
77
|
-
...info.repo?.includes("/") ? {
|
|
78
|
-
owner: info.repo.split("/")[0],
|
|
79
|
-
repo: info.repo.split("/")[1]
|
|
80
|
-
} : {},
|
|
81
|
-
skillPath: info.path,
|
|
82
|
-
ref: info.ref,
|
|
83
|
-
...info.source === "local" ? { localPath: info.repo } : {}
|
|
84
|
-
})).skills.find((s) => s.name === name);
|
|
85
|
-
if (match) {
|
|
86
|
-
const skillDir = join(skillsDir, name);
|
|
87
|
-
mkdirSync(skillDir, { recursive: true });
|
|
88
|
-
writeFileSync(join(skillDir, "SKILL.md"), sanitizeMarkdown(match.content));
|
|
89
|
-
for (const f of match.files) {
|
|
90
|
-
const filePath = join(skillDir, f.path);
|
|
91
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
92
|
-
writeFileSync(filePath, f.content);
|
|
93
|
-
}
|
|
94
|
-
p.log.success(`Restored ${name} from ${info.repo}`);
|
|
95
|
-
} else p.log.warn(`${name}: skill not found in ${info.repo}`);
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const skillDir = join(skillsDir, name);
|
|
99
|
-
const referencesPath = join(skillDir, ".skilld");
|
|
100
|
-
const globalCachePath = getCacheDir(pkgName, version);
|
|
101
|
-
const spin = timedSpinner();
|
|
102
|
-
if (isCached(pkgName, version)) {
|
|
103
|
-
spin.start(`Linking ${name}`);
|
|
104
|
-
mkdirSync(skillDir, { recursive: true });
|
|
105
|
-
mkdirSync(referencesPath, { recursive: true });
|
|
106
|
-
linkPkgSymlink(referencesPath, pkgName, cwd, version);
|
|
107
|
-
for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
|
|
108
|
-
if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {
|
|
109
|
-
const docsLink = join(referencesPath, "docs");
|
|
110
|
-
const cachedDocs = join(globalCachePath, "docs");
|
|
111
|
-
if (existsSync(docsLink)) unlinkSync(docsLink);
|
|
112
|
-
if (existsSync(cachedDocs)) symlinkSync(cachedDocs, docsLink, "junction");
|
|
113
|
-
}
|
|
114
|
-
const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null;
|
|
115
|
-
const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null;
|
|
116
|
-
if (features.issues) {
|
|
117
|
-
const issuesLink = join(referencesPath, "issues");
|
|
118
|
-
const repoIssues = repoCachePath ? join(repoCachePath, "issues") : null;
|
|
119
|
-
const cachedIssues = repoIssues && existsSync(repoIssues) ? repoIssues : join(globalCachePath, "issues");
|
|
120
|
-
if (existsSync(issuesLink)) unlinkSync(issuesLink);
|
|
121
|
-
if (existsSync(cachedIssues)) symlinkSync(cachedIssues, issuesLink, "junction");
|
|
122
|
-
}
|
|
123
|
-
if (features.discussions) {
|
|
124
|
-
const discussionsLink = join(referencesPath, "discussions");
|
|
125
|
-
const repoDiscussions = repoCachePath ? join(repoCachePath, "discussions") : null;
|
|
126
|
-
const cachedDiscussions = repoDiscussions && existsSync(repoDiscussions) ? repoDiscussions : join(globalCachePath, "discussions");
|
|
127
|
-
if (existsSync(discussionsLink)) unlinkSync(discussionsLink);
|
|
128
|
-
if (existsSync(cachedDiscussions)) symlinkSync(cachedDiscussions, discussionsLink, "junction");
|
|
129
|
-
}
|
|
130
|
-
if (features.releases) {
|
|
131
|
-
const releasesLink = join(referencesPath, "releases");
|
|
132
|
-
const repoReleases = repoCachePath ? join(repoCachePath, "releases") : null;
|
|
133
|
-
const cachedReleases = repoReleases && existsSync(repoReleases) ? repoReleases : join(globalCachePath, "releases");
|
|
134
|
-
if (existsSync(releasesLink)) unlinkSync(releasesLink);
|
|
135
|
-
if (existsSync(cachedReleases)) symlinkSync(cachedReleases, releasesLink, "junction");
|
|
136
|
-
}
|
|
137
|
-
const sectionsLink = join(referencesPath, "sections");
|
|
138
|
-
const cachedSections = join(globalCachePath, "sections");
|
|
139
|
-
if (existsSync(sectionsLink)) unlinkSync(sectionsLink);
|
|
140
|
-
if (existsSync(cachedSections)) symlinkSync(cachedSections, sectionsLink, "junction");
|
|
141
|
-
if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {
|
|
142
|
-
spin.message(`Indexing ${name}`);
|
|
143
|
-
await indexResources({
|
|
144
|
-
packageName: pkgName,
|
|
145
|
-
version,
|
|
146
|
-
cwd,
|
|
147
|
-
docsToIndex: readCachedDocs(pkgName, version).map((d) => ({
|
|
148
|
-
id: d.path,
|
|
149
|
-
content: d.content,
|
|
150
|
-
metadata: {
|
|
151
|
-
package: pkgName,
|
|
152
|
-
source: d.path,
|
|
153
|
-
type: classifyCachedDoc(d.path).type
|
|
154
|
-
}
|
|
155
|
-
})),
|
|
156
|
-
features,
|
|
157
|
-
onProgress: (msg) => spin.message(msg)
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {
|
|
161
|
-
if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages)) regenerated.push({
|
|
162
|
-
name,
|
|
163
|
-
pkgName,
|
|
164
|
-
version,
|
|
165
|
-
skillDir,
|
|
166
|
-
packages: info.packages
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
spin.stop(`Linked ${name}`);
|
|
30
|
+
const baseDir = isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir);
|
|
31
|
+
if (!explicit && !existsSync(baseDir)) {
|
|
32
|
+
skipped.push({
|
|
33
|
+
agent: agentType,
|
|
34
|
+
reason: "skills dir not found"
|
|
35
|
+
});
|
|
170
36
|
continue;
|
|
171
37
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
38
|
+
if (isGlobal && (writtenDirs.has(baseDir) || agent.additionalSkillsDirs.some((d) => writtenDirs.has(d)))) {
|
|
39
|
+
skipped.push({
|
|
40
|
+
agent: agentType,
|
|
41
|
+
reason: "already covered by another agent dir"
|
|
42
|
+
});
|
|
176
43
|
continue;
|
|
177
44
|
}
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const BATCH_SIZE = 20;
|
|
187
|
-
for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {
|
|
188
|
-
const batch = gitDocs.files.slice(i, i + BATCH_SIZE);
|
|
189
|
-
const results = await Promise.all(batch.map(async (file) => {
|
|
190
|
-
const content = await fetchGitHubRaw(`${gitDocs.baseUrl}/${file}`);
|
|
191
|
-
if (!content) return null;
|
|
192
|
-
return {
|
|
193
|
-
file,
|
|
194
|
-
content
|
|
195
|
-
};
|
|
196
|
-
}));
|
|
197
|
-
for (const r of results) if (r) {
|
|
198
|
-
const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, "") : r.file;
|
|
199
|
-
const cachePath = stripped.startsWith("docs/") ? stripped : `docs/${stripped}`;
|
|
200
|
-
cachedDocs.push({
|
|
201
|
-
path: cachePath,
|
|
202
|
-
content: r.content
|
|
203
|
-
});
|
|
204
|
-
docsToIndex.push({
|
|
205
|
-
id: cachePath,
|
|
206
|
-
content: r.content,
|
|
207
|
-
metadata: {
|
|
208
|
-
package: pkgName,
|
|
209
|
-
source: cachePath,
|
|
210
|
-
type: "doc"
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {
|
|
216
|
-
cachedDocs.length = 0;
|
|
217
|
-
docsToIndex.length = 0;
|
|
218
|
-
} else if (cachedDocs.length > 0 && resolved.llmsUrl) {
|
|
219
|
-
const llmsContent = await fetchLlmsTxt(resolved.llmsUrl);
|
|
220
|
-
if (llmsContent) {
|
|
221
|
-
const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin;
|
|
222
|
-
cachedDocs.push({
|
|
223
|
-
path: "llms.txt",
|
|
224
|
-
content: normalizeLlmsLinks(llmsContent.raw)
|
|
225
|
-
});
|
|
226
|
-
if (llmsContent.links.length > 0) {
|
|
227
|
-
const docs = await downloadLlmsDocs(llmsContent, baseUrl);
|
|
228
|
-
for (const doc of docs) {
|
|
229
|
-
if (!isFrameworkDoc(doc.url)) continue;
|
|
230
|
-
const localPath = doc.url.startsWith("/") ? doc.url.slice(1) : doc.url;
|
|
231
|
-
cachedDocs.push({
|
|
232
|
-
path: join("llms-docs", ...localPath.split("/")),
|
|
233
|
-
content: doc.content
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
if (resolved.llmsUrl && cachedDocs.length === 0) {
|
|
243
|
-
const llmsContent = await fetchLlmsTxt(resolved.llmsUrl);
|
|
244
|
-
if (llmsContent) {
|
|
245
|
-
cachedDocs.push({
|
|
246
|
-
path: "llms.txt",
|
|
247
|
-
content: normalizeLlmsLinks(llmsContent.raw)
|
|
248
|
-
});
|
|
249
|
-
if (llmsContent.links.length > 0) {
|
|
250
|
-
const docs = await downloadLlmsDocs(llmsContent, resolved.docsUrl || new URL(resolved.llmsUrl).origin);
|
|
251
|
-
for (const doc of docs) {
|
|
252
|
-
if (!isFrameworkDoc(doc.url)) continue;
|
|
253
|
-
const cachePath = join("docs", ...(doc.url.startsWith("/") ? doc.url.slice(1) : doc.url).split("/"));
|
|
254
|
-
cachedDocs.push({
|
|
255
|
-
path: cachePath,
|
|
256
|
-
content: doc.content
|
|
257
|
-
});
|
|
258
|
-
docsToIndex.push({
|
|
259
|
-
id: doc.url,
|
|
260
|
-
content: doc.content,
|
|
261
|
-
metadata: {
|
|
262
|
-
package: pkgName,
|
|
263
|
-
source: cachePath,
|
|
264
|
-
type: "doc"
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
if (resolved.readmeUrl && cachedDocs.length === 0) {
|
|
272
|
-
const content = await fetchReadmeContent(resolved.readmeUrl);
|
|
273
|
-
if (content) {
|
|
274
|
-
cachedDocs.push({
|
|
275
|
-
path: "docs/README.md",
|
|
276
|
-
content
|
|
277
|
-
});
|
|
278
|
-
docsToIndex.push({
|
|
279
|
-
id: "README.md",
|
|
280
|
-
content,
|
|
281
|
-
metadata: {
|
|
282
|
-
package: pkgName,
|
|
283
|
-
source: "docs/README.md",
|
|
284
|
-
type: "doc"
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (cachedDocs.length > 0) {
|
|
290
|
-
writeToCache(pkgName, version, cachedDocs);
|
|
291
|
-
mkdirSync(referencesPath, { recursive: true });
|
|
292
|
-
linkPkgSymlink(referencesPath, pkgName, cwd, version);
|
|
293
|
-
for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
|
|
294
|
-
if (!isReadmeOnly(globalCachePath)) {
|
|
295
|
-
const docsLink = join(referencesPath, "docs");
|
|
296
|
-
const cachedDocsDir = join(globalCachePath, "docs");
|
|
297
|
-
if (existsSync(docsLink)) unlinkSync(docsLink);
|
|
298
|
-
if (existsSync(cachedDocsDir)) symlinkSync(cachedDocsDir, docsLink, "junction");
|
|
299
|
-
}
|
|
300
|
-
if (features.search) try {
|
|
301
|
-
if (docsToIndex.length > 0) await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) });
|
|
302
|
-
const pkgDir = resolvePkgDir(pkgName, cwd, version);
|
|
303
|
-
const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : [];
|
|
304
|
-
if (entryFiles.length > 0) await createIndex(entryFiles.map((e) => ({
|
|
305
|
-
id: e.path,
|
|
306
|
-
content: e.content,
|
|
307
|
-
metadata: {
|
|
308
|
-
package: pkgName,
|
|
309
|
-
source: `pkg/${e.path}`,
|
|
310
|
-
type: e.type
|
|
311
|
-
}
|
|
312
|
-
})), { dbPath: getPackageDbPath(pkgName, version) });
|
|
313
|
-
} catch (err) {
|
|
314
|
-
if (!(err instanceof SearchDepsUnavailableError)) throw err;
|
|
315
|
-
}
|
|
316
|
-
if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {
|
|
317
|
-
if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages)) regenerated.push({
|
|
318
|
-
name,
|
|
319
|
-
pkgName,
|
|
320
|
-
version,
|
|
321
|
-
skillDir,
|
|
322
|
-
packages: info.packages
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
spin.stop(`Downloaded and linked ${name}`);
|
|
326
|
-
} else spin.stop(`No docs found for ${name}`);
|
|
327
|
-
}
|
|
328
|
-
if (regenerated.length > 0 && !readConfig().skipLlm) {
|
|
329
|
-
const llmConfig = await selectLlmConfig(void 0, `Enhance SKILL.md for ${regenerated.map((r) => r.name).join(", ")}`);
|
|
330
|
-
if (llmConfig?.promptOnly) {
|
|
331
|
-
const features = readConfig().features ?? defaultFeatures;
|
|
332
|
-
for (const { pkgName, version, skillDir } of regenerated) {
|
|
333
|
-
const globalCachePath = getCacheDir(pkgName, version);
|
|
334
|
-
writePromptFiles({
|
|
335
|
-
packageName: pkgName,
|
|
336
|
-
skillDir,
|
|
337
|
-
version,
|
|
338
|
-
hasIssues: existsSync(join(globalCachePath, "issues")),
|
|
339
|
-
hasDiscussions: existsSync(join(globalCachePath, "discussions")),
|
|
340
|
-
hasReleases: existsSync(join(globalCachePath, "releases")),
|
|
341
|
-
hasChangelog: false,
|
|
342
|
-
docsType: "docs",
|
|
343
|
-
hasShippedDocs: false,
|
|
344
|
-
pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
|
|
345
|
-
sections: llmConfig.sections,
|
|
346
|
-
customPrompt: llmConfig.customPrompt,
|
|
347
|
-
features
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
} else if (llmConfig) {
|
|
351
|
-
p.log.step(getModelLabel(llmConfig.model));
|
|
352
|
-
for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
for (const [name, info] of Object.entries(lock.skills)) writeLock(skillsDir, name, info);
|
|
356
|
-
if (shared) for (const [name] of skills) linkSkillToAgents(name, shared, cwd, opts.agent);
|
|
357
|
-
else syncLockfilesToDirs(lock, allSkillsDirs.filter((d) => d !== skillsDir));
|
|
358
|
-
await shutdownWorker();
|
|
359
|
-
p.outro("Install complete");
|
|
360
|
-
}
|
|
361
|
-
function copyFromExistingAgent(skillDir, name, allSkillsDirs) {
|
|
362
|
-
const targetMd = join(skillDir, "SKILL.md");
|
|
363
|
-
if (existsSync(targetMd)) return false;
|
|
364
|
-
for (const dir of allSkillsDirs) {
|
|
365
|
-
if (dir === skillDir) continue;
|
|
366
|
-
const candidateMd = join(dir, name, "SKILL.md");
|
|
367
|
-
if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {
|
|
368
|
-
mkdirSync(skillDir, { recursive: true });
|
|
369
|
-
copyFileSync(candidateMd, targetMd);
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
function unsanitizeName(sanitized, source) {
|
|
376
|
-
if (source?.includes("ungh://")) {
|
|
377
|
-
const match = source.match(/ungh:\/\/([^/]+)\/(.+)/);
|
|
378
|
-
if (match) return `@${match[1]}/${match[2]}`;
|
|
45
|
+
const skillDir = join(baseDir, sanitized);
|
|
46
|
+
const skilldDir = join(skillDir, ".skilld");
|
|
47
|
+
mkdirSync(skilldDir, { recursive: true });
|
|
48
|
+
writeFileSync(join(skilldDir, "_SKILL.md"), sanitizeMarkdown(repairMarkdown(skillContent)));
|
|
49
|
+
if (options.files) for (const [filename, content] of Object.entries(options.files)) writeFileSync(join(skillDir, filename), filename.endsWith(".md") ? sanitizeMarkdown(repairMarkdown(content)) : content);
|
|
50
|
+
installed.push(agentType);
|
|
51
|
+
paths.push(skillDir);
|
|
52
|
+
writtenDirs.add(baseDir);
|
|
379
53
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return sanitized;
|
|
386
|
-
}
|
|
387
|
-
function linkPkgSymlink(referencesDir, name, cwd, version) {
|
|
388
|
-
const pkgPath = resolvePkgDir(name, cwd, version);
|
|
389
|
-
if (!pkgPath) return;
|
|
390
|
-
const pkgLink = join(referencesDir, "pkg");
|
|
391
|
-
if (existsSync(pkgLink)) unlinkSync(pkgLink);
|
|
392
|
-
symlinkSync(pkgPath, pkgLink, "junction");
|
|
393
|
-
}
|
|
394
|
-
function isReadmeOnly(cacheDir) {
|
|
395
|
-
const docsDir = join(cacheDir, "docs");
|
|
396
|
-
if (!existsSync(docsDir)) return false;
|
|
397
|
-
const files = readdirSync(docsDir);
|
|
398
|
-
return files.length === 1 && files[0] === "README.md";
|
|
54
|
+
return {
|
|
55
|
+
installed,
|
|
56
|
+
skipped,
|
|
57
|
+
paths
|
|
58
|
+
};
|
|
399
59
|
}
|
|
400
|
-
function
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
for (const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const docFiles = listReferenceFiles(skillDir);
|
|
416
|
-
const globalCachePath = getCacheDir(pkgName, version);
|
|
417
|
-
const hasIssues = existsSync(join(globalCachePath, "issues"));
|
|
418
|
-
const hasDiscussions = existsSync(join(globalCachePath, "discussions"));
|
|
419
|
-
const hasGithub = hasIssues || hasDiscussions;
|
|
420
|
-
const hasReleases = existsSync(join(globalCachePath, "releases"));
|
|
421
|
-
const features = readConfig().features ?? defaultFeatures;
|
|
422
|
-
const { optimized, wasOptimized } = await optimizeDocs({
|
|
423
|
-
packageName: pkgName,
|
|
424
|
-
skillDir,
|
|
425
|
-
model,
|
|
426
|
-
version,
|
|
427
|
-
hasGithub,
|
|
428
|
-
hasReleases,
|
|
429
|
-
docFiles,
|
|
430
|
-
sections,
|
|
431
|
-
customPrompt,
|
|
432
|
-
features,
|
|
433
|
-
pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
|
|
434
|
-
onProgress: createToolProgress(llmLog)
|
|
435
|
-
});
|
|
436
|
-
if (wasOptimized) {
|
|
437
|
-
llmLog.success("Generated best practices");
|
|
438
|
-
const cwd = process.cwd();
|
|
439
|
-
const pkgPath = resolvePkgDir(pkgName, cwd, version);
|
|
440
|
-
let description;
|
|
441
|
-
if (pkgPath) {
|
|
442
|
-
const pkgJsonResult = readPackageJsonSafe(join(pkgPath, "package.json"));
|
|
443
|
-
if (pkgJsonResult) description = pkgJsonResult.parsed.description;
|
|
444
|
-
}
|
|
445
|
-
let docsType = "docs";
|
|
446
|
-
if (existsSync(join(globalCachePath, "docs", "llms.txt"))) docsType = "llms.txt";
|
|
447
|
-
else if (isReadmeOnly(globalCachePath)) docsType = "readme";
|
|
448
|
-
const dirName = skillDir.split("/").pop();
|
|
449
|
-
const allPackages = parsePackages(packages).map((p) => ({ name: p.name }));
|
|
450
|
-
const skillMd = generateSkillMd({
|
|
451
|
-
name: pkgName,
|
|
452
|
-
version,
|
|
453
|
-
description,
|
|
454
|
-
body: optimized,
|
|
455
|
-
relatedSkills: [],
|
|
456
|
-
hasIssues,
|
|
457
|
-
hasDiscussions,
|
|
458
|
-
hasReleases,
|
|
459
|
-
docsType,
|
|
460
|
-
hasShippedDocs: hasShippedDocs(pkgName, cwd, version),
|
|
461
|
-
pkgFiles: getPkgKeyFiles(pkgName, cwd, version),
|
|
462
|
-
dirName,
|
|
463
|
-
packages: allPackages.length > 1 ? allPackages : void 0,
|
|
464
|
-
features
|
|
465
|
-
});
|
|
466
|
-
writeFileSync(join(skillDir, "SKILL.md"), skillMd);
|
|
467
|
-
} else llmLog.message("Enhancement skipped");
|
|
468
|
-
}
|
|
469
|
-
const installCommandDef = defineCommand({
|
|
470
|
-
meta: {
|
|
471
|
-
name: "install",
|
|
472
|
-
description: "Restore references from lockfile"
|
|
473
|
-
},
|
|
474
|
-
args: {
|
|
475
|
-
global: sharedArgs.global,
|
|
476
|
-
agent: sharedArgs.agent
|
|
477
|
-
},
|
|
478
|
-
async run({ args }) {
|
|
479
|
-
let agent = resolveAgent(args.agent);
|
|
480
|
-
if (!agent || agent === "none") {
|
|
481
|
-
if (agent === "none") return;
|
|
482
|
-
const picked = await promptForAgent();
|
|
483
|
-
if (!picked || picked === "none") return;
|
|
484
|
-
agent = picked;
|
|
60
|
+
function linkSkillToAgents(skillName, sharedDir, cwd, agentType) {
|
|
61
|
+
const targetAgents = agentType ? [[agentType, targets[agentType]]] : Object.entries(targets);
|
|
62
|
+
const linkedDirs = /* @__PURE__ */ new Set();
|
|
63
|
+
for (const [type, agent] of targetAgents) {
|
|
64
|
+
const agentSkillsDir = join(cwd, agent.skillsDir);
|
|
65
|
+
if (agentType === type) mkdirSync(agentSkillsDir, { recursive: true });
|
|
66
|
+
else {
|
|
67
|
+
if (!existsSync(agentSkillsDir)) continue;
|
|
68
|
+
if (agent.additionalSkillsDirs.map((d) => join(cwd, d)).some((d) => linkedDirs.has(d))) {
|
|
69
|
+
const staleTarget = join(agentSkillsDir, skillName);
|
|
70
|
+
try {
|
|
71
|
+
if (lstatSync(staleTarget).isSymbolicLink() && !existsSync(staleTarget)) unlinkSync(staleTarget);
|
|
72
|
+
} catch {}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
485
75
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
if (pkgPath) {
|
|
499
|
-
const pkgResult = readPackageJsonSafe(join(pkgPath, "package.json"));
|
|
500
|
-
if (pkgResult) description = pkgResult.parsed.description;
|
|
76
|
+
const target = join(agentSkillsDir, skillName);
|
|
77
|
+
let isSymlink = false;
|
|
78
|
+
let targetExists = false;
|
|
79
|
+
try {
|
|
80
|
+
const stat = lstatSync(target);
|
|
81
|
+
targetExists = true;
|
|
82
|
+
isSymlink = stat.isSymbolicLink();
|
|
83
|
+
} catch {}
|
|
84
|
+
if (targetExists && !isSymlink) continue;
|
|
85
|
+
if (isSymlink) unlinkSync(target);
|
|
86
|
+
symlinkSync(relative(agentSkillsDir, join(sharedDir, skillName)), target);
|
|
87
|
+
linkedDirs.add(agentSkillsDir);
|
|
501
88
|
}
|
|
502
|
-
const globalCachePath = getCacheDir(pkgName, version);
|
|
503
|
-
let docsType = "docs";
|
|
504
|
-
if (source?.includes("llms.txt") || existsSync(join(globalCachePath, "docs", "llms.txt"))) docsType = "llms.txt";
|
|
505
|
-
else if (isReadmeOnly(globalCachePath)) docsType = "readme";
|
|
506
|
-
const feat = readConfig().features ?? defaultFeatures;
|
|
507
|
-
const hasIssues = feat.issues && existsSync(join(globalCachePath, "issues"));
|
|
508
|
-
const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, "discussions"));
|
|
509
|
-
const hasReleases = feat.releases && existsSync(join(globalCachePath, "releases"));
|
|
510
|
-
const relatedSkills = allSkillNames.filter((n) => n !== pkgName);
|
|
511
|
-
const dirName = skillDir.split("/").pop();
|
|
512
|
-
const allPackages = parsePackages(packages).map((p) => ({ name: p.name }));
|
|
513
|
-
const content = generateSkillMd({
|
|
514
|
-
name: pkgName,
|
|
515
|
-
version,
|
|
516
|
-
description,
|
|
517
|
-
relatedSkills,
|
|
518
|
-
hasIssues,
|
|
519
|
-
hasDiscussions,
|
|
520
|
-
hasReleases,
|
|
521
|
-
docsType,
|
|
522
|
-
hasShippedDocs: hasShippedDocs(pkgName, cwd, version),
|
|
523
|
-
pkgFiles: getPkgKeyFiles(pkgName, cwd, version),
|
|
524
|
-
dirName,
|
|
525
|
-
packages: allPackages.length > 1 ? allPackages : void 0,
|
|
526
|
-
features: readConfig().features ?? defaultFeatures
|
|
527
|
-
});
|
|
528
|
-
mkdirSync(skillDir, { recursive: true });
|
|
529
|
-
writeFileSync(skillMdPath, content);
|
|
530
|
-
return true;
|
|
531
89
|
}
|
|
532
|
-
function
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
90
|
+
function unlinkSkillFromAgents(skillName, cwd, agentType) {
|
|
91
|
+
const targetAgents = agentType ? [[agentType, targets[agentType]]] : Object.entries(targets);
|
|
92
|
+
for (const [, agent] of targetAgents) {
|
|
93
|
+
const target = join(cwd, agent.skillsDir, skillName);
|
|
94
|
+
try {
|
|
95
|
+
if (lstatSync(target).isSymbolicLink()) unlinkSync(target);
|
|
96
|
+
} catch {}
|
|
536
97
|
}
|
|
537
|
-
if (!existsSync(join(referencesPath, "pkg"))) return true;
|
|
538
|
-
const globalCachePath = getCacheDir(pkgName, version);
|
|
539
|
-
const expected = [
|
|
540
|
-
["docs", existsSync(join(globalCachePath, "docs"))],
|
|
541
|
-
["issues", features.issues && existsSync(join(globalCachePath, "issues"))],
|
|
542
|
-
["discussions", features.discussions && existsSync(join(globalCachePath, "discussions"))],
|
|
543
|
-
["releases", features.releases && existsSync(join(globalCachePath, "releases"))],
|
|
544
|
-
["sections", existsSync(join(globalCachePath, "sections"))]
|
|
545
|
-
];
|
|
546
|
-
for (const [name, shouldExist] of expected) if (shouldExist && !existsSync(join(referencesPath, name))) return true;
|
|
547
|
-
return false;
|
|
548
98
|
}
|
|
549
|
-
export {
|
|
99
|
+
export { unlinkSkillFromAgents as a, sanitizeName as i, installSkillForAgents as n, linkSkillToAgents as r, computeSkillDirName as t };
|
|
550
100
|
|
|
551
101
|
//# sourceMappingURL=install.mjs.map
|