skilld 0.15.4 → 1.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.
Files changed (39) hide show
  1. package/README.md +6 -5
  2. package/dist/_chunks/agent.mjs +6 -9
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/cache2.mjs +68 -3
  5. package/dist/_chunks/cache2.mjs.map +1 -0
  6. package/dist/_chunks/formatting.mjs +549 -1
  7. package/dist/_chunks/formatting.mjs.map +1 -1
  8. package/dist/_chunks/install.mjs +536 -12
  9. package/dist/_chunks/install.mjs.map +1 -0
  10. package/dist/_chunks/list.mjs +60 -3
  11. package/dist/_chunks/list.mjs.map +1 -0
  12. package/dist/_chunks/pool.mjs +167 -113
  13. package/dist/_chunks/pool.mjs.map +1 -1
  14. package/dist/_chunks/pool2.mjs +115 -0
  15. package/dist/_chunks/pool2.mjs.map +1 -0
  16. package/dist/_chunks/prompts.mjs +2 -2
  17. package/dist/_chunks/prompts.mjs.map +1 -1
  18. package/dist/_chunks/search-interactive.mjs +236 -5
  19. package/dist/_chunks/search-interactive.mjs.map +1 -0
  20. package/dist/_chunks/search.mjs +12 -171
  21. package/dist/_chunks/sync.mjs +9 -98
  22. package/dist/_chunks/sync.mjs.map +1 -1
  23. package/dist/_chunks/sync2.mjs +1 -2
  24. package/dist/_chunks/uninstall.mjs +200 -8
  25. package/dist/_chunks/uninstall.mjs.map +1 -0
  26. package/dist/cli.mjs +99 -836
  27. package/dist/cli.mjs.map +1 -1
  28. package/dist/retriv/index.mjs +1 -1
  29. package/dist/retriv/index.mjs.map +1 -1
  30. package/package.json +3 -3
  31. package/dist/_chunks/config2.mjs +0 -12
  32. package/dist/_chunks/remove.mjs +0 -12
  33. package/dist/_chunks/search-interactive2.mjs +0 -236
  34. package/dist/_chunks/search-interactive2.mjs.map +0 -1
  35. package/dist/_chunks/search.mjs.map +0 -1
  36. package/dist/_chunks/search2.mjs +0 -13
  37. package/dist/_chunks/skills.mjs +0 -552
  38. package/dist/_chunks/skills.mjs.map +0 -1
  39. package/dist/_chunks/status.mjs +0 -13
@@ -1,15 +1,539 @@
1
- import "./config.mjs";
2
- import "./sanitize.mjs";
3
- import "./cache.mjs";
1
+ import { a as getRepoCacheDir, i as getPackageDbPath, o as getCacheDir } from "./config.mjs";
2
+ import { n as sanitizeMarkdown } from "./sanitize.mjs";
3
+ import { _ as resolvePkgDir, a as getShippedSkills, f as linkShippedSkill, h as readCachedDocs, i as getPkgKeyFiles, m as listReferenceFiles, o as hasShippedDocs, r as ensureCacheDir, s as isCached, u as linkPkgNamed, y as writeToCache } from "./cache.mjs";
4
4
  import "./yaml.mjs";
5
5
  import "./markdown.mjs";
6
- import "./shared.mjs";
7
- import "./sources.mjs";
8
- import "./prompts.mjs";
9
- import "./agent.mjs";
10
- import "./skills.mjs";
11
- import "./formatting.mjs";
12
- import "./pool.mjs";
13
- import "./sync.mjs";
14
- import { u as installCommandDef } from "../cli.mjs";
6
+ import { createIndex } from "../retriv/index.mjs";
7
+ import { n as getSharedSkillsDir } from "./shared.mjs";
8
+ import { C as downloadLlmsDocs, D as normalizeLlmsLinks, G as $fetch, M as resolveEntryFiles, T as fetchLlmsTxt, X as parseGitHubUrl, b as isShallowGitDocs, d as resolvePackageDocs, h as fetchGitDocs, k as fetchGitSkills, v as fetchReadmeContent, y as filterFrameworkDocs } from "./sources.mjs";
9
+ import { _ as targets, i as linkSkillToAgents, t as generateSkillMd } from "./prompts.mjs";
10
+ import { i as getModelLabel, n as createToolProgress, o as optimizeDocs } from "./agent.mjs";
11
+ import { F as readConfig, O as resolveAgent, T as promptForAgent, g as readLock, h as parsePackages, j as defaultFeatures, k as sharedArgs, l as timedSpinner, m as mergeLocks, v as syncLockfilesToDirs, y as writeLock } from "./formatting.mjs";
12
+ import { n as shutdownWorker } from "./pool2.mjs";
13
+ import { c as classifyCachedDoc, f as indexResources, p as selectLlmConfig } from "./sync.mjs";
14
+ import { homedir } from "node:os";
15
+ import { dirname, join } from "pathe";
16
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
17
+ import * as p from "@clack/prompts";
18
+ import { defineCommand } from "citty";
19
+ async function installCommand(opts) {
20
+ const cwd = process.cwd();
21
+ const agent = targets[opts.agent];
22
+ const shared = !opts.global && getSharedSkillsDir(cwd);
23
+ const skillsDir = opts.global ? join(homedir(), ".skilld", "skills") : shared || join(cwd, agent.skillsDir);
24
+ const allSkillsDirs = shared ? [shared] : Object.values(targets).map((t) => opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir));
25
+ const allLocks = allSkillsDirs.map((dir) => readLock(dir)).filter((l) => !!l && Object.keys(l.skills).length > 0);
26
+ if (allLocks.length === 0) {
27
+ p.log.warn("No skilld-lock.yaml found. Run `skilld` to sync skills first.");
28
+ return;
29
+ }
30
+ const lock = mergeLocks(allLocks);
31
+ const skills = Object.entries(lock.skills);
32
+ const toRestore = [];
33
+ const features = readConfig().features ?? defaultFeatures;
34
+ for (const [name, info] of skills) {
35
+ if (!info.version) continue;
36
+ if (info.source === "shipped") {
37
+ if (!existsSync(join(skillsDir, name))) toRestore.push({
38
+ name,
39
+ info
40
+ });
41
+ continue;
42
+ }
43
+ const skillDir = join(skillsDir, name);
44
+ const referencesPath = join(skillDir, ".skilld");
45
+ const skillMdPath = join(skillDir, "SKILL.md");
46
+ if (!existsSync(skillDir) || !existsSync(skillMdPath) || !existsSync(referencesPath) || hasStaleReferences(referencesPath, info.packageName || name, info.version, features)) toRestore.push({
47
+ name,
48
+ info
49
+ });
50
+ }
51
+ if (toRestore.length === 0) {
52
+ p.log.success("All up to date");
53
+ return;
54
+ }
55
+ p.log.info(`Restoring ${toRestore.length} references`);
56
+ ensureCacheDir();
57
+ const allSkillNames = skills.map(([, info]) => info.packageName || "").filter(Boolean);
58
+ const regenerated = [];
59
+ for (const { name, info } of toRestore) {
60
+ const version = info.version;
61
+ const pkgName = info.packageName || unsanitizeName(name, info.source);
62
+ if (info.source === "shipped") {
63
+ const match = getShippedSkills(pkgName, cwd, version).find((s) => s.skillName === name);
64
+ if (match) {
65
+ linkShippedSkill(skillsDir, name, match.skillDir);
66
+ p.log.success(`Linked ${name}`);
67
+ } else p.log.warn(`${name}: package ${pkgName} no longer ships this skill`);
68
+ continue;
69
+ }
70
+ if (info.source === "github" || info.source === "gitlab" || info.source === "local") {
71
+ const match = (await fetchGitSkills({
72
+ type: info.source,
73
+ ...info.repo?.includes("/") ? {
74
+ owner: info.repo.split("/")[0],
75
+ repo: info.repo.split("/")[1]
76
+ } : {},
77
+ skillPath: info.path,
78
+ ref: info.ref,
79
+ ...info.source === "local" ? { localPath: info.repo } : {}
80
+ })).skills.find((s) => s.name === name);
81
+ if (match) {
82
+ const skillDir = join(skillsDir, name);
83
+ mkdirSync(skillDir, { recursive: true });
84
+ writeFileSync(join(skillDir, "SKILL.md"), sanitizeMarkdown(match.content));
85
+ for (const f of match.files) {
86
+ const filePath = join(skillDir, f.path);
87
+ mkdirSync(dirname(filePath), { recursive: true });
88
+ writeFileSync(filePath, f.content);
89
+ }
90
+ p.log.success(`Restored ${name} from ${info.repo}`);
91
+ } else p.log.warn(`${name}: skill not found in ${info.repo}`);
92
+ continue;
93
+ }
94
+ const skillDir = join(skillsDir, name);
95
+ const referencesPath = join(skillDir, ".skilld");
96
+ const globalCachePath = getCacheDir(pkgName, version);
97
+ const spin = timedSpinner();
98
+ if (isCached(pkgName, version)) {
99
+ spin.start(`Linking ${name}`);
100
+ mkdirSync(skillDir, { recursive: true });
101
+ mkdirSync(referencesPath, { recursive: true });
102
+ linkPkgSymlink(referencesPath, pkgName, cwd, version);
103
+ for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
104
+ if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {
105
+ const docsLink = join(referencesPath, "docs");
106
+ const cachedDocs = join(globalCachePath, "docs");
107
+ if (existsSync(docsLink)) unlinkSync(docsLink);
108
+ if (existsSync(cachedDocs)) symlinkSync(cachedDocs, docsLink, "junction");
109
+ }
110
+ const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null;
111
+ const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null;
112
+ if (features.issues) {
113
+ const issuesLink = join(referencesPath, "issues");
114
+ const repoIssues = repoCachePath ? join(repoCachePath, "issues") : null;
115
+ const cachedIssues = repoIssues && existsSync(repoIssues) ? repoIssues : join(globalCachePath, "issues");
116
+ if (existsSync(issuesLink)) unlinkSync(issuesLink);
117
+ if (existsSync(cachedIssues)) symlinkSync(cachedIssues, issuesLink, "junction");
118
+ }
119
+ if (features.discussions) {
120
+ const discussionsLink = join(referencesPath, "discussions");
121
+ const repoDiscussions = repoCachePath ? join(repoCachePath, "discussions") : null;
122
+ const cachedDiscussions = repoDiscussions && existsSync(repoDiscussions) ? repoDiscussions : join(globalCachePath, "discussions");
123
+ if (existsSync(discussionsLink)) unlinkSync(discussionsLink);
124
+ if (existsSync(cachedDiscussions)) symlinkSync(cachedDiscussions, discussionsLink, "junction");
125
+ }
126
+ if (features.releases) {
127
+ const releasesLink = join(referencesPath, "releases");
128
+ const repoReleases = repoCachePath ? join(repoCachePath, "releases") : null;
129
+ const cachedReleases = repoReleases && existsSync(repoReleases) ? repoReleases : join(globalCachePath, "releases");
130
+ if (existsSync(releasesLink)) unlinkSync(releasesLink);
131
+ if (existsSync(cachedReleases)) symlinkSync(cachedReleases, releasesLink, "junction");
132
+ }
133
+ const sectionsLink = join(referencesPath, "sections");
134
+ const cachedSections = join(globalCachePath, "sections");
135
+ if (existsSync(sectionsLink)) unlinkSync(sectionsLink);
136
+ if (existsSync(cachedSections)) symlinkSync(cachedSections, sectionsLink, "junction");
137
+ if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {
138
+ spin.message(`Indexing ${name}`);
139
+ await indexResources({
140
+ packageName: pkgName,
141
+ version,
142
+ cwd,
143
+ docsToIndex: readCachedDocs(pkgName, version).map((d) => ({
144
+ id: d.path,
145
+ content: d.content,
146
+ metadata: {
147
+ package: pkgName,
148
+ source: d.path,
149
+ type: classifyCachedDoc(d.path).type
150
+ }
151
+ })),
152
+ features,
153
+ onProgress: (msg) => spin.message(msg)
154
+ });
155
+ }
156
+ if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {
157
+ if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages)) regenerated.push({
158
+ name,
159
+ pkgName,
160
+ version,
161
+ skillDir,
162
+ packages: info.packages
163
+ });
164
+ }
165
+ spin.stop(`Linked ${name}`);
166
+ continue;
167
+ }
168
+ spin.start(`Downloading ${name}@${version}`);
169
+ const resolved = await resolvePackageDocs(pkgName, { version });
170
+ if (!resolved) {
171
+ spin.stop(`Could not resolve: ${name}`);
172
+ continue;
173
+ }
174
+ const cachedDocs = [];
175
+ const docsToIndex = [];
176
+ const isFrameworkDoc = (path) => filterFrameworkDocs([path], pkgName).length > 0;
177
+ if (resolved.gitDocsUrl && resolved.repoUrl) {
178
+ const gh = parseGitHubUrl(resolved.repoUrl);
179
+ if (gh) {
180
+ const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName);
181
+ if (gitDocs?.files.length) {
182
+ const BATCH_SIZE = 20;
183
+ for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {
184
+ const batch = gitDocs.files.slice(i, i + BATCH_SIZE);
185
+ const results = await Promise.all(batch.map(async (file) => {
186
+ const content = await $fetch(`${gitDocs.baseUrl}/${file}`, { responseType: "text" }).catch(() => null);
187
+ if (!content) return null;
188
+ return {
189
+ file,
190
+ content
191
+ };
192
+ }));
193
+ for (const r of results) if (r) {
194
+ const cachePath = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, "") : r.file;
195
+ cachedDocs.push({
196
+ path: cachePath,
197
+ content: r.content
198
+ });
199
+ docsToIndex.push({
200
+ id: cachePath,
201
+ content: r.content,
202
+ metadata: {
203
+ package: pkgName,
204
+ source: cachePath,
205
+ type: "doc"
206
+ }
207
+ });
208
+ }
209
+ }
210
+ if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {
211
+ cachedDocs.length = 0;
212
+ docsToIndex.length = 0;
213
+ } else if (cachedDocs.length > 0 && resolved.llmsUrl) {
214
+ const llmsContent = await fetchLlmsTxt(resolved.llmsUrl);
215
+ if (llmsContent) {
216
+ const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin;
217
+ cachedDocs.push({
218
+ path: "llms.txt",
219
+ content: normalizeLlmsLinks(llmsContent.raw)
220
+ });
221
+ if (llmsContent.links.length > 0) {
222
+ const docs = await downloadLlmsDocs(llmsContent, baseUrl);
223
+ for (const doc of docs) {
224
+ if (!isFrameworkDoc(doc.url)) continue;
225
+ const localPath = doc.url.startsWith("/") ? doc.url.slice(1) : doc.url;
226
+ cachedDocs.push({
227
+ path: join("llms-docs", ...localPath.split("/")),
228
+ content: doc.content
229
+ });
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ if (resolved.llmsUrl && cachedDocs.length === 0) {
238
+ const llmsContent = await fetchLlmsTxt(resolved.llmsUrl);
239
+ if (llmsContent) {
240
+ cachedDocs.push({
241
+ path: "llms.txt",
242
+ content: normalizeLlmsLinks(llmsContent.raw)
243
+ });
244
+ if (llmsContent.links.length > 0) {
245
+ const docs = await downloadLlmsDocs(llmsContent, resolved.docsUrl || new URL(resolved.llmsUrl).origin);
246
+ for (const doc of docs) {
247
+ if (!isFrameworkDoc(doc.url)) continue;
248
+ const cachePath = join("docs", ...(doc.url.startsWith("/") ? doc.url.slice(1) : doc.url).split("/"));
249
+ cachedDocs.push({
250
+ path: cachePath,
251
+ content: doc.content
252
+ });
253
+ docsToIndex.push({
254
+ id: doc.url,
255
+ content: doc.content,
256
+ metadata: {
257
+ package: pkgName,
258
+ source: cachePath,
259
+ type: "doc"
260
+ }
261
+ });
262
+ }
263
+ }
264
+ }
265
+ }
266
+ if (resolved.readmeUrl && cachedDocs.length === 0) {
267
+ const content = await fetchReadmeContent(resolved.readmeUrl);
268
+ if (content) {
269
+ cachedDocs.push({
270
+ path: "docs/README.md",
271
+ content
272
+ });
273
+ docsToIndex.push({
274
+ id: "README.md",
275
+ content,
276
+ metadata: {
277
+ package: pkgName,
278
+ source: "docs/README.md",
279
+ type: "doc"
280
+ }
281
+ });
282
+ }
283
+ }
284
+ if (cachedDocs.length > 0) {
285
+ writeToCache(pkgName, version, cachedDocs);
286
+ mkdirSync(referencesPath, { recursive: true });
287
+ linkPkgSymlink(referencesPath, pkgName, cwd, version);
288
+ for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
289
+ if (!isReadmeOnly(globalCachePath)) {
290
+ const docsLink = join(referencesPath, "docs");
291
+ const cachedDocsDir = join(globalCachePath, "docs");
292
+ if (existsSync(docsLink)) unlinkSync(docsLink);
293
+ if (existsSync(cachedDocsDir)) symlinkSync(cachedDocsDir, docsLink, "junction");
294
+ }
295
+ if (features.search) {
296
+ if (docsToIndex.length > 0) await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) });
297
+ const pkgDir = resolvePkgDir(pkgName, cwd, version);
298
+ const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : [];
299
+ if (entryFiles.length > 0) await createIndex(entryFiles.map((e) => ({
300
+ id: e.path,
301
+ content: e.content,
302
+ metadata: {
303
+ package: pkgName,
304
+ source: `pkg/${e.path}`,
305
+ type: e.type
306
+ }
307
+ })), { dbPath: getPackageDbPath(pkgName, version) });
308
+ }
309
+ if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {
310
+ if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages)) regenerated.push({
311
+ name,
312
+ pkgName,
313
+ version,
314
+ skillDir,
315
+ packages: info.packages
316
+ });
317
+ }
318
+ spin.stop(`Downloaded and linked ${name}`);
319
+ } else spin.stop(`No docs found for ${name}`);
320
+ }
321
+ if (regenerated.length > 0 && !readConfig().skipLlm) {
322
+ const llmConfig = await selectLlmConfig(void 0, `Enhance SKILL.md for ${regenerated.map((r) => r.name).join(", ")}`);
323
+ if (llmConfig) {
324
+ p.log.step(getModelLabel(llmConfig.model));
325
+ for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages);
326
+ }
327
+ }
328
+ for (const [name, info] of Object.entries(lock.skills)) writeLock(skillsDir, name, info);
329
+ if (shared) for (const [name] of skills) linkSkillToAgents(name, shared, cwd);
330
+ else syncLockfilesToDirs(lock, allSkillsDirs.filter((d) => d !== skillsDir));
331
+ await shutdownWorker();
332
+ p.outro("Install complete");
333
+ }
334
+ /** Copy SKILL.md from another agent's skill dir if one exists */
335
+ function copyFromExistingAgent(skillDir, name, allSkillsDirs) {
336
+ const targetMd = join(skillDir, "SKILL.md");
337
+ if (existsSync(targetMd)) return false;
338
+ for (const dir of allSkillsDirs) {
339
+ if (dir === skillDir) continue;
340
+ const candidateMd = join(dir, name, "SKILL.md");
341
+ if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {
342
+ mkdirSync(skillDir, { recursive: true });
343
+ copyFileSync(candidateMd, targetMd);
344
+ return true;
345
+ }
346
+ }
347
+ return false;
348
+ }
349
+ /** Try to recover original package name from sanitized name + source */
350
+ function unsanitizeName(sanitized, source) {
351
+ if (source?.includes("ungh://")) {
352
+ const match = source.match(/ungh:\/\/([^/]+)\/(.+)/);
353
+ if (match) return `@${match[1]}/${match[2]}`;
354
+ }
355
+ if (sanitized.startsWith("antfu-")) return `@antfu/${sanitized.slice(6)}`;
356
+ if (sanitized.startsWith("clack-")) return `@clack/${sanitized.slice(6)}`;
357
+ if (sanitized.startsWith("nuxt-")) return `@nuxt/${sanitized.slice(5)}`;
358
+ if (sanitized.startsWith("vue-")) return `@vue/${sanitized.slice(4)}`;
359
+ if (sanitized.startsWith("vueuse-")) return `@vueuse/${sanitized.slice(7)}`;
360
+ return sanitized;
361
+ }
362
+ /** Create pkg symlink inside references dir (links to entire package or cached dist) */
363
+ function linkPkgSymlink(referencesDir, name, cwd, version) {
364
+ const pkgPath = resolvePkgDir(name, cwd, version);
365
+ if (!pkgPath) return;
366
+ const pkgLink = join(referencesDir, "pkg");
367
+ if (existsSync(pkgLink)) unlinkSync(pkgLink);
368
+ symlinkSync(pkgPath, pkgLink, "junction");
369
+ }
370
+ /** Check if cache only has docs/README.md (pkg/ already has this) */
371
+ function isReadmeOnly(cacheDir) {
372
+ const docsDir = join(cacheDir, "docs");
373
+ if (!existsSync(docsDir)) return false;
374
+ const files = readdirSync(docsDir);
375
+ return files.length === 1 && files[0] === "README.md";
376
+ }
377
+ /** Check if package ships its own docs folder */
378
+ function pkgHasShippedDocs(name, cwd, version) {
379
+ const pkgPath = resolvePkgDir(name, cwd, version);
380
+ if (!pkgPath) return false;
381
+ for (const candidate of [
382
+ "docs",
383
+ "documentation",
384
+ "doc"
385
+ ]) if (existsSync(join(pkgPath, candidate))) return true;
386
+ return false;
387
+ }
388
+ /** Run LLM enhancement on a regenerated SKILL.md */
389
+ async function enhanceRegenerated(pkgName, version, skillDir, model, sections, customPrompt, packages) {
390
+ const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}` });
391
+ const docFiles = listReferenceFiles(skillDir);
392
+ const globalCachePath = getCacheDir(pkgName, version);
393
+ const hasIssues = existsSync(join(globalCachePath, "issues"));
394
+ const hasDiscussions = existsSync(join(globalCachePath, "discussions"));
395
+ const hasGithub = hasIssues || hasDiscussions;
396
+ const hasReleases = existsSync(join(globalCachePath, "releases"));
397
+ const features = readConfig().features ?? defaultFeatures;
398
+ const { optimized, wasOptimized } = await optimizeDocs({
399
+ packageName: pkgName,
400
+ skillDir,
401
+ model,
402
+ version,
403
+ hasGithub,
404
+ hasReleases,
405
+ docFiles,
406
+ sections,
407
+ customPrompt,
408
+ features,
409
+ pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
410
+ onProgress: createToolProgress(llmLog)
411
+ });
412
+ if (wasOptimized) {
413
+ llmLog.success("Generated best practices");
414
+ const cwd = process.cwd();
415
+ const pkgPath = resolvePkgDir(pkgName, cwd, version);
416
+ let description;
417
+ let dependencies;
418
+ if (pkgPath) {
419
+ const pkgJsonPath = join(pkgPath, "package.json");
420
+ if (existsSync(pkgJsonPath)) {
421
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
422
+ description = pkg.description;
423
+ dependencies = pkg.dependencies;
424
+ }
425
+ }
426
+ let docsType = "docs";
427
+ if (existsSync(join(globalCachePath, "docs", "llms.txt"))) docsType = "llms.txt";
428
+ else if (isReadmeOnly(globalCachePath)) docsType = "readme";
429
+ const dirName = skillDir.split("/").pop();
430
+ const allPackages = parsePackages(packages).map((p) => ({ name: p.name }));
431
+ const skillMd = generateSkillMd({
432
+ name: pkgName,
433
+ version,
434
+ description,
435
+ dependencies,
436
+ body: optimized,
437
+ relatedSkills: [],
438
+ hasIssues,
439
+ hasDiscussions,
440
+ hasReleases,
441
+ docsType,
442
+ hasShippedDocs: hasShippedDocs(pkgName, cwd, version),
443
+ pkgFiles: getPkgKeyFiles(pkgName, cwd, version),
444
+ dirName,
445
+ packages: allPackages.length > 1 ? allPackages : void 0,
446
+ features
447
+ });
448
+ writeFileSync(join(skillDir, "SKILL.md"), skillMd);
449
+ } else llmLog.error("LLM optimization skipped");
450
+ }
451
+ const installCommandDef = defineCommand({
452
+ meta: {
453
+ name: "install",
454
+ description: "Restore references from lockfile"
455
+ },
456
+ args: {
457
+ global: sharedArgs.global,
458
+ agent: sharedArgs.agent
459
+ },
460
+ async run({ args }) {
461
+ let agent = resolveAgent(args.agent);
462
+ if (!agent) {
463
+ agent = await promptForAgent();
464
+ if (!agent) return;
465
+ }
466
+ p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m install`);
467
+ return installCommand({
468
+ global: args.global,
469
+ agent
470
+ });
471
+ }
472
+ });
473
+ /** Regenerate base SKILL.md from local metadata if missing */
474
+ function regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, source, packages) {
475
+ const skillMdPath = join(skillDir, "SKILL.md");
476
+ if (existsSync(skillMdPath)) return false;
477
+ const pkgPath = resolvePkgDir(pkgName, cwd, version);
478
+ let description;
479
+ let dependencies;
480
+ if (pkgPath) {
481
+ const pkgJsonPath = join(pkgPath, "package.json");
482
+ if (existsSync(pkgJsonPath)) {
483
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
484
+ description = pkg.description;
485
+ dependencies = pkg.dependencies;
486
+ }
487
+ }
488
+ const globalCachePath = getCacheDir(pkgName, version);
489
+ let docsType = "docs";
490
+ if (source?.includes("llms.txt") || existsSync(join(globalCachePath, "docs", "llms.txt"))) docsType = "llms.txt";
491
+ else if (isReadmeOnly(globalCachePath)) docsType = "readme";
492
+ const feat = readConfig().features ?? defaultFeatures;
493
+ const hasIssues = feat.issues && existsSync(join(globalCachePath, "issues"));
494
+ const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, "discussions"));
495
+ const hasReleases = feat.releases && existsSync(join(globalCachePath, "releases"));
496
+ const relatedSkills = allSkillNames.filter((n) => n !== pkgName);
497
+ const dirName = skillDir.split("/").pop();
498
+ const allPackages = parsePackages(packages).map((p) => ({ name: p.name }));
499
+ const content = generateSkillMd({
500
+ name: pkgName,
501
+ version,
502
+ description,
503
+ dependencies,
504
+ relatedSkills,
505
+ hasIssues,
506
+ hasDiscussions,
507
+ hasReleases,
508
+ docsType,
509
+ hasShippedDocs: hasShippedDocs(pkgName, cwd, version),
510
+ pkgFiles: getPkgKeyFiles(pkgName, cwd, version),
511
+ dirName,
512
+ packages: allPackages.length > 1 ? allPackages : void 0,
513
+ features: readConfig().features ?? defaultFeatures
514
+ });
515
+ mkdirSync(skillDir, { recursive: true });
516
+ writeFileSync(skillMdPath, content);
517
+ return true;
518
+ }
519
+ /** Check if .skilld/ has broken symlinks or is missing expected references from global cache */
520
+ function hasStaleReferences(referencesPath, pkgName, version, features) {
521
+ for (const entry of readdirSync(referencesPath)) {
522
+ const entryPath = join(referencesPath, entry);
523
+ if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath)) return true;
524
+ }
525
+ if (!existsSync(join(referencesPath, "pkg"))) return true;
526
+ const globalCachePath = getCacheDir(pkgName, version);
527
+ const expected = [
528
+ ["docs", existsSync(join(globalCachePath, "docs"))],
529
+ ["issues", features.issues && existsSync(join(globalCachePath, "issues"))],
530
+ ["discussions", features.discussions && existsSync(join(globalCachePath, "discussions"))],
531
+ ["releases", features.releases && existsSync(join(globalCachePath, "releases"))],
532
+ ["sections", existsSync(join(globalCachePath, "sections"))]
533
+ ];
534
+ for (const [name, shouldExist] of expected) if (shouldExist && !existsSync(join(referencesPath, name))) return true;
535
+ return false;
536
+ }
15
537
  export { installCommandDef };
538
+
539
+ //# sourceMappingURL=install.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.mjs","names":["agents","checkShippedDocs"],"sources":["../../src/commands/install.ts"],"sourcesContent":["/**\n * Install command - restore .skilld/ and SKILL.md from lockfile\n *\n * After cloning a repo, the .skilld/ symlinks are missing (gitignored).\n * If SKILL.md was deleted, a base version is regenerated from local metadata.\n * This command recreates them from the lockfile:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> (always)\n * .claude/skills/<skill>/.skilld/docs -> ~/.skilld/references/<pkg>@<version>/docs (if external)\n * .claude/skills/<skill>/SKILL.md -> regenerated from package.json + cache state\n */\n\nimport type { AgentType, CustomPrompt, SkillSection } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { SkillInfo } from '../core/lockfile.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { dirname, join } from 'pathe'\nimport { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'\nimport { generateSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n isCached,\n linkPkgNamed,\n linkShippedSkill,\n listReferenceFiles,\n readCachedDocs,\n resolvePkgDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n $fetch,\n downloadLlmsDocs,\n fetchGitDocs,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { classifyCachedDoc, indexResources } from './sync-shared.ts'\nimport { selectLlmConfig } from './sync.ts'\n\nexport interface InstallOptions {\n global: boolean\n agent: AgentType\n}\n\nexport async function installCommand(opts: InstallOptions): Promise<void> {\n const cwd = process.cwd()\n const agent = agents[opts.agent]\n const shared = !opts.global && getSharedSkillsDir(cwd)\n const skillsDir = opts.global\n ? join(homedir(), '.skilld', 'skills')\n : shared || join(cwd, agent.skillsDir)\n\n // Collect lockfiles from all agent skill dirs and merge\n // In shared mode, read from .skills/ only\n const allSkillsDirs = shared\n ? [shared]\n : Object.values(agents).map(t =>\n opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir),\n )\n const allLocks = allSkillsDirs\n .map(dir => readLock(dir))\n .filter((l): l is NonNullable<typeof l> => !!l && Object.keys(l.skills).length > 0)\n\n if (allLocks.length === 0) {\n p.log.warn('No skilld-lock.yaml found. Run `skilld` to sync skills first.')\n return\n }\n\n const lock = mergeLocks(allLocks)\n\n const skills = Object.entries(lock.skills)\n const toRestore: Array<{ name: string, info: SkillInfo }> = []\n const features = readConfig().features ?? defaultFeatures\n\n // Find skills with missing/broken references symlinks\n for (const [name, info] of skills) {\n if (!info.version)\n continue\n\n // Shipped skills: the skill dir IS the symlink, no references/ subdir\n if (info.source === 'shipped') {\n const skillDir = join(skillsDir, name)\n if (!existsSync(skillDir)) {\n toRestore.push({ name, info })\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const skillMdPath = join(skillDir, 'SKILL.md')\n\n // Check skill dir, SKILL.md, and all internal .skilld/ references\n const needsRestore = !existsSync(skillDir)\n || !existsSync(skillMdPath)\n || !existsSync(referencesPath)\n || hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)\n\n if (needsRestore) {\n toRestore.push({ name, info })\n }\n }\n\n if (toRestore.length === 0) {\n p.log.success('All up to date')\n return\n }\n\n p.log.info(`Restoring ${toRestore.length} references`)\n ensureCacheDir()\n\n const allSkillNames = skills.map(([, info]) => info.packageName || '').filter(Boolean)\n const regenerated: Array<{ name: string, pkgName: string, version: string, skillDir: string, packages?: string }> = []\n\n for (const { name, info } of toRestore) {\n const version = info.version!\n const pkgName = info.packageName || unsanitizeName(name, info.source)\n\n // Shipped skills: re-link from node_modules or cached dist\n if (info.source === 'shipped') {\n const shipped = getShippedSkills(pkgName, cwd, version)\n const match = shipped.find(s => s.skillName === name)\n if (match) {\n linkShippedSkill(skillsDir, name, match.skillDir)\n p.log.success(`Linked ${name}`)\n }\n else {\n p.log.warn(`${name}: package ${pkgName} no longer ships this skill`)\n }\n continue\n }\n\n // Git-sourced skills: re-fetch from remote\n if (info.source === 'github' || info.source === 'gitlab' || info.source === 'local') {\n const source = {\n type: info.source as 'github' | 'gitlab' | 'local',\n ...(info.repo?.includes('/') ? { owner: info.repo.split('/')[0], repo: info.repo.split('/')[1] } : {}),\n skillPath: info.path,\n ref: info.ref,\n ...(info.source === 'local' ? { localPath: info.repo } : {}),\n }\n const result = await fetchGitSkills(source)\n const match = result.skills.find(s => s.name === name)\n if (match) {\n const skillDir = join(skillsDir, name)\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))\n for (const f of match.files) {\n const filePath = join(skillDir, f.path)\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, f.content)\n }\n p.log.success(`Restored ${name} from ${info.repo}`)\n }\n else {\n p.log.warn(`${name}: skill not found in ${info.repo}`)\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const globalCachePath = getCacheDir(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (isCached(pkgName, version)) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Only link external docs if package doesn't ship its own and has more than just README\n if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocs = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocs))\n symlinkSync(cachedDocs, docsLink, 'junction')\n }\n // Link issues, discussions, and releases (try repo cache first, fall back to package cache)\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null\n if (features.issues) {\n const issuesLink = join(referencesPath, 'issues')\n const repoIssues = repoCachePath ? join(repoCachePath, 'issues') : null\n const cachedIssues = (repoIssues && existsSync(repoIssues)) ? repoIssues : join(globalCachePath, 'issues')\n if (existsSync(issuesLink))\n unlinkSync(issuesLink)\n if (existsSync(cachedIssues))\n symlinkSync(cachedIssues, issuesLink, 'junction')\n }\n if (features.discussions) {\n const discussionsLink = join(referencesPath, 'discussions')\n const repoDiscussions = repoCachePath ? join(repoCachePath, 'discussions') : null\n const cachedDiscussions = (repoDiscussions && existsSync(repoDiscussions)) ? repoDiscussions : join(globalCachePath, 'discussions')\n if (existsSync(discussionsLink))\n unlinkSync(discussionsLink)\n if (existsSync(cachedDiscussions))\n symlinkSync(cachedDiscussions, discussionsLink, 'junction')\n }\n if (features.releases) {\n const releasesLink = join(referencesPath, 'releases')\n const repoReleases = repoCachePath ? join(repoCachePath, 'releases') : null\n const cachedReleases = (repoReleases && existsSync(repoReleases)) ? repoReleases : join(globalCachePath, 'releases')\n if (existsSync(releasesLink))\n unlinkSync(releasesLink)\n if (existsSync(cachedReleases))\n symlinkSync(cachedReleases, releasesLink, 'junction')\n }\n const sectionsLink = join(referencesPath, 'sections')\n const cachedSections = join(globalCachePath, 'sections')\n if (existsSync(sectionsLink))\n unlinkSync(sectionsLink)\n if (existsSync(cachedSections))\n symlinkSync(cachedSections, sectionsLink, 'junction')\n // Create search index from cached docs if missing\n if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {\n spin.message(`Indexing ${name}`)\n const cached = readCachedDocs(pkgName, version)\n const docsToIndex = cached.map(d => ({\n id: d.path,\n content: d.content,\n metadata: { package: pkgName, source: d.path, type: classifyCachedDoc(d.path).type },\n }))\n await indexResources({ packageName: pkgName, version, cwd, docsToIndex, features, onProgress: msg => spin.message(msg) })\n }\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Linked ${name}`)\n continue\n }\n\n // Need to download to global cache first\n spin.start(`Downloading ${name}@${version}`)\n\n const resolved = await resolvePackageDocs(pkgName, { version })\n\n if (!resolved) {\n spin.stop(`Could not resolve: ${name}`)\n continue\n }\n\n const cachedDocs: Array<{ path: string, content: string }> = []\n const docsToIndex: Array<{ id: string, content: string, metadata: Record<string, any> }> = []\n const isFrameworkDoc = (path: string) => filterFrameworkDocs([path], pkgName).length > 0\n\n // Try git docs first\n if (resolved.gitDocsUrl && resolved.repoUrl) {\n const gh = parseGitHubUrl(resolved.repoUrl)\n if (gh) {\n const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName)\n if (gitDocs?.files.length) {\n const BATCH_SIZE = 20\n for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {\n const batch = gitDocs.files.slice(i, i + BATCH_SIZE)\n const results = await Promise.all(\n batch.map(async (file) => {\n const url = `${gitDocs.baseUrl}/${file}`\n const content = await $fetch(url, { responseType: 'text' }).catch(() => null)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const cachePath = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n cachedDocs.push({ path: cachePath, content: r.content })\n docsToIndex.push({ id: cachePath, content: r.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n\n // Shallow git-docs: if < threshold and llms.txt exists, discard and fall through\n if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {\n cachedDocs.length = 0\n docsToIndex.length = 0\n }\n else if (cachedDocs.length > 0 && resolved.llmsUrl) {\n // Always cache llms.txt alongside good git-docs as supplementary reference\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n cachedDocs.push({ path: join('llms-docs', ...localPath.split('/')), content: doc.content })\n }\n }\n }\n }\n }\n }\n }\n\n // Try llms.txt\n if (resolved.llmsUrl && cachedDocs.length === 0) {\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n const cachePath = join('docs', ...localPath.split('/'))\n cachedDocs.push({ path: cachePath, content: doc.content })\n docsToIndex.push({ id: doc.url, content: doc.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n }\n\n // Fallback to README\n if (resolved.readmeUrl && cachedDocs.length === 0) {\n const content = await fetchReadmeContent(resolved.readmeUrl)\n if (content) {\n cachedDocs.push({ path: 'docs/README.md', content })\n docsToIndex.push({ id: 'README.md', content, metadata: { package: pkgName, source: 'docs/README.md', type: 'doc' } })\n }\n }\n\n if (cachedDocs.length > 0) {\n writeToCache(pkgName, version, cachedDocs)\n\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Link fetched docs unless it's just a README (already in pkg/)\n if (!isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocsDir = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocsDir))\n symlinkSync(cachedDocsDir, docsLink, 'junction')\n }\n\n if (features.search) {\n if (docsToIndex.length > 0) {\n await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) })\n }\n\n // Index package entry files (.d.ts / .js)\n const pkgDir = resolvePkgDir(pkgName, cwd, version)\n const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : []\n if (entryFiles.length > 0) {\n await createIndex(entryFiles.map(e => ({\n id: e.path,\n content: e.content,\n metadata: { package: pkgName, source: `pkg/${e.path}`, type: e.type },\n })), { dbPath: getPackageDbPath(pkgName, version) })\n }\n }\n\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Downloaded and linked ${name}`)\n }\n else {\n spin.stop(`No docs found for ${name}`)\n }\n }\n\n // Offer LLM enhancement for regenerated SKILL.md files\n if (regenerated.length > 0 && !readConfig().skipLlm) {\n const names = regenerated.map(r => r.name).join(', ')\n const llmConfig = await selectLlmConfig(undefined, `Enhance SKILL.md for ${names}`)\n if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) {\n await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages)\n }\n }\n }\n\n // Write merged lockfile to target dir and sync to all other existing lockfiles\n for (const [name, info] of Object.entries(lock.skills))\n writeLock(skillsDir, name, info)\n\n // In shared mode: recreate per-agent symlinks, skip per-agent lockfile sync\n if (shared) {\n for (const [name] of skills)\n linkSkillToAgents(name, shared, cwd)\n }\n else {\n syncLockfilesToDirs(lock, allSkillsDirs.filter(d => d !== skillsDir))\n }\n\n await shutdownWorker()\n\n p.outro('Install complete')\n}\n\n/** Copy SKILL.md from another agent's skill dir if one exists */\nfunction copyFromExistingAgent(skillDir: string, name: string, allSkillsDirs: string[]): boolean {\n const targetMd = join(skillDir, 'SKILL.md')\n if (existsSync(targetMd))\n return false\n for (const dir of allSkillsDirs) {\n if (dir === skillDir)\n continue\n const candidateMd = join(dir, name, 'SKILL.md')\n if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {\n mkdirSync(skillDir, { recursive: true })\n copyFileSync(candidateMd, targetMd)\n return true\n }\n }\n return false\n}\n\n/** Try to recover original package name from sanitized name + source */\nfunction unsanitizeName(sanitized: string, source?: string): string {\n if (source?.includes('ungh://')) {\n const match = source.match(/ungh:\\/\\/([^/]+)\\/(.+)/)\n if (match)\n return `@${match[1]}/${match[2]}`\n }\n\n if (sanitized.startsWith('antfu-'))\n return `@antfu/${sanitized.slice(6)}`\n if (sanitized.startsWith('clack-'))\n return `@clack/${sanitized.slice(6)}`\n if (sanitized.startsWith('nuxt-'))\n return `@nuxt/${sanitized.slice(5)}`\n if (sanitized.startsWith('vue-'))\n return `@vue/${sanitized.slice(4)}`\n if (sanitized.startsWith('vueuse-'))\n return `@vueuse/${sanitized.slice(7)}`\n\n return sanitized\n}\n\n/** Create pkg symlink inside references dir (links to entire package or cached dist) */\nfunction linkPkgSymlink(referencesDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const pkgLink = join(referencesDir, 'pkg')\n if (existsSync(pkgLink))\n unlinkSync(pkgLink)\n symlinkSync(pkgPath, pkgLink, 'junction')\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nfunction isReadmeOnly(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\n/** Check if package ships its own docs folder */\nfunction pkgHasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/** Run LLM enhancement on a regenerated SKILL.md */\nasync function enhanceRegenerated(\n pkgName: string,\n version: string,\n skillDir: string,\n model: Parameters<typeof optimizeDocs>[0]['model'],\n sections: SkillSection[],\n customPrompt?: CustomPrompt,\n packages?: string,\n): Promise<void> {\n const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}` })\n\n const docFiles = listReferenceFiles(skillDir)\n const globalCachePath = getCacheDir(pkgName, version)\n const hasIssues = existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = existsSync(join(globalCachePath, 'discussions'))\n const hasGithub = hasIssues || hasDiscussions\n const hasReleases = existsSync(join(globalCachePath, 'releases'))\n\n const features = readConfig().features ?? defaultFeatures\n const { optimized, wasOptimized } = await optimizeDocs({\n packageName: pkgName,\n skillDir,\n model,\n version,\n hasGithub,\n hasReleases,\n docFiles,\n sections,\n customPrompt,\n features,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n onProgress: createToolProgress(llmLog),\n })\n\n if (wasOptimized) {\n llmLog.success('Generated best practices')\n // Re-read local metadata for the enhanced version\n const cwd = process.cwd()\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.error('LLM optimization skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent) {\n agent = await promptForAgent()\n if (!agent)\n return\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n dependencies,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmEA,eAAsB,eAAe,MAAqC;CACxE,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,QAAQA,QAAO,KAAK;CAC1B,MAAM,SAAS,CAAC,KAAK,UAAU,mBAAmB,IAAI;CACtD,MAAM,YAAY,KAAK,SACnB,KAAK,SAAS,EAAE,WAAW,SAAS,GACpC,UAAU,KAAK,KAAK,MAAM,UAAU;CAIxC,MAAM,gBAAgB,SAClB,CAAC,OAAO,GACR,OAAO,OAAOA,QAAO,CAAC,KAAI,MACxB,KAAK,SAAS,EAAE,kBAAkB,KAAK,KAAK,EAAE,UAAU,CACzD;CACL,MAAM,WAAW,cACd,KAAI,QAAO,SAAS,IAAI,CAAC,CACzB,QAAQ,MAAkC,CAAC,CAAC,KAAK,OAAO,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE;AAErF,KAAI,SAAS,WAAW,GAAG;AACzB,IAAE,IAAI,KAAK,gEAAgE;AAC3E;;CAGF,MAAM,OAAO,WAAW,SAAS;CAEjC,MAAM,SAAS,OAAO,QAAQ,KAAK,OAAO;CAC1C,MAAM,YAAsD,EAAE;CAC9D,MAAM,WAAW,YAAY,CAAC,YAAY;AAG1C,MAAK,MAAM,CAAC,MAAM,SAAS,QAAQ;AACjC,MAAI,CAAC,KAAK,QACR;AAGF,MAAI,KAAK,WAAW,WAAW;AAE7B,OAAI,CAAC,WADY,KAAK,WAAW,KAAK,CACb,CACvB,WAAU,KAAK;IAAE;IAAM;IAAM,CAAC;AAEhC;;EAGF,MAAM,WAAW,KAAK,WAAW,KAAK;EACtC,MAAM,iBAAiB,KAAK,UAAU,UAAU;EAChD,MAAM,cAAc,KAAK,UAAU,WAAW;AAQ9C,MALqB,CAAC,WAAW,SAAS,IACrC,CAAC,WAAW,YAAY,IACxB,CAAC,WAAW,eAAe,IAC3B,mBAAmB,gBAAgB,KAAK,eAAe,MAAM,KAAK,SAAU,SAAS,CAGxF,WAAU,KAAK;GAAE;GAAM;GAAM,CAAC;;AAIlC,KAAI,UAAU,WAAW,GAAG;AAC1B,IAAE,IAAI,QAAQ,iBAAiB;AAC/B;;AAGF,GAAE,IAAI,KAAK,aAAa,UAAU,OAAO,aAAa;AACtD,iBAAgB;CAEhB,MAAM,gBAAgB,OAAO,KAAK,GAAG,UAAU,KAAK,eAAe,GAAG,CAAC,OAAO,QAAQ;CACtF,MAAM,cAA8G,EAAE;AAEtH,MAAK,MAAM,EAAE,MAAM,UAAU,WAAW;EACtC,MAAM,UAAU,KAAK;EACrB,MAAM,UAAU,KAAK,eAAe,eAAe,MAAM,KAAK,OAAO;AAGrE,MAAI,KAAK,WAAW,WAAW;GAE7B,MAAM,QADU,iBAAiB,SAAS,KAAK,QAAQ,CACjC,MAAK,MAAK,EAAE,cAAc,KAAK;AACrD,OAAI,OAAO;AACT,qBAAiB,WAAW,MAAM,MAAM,SAAS;AACjD,MAAE,IAAI,QAAQ,UAAU,OAAO;SAG/B,GAAE,IAAI,KAAK,GAAG,KAAK,YAAY,QAAQ,6BAA6B;AAEtE;;AAIF,MAAI,KAAK,WAAW,YAAY,KAAK,WAAW,YAAY,KAAK,WAAW,SAAS;GASnF,MAAM,SADS,MAAM,eAPN;IACb,MAAM,KAAK;IACX,GAAI,KAAK,MAAM,SAAS,IAAI,GAAG;KAAE,OAAO,KAAK,KAAK,MAAM,IAAI,CAAC;KAAI,MAAM,KAAK,KAAK,MAAM,IAAI,CAAC;KAAI,GAAG,EAAE;IACrG,WAAW,KAAK;IAChB,KAAK,KAAK;IACV,GAAI,KAAK,WAAW,UAAU,EAAE,WAAW,KAAK,MAAM,GAAG,EAAA;IAC1D,CAC0C,EACtB,OAAO,MAAK,MAAK,EAAE,SAAS,KAAK;AACtD,OAAI,OAAO;IACT,MAAM,WAAW,KAAK,WAAW,KAAK;AACtC,cAAU,UAAU,EAAE,WAAW,MAAM,CAAC;AACxC,kBAAc,KAAK,UAAU,WAAW,EAAE,iBAAiB,MAAM,QAAQ,CAAC;AAC1E,SAAK,MAAM,KAAK,MAAM,OAAO;KAC3B,MAAM,WAAW,KAAK,UAAU,EAAE,KAAK;AACvC,eAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AACjD,mBAAc,UAAU,EAAE,QAAQ;;AAEpC,MAAE,IAAI,QAAQ,YAAY,KAAK,QAAQ,KAAK,OAAO;SAGnD,GAAE,IAAI,KAAK,GAAG,KAAK,uBAAuB,KAAK,OAAO;AAExD;;EAGF,MAAM,WAAW,KAAK,WAAW,KAAK;EACtC,MAAM,iBAAiB,KAAK,UAAU,UAAU;EAChD,MAAM,kBAAkB,YAAY,SAAS,QAAQ;EACrD,MAAM,OAAO,cAAc;AAG3B,MAAI,SAAS,SAAS,QAAQ,EAAE;AAC9B,QAAK,MAAM,WAAW,OAAO;AAC7B,aAAU,UAAU,EAAE,WAAW,MAAM,CAAC;AACxC,aAAU,gBAAgB,EAAE,WAAW,MAAM,CAAC;AAC9C,kBAAe,gBAAgB,SAAS,KAAK,QAAQ;AAErD,QAAK,MAAM,OAAO,cAAc,KAAK,SAAS,CAC5C,cAAa,UAAU,IAAI,MAAM,KAAK,IAAI,QAAQ;AAEpD,OAAI,CAAC,kBAAkB,SAAS,KAAK,QAAQ,IAAI,CAAC,aAAa,gBAAgB,EAAE;IAC/E,MAAM,WAAW,KAAK,gBAAgB,OAAO;IAC7C,MAAM,aAAa,KAAK,iBAAiB,OAAO;AAChD,QAAI,WAAW,SAAS,CACtB,YAAW,SAAS;AACtB,QAAI,WAAW,WAAW,CACxB,aAAY,YAAY,UAAU,WAAW;;GAGjD,MAAM,SAAS,KAAK,OAAO,eAAe,sBAAsB,KAAK,OAAO,GAAG;GAC/E,MAAM,gBAAgB,SAAS,gBAAgB,OAAO,OAAO,OAAO,KAAK,GAAG;AAC5E,OAAI,SAAS,QAAQ;IACnB,MAAM,aAAa,KAAK,gBAAgB,SAAS;IACjD,MAAM,aAAa,gBAAgB,KAAK,eAAe,SAAS,GAAG;IACnE,MAAM,eAAgB,cAAc,WAAW,WAAW,GAAI,aAAa,KAAK,iBAAiB,SAAS;AAC1G,QAAI,WAAW,WAAW,CACxB,YAAW,WAAW;AACxB,QAAI,WAAW,aAAa,CAC1B,aAAY,cAAc,YAAY,WAAW;;AAErD,OAAI,SAAS,aAAa;IACxB,MAAM,kBAAkB,KAAK,gBAAgB,cAAc;IAC3D,MAAM,kBAAkB,gBAAgB,KAAK,eAAe,cAAc,GAAG;IAC7E,MAAM,oBAAqB,mBAAmB,WAAW,gBAAgB,GAAI,kBAAkB,KAAK,iBAAiB,cAAc;AACnI,QAAI,WAAW,gBAAgB,CAC7B,YAAW,gBAAgB;AAC7B,QAAI,WAAW,kBAAkB,CAC/B,aAAY,mBAAmB,iBAAiB,WAAW;;AAE/D,OAAI,SAAS,UAAU;IACrB,MAAM,eAAe,KAAK,gBAAgB,WAAW;IACrD,MAAM,eAAe,gBAAgB,KAAK,eAAe,WAAW,GAAG;IACvE,MAAM,iBAAkB,gBAAgB,WAAW,aAAa,GAAI,eAAe,KAAK,iBAAiB,WAAW;AACpH,QAAI,WAAW,aAAa,CAC1B,YAAW,aAAa;AAC1B,QAAI,WAAW,eAAe,CAC5B,aAAY,gBAAgB,cAAc,WAAW;;GAEzD,MAAM,eAAe,KAAK,gBAAgB,WAAW;GACrD,MAAM,iBAAiB,KAAK,iBAAiB,WAAW;AACxD,OAAI,WAAW,aAAa,CAC1B,YAAW,aAAa;AAC1B,OAAI,WAAW,eAAe,CAC5B,aAAY,gBAAgB,cAAc,WAAW;AAEvD,OAAI,SAAS,UAAU,CAAC,WAAW,iBAAiB,SAAS,QAAQ,CAAC,EAAE;AACtE,SAAK,QAAQ,YAAY,OAAO;AAOhC,UAAM,eAAe;KAAE,aAAa;KAAS;KAAS;KAAK,aAN5C,eAAe,SAAS,QAAQ,CACpB,KAAI,OAAM;MACnC,IAAI,EAAE;MACN,SAAS,EAAE;MACX,UAAU;OAAE,SAAS;OAAS,QAAQ,EAAE;OAAM,MAAM,kBAAkB,EAAE,KAAK,CAAC;;MAC/E,EAAE;KACqE;KAAU,aAAY,QAAO,KAAK,QAAQ,IAAA;KAAM,CAAC;;AAE3H,OAAI,CAAC,sBAAsB,UAAU,MAAM,cAAc;QACnD,sBAAsB,UAAU,SAAS,SAAS,KAAK,eAAe,KAAK,QAAQ,KAAK,SAAS,CACnG,aAAY,KAAK;KAAE;KAAM;KAAS;KAAS;KAAU,UAAU,KAAK;KAAU,CAAC;;AAEnF,QAAK,KAAK,UAAU,OAAO;AAC3B;;AAIF,OAAK,MAAM,eAAe,KAAK,GAAG,UAAU;EAE5C,MAAM,WAAW,MAAM,mBAAmB,SAAS,EAAE,SAAS,CAAC;AAE/D,MAAI,CAAC,UAAU;AACb,QAAK,KAAK,sBAAsB,OAAO;AACvC;;EAGF,MAAM,aAAuD,EAAE;EAC/D,MAAM,cAAqF,EAAE;EAC7F,MAAM,kBAAkB,SAAiB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS;AAGvF,MAAI,SAAS,cAAc,SAAS,SAAS;GAC3C,MAAM,KAAK,eAAe,SAAS,QAAQ;AAC3C,OAAI,IAAI;IACN,MAAM,UAAU,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,SAAS,QAAQ;AACvE,QAAI,SAAS,MAAM,QAAQ;KACzB,MAAM,aAAa;AACnB,UAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,MAAM,QAAQ,KAAK,YAAY;MACzD,MAAM,QAAQ,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;MACpD,MAAM,UAAU,MAAM,QAAQ,IAC5B,MAAM,IAAI,OAAO,SAAS;OAExB,MAAM,UAAU,MAAM,OADV,GAAG,QAAQ,QAAQ,GAAG,QACA,EAAE,cAAc,QAAQ,CAAC,CAAC,YAAY,KAAK;AAC7E,WAAI,CAAC,QACH,QAAO;AACT,cAAO;QAAE;QAAM;QAAS;QACxB,CACH;AACD,WAAK,MAAM,KAAK,QACd,KAAI,GAAG;OACL,MAAM,YAAY,QAAQ,aAAa,EAAE,KAAK,QAAQ,QAAQ,YAAY,GAAG,GAAG,EAAE;AAClF,kBAAW,KAAK;QAAE,MAAM;QAAW,SAAS,EAAE;QAAS,CAAC;AACxD,mBAAY,KAAK;QAAE,IAAI;QAAW,SAAS,EAAE;QAAS,UAAU;SAAE,SAAS;SAAS,QAAQ;SAAW,MAAM;;QAAS,CAAC;;;AAM7H,SAAI,iBAAiB,WAAW,OAAO,IAAI,SAAS,SAAS;AAC3D,iBAAW,SAAS;AACpB,kBAAY,SAAS;gBAEd,WAAW,SAAS,KAAK,SAAS,SAAS;MAElD,MAAM,cAAc,MAAM,aAAa,SAAS,QAAQ;AACxD,UAAI,aAAa;OACf,MAAM,UAAU,SAAS,WAAW,IAAI,IAAI,SAAS,QAAQ,CAAC;AAC9D,kBAAW,KAAK;QAAE,MAAM;QAAY,SAAS,mBAAmB,YAAY,IAAA;QAAM,CAAC;AACnF,WAAI,YAAY,MAAM,SAAS,GAAG;QAChC,MAAM,OAAO,MAAM,iBAAiB,aAAa,QAAQ;AACzD,aAAK,MAAM,OAAO,MAAM;AACtB,aAAI,CAAC,eAAe,IAAI,IAAI,CAC1B;SACF,MAAM,YAAY,IAAI,IAAI,WAAW,IAAI,GAAG,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI;AACnE,oBAAW,KAAK;UAAE,MAAM,KAAK,aAAa,GAAG,UAAU,MAAM,IAAI,CAAC;UAAE,SAAS,IAAI;UAAS,CAAC;;;;;;;;AAUzG,MAAI,SAAS,WAAW,WAAW,WAAW,GAAG;GAC/C,MAAM,cAAc,MAAM,aAAa,SAAS,QAAQ;AACxD,OAAI,aAAa;AACf,eAAW,KAAK;KAAE,MAAM;KAAY,SAAS,mBAAmB,YAAY,IAAA;KAAM,CAAC;AACnF,QAAI,YAAY,MAAM,SAAS,GAAG;KAEhC,MAAM,OAAO,MAAM,iBAAiB,aADpB,SAAS,WAAW,IAAI,IAAI,SAAS,QAAQ,CAAC,OACL;AACzD,UAAK,MAAM,OAAO,MAAM;AACtB,UAAI,CAAC,eAAe,IAAI,IAAI,CAC1B;MAEF,MAAM,YAAY,KAAK,QAAQ,IADb,IAAI,IAAI,WAAW,IAAI,GAAG,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI,KACvB,MAAM,IAAI,CAAC;AACvD,iBAAW,KAAK;OAAE,MAAM;OAAW,SAAS,IAAI;OAAS,CAAC;AAC1D,kBAAY,KAAK;OAAE,IAAI,IAAI;OAAK,SAAS,IAAI;OAAS,UAAU;QAAE,SAAS;QAAS,QAAQ;QAAW,MAAM;;OAAS,CAAC;;;;;AAO/H,MAAI,SAAS,aAAa,WAAW,WAAW,GAAG;GACjD,MAAM,UAAU,MAAM,mBAAmB,SAAS,UAAU;AAC5D,OAAI,SAAS;AACX,eAAW,KAAK;KAAE,MAAM;KAAkB;KAAS,CAAC;AACpD,gBAAY,KAAK;KAAE,IAAI;KAAa;KAAS,UAAU;MAAE,SAAS;MAAS,QAAQ;MAAkB,MAAM;;KAAS,CAAC;;;AAIzH,MAAI,WAAW,SAAS,GAAG;AACzB,gBAAa,SAAS,SAAS,WAAW;AAE1C,aAAU,gBAAgB,EAAE,WAAW,MAAM,CAAC;AAC9C,kBAAe,gBAAgB,SAAS,KAAK,QAAQ;AAErD,QAAK,MAAM,OAAO,cAAc,KAAK,SAAS,CAC5C,cAAa,UAAU,IAAI,MAAM,KAAK,IAAI,QAAQ;AAEpD,OAAI,CAAC,aAAa,gBAAgB,EAAE;IAClC,MAAM,WAAW,KAAK,gBAAgB,OAAO;IAC7C,MAAM,gBAAgB,KAAK,iBAAiB,OAAO;AACnD,QAAI,WAAW,SAAS,CACtB,YAAW,SAAS;AACtB,QAAI,WAAW,cAAc,CAC3B,aAAY,eAAe,UAAU,WAAW;;AAGpD,OAAI,SAAS,QAAQ;AACnB,QAAI,YAAY,SAAS,EACvB,OAAM,YAAY,aAAa,EAAE,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,CAAC;IAIhF,MAAM,SAAS,cAAc,SAAS,KAAK,QAAQ;IACnD,MAAM,aAAa,SAAS,MAAM,kBAAkB,OAAO,GAAG,EAAE;AAChE,QAAI,WAAW,SAAS,EACtB,OAAM,YAAY,WAAW,KAAI,OAAM;KACrC,IAAI,EAAE;KACN,SAAS,EAAE;KACX,UAAU;MAAE,SAAS;MAAS,QAAQ,OAAO,EAAE;MAAQ,MAAM,EAAE;;KAChE,EAAE,EAAE,EAAE,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,CAAC;;AAIxD,OAAI,CAAC,sBAAsB,UAAU,MAAM,cAAc;QACnD,sBAAsB,UAAU,SAAS,SAAS,KAAK,eAAe,KAAK,QAAQ,KAAK,SAAS,CACnG,aAAY,KAAK;KAAE;KAAM;KAAS;KAAS;KAAU,UAAU,KAAK;KAAU,CAAC;;AAEnF,QAAK,KAAK,yBAAyB,OAAO;QAG1C,MAAK,KAAK,qBAAqB,OAAO;;AAK1C,KAAI,YAAY,SAAS,KAAK,CAAC,YAAY,CAAC,SAAS;EAEnD,MAAM,YAAY,MAAM,gBAAgB,KAAA,GAAW,wBADrC,YAAY,KAAI,MAAK,EAAE,KAAK,CAAC,KAAK,KAAK,GAC8B;AACnF,MAAI,WAAW;AACb,KAAE,IAAI,KAAK,cAAc,UAAU,MAAM,CAAC;AAC1C,QAAK,MAAM,EAAE,SAAS,SAAS,UAAU,UAAU,iBAAiB,YAClE,OAAM,mBAAmB,SAAS,SAAS,UAAU,UAAU,OAAO,UAAU,UAAU,UAAU,cAAc,YAAY;;;AAMpI,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,OAAO,CACpD,WAAU,WAAW,MAAM,KAAK;AAGlC,KAAI,OACF,MAAK,MAAM,CAAC,SAAS,OACnB,mBAAkB,MAAM,QAAQ,IAAI;KAGtC,qBAAoB,MAAM,cAAc,QAAO,MAAK,MAAM,UAAU,CAAC;AAGvE,OAAM,gBAAgB;AAEtB,GAAE,MAAM,mBAAmB;;;AAI7B,SAAS,sBAAsB,UAAkB,MAAc,eAAkC;CAC/F,MAAM,WAAW,KAAK,UAAU,WAAW;AAC3C,KAAI,WAAW,SAAS,CACtB,QAAO;AACT,MAAK,MAAM,OAAO,eAAe;AAC/B,MAAI,QAAQ,SACV;EACF,MAAM,cAAc,KAAK,KAAK,MAAM,WAAW;AAC/C,MAAI,WAAW,YAAY,IAAI,CAAC,UAAU,YAAY,CAAC,gBAAgB,EAAE;AACvE,aAAU,UAAU,EAAE,WAAW,MAAM,CAAC;AACxC,gBAAa,aAAa,SAAS;AACnC,UAAO;;;AAGX,QAAO;;;AAIT,SAAS,eAAe,WAAmB,QAAyB;AAClE,KAAI,QAAQ,SAAS,UAAU,EAAE;EAC/B,MAAM,QAAQ,OAAO,MAAM,yBAAyB;AACpD,MAAI,MACF,QAAO,IAAI,MAAM,GAAG,GAAG,MAAM;;AAGjC,KAAI,UAAU,WAAW,SAAS,CAChC,QAAO,UAAU,UAAU,MAAM,EAAE;AACrC,KAAI,UAAU,WAAW,SAAS,CAChC,QAAO,UAAU,UAAU,MAAM,EAAE;AACrC,KAAI,UAAU,WAAW,QAAQ,CAC/B,QAAO,SAAS,UAAU,MAAM,EAAE;AACpC,KAAI,UAAU,WAAW,OAAO,CAC9B,QAAO,QAAQ,UAAU,MAAM,EAAE;AACnC,KAAI,UAAU,WAAW,UAAU,CACjC,QAAO,WAAW,UAAU,MAAM,EAAE;AAEtC,QAAO;;;AAIT,SAAS,eAAe,eAAuB,MAAc,KAAa,SAAwB;CAChG,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;AACjD,KAAI,CAAC,QACH;CAEF,MAAM,UAAU,KAAK,eAAe,MAAM;AAC1C,KAAI,WAAW,QAAQ,CACrB,YAAW,QAAQ;AACrB,aAAY,SAAS,SAAS,WAAW;;;AAI3C,SAAS,aAAa,UAA2B;CAC/C,MAAM,UAAU,KAAK,UAAU,OAAO;AACtC,KAAI,CAAC,WAAW,QAAQ,CACtB,QAAO;CACT,MAAM,QAAQ,YAAY,QAAQ;AAClC,QAAO,MAAM,WAAW,KAAK,MAAM,OAAO;;;AAI5C,SAAS,kBAAkB,MAAc,KAAa,SAA2B;CAC/E,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;AACjD,KAAI,CAAC,QACH,QAAO;AAGT,MAAK,MAAM,aADY;EAAC;EAAQ;EAAiB;EAAM,CAGrD,KAAI,WADa,KAAK,SAAS,UAAU,CACjB,CACtB,QAAO;AAEX,QAAO;;;AAIT,eAAe,mBACb,SACA,SACA,UACA,OACA,UACA,cACA,UACe;CACf,MAAM,SAAS,EAAE,QAAQ,EAAE,OAAO,mBAAmB,WAAW,CAAC;CAEjE,MAAM,WAAW,mBAAmB,SAAS;CAC7C,MAAM,kBAAkB,YAAY,SAAS,QAAQ;CACrD,MAAM,YAAY,WAAW,KAAK,iBAAiB,SAAS,CAAC;CAC7D,MAAM,iBAAiB,WAAW,KAAK,iBAAiB,cAAc,CAAC;CACvE,MAAM,YAAY,aAAa;CAC/B,MAAM,cAAc,WAAW,KAAK,iBAAiB,WAAW,CAAC;CAEjE,MAAM,WAAW,YAAY,CAAC,YAAY;CAC1C,MAAM,EAAE,WAAW,iBAAiB,MAAM,aAAa;EACrD,aAAa;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,eAAe,SAAS,QAAQ,KAAK,EAAE,QAAQ;EACzD,YAAY,mBAAmB,OAAA;EAChC,CAAC;AAEF,KAAI,cAAc;AAChB,SAAO,QAAQ,2BAA2B;EAE1C,MAAM,MAAM,QAAQ,KAAK;EACzB,MAAM,UAAU,cAAc,SAAS,KAAK,QAAQ;EACpD,IAAI;EACJ,IAAI;AACJ,MAAI,SAAS;GACX,MAAM,cAAc,KAAK,SAAS,eAAe;AACjD,OAAI,WAAW,YAAY,EAAE;IAC3B,MAAM,MAAM,KAAK,MAAM,aAAa,aAAa,QAAQ,CAAC;AAC1D,kBAAc,IAAI;AAClB,mBAAe,IAAI;;;EAIvB,IAAI,WAA2C;AAC/C,MAAI,WAAW,KAAK,iBAAiB,QAAQ,WAAW,CAAC,CACvD,YAAW;WACJ,aAAa,gBAAgB,CACpC,YAAW;EAGb,MAAM,UAAU,SAAS,MAAM,IAAI,CAAC,KAAK;EAEzC,MAAM,cAAc,cAAc,SAAS,CAAC,KAAI,OAAM,EAAE,MAAM,EAAE,MAAM,EAAE;EACxE,MAAM,UAAU,gBAAgB;GAC9B,MAAM;GACN;GACA;GACA;GACA,MAAM;GACN,eAAe,EAAE;GACjB;GACA;GACA;GACA;GACA,gBAAgBC,eAAiB,SAAS,KAAK,QAAQ;GACvD,UAAU,eAAe,SAAS,KAAK,QAAQ;GAC/C;GACA,UAAU,YAAY,SAAS,IAAI,cAAc,KAAA;GACjD;GACD,CAAC;AACF,gBAAc,KAAK,UAAU,WAAW,EAAE,QAAQ;OAGlD,QAAO,MAAM,2BAA2B;;AAI5C,MAAa,oBAAoB,cAAc;CAC7C,MAAM;EAAE,MAAM;EAAW,aAAa;EAAoC;CAC1E,MAAM;EACJ,QAAQ,WAAW;EACnB,OAAO,WAAW;EACnB;CACD,MAAM,IAAI,EAAE,QAAQ;EAClB,IAAI,QAAQ,aAAa,KAAK,MAAM;AACpC,MAAI,CAAC,OAAO;AACV,WAAQ,MAAM,gBAAgB;AAC9B,OAAI,CAAC,MACH;;AAGJ,IAAE,MAAM,uCAAuC;AAC/C,SAAO,eAAe;GAAE,QAAQ,KAAK;GAAQ;GAAO,CAAC;;CAExD,CAAC;;AAGF,SAAS,sBACP,UACA,SACA,SACA,KACA,eACA,QACA,UACS;CACT,MAAM,cAAc,KAAK,UAAU,WAAW;AAC9C,KAAI,WAAW,YAAY,CACzB,QAAO;CAGT,MAAM,UAAU,cAAc,SAAS,KAAK,QAAQ;CACpD,IAAI;CACJ,IAAI;AACJ,KAAI,SAAS;EACX,MAAM,cAAc,KAAK,SAAS,eAAe;AACjD,MAAI,WAAW,YAAY,EAAE;GAC3B,MAAM,MAAM,KAAK,MAAM,aAAa,aAAa,QAAQ,CAAC;AAC1D,iBAAc,IAAI;AAClB,kBAAe,IAAI;;;CAKvB,MAAM,kBAAkB,YAAY,SAAS,QAAQ;CACrD,IAAI,WAA2C;AAC/C,KAAI,QAAQ,SAAS,WAAW,IAAI,WAAW,KAAK,iBAAiB,QAAQ,WAAW,CAAC,CACvF,YAAW;UACJ,aAAa,gBAAgB,CACpC,YAAW;CAGb,MAAM,OAAO,YAAY,CAAC,YAAY;CACtC,MAAM,YAAY,KAAK,UAAU,WAAW,KAAK,iBAAiB,SAAS,CAAC;CAC5E,MAAM,iBAAiB,KAAK,eAAe,WAAW,KAAK,iBAAiB,cAAc,CAAC;CAC3F,MAAM,cAAc,KAAK,YAAY,WAAW,KAAK,iBAAiB,WAAW,CAAC;CAGlF,MAAM,gBAAgB,cAAc,QAAO,MAAK,MAAM,QAAQ;CAG9D,MAAM,UAAU,SAAS,MAAM,IAAI,CAAC,KAAK;CAGzC,MAAM,cAAc,cAAc,SAAS,CAAC,KAAI,OAAM,EAAE,MAAM,EAAE,MAAM,EAAE;CAExE,MAAM,UAAU,gBAAgB;EAC9B,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,gBAAgBA,eAAiB,SAAS,KAAK,QAAQ;EACvD,UAAU,eAAe,SAAS,KAAK,QAAQ;EAC/C;EACA,UAAU,YAAY,SAAS,IAAI,cAAc,KAAA;EACjD,UAAU,YAAY,CAAC,YAAY;EACpC,CAAC;AAEF,WAAU,UAAU,EAAE,WAAW,MAAM,CAAC;AACxC,eAAc,aAAa,QAAQ;AACnC,QAAO;;;AAIT,SAAS,mBAAmB,gBAAwB,SAAiB,SAAiB,UAAmC;AAEvH,MAAK,MAAM,SAAS,YAAY,eAAe,EAAE;EAC/C,MAAM,YAAY,KAAK,gBAAgB,MAAM;AAC7C,MAAI,UAAU,UAAU,CAAC,gBAAgB,IAAI,CAAC,WAAW,UAAU,CACjE,QAAO;;AAIX,KAAI,CAAC,WAAW,KAAK,gBAAgB,MAAM,CAAC,CAC1C,QAAO;CAGT,MAAM,kBAAkB,YAAY,SAAS,QAAQ;CACrD,MAAM,WAAqC;EACzC,CAAC,QAAQ,WAAW,KAAK,iBAAiB,OAAO,CAAC,CAAC;EACnD,CAAC,UAAU,SAAS,UAAU,WAAW,KAAK,iBAAiB,SAAS,CAAC,CAAC;EAC1E,CAAC,eAAe,SAAS,eAAe,WAAW,KAAK,iBAAiB,cAAc,CAAC,CAAC;EACzF,CAAC,YAAY,SAAS,YAAY,WAAW,KAAK,iBAAiB,WAAW,CAAC,CAAC;EAChF,CAAC,YAAY,WAAW,KAAK,iBAAiB,WAAW,CAAC,CAAA;EAC3D;AAED,MAAK,MAAM,CAAC,MAAM,gBAAgB,SAChC,KAAI,eAAe,CAAC,WAAW,KAAK,gBAAgB,KAAK,CAAC,CACxD,QAAO;AAGX,QAAO"}