skilld 1.5.5 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +32 -23
  2. package/dist/_chunks/agent.mjs +2 -78
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/assemble.mjs +1 -18
  5. package/dist/_chunks/assemble.mjs.map +1 -1
  6. package/dist/_chunks/author-group.mjs +17 -0
  7. package/dist/_chunks/author-group.mjs.map +1 -0
  8. package/dist/_chunks/author.mjs +8 -24
  9. package/dist/_chunks/author.mjs.map +1 -1
  10. package/dist/_chunks/cache.mjs +1 -73
  11. package/dist/_chunks/cache.mjs.map +1 -1
  12. package/dist/_chunks/cache2.mjs +84 -17
  13. package/dist/_chunks/cache2.mjs.map +1 -1
  14. package/dist/_chunks/cli-helpers.mjs +3 -166
  15. package/dist/_chunks/cli-helpers.mjs.map +1 -1
  16. package/dist/_chunks/cli-helpers2.mjs +0 -11
  17. package/dist/_chunks/config.mjs +119 -54
  18. package/dist/_chunks/config.mjs.map +1 -1
  19. package/dist/_chunks/core.mjs +9 -0
  20. package/dist/_chunks/detect.mjs +29 -226
  21. package/dist/_chunks/detect.mjs.map +1 -1
  22. package/dist/_chunks/embedding-cache.mjs +0 -5
  23. package/dist/_chunks/embedding-cache2.mjs +2 -3
  24. package/dist/_chunks/formatting.mjs +0 -6
  25. package/dist/_chunks/formatting.mjs.map +1 -1
  26. package/dist/_chunks/index.d.mts +0 -10
  27. package/dist/_chunks/index.d.mts.map +1 -1
  28. package/dist/_chunks/index2.d.mts +3 -6
  29. package/dist/_chunks/index2.d.mts.map +1 -1
  30. package/dist/_chunks/index3.d.mts +81 -109
  31. package/dist/_chunks/index3.d.mts.map +1 -1
  32. package/dist/_chunks/install.mjs +85 -550
  33. package/dist/_chunks/install.mjs.map +1 -1
  34. package/dist/_chunks/install2.mjs +554 -0
  35. package/dist/_chunks/install2.mjs.map +1 -0
  36. package/dist/_chunks/libs/@sinclair/typebox.mjs +0 -444
  37. package/dist/_chunks/libs/@sinclair/typebox.mjs.map +1 -1
  38. package/dist/_chunks/list.mjs +0 -16
  39. package/dist/_chunks/list.mjs.map +1 -1
  40. package/dist/_chunks/lockfile.mjs +2 -10
  41. package/dist/_chunks/lockfile.mjs.map +1 -1
  42. package/dist/_chunks/markdown.mjs +0 -9
  43. package/dist/_chunks/markdown.mjs.map +1 -1
  44. package/dist/_chunks/package-json.mjs +0 -25
  45. package/dist/_chunks/package-json.mjs.map +1 -1
  46. package/dist/_chunks/package-registry.mjs +465 -0
  47. package/dist/_chunks/package-registry.mjs.map +1 -0
  48. package/dist/_chunks/pool2.mjs +0 -2
  49. package/dist/_chunks/pool2.mjs.map +1 -1
  50. package/dist/_chunks/prefix.mjs +108 -0
  51. package/dist/_chunks/prefix.mjs.map +1 -0
  52. package/dist/_chunks/prepare.mjs +14 -9
  53. package/dist/_chunks/prepare.mjs.map +1 -1
  54. package/dist/_chunks/prepare2.mjs +1 -19
  55. package/dist/_chunks/prepare2.mjs.map +1 -1
  56. package/dist/_chunks/prompts.mjs +6 -201
  57. package/dist/_chunks/prompts.mjs.map +1 -1
  58. package/dist/_chunks/retriv.mjs +23 -24
  59. package/dist/_chunks/retriv.mjs.map +1 -1
  60. package/dist/_chunks/rolldown-runtime.mjs +0 -2
  61. package/dist/_chunks/sanitize.mjs +0 -78
  62. package/dist/_chunks/sanitize.mjs.map +1 -1
  63. package/dist/_chunks/search-helpers.mjs +99 -0
  64. package/dist/_chunks/search-helpers.mjs.map +1 -0
  65. package/dist/_chunks/search-interactive.mjs +1 -18
  66. package/dist/_chunks/search-interactive.mjs.map +1 -1
  67. package/dist/_chunks/search.mjs +218 -19
  68. package/dist/_chunks/search.mjs.map +1 -0
  69. package/dist/_chunks/setup.mjs +0 -13
  70. package/dist/_chunks/setup.mjs.map +1 -1
  71. package/dist/_chunks/shared.mjs +1 -473
  72. package/dist/_chunks/shared.mjs.map +1 -1
  73. package/dist/_chunks/skills.mjs +3 -3
  74. package/dist/_chunks/skills.mjs.map +1 -1
  75. package/dist/_chunks/sources.mjs +1179 -1440
  76. package/dist/_chunks/sources.mjs.map +1 -1
  77. package/dist/_chunks/sync-registry.mjs +59 -0
  78. package/dist/_chunks/sync-registry.mjs.map +1 -0
  79. package/dist/_chunks/sync-shared.mjs +0 -16
  80. package/dist/_chunks/sync-shared2.mjs +10 -49
  81. package/dist/_chunks/sync-shared2.mjs.map +1 -1
  82. package/dist/_chunks/sync.mjs +209 -120
  83. package/dist/_chunks/sync.mjs.map +1 -1
  84. package/dist/_chunks/sync2.mjs +1 -21
  85. package/dist/_chunks/types.d.mts +0 -2
  86. package/dist/_chunks/types.d.mts.map +1 -1
  87. package/dist/_chunks/uninstall.mjs +3 -27
  88. package/dist/_chunks/uninstall.mjs.map +1 -1
  89. package/dist/_chunks/upload.mjs +152 -0
  90. package/dist/_chunks/upload.mjs.map +1 -0
  91. package/dist/_chunks/validate.mjs +1 -8
  92. package/dist/_chunks/validate.mjs.map +1 -1
  93. package/dist/_chunks/version.mjs +30 -0
  94. package/dist/_chunks/version.mjs.map +1 -0
  95. package/dist/_chunks/wizard.mjs +2 -3
  96. package/dist/_chunks/yaml.mjs +0 -21
  97. package/dist/_chunks/yaml.mjs.map +1 -1
  98. package/dist/agent/index.d.mts +0 -24
  99. package/dist/agent/index.d.mts.map +1 -1
  100. package/dist/agent/index.mjs +2 -9
  101. package/dist/cache/index.mjs +1 -3
  102. package/dist/cli-entry.mjs +0 -6
  103. package/dist/cli-entry.mjs.map +1 -1
  104. package/dist/cli.mjs +48 -33
  105. package/dist/cli.mjs.map +1 -1
  106. package/dist/index.d.mts +1 -1
  107. package/dist/index.mjs +2 -8
  108. package/dist/prepare.mjs +0 -12
  109. package/dist/prepare.mjs.map +1 -1
  110. package/dist/retriv/index.mjs +0 -2
  111. package/dist/retriv/worker.d.mts +0 -3
  112. package/dist/retriv/worker.d.mts.map +1 -1
  113. package/dist/retriv/worker.mjs +0 -2
  114. package/dist/retriv/worker.mjs.map +1 -1
  115. package/dist/sources/index.d.mts +2 -2
  116. package/dist/sources/index.mjs +3 -7
  117. package/dist/types.d.mts +1 -1
  118. package/package.json +20 -21
  119. package/dist/_chunks/search2.mjs +0 -319
  120. package/dist/_chunks/search2.mjs.map +0 -1
@@ -1,8 +1,10 @@
1
- import { o as getCacheDir } from "./config.mjs";
1
+ import { t as getCacheDir } from "./version.mjs";
2
2
  import { join } from "pathe";
3
3
  import { existsSync, lstatSync, mkdirSync, readdirSync, rmSync, symlinkSync, unlinkSync } from "node:fs";
4
- //#region src/core/prepare.ts
5
- /** Resolve package directory: node_modules first, then global cache */
4
+ function toStorageName(name) {
5
+ if (name.startsWith("crate:")) return `@skilld-crate/${name.slice(6)}`;
6
+ return name;
7
+ }
6
8
  function resolvePkgDir(name, cwd, version) {
7
9
  const nodeModulesPath = join(cwd, "node_modules", name);
8
10
  if (existsSync(nodeModulesPath)) return nodeModulesPath;
@@ -12,18 +14,23 @@ function resolvePkgDir(name, cwd, version) {
12
14
  }
13
15
  return null;
14
16
  }
15
- /** Restore .skilld/pkg symlink to node_modules if broken */
16
17
  function restorePkgSymlink(skillsDir, name, info, cwd) {
17
18
  const refsDir = join(skillsDir, name, ".skilld");
18
19
  const pkgLink = join(refsDir, "pkg");
19
20
  if (!existsSync(join(skillsDir, name))) return;
20
- if (existsSync(pkgLink)) return;
21
- const pkgDir = resolvePkgDir(info.packageName || name, cwd, info.version);
21
+ try {
22
+ if (lstatSync(pkgLink).isSymbolicLink()) {
23
+ if (existsSync(pkgLink)) return;
24
+ unlinkSync(pkgLink);
25
+ } else return;
26
+ } catch (err) {
27
+ if (err.code !== "ENOENT") return;
28
+ }
29
+ const pkgDir = resolvePkgDir(toStorageName(info.packageName || name), cwd, info.version);
22
30
  if (!pkgDir) return;
23
31
  mkdirSync(refsDir, { recursive: true });
24
32
  symlinkSync(pkgDir, pkgLink);
25
33
  }
26
- /** Check if package ships a skills/ directory with SKILL.md or _SKILL.md subdirs */
27
34
  function getShippedSkills(name, cwd, version) {
28
35
  const pkgPath = resolvePkgDir(name, cwd, version);
29
36
  if (!pkgPath) return [];
@@ -34,7 +41,6 @@ function getShippedSkills(name, cwd, version) {
34
41
  skillDir: join(skillsPath, d.name)
35
42
  }));
36
43
  }
37
- /** Create symlink from skills dir to shipped skill dir */
38
44
  function linkShippedSkill(baseDir, skillName, targetDir) {
39
45
  const linkPath = join(baseDir, skillName);
40
46
  if (existsSync(linkPath)) if (lstatSync(linkPath).isSymbolicLink()) unlinkSync(linkPath);
@@ -44,7 +50,6 @@ function linkShippedSkill(baseDir, skillName, targetDir) {
44
50
  });
45
51
  symlinkSync(targetDir, linkPath);
46
52
  }
47
- //#endregion
48
53
  export { restorePkgSymlink as i, linkShippedSkill as n, resolvePkgDir as r, getShippedSkills as t };
49
54
 
50
55
  //# sourceMappingURL=prepare.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.mjs","names":[],"sources":["../../src/core/prepare.ts"],"sourcesContent":["/**\n * Shared prepare utilities used by both the fast entry (src/prepare.ts)\n * and the full CLI command (src/commands/prepare.ts).\n *\n * Keep this module lightweight: no imports from agent/, cache/storage.ts,\n * or any module that pulls in sanitize/clack/citty.\n */\n\nimport type { SkillInfo } from './lockfile.ts'\nimport { existsSync, lstatSync, mkdirSync, readdirSync, rmSync, symlinkSync, unlinkSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { getCacheDir } from '../cache/version.ts'\n\n/** Resolve package directory: node_modules first, then global cache */\nexport function resolvePkgDir(name: string, cwd: string, version?: string): string | null {\n const nodeModulesPath = join(cwd, 'node_modules', name)\n if (existsSync(nodeModulesPath))\n return nodeModulesPath\n\n if (version) {\n const cachedPkgDir = join(getCacheDir(name, version), 'pkg')\n if (existsSync(join(cachedPkgDir, 'package.json')))\n return cachedPkgDir\n }\n\n return null\n}\n\n/** Restore .skilld/pkg symlink to node_modules if broken */\nexport function restorePkgSymlink(skillsDir: string, name: string, info: SkillInfo, cwd: string): void {\n const refsDir = join(skillsDir, name, '.skilld')\n const pkgLink = join(refsDir, 'pkg')\n\n if (!existsSync(join(skillsDir, name)))\n return\n\n if (existsSync(pkgLink))\n return\n\n const pkgName = info.packageName || name\n const pkgDir = resolvePkgDir(pkgName, cwd, info.version)\n if (!pkgDir)\n return\n\n mkdirSync(refsDir, { recursive: true })\n symlinkSync(pkgDir, pkgLink)\n}\n\nexport interface ShippedSkill {\n skillName: string\n skillDir: string\n}\n\n/** Check if package ships a skills/ directory with SKILL.md or _SKILL.md subdirs */\nexport function getShippedSkills(name: string, cwd: string, version?: string): ShippedSkill[] {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return []\n\n const skillsPath = join(pkgPath, 'skills')\n if (!existsSync(skillsPath))\n return []\n\n return readdirSync(skillsPath, { withFileTypes: true })\n .filter(d => d.isDirectory() && (existsSync(join(skillsPath, d.name, 'SKILL.md')) || existsSync(join(skillsPath, d.name, '_SKILL.md'))))\n .map(d => ({ skillName: d.name, skillDir: join(skillsPath, d.name) }))\n}\n\n/** Create symlink from skills dir to shipped skill dir */\nexport function linkShippedSkill(baseDir: string, skillName: string, targetDir: string): void {\n const linkPath = join(baseDir, skillName)\n if (existsSync(linkPath)) {\n const stat = lstatSync(linkPath)\n if (stat.isSymbolicLink())\n unlinkSync(linkPath)\n else rmSync(linkPath, { recursive: true, force: true })\n }\n symlinkSync(targetDir, linkPath)\n}\n"],"mappings":";;;;;AAcA,SAAgB,cAAc,MAAc,KAAa,SAAiC;CACxF,MAAM,kBAAkB,KAAK,KAAK,gBAAgB,KAAK;AACvD,KAAI,WAAW,gBAAgB,CAC7B,QAAO;AAET,KAAI,SAAS;EACX,MAAM,eAAe,KAAK,YAAY,MAAM,QAAQ,EAAE,MAAM;AAC5D,MAAI,WAAW,KAAK,cAAc,eAAe,CAAC,CAChD,QAAO;;AAGX,QAAO;;;AAIT,SAAgB,kBAAkB,WAAmB,MAAc,MAAiB,KAAmB;CACrG,MAAM,UAAU,KAAK,WAAW,MAAM,UAAU;CAChD,MAAM,UAAU,KAAK,SAAS,MAAM;AAEpC,KAAI,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,CACpC;AAEF,KAAI,WAAW,QAAQ,CACrB;CAGF,MAAM,SAAS,cADC,KAAK,eAAe,MACE,KAAK,KAAK,QAAQ;AACxD,KAAI,CAAC,OACH;AAEF,WAAU,SAAS,EAAE,WAAW,MAAM,CAAC;AACvC,aAAY,QAAQ,QAAQ;;;AAS9B,SAAgB,iBAAiB,MAAc,KAAa,SAAkC;CAC5F,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;AACjD,KAAI,CAAC,QACH,QAAO,EAAE;CAEX,MAAM,aAAa,KAAK,SAAS,SAAS;AAC1C,KAAI,CAAC,WAAW,WAAW,CACzB,QAAO,EAAE;AAEX,QAAO,YAAY,YAAY,EAAE,eAAe,MAAM,CAAC,CACpD,QAAO,MAAK,EAAE,aAAa,KAAK,WAAW,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC,IAAI,WAAW,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC,EAAE,CACvI,KAAI,OAAM;EAAE,WAAW,EAAE;EAAM,UAAU,KAAK,YAAY,EAAE,KAAA;EAAO,EAAE;;;AAI1E,SAAgB,iBAAiB,SAAiB,WAAmB,WAAyB;CAC5F,MAAM,WAAW,KAAK,SAAS,UAAU;AACzC,KAAI,WAAW,SAAS,CAEtB,KADa,UAAU,SAAS,CACvB,gBAAgB,CACvB,YAAW,SAAS;KACjB,QAAO,UAAU;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEzD,aAAY,WAAW,SAAS"}
1
+ {"version":3,"file":"prepare.mjs","names":[],"sources":["../../src/core/prepare.ts"],"sourcesContent":["/**\n * Shared prepare utilities used by both the fast entry (src/prepare.ts)\n * and the full CLI command (src/commands/prepare.ts).\n *\n * Keep this module lightweight: no imports from agent/, cache/storage.ts,\n * or any module that pulls in sanitize/clack/citty.\n */\n\nimport type { SkillInfo } from './lockfile.ts'\nimport { existsSync, lstatSync, mkdirSync, readdirSync, rmSync, symlinkSync, unlinkSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { getCacheDir } from '../cache/version.ts'\n\n/** Map lockfile identity name to storage-safe cache key (crate:X → @skilld-crate/X) */\nfunction toStorageName(name: string): string {\n if (name.startsWith('crate:'))\n return `@skilld-crate/${name.slice('crate:'.length)}`\n return name\n}\n\n/** Resolve package directory: node_modules first, then global cache */\nexport function resolvePkgDir(name: string, cwd: string, version?: string): string | null {\n const nodeModulesPath = join(cwd, 'node_modules', name)\n if (existsSync(nodeModulesPath))\n return nodeModulesPath\n\n if (version) {\n const cachedPkgDir = join(getCacheDir(name, version), 'pkg')\n if (existsSync(join(cachedPkgDir, 'package.json')))\n return cachedPkgDir\n }\n\n return null\n}\n\n/** Restore .skilld/pkg symlink to node_modules if broken */\nexport function restorePkgSymlink(skillsDir: string, name: string, info: SkillInfo, cwd: string): void {\n const refsDir = join(skillsDir, name, '.skilld')\n const pkgLink = join(refsDir, 'pkg')\n\n if (!existsSync(join(skillsDir, name)))\n return\n\n // Use lstatSync to detect dangling symlinks — existsSync follows symlinks\n // and returns false for dangling ones, causing symlinkSync to throw EEXIST\n try {\n const stat = lstatSync(pkgLink)\n if (stat.isSymbolicLink()) {\n if (existsSync(pkgLink))\n return // symlink exists and target is valid\n unlinkSync(pkgLink) // dangling symlink — remove before re-creating\n }\n else {\n return // real file/dir exists at this path\n }\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT')\n return // permission/IO error — bail instead of masking\n }\n\n const pkgName = toStorageName(info.packageName || name)\n const pkgDir = resolvePkgDir(pkgName, cwd, info.version)\n if (!pkgDir)\n return\n\n mkdirSync(refsDir, { recursive: true })\n symlinkSync(pkgDir, pkgLink)\n}\n\nexport interface ShippedSkill {\n skillName: string\n skillDir: string\n}\n\n/** Check if package ships a skills/ directory with SKILL.md or _SKILL.md subdirs */\nexport function getShippedSkills(name: string, cwd: string, version?: string): ShippedSkill[] {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return []\n\n const skillsPath = join(pkgPath, 'skills')\n if (!existsSync(skillsPath))\n return []\n\n return readdirSync(skillsPath, { withFileTypes: true })\n .filter(d => d.isDirectory() && (existsSync(join(skillsPath, d.name, 'SKILL.md')) || existsSync(join(skillsPath, d.name, '_SKILL.md'))))\n .map(d => ({ skillName: d.name, skillDir: join(skillsPath, d.name) }))\n}\n\n/** Create symlink from skills dir to shipped skill dir */\nexport function linkShippedSkill(baseDir: string, skillName: string, targetDir: string): void {\n const linkPath = join(baseDir, skillName)\n if (existsSync(linkPath)) {\n const stat = lstatSync(linkPath)\n if (stat.isSymbolicLink())\n unlinkSync(linkPath)\n else rmSync(linkPath, { recursive: true, force: true })\n }\n symlinkSync(targetDir, linkPath)\n}\n"],"mappings":";;;AAcA,SAAS,cAAc,MAAsB;AAC3C,KAAI,KAAK,WAAW,SAAS,CAC3B,QAAO,iBAAiB,KAAK,MAAM,EAAgB;AACrD,QAAO;;AAIT,SAAgB,cAAc,MAAc,KAAa,SAAiC;CACxF,MAAM,kBAAkB,KAAK,KAAK,gBAAgB,KAAK;AACvD,KAAI,WAAW,gBAAgB,CAC7B,QAAO;AAET,KAAI,SAAS;EACX,MAAM,eAAe,KAAK,YAAY,MAAM,QAAQ,EAAE,MAAM;AAC5D,MAAI,WAAW,KAAK,cAAc,eAAe,CAAC,CAChD,QAAO;;AAGX,QAAO;;AAIT,SAAgB,kBAAkB,WAAmB,MAAc,MAAiB,KAAmB;CACrG,MAAM,UAAU,KAAK,WAAW,MAAM,UAAU;CAChD,MAAM,UAAU,KAAK,SAAS,MAAM;AAEpC,KAAI,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,CACpC;AAIF,KAAI;AAEF,MADa,UAAU,QAAQ,CACtB,gBAAgB,EAAE;AACzB,OAAI,WAAW,QAAQ,CACrB;AACF,cAAW,QAAQ;QAGnB;UAGG,KAAK;AACV,MAAK,IAA8B,SAAS,SAC1C;;CAIJ,MAAM,SAAS,cADC,cAAc,KAAK,eAAe,KAAK,EACjB,KAAK,KAAK,QAAQ;AACxD,KAAI,CAAC,OACH;AAEF,WAAU,SAAS,EAAE,WAAW,MAAM,CAAC;AACvC,aAAY,QAAQ,QAAQ;;AAS9B,SAAgB,iBAAiB,MAAc,KAAa,SAAkC;CAC5F,MAAM,UAAU,cAAc,MAAM,KAAK,QAAQ;AACjD,KAAI,CAAC,QACH,QAAO,EAAE;CAEX,MAAM,aAAa,KAAK,SAAS,SAAS;AAC1C,KAAI,CAAC,WAAW,WAAW,CACzB,QAAO,EAAE;AAEX,QAAO,YAAY,YAAY,EAAE,eAAe,MAAM,CAAC,CACpD,QAAO,MAAK,EAAE,aAAa,KAAK,WAAW,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC,IAAI,WAAW,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC,EAAE,CACvI,KAAI,OAAM;EAAE,WAAW,EAAE;EAAM,UAAU,KAAK,YAAY,EAAE,KAAA;EAAO,EAAE;;AAI1E,SAAgB,iBAAiB,SAAiB,WAAmB,WAAyB;CAC5F,MAAM,WAAW,KAAK,SAAS,UAAU;AACzC,KAAI,WAAW,SAAS,CAEtB,KADa,UAAU,SAAS,CACvB,gBAAgB,CACvB,YAAW,SAAS;KACjB,QAAO,UAAU;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEzD,aAAY,WAAW,SAAS"}
@@ -1,16 +1,8 @@
1
- import "./config.mjs";
2
- import "./package-json.mjs";
3
1
  import { i as restorePkgSymlink, n as linkShippedSkill, t as getShippedSkills } from "./prepare.mjs";
4
- import "./sanitize.mjs";
5
- import "./cache.mjs";
6
- import "./yaml.mjs";
7
- import "./markdown.mjs";
8
2
  import { n as getSharedSkillsDir } from "./shared.mjs";
9
- import "./sources.mjs";
10
3
  import { a as targets } from "./detect.mjs";
11
- import { i as linkSkillToAgents } from "./prompts.mjs";
4
+ import { r as linkSkillToAgents } from "./install.mjs";
12
5
  import "./agent.mjs";
13
- import "./libs/@sinclair/typebox.mjs";
14
6
  import { b as resolveAgent } from "./cli-helpers.mjs";
15
7
  import { i as readLock, s as writeLock } from "./lockfile.mjs";
16
8
  import { t as getProjectState } from "./skills.mjs";
@@ -18,15 +10,6 @@ import { join } from "pathe";
18
10
  import { existsSync, mkdirSync } from "node:fs";
19
11
  import * as p from "@clack/prompts";
20
12
  import { defineCommand } from "citty";
21
- //#region src/commands/prepare.ts
22
- /**
23
- * Prepare command — lightweight hook for package.json "prepare" script.
24
- *
25
- * Designed to run on every `pnpm install` / `npm install`. Blocking, fast, no LLM calls.
26
- * 1. Restore broken symlinks from lockfile (like `install` but skips doc fetching)
27
- * 2. Auto-install shipped skills from deps (just symlinks + lockfile writes)
28
- * 3. Report outdated skills count and suggest `skilld update`
29
- */
30
13
  const prepareCommandDef = defineCommand({
31
14
  meta: {
32
15
  name: "prepare",
@@ -89,7 +72,6 @@ const prepareCommandDef = defineCommand({
89
72
  }
90
73
  }
91
74
  });
92
- //#endregion
93
75
  export { prepareCommandDef };
94
76
 
95
77
  //# sourceMappingURL=prepare2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare2.mjs","names":["agents"],"sources":["../../src/commands/prepare.ts"],"sourcesContent":["/**\n * Prepare command — lightweight hook for package.json \"prepare\" script.\n *\n * Designed to run on every `pnpm install` / `npm install`. Blocking, fast, no LLM calls.\n * 1. Restore broken symlinks from lockfile (like `install` but skips doc fetching)\n * 2. Auto-install shipped skills from deps (just symlinks + lockfile writes)\n * 3. Report outdated skills count and suggest `skilld update`\n */\n\nimport { existsSync, mkdirSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { agents, linkSkillToAgents } from '../agent/index.ts'\nimport { resolveAgent } from '../cli-helpers.ts'\nimport { readLock, writeLock } from '../core/lockfile.ts'\nimport { getShippedSkills, linkShippedSkill, restorePkgSymlink } from '../core/prepare.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { getProjectState } from '../core/skills.ts'\n\nexport const prepareCommandDef = defineCommand({\n meta: { name: 'prepare', description: 'Restore references and sync shipped skills (for package.json hooks)' },\n args: {\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Target agent',\n },\n },\n async run({ args }) {\n const cwd = process.cwd()\n\n const agent = resolveAgent(args.agent)\n if (!agent || agent === 'none')\n return\n\n const agentConfig = agents[agent]\n const shared = getSharedSkillsDir(cwd)\n const skillsDir = shared || join(cwd, agentConfig.skillsDir)\n\n // ── Fast path: read primary lockfile, check all skills intact ──\n\n const lock = readLock(skillsDir)\n if (lock && Object.keys(lock.skills).length > 0) {\n let allIntact = true\n\n for (const [name, info] of Object.entries(lock.skills)) {\n if (!info.version)\n continue\n\n const skillDir = join(skillsDir, name)\n if (existsSync(skillDir)) {\n // Skill dir exists; for non-shipped, also check .skilld/pkg symlink\n if (info.source !== 'shipped')\n restorePkgSymlink(skillsDir, name, info, cwd)\n continue\n }\n\n // Skill dir missing, needs restore\n allIntact = false\n\n if (info.source === 'shipped') {\n const pkgName = info.packageName || name\n const shipped = getShippedSkills(pkgName, cwd, info.version)\n const match = shipped.find(s => s.skillName === name)\n if (match)\n linkShippedSkill(skillsDir, name, match.skillDir)\n }\n }\n\n // If all skills intact, skip expensive getProjectState entirely\n if (allIntact)\n return\n }\n\n // ── Slow path: discover new shipped skills + report outdated ──\n\n const state = await getProjectState(cwd)\n let shippedCount = 0\n\n if (state.shipped.length > 0) {\n mkdirSync(skillsDir, { recursive: true })\n\n for (const entry of state.shipped) {\n const version = state.deps.get(entry.packageName)?.replace(/^[\\^~>=<]+/, '') || '0.0.0'\n\n for (const skill of entry.skills) {\n linkShippedSkill(skillsDir, skill.skillName, skill.skillDir)\n writeLock(skillsDir, skill.skillName, {\n packageName: entry.packageName,\n version,\n source: 'shipped',\n syncedAt: new Date().toISOString().split('T')[0],\n generator: 'skilld',\n })\n\n if (shared)\n linkSkillToAgents(skill.skillName, shared, cwd, agent)\n\n shippedCount++\n }\n }\n\n if (shippedCount > 0)\n p.log.success(`Installed ${shippedCount} shipped skill${shippedCount > 1 ? 's' : ''}`)\n }\n\n if (state.outdated.length > 0) {\n const n = state.outdated.length\n p.log.info(`${n} package${n > 1 ? 's' : ''} ha${n > 1 ? 've' : 's'} new features and/or breaking changes. Run \\`skilld update\\` to sync.`)\n }\n },\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,oBAAoB,cAAc;CAC7C,MAAM;EAAE,MAAM;EAAW,aAAa;EAAuE;CAC7G,MAAM,EACJ,OAAO;EACL,MAAM;EACN,SAAS,OAAO,KAAKA,QAAO;EAC5B,OAAO;EACP,aAAa;EACd,EACF;CACD,MAAM,IAAI,EAAE,QAAQ;EAClB,MAAM,MAAM,QAAQ,KAAK;EAEzB,MAAM,QAAQ,aAAa,KAAK,MAAM;AACtC,MAAI,CAAC,SAAS,UAAU,OACtB;EAEF,MAAM,cAAcA,QAAO;EAC3B,MAAM,SAAS,mBAAmB,IAAI;EACtC,MAAM,YAAY,UAAU,KAAK,KAAK,YAAY,UAAU;EAI5D,MAAM,OAAO,SAAS,UAAU;AAChC,MAAI,QAAQ,OAAO,KAAK,KAAK,OAAO,CAAC,SAAS,GAAG;GAC/C,IAAI,YAAY;AAEhB,QAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,OAAO,EAAE;AACtD,QAAI,CAAC,KAAK,QACR;AAGF,QAAI,WADa,KAAK,WAAW,KAAK,CACd,EAAE;AAExB,SAAI,KAAK,WAAW,UAClB,mBAAkB,WAAW,MAAM,MAAM,IAAI;AAC/C;;AAIF,gBAAY;AAEZ,QAAI,KAAK,WAAW,WAAW;KAG7B,MAAM,QADU,iBADA,KAAK,eAAe,MACM,KAAK,KAAK,QAAQ,CACtC,MAAK,MAAK,EAAE,cAAc,KAAK;AACrD,SAAI,MACF,kBAAiB,WAAW,MAAM,MAAM,SAAS;;;AAKvD,OAAI,UACF;;EAKJ,MAAM,QAAQ,MAAM,gBAAgB,IAAI;EACxC,IAAI,eAAe;AAEnB,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,aAAU,WAAW,EAAE,WAAW,MAAM,CAAC;AAEzC,QAAK,MAAM,SAAS,MAAM,SAAS;IACjC,MAAM,UAAU,MAAM,KAAK,IAAI,MAAM,YAAY,EAAE,QAAQ,cAAc,GAAG,IAAI;AAEhF,SAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,sBAAiB,WAAW,MAAM,WAAW,MAAM,SAAS;AAC5D,eAAU,WAAW,MAAM,WAAW;MACpC,aAAa,MAAM;MACnB;MACA,QAAQ;MACR,2BAAU,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,IAAI,CAAC;MAC9C,WAAW;MACZ,CAAC;AAEF,SAAI,OACF,mBAAkB,MAAM,WAAW,QAAQ,KAAK,MAAM;AAExD;;;AAIJ,OAAI,eAAe,EACjB,GAAE,IAAI,QAAQ,aAAa,aAAa,gBAAgB,eAAe,IAAI,MAAM,KAAK;;AAG1F,MAAI,MAAM,SAAS,SAAS,GAAG;GAC7B,MAAM,IAAI,MAAM,SAAS;AACzB,KAAE,IAAI,KAAK,GAAG,EAAE,UAAU,IAAI,IAAI,MAAM,GAAG,KAAK,IAAI,IAAI,OAAO,IAAI,uEAAuE;;;CAG/I,CAAC"}
1
+ {"version":3,"file":"prepare2.mjs","names":["agents"],"sources":["../../src/commands/prepare.ts"],"sourcesContent":["/**\n * Prepare command — lightweight hook for package.json \"prepare\" script.\n *\n * Designed to run on every `pnpm install` / `npm install`. Blocking, fast, no LLM calls.\n * 1. Restore broken symlinks from lockfile (like `install` but skips doc fetching)\n * 2. Auto-install shipped skills from deps (just symlinks + lockfile writes)\n * 3. Report outdated skills count and suggest `skilld update`\n */\n\nimport { existsSync, mkdirSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { agents, linkSkillToAgents } from '../agent/index.ts'\nimport { resolveAgent } from '../cli-helpers.ts'\nimport { readLock, writeLock } from '../core/lockfile.ts'\nimport { getShippedSkills, linkShippedSkill, restorePkgSymlink } from '../core/prepare.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { getProjectState } from '../core/skills.ts'\n\nexport const prepareCommandDef = defineCommand({\n meta: { name: 'prepare', description: 'Restore references and sync shipped skills (for package.json hooks)' },\n args: {\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Target agent',\n },\n },\n async run({ args }) {\n const cwd = process.cwd()\n\n const agent = resolveAgent(args.agent)\n if (!agent || agent === 'none')\n return\n\n const agentConfig = agents[agent]\n const shared = getSharedSkillsDir(cwd)\n const skillsDir = shared || join(cwd, agentConfig.skillsDir)\n\n // ── Fast path: read primary lockfile, check all skills intact ──\n\n const lock = readLock(skillsDir)\n if (lock && Object.keys(lock.skills).length > 0) {\n let allIntact = true\n\n for (const [name, info] of Object.entries(lock.skills)) {\n if (!info.version)\n continue\n\n const skillDir = join(skillsDir, name)\n if (existsSync(skillDir)) {\n // Skill dir exists; for non-shipped, also check .skilld/pkg symlink\n if (info.source !== 'shipped')\n restorePkgSymlink(skillsDir, name, info, cwd)\n continue\n }\n\n // Skill dir missing, needs restore\n allIntact = false\n\n if (info.source === 'shipped') {\n const pkgName = info.packageName || name\n const shipped = getShippedSkills(pkgName, cwd, info.version)\n const match = shipped.find(s => s.skillName === name)\n if (match)\n linkShippedSkill(skillsDir, name, match.skillDir)\n }\n }\n\n // If all skills intact, skip expensive getProjectState entirely\n if (allIntact)\n return\n }\n\n // ── Slow path: discover new shipped skills + report outdated ──\n\n const state = await getProjectState(cwd)\n let shippedCount = 0\n\n if (state.shipped.length > 0) {\n mkdirSync(skillsDir, { recursive: true })\n\n for (const entry of state.shipped) {\n const version = state.deps.get(entry.packageName)?.replace(/^[\\^~>=<]+/, '') || '0.0.0'\n\n for (const skill of entry.skills) {\n linkShippedSkill(skillsDir, skill.skillName, skill.skillDir)\n writeLock(skillsDir, skill.skillName, {\n packageName: entry.packageName,\n version,\n source: 'shipped',\n syncedAt: new Date().toISOString().split('T')[0],\n generator: 'skilld',\n })\n\n if (shared)\n linkSkillToAgents(skill.skillName, shared, cwd, agent)\n\n shippedCount++\n }\n }\n\n if (shippedCount > 0)\n p.log.success(`Installed ${shippedCount} shipped skill${shippedCount > 1 ? 's' : ''}`)\n }\n\n if (state.outdated.length > 0) {\n const n = state.outdated.length\n p.log.info(`${n} package${n > 1 ? 's' : ''} ha${n > 1 ? 've' : 's'} new features and/or breaking changes. Run \\`skilld update\\` to sync.`)\n }\n },\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAoBA,SAAa,OAAA,KAAA,QAAoB;EAC/B,OAAM;EAAE,aAAM;EAAW,EAAA;OAAoF,IAAA,EAAA,QAAA;EAC7G,MAAM,MACJ,QAAO,KAAA;EACL,MAAM,QAAA,aAAA,KAAA,MAAA;AACN,MAAA,CAAA,SAAS,UAAYA,OAAO;EAC5B,MAAA,cAAO,QAAA;EACP,MAAA,SAAa,mBAAA,IAAA;EACd,MACF,YAAA,UAAA,KAAA,KAAA,YAAA,UAAA;EACD,MAAM,OAAM,SAAQ,UAAA;AAClB,MAAA,QAAY,OAAA,KAAQ,KAAK,OAAA,CAAA,SAAA,GAAA;GAEzB,IAAA,YAAc;AACd,QAAK,MAAA,CAAA,MAAS,SAAU,OACtB,QAAA,KAAA,OAAA,EAAA;AAEF,QAAM,CAAA,KAAA,QAAcA;AACpB,QAAM,WAAS,KAAA,WAAA,KAAuB,CAAA,EAAA;AACtC,SAAM,KAAA,WAAY,UAAe,mBAAiB,WAAU,MAAA,MAAA,IAAA;AAI5D;;AAEE,gBAAI;AAEJ,QAAK,KAAA,WAAa,WAAS;KACzB,MAAK,QAAK,iBACR,KAAA,eAAA,MAAA,KAAA,KAAA,QAAA,CAAA,MAAA,MAAA,EAAA,cAAA,KAAA;AAGF,SAAI,MAAA,kBADkB,WACI,MAAA,MAAA,SAAA;;;;;EAU1B,MAAI,QAAK,MAAA,gBAAsB,IAAA;MAG7B,eADgB;AAEhB,MAAA,MAAI,QACF,SAAA,GAAA;;;IAKN,MAAI,UACF,MAAA,KAAA,IAAA,MAAA,YAAA,EAAA,QAAA,cAAA,GAAA,IAAA;;AAKJ,sBAAoB,WAAA,MAAgB,WAAI,MAAA,SAAA;AACxC,eAAI,WAAe,MAAA,WAAA;MAEf,aAAM,MAAQ;MAChB;MAEA,QAAW;MACT,2BAA2B,IAAI,MAAM,EAAA,aAAc,CAAA,MAAQ,IAAA,CAAA;MAE3D,WAAW;MACT,CAAA;AACA,SAAA,OAAU,mBAAiB,MAAA,WAAW,QAAA,KAAA,MAAA;;;;OAIpC,eAAA,EAAA,GAAA,IAAA,QAAc,aAAO,aAAoB,gBAAK,eAAA,IAAA,MAAA,KAAA;;MAE/C,MAAC,SAAA,SAAA,GAAA;GAEF,MAAI,IAAA,MACF,SAAA;AAEF,KAAA,IAAA,KAAA,GAAA,EAAA,UAAA,IAAA,IAAA,MAAA,GAAA,KAAA,IAAA,IAAA,OAAA,IAAA,uEAAA;;;CAIJ,CAAA;AAIF,SAAI"}
@@ -1,43 +1,24 @@
1
1
  import { n as sanitizeMarkdown, t as repairMarkdown } from "./sanitize.mjs";
2
2
  import { t as yamlEscape } from "./yaml.mjs";
3
- import { d as getFilePatterns, f as getPackageRules, i as resolveSkilldCommand } from "./shared.mjs";
4
- import { a as targets, t as detectInstalledAgents } from "./detect.mjs";
5
- import { dirname, join, relative } from "pathe";
6
- import { existsSync, lstatSync, mkdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
7
- //#region src/agent/prompts/optional/budget.ts
8
- /**
9
- * Dynamic budget allocation for skill sections.
10
- *
11
- * Total SKILL.md target is ~500 lines. Overhead (frontmatter, header, search, footer)
12
- * is subtracted to get the available body budget, which is divided among enabled sections.
13
- * When a package has many releases, budgets scale up.
14
- */
3
+ import { a as getPackageRules, i as getFilePatterns } from "./package-registry.mjs";
4
+ import { i as resolveSkilldCommand } from "./shared.mjs";
5
+ import { t as computeSkillDirName } from "./install.mjs";
6
+ import { dirname } from "pathe";
15
7
  const TOTAL_TARGET = 500;
16
8
  const DEFAULT_OVERHEAD = 30;
17
- /** Available body lines after overhead is subtracted */
18
9
  function remainingLines(overheadLines) {
19
10
  return TOTAL_TARGET - (overheadLines ?? DEFAULT_OVERHEAD);
20
11
  }
21
- /** Scale max lines based on enabled section count and available remaining space. */
22
12
  function maxLines(min, max, sectionCount, overheadLines) {
23
13
  const remaining = remainingLines(overheadLines);
24
- const sections = Math.max(1, sectionCount ?? 1);
25
- const perSection = Math.floor(remaining / sections);
14
+ const perSection = Math.floor(remaining / Math.max(1, sectionCount ?? 1));
26
15
  const scale = budgetScale(sectionCount);
27
16
  return Math.max(min, Math.min(Math.round(max * scale), perSection));
28
17
  }
29
- /** Scale item count based on enabled section count. */
30
18
  function maxItems(min, max, sectionCount) {
31
19
  const scale = budgetScale(sectionCount);
32
20
  return Math.max(min, Math.round(max * scale));
33
21
  }
34
- /**
35
- * Boost budget for high-churn packages based on API-level release density.
36
- * Combines major/minor release count with current minor version as a churn signal.
37
- *
38
- * @param significantReleases - Count of major/minor releases (patch releases excluded)
39
- * @param minorVersion - Current minor version number (e.g., 15 for v3.15.0)
40
- */
41
22
  function releaseBoost(significantReleases, minorVersion) {
42
23
  const combined = (!significantReleases ? 0 : significantReleases <= 5 ? 0 : significantReleases <= 15 ? 1 : 2) + (!minorVersion ? 0 : minorVersion <= 3 ? 0 : minorVersion <= 10 ? 1 : 2);
43
24
  if (combined <= 0) return 1;
@@ -50,41 +31,32 @@ function budgetScale(sectionCount) {
50
31
  if (sectionCount === 3) return .7;
51
32
  return .6;
52
33
  }
53
- //#endregion
54
- //#region src/agent/prompts/optional/validate.ts
55
- /** Warns if content exceeds 150% of max lines */
56
34
  function checkLineCount(content, max) {
57
35
  const lines = content.split("\n").length;
58
36
  if (lines > Math.round(max * 1.5)) return [{ warning: `Output ${lines} lines exceeds ${max} max by >50%` }];
59
37
  return [];
60
38
  }
61
- /** Warns if content is fewer than 3 lines */
62
39
  function checkSparseness(content) {
63
40
  const lines = content.split("\n").length;
64
41
  if (lines < 3) return [{ warning: `Output only ${lines} lines — likely too sparse` }];
65
42
  return [];
66
43
  }
67
- /** Warns if sourced/bullets ratio is below minRatio */
68
44
  function checkSourceCoverage(content, minRatio = .8) {
69
45
  const bullets = (content.match(/^- /gm) || []).length;
70
46
  const sourced = (content.match(/\[source\]/g) || []).length;
71
47
  if (bullets > 2 && sourced / bullets < minRatio) return [{ warning: `Only ${sourced}/${bullets} items have source citations (need ${Math.round(minRatio * 100)}% coverage)` }];
72
48
  return [];
73
49
  }
74
- /** Warns if source links are missing .skilld/ prefix */
75
50
  function checkSourcePaths(content) {
76
51
  const badPaths = content.match(/\[source\]\(\.\/(docs|issues|discussions|releases|pkg|guide)\//g);
77
52
  if (badPaths?.length) return [{ warning: `${badPaths.length} source links missing .skilld/ prefix` }];
78
53
  return [];
79
54
  }
80
- /** Warns if source links use absolute filesystem paths instead of relative ./.skilld/ paths */
81
55
  function checkAbsolutePaths(content) {
82
56
  const absPaths = content.match(/\[source\]\(\/[^)]+\)/g);
83
57
  if (absPaths?.length) return [{ warning: `${absPaths.length} source links use absolute paths — must use relative ./.skilld/ paths` }];
84
58
  return [];
85
59
  }
86
- //#endregion
87
- //#region src/agent/prompts/optional/api-changes.ts
88
60
  function apiChangesSection({ packageName, version, hasReleases, hasChangelog, hasDocs, hasIssues, hasDiscussions, pkgFiles, features, enabledSectionCount, releaseCount, overheadLines }) {
89
61
  const [, major, minor] = version?.match(/^(\d+)\.(\d+)/) ?? [];
90
62
  const boost = releaseBoost(releaseCount, minor ? Number(minor) : void 0);
@@ -207,8 +179,6 @@ Each item: BREAKING/DEPRECATED/NEW label + API name + what changed + source link
207
179
  ].filter(Boolean)
208
180
  };
209
181
  }
210
- //#endregion
211
- //#region src/agent/prompts/optional/best-practices.ts
212
182
  function bestPracticesSection({ packageName, hasIssues, hasDiscussions, hasReleases, hasChangelog, hasDocs, pkgFiles, features, enabledSectionCount, releaseCount, version, overheadLines }) {
213
183
  const [, , minor] = version?.match(/^(\d+)\.(\d+)/) ?? [];
214
184
  const boost = 1 + (releaseBoost(releaseCount, minor ? Number(minor) : void 0) - 1) * .5;
@@ -300,8 +270,6 @@ Each item: markdown list item (-) + ${packageName}-specific pattern + why it's p
300
270
  ]
301
271
  };
302
272
  }
303
- //#endregion
304
- //#region src/agent/prompts/optional/custom.ts
305
273
  function customSection({ heading, body }, enabledSectionCount, overheadLines) {
306
274
  const customMaxLines = maxLines(50, 80, enabledSectionCount, overheadLines);
307
275
  return {
@@ -324,25 +292,19 @@ Content addressing the user's instructions above, using concise examples and sou
324
292
  rules: [`- **Custom section "${heading}":** MAX ${customMaxLines} lines, use \`## ${heading}\` heading`]
325
293
  };
326
294
  }
327
- //#endregion
328
- //#region src/agent/prompts/prompt.ts
329
- /** Output file per section (inside .skilld/) */
330
295
  const SECTION_OUTPUT_FILES = {
331
296
  "best-practices": "_BEST_PRACTICES.md",
332
297
  "api-changes": "_API_CHANGES.md",
333
298
  "custom": "_CUSTOM.md"
334
299
  };
335
- /** Merge order for final SKILL.md body */
336
300
  const SECTION_MERGE_ORDER = [
337
301
  "api-changes",
338
302
  "best-practices",
339
303
  "custom"
340
304
  ];
341
- /** Wrap section content with HTML comment markers for targeted re-assembly */
342
305
  function wrapSection(section, content) {
343
306
  return `<!-- skilld:${section} -->\n${content}\n<!-- /skilld:${section} -->`;
344
307
  }
345
- /** Extract marker-delimited sections from existing SKILL.md */
346
308
  function extractMarkedSections(md) {
347
309
  const sections = /* @__PURE__ */ new Map();
348
310
  for (const section of SECTION_MERGE_ORDER) {
@@ -357,10 +319,6 @@ function extractMarkedSections(md) {
357
319
  }
358
320
  return sections;
359
321
  }
360
- /**
361
- * Group files by parent directory with counts
362
- * e.g. `/path/to/docs/api/ (15 .md files)`
363
- */
364
322
  function formatDocTree(files) {
365
323
  const dirs = /* @__PURE__ */ new Map();
366
324
  for (const f of files) {
@@ -390,7 +348,6 @@ Use \`${cmd} search "query" -p ${packageName}\` as your primary research tool
390
348
 
391
349
  ${table}`;
392
350
  }
393
- /** Shared preamble: Security, references table, Quality Principles, doc tree */
394
351
  function buildPreamble(opts) {
395
352
  const { packageName, skillDir, hasIssues, hasDiscussions, hasReleases, hasChangelog, docFiles, docsType = "docs", hasShippedDocs = false, versionContext } = opts;
396
353
  const docsSection = docFiles?.length ? `<external-docs>\n**Documentation** (use Read tool to explore):\n${formatDocTree(docFiles)}\n</external-docs>` : "";
@@ -424,19 +381,12 @@ function getSectionDef(section, ctx, customPrompt) {
424
381
  case "custom": return customPrompt ? customSection(customPrompt, ctx.enabledSectionCount, ctx.overheadLines) : null;
425
382
  }
426
383
  }
427
- /**
428
- * Get the validate function for a section using default context (validators use fixed thresholds).
429
- * Returns null if section has no validator.
430
- */
431
384
  function getSectionValidator(section) {
432
385
  return getSectionDef(section, { packageName: "" }, section === "custom" ? {
433
386
  heading: "Custom",
434
387
  body: ""
435
388
  } : void 0)?.validate ?? null;
436
389
  }
437
- /**
438
- * Build prompt for a single section
439
- */
440
390
  function buildSectionPrompt(opts) {
441
391
  const { packageName, hasIssues, hasDiscussions, hasReleases, hasChangelog, version, section, customPrompt, skillDir } = opts;
442
392
  const versionContext = version ? ` v${version}` : "";
@@ -502,9 +452,6 @@ Write your final output to the file \`${skillDir}/.skilld/${outputFile}\` using
502
452
  After writing, run \`${cmd} validate ${skillDir}/.skilld/${outputFile}\` and fix any warnings before finishing. If unavailable, use \`${fallbackCmd} validate ${skillDir}/.skilld/${outputFile}\`.
503
453
  `;
504
454
  }
505
- /**
506
- * Build prompts for all selected sections, sharing the computed preamble
507
- */
508
455
  function buildAllSectionPrompts(opts) {
509
456
  const result = /* @__PURE__ */ new Map();
510
457
  for (const section of opts.sections) {
@@ -517,14 +464,6 @@ function buildAllSectionPrompts(opts) {
517
464
  }
518
465
  return result;
519
466
  }
520
- /**
521
- * Transform an agent-specific prompt into a portable prompt for any LLM.
522
- * - Rewrites .skilld/ paths → ./references/
523
- * - Strips ## Output section (file-writing instructions)
524
- * - Strips skilld search/validate instructions
525
- * - Replaces tool-specific language with generic equivalents
526
- * - Strips agent-specific rules
527
- */
528
467
  function portabilizePrompt(prompt, section) {
529
468
  let out = prompt;
530
469
  out = out.replace(/`[^`]*\/\.skilld\//g, (m) => m.replace(/[^`]*\/\.skilld\//, "./references/"));
@@ -551,130 +490,6 @@ function portabilizePrompt(prompt, section) {
551
490
  out = out.replace(/\n{3,}/g, "\n\n");
552
491
  return out;
553
492
  }
554
- //#endregion
555
- //#region src/agent/install.ts
556
- /**
557
- * Sanitize skill name for filesystem
558
- */
559
- function sanitizeName(name) {
560
- return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
561
- }
562
- /**
563
- * Compute skill directory name from package name with -skilld suffix.
564
- * No collisions for monorepo packages (each gets a unique name).
565
- *
566
- * Examples:
567
- * vue → vue-skilld
568
- * @unhead/vue → unhead-vue-skilld
569
- * @unhead/react → unhead-react-skilld
570
- */
571
- function computeSkillDirName(packageName) {
572
- return `${sanitizeName(packageName)}-skilld`;
573
- }
574
- /**
575
- * Install a skill directly to agent skill directories.
576
- * When agents are explicitly specified, creates directories as needed.
577
- * When falling back to auto-detection, only writes to agents whose skills dir already exists.
578
- */
579
- function installSkillForAgents(skillName, skillContent, options = {}) {
580
- const isGlobal = options.global ?? false;
581
- const cwd = options.cwd || process.cwd();
582
- const sanitized = sanitizeName(skillName);
583
- const explicit = !!options.agents;
584
- const targetAgents = options.agents || detectInstalledAgents();
585
- const installed = [];
586
- const skipped = [];
587
- const paths = [];
588
- const writtenDirs = /* @__PURE__ */ new Set();
589
- for (const agentType of targetAgents) {
590
- const agent = targets[agentType];
591
- if (isGlobal && !agent.globalSkillsDir) {
592
- skipped.push({
593
- agent: agentType,
594
- reason: "no global support"
595
- });
596
- continue;
597
- }
598
- const baseDir = isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir);
599
- if (!explicit && !existsSync(baseDir)) {
600
- skipped.push({
601
- agent: agentType,
602
- reason: "skills dir not found"
603
- });
604
- continue;
605
- }
606
- if (isGlobal && (writtenDirs.has(baseDir) || agent.additionalSkillsDirs.some((d) => writtenDirs.has(d)))) {
607
- skipped.push({
608
- agent: agentType,
609
- reason: "already covered by another agent dir"
610
- });
611
- continue;
612
- }
613
- const skillDir = join(baseDir, sanitized);
614
- const skilldDir = join(skillDir, ".skilld");
615
- mkdirSync(skilldDir, { recursive: true });
616
- writeFileSync(join(skilldDir, "_SKILL.md"), sanitizeMarkdown(repairMarkdown(skillContent)));
617
- if (options.files) for (const [filename, content] of Object.entries(options.files)) writeFileSync(join(skillDir, filename), filename.endsWith(".md") ? sanitizeMarkdown(repairMarkdown(content)) : content);
618
- installed.push(agentType);
619
- paths.push(skillDir);
620
- writtenDirs.add(baseDir);
621
- }
622
- return {
623
- installed,
624
- skipped,
625
- paths
626
- };
627
- }
628
- /**
629
- * Create a relative symlink from the target agent's skills dir to the shared .skills/ dir.
630
- * Only creates directories for the explicit target agent; other agents must already have
631
- * their skills dir present. This prevents skilld from polluting projects with dirs
632
- * for agents the user doesn't use (e.g. .gemini/, .agent/).
633
- */
634
- function linkSkillToAgents(skillName, sharedDir, cwd, agentType) {
635
- const targetAgents = agentType ? [[agentType, targets[agentType]]] : Object.entries(targets);
636
- const linkedDirs = /* @__PURE__ */ new Set();
637
- for (const [type, agent] of targetAgents) {
638
- const agentSkillsDir = join(cwd, agent.skillsDir);
639
- if (agentType === type) mkdirSync(agentSkillsDir, { recursive: true });
640
- else {
641
- if (!existsSync(agentSkillsDir)) continue;
642
- if (agent.additionalSkillsDirs.map((d) => join(cwd, d)).some((d) => linkedDirs.has(d))) {
643
- const staleTarget = join(agentSkillsDir, skillName);
644
- try {
645
- if (lstatSync(staleTarget).isSymbolicLink() && !existsSync(staleTarget)) unlinkSync(staleTarget);
646
- } catch {}
647
- continue;
648
- }
649
- }
650
- const target = join(agentSkillsDir, skillName);
651
- let isSymlink = false;
652
- let targetExists = false;
653
- try {
654
- const stat = lstatSync(target);
655
- targetExists = true;
656
- isSymlink = stat.isSymbolicLink();
657
- } catch {}
658
- if (targetExists && !isSymlink) continue;
659
- if (isSymlink) unlinkSync(target);
660
- symlinkSync(relative(agentSkillsDir, join(sharedDir, skillName)), target);
661
- linkedDirs.add(agentSkillsDir);
662
- }
663
- }
664
- /**
665
- * Remove per-agent symlinks for a skill when removing from shared dir.
666
- */
667
- function unlinkSkillFromAgents(skillName, cwd, agentType) {
668
- const targetAgents = agentType ? [[agentType, targets[agentType]]] : Object.entries(targets);
669
- for (const [, agent] of targetAgents) {
670
- const target = join(cwd, agent.skillsDir, skillName);
671
- try {
672
- if (lstatSync(target).isSymbolicLink()) unlinkSync(target);
673
- } catch {}
674
- }
675
- }
676
- //#endregion
677
- //#region src/agent/prompts/skill.ts
678
493
  function generateSkillMd(opts) {
679
494
  const header = generatePackageHeader(opts);
680
495
  const search = !opts.eject && opts.features?.search !== false ? generateSearchBlock(opts.name) : "";
@@ -687,7 +502,6 @@ function generateSkillMd(opts) {
687
502
  const footer = generateFooter(opts.relatedSkills);
688
503
  return sanitizeMarkdown(repairMarkdown(`${generateFrontmatter(opts)}${content}\n${footer}`));
689
504
  }
690
- /** Format ISO date as short absolute date: "Jan 2025", "Dec 2024" */
691
505
  function formatShortDate(isoDate) {
692
506
  const date = new Date(isoDate);
693
507
  if (Number.isNaN(date.getTime())) return "";
@@ -739,10 +553,6 @@ function generatePackageHeader({ name, version, distTags, repoUrl, hasIssues, ha
739
553
  if (refs.length > 0) lines.push(`**References:** ${refs.join(" • ")}`);
740
554
  return lines.join("\n");
741
555
  }
742
- /**
743
- * Expand a package name into keyword variants for better trigger matching.
744
- * e.g. "@nuxt/ui" → ["nuxt ui", "nuxt/ui"], "vue-router" → ["vue router"]
745
- */
746
556
  function expandPackageName(name) {
747
557
  const variants = /* @__PURE__ */ new Set();
748
558
  const unscoped = name.replace(/^@/, "");
@@ -757,10 +567,6 @@ function expandPackageName(name) {
757
567
  variants.delete(name);
758
568
  return [...variants];
759
569
  }
760
- /**
761
- * Extract and expand GitHub repo name into keyword variants.
762
- * e.g. "motion-v" → ["motion-v", "motion v"]
763
- */
764
570
  function expandRepoName(repoUrl) {
765
571
  const variants = /* @__PURE__ */ new Set();
766
572
  const repoName = repoUrl.startsWith("http") ? repoUrl.split("/").pop() : repoUrl.split("/").pop();
@@ -820,7 +626,6 @@ function generateFooter(relatedSkills) {
820
626
  if (relatedSkills.length === 0) return "";
821
627
  return `\nRelated: ${relatedSkills.join(", ")}\n`;
822
628
  }
823
- //#endregion
824
- export { sanitizeName as a, SECTION_OUTPUT_FILES as c, extractMarkedSections as d, getSectionValidator as f, maxLines as g, maxItems as h, linkSkillToAgents as i, buildAllSectionPrompts as l, wrapSection as m, computeSkillDirName as n, unlinkSkillFromAgents as o, portabilizePrompt as p, installSkillForAgents as r, SECTION_MERGE_ORDER as s, generateSkillMd as t, buildSectionPrompt as u };
629
+ export { buildSectionPrompt as a, portabilizePrompt as c, maxLines as d, buildAllSectionPrompts as i, wrapSection as l, SECTION_MERGE_ORDER as n, extractMarkedSections as o, SECTION_OUTPUT_FILES as r, getSectionValidator as s, generateSkillMd as t, maxItems as u };
825
630
 
826
631
  //# sourceMappingURL=prompts.mjs.map