skilld 1.7.3 → 1.7.4

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 (96) hide show
  1. package/dist/_chunks/agent.mjs +693 -599
  2. package/dist/_chunks/agent.mjs.map +1 -1
  3. package/dist/_chunks/assemble.mjs +3 -3
  4. package/dist/_chunks/author.mjs +51 -121
  5. package/dist/_chunks/author.mjs.map +1 -1
  6. package/dist/_chunks/cache.mjs +315 -9
  7. package/dist/_chunks/cache.mjs.map +1 -1
  8. package/dist/_chunks/cache2.mjs +2 -2
  9. package/dist/_chunks/cli-helpers.mjs +3 -3
  10. package/dist/_chunks/core.mjs +7 -4
  11. package/dist/_chunks/detect.mjs +1 -1
  12. package/dist/_chunks/embedding-cache2.mjs +2 -2
  13. package/dist/_chunks/index.d.mts +305 -112
  14. package/dist/_chunks/index.d.mts.map +1 -1
  15. package/dist/_chunks/index2.d.mts +267 -32
  16. package/dist/_chunks/index2.d.mts.map +1 -1
  17. package/dist/_chunks/index3.d.mts +32 -577
  18. package/dist/_chunks/index3.d.mts.map +1 -1
  19. package/dist/_chunks/index4.d.mts +553 -0
  20. package/dist/_chunks/index4.d.mts.map +1 -0
  21. package/dist/_chunks/install.mjs +48 -88
  22. package/dist/_chunks/install.mjs.map +1 -1
  23. package/dist/_chunks/list.mjs +1 -1
  24. package/dist/_chunks/lockfile.mjs +29 -6
  25. package/dist/_chunks/lockfile.mjs.map +1 -1
  26. package/dist/_chunks/monorepo.mjs +71 -0
  27. package/dist/_chunks/monorepo.mjs.map +1 -0
  28. package/dist/_chunks/{shared.mjs → package-registry.mjs} +2 -40
  29. package/dist/_chunks/package-registry.mjs.map +1 -0
  30. package/dist/_chunks/paths.mjs +49 -0
  31. package/dist/_chunks/paths.mjs.map +1 -0
  32. package/dist/_chunks/pool2.mjs +1 -1
  33. package/dist/_chunks/prepare.mjs +1 -1
  34. package/dist/_chunks/prepare2.mjs +5 -5
  35. package/dist/_chunks/prepare2.mjs.map +1 -1
  36. package/dist/_chunks/prompts.mjs +366 -18
  37. package/dist/_chunks/prompts.mjs.map +1 -1
  38. package/dist/_chunks/search-helpers.mjs +5 -6
  39. package/dist/_chunks/search-helpers.mjs.map +1 -1
  40. package/dist/_chunks/search-interactive.mjs +1 -1
  41. package/dist/_chunks/search.mjs +1 -2
  42. package/dist/_chunks/search.mjs.map +1 -1
  43. package/dist/_chunks/semver.mjs +13 -0
  44. package/dist/_chunks/semver.mjs.map +1 -0
  45. package/dist/_chunks/skill-installer.mjs +2 -0
  46. package/dist/_chunks/skill-installer2.mjs +155 -0
  47. package/dist/_chunks/skill-installer2.mjs.map +1 -0
  48. package/dist/_chunks/skills.mjs +10 -9
  49. package/dist/_chunks/skills.mjs.map +1 -1
  50. package/dist/_chunks/sources.mjs +549 -372
  51. package/dist/_chunks/sources.mjs.map +1 -1
  52. package/dist/_chunks/sync-pipeline.mjs +952 -0
  53. package/dist/_chunks/sync-pipeline.mjs.map +1 -0
  54. package/dist/_chunks/sync-registry.mjs +19 -13
  55. package/dist/_chunks/sync-registry.mjs.map +1 -1
  56. package/dist/_chunks/sync.mjs +797 -886
  57. package/dist/_chunks/sync.mjs.map +1 -1
  58. package/dist/_chunks/sync2.mjs +4 -2
  59. package/dist/_chunks/types.d.mts +65 -77
  60. package/dist/_chunks/types.d.mts.map +1 -1
  61. package/dist/_chunks/types2.d.mts +88 -0
  62. package/dist/_chunks/types2.d.mts.map +1 -0
  63. package/dist/_chunks/uninstall.mjs +7 -8
  64. package/dist/_chunks/uninstall.mjs.map +1 -1
  65. package/dist/_chunks/upload.mjs +2 -2
  66. package/dist/_chunks/validate.mjs +1 -1
  67. package/dist/_chunks/version.mjs +3 -13
  68. package/dist/_chunks/version.mjs.map +1 -1
  69. package/dist/_chunks/wizard.mjs +2 -2
  70. package/dist/agent/index.d.mts +2 -346
  71. package/dist/agent/index.mjs +2 -3
  72. package/dist/cache/index.d.mts +2 -2
  73. package/dist/cache/index.mjs +4 -3
  74. package/dist/cli.mjs +12 -13
  75. package/dist/cli.mjs.map +1 -1
  76. package/dist/index.d.mts +5 -4
  77. package/dist/index.mjs +4 -3
  78. package/dist/prepare.mjs +2 -2
  79. package/dist/prepare.mjs.map +1 -1
  80. package/dist/retriv/index.d.mts +2 -2
  81. package/dist/retriv/worker.d.mts +1 -1
  82. package/dist/sources/index.d.mts +3 -2
  83. package/dist/sources/index.mjs +3 -3
  84. package/dist/types.d.mts +3 -3
  85. package/package.json +2 -2
  86. package/dist/_chunks/config.mjs +0 -122
  87. package/dist/_chunks/config.mjs.map +0 -1
  88. package/dist/_chunks/prefix.mjs +0 -108
  89. package/dist/_chunks/prefix.mjs.map +0 -1
  90. package/dist/_chunks/shared.mjs.map +0 -1
  91. package/dist/_chunks/skill.mjs +0 -329
  92. package/dist/_chunks/skill.mjs.map +0 -1
  93. package/dist/_chunks/sync-shared.mjs +0 -2
  94. package/dist/_chunks/sync-shared2.mjs +0 -1020
  95. package/dist/_chunks/sync-shared2.mjs.map +0 -1
  96. package/dist/agent/index.d.mts.map +0 -1
@@ -1,24 +1,22 @@
1
- import { a as getModelLabel, r as createToolProgress, s as optimizeDocs } from "./agent.mjs";
2
- import { c as getRepoCacheDir, s as getPackageDbPath, t as getCacheDir } from "./version.mjs";
1
+ import { d as getSharedSkillsDir, l as getPackageDbPath, p as skillInternalDir } from "./paths.mjs";
2
+ import { P as readConfig, a as getPkgKeyFiles, h as listReferenceFiles, i as ensureCacheDir, k as defaultFeatures, o as hasShippedDocs, s as inferDocsTypeFromCache, t as createReferenceCache, x as classifyCachedDoc } from "./cache.mjs";
3
3
  import { i as readPackageJsonSafe } from "./package-json.mjs";
4
+ import { t as getCacheDir } from "./version.mjs";
4
5
  import { n as linkShippedSkill, r as resolvePkgDir, t as getShippedSkills } from "./prepare.mjs";
5
6
  import { n as sanitizeMarkdown } from "./sanitize.mjs";
6
- import { a as hasShippedDocs, c as isReadmeOnlyCache, d as linkPkgNamed, h as readCachedDocs, i as getPkgKeyFiles, m as listReferenceFiles, o as inferDocsTypeFromCache, r as ensureCacheDir, s as isCached, v as writeToCache } from "./cache.mjs";
7
7
  import { r as createIndex, t as SearchDepsUnavailableError } from "./retriv.mjs";
8
- import { n as getSharedSkillsDir } from "./shared.mjs";
9
- import { A as filterFrameworkDocs, E as fetchGitDocs, I as fetchLlmsTxt, P as downloadLlmsDocs, Q as fetchGitHubRaw, R as normalizeLlmsLinks, _ as resolveEntryFiles, d as resolvePackageDocs, j as isShallowGitDocs, k as fetchReadmeContent, m as fetchGitSkills, rt as parseGitHubUrl } from "./sources.mjs";
8
+ import { C as resolveEntryFiles, F as downloadLlmsDocs, J as isShallowGitDocs, K as fetchGitDocs, L as fetchLlmsTxt, N as fetchReadmeContent, a as toStoragePackageName, at as fetchGitHubRaw, b as fetchGitSkills, g as resolvePackageDocs, q as filterFrameworkDocs, ut as parseGitHubUrl, z as normalizeLlmsLinks } from "./sources.mjs";
10
9
  import { a as targets } from "./detect.mjs";
11
- import { _ as timedSpinner, n as writeGeneratedSkillMd, o as linkSkillToAgents, r as writeSkillMd } from "./skill.mjs";
12
- import { a as readConfig, t as defaultFeatures } from "./config.mjs";
10
+ import { i as getModelLabel, o as createToolProgress, t as optimizeDocs } from "./agent.mjs";
11
+ import { _ as timedSpinner, n as writeGeneratedSkillMd, o as linkSkillToAgents, r as writeSkillMd } from "./prompts.mjs";
13
12
  import { _ as promptForAgent, b as resolveAgent, x as sharedArgs } from "./cli-helpers.mjs";
14
- import { a as readLock, c as writeLock, n as parsePackageNames, r as parsePackages, s as syncLockfilesToDirs, t as mergeLocks } from "./lockfile.mjs";
15
- import { r as toStoragePackageName } from "./prefix.mjs";
16
- import { S as writePromptFiles, a as classifyCachedDoc, b as selectLlmConfig, g as indexResources } from "./sync-shared2.mjs";
13
+ import { a as parsePackageNames, c as readLock, d as writeLock, i as mergeLocks, o as parsePackages, u as syncLockfilesToDirs } from "./lockfile.mjs";
14
+ import { h as writePromptFiles, l as selectLlmConfig, o as indexResources } from "./sync-pipeline.mjs";
17
15
  import { n as shutdownWorker } from "./pool2.mjs";
18
16
  import "./sync.mjs";
17
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
19
18
  import { homedir } from "node:os";
20
19
  import { dirname, join } from "pathe";
21
- import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
22
20
  import * as p from "@clack/prompts";
23
21
  import { defineCommand } from "citty";
24
22
  async function installCommand(opts) {
@@ -46,7 +44,7 @@ async function installCommand(opts) {
46
44
  continue;
47
45
  }
48
46
  const skillDir = join(skillsDir, name);
49
- const referencesPath = join(skillDir, ".skilld");
47
+ const referencesPath = skillInternalDir(skillDir);
50
48
  const skillMdPath = join(skillDir, "SKILL.md");
51
49
  if (!existsSync(skillDir) || !existsSync(skillMdPath) || !existsSync(referencesPath) || hasStaleReferences(referencesPath, toStoragePackageName(info.packageName || name), info.version, features)) toRestore.push({
52
50
  name,
@@ -97,55 +95,28 @@ async function installCommand(opts) {
97
95
  continue;
98
96
  }
99
97
  const skillDir = join(skillsDir, name);
100
- const referencesPath = join(skillDir, ".skilld");
101
- const globalCachePath = getCacheDir(pkgName, version);
98
+ const cache = createReferenceCache(pkgName, version);
102
99
  const spin = timedSpinner();
103
- if (isCached(pkgName, version)) {
100
+ if (cache.has()) {
104
101
  spin.start(`Linking ${name}`);
105
102
  mkdirSync(skillDir, { recursive: true });
106
- mkdirSync(referencesPath, { recursive: true });
107
- linkPkgSymlink(referencesPath, pkgName, cwd, version);
108
- for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
109
- if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnlyCache(globalCachePath)) {
110
- const docsLink = join(referencesPath, "docs");
111
- const cachedDocs = join(globalCachePath, "docs");
112
- if (existsSync(docsLink)) unlinkSync(docsLink);
113
- if (existsSync(cachedDocs)) symlinkSync(cachedDocs, docsLink, "junction");
114
- }
115
103
  const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null;
116
- const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null;
117
- if (features.issues) {
118
- const issuesLink = join(referencesPath, "issues");
119
- const repoIssues = repoCachePath ? join(repoCachePath, "issues") : null;
120
- const cachedIssues = repoIssues && existsSync(repoIssues) ? repoIssues : join(globalCachePath, "issues");
121
- if (existsSync(issuesLink)) unlinkSync(issuesLink);
122
- if (existsSync(cachedIssues)) symlinkSync(cachedIssues, issuesLink, "junction");
123
- }
124
- if (features.discussions) {
125
- const discussionsLink = join(referencesPath, "discussions");
126
- const repoDiscussions = repoCachePath ? join(repoCachePath, "discussions") : null;
127
- const cachedDiscussions = repoDiscussions && existsSync(repoDiscussions) ? repoDiscussions : join(globalCachePath, "discussions");
128
- if (existsSync(discussionsLink)) unlinkSync(discussionsLink);
129
- if (existsSync(cachedDiscussions)) symlinkSync(cachedDiscussions, discussionsLink, "junction");
130
- }
131
- if (features.releases) {
132
- const releasesLink = join(referencesPath, "releases");
133
- const repoReleases = repoCachePath ? join(repoCachePath, "releases") : null;
134
- const cachedReleases = repoReleases && existsSync(repoReleases) ? repoReleases : join(globalCachePath, "releases");
135
- if (existsSync(releasesLink)) unlinkSync(releasesLink);
136
- if (existsSync(cachedReleases)) symlinkSync(cachedReleases, releasesLink, "junction");
137
- }
138
- const sectionsLink = join(referencesPath, "sections");
139
- const cachedSections = join(globalCachePath, "sections");
140
- if (existsSync(sectionsLink)) unlinkSync(sectionsLink);
141
- if (existsSync(cachedSections)) symlinkSync(cachedSections, sectionsLink, "junction");
104
+ const docsType = inferDocsTypeFromCache(cache.dir, info.source);
105
+ cache.linkInto(skillDir, cwd, docsType, {
106
+ extraPackages: parsePackages(info.packages),
107
+ features,
108
+ repoInfo: repoGh ? {
109
+ owner: repoGh.owner,
110
+ repo: repoGh.repo
111
+ } : void 0
112
+ });
142
113
  if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {
143
114
  spin.message(`Indexing ${name}`);
144
115
  await indexResources({
145
116
  packageName: pkgName,
146
117
  version,
147
118
  cwd,
148
- docsToIndex: readCachedDocs(pkgName, version).map((d) => ({
119
+ docsToIndex: cache.readDocs().map((d) => ({
149
120
  id: d.path,
150
121
  content: d.content,
151
122
  metadata: {
@@ -288,16 +259,17 @@ async function installCommand(opts) {
288
259
  }
289
260
  }
290
261
  if (cachedDocs.length > 0) {
291
- writeToCache(pkgName, version, cachedDocs);
292
- mkdirSync(referencesPath, { recursive: true });
293
- linkPkgSymlink(referencesPath, pkgName, cwd, version);
294
- for (const pkg of parsePackages(info.packages)) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
295
- if (!isReadmeOnlyCache(globalCachePath)) {
296
- const docsLink = join(referencesPath, "docs");
297
- const cachedDocsDir = join(globalCachePath, "docs");
298
- if (existsSync(docsLink)) unlinkSync(docsLink);
299
- if (existsSync(cachedDocsDir)) symlinkSync(cachedDocsDir, docsLink, "junction");
300
- }
262
+ cache.write(cachedDocs);
263
+ const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null;
264
+ const docsType = inferDocsTypeFromCache(cache.dir, info.source);
265
+ cache.linkInto(skillDir, cwd, docsType, {
266
+ extraPackages: parsePackages(info.packages),
267
+ features,
268
+ repoInfo: repoGh ? {
269
+ owner: repoGh.owner,
270
+ repo: repoGh.repo
271
+ } : void 0
272
+ });
301
273
  if (features.search) try {
302
274
  if (docsToIndex.length > 0) await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) });
303
275
  const pkgDir = resolvePkgDir(pkgName, cwd, version);
@@ -334,18 +306,23 @@ async function installCommand(opts) {
334
306
  const globalCachePath = getCacheDir(pkgName, version);
335
307
  writePromptFiles({
336
308
  packageName: pkgName,
337
- skillDir,
338
309
  version,
339
- hasIssues: existsSync(join(globalCachePath, "issues")),
340
- hasDiscussions: existsSync(join(globalCachePath, "discussions")),
341
- hasReleases: existsSync(join(globalCachePath, "releases")),
342
- hasChangelog: false,
343
- docsType: "docs",
344
- hasShippedDocs: false,
345
- pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
346
- sections: llmConfig.sections,
347
- customPrompt: llmConfig.customPrompt,
310
+ skillDir,
311
+ references: {
312
+ docsType: "docs",
313
+ hasShippedDocs: false,
314
+ pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
315
+ hasIssues: existsSync(join(globalCachePath, "issues")),
316
+ hasDiscussions: existsSync(join(globalCachePath, "discussions")),
317
+ hasReleases: existsSync(join(globalCachePath, "releases")),
318
+ hasChangelog: false
319
+ },
320
+ resolved: {},
321
+ relatedSkills: [],
348
322
  features
323
+ }, {
324
+ sections: llmConfig.sections,
325
+ customPrompt: llmConfig.customPrompt
349
326
  });
350
327
  }
351
328
  } else if (llmConfig) {
@@ -385,23 +362,6 @@ function unsanitizeName(sanitized, source) {
385
362
  if (sanitized.startsWith("vueuse-")) return `@vueuse/${sanitized.slice(7)}`;
386
363
  return sanitized;
387
364
  }
388
- function linkPkgSymlink(referencesDir, name, cwd, version) {
389
- const pkgPath = resolvePkgDir(name, cwd, version);
390
- if (!pkgPath) return;
391
- const pkgLink = join(referencesDir, "pkg");
392
- if (existsSync(pkgLink)) unlinkSync(pkgLink);
393
- symlinkSync(pkgPath, pkgLink, "junction");
394
- }
395
- function pkgHasShippedDocs(name, cwd, version) {
396
- const pkgPath = resolvePkgDir(name, cwd, version);
397
- if (!pkgPath) return false;
398
- for (const candidate of [
399
- "docs",
400
- "documentation",
401
- "doc"
402
- ]) if (existsSync(join(pkgPath, candidate))) return true;
403
- return false;
404
- }
405
365
  async function enhanceRegenerated(pkgName, version, skillDir, model, sections, customPrompt, packages) {
406
366
  const llmLog = p.taskLog({
407
367
  title: `Agent exploring ${pkgName}`,
@@ -1 +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, 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 { writeGeneratedSkillMd, writeSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n inferDocsTypeFromCache,\n isCached,\n isReadmeOnlyCache,\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, parsePackageNames, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { readPackageJsonSafe } from '../core/package-json.ts'\nimport { toStoragePackageName } from '../core/prefix.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n downloadLlmsDocs,\n fetchGitDocs,\n fetchGitHubRaw,\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, writePromptFiles } 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, toStoragePackageName(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 identityName = info.packageName || unsanitizeName(name, info.source)\n const pkgName = toStoragePackageName(identityName)\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 writeSkillMd(skillDir, 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) && !isReadmeOnlyCache(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 fetchGitHubRaw(url)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n const cachePath = stripped.startsWith('docs/') ? stripped : `docs/${stripped}`\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 (!isReadmeOnlyCache(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 try {\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 catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\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?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n skillDir,\n version,\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n }\n else 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, opts.agent)\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 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}`, limit: 3 })\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 if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n const pkgJsonResult = readPackageJsonSafe(pkgJsonPath)\n if (pkgJsonResult) {\n description = pkgJsonResult.parsed.description as string | undefined\n }\n }\n\n const docsType = inferDocsTypeFromCache(globalCachePath)\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackageNames(packages)\n writeGeneratedSkillMd(skillDir, {\n name: pkgName,\n version,\n description,\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 }\n else {\n llmLog.message('Enhancement 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 || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\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 if (pkgPath) {\n const pkgResult = readPackageJsonSafe(join(pkgPath, 'package.json'))\n if (pkgResult) {\n description = pkgResult.parsed.description as string | undefined\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n const docsType = inferDocsTypeFromCache(globalCachePath, source)\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 = parsePackageNames(packages)\n\n mkdirSync(skillDir, { recursive: true })\n writeGeneratedSkillMd(skillDir, {\n name: pkgName,\n version,\n description,\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 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":";;;;;;;;;;;;;;;;;;;;;;;AAuEA,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;CAErF,IAAI,SAAS,WAAW,GAAG;EACzB,EAAE,IAAI,KAAK,gEAAgE;EAC3E;;CAGF,MAAM,OAAO,WAAW,SAAS;CAEjC,MAAM,SAAS,OAAO,QAAQ,KAAK,OAAO;CAC1C,MAAM,YAAsD,EAAE;CAC9D,MAAM,WAAW,YAAY,CAAC,YAAY;CAG1C,KAAK,MAAM,CAAC,MAAM,SAAS,QAAQ;EACjC,IAAI,CAAC,KAAK,SACR;EAGF,IAAI,KAAK,WAAW,WAAW;GAE7B,IAAI,CAAC,WADY,KAAK,WAAW,KACT,CAAC,EACvB,UAAU,KAAK;IAAE;IAAM;IAAM,CAAC;GAEhC;;EAGF,MAAM,WAAW,KAAK,WAAW,KAAK;EACtC,MAAM,iBAAiB,KAAK,UAAU,UAAU;EAChD,MAAM,cAAc,KAAK,UAAU,WAAW;EAQ9C,IALqB,CAAC,WAAW,SAAS,IACrC,CAAC,WAAW,YAAY,IACxB,CAAC,WAAW,eAAe,IAC3B,mBAAmB,gBAAgB,qBAAqB,KAAK,eAAe,KAAK,EAAE,KAAK,SAAU,SAAS,EAG9G,UAAU,KAAK;GAAE;GAAM;GAAM,CAAC;;CAIlC,IAAI,UAAU,WAAW,GAAG;EAC1B,EAAE,IAAI,QAAQ,iBAAiB;EAC/B;;CAGF,EAAE,IAAI,KAAK,aAAa,UAAU,OAAO,aAAa;CACtD,gBAAgB;CAEhB,MAAM,gBAAgB,OAAO,KAAK,GAAG,UAAU,KAAK,eAAe,GAAG,CAAC,OAAO,QAAQ;CACtF,MAAM,cAA8G,EAAE;CAEtH,KAAK,MAAM,EAAE,MAAM,UAAU,WAAW;EACtC,MAAM,UAAU,KAAK;EAErB,MAAM,UAAU,qBADK,KAAK,eAAe,eAAe,MAAM,KAAK,OAAO,CACxB;EAGlD,IAAI,KAAK,WAAW,WAAW;GAE7B,MAAM,QADU,iBAAiB,SAAS,KAAK,QAC1B,CAAC,MAAK,MAAK,EAAE,cAAc,KAAK;GACrD,IAAI,OAAO;IACT,iBAAiB,WAAW,MAAM,MAAM,SAAS;IACjD,EAAE,IAAI,QAAQ,UAAU,OAAO;UAG/B,EAAE,IAAI,KAAK,GAAG,KAAK,YAAY,QAAQ,6BAA6B;GAEtE;;EAIF,IAAI,KAAK,WAAW,YAAY,KAAK,WAAW,YAAY,KAAK,WAAW,SAAS;GASnF,MAAM,SAAQ,MADO,eAAe;IANlC,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,EAAE;IAEnB,CAAC,EACtB,OAAO,MAAK,MAAK,EAAE,SAAS,KAAK;GACtD,IAAI,OAAO;IACT,MAAM,WAAW,KAAK,WAAW,KAAK;IACtC,UAAU,UAAU,EAAE,WAAW,MAAM,CAAC;IACxC,aAAa,UAAU,iBAAiB,MAAM,QAAQ,CAAC;IACvD,KAAK,MAAM,KAAK,MAAM,OAAO;KAC3B,MAAM,WAAW,KAAK,UAAU,EAAE,KAAK;KACvC,UAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;KACjD,cAAc,UAAU,EAAE,QAAQ;;IAEpC,EAAE,IAAI,QAAQ,YAAY,KAAK,QAAQ,KAAK,OAAO;UAGnD,EAAE,IAAI,KAAK,GAAG,KAAK,uBAAuB,KAAK,OAAO;GAExD;;EAGF,MAAM,WAAW,KAAK,WAAW,KAAK;EACtC,MAAM,iBAAiB,KAAK,UAAU,UAAU;EAChD,MAAM,kBAAkB,YAAY,SAAS,QAAQ;EACrD,MAAM,OAAO,cAAc;EAG3B,IAAI,SAAS,SAAS,QAAQ,EAAE;GAC9B,KAAK,MAAM,WAAW,OAAO;GAC7B,UAAU,UAAU,EAAE,WAAW,MAAM,CAAC;GACxC,UAAU,gBAAgB,EAAE,WAAW,MAAM,CAAC;GAC9C,eAAe,gBAAgB,SAAS,KAAK,QAAQ;GAErD,KAAK,MAAM,OAAO,cAAc,KAAK,SAAS,EAC5C,aAAa,UAAU,IAAI,MAAM,KAAK,IAAI,QAAQ;GAEpD,IAAI,CAAC,kBAAkB,SAAS,KAAK,QAAQ,IAAI,CAAC,kBAAkB,gBAAgB,EAAE;IACpF,MAAM,WAAW,KAAK,gBAAgB,OAAO;IAC7C,MAAM,aAAa,KAAK,iBAAiB,OAAO;IAChD,IAAI,WAAW,SAAS,EACtB,WAAW,SAAS;IACtB,IAAI,WAAW,WAAW,EACxB,YAAY,YAAY,UAAU,WAAW;;GAGjD,MAAM,SAAS,KAAK,OAAO,eAAe,sBAAsB,KAAK,OAAO,GAAG;GAC/E,MAAM,gBAAgB,SAAS,gBAAgB,OAAO,OAAO,OAAO,KAAK,GAAG;GAC5E,IAAI,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;IAC1G,IAAI,WAAW,WAAW,EACxB,WAAW,WAAW;IACxB,IAAI,WAAW,aAAa,EAC1B,YAAY,cAAc,YAAY,WAAW;;GAErD,IAAI,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;IACnI,IAAI,WAAW,gBAAgB,EAC7B,WAAW,gBAAgB;IAC7B,IAAI,WAAW,kBAAkB,EAC/B,YAAY,mBAAmB,iBAAiB,WAAW;;GAE/D,IAAI,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;IACpH,IAAI,WAAW,aAAa,EAC1B,WAAW,aAAa;IAC1B,IAAI,WAAW,eAAe,EAC5B,YAAY,gBAAgB,cAAc,WAAW;;GAEzD,MAAM,eAAe,KAAK,gBAAgB,WAAW;GACrD,MAAM,iBAAiB,KAAK,iBAAiB,WAAW;GACxD,IAAI,WAAW,aAAa,EAC1B,WAAW,aAAa;GAC1B,IAAI,WAAW,eAAe,EAC5B,YAAY,gBAAgB,cAAc,WAAW;GAEvD,IAAI,SAAS,UAAU,CAAC,WAAW,iBAAiB,SAAS,QAAQ,CAAC,EAAE;IACtE,KAAK,QAAQ,YAAY,OAAO;IAOhC,MAAM,eAAe;KAAE,aAAa;KAAS;KAAS;KAAK,aAN5C,eAAe,SAAS,QACb,CAAC,KAAI,OAAM;MACnC,IAAI,EAAE;MACN,SAAS,EAAE;MACX,UAAU;OAAE,SAAS;OAAS,QAAQ,EAAE;OAAM,MAAM,kBAAkB,EAAE,KAAK,CAAC;OAAM;MACrF,EACqE;KAAE;KAAU,aAAY,QAAO,KAAK,QAAQ,IAAI;KAAE,CAAC;;GAE3H,IAAI,CAAC,sBAAsB,UAAU,MAAM,cAAc;QACnD,sBAAsB,UAAU,SAAS,SAAS,KAAK,eAAe,KAAK,QAAQ,KAAK,SAAS,EACnG,YAAY,KAAK;KAAE;KAAM;KAAS;KAAS;KAAU,UAAU,KAAK;KAAU,CAAC;;GAEnF,KAAK,KAAK,UAAU,OAAO;GAC3B;;EAIF,KAAK,MAAM,eAAe,KAAK,GAAG,UAAU;EAE5C,MAAM,WAAW,MAAM,mBAAmB,SAAS,EAAE,SAAS,CAAC;EAE/D,IAAI,CAAC,UAAU;GACb,KAAK,KAAK,sBAAsB,OAAO;GACvC;;EAGF,MAAM,aAAuD,EAAE;EAC/D,MAAM,cAAqF,EAAE;EAC7F,MAAM,kBAAkB,SAAiB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS;EAGvF,IAAI,SAAS,cAAc,SAAS,SAAS;GAC3C,MAAM,KAAK,eAAe,SAAS,QAAQ;GAC3C,IAAI,IAAI;IACN,MAAM,UAAU,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,SAAS,QAAQ;IACvE,IAAI,SAAS,MAAM,QAAQ;KACzB,MAAM,aAAa;KACnB,KAAK,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,eAAe,GADtB,QAAQ,QAAQ,GAAG,OACO;OACzC,IAAI,CAAC,SACH,OAAO;OACT,OAAO;QAAE;QAAM;QAAS;QACxB,CACH;MACD,KAAK,MAAM,KAAK,SACd,IAAI,GAAG;OACL,MAAM,WAAW,QAAQ,aAAa,EAAE,KAAK,QAAQ,QAAQ,YAAY,GAAG,GAAG,EAAE;OACjF,MAAM,YAAY,SAAS,WAAW,QAAQ,GAAG,WAAW,QAAQ;OACpE,WAAW,KAAK;QAAE,MAAM;QAAW,SAAS,EAAE;QAAS,CAAC;OACxD,YAAY,KAAK;QAAE,IAAI;QAAW,SAAS,EAAE;QAAS,UAAU;SAAE,SAAS;SAAS,QAAQ;SAAW,MAAM;SAAO;QAAE,CAAC;;;KAM7H,IAAI,iBAAiB,WAAW,OAAO,IAAI,SAAS,SAAS;MAC3D,WAAW,SAAS;MACpB,YAAY,SAAS;YAElB,IAAI,WAAW,SAAS,KAAK,SAAS,SAAS;MAElD,MAAM,cAAc,MAAM,aAAa,SAAS,QAAQ;MACxD,IAAI,aAAa;OACf,MAAM,UAAU,SAAS,WAAW,IAAI,IAAI,SAAS,QAAQ,CAAC;OAC9D,WAAW,KAAK;QAAE,MAAM;QAAY,SAAS,mBAAmB,YAAY,IAAI;QAAE,CAAC;OACnF,IAAI,YAAY,MAAM,SAAS,GAAG;QAChC,MAAM,OAAO,MAAM,iBAAiB,aAAa,QAAQ;QACzD,KAAK,MAAM,OAAO,MAAM;SACtB,IAAI,CAAC,eAAe,IAAI,IAAI,EAC1B;SACF,MAAM,YAAY,IAAI,IAAI,WAAW,IAAI,GAAG,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI;SACnE,WAAW,KAAK;UAAE,MAAM,KAAK,aAAa,GAAG,UAAU,MAAM,IAAI,CAAC;UAAE,SAAS,IAAI;UAAS,CAAC;;;;;;;;EAUzG,IAAI,SAAS,WAAW,WAAW,WAAW,GAAG;GAC/C,MAAM,cAAc,MAAM,aAAa,SAAS,QAAQ;GACxD,IAAI,aAAa;IACf,WAAW,KAAK;KAAE,MAAM;KAAY,SAAS,mBAAmB,YAAY,IAAI;KAAE,CAAC;IACnF,IAAI,YAAY,MAAM,SAAS,GAAG;KAEhC,MAAM,OAAO,MAAM,iBAAiB,aADpB,SAAS,WAAW,IAAI,IAAI,SAAS,QAAQ,CAAC,OACL;KACzD,KAAK,MAAM,OAAO,MAAM;MACtB,IAAI,CAAC,eAAe,IAAI,IAAI,EAC1B;MAEF,MAAM,YAAY,KAAK,QAAQ,IADb,IAAI,IAAI,WAAW,IAAI,GAAG,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI,KACvB,MAAM,IAAI,CAAC;MACvD,WAAW,KAAK;OAAE,MAAM;OAAW,SAAS,IAAI;OAAS,CAAC;MAC1D,YAAY,KAAK;OAAE,IAAI,IAAI;OAAK,SAAS,IAAI;OAAS,UAAU;QAAE,SAAS;QAAS,QAAQ;QAAW,MAAM;QAAO;OAAE,CAAC;;;;;EAO/H,IAAI,SAAS,aAAa,WAAW,WAAW,GAAG;GACjD,MAAM,UAAU,MAAM,mBAAmB,SAAS,UAAU;GAC5D,IAAI,SAAS;IACX,WAAW,KAAK;KAAE,MAAM;KAAkB;KAAS,CAAC;IACpD,YAAY,KAAK;KAAE,IAAI;KAAa;KAAS,UAAU;MAAE,SAAS;MAAS,QAAQ;MAAkB,MAAM;MAAO;KAAE,CAAC;;;EAIzH,IAAI,WAAW,SAAS,GAAG;GACzB,aAAa,SAAS,SAAS,WAAW;GAE1C,UAAU,gBAAgB,EAAE,WAAW,MAAM,CAAC;GAC9C,eAAe,gBAAgB,SAAS,KAAK,QAAQ;GAErD,KAAK,MAAM,OAAO,cAAc,KAAK,SAAS,EAC5C,aAAa,UAAU,IAAI,MAAM,KAAK,IAAI,QAAQ;GAEpD,IAAI,CAAC,kBAAkB,gBAAgB,EAAE;IACvC,MAAM,WAAW,KAAK,gBAAgB,OAAO;IAC7C,MAAM,gBAAgB,KAAK,iBAAiB,OAAO;IACnD,IAAI,WAAW,SAAS,EACtB,WAAW,SAAS;IACtB,IAAI,WAAW,cAAc,EAC3B,YAAY,eAAe,UAAU,WAAW;;GAGpD,IAAI,SAAS,QACX,IAAI;IACF,IAAI,YAAY,SAAS,GACvB,MAAM,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;IAChE,IAAI,WAAW,SAAS,GACtB,MAAM,YAAY,WAAW,KAAI,OAAM;KACrC,IAAI,EAAE;KACN,SAAS,EAAE;KACX,UAAU;MAAE,SAAS;MAAS,QAAQ,OAAO,EAAE;MAAQ,MAAM,EAAE;MAAM;KACtE,EAAE,EAAE,EAAE,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,CAAC;YAGjD,KAAK;IACV,IAAI,EAAE,eAAe,6BACnB,MAAM;;GAIZ,IAAI,CAAC,sBAAsB,UAAU,MAAM,cAAc;QACnD,sBAAsB,UAAU,SAAS,SAAS,KAAK,eAAe,KAAK,QAAQ,KAAK,SAAS,EACnG,YAAY,KAAK;KAAE;KAAM;KAAS;KAAS;KAAU,UAAU,KAAK;KAAU,CAAC;;GAEnF,KAAK,KAAK,yBAAyB,OAAO;SAG1C,KAAK,KAAK,qBAAqB,OAAO;;CAK1C,IAAI,YAAY,SAAS,KAAK,CAAC,YAAY,CAAC,SAAS;EAEnD,MAAM,YAAY,MAAM,gBAAgB,KAAA,GAAW,wBADrC,YAAY,KAAI,MAAK,EAAE,KAAK,CAAC,KAAK,KACgC,GAAG;EACnF,IAAI,WAAW,YAAY;GACzB,MAAM,WAAW,YAAY,CAAC,YAAY;GAC1C,KAAK,MAAM,EAAE,SAAS,SAAS,cAAc,aAAa;IACxD,MAAM,kBAAkB,YAAY,SAAS,QAAQ;IACrD,iBAAiB;KACf,aAAa;KACb;KACA;KACA,WAAW,WAAW,KAAK,iBAAiB,SAAS,CAAC;KACtD,gBAAgB,WAAW,KAAK,iBAAiB,cAAc,CAAC;KAChE,aAAa,WAAW,KAAK,iBAAiB,WAAW,CAAC;KAC1D,cAAc;KACd,UAAU;KACV,gBAAgB;KAChB,UAAU,eAAe,SAAS,QAAQ,KAAK,EAAE,QAAQ;KACzD,UAAU,UAAU;KACpB,cAAc,UAAU;KACxB;KACD,CAAC;;SAGD,IAAI,WAAW;GAClB,EAAE,IAAI,KAAK,cAAc,UAAU,MAAM,CAAC;GAC1C,KAAK,MAAM,EAAE,SAAS,SAAS,UAAU,UAAU,iBAAiB,aAClE,MAAM,mBAAmB,SAAS,SAAS,UAAU,UAAU,OAAO,UAAU,UAAU,UAAU,cAAc,YAAY;;;CAMpI,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,OAAO,EACpD,UAAU,WAAW,MAAM,KAAK;CAGlC,IAAI,QACF,KAAK,MAAM,CAAC,SAAS,QACnB,kBAAkB,MAAM,QAAQ,KAAK,KAAK,MAAM;MAGlD,oBAAoB,MAAM,cAAc,QAAO,MAAK,MAAM,UAAU,CAAC;CAGvE,MAAM,gBAAgB;CAEtB,EAAE,MAAM,mBAAmB;;AAI7B,SAAS,sBAAsB,UAAkB,MAAc,eAAkC;CAC/F,MAAM,WAAW,KAAK,UAAU,WAAW;CAC3C,IAAI,WAAW,SAAS,EACtB,OAAO;CACT,KAAK,MAAM,OAAO,eAAe;EAC/B,IAAI,QAAQ,UACV;EACF,MAAM,cAAc,KAAK,KAAK,MAAM,WAAW;EAC/C,IAAI,WAAW,YAAY,IAAI,CAAC,UAAU,YAAY,CAAC,gBAAgB,EAAE;GACvE,UAAU,UAAU,EAAE,WAAW,MAAM,CAAC;GACxC,aAAa,aAAa,SAAS;GACnC,OAAO;;;CAGX,OAAO;;AAIT,SAAS,eAAe,WAAmB,QAAyB;CAClE,IAAI,QAAQ,SAAS,UAAU,EAAE;EAC/B,MAAM,QAAQ,OAAO,MAAM,yBAAyB;EACpD,IAAI,OACF,OAAO,IAAI,MAAM,GAAG,GAAG,MAAM;;CAGjC,IAAI,UAAU,WAAW,SAAS,EAChC,OAAO,UAAU,UAAU,MAAM,EAAE;CACrC,IAAI,UAAU,WAAW,SAAS,EAChC,OAAO,UAAU,UAAU,MAAM,EAAE;CACrC,IAAI,UAAU,WAAW,QAAQ,EAC/B,OAAO,SAAS,UAAU,MAAM,EAAE;CACpC,IAAI,UAAU,WAAW,OAAO,EAC9B,OAAO,QAAQ,UAAU,MAAM,EAAE;CACnC,IAAI,UAAU,WAAW,UAAU,EACjC,OAAO,WAAW,UAAU,MAAM,EAAE;CAEtC,OAAO;;AAIT,SAAS,eAAe,eAAuB,MAAc,KAAa,SAAwB;CAChG,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;CACjD,IAAI,CAAC,SACH;CAEF,MAAM,UAAU,KAAK,eAAe,MAAM;CAC1C,IAAI,WAAW,QAAQ,EACrB,WAAW,QAAQ;CACrB,YAAY,SAAS,SAAS,WAAW;;AAI3C,SAAS,kBAAkB,MAAc,KAAa,SAA2B;CAC/E,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;CACjD,IAAI,CAAC,SACH,OAAO;CAGT,KAAK,MAAM,aAAa;EADA;EAAQ;EAAiB;EACX,EAEpC,IAAI,WADa,KAAK,SAAS,UACR,CAAC,EACtB,OAAO;CAEX,OAAO;;AAIT,eAAe,mBACb,SACA,SACA,UACA,OACA,UACA,cACA,UACe;CACf,MAAM,SAAS,EAAE,QAAQ;EAAE,OAAO,mBAAmB;EAAW,OAAO;EAAG,CAAC;CAE3E,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,OAAO;EACvC,CAAC;CAEF,IAAI,cAAc;EAChB,OAAO,QAAQ,2BAA2B;EAE1C,MAAM,MAAM,QAAQ,KAAK;EACzB,MAAM,UAAU,cAAc,SAAS,KAAK,QAAQ;EACpD,IAAI;EACJ,IAAI,SAAS;GAEX,MAAM,gBAAgB,oBADF,KAAK,SAAS,eACmB,CAAC;GACtD,IAAI,eACF,cAAc,cAAc,OAAO;;EAIvC,MAAM,WAAW,uBAAuB,gBAAgB;EAGxD,MAAM,UAAU,SAAS,MAAM,IAAI,CAAC,KAAK;EAEzC,MAAM,cAAc,kBAAkB,SAAS;EAC/C,sBAAsB,UAAU;GAC9B,MAAM;GACN;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;QAGF,OAAO,QAAQ,sBAAsB;;AAIzC,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;EACpC,IAAI,CAAC,SAAS,UAAU,QAAQ;GAC9B,IAAI,UAAU,QACZ;GACF,MAAM,SAAS,MAAM,gBAAgB;GACrC,IAAI,CAAC,UAAU,WAAW,QACxB;GACF,QAAQ;;EAGV,EAAE,MAAM,uCAAuC;EAC/C,OAAO,eAAe;GAAE,QAAQ,KAAK;GAAQ;GAAO,CAAC;;CAExD,CAAC;AAGF,SAAS,sBACP,UACA,SACA,SACA,KACA,eACA,QACA,UACS;CAET,IAAI,WADgB,KAAK,UAAU,WACT,CAAC,EACzB,OAAO;CAGT,MAAM,UAAU,cAAc,SAAS,KAAK,QAAQ;CACpD,IAAI;CACJ,IAAI,SAAS;EACX,MAAM,YAAY,oBAAoB,KAAK,SAAS,eAAe,CAAC;EACpE,IAAI,WACF,cAAc,UAAU,OAAO;;CAKnC,MAAM,kBAAkB,YAAY,SAAS,QAAQ;CACrD,MAAM,WAAW,uBAAuB,iBAAiB,OAAO;CAGhE,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,kBAAkB,SAAS;CAE/C,UAAU,UAAU,EAAE,WAAW,MAAM,CAAC;CACxC,sBAAsB,UAAU;EAC9B,MAAM;EACN;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;CAEF,OAAO;;AAIT,SAAS,mBAAmB,gBAAwB,SAAiB,SAAiB,UAAmC;CAEvH,KAAK,MAAM,SAAS,YAAY,eAAe,EAAE;EAC/C,MAAM,YAAY,KAAK,gBAAgB,MAAM;EAC7C,IAAI,UAAU,UAAU,CAAC,gBAAgB,IAAI,CAAC,WAAW,UAAU,EACjE,OAAO;;CAIX,IAAI,CAAC,WAAW,KAAK,gBAAgB,MAAM,CAAC,EAC1C,OAAO;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,CAAC;EAC5D;CAED,KAAK,MAAM,CAAC,MAAM,gBAAgB,UAChC,IAAI,eAAe,CAAC,WAAW,KAAK,gBAAgB,KAAK,CAAC,EACxD,OAAO;CAGX,OAAO"}
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, 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 { writeGeneratedSkillMd, writeSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n classifyCachedDoc,\n createReferenceCache,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getShippedSkills,\n inferDocsTypeFromCache,\n linkShippedSkill,\n listReferenceFiles,\n resolvePkgDir,\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, parsePackageNames, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { readPackageJsonSafe } from '../core/package-json.ts'\nimport { getSharedSkillsDir, skillInternalDir } from '../core/paths.ts'\nimport { toStoragePackageName } from '../core/prefix.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { indexResources } from '../retriv/index-pipeline.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n downloadLlmsDocs,\n fetchGitDocs,\n fetchGitHubRaw,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { selectLlmConfig, writePromptFiles } 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 = skillInternalDir(skillDir)\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, toStoragePackageName(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 identityName = info.packageName || unsanitizeName(name, info.source)\n const pkgName = toStoragePackageName(identityName)\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 writeSkillMd(skillDir, 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 cache = createReferenceCache(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (cache.has()) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const docsType = inferDocsTypeFromCache(cache.dir, info.source)\n cache.linkInto(skillDir, cwd, docsType, {\n extraPackages: parsePackages(info.packages),\n features,\n repoInfo: repoGh ? { owner: repoGh.owner, repo: repoGh.repo } : undefined,\n })\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 = cache.readDocs()\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 fetchGitHubRaw(url)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n const cachePath = stripped.startsWith('docs/') ? stripped : `docs/${stripped}`\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 cache.write(cachedDocs)\n\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const docsType = inferDocsTypeFromCache(cache.dir, info.source)\n cache.linkInto(skillDir, cwd, docsType, {\n extraPackages: parsePackages(info.packages),\n features,\n repoInfo: repoGh ? { owner: repoGh.owner, repo: repoGh.repo } : undefined,\n })\n\n if (features.search) {\n try {\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 catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\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?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n version,\n skillDir,\n references: {\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n },\n resolved: {},\n relatedSkills: [],\n features,\n }, {\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n })\n }\n }\n else 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, opts.agent)\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/** 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}`, limit: 3 })\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 if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n const pkgJsonResult = readPackageJsonSafe(pkgJsonPath)\n if (pkgJsonResult) {\n description = pkgJsonResult.parsed.description as string | undefined\n }\n }\n\n const docsType = inferDocsTypeFromCache(globalCachePath)\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackageNames(packages)\n writeGeneratedSkillMd(skillDir, {\n name: pkgName,\n version,\n description,\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 }\n else {\n llmLog.message('Enhancement 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 || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\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 if (pkgPath) {\n const pkgResult = readPackageJsonSafe(join(pkgPath, 'package.json'))\n if (pkgResult) {\n description = pkgResult.parsed.description as string | undefined\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n const docsType = inferDocsTypeFromCache(globalCachePath, source)\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 = parsePackageNames(packages)\n\n mkdirSync(skillDir, { recursive: true })\n writeGeneratedSkillMd(skillDir, {\n name: pkgName,\n version,\n description,\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 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":"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"}
@@ -1,4 +1,4 @@
1
- import { f as formatSource, g as timeAgo } from "./skill.mjs";
1
+ import { f as formatSource, g as timeAgo } from "./prompts.mjs";
2
2
  import { x as sharedArgs } from "./cli-helpers.mjs";
3
3
  import { i as iterateSkills, t as getProjectState } from "./skills.mjs";
4
4
  import { defineCommand } from "citty";
@@ -1,6 +1,6 @@
1
+ import { f as lockfilePath } from "./paths.mjs";
1
2
  import { n as yamlParseKV, t as yamlEscape } from "./yaml.mjs";
2
3
  import { i as parseFrontmatter } from "./markdown.mjs";
3
- import { join } from "pathe";
4
4
  import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
5
5
  function parsePackages(packages) {
6
6
  if (!packages) return [];
@@ -54,7 +54,7 @@ function invalidateLockCache(skillsDir) {
54
54
  function readLock(skillsDir) {
55
55
  const cached = lockCache.get(skillsDir);
56
56
  if (cached) return { skills: { ...cached.skills } };
57
- const lockPath = join(skillsDir, "skilld-lock.yaml");
57
+ const lockPath = lockfilePath(skillsDir);
58
58
  if (!existsSync(lockPath)) return null;
59
59
  const content = readFileSync(lockPath, "utf-8");
60
60
  const skills = {};
@@ -76,6 +76,29 @@ function readLock(skillsDir) {
76
76
  lockCache.set(skillsDir, lock);
77
77
  return { skills: { ...lock.skills } };
78
78
  }
79
+ function findSkillDirByPackage(lock, packageName) {
80
+ for (const [dirName, info] of Object.entries(lock.skills)) {
81
+ if (info.packageName === packageName) return dirName;
82
+ if (parsePackages(info.packages).some((p) => p.name === packageName)) return dirName;
83
+ }
84
+ return null;
85
+ }
86
+ function findSkillDirsByPackage(lock, packageName, excludeDir) {
87
+ const out = [];
88
+ for (const [dirName, info] of Object.entries(lock.skills)) {
89
+ if (dirName === excludeDir) continue;
90
+ if (info.packageName === packageName || parsePackages(info.packages).some((p) => p.name === packageName)) out.push(dirName);
91
+ }
92
+ return out;
93
+ }
94
+ function buildPackageDirMap(lock) {
95
+ const map = /* @__PURE__ */ new Map();
96
+ for (const [dirName, info] of Object.entries(lock.skills)) {
97
+ if (info.packageName) map.set(info.packageName, dirName);
98
+ for (const pkg of parsePackages(info.packages)) map.set(pkg.name, dirName);
99
+ }
100
+ return map;
101
+ }
79
102
  function serializeLock(lock) {
80
103
  let yaml = "skills:\n";
81
104
  for (const [name, skill] of Object.entries(lock.skills)) {
@@ -85,7 +108,7 @@ function serializeLock(lock) {
85
108
  return yaml;
86
109
  }
87
110
  function writeLock(skillsDir, skillName, info) {
88
- const lockPath = join(skillsDir, "skilld-lock.yaml");
111
+ const lockPath = lockfilePath(skillsDir);
89
112
  let lock = { skills: {} };
90
113
  if (existsSync(lockPath)) lock = readLock(skillsDir) || { skills: {} };
91
114
  const existing = lock.skills[skillName];
@@ -122,7 +145,7 @@ function mergeLocks(locks) {
122
145
  }
123
146
  function syncLockfilesToDirs(sourceLock, dirs) {
124
147
  for (const dir of dirs) {
125
- const lockPath = join(dir, "skilld-lock.yaml");
148
+ const lockPath = lockfilePath(dir);
126
149
  if (!existsSync(lockPath)) continue;
127
150
  const existing = readLock(dir);
128
151
  if (!existing) continue;
@@ -131,7 +154,7 @@ function syncLockfilesToDirs(sourceLock, dirs) {
131
154
  }
132
155
  }
133
156
  function removeLockEntry(skillsDir, skillName) {
134
- const lockPath = join(skillsDir, "skilld-lock.yaml");
157
+ const lockPath = lockfilePath(skillsDir);
135
158
  const lock = readLock(skillsDir);
136
159
  if (!lock) return;
137
160
  delete lock.skills[skillName];
@@ -143,6 +166,6 @@ function removeLockEntry(skillsDir, skillName) {
143
166
  writeFileSync(lockPath, serializeLock(lock));
144
167
  invalidateLockCache(skillsDir);
145
168
  }
146
- export { readLock as a, writeLock as c, parseSkillFrontmatter as i, parsePackageNames as n, removeLockEntry as o, parsePackages as r, syncLockfilesToDirs as s, mergeLocks as t };
169
+ export { parsePackageNames as a, readLock as c, writeLock as d, mergeLocks as i, removeLockEntry as l, findSkillDirByPackage as n, parsePackages as o, findSkillDirsByPackage as r, parseSkillFrontmatter as s, buildPackageDirMap as t, syncLockfilesToDirs as u };
147
170
 
148
171
  //# sourceMappingURL=lockfile.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.mjs","names":[],"sources":["../../src/core/lockfile.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { parseFrontmatter } from './markdown.ts'\nimport { yamlEscape, yamlParseKV } from './yaml.ts'\n\nexport interface SkillInfo {\n packageName?: string\n version?: string\n /** All tracked packages as comma-separated \"name@version\" pairs (multi-package skills) */\n packages?: string\n repo?: string\n source?: string\n syncedAt?: string\n generator?: string\n /** Skill path within repo (git-sourced skills) */\n path?: string\n /** Git ref tracked for updates */\n ref?: string\n /** Git commit SHA at install time */\n commit?: string\n}\n\nexport function parsePackages(packages?: string): Array<{ name: string, version: string }> {\n if (!packages)\n return []\n return packages.split(',').map((s) => {\n const trimmed = s.trim()\n const atIdx = trimmed.lastIndexOf('@')\n if (atIdx <= 0)\n return { name: trimmed, version: '' }\n return { name: trimmed.slice(0, atIdx), version: trimmed.slice(atIdx + 1) }\n }).filter(p => p.name)\n}\n\nexport function parsePackageNames(packages?: string): Array<{ name: string }> {\n return parsePackages(packages).map(({ name }) => ({ name }))\n}\n\nexport function serializePackages(pkgs: Array<{ name: string, version: string }>): string {\n return pkgs.map(p => `${p.name}@${p.version}`).join(', ')\n}\n\nexport interface SkilldLock {\n skills: Record<string, SkillInfo>\n}\n\nconst SKILL_FM_KEYS: (keyof SkillInfo)[] = ['packageName', 'version', 'packages', 'repo', 'source', 'syncedAt', 'generator', 'path', 'ref', 'commit']\n\nfunction isSkillInfoKey(key: string): key is keyof SkillInfo {\n return (SKILL_FM_KEYS as readonly string[]).includes(key)\n}\n\nexport function parseSkillFrontmatter(skillPath: string): SkillInfo | null {\n if (!existsSync(skillPath))\n return null\n const content = readFileSync(skillPath, 'utf-8')\n const fm = parseFrontmatter(content)\n if (Object.keys(fm).length === 0)\n return null\n\n const info: SkillInfo = {}\n for (const key of SKILL_FM_KEYS) {\n if (fm[key])\n info[key] = fm[key]\n }\n return info\n}\n\nconst lockCache = new Map<string, SkilldLock>()\n\nexport function invalidateLockCache(skillsDir?: string): void {\n if (skillsDir)\n lockCache.delete(skillsDir)\n else\n lockCache.clear()\n}\n\nexport function readLock(skillsDir: string): SkilldLock | null {\n const cached = lockCache.get(skillsDir)\n if (cached)\n return { skills: { ...cached.skills } }\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n return null\n const content = readFileSync(lockPath, 'utf-8')\n\n const skills: Record<string, SkillInfo> = {}\n let currentSkill: string | null = null\n\n for (const line of content.split('\\n')) {\n const skillMatch = line.match(/^ {2}(\\S+):$/)\n if (skillMatch) {\n currentSkill = skillMatch[1]!\n skills[currentSkill] = {}\n continue\n }\n if (currentSkill && line.startsWith(' ')) {\n const kv = yamlParseKV(line)\n if (kv && isSkillInfoKey(kv[0]))\n skills[currentSkill]![kv[0]] = kv[1]\n }\n }\n // Normalize legacy source values\n for (const info of Object.values(skills)) {\n if (info.source === 'npm')\n info.source = 'registry'\n }\n const lock = { skills }\n lockCache.set(skillsDir, lock)\n return { skills: { ...lock.skills } }\n}\n\nfunction serializeLock(lock: SkilldLock): string {\n let yaml = 'skills:\\n'\n for (const [name, skill] of Object.entries(lock.skills)) {\n yaml += ` ${name}:\\n`\n for (const key of SKILL_FM_KEYS) {\n if (skill[key])\n yaml += ` ${key}: ${yamlEscape(skill[key])}\\n`\n }\n }\n return yaml\n}\n\nexport function writeLock(skillsDir: string, skillName: string, info: SkillInfo): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n let lock: SkilldLock = { skills: {} }\n if (existsSync(lockPath)) {\n lock = readLock(skillsDir) || { skills: {} }\n }\n\n const existing = lock.skills[skillName]\n if (existing && info.packageName) {\n // Merge packages list\n const existingPkgs = parsePackages(existing.packages)\n // Also include existing primary if not yet in packages list\n if (existing.packageName && !existingPkgs.some(p => p.name === existing.packageName)) {\n existingPkgs.unshift({ name: existing.packageName, version: existing.version || '' })\n }\n // Add/update new package\n const idx = existingPkgs.findIndex(p => p.name === info.packageName)\n if (idx >= 0) {\n existingPkgs[idx]!.version = info.version || ''\n }\n else {\n existingPkgs.push({ name: info.packageName, version: info.version || '' })\n }\n info.packages = serializePackages(existingPkgs)\n // Keep primary as first package\n info.packageName = existingPkgs[0]!.name\n info.version = existingPkgs[0]!.version\n // Preserve fields from existing entry that aren't in new info\n if (!info.repo && existing.repo)\n info.repo = existing.repo\n if (!info.source && existing.source)\n info.source = existing.source\n if (!info.generator && existing.generator)\n info.generator = existing.generator\n }\n\n lock.skills[skillName] = info\n writeFileSync(lockPath, serializeLock(lock))\n invalidateLockCache(skillsDir)\n}\n\n/**\n * Merge multiple lockfiles, preferring the most recently synced entry per skill.\n */\nexport function mergeLocks(locks: SkilldLock[]): SkilldLock {\n const merged: Record<string, SkillInfo> = {}\n for (const lock of locks) {\n for (const [name, info] of Object.entries(lock.skills)) {\n const existing = merged[name]\n if (!existing || (info.syncedAt && (!existing.syncedAt || info.syncedAt > existing.syncedAt)))\n merged[name] = info\n }\n }\n return { skills: merged }\n}\n\n/**\n * Sync a lockfile to all other dirs that already have a skilld-lock.yaml.\n * Only updates existing lockfiles — does not create new ones.\n */\nexport function syncLockfilesToDirs(sourceLock: SkilldLock, dirs: string[]): void {\n for (const dir of dirs) {\n const lockPath = join(dir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n continue\n const existing = readLock(dir)\n if (!existing)\n continue\n // Merge source into existing\n const merged = mergeLocks([existing, sourceLock])\n writeFileSync(lockPath, serializeLock(merged))\n invalidateLockCache(dir)\n }\n}\n\nexport function removeLockEntry(skillsDir: string, skillName: string): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n const lock = readLock(skillsDir)\n if (!lock)\n return\n\n delete lock.skills[skillName]\n\n if (Object.keys(lock.skills).length === 0) {\n unlinkSync(lockPath)\n invalidateLockCache(skillsDir)\n return\n }\n\n writeFileSync(lockPath, serializeLock(lock))\n invalidateLockCache(skillsDir)\n}\n"],"mappings":";;;;AAsBA,SAAgB,cAAc,UAA6D;CACzF,IAAI,CAAC,UACH,OAAO,EAAE;CACX,OAAO,SAAS,MAAM,IAAI,CAAC,KAAK,MAAM;EACpC,MAAM,UAAU,EAAE,MAAM;EACxB,MAAM,QAAQ,QAAQ,YAAY,IAAI;EACtC,IAAI,SAAS,GACX,OAAO;GAAE,MAAM;GAAS,SAAS;GAAI;EACvC,OAAO;GAAE,MAAM,QAAQ,MAAM,GAAG,MAAM;GAAE,SAAS,QAAQ,MAAM,QAAQ,EAAE;GAAE;GAC3E,CAAC,QAAO,MAAK,EAAE,KAAK;;AAGxB,SAAgB,kBAAkB,UAA4C;CAC5E,OAAO,cAAc,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE;;AAG9D,SAAgB,kBAAkB,MAAwD;CACxF,OAAO,KAAK,KAAI,MAAK,GAAG,EAAE,KAAK,GAAG,EAAE,UAAU,CAAC,KAAK,KAAK;;AAO3D,MAAM,gBAAqC;CAAC;CAAe;CAAW;CAAY;CAAQ;CAAU;CAAY;CAAa;CAAQ;CAAO;CAAS;AAErJ,SAAS,eAAe,KAAqC;CAC3D,OAAQ,cAAoC,SAAS,IAAI;;AAG3D,SAAgB,sBAAsB,WAAqC;CACzE,IAAI,CAAC,WAAW,UAAU,EACxB,OAAO;CAET,MAAM,KAAK,iBADK,aAAa,WAAW,QACL,CAAC;CACpC,IAAI,OAAO,KAAK,GAAG,CAAC,WAAW,GAC7B,OAAO;CAET,MAAM,OAAkB,EAAE;CAC1B,KAAK,MAAM,OAAO,eAChB,IAAI,GAAG,MACL,KAAK,OAAO,GAAG;CAEnB,OAAO;;AAGT,MAAM,4BAAY,IAAI,KAAyB;AAE/C,SAAgB,oBAAoB,WAA0B;CAC5D,IAAI,WACF,UAAU,OAAO,UAAU;MAE3B,UAAU,OAAO;;AAGrB,SAAgB,SAAS,WAAsC;CAC7D,MAAM,SAAS,UAAU,IAAI,UAAU;CACvC,IAAI,QACF,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,QAAQ,EAAE;CACzC,MAAM,WAAW,KAAK,WAAW,mBAAmB;CACpD,IAAI,CAAC,WAAW,SAAS,EACvB,OAAO;CACT,MAAM,UAAU,aAAa,UAAU,QAAQ;CAE/C,MAAM,SAAoC,EAAE;CAC5C,IAAI,eAA8B;CAElC,KAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,EAAE;EACtC,MAAM,aAAa,KAAK,MAAM,eAAe;EAC7C,IAAI,YAAY;GACd,eAAe,WAAW;GAC1B,OAAO,gBAAgB,EAAE;GACzB;;EAEF,IAAI,gBAAgB,KAAK,WAAW,OAAO,EAAE;GAC3C,MAAM,KAAK,YAAY,KAAK;GAC5B,IAAI,MAAM,eAAe,GAAG,GAAG,EAC7B,OAAO,cAAe,GAAG,MAAM,GAAG;;;CAIxC,KAAK,MAAM,QAAQ,OAAO,OAAO,OAAO,EACtC,IAAI,KAAK,WAAW,OAClB,KAAK,SAAS;CAElB,MAAM,OAAO,EAAE,QAAQ;CACvB,UAAU,IAAI,WAAW,KAAK;CAC9B,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,QAAQ,EAAE;;AAGvC,SAAS,cAAc,MAA0B;CAC/C,IAAI,OAAO;CACX,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,OAAO,EAAE;EACvD,QAAQ,KAAK,KAAK;EAClB,KAAK,MAAM,OAAO,eAChB,IAAI,MAAM,MACR,QAAQ,OAAO,IAAI,IAAI,WAAW,MAAM,KAAK,CAAC;;CAGpD,OAAO;;AAGT,SAAgB,UAAU,WAAmB,WAAmB,MAAuB;CACrF,MAAM,WAAW,KAAK,WAAW,mBAAmB;CACpD,IAAI,OAAmB,EAAE,QAAQ,EAAE,EAAE;CACrC,IAAI,WAAW,SAAS,EACtB,OAAO,SAAS,UAAU,IAAI,EAAE,QAAQ,EAAE,EAAE;CAG9C,MAAM,WAAW,KAAK,OAAO;CAC7B,IAAI,YAAY,KAAK,aAAa;EAEhC,MAAM,eAAe,cAAc,SAAS,SAAS;EAErD,IAAI,SAAS,eAAe,CAAC,aAAa,MAAK,MAAK,EAAE,SAAS,SAAS,YAAY,EAClF,aAAa,QAAQ;GAAE,MAAM,SAAS;GAAa,SAAS,SAAS,WAAW;GAAI,CAAC;EAGvF,MAAM,MAAM,aAAa,WAAU,MAAK,EAAE,SAAS,KAAK,YAAY;EACpE,IAAI,OAAO,GACT,aAAa,KAAM,UAAU,KAAK,WAAW;OAG7C,aAAa,KAAK;GAAE,MAAM,KAAK;GAAa,SAAS,KAAK,WAAW;GAAI,CAAC;EAE5E,KAAK,WAAW,kBAAkB,aAAa;EAE/C,KAAK,cAAc,aAAa,GAAI;EACpC,KAAK,UAAU,aAAa,GAAI;EAEhC,IAAI,CAAC,KAAK,QAAQ,SAAS,MACzB,KAAK,OAAO,SAAS;EACvB,IAAI,CAAC,KAAK,UAAU,SAAS,QAC3B,KAAK,SAAS,SAAS;EACzB,IAAI,CAAC,KAAK,aAAa,SAAS,WAC9B,KAAK,YAAY,SAAS;;CAG9B,KAAK,OAAO,aAAa;CACzB,cAAc,UAAU,cAAc,KAAK,CAAC;CAC5C,oBAAoB,UAAU;;;;CAMhC,KAAA,MAAgB,QAAW,OAAiC,KAAA,MAAA,CAAA,MAAA,SAAA,OAAA,QAAA,KAAA,OAAA,EAAA;EAC1D,MAAM,WAAsC,OAAA;EAC5C,IAAK,CAAA,YAAM,KAAQ,aACZ,CAAM,SAAO,YAAS,KAAO,WAAa,SAAS,WAAA,OAAA,QAAA;;QAEjD,EAAA,QAAA,QAAkB;;;;;;;EAW7B,IAAA,CAAA,UAAgB;EACd,cAAW,UAAa,cAAA,WAAA,CAAA,UAAA,WAAA,CAAA,CAAA,CAAA;EACtB,oBAAiB,IAAK;;;SAIjB,gBACH,WAAA,WAAA;OAGF,WAAc,KAAA,WAAU,mBADG;OAE3B,OAAA,SAAoB,UAAI;;;CAI5B,IAAA,OAAgB,KAAA,KAAA,OAAgB,CAAA,WAAmB,GAAA;EACjD,WAAM,SAAW;EACjB,oBAAa,UAAS;EACtB;;CAKA,cAAW,UAAU,cAAQ,KAAc,CAAA;qBAC9B,UAAS"}
1
+ {"version":3,"file":"lockfile.mjs","names":[],"sources":["../../src/core/lockfile.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { parseFrontmatter } from './markdown.ts'\nimport { lockfilePath } from './paths.ts'\nimport { yamlEscape, yamlParseKV } from './yaml.ts'\n\nexport interface SkillInfo {\n packageName?: string\n version?: string\n /** All tracked packages as comma-separated \"name@version\" pairs (multi-package skills) */\n packages?: string\n repo?: string\n source?: string\n syncedAt?: string\n generator?: string\n /** Skill path within repo (git-sourced skills) */\n path?: string\n /** Git ref tracked for updates */\n ref?: string\n /** Git commit SHA at install time */\n commit?: string\n}\n\nexport function parsePackages(packages?: string): Array<{ name: string, version: string }> {\n if (!packages)\n return []\n return packages.split(',').map((s) => {\n const trimmed = s.trim()\n const atIdx = trimmed.lastIndexOf('@')\n if (atIdx <= 0)\n return { name: trimmed, version: '' }\n return { name: trimmed.slice(0, atIdx), version: trimmed.slice(atIdx + 1) }\n }).filter(p => p.name)\n}\n\nexport function parsePackageNames(packages?: string): Array<{ name: string }> {\n return parsePackages(packages).map(({ name }) => ({ name }))\n}\n\nexport function serializePackages(pkgs: Array<{ name: string, version: string }>): string {\n return pkgs.map(p => `${p.name}@${p.version}`).join(', ')\n}\n\nexport interface SkilldLock {\n skills: Record<string, SkillInfo>\n}\n\nconst SKILL_FM_KEYS: (keyof SkillInfo)[] = ['packageName', 'version', 'packages', 'repo', 'source', 'syncedAt', 'generator', 'path', 'ref', 'commit']\n\nfunction isSkillInfoKey(key: string): key is keyof SkillInfo {\n return (SKILL_FM_KEYS as readonly string[]).includes(key)\n}\n\nexport function parseSkillFrontmatter(skillPath: string): SkillInfo | null {\n if (!existsSync(skillPath))\n return null\n const content = readFileSync(skillPath, 'utf-8')\n const fm = parseFrontmatter(content)\n if (Object.keys(fm).length === 0)\n return null\n\n const info: SkillInfo = {}\n for (const key of SKILL_FM_KEYS) {\n if (fm[key])\n info[key] = fm[key]\n }\n return info\n}\n\nconst lockCache = new Map<string, SkilldLock>()\n\nexport function invalidateLockCache(skillsDir?: string): void {\n if (skillsDir)\n lockCache.delete(skillsDir)\n else\n lockCache.clear()\n}\n\nexport function readLock(skillsDir: string): SkilldLock | null {\n const cached = lockCache.get(skillsDir)\n if (cached)\n return { skills: { ...cached.skills } }\n const lockPath = lockfilePath(skillsDir)\n if (!existsSync(lockPath))\n return null\n const content = readFileSync(lockPath, 'utf-8')\n\n const skills: Record<string, SkillInfo> = {}\n let currentSkill: string | null = null\n\n for (const line of content.split('\\n')) {\n const skillMatch = line.match(/^ {2}(\\S+):$/)\n if (skillMatch) {\n currentSkill = skillMatch[1]!\n skills[currentSkill] = {}\n continue\n }\n if (currentSkill && line.startsWith(' ')) {\n const kv = yamlParseKV(line)\n if (kv && isSkillInfoKey(kv[0]))\n skills[currentSkill]![kv[0]] = kv[1]\n }\n }\n // Normalize legacy source values\n for (const info of Object.values(skills)) {\n if (info.source === 'npm')\n info.source = 'registry'\n }\n const lock = { skills }\n lockCache.set(skillsDir, lock)\n return { skills: { ...lock.skills } }\n}\n\n/**\n * Find the skill dir that tracks `packageName` (as primary or in `packages`),\n * or null. Single source of truth for \"is this package already synced?\".\n */\nexport function findSkillDirByPackage(lock: SkilldLock, packageName: string): string | null {\n for (const [dirName, info] of Object.entries(lock.skills)) {\n if (info.packageName === packageName)\n return dirName\n if (parsePackages(info.packages).some(p => p.name === packageName))\n return dirName\n }\n return null\n}\n\n/**\n * Every skill dir referencing `packageName`, optionally excluding one. Used by\n * the installer to dedupe stale entries when a skill is renamed or merged.\n */\nexport function findSkillDirsByPackage(lock: SkilldLock, packageName: string, excludeDir?: string): string[] {\n const out: string[] = []\n for (const [dirName, info] of Object.entries(lock.skills)) {\n if (dirName === excludeDir)\n continue\n if (info.packageName === packageName || parsePackages(info.packages).some(p => p.name === packageName))\n out.push(dirName)\n }\n return out\n}\n\n/**\n * Build a `packageName → skillDir` map covering both primary names and\n * additional packages tracked in `packages`. Used for related-skill lookup.\n */\nexport function buildPackageDirMap(lock: SkilldLock): Map<string, string> {\n const map = new Map<string, string>()\n for (const [dirName, info] of Object.entries(lock.skills)) {\n if (info.packageName)\n map.set(info.packageName, dirName)\n for (const pkg of parsePackages(info.packages))\n map.set(pkg.name, dirName)\n }\n return map\n}\n\nfunction serializeLock(lock: SkilldLock): string {\n let yaml = 'skills:\\n'\n for (const [name, skill] of Object.entries(lock.skills)) {\n yaml += ` ${name}:\\n`\n for (const key of SKILL_FM_KEYS) {\n if (skill[key])\n yaml += ` ${key}: ${yamlEscape(skill[key])}\\n`\n }\n }\n return yaml\n}\n\nexport function writeLock(skillsDir: string, skillName: string, info: SkillInfo): void {\n const lockPath = lockfilePath(skillsDir)\n let lock: SkilldLock = { skills: {} }\n if (existsSync(lockPath)) {\n lock = readLock(skillsDir) || { skills: {} }\n }\n\n const existing = lock.skills[skillName]\n if (existing && info.packageName) {\n // Merge packages list\n const existingPkgs = parsePackages(existing.packages)\n // Also include existing primary if not yet in packages list\n if (existing.packageName && !existingPkgs.some(p => p.name === existing.packageName)) {\n existingPkgs.unshift({ name: existing.packageName, version: existing.version || '' })\n }\n // Add/update new package\n const idx = existingPkgs.findIndex(p => p.name === info.packageName)\n if (idx >= 0) {\n existingPkgs[idx]!.version = info.version || ''\n }\n else {\n existingPkgs.push({ name: info.packageName, version: info.version || '' })\n }\n info.packages = serializePackages(existingPkgs)\n // Keep primary as first package\n info.packageName = existingPkgs[0]!.name\n info.version = existingPkgs[0]!.version\n // Preserve fields from existing entry that aren't in new info\n if (!info.repo && existing.repo)\n info.repo = existing.repo\n if (!info.source && existing.source)\n info.source = existing.source\n if (!info.generator && existing.generator)\n info.generator = existing.generator\n }\n\n lock.skills[skillName] = info\n writeFileSync(lockPath, serializeLock(lock))\n invalidateLockCache(skillsDir)\n}\n\n/**\n * Merge multiple lockfiles, preferring the most recently synced entry per skill.\n */\nexport function mergeLocks(locks: SkilldLock[]): SkilldLock {\n const merged: Record<string, SkillInfo> = {}\n for (const lock of locks) {\n for (const [name, info] of Object.entries(lock.skills)) {\n const existing = merged[name]\n if (!existing || (info.syncedAt && (!existing.syncedAt || info.syncedAt > existing.syncedAt)))\n merged[name] = info\n }\n }\n return { skills: merged }\n}\n\n/**\n * Sync a lockfile to all other dirs that already have a skilld-lock.yaml.\n * Only updates existing lockfiles — does not create new ones.\n */\nexport function syncLockfilesToDirs(sourceLock: SkilldLock, dirs: string[]): void {\n for (const dir of dirs) {\n const lockPath = lockfilePath(dir)\n if (!existsSync(lockPath))\n continue\n const existing = readLock(dir)\n if (!existing)\n continue\n // Merge source into existing\n const merged = mergeLocks([existing, sourceLock])\n writeFileSync(lockPath, serializeLock(merged))\n invalidateLockCache(dir)\n }\n}\n\nexport function removeLockEntry(skillsDir: string, skillName: string): void {\n const lockPath = lockfilePath(skillsDir)\n const lock = readLock(skillsDir)\n if (!lock)\n return\n\n delete lock.skills[skillName]\n\n if (Object.keys(lock.skills).length === 0) {\n unlinkSync(lockPath)\n invalidateLockCache(skillsDir)\n return\n }\n\n writeFileSync(lockPath, serializeLock(lock))\n invalidateLockCache(skillsDir)\n}\n"],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { i as readPackageJsonSafe } from "./package-json.mjs";
2
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
3
+ import { join, resolve } from "pathe";
4
+ const QUOTE_PREFIX_RE = /^['"]/;
5
+ const QUOTE_SUFFIX_RE = /['"]$/;
6
+ function readRepoUrl(pkg) {
7
+ return typeof pkg.repository === "string" ? pkg.repository : pkg.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
8
+ }
9
+ function readWorkspacePatterns(cwd, pkg) {
10
+ let patterns = [];
11
+ if (Array.isArray(pkg.workspaces)) patterns = pkg.workspaces;
12
+ else if (pkg.workspaces?.packages) patterns = pkg.workspaces.packages;
13
+ if (patterns.length === 0) {
14
+ const pnpmWs = join(cwd, "pnpm-workspace.yaml");
15
+ if (existsSync(pnpmWs)) {
16
+ const lines = readFileSync(pnpmWs, "utf-8").split("\n");
17
+ for (const line of lines) {
18
+ const trimmed = line.trim();
19
+ if (!trimmed.startsWith("-")) continue;
20
+ const value = trimmed.slice(1).trim().replace(QUOTE_PREFIX_RE, "").replace(QUOTE_SUFFIX_RE, "");
21
+ if (value) patterns.push(value);
22
+ }
23
+ }
24
+ }
25
+ return patterns;
26
+ }
27
+ function detectMonorepoPackages(cwd) {
28
+ const rootResult = readPackageJsonSafe(join(cwd, "package.json"));
29
+ if (!rootResult) return null;
30
+ const pkg = rootResult.parsed;
31
+ if (!pkg.private) return null;
32
+ const patterns = readWorkspacePatterns(cwd, pkg);
33
+ if (patterns.length === 0) return null;
34
+ const packages = [];
35
+ for (const pattern of patterns) {
36
+ const scanDir = resolve(cwd, pattern.replace(/\/?\*+$/, ""));
37
+ if (!existsSync(scanDir)) continue;
38
+ const directResult = readPackageJsonSafe(join(scanDir, "package.json"));
39
+ if (directResult) {
40
+ const directPkg = directResult.parsed;
41
+ if (!directPkg.private && directPkg.name) {
42
+ packages.push({
43
+ name: directPkg.name,
44
+ version: directPkg.version || "0.0.0",
45
+ description: directPkg.description,
46
+ repoUrl: readRepoUrl(directPkg),
47
+ dir: scanDir
48
+ });
49
+ continue;
50
+ }
51
+ }
52
+ for (const entry of readdirSync(scanDir, { withFileTypes: true })) {
53
+ if (!entry.isDirectory()) continue;
54
+ const childResult = readPackageJsonSafe(join(scanDir, entry.name, "package.json"));
55
+ if (!childResult) continue;
56
+ const childPkg = childResult.parsed;
57
+ if (childPkg.private || !childPkg.name) continue;
58
+ packages.push({
59
+ name: childPkg.name,
60
+ version: childPkg.version || "0.0.0",
61
+ description: childPkg.description,
62
+ repoUrl: readRepoUrl(childPkg),
63
+ dir: join(scanDir, entry.name)
64
+ });
65
+ }
66
+ }
67
+ return packages.length > 0 ? packages : null;
68
+ }
69
+ export { detectMonorepoPackages as t };
70
+
71
+ //# sourceMappingURL=monorepo.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo.mjs","names":[],"sources":["../../src/core/monorepo.ts"],"sourcesContent":["/**\n * Monorepo detection — discovers public packages in a workspace root.\n * Used by author flow to drive multi-package skill generation.\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'pathe'\nimport { readPackageJsonSafe } from './package-json.ts'\n\nconst QUOTE_PREFIX_RE = /^['\"]/\nconst QUOTE_SUFFIX_RE = /['\"]$/\n\nexport interface MonorepoPackage {\n name: string\n version: string\n description?: string\n repoUrl?: string\n dir: string\n}\n\nfunction readRepoUrl(pkg: Record<string, any>): string | undefined {\n return typeof pkg.repository === 'string'\n ? pkg.repository\n : pkg.repository?.url?.replace(/^git\\+/, '').replace(/\\.git$/, '')\n}\n\nfunction readWorkspacePatterns(cwd: string, pkg: Record<string, any>): string[] {\n let patterns: string[] = []\n\n if (Array.isArray(pkg.workspaces))\n patterns = pkg.workspaces\n else if (pkg.workspaces?.packages)\n patterns = pkg.workspaces.packages\n\n if (patterns.length === 0) {\n const pnpmWs = join(cwd, 'pnpm-workspace.yaml')\n if (existsSync(pnpmWs)) {\n const lines = readFileSync(pnpmWs, 'utf-8').split('\\n')\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed.startsWith('-'))\n continue\n const value = trimmed.slice(1).trim().replace(QUOTE_PREFIX_RE, '').replace(QUOTE_SUFFIX_RE, '')\n if (value)\n patterns.push(value)\n }\n }\n }\n\n return patterns\n}\n\n/**\n * Detect public (non-private) packages declared by a workspace root.\n * Returns null if `cwd` is not a private workspace root or has no public\n * packages. Supports `package.json#workspaces` (array or `{ packages }`)\n * and `pnpm-workspace.yaml`.\n */\nexport function detectMonorepoPackages(cwd: string): MonorepoPackage[] | null {\n const rootResult = readPackageJsonSafe(join(cwd, 'package.json'))\n if (!rootResult)\n return null\n\n const pkg = rootResult.parsed as Record<string, any>\n if (!pkg.private)\n return null\n\n const patterns = readWorkspacePatterns(cwd, pkg)\n if (patterns.length === 0)\n return null\n\n const packages: MonorepoPackage[] = []\n\n for (const pattern of patterns) {\n const base = pattern.replace(/\\/?\\*+$/, '')\n const scanDir = resolve(cwd, base)\n if (!existsSync(scanDir))\n continue\n\n const directResult = readPackageJsonSafe(join(scanDir, 'package.json'))\n if (directResult) {\n const directPkg = directResult.parsed as Record<string, any>\n if (!directPkg.private && directPkg.name) {\n packages.push({\n name: directPkg.name,\n version: directPkg.version || '0.0.0',\n description: directPkg.description,\n repoUrl: readRepoUrl(directPkg),\n dir: scanDir,\n })\n continue\n }\n }\n\n for (const entry of readdirSync(scanDir, { withFileTypes: true })) {\n if (!entry.isDirectory())\n continue\n const childResult = readPackageJsonSafe(join(scanDir, entry.name, 'package.json'))\n if (!childResult)\n continue\n\n const childPkg = childResult.parsed as Record<string, any>\n if (childPkg.private || !childPkg.name)\n continue\n\n packages.push({\n name: childPkg.name,\n version: childPkg.version || '0.0.0',\n description: childPkg.description,\n repoUrl: readRepoUrl(childPkg),\n dir: join(scanDir, entry.name),\n })\n }\n }\n\n return packages.length > 0 ? packages : null\n}\n"],"mappings":";;;;;;CASA,OAAM,OAAA,IAAA,eAAkB,WAAA,IAAA,aAAA,IAAA,YAAA,KAAA,QAAA,UAAA,GAAA,CAAA,QAAA,UAAA,GAAA;;AAWxB,SAAS,sBAA0D,KAAA,KAAA;CACjE,IAAA,WAAc,EAAA;;MAKhB,IAAS,IAAA,YAAA,UAAmC,WAAoC,IAAA,WAAA;CAC9E,IAAI,SAAA,WAAuB,GAAA;EAE3B,MAAI,SAAM,KAAQ,KAAI,sBACT;MACR,WAAQ,OAAA,EAAY;GAGzB,MAAI,QAAS,aAAc,QAAA,QAAA,CAAA,MAAA,KAAA;GACzB,KAAM,MAAA,QAAc,OAAK;IACzB,MAAI,UAAW,KAAO,MAAE;IACtB,IAAA,CAAM,QAAQ,WAAA,IAAa,EAAA;IAC3B,MAAK,QAAM,QAAQ,MAAO,EAAA,CAAA,MAAA,CAAA,QAAA,iBAAA,GAAA,CAAA,QAAA,iBAAA,GAAA;IACxB,IAAA,OAAM,SAAU,KAAK,MAAM;;;;;;SAU1B,uBAAA,KAAA;;;;;;;;CAST,KAAA,MAAgB,WAAA,UAAuB;EACrC,MAAM,UAAA,QAAa,KAAA,QAAA,QAAyB,WAAK,GAAA,CAAA;EACjD,IAAK,CAAA,WACH,QAAO,EAAA;EAET,MAAM,eAAM,oBAAW,KAAA,SAAA,eAAA,CAAA;EACvB,IAAK,cACH;GAEF,MAAM,YAAW,aAAA;GACjB,IAAI,CAAA,UAAS,WACX,UAAO,MAAA;IAET,SAAM,KAA8B;KAEpC,MAAK,UAAM;KAET,SAAM,UAAU,WADH;KAEb,aAAgB,UACd;KAEF,SAAM,YAAe,UAAA;KACrB,KAAI;KACF,CAAA;IACA;;;OAGI,MAAA,SAAS,YAAU,SAAW,EAAA,eAAA,MAAA,CAAA,EAAA;OAC9B,CAAA,MAAA,aAAa,EAAU;SACvB,cAAS,oBAAsB,KAAA,SAAA,MAAA,MAAA,eAAA,CAAA;OAC/B,CAAA,aAAK;SACL,WAAA,YAAA;OACF,SAAA,WAAA,CAAA,SAAA,MAAA;;;IAIJ,SAAW,SAAS,WAAA;IAClB,aAAW,SAAA;IAEX,SAAM,YAAc,SAAA;IACpB,KAAK,KAAA,SACH,MAAA,KAAA;IAEF,CAAA;;;QAKE,SAAM,SAAS,IAAA,WAAA;;SAGf,0BAA8B"}