skilld 1.7.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/_chunks/add.mjs +66 -0
  2. package/dist/_chunks/add.mjs.map +1 -0
  3. package/dist/_chunks/agent-prompt.mjs +88 -0
  4. package/dist/_chunks/agent-prompt.mjs.map +1 -0
  5. package/dist/_chunks/agent.mjs +737 -619
  6. package/dist/_chunks/agent.mjs.map +1 -1
  7. package/dist/_chunks/args.mjs +42 -0
  8. package/dist/_chunks/args.mjs.map +1 -0
  9. package/dist/_chunks/assemble.mjs +11 -8
  10. package/dist/_chunks/assemble.mjs.map +1 -1
  11. package/dist/_chunks/author.mjs +77 -131
  12. package/dist/_chunks/author.mjs.map +1 -1
  13. package/dist/_chunks/cache.mjs +320 -54
  14. package/dist/_chunks/cache.mjs.map +1 -1
  15. package/dist/_chunks/cache2.mjs +7 -6
  16. package/dist/_chunks/cache2.mjs.map +1 -1
  17. package/dist/_chunks/client.mjs +117 -0
  18. package/dist/_chunks/client.mjs.map +1 -0
  19. package/dist/_chunks/core.mjs +7 -4
  20. package/dist/_chunks/detect.mjs +54 -44
  21. package/dist/_chunks/detect.mjs.map +1 -1
  22. package/dist/_chunks/eject.mjs +69 -0
  23. package/dist/_chunks/eject.mjs.map +1 -0
  24. package/dist/_chunks/embedding-cache2.mjs +2 -2
  25. package/dist/_chunks/env.mjs +19 -0
  26. package/dist/_chunks/env.mjs.map +1 -0
  27. package/dist/_chunks/install-many.mjs +376 -0
  28. package/dist/_chunks/install-many.mjs.map +1 -0
  29. package/dist/_chunks/install.mjs +86 -371
  30. package/dist/_chunks/install.mjs.map +1 -1
  31. package/dist/_chunks/intro.mjs +63 -0
  32. package/dist/_chunks/intro.mjs.map +1 -0
  33. package/dist/_chunks/list.mjs +2 -2
  34. package/dist/_chunks/list.mjs.map +1 -1
  35. package/dist/_chunks/lockfile.mjs +31 -7
  36. package/dist/_chunks/lockfile.mjs.map +1 -1
  37. package/dist/_chunks/login.mjs +233 -0
  38. package/dist/_chunks/login.mjs.map +1 -0
  39. package/dist/_chunks/logout.mjs +27 -0
  40. package/dist/_chunks/logout.mjs.map +1 -0
  41. package/dist/_chunks/map.mjs +11 -0
  42. package/dist/_chunks/map.mjs.map +1 -0
  43. package/dist/_chunks/markdown.mjs +79 -54
  44. package/dist/_chunks/markdown.mjs.map +1 -1
  45. package/dist/_chunks/menu.mjs +33 -0
  46. package/dist/_chunks/menu.mjs.map +1 -0
  47. package/dist/_chunks/model-picker.mjs +61 -0
  48. package/dist/_chunks/model-picker.mjs.map +1 -0
  49. package/dist/_chunks/monorepo.mjs +73 -0
  50. package/dist/_chunks/monorepo.mjs.map +1 -0
  51. package/dist/_chunks/package-json.mjs.map +1 -1
  52. package/dist/_chunks/paths.mjs +47 -0
  53. package/dist/_chunks/paths.mjs.map +1 -0
  54. package/dist/_chunks/pipeline.mjs +985 -0
  55. package/dist/_chunks/pipeline.mjs.map +1 -0
  56. package/dist/_chunks/pool2.mjs +2 -2
  57. package/dist/_chunks/portable.mjs +151 -0
  58. package/dist/_chunks/portable.mjs.map +1 -0
  59. package/dist/_chunks/prepare-hook.mjs +2 -0
  60. package/dist/_chunks/prepare-hook2.mjs +61 -0
  61. package/dist/_chunks/prepare-hook2.mjs.map +1 -0
  62. package/dist/_chunks/prepare.mjs +47 -3
  63. package/dist/_chunks/prepare.mjs.map +1 -1
  64. package/dist/_chunks/prepare2.mjs +9 -8
  65. package/dist/_chunks/prepare2.mjs.map +1 -1
  66. package/dist/_chunks/prompts.mjs +784 -26
  67. package/dist/_chunks/prompts.mjs.map +1 -1
  68. package/dist/_chunks/pull.mjs +219 -0
  69. package/dist/_chunks/pull.mjs.map +1 -0
  70. package/dist/_chunks/regex.mjs +19 -0
  71. package/dist/_chunks/regex.mjs.map +1 -0
  72. package/dist/_chunks/retriv.mjs +2 -171
  73. package/dist/_chunks/retriv2.mjs +159 -0
  74. package/dist/_chunks/retriv2.mjs.map +1 -0
  75. package/dist/_chunks/sanitize.mjs +12 -9
  76. package/dist/_chunks/sanitize.mjs.map +1 -1
  77. package/dist/_chunks/search-helpers.mjs +9 -8
  78. package/dist/_chunks/search-helpers.mjs.map +1 -1
  79. package/dist/_chunks/search-interactive.mjs +23 -20
  80. package/dist/_chunks/search-interactive.mjs.map +1 -1
  81. package/dist/_chunks/search.mjs +3 -4
  82. package/dist/_chunks/search.mjs.map +1 -1
  83. package/dist/_chunks/{sources.mjs → semver.mjs} +1128 -838
  84. package/dist/_chunks/semver.mjs.map +1 -0
  85. package/dist/_chunks/skill-installer.mjs +2 -0
  86. package/dist/_chunks/skill-installer2.mjs +154 -0
  87. package/dist/_chunks/skill-installer2.mjs.map +1 -0
  88. package/dist/_chunks/skills.mjs +12 -12
  89. package/dist/_chunks/skills.mjs.map +1 -1
  90. package/dist/_chunks/store.mjs +107 -0
  91. package/dist/_chunks/store.mjs.map +1 -0
  92. package/dist/_chunks/sync.mjs +761 -1349
  93. package/dist/_chunks/sync.mjs.map +1 -1
  94. package/dist/_chunks/sync2.mjs +2 -3
  95. package/dist/_chunks/telemetry.mjs +26 -0
  96. package/dist/_chunks/telemetry.mjs.map +1 -0
  97. package/dist/_chunks/uninstall.mjs +15 -13
  98. package/dist/_chunks/uninstall.mjs.map +1 -1
  99. package/dist/_chunks/update.mjs +171 -0
  100. package/dist/_chunks/update.mjs.map +1 -0
  101. package/dist/_chunks/upload.mjs +4 -4
  102. package/dist/_chunks/validate.mjs +1 -1
  103. package/dist/_chunks/version.mjs +16 -27
  104. package/dist/_chunks/version.mjs.map +1 -1
  105. package/dist/_chunks/whoami.mjs +21 -0
  106. package/dist/_chunks/whoami.mjs.map +1 -0
  107. package/dist/_chunks/wizard.mjs +2 -190
  108. package/dist/_chunks/wizard2.mjs +200 -0
  109. package/dist/_chunks/wizard2.mjs.map +1 -0
  110. package/dist/cli.mjs +77 -59
  111. package/dist/cli.mjs.map +1 -1
  112. package/dist/prepare.mjs +5 -4
  113. package/dist/prepare.mjs.map +1 -1
  114. package/dist/retriv/worker.d.mts +5 -1
  115. package/dist/retriv/worker.d.mts.map +1 -1
  116. package/dist/retriv/worker.mjs +1 -1
  117. package/package.json +20 -29
  118. package/dist/_chunks/author-group.mjs +0 -17
  119. package/dist/_chunks/author-group.mjs.map +0 -1
  120. package/dist/_chunks/cli-helpers.mjs +0 -335
  121. package/dist/_chunks/cli-helpers.mjs.map +0 -1
  122. package/dist/_chunks/cli-helpers2.mjs +0 -2
  123. package/dist/_chunks/config.mjs +0 -122
  124. package/dist/_chunks/config.mjs.map +0 -1
  125. package/dist/_chunks/index.d.mts +0 -151
  126. package/dist/_chunks/index.d.mts.map +0 -1
  127. package/dist/_chunks/index2.d.mts +0 -44
  128. package/dist/_chunks/index2.d.mts.map +0 -1
  129. package/dist/_chunks/index3.d.mts +0 -589
  130. package/dist/_chunks/index3.d.mts.map +0 -1
  131. package/dist/_chunks/prefix.mjs +0 -108
  132. package/dist/_chunks/prefix.mjs.map +0 -1
  133. package/dist/_chunks/retriv.mjs.map +0 -1
  134. package/dist/_chunks/setup.mjs +0 -17
  135. package/dist/_chunks/setup.mjs.map +0 -1
  136. package/dist/_chunks/shared.mjs +0 -503
  137. package/dist/_chunks/shared.mjs.map +0 -1
  138. package/dist/_chunks/skill.mjs +0 -329
  139. package/dist/_chunks/skill.mjs.map +0 -1
  140. package/dist/_chunks/sources.mjs.map +0 -1
  141. package/dist/_chunks/sync-registry.mjs +0 -59
  142. package/dist/_chunks/sync-registry.mjs.map +0 -1
  143. package/dist/_chunks/sync-shared.mjs +0 -2
  144. package/dist/_chunks/sync-shared2.mjs +0 -1020
  145. package/dist/_chunks/sync-shared2.mjs.map +0 -1
  146. package/dist/_chunks/types.d.mts +0 -88
  147. package/dist/_chunks/types.d.mts.map +0 -1
  148. package/dist/_chunks/wizard.mjs.map +0 -1
  149. package/dist/agent/index.d.mts +0 -346
  150. package/dist/agent/index.d.mts.map +0 -1
  151. package/dist/agent/index.mjs +0 -5
  152. package/dist/cache/index.d.mts +0 -2
  153. package/dist/cache/index.mjs +0 -4
  154. package/dist/index.d.mts +0 -5
  155. package/dist/index.mjs +0 -5
  156. package/dist/retriv/index.d.mts +0 -3
  157. package/dist/retriv/index.mjs +0 -2
  158. package/dist/sources/index.d.mts +0 -2
  159. package/dist/sources/index.mjs +0 -3
  160. package/dist/types.d.mts +0 -4
  161. package/dist/types.mjs +0 -1
@@ -1,10 +1,13 @@
1
- import { n as cleanSectionOutput } from "./agent.mjs";
2
- import { a as extractMarkedSections, c as wrapSection, n as SECTION_OUTPUT_FILES, o as getSectionValidator, t as SECTION_MERGE_ORDER } from "./prompts.mjs";
1
+ import { s as cleanSectionOutput } from "./agent.mjs";
2
+ import { C as SECTION_OUTPUT_FILES, S as SECTION_MERGE_ORDER, v as extractMarkedSections, x as wrapSection, y as getSectionValidator } from "./prompts.mjs";
3
+ import { d as SECTION_HEADING_RE, p as SOURCE_LINK_RE, t as API_CHANGE_BULLET_RE } from "./regex.mjs";
3
4
  import { i as iterateSkills } from "./skills.mjs";
4
- import { join, relative, resolve } from "pathe";
5
5
  import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
6
+ import { styleText } from "node:util";
6
7
  import * as p from "@clack/prompts";
7
8
  import { defineCommand } from "citty";
9
+ import { join, relative, resolve } from "pathe";
10
+ const STATIC_REGEX_4 = /^## .+$/m;
8
11
  const OUTPUT_FILE_SET = new Set(Object.values(SECTION_OUTPUT_FILES));
9
12
  function discoverSkillDirsWithOutputs() {
10
13
  const dirs = [];
@@ -49,9 +52,9 @@ function assembleDir(targetDir, cwd) {
49
52
  const cleaned = cleanSectionOutput(raw);
50
53
  if (!cleaned) {
51
54
  const missing = [];
52
- if (!/^##\s/m.test(raw)) missing.push("h2 heading (## ...)");
53
- if (!/^- (?:BREAKING|DEPRECATED|NEW): /m.test(raw)) missing.push("change label (- BREAKING/DEPRECATED/NEW: ...)");
54
- if (!/\[source\]/.test(raw)) missing.push("[source] link");
55
+ if (!SECTION_HEADING_RE.test(raw)) missing.push("h2 heading (## ...)");
56
+ if (!API_CHANGE_BULLET_RE.test(raw)) missing.push("change label (- BREAKING/DEPRECATED/NEW: ...)");
57
+ if (!SOURCE_LINK_RE.test(raw)) missing.push("[source] link");
55
58
  p.log.warn(`${outputFile}: content rejected — missing ${missing.join(", ")}`);
56
59
  continue;
57
60
  }
@@ -67,7 +70,7 @@ function assembleDir(targetDir, cwd) {
67
70
  p.log.warn(`No section output files in ${relative(cwd, targetDir)}. Expected: ${Object.values(SECTION_OUTPUT_FILES).join(", ")}`);
68
71
  return;
69
72
  }
70
- for (const w of warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
73
+ for (const w of warnings) p.log.warn(styleText("yellow", w));
71
74
  const wrappedSections = [];
72
75
  for (const section of SECTION_MERGE_ORDER) {
73
76
  const result = sections.find((s) => s.section === section);
@@ -91,7 +94,7 @@ function assembleDir(targetDir, cwd) {
91
94
  const body = wrappedSections.map((s) => s.wrapped).join("\n\n");
92
95
  const fmEnd = existingSkillMd.indexOf("\n---\n", 4);
93
96
  const afterFm = fmEnd !== -1 ? existingSkillMd.slice(fmEnd + 5) : existingSkillMd;
94
- const firstLlmHeading = body.match(/^## .+$/m)?.[0];
97
+ const firstLlmHeading = body.match(STATIC_REGEX_4)?.[0];
95
98
  let headerPart = afterFm;
96
99
  if (firstLlmHeading) {
97
100
  const idx = afterFm.indexOf(firstLlmHeading);
@@ -1 +1 @@
1
- {"version":3,"file":"assemble.mjs","names":[],"sources":["../../src/commands/assemble.ts"],"sourcesContent":["/**\n * `skilld assemble` — merge pasted LLM output back into SKILL.md\n *\n * Auto-discovers skill directories with pending output files when run without arguments.\n */\n\nimport type { SkillSection } from '../agent/index.ts'\nimport { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join, relative, resolve } from 'pathe'\nimport { cleanSectionOutput } from '../agent/clis/index.ts'\nimport {\n extractMarkedSections,\n getSectionValidator,\n SECTION_MERGE_ORDER,\n SECTION_OUTPUT_FILES,\n wrapSection,\n} from '../agent/index.ts'\nimport { iterateSkills } from '../core/skills.ts'\n\nconst OUTPUT_FILE_SET = new Set(Object.values(SECTION_OUTPUT_FILES))\n\n/**\n * Find installed skill dirs that have pending section output files.\n */\nfunction discoverSkillDirsWithOutputs(): string[] {\n const dirs: string[] = []\n for (const skill of iterateSkills({})) {\n if (readdirSync(skill.dir).some(f => OUTPUT_FILE_SET.has(f)))\n dirs.push(skill.dir)\n }\n return dirs\n}\n\nexport async function assembleCommand(dir: string | undefined): Promise<void> {\n const cwd = process.cwd()\n\n let dirs: string[]\n if (dir) {\n dirs = [resolve(cwd, dir)]\n }\n else {\n // Check cwd first — if it has SKILL.md + output files, use it\n if (existsSync(join(cwd, 'SKILL.md'))\n && readdirSync(cwd).some(f => OUTPUT_FILE_SET.has(f))) {\n dirs = [cwd]\n }\n else {\n dirs = discoverSkillDirsWithOutputs()\n if (dirs.length === 0) {\n p.log.error('No skill directories with output files found. Run `skilld add` first.')\n return\n }\n }\n }\n\n for (const targetDir of dirs)\n assembleDir(targetDir, cwd)\n}\n\nfunction assembleDir(targetDir: string, cwd: string): void {\n if (!existsSync(targetDir)) {\n p.log.error(`Directory not found: ${targetDir}`)\n return\n }\n\n const skillMdPath = join(targetDir, 'SKILL.md')\n if (!existsSync(skillMdPath)) {\n p.log.error(`No SKILL.md found in ${targetDir}`)\n return\n }\n\n const existingSkillMd = readFileSync(skillMdPath, 'utf-8')\n\n // Find and read section output files\n const sections: Array<{ section: SkillSection, content: string }> = []\n const warnings: string[] = []\n\n for (const [section, outputFile] of Object.entries(SECTION_OUTPUT_FILES) as Array<[SkillSection, string]>) {\n const filePath = join(targetDir, outputFile)\n if (!existsSync(filePath))\n continue\n\n const raw = readFileSync(filePath, 'utf-8').trim()\n if (!raw) {\n p.log.warn(`Empty file: ${outputFile}`)\n continue\n }\n\n const cleaned = cleanSectionOutput(raw)\n if (!cleaned) {\n const missing: string[] = []\n if (!/^##\\s/m.test(raw))\n missing.push('h2 heading (## ...)')\n if (!/^- (?:BREAKING|DEPRECATED|NEW): /m.test(raw))\n missing.push('change label (- BREAKING/DEPRECATED/NEW: ...)')\n if (!/\\[source\\]/.test(raw))\n missing.push('[source] link')\n p.log.warn(`${outputFile}: content rejected — missing ${missing.join(', ')}`)\n continue\n }\n\n const validator = getSectionValidator(section)\n if (validator) {\n for (const w of validator(cleaned))\n warnings.push(`${section}: ${w.warning}`)\n }\n\n sections.push({ section, content: cleaned })\n p.log.success(`Loaded ${outputFile}`)\n }\n\n if (sections.length === 0) {\n p.log.warn(`No section output files in ${relative(cwd, targetDir)}. Expected: ${Object.values(SECTION_OUTPUT_FILES).join(', ')}`)\n return\n }\n\n for (const w of warnings)\n p.log.warn(`\\x1B[33m${w}\\x1B[0m`)\n\n // Wrap each section with comment markers\n const wrappedSections: Array<{ section: SkillSection, wrapped: string }> = []\n for (const section of SECTION_MERGE_ORDER) {\n const result = sections.find(s => s.section === section)\n if (result)\n wrappedSections.push({ section, wrapped: wrapSection(section, result.content) })\n }\n\n // Try marker-based replacement first (re-assembly of previously assembled SKILL.md)\n const existingMarkers = extractMarkedSections(existingSkillMd)\n let newSkillMd: string\n\n if (existingMarkers.size > 0) {\n // Replace existing marked sections in-place, append new ones at the end\n newSkillMd = existingSkillMd\n // Process in reverse offset order to preserve indices\n const replacements = wrappedSections\n .filter(s => existingMarkers.has(s.section))\n .sort((a, b) => existingMarkers.get(b.section)!.start - existingMarkers.get(a.section)!.start)\n for (const { section, wrapped } of replacements) {\n const { start, end } = existingMarkers.get(section)!\n newSkillMd = newSkillMd.slice(0, start) + wrapped + newSkillMd.slice(end)\n }\n // Append sections that don't have existing markers\n const newSections = wrappedSections.filter(s => !existingMarkers.has(s.section))\n if (newSections.length > 0)\n newSkillMd = `${newSkillMd.trimEnd()}\\n\\n${newSections.map(s => s.wrapped).join('\\n\\n')}\\n`\n }\n else {\n // First assembly — find header boundary and append all sections\n const body = wrappedSections.map(s => s.wrapped).join('\\n\\n')\n const fmEnd = existingSkillMd.indexOf('\\n---\\n', 4)\n const afterFm = fmEnd !== -1 ? existingSkillMd.slice(fmEnd + 5) : existingSkillMd\n\n const firstLlmHeading = body.match(/^## .+$/m)?.[0]\n let headerPart = afterFm\n if (firstLlmHeading) {\n const idx = afterFm.indexOf(firstLlmHeading)\n if (idx !== -1)\n headerPart = afterFm.slice(0, idx)\n }\n\n const fmPart = fmEnd !== -1 ? existingSkillMd.slice(0, fmEnd + 5) : ''\n const cleanHeader = headerPart.trimEnd()\n newSkillMd = fmPart\n ? `${fmPart}${cleanHeader}\\n\\n${body}\\n`\n : `${cleanHeader}\\n\\n${body}\\n`\n }\n\n writeFileSync(skillMdPath, newSkillMd)\n p.log.success(`Updated ${relative(cwd, skillMdPath)} with ${sections.length} section(s)`)\n}\n\nexport const assembleCommandDef = defineCommand({\n meta: { name: 'assemble', description: 'Merge enhancement output files into SKILL.md' },\n args: {\n dir: {\n type: 'positional',\n description: 'Skill directory with output files (auto-discovers installed skills)',\n required: false,\n },\n },\n async run({ args }) {\n await assembleCommand(args.dir)\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"assemble.mjs","names":[],"sources":["../../src/commands/assemble.ts"],"sourcesContent":["/**\n * `skilld assemble` — merge pasted LLM output back into SKILL.md\n *\n * Auto-discovers skill directories with pending output files when run without arguments.\n */\n\nimport type { SkillSection } from '../agent/index.ts'\nimport { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join, relative, resolve } from 'pathe'\nimport { cleanSectionOutput } from '../agent/clis/index.ts'\nimport {\n extractMarkedSections,\n getSectionValidator,\n SECTION_MERGE_ORDER,\n SECTION_OUTPUT_FILES,\n wrapSection,\n} from '../agent/index.ts'\nimport { API_CHANGE_BULLET_RE, SECTION_HEADING_RE, SOURCE_LINK_RE } from '../core/regex.ts'\nimport { iterateSkills } from '../core/skills.ts'\n\nconst STATIC_REGEX_4 = /^## .+$/m\n\nconst OUTPUT_FILE_SET = new Set(Object.values(SECTION_OUTPUT_FILES))\n\n/**\n * Find installed skill dirs that have pending section output files.\n */\nfunction discoverSkillDirsWithOutputs(): string[] {\n const dirs: string[] = []\n for (const skill of iterateSkills({})) {\n if (readdirSync(skill.dir).some(f => OUTPUT_FILE_SET.has(f)))\n dirs.push(skill.dir)\n }\n return dirs\n}\n\nexport async function assembleCommand(dir: string | undefined): Promise<void> {\n const cwd = process.cwd()\n\n let dirs: string[]\n if (dir) {\n dirs = [resolve(cwd, dir)]\n }\n else {\n // Check cwd first — if it has SKILL.md + output files, use it\n if (existsSync(join(cwd, 'SKILL.md'))\n && readdirSync(cwd).some(f => OUTPUT_FILE_SET.has(f))) {\n dirs = [cwd]\n }\n else {\n dirs = discoverSkillDirsWithOutputs()\n if (dirs.length === 0) {\n p.log.error('No skill directories with output files found. Run `skilld add` first.')\n return\n }\n }\n }\n\n for (const targetDir of dirs)\n assembleDir(targetDir, cwd)\n}\n\nfunction assembleDir(targetDir: string, cwd: string): void {\n if (!existsSync(targetDir)) {\n p.log.error(`Directory not found: ${targetDir}`)\n return\n }\n\n const skillMdPath = join(targetDir, 'SKILL.md')\n if (!existsSync(skillMdPath)) {\n p.log.error(`No SKILL.md found in ${targetDir}`)\n return\n }\n\n const existingSkillMd = readFileSync(skillMdPath, 'utf-8')\n\n // Find and read section output files\n const sections: Array<{ section: SkillSection, content: string }> = []\n const warnings: string[] = []\n\n for (const [section, outputFile] of Object.entries(SECTION_OUTPUT_FILES) as Array<[SkillSection, string]>) {\n const filePath = join(targetDir, outputFile)\n if (!existsSync(filePath))\n continue\n\n const raw = readFileSync(filePath, 'utf-8').trim()\n if (!raw) {\n p.log.warn(`Empty file: ${outputFile}`)\n continue\n }\n\n const cleaned = cleanSectionOutput(raw)\n if (!cleaned) {\n const missing: string[] = []\n if (!SECTION_HEADING_RE.test(raw))\n missing.push('h2 heading (## ...)')\n if (!API_CHANGE_BULLET_RE.test(raw))\n missing.push('change label (- BREAKING/DEPRECATED/NEW: ...)')\n if (!SOURCE_LINK_RE.test(raw))\n missing.push('[source] link')\n p.log.warn(`${outputFile}: content rejected — missing ${missing.join(', ')}`)\n continue\n }\n\n const validator = getSectionValidator(section)\n if (validator) {\n for (const w of validator(cleaned))\n warnings.push(`${section}: ${w.warning}`)\n }\n\n sections.push({ section, content: cleaned })\n p.log.success(`Loaded ${outputFile}`)\n }\n\n if (sections.length === 0) {\n p.log.warn(`No section output files in ${relative(cwd, targetDir)}. Expected: ${Object.values(SECTION_OUTPUT_FILES).join(', ')}`)\n return\n }\n\n for (const w of warnings)\n p.log.warn(styleText('yellow', w))\n\n // Wrap each section with comment markers\n const wrappedSections: Array<{ section: SkillSection, wrapped: string }> = []\n for (const section of SECTION_MERGE_ORDER) {\n const result = sections.find(s => s.section === section)\n if (result)\n wrappedSections.push({ section, wrapped: wrapSection(section, result.content) })\n }\n\n // Try marker-based replacement first (re-assembly of previously assembled SKILL.md)\n const existingMarkers = extractMarkedSections(existingSkillMd)\n let newSkillMd: string\n\n if (existingMarkers.size > 0) {\n // Replace existing marked sections in-place, append new ones at the end\n newSkillMd = existingSkillMd\n // Process in reverse offset order to preserve indices\n const replacements = wrappedSections\n .filter(s => existingMarkers.has(s.section))\n .sort((a, b) => existingMarkers.get(b.section)!.start - existingMarkers.get(a.section)!.start)\n for (const { section, wrapped } of replacements) {\n const { start, end } = existingMarkers.get(section)!\n newSkillMd = newSkillMd.slice(0, start) + wrapped + newSkillMd.slice(end)\n }\n // Append sections that don't have existing markers\n const newSections = wrappedSections.filter(s => !existingMarkers.has(s.section))\n if (newSections.length > 0)\n newSkillMd = `${newSkillMd.trimEnd()}\\n\\n${newSections.map(s => s.wrapped).join('\\n\\n')}\\n`\n }\n else {\n // First assembly — find header boundary and append all sections\n const body = wrappedSections.map(s => s.wrapped).join('\\n\\n')\n const fmEnd = existingSkillMd.indexOf('\\n---\\n', 4)\n const afterFm = fmEnd !== -1 ? existingSkillMd.slice(fmEnd + 5) : existingSkillMd\n\n const firstLlmHeading = body.match(STATIC_REGEX_4)?.[0]\n let headerPart = afterFm\n if (firstLlmHeading) {\n const idx = afterFm.indexOf(firstLlmHeading)\n if (idx !== -1)\n headerPart = afterFm.slice(0, idx)\n }\n\n const fmPart = fmEnd !== -1 ? existingSkillMd.slice(0, fmEnd + 5) : ''\n const cleanHeader = headerPart.trimEnd()\n newSkillMd = fmPart\n ? `${fmPart}${cleanHeader}\\n\\n${body}\\n`\n : `${cleanHeader}\\n\\n${body}\\n`\n }\n\n writeFileSync(skillMdPath, newSkillMd)\n p.log.success(`Updated ${relative(cwd, skillMdPath)} with ${sections.length} section(s)`)\n}\n\nexport const assembleCommandDef = defineCommand({\n meta: { name: 'assemble', description: 'Merge enhancement output files into SKILL.md' },\n args: {\n dir: {\n type: 'positional',\n description: 'Skill directory with output files (auto-discovers installed skills)',\n required: false,\n },\n },\n async run({ args }) {\n await assembleCommand(args.dir)\n },\n})\n"],"mappings":"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"}
@@ -1,78 +1,20 @@
1
- import { a as getModelLabel } from "./agent.mjs";
2
- import { t as getCacheDir } from "./version.mjs";
3
- import { i as readPackageJsonSafe, r as patchPackageJson, t as appendToJsonArray } from "./package-json.mjs";
1
+ import { i as getModelLabel } from "./agent.mjs";
2
+ import { h as timedSpinner, r as computeSkillDirName, t as writeGeneratedSkillMd } from "./prompts.mjs";
3
+ import { m as skillInternalDir } from "./paths.mjs";
4
+ import { i as GIT_PLUS_PREFIX_RE, o as GIT_SUFFIX_RE, u as README_FILENAME_RE } from "./regex.mjs";
4
5
  import { n as sanitizeMarkdown } from "./sanitize.mjs";
5
- import { r as ensureCacheDir, v as writeToCache } from "./cache.mjs";
6
- import { B as fetchGitHubIssues, H as generateIssueIndex, U as isGhAvailable, V as formatIssueAsMarkdown, b as formatDiscussionAsMarkdown, c as readLocalPackageInfo, rt as parseGitHubUrl, x as generateDiscussionIndex, y as fetchGitHubDiscussions } from "./sources.mjs";
7
- import { _ as timedSpinner, i as computeSkillDirName, n as writeGeneratedSkillMd } from "./skill.mjs";
8
- import { a as readConfig, t as defaultFeatures } from "./config.mjs";
9
- import { u as guard } from "./cli-helpers.mjs";
10
- import { S as writePromptFiles, _ as linkAllReferences, b as selectLlmConfig, c as ejectReferences, l as enhanceSkillWithLLM, m as forceClearCache, o as detectChangelog } from "./sync-shared2.mjs";
11
- import { join, relative, resolve } from "pathe";
6
+ import { i as readPackageJsonSafe, r as patchPackageJson, t as appendToJsonArray } from "./package-json.mjs";
7
+ import { d as readConfig, o as defaultFeatures, r as ensureCacheDir, t as createReferenceCache } from "./cache.mjs";
8
+ import { t as guard } from "./menu.mjs";
9
+ import { A as fetchGitHubIssues, M as generateIssueIndex, N as isGhAvailable, R as parseGitHubUrl, S as generateDiscussionIndex, b as fetchGitHubDiscussions, g as readLocalPackageInfo, j as formatIssueAsMarkdown, x as formatDiscussionAsMarkdown } from "./semver.mjs";
10
+ import { t as detectMonorepoPackages } from "./monorepo.mjs";
11
+ import { c as selectLlmConfig, n as detectChangelog, p as writePromptFiles, u as enhanceSkillWithLLM } from "./pipeline.mjs";
12
12
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from "node:fs";
13
+ import { styleText } from "node:util";
13
14
  import * as p from "@clack/prompts";
14
15
  import { defineCommand } from "citty";
15
- const QUOTE_PREFIX_RE = /^['"]/;
16
- const QUOTE_SUFFIX_RE = /['"]$/;
17
- function detectMonorepoPackages(cwd) {
18
- const rootResult = readPackageJsonSafe(join(cwd, "package.json"));
19
- if (!rootResult) return null;
20
- const pkg = rootResult.parsed;
21
- if (!pkg.private) return null;
22
- let patterns = [];
23
- if (Array.isArray(pkg.workspaces)) patterns = pkg.workspaces;
24
- else if (pkg.workspaces?.packages) patterns = pkg.workspaces.packages;
25
- if (patterns.length === 0) {
26
- const pnpmWs = join(cwd, "pnpm-workspace.yaml");
27
- if (existsSync(pnpmWs)) {
28
- const lines = readFileSync(pnpmWs, "utf-8").split("\n");
29
- for (const line of lines) {
30
- const trimmed = line.trim();
31
- if (!trimmed.startsWith("-")) continue;
32
- const value = trimmed.slice(1).trim().replace(QUOTE_PREFIX_RE, "").replace(QUOTE_SUFFIX_RE, "");
33
- if (value) patterns.push(value);
34
- }
35
- }
36
- }
37
- if (patterns.length === 0) return null;
38
- const packages = [];
39
- for (const pattern of patterns) {
40
- const scanDir = resolve(cwd, pattern.replace(/\/?\*+$/, ""));
41
- if (!existsSync(scanDir)) continue;
42
- const directResult = readPackageJsonSafe(join(scanDir, "package.json"));
43
- if (directResult) {
44
- const directPkg = directResult.parsed;
45
- if (!directPkg.private && directPkg.name) {
46
- const repoUrl = typeof directPkg.repository === "string" ? directPkg.repository : directPkg.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
47
- packages.push({
48
- name: directPkg.name,
49
- version: directPkg.version || "0.0.0",
50
- description: directPkg.description,
51
- repoUrl,
52
- dir: scanDir
53
- });
54
- continue;
55
- }
56
- }
57
- for (const entry of readdirSync(scanDir, { withFileTypes: true })) {
58
- if (!entry.isDirectory()) continue;
59
- const childResult = readPackageJsonSafe(join(scanDir, entry.name, "package.json"));
60
- if (!childResult) continue;
61
- const childPkg = childResult.parsed;
62
- if (childPkg.private) continue;
63
- if (!childPkg.name) continue;
64
- const repoUrl = typeof childPkg.repository === "string" ? childPkg.repository : childPkg.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
65
- packages.push({
66
- name: childPkg.name,
67
- version: childPkg.version || "0.0.0",
68
- description: childPkg.description,
69
- repoUrl,
70
- dir: join(scanDir, entry.name)
71
- });
72
- }
73
- }
74
- return packages.length > 0 ? packages : null;
75
- }
16
+ import { join, relative, resolve } from "pathe";
17
+ const STATIC_REGEX_1 = /\.mdx?$/;
76
18
  function walkMarkdownFiles(dir, base = "") {
77
19
  const results = [];
78
20
  if (!existsSync(dir)) return results;
@@ -80,16 +22,16 @@ function walkMarkdownFiles(dir, base = "") {
80
22
  const rel = base ? `${base}/${entry.name}` : entry.name;
81
23
  const full = join(dir, entry.name);
82
24
  if (entry.isDirectory()) results.push(...walkMarkdownFiles(full, rel));
83
- else if (/\.mdx?$/.test(entry.name)) results.push({
25
+ else if (STATIC_REGEX_1.test(entry.name)) results.push({
84
26
  path: rel,
85
27
  content: readFileSync(full, "utf-8")
86
28
  });
87
29
  }
88
30
  return results;
89
31
  }
90
- function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
32
+ function resolveLocalDocs(cache, packageDir, monorepoRoot) {
91
33
  const cachedDocs = [];
92
- const cacheChangelog = () => cacheLocalChangelog(packageDir, packageName, version, monorepoRoot);
34
+ const cacheChangelog = () => cacheLocalChangelog(cache, packageDir, monorepoRoot);
93
35
  const docsDir = join(packageDir, "docs");
94
36
  if (existsSync(docsDir)) {
95
37
  const mdFiles = walkMarkdownFiles(docsDir);
@@ -98,7 +40,7 @@ function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
98
40
  path: `docs/${f.path}`,
99
41
  content: sanitizeMarkdown(f.content)
100
42
  });
101
- writeToCache(packageName, version, cachedDocs);
43
+ cache.write(cachedDocs);
102
44
  cacheChangelog();
103
45
  return {
104
46
  docsType: "docs",
@@ -115,7 +57,7 @@ function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
115
57
  path: `docs/${f.path}`,
116
58
  content: sanitizeMarkdown(f.content)
117
59
  });
118
- writeToCache(packageName, version, cachedDocs);
60
+ cache.write(cachedDocs);
119
61
  cacheChangelog();
120
62
  return {
121
63
  docsType: "docs",
@@ -131,7 +73,7 @@ function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
131
73
  path: "llms.txt",
132
74
  content: sanitizeMarkdown(readFileSync(llmsPath, "utf-8"))
133
75
  });
134
- writeToCache(packageName, version, cachedDocs);
76
+ cache.write(cachedDocs);
135
77
  cacheChangelog();
136
78
  return {
137
79
  docsType: "llms.txt",
@@ -140,13 +82,13 @@ function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
140
82
  }
141
83
  }
142
84
  for (const dir of [packageDir, monorepoRoot].filter(Boolean)) {
143
- const readmeFile = readdirSync(dir).find((f) => /^readme\.md$/i.test(f));
85
+ const readmeFile = readdirSync(dir).find((f) => README_FILENAME_RE.test(f));
144
86
  if (readmeFile) {
145
87
  cachedDocs.push({
146
88
  path: "docs/README.md",
147
89
  content: sanitizeMarkdown(readFileSync(join(dir, readmeFile), "utf-8"))
148
90
  });
149
- writeToCache(packageName, version, cachedDocs);
91
+ cache.write(cachedDocs);
150
92
  cacheChangelog();
151
93
  return {
152
94
  docsType: "readme",
@@ -160,17 +102,17 @@ function resolveLocalDocs(packageDir, packageName, version, monorepoRoot) {
160
102
  docSource: "none"
161
103
  };
162
104
  }
163
- function cacheLocalChangelog(dir, packageName, version, monorepoRoot) {
105
+ function cacheLocalChangelog(cache, dir, monorepoRoot) {
164
106
  const candidates = ["CHANGELOG.md", "changelog.md"];
165
107
  const changelogFile = candidates.find((f) => existsSync(join(dir, f))) || (monorepoRoot ? candidates.find((f) => existsSync(join(monorepoRoot, f))) : void 0);
166
108
  const changelogDir = changelogFile && existsSync(join(dir, changelogFile)) ? dir : monorepoRoot;
167
- if (changelogFile && changelogDir) writeToCache(packageName, version, [{
109
+ if (changelogFile && changelogDir) cache.write([{
168
110
  path: `releases/${changelogFile}`,
169
111
  content: sanitizeMarkdown(readFileSync(join(changelogDir, changelogFile), "utf-8"))
170
112
  }]);
171
113
  }
172
114
  async function fetchRemoteSupplements(opts) {
173
- const { packageName, version, repoUrl, features, onProgress } = opts;
115
+ const { cache, repoUrl, features, onProgress } = opts;
174
116
  if (!repoUrl || !isGhAvailable()) return {
175
117
  hasIssues: false,
176
118
  hasDiscussions: false
@@ -180,19 +122,18 @@ async function fetchRemoteSupplements(opts) {
180
122
  hasIssues: false,
181
123
  hasDiscussions: false
182
124
  };
183
- const cacheDir = getCacheDir(packageName, version);
184
125
  let hasIssues = false;
185
- const issuesDir = join(cacheDir, "issues");
126
+ const issuesDir = join(cache.dir, "issues");
186
127
  if (features.issues && !existsSync(issuesDir)) {
187
128
  onProgress("Fetching issues via GitHub API");
188
129
  const issues = await fetchGitHubIssues(gh.owner, gh.repo, 30).catch(() => []);
189
130
  if (issues.length > 0) {
190
131
  onProgress(`Caching ${issues.length} issues`);
191
- writeToCache(packageName, version, issues.map((issue) => ({
132
+ cache.write(issues.map((issue) => ({
192
133
  path: `issues/issue-${issue.number}.md`,
193
134
  content: formatIssueAsMarkdown(issue)
194
135
  })));
195
- writeToCache(packageName, version, [{
136
+ cache.write([{
196
137
  path: "issues/_INDEX.md",
197
138
  content: generateIssueIndex(issues)
198
139
  }]);
@@ -200,17 +141,17 @@ async function fetchRemoteSupplements(opts) {
200
141
  }
201
142
  } else hasIssues = features.issues && existsSync(issuesDir);
202
143
  let hasDiscussions = false;
203
- const discussionsDir = join(cacheDir, "discussions");
144
+ const discussionsDir = join(cache.dir, "discussions");
204
145
  if (features.discussions && !existsSync(discussionsDir)) {
205
146
  onProgress("Fetching discussions via GitHub API");
206
147
  const discussions = await fetchGitHubDiscussions(gh.owner, gh.repo, 20).catch(() => []);
207
148
  if (discussions.length > 0) {
208
149
  onProgress(`Caching ${discussions.length} discussions`);
209
- writeToCache(packageName, version, discussions.map((d) => ({
150
+ cache.write(discussions.map((d) => ({
210
151
  path: `discussions/discussion-${d.number}.md`,
211
152
  content: formatDiscussionAsMarkdown(d)
212
153
  })));
213
- writeToCache(packageName, version, [{
154
+ cache.write([{
214
155
  path: "discussions/_INDEX.md",
215
156
  content: generateDiscussionIndex(discussions)
216
157
  }]);
@@ -251,17 +192,17 @@ async function authorSinglePackage(opts) {
251
192
  force: true
252
193
  });
253
194
  mkdirSync(outDir, { recursive: true });
254
- if (opts.force) forceClearCache(packageName, version);
195
+ const cache = createReferenceCache(packageName, version);
196
+ if (opts.force) cache.clearForce();
255
197
  ensureCacheDir();
256
198
  const features = readConfig().features ?? defaultFeatures;
257
199
  spin.start("Resolving local docs");
258
- const { docsType, docSource } = resolveLocalDocs(packageDir, packageName, version, opts.monorepoRoot);
200
+ const { docsType, docSource } = resolveLocalDocs(cache, packageDir, opts.monorepoRoot);
259
201
  spin.stop(`Resolved docs: ${docSource}`);
260
202
  const supSpin = timedSpinner();
261
203
  supSpin.start("Checking remote supplements");
262
204
  const { hasIssues, hasDiscussions } = await fetchRemoteSupplements({
263
- packageName,
264
- version,
205
+ cache,
265
206
  repoUrl: opts.repoUrl,
266
207
  features,
267
208
  onProgress: (msg) => supSpin.message(msg)
@@ -270,10 +211,9 @@ async function authorSinglePackage(opts) {
270
211
  if (hasIssues) supParts.push("issues");
271
212
  if (hasDiscussions) supParts.push("discussions");
272
213
  supSpin.stop(supParts.length > 0 ? `Fetched ${supParts.join(", ")}` : "No remote supplements");
273
- linkAllReferences(outDir, packageName, packageDir, version, docsType, void 0, features);
274
- const cacheDir = getCacheDir(packageName, version);
275
- const hasChangelog = detectChangelog(packageDir, cacheDir);
276
- const hasReleases = existsSync(join(cacheDir, "releases"));
214
+ cache.linkInto(outDir, packageDir, docsType, { features });
215
+ const hasChangelog = detectChangelog(packageDir, cache.dir);
216
+ const hasReleases = existsSync(join(cache.dir, "releases"));
277
217
  writeGeneratedSkillMd(outDir, {
278
218
  name: packageName,
279
219
  version,
@@ -292,50 +232,43 @@ async function authorSinglePackage(opts) {
292
232
  eject: true
293
233
  });
294
234
  p.log.success(`Created base skill: ${relative(packageDir, outDir)}`);
295
- const skilldDir = join(outDir, ".skilld");
235
+ const skilldDir = skillInternalDir(outDir);
296
236
  try {
297
237
  const llmConfig = opts.llmConfig;
298
- if (llmConfig?.promptOnly) writePromptFiles({
238
+ const baseCtx = {
299
239
  packageName,
300
- skillDir: outDir,
301
240
  version,
302
- hasIssues,
303
- hasDiscussions,
304
- hasReleases,
305
- hasChangelog,
306
- docsType,
307
- hasShippedDocs: false,
308
- pkgFiles: [],
309
- sections: llmConfig.sections,
310
- customPrompt: llmConfig.customPrompt,
241
+ skillDir: outDir,
242
+ dirName: sanitizedName,
243
+ references: {
244
+ docsType,
245
+ hasShippedDocs: false,
246
+ pkgFiles: [],
247
+ hasIssues,
248
+ hasDiscussions,
249
+ hasReleases,
250
+ hasChangelog
251
+ },
252
+ resolved: { repoUrl: opts.repoUrl },
253
+ relatedSkills: [],
311
254
  features
255
+ };
256
+ if (llmConfig?.promptOnly) writePromptFiles(baseCtx, {
257
+ sections: llmConfig.sections,
258
+ customPrompt: llmConfig.customPrompt
312
259
  });
313
260
  else if (llmConfig) {
314
261
  p.log.step(getModelLabel(llmConfig.model));
315
- await enhanceSkillWithLLM({
316
- packageName,
317
- version,
318
- skillDir: outDir,
319
- dirName: sanitizedName,
262
+ await enhanceSkillWithLLM(baseCtx, {
320
263
  model: llmConfig.model,
321
- resolved: { repoUrl: opts.repoUrl },
322
- relatedSkills: [],
323
- hasIssues,
324
- hasDiscussions,
325
- hasReleases,
326
- hasChangelog,
327
- docsType,
328
- hasShippedDocs: false,
329
- pkgFiles: [],
330
264
  force: opts.force,
331
265
  debug: opts.debug,
332
266
  sections: llmConfig.sections,
333
267
  customPrompt: llmConfig.customPrompt,
334
- features,
335
268
  eject: true
336
269
  });
337
270
  }
338
- ejectReferences(outDir, packageName, packageDir, version, docsType, features);
271
+ cache.eject(outDir, packageDir, docsType, { features });
339
272
  } finally {
340
273
  if (existsSync(skilldDir)) rmSync(skilldDir, {
341
274
  recursive: true,
@@ -355,7 +288,7 @@ async function authorCommand(opts) {
355
288
  const cwd = process.cwd();
356
289
  const monoPackages = detectMonorepoPackages(cwd);
357
290
  if (monoPackages && monoPackages.length > 0) {
358
- p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m author \x1B[90m(monorepo: ${monoPackages.length} packages)\x1B[0m`);
291
+ p.intro(`${styleText(["bold", "magenta"], "skilld")} author ${styleText("gray", `(monorepo: ${monoPackages.length} packages)`)}`);
359
292
  if (opts.out) {
360
293
  p.log.error("--out is not supported in monorepo mode (each package gets its own skills/ directory)");
361
294
  return;
@@ -375,10 +308,10 @@ async function authorCommand(opts) {
375
308
  return;
376
309
  }
377
310
  const rootPkg = readPackageJsonSafe(join(cwd, "package.json"))?.parsed;
378
- const rootRepoUrl = typeof rootPkg?.repository === "string" ? rootPkg.repository : rootPkg?.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
311
+ const rootRepoUrl = typeof rootPkg?.repository === "string" ? rootPkg.repository : rootPkg?.repository?.url?.replace(GIT_PLUS_PREFIX_RE, "").replace(GIT_SUFFIX_RE, "");
379
312
  const results = [];
380
313
  for (const pkg of selected) {
381
- p.log.step(`\x1B[36m${pkg.name}\x1B[0m@${pkg.version}`);
314
+ p.log.step(`${styleText("cyan", pkg.name)}@${pkg.version}`);
382
315
  const outDir = await authorSinglePackage({
383
316
  packageDir: pkg.dir,
384
317
  packageName: pkg.name,
@@ -409,7 +342,7 @@ async function authorCommand(opts) {
409
342
  return;
410
343
  }
411
344
  const { name: packageName, version, repoUrl } = pkgInfo;
412
- p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m author \x1B[36m${packageName}\x1B[0m@${version}`);
345
+ p.intro(`${styleText(["bold", "magenta"], "skilld")} author ${styleText("cyan", packageName)}@${version}`);
413
346
  const llmConfig = await resolveLlmConfig(opts.model, opts.yes);
414
347
  if (llmConfig === null) {
415
348
  p.cancel("Cancelled");
@@ -433,7 +366,7 @@ async function authorCommand(opts) {
433
366
  }
434
367
  function printConsumerGuidance(packageNames) {
435
368
  const names = packageNames.join(", ");
436
- p.log.info(`\x1B[90mConsumers get ${packageNames.length > 1 ? "these skills" : "this skill"} automatically:\x1B[0m\n \x1B[90m1. Install ${names} as a dependency\x1B[0m\n \x1B[90m2. Run \x1B[36mskilld prepare\x1B[90m (or add to package.json: \x1B[36m"prepare": "skilld prepare"\x1B[90m)\x1B[0m`);
369
+ p.log.info(`${styleText("gray", `Consumers get ${packageNames.length > 1 ? "these skills" : "this skill"} automatically:`)}\n ${styleText("gray", `1. Install ${names} as a dependency`)}\n ${styleText("gray", "2. Run ")}${styleText("cyan", "skilld prepare")}${styleText("gray", " (or add to package.json: ")}${styleText("cyan", "\"prepare\": \"skilld prepare\"")}${styleText("gray", ")")}`);
437
370
  }
438
371
  const authorCommandDef = defineCommand({
439
372
  meta: {
@@ -480,6 +413,19 @@ const authorCommandDef = defineCommand({
480
413
  });
481
414
  }
482
415
  });
483
- export { authorCommandDef };
416
+ const authorGroupDef = defineCommand({
417
+ meta: {
418
+ name: "author",
419
+ description: "Create, generate, and publish skills"
420
+ },
421
+ subCommands: {
422
+ package: () => import("./author.mjs").then((m) => m.authorCommandDef),
423
+ publish: () => import("./upload.mjs").then((m) => m.uploadCommandDef),
424
+ eject: () => import("./eject.mjs").then((m) => m.ejectCommandDef),
425
+ validate: () => import("./validate.mjs").then((m) => m.validateCommandDef),
426
+ assemble: () => import("./assemble.mjs").then((m) => m.assembleCommandDef)
427
+ }
428
+ });
429
+ export { authorCommandDef, authorGroupDef };
484
430
 
485
431
  //# sourceMappingURL=author.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"author.mjs","names":[],"sources":["../../src/commands/author.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { LlmConfig } from './sync-shared.ts'\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join, relative, resolve } from 'pathe'\nimport {\n computeSkillDirName,\n getModelLabel,\n writeGeneratedSkillMd,\n} from '../agent/index.ts'\nimport {\n ensureCacheDir,\n getCacheDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { guard } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { appendToJsonArray, patchPackageJson, readPackageJsonSafe } from '../core/package-json.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport {\n fetchGitHubDiscussions,\n fetchGitHubIssues,\n formatDiscussionAsMarkdown,\n formatIssueAsMarkdown,\n generateDiscussionIndex,\n generateIssueIndex,\n isGhAvailable,\n parseGitHubUrl,\n readLocalPackageInfo,\n} from '../sources/index.ts'\nimport {\n detectChangelog,\n ejectReferences,\n enhanceSkillWithLLM,\n forceClearCache,\n linkAllReferences,\n selectLlmConfig,\n writePromptFiles,\n} from './sync-shared.ts'\n\nconst QUOTE_PREFIX_RE = /^['\"]/\nconst QUOTE_SUFFIX_RE = /['\"]$/\n\n// ── Monorepo detection ──\n\nexport interface MonorepoPackage {\n name: string\n version: string\n description?: string\n repoUrl?: string\n dir: string\n}\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\n // Must be private (monorepo root) with workspaces or pnpm-workspace.yaml\n if (!pkg.private)\n return null\n\n let patterns: string[] = []\n\n if (Array.isArray(pkg.workspaces)) {\n patterns = pkg.workspaces\n }\n else if (pkg.workspaces?.packages) {\n patterns = pkg.workspaces.packages\n }\n\n // Check pnpm-workspace.yaml\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 if (patterns.length === 0)\n return null\n\n const packages: MonorepoPackage[] = []\n\n for (const pattern of patterns) {\n // Expand simple glob: \"packages/*\" → scan packages/*/package.json\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 const repoUrl = typeof directPkg.repository === 'string'\n ? directPkg.repository\n : directPkg.repository?.url?.replace(/^git\\+/, '').replace(/\\.git$/, '')\n\n packages.push({\n name: directPkg.name,\n version: directPkg.version || '0.0.0',\n description: directPkg.description,\n repoUrl,\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)\n continue\n if (!childPkg.name)\n continue\n\n const repoUrl = typeof childPkg.repository === 'string'\n ? childPkg.repository\n : childPkg.repository?.url?.replace(/^git\\+/, '').replace(/\\.git$/, '')\n\n packages.push({\n name: childPkg.name,\n version: childPkg.version || '0.0.0',\n description: childPkg.description,\n repoUrl,\n dir: join(scanDir, entry.name),\n })\n }\n }\n\n return packages.length > 0 ? packages : null\n}\n\n// ── Docs resolution ──\n\nfunction walkMarkdownFiles(dir: string, base = ''): Array<{ path: string, content: string }> {\n const results: Array<{ path: string, content: string }> = []\n if (!existsSync(dir))\n return results\n\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const rel = base ? `${base}/${entry.name}` : entry.name\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMarkdownFiles(full, rel))\n }\n else if (/\\.mdx?$/.test(entry.name)) {\n results.push({ path: rel, content: readFileSync(full, 'utf-8') })\n }\n }\n return results\n}\n\n/**\n * Resolve docs from local filesystem. Cascade:\n * 1. Package-level docs/ directory\n * 2. Monorepo-root docs/ directory (if monorepoRoot provided)\n * 3. Monorepo-root docs/content/ (Nuxt Content convention)\n * 4. llms.txt in package dir\n * 5. README.md in package dir\n */\nfunction resolveLocalDocs(\n packageDir: string,\n packageName: string,\n version: string,\n monorepoRoot?: string,\n): { docsType: 'docs' | 'llms.txt' | 'readme', docSource: string } {\n const cachedDocs: Array<{ path: string, content: string }> = []\n\n const cacheChangelog = () => cacheLocalChangelog(packageDir, packageName, version, monorepoRoot)\n\n // 1. Package-level docs/\n const docsDir = join(packageDir, 'docs')\n if (existsSync(docsDir)) {\n const mdFiles = walkMarkdownFiles(docsDir)\n if (mdFiles.length > 0) {\n for (const f of mdFiles)\n cachedDocs.push({ path: `docs/${f.path}`, content: sanitizeMarkdown(f.content) })\n writeToCache(packageName, version, cachedDocs)\n cacheChangelog()\n return { docsType: 'docs', docSource: `local docs/ (${mdFiles.length} files)` }\n }\n }\n\n // 2. Monorepo-root docs/ or docs/content/\n if (monorepoRoot) {\n for (const candidate of ['docs/content', 'docs']) {\n const rootDocsDir = join(monorepoRoot, candidate)\n if (existsSync(rootDocsDir)) {\n const mdFiles = walkMarkdownFiles(rootDocsDir)\n if (mdFiles.length > 0) {\n for (const f of mdFiles)\n cachedDocs.push({ path: `docs/${f.path}`, content: sanitizeMarkdown(f.content) })\n writeToCache(packageName, version, cachedDocs)\n cacheChangelog()\n return { docsType: 'docs', docSource: `monorepo ${candidate}/ (${mdFiles.length} files)` }\n }\n }\n }\n }\n\n // 3. llms.txt (package dir, then monorepo root)\n for (const dir of [packageDir, monorepoRoot].filter(Boolean) as string[]) {\n const llmsPath = join(dir, 'llms.txt')\n if (existsSync(llmsPath)) {\n cachedDocs.push({ path: 'llms.txt', content: sanitizeMarkdown(readFileSync(llmsPath, 'utf-8')) })\n writeToCache(packageName, version, cachedDocs)\n cacheChangelog()\n const source = dir === packageDir ? 'local llms.txt' : 'monorepo llms.txt'\n return { docsType: 'llms.txt', docSource: source }\n }\n }\n\n // 4. README.md (package dir, then monorepo root)\n for (const dir of [packageDir, monorepoRoot].filter(Boolean) as string[]) {\n const readmeFile = readdirSync(dir).find(f => /^readme\\.md$/i.test(f))\n if (readmeFile) {\n cachedDocs.push({ path: 'docs/README.md', content: sanitizeMarkdown(readFileSync(join(dir, readmeFile), 'utf-8')) })\n writeToCache(packageName, version, cachedDocs)\n cacheChangelog()\n const source = dir === packageDir ? 'local README.md' : 'monorepo README.md'\n return { docsType: 'readme', docSource: source }\n }\n }\n\n cacheChangelog()\n return { docsType: 'readme', docSource: 'none' }\n}\n\nfunction cacheLocalChangelog(dir: string, packageName: string, version: string, monorepoRoot?: string): void {\n const candidates = ['CHANGELOG.md', 'changelog.md']\n const changelogFile = candidates.find(f => existsSync(join(dir, f)))\n || (monorepoRoot ? candidates.find(f => existsSync(join(monorepoRoot, f))) : undefined)\n const changelogDir = changelogFile && existsSync(join(dir, changelogFile)) ? dir : monorepoRoot\n if (changelogFile && changelogDir) {\n writeToCache(packageName, version, [{\n path: `releases/${changelogFile}`,\n content: sanitizeMarkdown(readFileSync(join(changelogDir, changelogFile), 'utf-8')),\n }])\n }\n}\n\n// ── Remote supplements ──\n\nasync function fetchRemoteSupplements(opts: {\n packageName: string\n version: string\n repoUrl?: string\n features: FeaturesConfig\n onProgress: (msg: string) => void\n}): Promise<{ hasIssues: boolean, hasDiscussions: boolean }> {\n const { packageName, version, repoUrl, features, onProgress } = opts\n\n if (!repoUrl || !isGhAvailable())\n return { hasIssues: false, hasDiscussions: false }\n\n const gh = parseGitHubUrl(repoUrl)\n if (!gh)\n return { hasIssues: false, hasDiscussions: false }\n\n const cacheDir = getCacheDir(packageName, version)\n\n let hasIssues = false\n const issuesDir = join(cacheDir, 'issues')\n if (features.issues && !existsSync(issuesDir)) {\n onProgress('Fetching issues via GitHub API')\n const issues = await fetchGitHubIssues(gh.owner, gh.repo, 30).catch(() => [])\n if (issues.length > 0) {\n onProgress(`Caching ${issues.length} issues`)\n writeToCache(packageName, version, issues.map(issue => ({\n path: `issues/issue-${issue.number}.md`,\n content: formatIssueAsMarkdown(issue),\n })))\n writeToCache(packageName, version, [{\n path: 'issues/_INDEX.md',\n content: generateIssueIndex(issues),\n }])\n hasIssues = true\n }\n }\n else {\n hasIssues = features.issues && existsSync(issuesDir)\n }\n\n let hasDiscussions = false\n const discussionsDir = join(cacheDir, 'discussions')\n if (features.discussions && !existsSync(discussionsDir)) {\n onProgress('Fetching discussions via GitHub API')\n const discussions = await fetchGitHubDiscussions(gh.owner, gh.repo, 20).catch(() => [])\n if (discussions.length > 0) {\n onProgress(`Caching ${discussions.length} discussions`)\n writeToCache(packageName, version, discussions.map(d => ({\n path: `discussions/discussion-${d.number}.md`,\n content: formatDiscussionAsMarkdown(d),\n })))\n writeToCache(packageName, version, [{\n path: 'discussions/_INDEX.md',\n content: generateDiscussionIndex(discussions),\n }])\n hasDiscussions = true\n }\n }\n else {\n hasDiscussions = features.discussions && existsSync(discussionsDir)\n }\n\n return { hasIssues, hasDiscussions }\n}\n\n// ── package.json patching ──\n\nexport function patchPackageJsonFiles(packageDir: string): void {\n const pkgPath = join(packageDir, 'package.json')\n if (!existsSync(pkgPath))\n return\n\n const wrote = patchPackageJson(pkgPath, (raw, pkg) => {\n if (!Array.isArray(pkg.files)) {\n p.log.warn('No `files` array in package.json. Add `\"skills\"` to your files array manually.')\n return null\n }\n\n if ((pkg.files as string[]).some((f: string) => f === 'skills' || f === 'skills/' || f === 'skills/**'))\n return null\n\n return appendToJsonArray(raw, ['files'], 'skills')\n })\n\n if (wrote)\n p.log.success('Added `\"skills\"` to package.json files array')\n}\n\n// ── Core author flow for a single package ──\n\nasync function authorSinglePackage(opts: {\n packageDir: string\n packageName: string\n version: string\n description?: string\n repoUrl?: string\n monorepoRoot?: string\n out?: string\n llmConfig?: LlmConfig | null\n force?: boolean\n debug?: boolean\n}): Promise<string | null> {\n const { packageDir, packageName, version } = opts\n const spin = timedSpinner()\n\n const sanitizedName = computeSkillDirName(packageName)\n const outDir = opts.out ? resolve(packageDir, opts.out) : join(packageDir, 'skills', sanitizedName)\n\n // Validate --out doesn't point at the package root or a parent\n if (opts.out) {\n const rel = relative(packageDir, outDir)\n if (!rel || rel === '.' || rel.startsWith('..')) {\n p.log.error('--out must point to a child directory, not the package root or a parent')\n return null\n }\n }\n\n if (existsSync(outDir))\n rmSync(outDir, { recursive: true, force: true })\n mkdirSync(outDir, { recursive: true })\n\n if (opts.force) {\n forceClearCache(packageName, version)\n }\n\n ensureCacheDir()\n const features = readConfig().features ?? defaultFeatures\n\n // Resolve local docs\n spin.start('Resolving local docs')\n const { docsType, docSource } = resolveLocalDocs(packageDir, packageName, version, opts.monorepoRoot)\n spin.stop(`Resolved docs: ${docSource}`)\n\n // Fetch remote supplements (issues/discussions)\n const supSpin = timedSpinner()\n supSpin.start('Checking remote supplements')\n const { hasIssues, hasDiscussions } = await fetchRemoteSupplements({\n packageName,\n version,\n repoUrl: opts.repoUrl,\n features,\n onProgress: msg => supSpin.message(msg),\n })\n const supParts: string[] = []\n if (hasIssues)\n supParts.push('issues')\n if (hasDiscussions)\n supParts.push('discussions')\n supSpin.stop(supParts.length > 0 ? `Fetched ${supParts.join(', ')}` : 'No remote supplements')\n\n // Create temporary .skilld/ symlinks (LLM needs these to read docs)\n linkAllReferences(outDir, packageName, packageDir, version, docsType, undefined, features)\n\n // Detect changelog + releases\n const cacheDir = getCacheDir(packageName, version)\n const hasChangelog = detectChangelog(packageDir, cacheDir)\n const hasReleases = existsSync(join(cacheDir, 'releases'))\n\n // Generate base SKILL.md\n writeGeneratedSkillMd(outDir, {\n name: packageName,\n version,\n description: opts.description,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n hasChangelog,\n docsType,\n hasShippedDocs: false,\n pkgFiles: [],\n dirName: sanitizedName,\n repoUrl: opts.repoUrl,\n features,\n eject: true,\n })\n p.log.success(`Created base skill: ${relative(packageDir, outDir)}`)\n\n // LLM enhancement (config resolved by caller)\n const skilldDir = join(outDir, '.skilld')\n try {\n const llmConfig = opts.llmConfig\n if (llmConfig?.promptOnly) {\n writePromptFiles({\n packageName,\n skillDir: outDir,\n version,\n hasIssues,\n hasDiscussions,\n hasReleases,\n hasChangelog,\n docsType,\n hasShippedDocs: false,\n pkgFiles: [],\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n await enhanceSkillWithLLM({\n packageName,\n version,\n skillDir: outDir,\n dirName: sanitizedName,\n model: llmConfig.model,\n resolved: { repoUrl: opts.repoUrl },\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n hasChangelog,\n docsType,\n hasShippedDocs: false,\n pkgFiles: [],\n force: opts.force,\n debug: opts.debug,\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n eject: true,\n })\n }\n\n ejectReferences(outDir, packageName, packageDir, version, docsType, features)\n }\n finally {\n // Always clean up .skilld/ symlinks, even if LLM enhancement fails\n if (existsSync(skilldDir))\n rmSync(skilldDir, { recursive: true, force: true })\n }\n\n // Only patch package.json when output is under skills/\n const relOut = relative(packageDir, outDir)\n if (relOut === 'skills' || relOut.startsWith('skills/'))\n patchPackageJsonFiles(packageDir)\n else if (opts.out)\n p.log.info('Output is outside skills/, skipping package.json patch. Add the path to \"files\" manually if publishing.')\n\n return outDir\n}\n\n// ── Main command ──\n\nasync function resolveLlmConfig(model?: OptimizeModel, yes?: boolean): Promise<LlmConfig | null | undefined> {\n const globalConfig = readConfig()\n if (globalConfig.skipLlm || (yes && !model))\n return undefined\n return selectLlmConfig(model, 'Generate skill sections')\n}\n\nasync function authorCommand(opts: {\n out?: string\n model?: OptimizeModel\n yes?: boolean\n force?: boolean\n debug?: boolean\n}): Promise<void> {\n const cwd = process.cwd()\n\n // Check for monorepo\n const monoPackages = detectMonorepoPackages(cwd)\n\n if (monoPackages && monoPackages.length > 0) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m author \\x1B[90m(monorepo: ${monoPackages.length} packages)\\x1B[0m`)\n\n if (opts.out) {\n p.log.error('--out is not supported in monorepo mode (each package gets its own skills/ directory)')\n return\n }\n\n const selected = guard(await p.multiselect({\n message: 'Which packages should ship skills?',\n options: monoPackages.map(pkg => ({\n label: pkg.name,\n value: pkg,\n hint: pkg.description,\n })),\n }))\n\n if (selected.length === 0)\n return\n\n // Resolve LLM config once for all packages\n const llmConfig = await resolveLlmConfig(opts.model, opts.yes)\n if (llmConfig === null) {\n p.cancel('Cancelled')\n return\n }\n\n // Resolve monorepo-level repoUrl for packages that lack their own\n const rootPkgResult = readPackageJsonSafe(join(cwd, 'package.json'))\n const rootPkg = rootPkgResult?.parsed as Record<string, any> | undefined\n const rootRepoUrl = typeof rootPkg?.repository === 'string'\n ? rootPkg.repository\n : rootPkg?.repository?.url?.replace(/^git\\+/, '').replace(/\\.git$/, '')\n\n const results: Array<{ name: string, outDir: string }> = []\n\n for (const pkg of selected) {\n p.log.step(`\\x1B[36m${pkg.name}\\x1B[0m@${pkg.version}`)\n const outDir = await authorSinglePackage({\n packageDir: pkg.dir,\n packageName: pkg.name,\n version: pkg.version,\n description: pkg.description,\n repoUrl: pkg.repoUrl || rootRepoUrl,\n monorepoRoot: cwd,\n llmConfig,\n force: opts.force,\n debug: opts.debug,\n })\n if (outDir)\n results.push({ name: pkg.name, outDir })\n }\n\n if (results.length > 0) {\n p.log.message('')\n for (const { name, outDir } of results)\n p.log.success(`${name} → ${relative(cwd, outDir)}`)\n\n printConsumerGuidance(results.map(r => r.name))\n }\n\n p.outro('Done')\n return\n }\n\n // Single package mode\n const pkgInfo = readLocalPackageInfo(cwd)\n if (!pkgInfo) {\n p.log.error('No package.json found in current directory')\n return\n }\n\n const { name: packageName, version, repoUrl } = pkgInfo\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m author \\x1B[36m${packageName}\\x1B[0m@${version}`)\n\n const llmConfig = await resolveLlmConfig(opts.model, opts.yes)\n if (llmConfig === null) {\n p.cancel('Cancelled')\n return\n }\n\n const outDir = await authorSinglePackage({\n packageDir: cwd,\n packageName,\n version,\n description: pkgInfo.description,\n repoUrl,\n out: opts.out,\n llmConfig,\n force: opts.force,\n debug: opts.debug,\n })\n\n if (outDir) {\n printConsumerGuidance([packageName])\n p.outro(`Authored skill to ${relative(cwd, outDir)}`)\n }\n}\n\nfunction printConsumerGuidance(packageNames: string[]): void {\n const names = packageNames.join(', ')\n p.log.info(\n `\\x1B[90mConsumers get ${packageNames.length > 1 ? 'these skills' : 'this skill'} automatically:\\x1B[0m\\n`\n + ` \\x1B[90m1. Install ${names} as a dependency\\x1B[0m\\n`\n + ` \\x1B[90m2. Run \\x1B[36mskilld prepare\\x1B[90m (or add to package.json: \\x1B[36m\"prepare\": \"skilld prepare\"\\x1B[90m)\\x1B[0m`,\n )\n}\n\nexport const authorCommandDef = defineCommand({\n meta: { name: 'package', description: 'Generate a package skill from documentation' },\n args: {\n out: {\n type: 'string',\n alias: 'o',\n description: 'Output directory (default: ./skills/<name>/)',\n },\n model: {\n type: 'string',\n alias: 'm',\n description: 'Enhancement model for SKILL.md generation',\n valueHint: 'id',\n },\n yes: {\n type: 'boolean',\n alias: 'y',\n description: 'Skip prompts, use defaults',\n default: false,\n },\n force: {\n type: 'boolean',\n alias: 'f',\n description: 'Clear cache and regenerate',\n default: false,\n },\n debug: {\n type: 'boolean',\n description: 'Save raw enhancement output to logs/',\n default: false,\n },\n },\n async run({ args }) {\n await authorCommand({\n out: args.out,\n model: args.model as OptimizeModel | undefined,\n yes: args.yes,\n force: args.force,\n debug: args.debug,\n })\n },\n})\n"],"mappings":";;;;;;;;;;;;;;AA2CA,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AAYxB,SAAgB,uBAAuB,KAAuC;CAC5E,MAAM,aAAa,oBAAoB,KAAK,KAAK,eAAe,CAAC;CACjE,IAAI,CAAC,YACH,OAAO;CAET,MAAM,MAAM,WAAW;CAGvB,IAAI,CAAC,IAAI,SACP,OAAO;CAET,IAAI,WAAqB,EAAE;CAE3B,IAAI,MAAM,QAAQ,IAAI,WAAW,EAC/B,WAAW,IAAI;MAEZ,IAAI,IAAI,YAAY,UACvB,WAAW,IAAI,WAAW;CAI5B,IAAI,SAAS,WAAW,GAAG;EACzB,MAAM,SAAS,KAAK,KAAK,sBAAsB;EAC/C,IAAI,WAAW,OAAO,EAAE;GACtB,MAAM,QAAQ,aAAa,QAAQ,QAAQ,CAAC,MAAM,KAAK;GACvD,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,UAAU,KAAK,MAAM;IAC3B,IAAI,CAAC,QAAQ,WAAW,IAAI,EAC1B;IACF,MAAM,QAAQ,QAAQ,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,iBAAiB,GAAG,CAAC,QAAQ,iBAAiB,GAAG;IAC/F,IAAI,OACF,SAAS,KAAK,MAAM;;;;CAK5B,IAAI,SAAS,WAAW,GACtB,OAAO;CAET,MAAM,WAA8B,EAAE;CAEtC,KAAK,MAAM,WAAW,UAAU;EAG9B,MAAM,UAAU,QAAQ,KADX,QAAQ,QAAQ,WAAW,GACP,CAAC;EAClC,IAAI,CAAC,WAAW,QAAQ,EACtB;EAEF,MAAM,eAAe,oBAAoB,KAAK,SAAS,eAAe,CAAC;EACvE,IAAI,cAAc;GAChB,MAAM,YAAY,aAAa;GAC/B,IAAI,CAAC,UAAU,WAAW,UAAU,MAAM;IACxC,MAAM,UAAU,OAAO,UAAU,eAAe,WAC5C,UAAU,aACV,UAAU,YAAY,KAAK,QAAQ,UAAU,GAAG,CAAC,QAAQ,UAAU,GAAG;IAE1E,SAAS,KAAK;KACZ,MAAM,UAAU;KAChB,SAAS,UAAU,WAAW;KAC9B,aAAa,UAAU;KACvB;KACA,KAAK;KACN,CAAC;IACF;;;EAIJ,KAAK,MAAM,SAAS,YAAY,SAAS,EAAE,eAAe,MAAM,CAAC,EAAE;GACjE,IAAI,CAAC,MAAM,aAAa,EACtB;GACF,MAAM,cAAc,oBAAoB,KAAK,SAAS,MAAM,MAAM,eAAe,CAAC;GAClF,IAAI,CAAC,aACH;GAEF,MAAM,WAAW,YAAY;GAC7B,IAAI,SAAS,SACX;GACF,IAAI,CAAC,SAAS,MACZ;GAEF,MAAM,UAAU,OAAO,SAAS,eAAe,WAC3C,SAAS,aACT,SAAS,YAAY,KAAK,QAAQ,UAAU,GAAG,CAAC,QAAQ,UAAU,GAAG;GAEzE,SAAS,KAAK;IACZ,MAAM,SAAS;IACf,SAAS,SAAS,WAAW;IAC7B,aAAa,SAAS;IACtB;IACA,KAAK,KAAK,SAAS,MAAM,KAAK;IAC/B,CAAC;;;CAIN,OAAO,SAAS,SAAS,IAAI,WAAW;;AAK1C,SAAS,kBAAkB,KAAa,OAAO,IAA8C;CAC3F,MAAM,UAAoD,EAAE;CAC5D,IAAI,CAAC,WAAW,IAAI,EAClB,OAAO;CAET,KAAK,MAAM,SAAS,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC,EAAE;EAC7D,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,SAAS,MAAM;EACnD,MAAM,OAAO,KAAK,KAAK,MAAM,KAAK;EAClC,IAAI,MAAM,aAAa,EACrB,QAAQ,KAAK,GAAG,kBAAkB,MAAM,IAAI,CAAC;OAE1C,IAAI,UAAU,KAAK,MAAM,KAAK,EACjC,QAAQ,KAAK;GAAE,MAAM;GAAK,SAAS,aAAa,MAAM,QAAQ;GAAE,CAAC;;CAGrE,OAAO;;;;;;;;;GAWT,KAAA,MAAS,KAAA,SACP,WACA,KAAA;IAIA,MAAM,QAAA,EAAuD;IAE7D,SAAM,iBAAuB,EAAA,QAAA;IAG7B,CAAA;GACA,aAAe,aAAU,SAAA,WAAA;GACvB,gBAAgB;GAChB,OAAI;IACF,UAAW;IACS,WAAM,gBAAU,QAAA,OAAA;IAAQ;;;KAE5C,cAAgB,KAAA,MAAA,aAAA,CAAA,gBAAA,OAAA,EAAA;QAChB,cAAO,KAAA,cAAA,UAAA;MAAE,WAAU,YAAA,EAAA;SAAQ,UAAW,kBAAgB,YAAe;OAAU,QAAA,SAAA,GAAA;;;KAK/E,SAAA,iBACS,EAAA,QAAA;KACT,CAAA;IACA,aAAe,aAAY,SAAE,WAAA;IAC3B,gBAAgB;IAChB,OAAI;KACF,UAAW;KACS,WAAM,YAAU,UAAA,KAAA,QAAA,OAAA;KAAQ;;;;MAG5C,MAAO,OAAA,CAAA,YAAA,aAAA,CAAA,OAAA,QAAA,EAAA;QAAE,WAAU,KAAA,KAAA,WAAA;MAAQ,WAAW,SAAA,EAAY;cAAwC,KAAA;;;;GAOlG,aAAW,aAAQ,SAAY,WAAc;GAC3C,gBAAiB;GACjB,OAAI;IACF,UAAW;IAAO,WAAM,QAAA,aAAA,mBAAA;IAAY;;;MAEpC,MAAA,OAAgB,CAAA,YAAA,aAAA,CAAA,OAAA,QAAA,EAAA;QAEhB,aAAO,YAAA,IAAA,CAAA,MAAA,MAAA,gBAAA,KAAA,EAAA,CAAA;MAAE,YAAU;cAAY,KADhB;IACmC,MAAA;;;GAKtD,aAAW,aAAQ,SAAY,WAAc;GAC3C,gBAAM;GACN,OAAI;IACF,UAAW;IAAO,WAAM,QAAA,aAAA,oBAAA;IAAkB;;;iBAE1C;QAEA;YAAS;aAAoB;;;;CAIjC,MAAA,aAAgB,CAAA,gBAAA,eAAA;CAChB,MAAA,gBAAO,WAAA,MAAA,MAAA,WAAA,KAAA,KAAA,EAAA,CAAA,CAAA,KAAA,eAAA,WAAA,MAAA,MAAA,WAAA,KAAA,cAAA,EAAA,CAAA,CAAA,GAAA,KAAA;OAAE,eAAU,iBAAA,WAAA,KAAA,KAAA,cAAA,CAAA,GAAA,MAAA;KAAU,iBAAW,cAAA,aAAA,aAAA,SAAA,CAAA;EAAQ,MAAA,YAAA;;EAGlD,CAAA,CAAA;;eAEQ,uBAA2B,MAAK;CAEtC,MAAM,EAAA,aAAe,SAAA,SAAiB,UAAW,eAAU;CAC3D,IAAI,CAAA,WAAA,CAAA,eAAiB,EAAA,OACnB;EACE,WAAM;EACN,gBAAS;EACV;;CAML,IAAA,CAAA,IAAA,OAAe;EAOb,WAAQ;EAER,gBAAiB;EACN;OAAkB,WAAgB,YAAA,aAAA,QAAA;KAAO,YAAA;CAEpD,MAAM,YAAK,KAAA,UAAe,SAAQ;CAClC,IAAI,SACF,UAAO,CAAA,WAAA,UAAA,EAAA;EAAE,WAAW,iCAAA;EAAO,MAAA,SAAA,MAAgB,kBAAA,GAAA,OAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,CAAA;EAAO,IAAA,OAAA,SAAA,GAAA;GAEpD,WAAM,WAAW,OAAY,OAAA,SAAa;GAE1C,aAAI,aAAY,SAAA,OAAA,KAAA,WAAA;IAChB,MAAM,gBAAiB,MAAA,OAAU;IACjC,SAAI,sBAAoB,MAAW;IACjC,EAAA,CAAA;GACA,aAAM,aAAe,SAAA,CAAA;IACrB,MAAI;IACF,SAAA,mBAA6B,OAAO;IACpC,CAAA,CAAA;eACQ;;QAEJ,YAAA,SAAA,UAAA,WAAA,UAAA;KACJ,iBAAa;OACX,iBAAM,KAAA,UAAA,cAAA;KACN,SAAS,eAAA,CAAA,WAA0B,eAAA,EAAA;aAClC,sCAAA;QACH,cAAY,MAAA,uBAAA,GAAA,OAAA,GAAA,MAAA,GAAA,CAAA,YAAA,EAAA,CAAA;;cAId,WAAY,YAAS,OAAU,cAAW;GAG5C,aAAI,aAAiB,SAAA,YAAA,KAAA,OAAA;IACrB,MAAM,0BAAsB,EAAA,OAAU;IACtC,SAAI,2BAAyB,EAAW;IACtC,EAAA,CAAA;GACA,aAAM,aAAoB,SAAA,CAAA;IAC1B,MAAI;IACF,SAAA,wBAAkC,YAAO;IACzC,CAAA,CAAA;oBACQ;;QAEJ,iBAAA,SAAA,eAAA,WAAA,eAAA;QACJ;;;;;;iBAQF,KAAA,YAA0B,eAAe;CAG3C,IAAA,CAAA,WAAO,QAAA,EAAA;KAAE,iBAAA,UAAA,KAAA,QAAA;EAAW,IAAA,CAAA,MAAA,QAAA,IAAA,MAAA,EAAA;GAAgB,EAAA,IAAA,KAAA,mFAAA;;;EAMpC,IAAA,IAAM,MAAA,MAAe,MAAA,MAAY,YAAA,MAAe,aAAA,MAAA,YAAA,EAAA,OAAA;EAChD,OAAK,kBACH,KAAA,CAAA,QAAA,EAAA,SAAA;GAcF,EAZc,EAAA,IAAA,QAAA,iDAAwC;;eAEvC,oBAAA,MAAA;OACX,EAAA,YAAO,aAAA,YAAA;;OAGJ,gBAA6B,oBAAoB,YAAkB;OAGxE,SAAO,KAAA,MAAkB,QAAM,YAAU,KAAS,IAAA,GAAA,KAAA,YAAA,UAAA,cAAA;KAIlD,KAAE,KAAI;;EAKV,IAAA,CAAA,OAAA,QAAe,OAAA,IAAA,WAWY,KAAA,EAAA;GACzB,EAAA,IAAQ,MAAA,0EAAqC;GAC7C,OAAM;;;CAMN,IAAI,WAAU,OAAA,EAAA,OAAA,QAAA;EACZ,WAAM;EACN,OAAK;GACH;WACO,QAAA,EAAA,WAAA,MAAA,CAAA;;;CAIX,MAAI,WAAW,YACb,CAAA,YAAe;MAAE,MAAA,uBAAW;OAAM,EAAO,UAAA,cAAA,iBAAA,YAAA,aAAA,SAAA,KAAA,aAAA;MAAO,KAAA,kBAAA,YAAA;CAClD,MAAA,UAAU,cAAU;CAEpB,QAAI,MAAK,8BACS;CAGlB,MAAA,EAAA,WAAgB,mBAAA,MAAA,uBAAA;EAChB;EAGA;EACA,SAAQ,KAAA;EACR;EAGA,aAAM,QAAU,QAAc,QAAA,IAAA;EAC9B,CAAA;CACA,MAAM,WAAE,EAAW;KACjB,WAAA,SAAA,KAAA,SAAA;KACA,gBAAA,SAAA,KAAA,cAAA;SACA,KAAS,SAAK,SAAA,IAAA,WAAA,SAAA,KAAA,KAAA,KAAA,wBAAA;mBACd,QAAA,aAAA,YAAA,SAAA,UAAA,KAAA,GAAA,SAAA;OACA,WAAY,YAAO,aAAoB,QAAA;OACvC,eAAA,gBAAA,YAAA,SAAA;CACF,MAAM,cAAuB,WAAA,KAAA,UAAA,WAAA,CAAA;CAC7B,sBACE,QAAc;EAChB,MAAI;EAEJ;EAGA,aAAA,KAAkB;EAGlB,eAAM,EAAW;EACjB;EACA;EAGA;EACE;EACA;EACA,gBAAa;EACb,UAAA,EAAA;EACA,SAAA;EACA,SAAA,KAAA;EACA;EACA,OAAA;EACA,CAAA;GACA,IAAA,QAAA,uBAAgB,SAAA,YAAA,OAAA,GAAA;OAChB,YAAY,KAAA,QAAA,UAAA;KACZ;EACA,MAAA,YAAc,KAAA;EACd,IAAA,WAAA,YAAA,iBAAA;GACA;GACA,UAAA;GACA;GAGF;GACA;GACE;GACA;GAEI;GACA,gBAAU;GACV,UAAA,EAAA;GACA,UAAA,UAAA;GACA,cAAA,UAAA;GACA;GACA,CAAA;OACA,IAAA,WAAA;GACA,EAAA,IAAA,KAAA,cAAgB,UAAA,MAAA,CAAA;GAChB,MAAA,oBAAY;IACZ;IACA;IACA,UAAA;IACA,SAAA;WAEK,UAAA;IACP,UAAW,EAAA,SAAA,KAAc,SAAU;IACnC,eAAM,EAAA;IACJ;IACA;IACA;IACA;IACA;IACA,gBAAY;IACZ,UAAA,EAAA;IACA,OAAA,KAAA;IACA,OAAA,KAAA;IACA,UAAA,UAAA;IACA,cAAA,UAAA;IACA;IACA,OAAA;IACA,CAAA;;kBAEY,QAAA,aAAA,YAAA,SAAA,UAAA,SAAA;WACZ;MACA,WAAA,UAAc,EAAU,OAAA,WAAA;cACxB;UACA;IACD;;OAGH,SAAA,SAAgB,YAAQ,OAAa;gBAE/B,YAAA,OAAA,WAAA,UAAA,EAAA,sBAAA,WAAA;MAEF,IAAA,KAAA,KAAW,EAAA,IAAA,KACb,4GAAkB;QAAE;;eAA+B,iBAAA,OAAA,KAAA;;CAIvD,OAAM,gBAAS,OAAS,0BAAmB;;eAG7B,cACN,MAAK;CAEb,MAAA,MAAO,QAAA,KAAA;;CAKT,IAAA,gBAAe,aAAiB,SAAuB,GAAsD;EAE3G,EAAA,MADqB,0DAEZ,aAAA,OAAA,mBAAA;EACT,IAAA,KAAO,KAAA;;GAGT;;EAUE,MAAM,WAAA,MAAe,MAAA,EAAA,YAAuB;GAE5C,SAAI;GACF,SAAQ,aAAA,KAAA,SAAA;IAER,OAAS,IAAA;IACP,OAAM;IACN,MAAA,IAAA;;GAGF,CAAA,CAAA;MACE,SAAS,WAAA,GAAA;QACT,YAAS,MAAa,iBAAY,KAAA,OAAA,KAAA,IAAA;MAChC,cAAW,MAAA;KACX,OAAO,YAAA;;;QAGR,UAAA,oBAAA,KAAA,KAAA,eAAA,CAAA,EAAA;EAEH,MAAI,cAAS,OACX,SAAA,eAAA,WAAA,QAAA,aAAA,SAAA,YAAA,KAAA,QAAA,UAAA,GAAA,CAAA,QAAA,UAAA,GAAA;EAGF,MAAM,UAAA,EAAY;EAClB,KAAI,MAAA,OAAc,UAAM;GACtB,EAAE,IAAA,KAAO,WAAY,IAAA,KAAA,UAAA,IAAA,UAAA;GACrB,MAAA,SAAA,MAAA,oBAAA;;IAKF,aAAM,IADgB;IAEtB,SAAM,IAAA;IAIN,aAAM,IAAqD;IAE3D,SAAW,IAAA,WAAO;IAChB,cAAW;IACX;IACE,OAAA,KAAY;IACZ,OAAA,KAAA;IACA,CAAA;OACA,QAAA,QAAiB,KAAA;IACjB,MAAA,IAAS;IACT;IACA,CAAA;;MAEA,QAAO,SAAK,GAAA;KACZ,IAAA,QAAA,GAAA;GACF,KAAI,MAAA,EACF,MAAA,YAAa,SAAA,EAAA,IAAA,QAAA,GAAA,KAAA,KAAA,SAAA,KAAA,OAAA,GAAA;yBAAY,QAAA,KAAA,MAAA,EAAA,KAAA,CAAA;;IAAc,MAAC,OAAA;;;OAIxC,UAAY,qBAAG,IAAA;KACjB,CAAA,SAAW;IAGX,IAAA,MAAA,6CAA+C;;;OAIjD,EAAA,MAAA,aAAA,SAAA,YAAA;;CAIF,MAAM,YAAU,MAAA,iBAAyB,KAAA,OAAA,KAAA,IAAA;CACzC,IAAI,cAAU,MAAA;EACZ,EAAE,OAAI,YAAM;EACZ;;CAGF,MAAM,SAAQ,MAAA,oBAAsB;EAEpC,YAAQ;EAER;EACA;EACE,aAAS,QAAY;EACrB;;EAGF;EACE,OAAA,KAAY;EACZ,OAAA,KAAA;EACA,CAAA;KACA,QAAA;EACA,sBAAA,CAAA,YAAA,CAAA;EACA,EAAA,MAAK,qBAAK,SAAA,KAAA,OAAA,GAAA;;;SAGH,sBAAK,cAAA;OACZ,QAAA,aAAA,KAAA,KAAA;CAEF,EAAA,IAAI,KAAA,yBAAQ,aAAA,SAAA,IAAA,iBAAA,aAAA,+CAAA,MAAA,uJAAA;;MAER,mBAAM,cAAqB;;;EAIjC,aAAS;EACP;CACA,MAAM;;GAOR,MAAa;GACX,OAAM;GAAE,aAAM;GAAW;EAA4D,OAAA;GACrF,MAAM;GACJ,OAAK;GACH,aAAM;GACN,WAAO;GACP;OACD;GACD,MAAO;GACL,OAAM;GACN,aAAO;GACP,SAAA;GACA;SACD;GACD,MAAK;GACH,OAAM;GACN,aAAO;GACP,SAAA;GACA;SACD;GACD,MAAO;GACL,aAAM;GACN,SAAO;GACP;;OAED,IAAA,EAAA,QAAA;EACD,MAAA,cAAO;GACL,KAAA,KAAM;GACN,OAAA,KAAA;GACA,KAAA,KAAS;GACV,OAAA,KAAA;GACF,OAAA,KAAA;GACD,CAAA;;;SAIS"}
1
+ {"version":3,"file":"author.mjs","names":[],"sources":["../../src/commands/author.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport type { ReferenceCache } from '../cache/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { LlmConfig } from './llm-prompts.ts'\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join, relative, resolve } from 'pathe'\nimport {\n\n computeSkillDirName,\n getModelLabel,\n writeGeneratedSkillMd,\n} from '../agent/index.ts'\nimport { enhanceSkillWithLLM, writePromptFiles } from '../agent/skill-builder.ts'\nimport { createReferenceCache, ensureCacheDir } from '../cache/index.ts'\nimport { guard } from '../cli/menu.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { detectMonorepoPackages } from '../core/monorepo.ts'\nimport { appendToJsonArray, patchPackageJson, readPackageJsonSafe } from '../core/package-json.ts'\nimport { skillInternalDir } from '../core/paths.ts'\nimport { GIT_PLUS_PREFIX_RE, GIT_SUFFIX_RE, README_FILENAME_RE } from '../core/regex.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { parseGitHubUrl } from '../core/url.ts'\nimport {\n fetchGitHubDiscussions,\n fetchGitHubIssues,\n formatDiscussionAsMarkdown,\n formatIssueAsMarkdown,\n generateDiscussionIndex,\n generateIssueIndex,\n isGhAvailable,\n readLocalPackageInfo,\n} from '../sources/index.ts'\nimport { selectLlmConfig } from './llm-prompts.ts'\nimport { detectChangelog } from './sync/pipeline.ts'\n\nconst STATIC_REGEX_1 = /\\.mdx?$/\n\n// ── Docs resolution ──\n\nfunction walkMarkdownFiles(dir: string, base = ''): Array<{ path: string, content: string }> {\n const results: Array<{ path: string, content: string }> = []\n if (!existsSync(dir))\n return results\n\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const rel = base ? `${base}/${entry.name}` : entry.name\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMarkdownFiles(full, rel))\n }\n else if (STATIC_REGEX_1.test(entry.name)) {\n results.push({ path: rel, content: readFileSync(full, 'utf-8') })\n }\n }\n return results\n}\n\n/**\n * Resolve docs from local filesystem. Cascade:\n * 1. Package-level docs/ directory\n * 2. Monorepo-root docs/ directory (if monorepoRoot provided)\n * 3. Monorepo-root docs/content/ (Nuxt Content convention)\n * 4. llms.txt in package dir\n * 5. README.md in package dir\n */\nfunction resolveLocalDocs(\n cache: ReferenceCache,\n packageDir: string,\n monorepoRoot?: string,\n): { docsType: 'docs' | 'llms.txt' | 'readme', docSource: string } {\n const cachedDocs: Array<{ path: string, content: string }> = []\n\n const cacheChangelog = () => cacheLocalChangelog(cache, packageDir, monorepoRoot)\n\n // 1. Package-level docs/\n const docsDir = join(packageDir, 'docs')\n if (existsSync(docsDir)) {\n const mdFiles = walkMarkdownFiles(docsDir)\n if (mdFiles.length > 0) {\n for (const f of mdFiles)\n cachedDocs.push({ path: `docs/${f.path}`, content: sanitizeMarkdown(f.content) })\n cache.write(cachedDocs)\n cacheChangelog()\n return { docsType: 'docs', docSource: `local docs/ (${mdFiles.length} files)` }\n }\n }\n\n // 2. Monorepo-root docs/ or docs/content/\n if (monorepoRoot) {\n for (const candidate of ['docs/content', 'docs']) {\n const rootDocsDir = join(monorepoRoot, candidate)\n if (existsSync(rootDocsDir)) {\n const mdFiles = walkMarkdownFiles(rootDocsDir)\n if (mdFiles.length > 0) {\n for (const f of mdFiles)\n cachedDocs.push({ path: `docs/${f.path}`, content: sanitizeMarkdown(f.content) })\n cache.write(cachedDocs)\n cacheChangelog()\n return { docsType: 'docs', docSource: `monorepo ${candidate}/ (${mdFiles.length} files)` }\n }\n }\n }\n }\n\n // 3. llms.txt (package dir, then monorepo root)\n for (const dir of [packageDir, monorepoRoot].filter(Boolean) as string[]) {\n const llmsPath = join(dir, 'llms.txt')\n if (existsSync(llmsPath)) {\n cachedDocs.push({ path: 'llms.txt', content: sanitizeMarkdown(readFileSync(llmsPath, 'utf-8')) })\n cache.write(cachedDocs)\n cacheChangelog()\n const source = dir === packageDir ? 'local llms.txt' : 'monorepo llms.txt'\n return { docsType: 'llms.txt', docSource: source }\n }\n }\n\n // 4. README.md (package dir, then monorepo root)\n for (const dir of [packageDir, monorepoRoot].filter(Boolean) as string[]) {\n const readmeFile = readdirSync(dir).find(f => README_FILENAME_RE.test(f))\n if (readmeFile) {\n cachedDocs.push({ path: 'docs/README.md', content: sanitizeMarkdown(readFileSync(join(dir, readmeFile), 'utf-8')) })\n cache.write(cachedDocs)\n cacheChangelog()\n const source = dir === packageDir ? 'local README.md' : 'monorepo README.md'\n return { docsType: 'readme', docSource: source }\n }\n }\n\n cacheChangelog()\n return { docsType: 'readme', docSource: 'none' }\n}\n\nfunction cacheLocalChangelog(cache: ReferenceCache, dir: string, monorepoRoot?: string): void {\n const candidates = ['CHANGELOG.md', 'changelog.md']\n const changelogFile = candidates.find(f => existsSync(join(dir, f)))\n || (monorepoRoot ? candidates.find(f => existsSync(join(monorepoRoot, f))) : undefined)\n const changelogDir = changelogFile && existsSync(join(dir, changelogFile)) ? dir : monorepoRoot\n if (changelogFile && changelogDir) {\n cache.write([{\n path: `releases/${changelogFile}`,\n content: sanitizeMarkdown(readFileSync(join(changelogDir, changelogFile), 'utf-8')),\n }])\n }\n}\n\n// ── Remote supplements ──\n\nasync function fetchRemoteSupplements(opts: {\n cache: ReferenceCache\n repoUrl?: string\n features: FeaturesConfig\n onProgress: (msg: string) => void\n}): Promise<{ hasIssues: boolean, hasDiscussions: boolean }> {\n const { cache, repoUrl, features, onProgress } = opts\n\n if (!repoUrl || !isGhAvailable())\n return { hasIssues: false, hasDiscussions: false }\n\n const gh = parseGitHubUrl(repoUrl)\n if (!gh)\n return { hasIssues: false, hasDiscussions: false }\n\n let hasIssues = false\n const issuesDir = join(cache.dir, 'issues')\n if (features.issues && !existsSync(issuesDir)) {\n onProgress('Fetching issues via GitHub API')\n const issues = await fetchGitHubIssues(gh.owner, gh.repo, 30).catch(() => [])\n if (issues.length > 0) {\n onProgress(`Caching ${issues.length} issues`)\n cache.write(issues.map(issue => ({\n path: `issues/issue-${issue.number}.md`,\n content: formatIssueAsMarkdown(issue),\n })))\n cache.write([{\n path: 'issues/_INDEX.md',\n content: generateIssueIndex(issues),\n }])\n hasIssues = true\n }\n }\n else {\n hasIssues = features.issues && existsSync(issuesDir)\n }\n\n let hasDiscussions = false\n const discussionsDir = join(cache.dir, 'discussions')\n if (features.discussions && !existsSync(discussionsDir)) {\n onProgress('Fetching discussions via GitHub API')\n const discussions = await fetchGitHubDiscussions(gh.owner, gh.repo, 20).catch(() => [])\n if (discussions.length > 0) {\n onProgress(`Caching ${discussions.length} discussions`)\n cache.write(discussions.map(d => ({\n path: `discussions/discussion-${d.number}.md`,\n content: formatDiscussionAsMarkdown(d),\n })))\n cache.write([{\n path: 'discussions/_INDEX.md',\n content: generateDiscussionIndex(discussions),\n }])\n hasDiscussions = true\n }\n }\n else {\n hasDiscussions = features.discussions && existsSync(discussionsDir)\n }\n\n return { hasIssues, hasDiscussions }\n}\n\n// ── package.json patching ──\n\nexport function patchPackageJsonFiles(packageDir: string): void {\n const pkgPath = join(packageDir, 'package.json')\n if (!existsSync(pkgPath))\n return\n\n const wrote = patchPackageJson(pkgPath, (raw, pkg) => {\n if (!Array.isArray(pkg.files)) {\n p.log.warn('No `files` array in package.json. Add `\"skills\"` to your files array manually.')\n return null\n }\n\n if ((pkg.files as string[]).some((f: string) => f === 'skills' || f === 'skills/' || f === 'skills/**'))\n return null\n\n return appendToJsonArray(raw, ['files'], 'skills')\n })\n\n if (wrote)\n p.log.success('Added `\"skills\"` to package.json files array')\n}\n\n// ── Core author flow for a single package ──\n\nasync function authorSinglePackage(opts: {\n packageDir: string\n packageName: string\n version: string\n description?: string\n repoUrl?: string\n monorepoRoot?: string\n out?: string\n llmConfig?: LlmConfig | null\n force?: boolean\n debug?: boolean\n}): Promise<string | null> {\n const { packageDir, packageName, version } = opts\n const spin = timedSpinner()\n\n const sanitizedName = computeSkillDirName(packageName)\n const outDir = opts.out ? resolve(packageDir, opts.out) : join(packageDir, 'skills', sanitizedName)\n\n // Validate --out doesn't point at the package root or a parent\n if (opts.out) {\n const rel = relative(packageDir, outDir)\n if (!rel || rel === '.' || rel.startsWith('..')) {\n p.log.error('--out must point to a child directory, not the package root or a parent')\n return null\n }\n }\n\n if (existsSync(outDir))\n rmSync(outDir, { recursive: true, force: true })\n mkdirSync(outDir, { recursive: true })\n\n const cache = createReferenceCache(packageName, version)\n\n if (opts.force) {\n cache.clearForce()\n }\n\n ensureCacheDir()\n const features = readConfig().features ?? defaultFeatures\n\n // Resolve local docs\n spin.start('Resolving local docs')\n const { docsType, docSource } = resolveLocalDocs(cache, packageDir, opts.monorepoRoot)\n spin.stop(`Resolved docs: ${docSource}`)\n\n // Fetch remote supplements (issues/discussions)\n const supSpin = timedSpinner()\n supSpin.start('Checking remote supplements')\n const { hasIssues, hasDiscussions } = await fetchRemoteSupplements({\n cache,\n repoUrl: opts.repoUrl,\n features,\n onProgress: msg => supSpin.message(msg),\n })\n const supParts: string[] = []\n if (hasIssues)\n supParts.push('issues')\n if (hasDiscussions)\n supParts.push('discussions')\n supSpin.stop(supParts.length > 0 ? `Fetched ${supParts.join(', ')}` : 'No remote supplements')\n\n // Create temporary .skilld/ symlinks (LLM needs these to read docs)\n cache.linkInto(outDir, packageDir, docsType, { features })\n\n // Detect changelog + releases\n const hasChangelog = detectChangelog(packageDir, cache.dir)\n const hasReleases = existsSync(join(cache.dir, 'releases'))\n\n // Generate base SKILL.md\n writeGeneratedSkillMd(outDir, {\n name: packageName,\n version,\n description: opts.description,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n hasChangelog,\n docsType,\n hasShippedDocs: false,\n pkgFiles: [],\n dirName: sanitizedName,\n repoUrl: opts.repoUrl,\n features,\n eject: true,\n })\n p.log.success(`Created base skill: ${relative(packageDir, outDir)}`)\n\n // LLM enhancement (config resolved by caller)\n const skilldDir = skillInternalDir(outDir)\n try {\n const llmConfig = opts.llmConfig\n const baseCtx = {\n packageName,\n version,\n skillDir: outDir,\n dirName: sanitizedName,\n references: {\n docsType,\n hasShippedDocs: false,\n pkgFiles: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n hasChangelog,\n },\n resolved: { repoUrl: opts.repoUrl },\n relatedSkills: [],\n features,\n }\n if (llmConfig?.promptOnly) {\n writePromptFiles(baseCtx, {\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n })\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n await enhanceSkillWithLLM(baseCtx, {\n model: llmConfig.model,\n force: opts.force,\n debug: opts.debug,\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n eject: true,\n })\n }\n\n cache.eject(outDir, packageDir, docsType, { features })\n }\n finally {\n // Always clean up .skilld/ symlinks, even if LLM enhancement fails\n if (existsSync(skilldDir))\n rmSync(skilldDir, { recursive: true, force: true })\n }\n\n // Only patch package.json when output is under skills/\n const relOut = relative(packageDir, outDir)\n if (relOut === 'skills' || relOut.startsWith('skills/'))\n patchPackageJsonFiles(packageDir)\n else if (opts.out)\n p.log.info('Output is outside skills/, skipping package.json patch. Add the path to \"files\" manually if publishing.')\n\n return outDir\n}\n\n// ── Main command ──\n\nasync function resolveLlmConfig(model?: OptimizeModel, yes?: boolean): Promise<LlmConfig | null | undefined> {\n const globalConfig = readConfig()\n if (globalConfig.skipLlm || (yes && !model))\n return undefined\n return selectLlmConfig(model, 'Generate skill sections')\n}\n\nasync function authorCommand(opts: {\n out?: string\n model?: OptimizeModel\n yes?: boolean\n force?: boolean\n debug?: boolean\n}): Promise<void> {\n const cwd = process.cwd()\n\n // Check for monorepo\n const monoPackages = detectMonorepoPackages(cwd)\n\n if (monoPackages && monoPackages.length > 0) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} author ${styleText('gray', `(monorepo: ${monoPackages.length} packages)`)}`)\n\n if (opts.out) {\n p.log.error('--out is not supported in monorepo mode (each package gets its own skills/ directory)')\n return\n }\n\n const selected = guard(await p.multiselect({\n message: 'Which packages should ship skills?',\n options: monoPackages.map(pkg => ({\n label: pkg.name,\n value: pkg,\n hint: pkg.description,\n })),\n }))\n\n if (selected.length === 0)\n return\n\n // Resolve LLM config once for all packages\n const llmConfig = await resolveLlmConfig(opts.model, opts.yes)\n if (llmConfig === null) {\n p.cancel('Cancelled')\n return\n }\n\n // Resolve monorepo-level repoUrl for packages that lack their own\n const rootPkgResult = readPackageJsonSafe(join(cwd, 'package.json'))\n const rootPkg = rootPkgResult?.parsed as Record<string, any> | undefined\n const rootRepoUrl = typeof rootPkg?.repository === 'string'\n ? rootPkg.repository\n : rootPkg?.repository?.url?.replace(GIT_PLUS_PREFIX_RE, '').replace(GIT_SUFFIX_RE, '')\n\n const results: Array<{ name: string, outDir: string }> = []\n\n for (const pkg of selected) {\n p.log.step(`${styleText('cyan', pkg.name)}@${pkg.version}`)\n const outDir = await authorSinglePackage({\n packageDir: pkg.dir,\n packageName: pkg.name,\n version: pkg.version,\n description: pkg.description,\n repoUrl: pkg.repoUrl || rootRepoUrl,\n monorepoRoot: cwd,\n llmConfig,\n force: opts.force,\n debug: opts.debug,\n })\n if (outDir)\n results.push({ name: pkg.name, outDir })\n }\n\n if (results.length > 0) {\n p.log.message('')\n for (const { name, outDir } of results)\n p.log.success(`${name} → ${relative(cwd, outDir)}`)\n\n printConsumerGuidance(results.map(r => r.name))\n }\n\n p.outro('Done')\n return\n }\n\n // Single package mode\n const pkgInfo = readLocalPackageInfo(cwd)\n if (!pkgInfo) {\n p.log.error('No package.json found in current directory')\n return\n }\n\n const { name: packageName, version, repoUrl } = pkgInfo\n\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} author ${styleText('cyan', packageName)}@${version}`)\n\n const llmConfig = await resolveLlmConfig(opts.model, opts.yes)\n if (llmConfig === null) {\n p.cancel('Cancelled')\n return\n }\n\n const outDir = await authorSinglePackage({\n packageDir: cwd,\n packageName,\n version,\n description: pkgInfo.description,\n repoUrl,\n out: opts.out,\n llmConfig,\n force: opts.force,\n debug: opts.debug,\n })\n\n if (outDir) {\n printConsumerGuidance([packageName])\n p.outro(`Authored skill to ${relative(cwd, outDir)}`)\n }\n}\n\nfunction printConsumerGuidance(packageNames: string[]): void {\n const names = packageNames.join(', ')\n p.log.info(\n `${styleText('gray', `Consumers get ${packageNames.length > 1 ? 'these skills' : 'this skill'} automatically:`)}\\n`\n + ` ${styleText('gray', `1. Install ${names} as a dependency`)}\\n`\n + ` ${styleText('gray', '2. Run ')}${styleText('cyan', 'skilld prepare')}${styleText('gray', ' (or add to package.json: ')}${styleText('cyan', '\"prepare\": \"skilld prepare\"')}${styleText('gray', ')')}`,\n )\n}\n\nexport const authorCommandDef = defineCommand({\n meta: { name: 'package', description: 'Generate a package skill from documentation' },\n args: {\n out: {\n type: 'string',\n alias: 'o',\n description: 'Output directory (default: ./skills/<name>/)',\n },\n model: {\n type: 'string',\n alias: 'm',\n description: 'Enhancement model for SKILL.md generation',\n valueHint: 'id',\n },\n yes: {\n type: 'boolean',\n alias: 'y',\n description: 'Skip prompts, use defaults',\n default: false,\n },\n force: {\n type: 'boolean',\n alias: 'f',\n description: 'Clear cache and regenerate',\n default: false,\n },\n debug: {\n type: 'boolean',\n description: 'Save raw enhancement output to logs/',\n default: false,\n },\n },\n async run({ args }) {\n await authorCommand({\n out: args.out,\n model: args.model as OptimizeModel | undefined,\n yes: args.yes,\n force: args.force,\n debug: args.debug,\n })\n },\n})\n\nexport const authorGroupDef = defineCommand({\n meta: { name: 'author', description: 'Create, generate, and publish skills' },\n subCommands: {\n package: () => import('./author.ts').then(m => m.authorCommandDef),\n publish: () => import('./upload.ts').then(m => m.uploadCommandDef),\n eject: () => import('./sync/eject.ts').then(m => m.ejectCommandDef),\n validate: () => import('./validate.ts').then(m => m.validateCommandDef),\n assemble: () => import('./assemble.ts').then(m => m.assembleCommandDef),\n },\n})\n"],"mappings":"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"}