@niujiajie/freespec 0.0.0-stage → 1.15.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 (308) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +58 -2
  3. package/bin/freespec.js +5 -0
  4. package/dist/cli/index.d.ts +25 -0
  5. package/dist/cli/index.js +359 -0
  6. package/dist/commands/shared-output.d.ts +18 -0
  7. package/dist/commands/shared-output.js +61 -0
  8. package/dist/commands/workflow/default-schema.d.ts +2 -0
  9. package/dist/commands/workflow/default-schema.js +4 -0
  10. package/dist/commands/workflow/index.d.ts +13 -0
  11. package/dist/commands/workflow/index.js +10 -0
  12. package/dist/commands/workflow/instructions.d.ts +39 -0
  13. package/dist/commands/workflow/instructions.js +565 -0
  14. package/dist/commands/workflow/new-change.d.ts +19 -0
  15. package/dist/commands/workflow/new-change.js +135 -0
  16. package/dist/commands/workflow/shared.d.ts +94 -0
  17. package/dist/commands/workflow/shared.js +169 -0
  18. package/dist/commands/workflow/status.d.ts +18 -0
  19. package/dist/commands/workflow/status.js +201 -0
  20. package/dist/core/artifact-graph/graph.d.ts +72 -0
  21. package/dist/core/artifact-graph/graph.js +165 -0
  22. package/dist/core/artifact-graph/index.d.ts +9 -0
  23. package/dist/core/artifact-graph/index.js +14 -0
  24. package/dist/core/artifact-graph/instruction-loader.d.ts +208 -0
  25. package/dist/core/artifact-graph/instruction-loader.js +268 -0
  26. package/dist/core/artifact-graph/outputs.d.ts +19 -0
  27. package/dist/core/artifact-graph/outputs.js +351 -0
  28. package/dist/core/artifact-graph/resolver.d.ts +89 -0
  29. package/dist/core/artifact-graph/resolver.js +342 -0
  30. package/dist/core/artifact-graph/schema.d.ts +27 -0
  31. package/dist/core/artifact-graph/schema.js +160 -0
  32. package/dist/core/artifact-graph/state.d.ts +12 -0
  33. package/dist/core/artifact-graph/state.js +31 -0
  34. package/dist/core/artifact-graph/types.d.ts +40 -0
  35. package/dist/core/artifact-graph/types.js +59 -0
  36. package/dist/core/available-tools.d.ts +18 -0
  37. package/dist/core/available-tools.js +49 -0
  38. package/dist/core/change-layout.d.ts +17 -0
  39. package/dist/core/change-layout.js +30 -0
  40. package/dist/core/change-metadata/index.d.ts +2 -0
  41. package/dist/core/change-metadata/index.js +2 -0
  42. package/dist/core/change-metadata/schema.d.ts +23 -0
  43. package/dist/core/change-metadata/schema.js +46 -0
  44. package/dist/core/change-status-policy.d.ts +49 -0
  45. package/dist/core/change-status-policy.js +50 -0
  46. package/dist/core/command-generation/adapters/amazon-q.d.ts +17 -0
  47. package/dist/core/command-generation/adapters/amazon-q.js +32 -0
  48. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  49. package/dist/core/command-generation/adapters/antigravity.js +27 -0
  50. package/dist/core/command-generation/adapters/atomcode.d.ts +24 -0
  51. package/dist/core/command-generation/adapters/atomcode.js +46 -0
  52. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  53. package/dist/core/command-generation/adapters/auggie.js +28 -0
  54. package/dist/core/command-generation/adapters/bob.d.ts +18 -0
  55. package/dist/core/command-generation/adapters/bob.js +33 -0
  56. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  57. package/dist/core/command-generation/adapters/claude.js +32 -0
  58. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  59. package/dist/core/command-generation/adapters/cline.js +27 -0
  60. package/dist/core/command-generation/adapters/codeassistant.d.ts +15 -0
  61. package/dist/core/command-generation/adapters/codeassistant.js +29 -0
  62. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  63. package/dist/core/command-generation/adapters/codebuddy.js +29 -0
  64. package/dist/core/command-generation/adapters/codestudio.d.ts +13 -0
  65. package/dist/core/command-generation/adapters/codestudio.js +27 -0
  66. package/dist/core/command-generation/adapters/command-code.d.ts +19 -0
  67. package/dist/core/command-generation/adapters/command-code.js +34 -0
  68. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/continue.js +33 -0
  70. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/costrict.js +28 -0
  72. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  73. package/dist/core/command-generation/adapters/crush.js +30 -0
  74. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  75. package/dist/core/command-generation/adapters/cursor.js +31 -0
  76. package/dist/core/command-generation/adapters/devin.d.ts +19 -0
  77. package/dist/core/command-generation/adapters/devin.js +36 -0
  78. package/dist/core/command-generation/adapters/easycode.d.ts +17 -0
  79. package/dist/core/command-generation/adapters/easycode.js +28 -0
  80. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/factory.js +28 -0
  82. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  83. package/dist/core/command-generation/adapters/gemini.js +27 -0
  84. package/dist/core/command-generation/adapters/gigacode.d.ts +17 -0
  85. package/dist/core/command-generation/adapters/gigacode.js +31 -0
  86. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/github-copilot.js +27 -0
  88. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/iflow.js +30 -0
  90. package/dist/core/command-generation/adapters/index.d.ts +40 -0
  91. package/dist/core/command-generation/adapters/index.js +40 -0
  92. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  93. package/dist/core/command-generation/adapters/junie.js +27 -0
  94. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  95. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  96. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  97. package/dist/core/command-generation/adapters/kiro.js +27 -0
  98. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  99. package/dist/core/command-generation/adapters/lingma.js +30 -0
  100. package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
  101. package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
  102. package/dist/core/command-generation/adapters/opencode.d.ts +14 -0
  103. package/dist/core/command-generation/adapters/opencode.js +38 -0
  104. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  105. package/dist/core/command-generation/adapters/pi.js +39 -0
  106. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/qoder.js +30 -0
  108. package/dist/core/command-generation/adapters/qwen.d.ts +17 -0
  109. package/dist/core/command-generation/adapters/qwen.js +31 -0
  110. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  111. package/dist/core/command-generation/adapters/roocode.js +27 -0
  112. package/dist/core/command-generation/adapters/trae.d.ts +13 -0
  113. package/dist/core/command-generation/adapters/trae.js +28 -0
  114. package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
  115. package/dist/core/command-generation/adapters/zcode.js +33 -0
  116. package/dist/core/command-generation/generator.d.ts +29 -0
  117. package/dist/core/command-generation/generator.js +43 -0
  118. package/dist/core/command-generation/index.d.ts +22 -0
  119. package/dist/core/command-generation/index.js +24 -0
  120. package/dist/core/command-generation/invocation.d.ts +73 -0
  121. package/dist/core/command-generation/invocation.js +77 -0
  122. package/dist/core/command-generation/registry.d.ts +36 -0
  123. package/dist/core/command-generation/registry.js +114 -0
  124. package/dist/core/command-generation/toml.d.ts +19 -0
  125. package/dist/core/command-generation/toml.js +39 -0
  126. package/dist/core/command-generation/types.d.ts +63 -0
  127. package/dist/core/command-generation/types.js +8 -0
  128. package/dist/core/command-generation/yaml.d.ts +36 -0
  129. package/dist/core/command-generation/yaml.js +48 -0
  130. package/dist/core/command-surface.d.ts +15 -0
  131. package/dist/core/command-surface.js +33 -0
  132. package/dist/core/config-prompts.d.ts +9 -0
  133. package/dist/core/config-prompts.js +56 -0
  134. package/dist/core/config-schema.d.ts +98 -0
  135. package/dist/core/config-schema.js +308 -0
  136. package/dist/core/config.d.ts +50 -0
  137. package/dist/core/config.js +122 -0
  138. package/dist/core/file-state.d.ts +36 -0
  139. package/dist/core/file-state.js +144 -0
  140. package/dist/core/file-view.d.ts +13 -0
  141. package/dist/core/file-view.js +14 -0
  142. package/dist/core/global-config.d.ts +101 -0
  143. package/dist/core/global-config.js +182 -0
  144. package/dist/core/id.d.ts +17 -0
  145. package/dist/core/id.js +30 -0
  146. package/dist/core/index.d.ts +6 -0
  147. package/dist/core/index.js +7 -0
  148. package/dist/core/init.d.ts +57 -0
  149. package/dist/core/init.js +836 -0
  150. package/dist/core/list.d.ts +11 -0
  151. package/dist/core/list.js +197 -0
  152. package/dist/core/migration.d.ts +121 -0
  153. package/dist/core/migration.js +540 -0
  154. package/dist/core/onboarding-commands.d.ts +30 -0
  155. package/dist/core/onboarding-commands.js +38 -0
  156. package/dist/core/openspec-root.d.ts +47 -0
  157. package/dist/core/openspec-root.js +196 -0
  158. package/dist/core/planning-home.d.ts +16 -0
  159. package/dist/core/planning-home.js +67 -0
  160. package/dist/core/profile-sync-drift.d.ts +31 -0
  161. package/dist/core/profile-sync-drift.js +201 -0
  162. package/dist/core/profiles.d.ts +19 -0
  163. package/dist/core/profiles.js +33 -0
  164. package/dist/core/project-config.d.ts +132 -0
  165. package/dist/core/project-config.js +519 -0
  166. package/dist/core/references.d.ts +10 -0
  167. package/dist/core/references.js +46 -0
  168. package/dist/core/root-selection.d.ts +59 -0
  169. package/dist/core/root-selection.js +132 -0
  170. package/dist/core/shared/allowed-tools.d.ts +12 -0
  171. package/dist/core/shared/allowed-tools.js +12 -0
  172. package/dist/core/shared/ide-restart.d.ts +26 -0
  173. package/dist/core/shared/ide-restart.js +42 -0
  174. package/dist/core/shared/index.d.ts +11 -0
  175. package/dist/core/shared/index.js +11 -0
  176. package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
  177. package/dist/core/shared/skill-content-equivalence.js +45 -0
  178. package/dist/core/shared/skill-files.d.ts +7 -0
  179. package/dist/core/shared/skill-files.js +43 -0
  180. package/dist/core/shared/skill-generation.d.ts +49 -0
  181. package/dist/core/shared/skill-generation.js +125 -0
  182. package/dist/core/shared/skill-paths.d.ts +13 -0
  183. package/dist/core/shared/skill-paths.js +23 -0
  184. package/dist/core/shared/tool-detection.d.ts +99 -0
  185. package/dist/core/shared/tool-detection.js +318 -0
  186. package/dist/core/shared-skill-target.d.ts +51 -0
  187. package/dist/core/shared-skill-target.js +239 -0
  188. package/dist/core/store/errors.d.ts +20 -0
  189. package/dist/core/store/errors.js +22 -0
  190. package/dist/core/store/index.d.ts +2 -0
  191. package/dist/core/store/index.js +2 -0
  192. package/dist/core/styles/palette.d.ts +7 -0
  193. package/dist/core/styles/palette.js +8 -0
  194. package/dist/core/templates/optional-workflow.d.ts +69 -0
  195. package/dist/core/templates/optional-workflow.js +140 -0
  196. package/dist/core/templates/types.d.ts +19 -0
  197. package/dist/core/templates/types.js +5 -0
  198. package/dist/core/templates/workflows/personal.d.ts +22 -0
  199. package/dist/core/templates/workflows/personal.js +225 -0
  200. package/dist/core/update-plan.d.ts +127 -0
  201. package/dist/core/update-plan.js +390 -0
  202. package/dist/core/update.d.ts +154 -0
  203. package/dist/core/update.js +723 -0
  204. package/dist/core/version-check.d.ts +188 -0
  205. package/dist/core/version-check.js +906 -0
  206. package/dist/core/zod-issues.d.ts +4 -0
  207. package/dist/core/zod-issues.js +10 -0
  208. package/dist/index.d.ts +3 -0
  209. package/dist/index.js +3 -0
  210. package/dist/prompts/searchable-multi-select.d.ts +35 -0
  211. package/dist/prompts/searchable-multi-select.js +188 -0
  212. package/dist/telemetry/config.d.ts +37 -0
  213. package/dist/telemetry/config.js +148 -0
  214. package/dist/telemetry/index.d.ts +39 -0
  215. package/dist/telemetry/index.js +217 -0
  216. package/dist/telemetry/opt-out.d.ts +17 -0
  217. package/dist/telemetry/opt-out.js +27 -0
  218. package/dist/ui/ascii-patterns.d.ts +16 -0
  219. package/dist/ui/ascii-patterns.js +133 -0
  220. package/dist/ui/welcome-screen.d.ts +18 -0
  221. package/dist/ui/welcome-screen.js +199 -0
  222. package/dist/utils/change-metadata.d.ts +116 -0
  223. package/dist/utils/change-metadata.js +324 -0
  224. package/dist/utils/change-utils.d.ts +79 -0
  225. package/dist/utils/change-utils.js +121 -0
  226. package/dist/utils/ci.d.ts +12 -0
  227. package/dist/utils/ci.js +16 -0
  228. package/dist/utils/command-references.d.ts +104 -0
  229. package/dist/utils/command-references.js +190 -0
  230. package/dist/utils/date.d.ts +8 -0
  231. package/dist/utils/date.js +13 -0
  232. package/dist/utils/executable-path.d.ts +5 -0
  233. package/dist/utils/executable-path.js +44 -0
  234. package/dist/utils/file-system.d.ts +58 -0
  235. package/dist/utils/file-system.js +432 -0
  236. package/dist/utils/index.d.ts +6 -0
  237. package/dist/utils/index.js +9 -0
  238. package/dist/utils/interactive.d.ts +85 -0
  239. package/dist/utils/interactive.js +174 -0
  240. package/dist/utils/item-discovery.d.ts +15 -0
  241. package/dist/utils/item-discovery.js +33 -0
  242. package/dist/utils/line-endings.d.ts +34 -0
  243. package/dist/utils/line-endings.js +46 -0
  244. package/dist/utils/match.d.ts +3 -0
  245. package/dist/utils/match.js +22 -0
  246. package/dist/utils/nested-change.d.ts +35 -0
  247. package/dist/utils/nested-change.js +185 -0
  248. package/dist/utils/shell-detection.d.ts +20 -0
  249. package/dist/utils/shell-detection.js +94 -0
  250. package/dist/utils/task-progress.d.ts +67 -0
  251. package/dist/utils/task-progress.js +184 -0
  252. package/package.json +74 -4
  253. package/schemas//351/273/230/350/256/244/schema.yaml +68 -0
  254. package/schemas//351/273/230/350/256/244/templates//344/273/273/345/212/241/346/270/205/345/215/225.md +25 -0
  255. package/schemas//351/273/230/350/256/244/templates//346/265/213/350/257/225/347/224/250/344/276/213.md +34 -0
  256. package/schemas//351/273/230/350/256/244/templates//350/256/276/350/256/241/346/226/207/346/241/243.md +172 -0
  257. package/schemas//351/273/230/350/256/244/templates//351/234/200/346/261/202/346/226/207/346/241/243.md +19 -0
  258. package/skill-files//344/273/273/345/212/241/references//346/212/244/346/240/217.md +43 -0
  259. package/skill-files//344/273/273/345/212/241/references//347/262/222/345/272/246.md +23 -0
  260. package/skill-files//344/273/273/345/212/241/references//347/272/246/346/235/237.md +8 -0
  261. package/skill-files//344/273/273/345/212/241/scripts/check-tasks.mjs +83 -0
  262. package/skill-files//345/206/231Java/references/Java/350/247/204/350/214/203.md +25 -0
  263. package/skill-files//345/206/231Java/references//345/215/261/351/231/251/345/206/231/346/263/225.md +27 -0
  264. package/skill-files//345/206/231Java/references//345/256/214/346/210/220/345/257/271/347/205/247.md +15 -0
  265. package/skill-files//345/206/231Java/references//346/212/244/346/240/217.md +35 -0
  266. package/skill-files//345/206/231Java/references//347/272/246/346/235/237.md +8 -0
  267. package/skill-files//345/206/231Java/references//350/270/251/345/235/221.md +17 -0
  268. package/skill-files//345/256/241Java/references//346/212/244/346/240/217.md +19 -0
  269. package/skill-files//345/256/241Java/references//347/244/272/344/276/213.md +23 -0
  270. package/skill-files//345/256/241Java/references//347/272/246/346/235/237.md +7 -0
  271. package/skill-files//345/256/241Java/references//350/247/204/345/210/231.md +23 -0
  272. package/skill-files//345/256/241Java/references//351/242/206/345/237/237/346/243/200/351/241/271.md +58 -0
  273. package/skill-files//345/256/241/346/226/207/346/241/243/references//346/212/244/346/240/217.md +18 -0
  274. package/skill-files//345/256/241/346/226/207/346/241/243/references//347/272/246/346/235/237.md +8 -0
  275. package/skill-files//345/256/241/346/226/207/346/241/243/references//347/273/264/345/272/246.md +17 -0
  276. package/skill-files//345/256/241/346/226/207/346/241/243/references//350/270/251/345/235/221.md +11 -0
  277. package/skill-files//346/226/260/345/273/272/references//344/272/244/346/216/245.md +11 -0
  278. package/skill-files//346/226/260/345/273/272/references//346/212/244/346/240/217.md +14 -0
  279. package/skill-files//346/226/260/345/273/272/references//347/272/246/346/235/237.md +7 -0
  280. package/skill-files//346/267/261/346/200/235/config/prompts.yaml +114 -0
  281. package/skill-files//346/267/261/346/200/235/references//344/270/211/346/226/271/346/240/270/345/257/271.md +72 -0
  282. package/skill-files//346/267/261/346/200/235/references//344/276/213/345/255/220.md +39 -0
  283. package/skill-files//346/267/261/346/200/235/references//346/200/216/344/271/210/346/203/263.md +61 -0
  284. package/skill-files//346/267/261/346/200/235/references//346/212/244/346/240/217.md +26 -0
  285. package/skill-files//346/267/261/346/200/235/references//347/202/271/351/200/211/346/217/220/351/227/256.md +66 -0
  286. package/skill-files//346/267/261/346/200/235/references//347/231/273/350/256/260.md +45 -0
  287. package/skill-files//346/267/261/346/200/235/references//347/272/246/346/235/237.md +9 -0
  288. package/skill-files//347/224/250/344/276/213/references//346/200/216/344/271/210/345/206/231.md +13 -0
  289. package/skill-files//347/224/250/344/276/213/references//346/212/244/346/240/217.md +42 -0
  290. package/skill-files//347/224/250/344/276/213/references//347/272/246/346/235/237.md +5 -0
  291. package/skill-files//347/224/250/344/276/213/scripts/check-cases.mjs +70 -0
  292. package/skill-files//350/256/276/350/256/241/references//345/207/206/345/244/207.md +25 -0
  293. package/skill-files//350/256/276/350/256/241/references//346/212/244/346/240/217.md +134 -0
  294. package/skill-files//350/256/276/350/256/241/references//346/226/207/351/243/216.md +17 -0
  295. package/skill-files//350/256/276/350/256/241/references//347/225/214/351/235/242.md +18 -0
  296. package/skill-files//350/256/276/350/256/241/references//347/261/273/345/236/213.md +19 -0
  297. package/skill-files//350/256/276/350/256/241/references//347/272/246/346/235/237.md +25 -0
  298. package/skill-files//350/256/276/350/256/241/scripts/_smoke.mjs +72 -0
  299. package/skill-files//350/256/276/350/256/241/scripts/check-design.mjs +331 -0
  300. package/skill-files//351/234/200/346/261/202/references//346/212/244/346/240/217.md +26 -0
  301. package/skill-files//351/234/200/346/261/202/references//346/226/207/351/243/216.md +23 -0
  302. package/skill-files//351/234/200/346/261/202/references//346/267/261/346/200/235/346/221/204/345/205/245.md +21 -0
  303. package/skill-files//351/234/200/346/261/202/references//347/272/246/346/235/237.md +8 -0
  304. package/skill-files//351/234/200/346/261/202/references//351/234/200/346/261/202/345/276/205/345/256/232.md +13 -0
  305. package/skill-files//351/234/200/346/261/202/scripts/check-requirements.mjs +60 -0
  306. package/skill-files//351/252/214/346/224/266/references//346/212/244/346/240/217.md +27 -0
  307. package/skill-files//351/252/214/346/224/266/references//346/240/270/345/257/271.md +17 -0
  308. package/skill-files//351/252/214/346/224/266/references//347/272/246/346/235/237.md +7 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Command Generation Types
3
+ *
4
+ * Tool-agnostic interfaces for command generation.
5
+ * These types separate "what to generate" from "how to format it".
6
+ */
7
+ /**
8
+ * Tool-agnostic command data.
9
+ * Represents the content of a command without any tool-specific formatting.
10
+ */
11
+ export interface CommandContent {
12
+ /** Command identifier (e.g., 'explore', 'apply', 'new') */
13
+ id: string;
14
+ /** Human-readable name (e.g., 'FreeSpec Explore') */
15
+ name: string;
16
+ /** Brief description of command purpose */
17
+ description: string;
18
+ /** Grouping category (e.g., 'Workflow') */
19
+ category: string;
20
+ /** Array of tag strings */
21
+ tags: string[];
22
+ /** The command instruction content (body text) */
23
+ body: string;
24
+ }
25
+ /**
26
+ * Per-tool formatting strategy.
27
+ * Each AI tool implements this interface to handle its specific file path
28
+ * and frontmatter format requirements.
29
+ */
30
+ export interface ToolCommandAdapter {
31
+ /** Tool identifier matching AIToolOption.value (e.g., 'claude', 'cursor') */
32
+ toolId: string;
33
+ /**
34
+ * Returns the file path for a command.
35
+ * @param commandId - The command identifier (e.g., 'explore')
36
+ * @returns Path from project root (e.g., '.claude/commands/freespec/explore.md').
37
+ * May be absolute for tools with global-scoped command files.
38
+ */
39
+ getFilePath(commandId: string): string;
40
+ /**
41
+ * What the user types before the command name, when it is not the default
42
+ * `/`. Amazon Q loads these files into its prompt library, which is invoked
43
+ * with `@` (`@freespec-propose`), so its adapter sets '@'. The name itself is
44
+ * still derived from getFilePath — see invocation.ts.
45
+ */
46
+ invocationPrefix?: string;
47
+ /**
48
+ * Formats the complete file content including frontmatter.
49
+ * @param content - The tool-agnostic command content
50
+ * @returns Complete file content ready to write
51
+ */
52
+ formatFile(content: CommandContent): string;
53
+ }
54
+ /**
55
+ * Result of generating a command file.
56
+ */
57
+ export interface GeneratedCommand {
58
+ /** File path from project root, or absolute for global-scoped command files */
59
+ path: string;
60
+ /** Complete file content (frontmatter + body) */
61
+ fileContent: string;
62
+ }
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Command Generation Types
3
+ *
4
+ * Tool-agnostic interfaces for command generation.
5
+ * These types separate "what to generate" from "how to format it".
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared YAML frontmatter helpers for command adapters.
3
+ *
4
+ * Several tool adapters emit YAML frontmatter and need to escape
5
+ * user-facing strings (name, description, category, tags) so the
6
+ * generated file stays valid YAML. This module centralizes that logic
7
+ * so the behavior is identical across adapters and fixed in one place.
8
+ */
9
+ /**
10
+ * Escapes a string value for safe YAML output.
11
+ *
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
24
+ *
25
+ * @param value - The raw string to embed in YAML frontmatter.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
27
+ */
28
+ export declare function escapeYamlValue(value: string): string;
29
+ /**
30
+ * Formats a tags array as a YAML array with proper escaping.
31
+ *
32
+ * @param tags - Array of tag strings.
33
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
34
+ */
35
+ export declare function formatTagsArray(tags: string[]): string;
36
+ //# sourceMappingURL=yaml.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared YAML frontmatter helpers for command adapters.
3
+ *
4
+ * Several tool adapters emit YAML frontmatter and need to escape
5
+ * user-facing strings (name, description, category, tags) so the
6
+ * generated file stays valid YAML. This module centralizes that logic
7
+ * so the behavior is identical across adapters and fixed in one place.
8
+ */
9
+ /**
10
+ * Escapes a string value for safe YAML output.
11
+ *
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
24
+ *
25
+ * @param value - The raw string to embed in YAML frontmatter.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
27
+ */
28
+ export function escapeYamlValue(value) {
29
+ const escaped = value
30
+ .replace(/\\/g, '\\\\')
31
+ .replace(/"/g, '\\"')
32
+ .replace(/\n/g, '\\n')
33
+ .replace(/\r/g, '\\r')
34
+ // Remaining non-printables have no dedicated escape; emit them as \xHH.
35
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, '0')}`);
36
+ return `"${escaped}"`;
37
+ }
38
+ /**
39
+ * Formats a tags array as a YAML array with proper escaping.
40
+ *
41
+ * @param tags - Array of tag strings.
42
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
43
+ */
44
+ export function formatTagsArray(tags) {
45
+ const escapedTags = tags.map((tag) => escapeYamlValue(tag));
46
+ return `[${escapedTags.join(', ')}]`;
47
+ }
48
+ //# sourceMappingURL=yaml.js.map
@@ -0,0 +1,15 @@
1
+ import { type CommandInvocation } from './command-generation/invocation.js';
2
+ import type { Delivery } from './global-config.js';
3
+ export type CommandSurfaceCapability = 'adapter-backed' | 'skills-invocable' | 'none';
4
+ /**
5
+ * How the tool spells its FreeSpec commands: the name from the command files
6
+ * its adapter writes, the prefix the adapter declares. Returns undefined for
7
+ * tools with no command adapter, which have no command names to spell.
8
+ */
9
+ export declare function resolveCommandInvocation(toolId: string): CommandInvocation | undefined;
10
+ export declare function resolveCommandSurfaceCapability(toolId: string): CommandSurfaceCapability;
11
+ export declare function shouldGenerateSkillsForTool(toolId: string, delivery: Delivery): boolean;
12
+ export declare function shouldRemoveSkillsForTool(toolId: string, delivery: Delivery): boolean;
13
+ export declare function shouldGenerateCommandsForTool(toolId: string, delivery: Delivery): boolean;
14
+ export declare function shouldReconcileCommandFilesForTool(toolId: string, delivery: Delivery): boolean;
15
+ //# sourceMappingURL=command-surface.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { CommandAdapterRegistry } from './command-generation/index.js';
2
+ import { getInvocationForAdapter } from './command-generation/invocation.js';
3
+ /**
4
+ * How the tool spells its FreeSpec commands: the name from the command files
5
+ * its adapter writes, the prefix the adapter declares. Returns undefined for
6
+ * tools with no command adapter, which have no command names to spell.
7
+ */
8
+ export function resolveCommandInvocation(toolId) {
9
+ const adapter = CommandAdapterRegistry.get(toolId);
10
+ return adapter ? getInvocationForAdapter(adapter) : undefined;
11
+ }
12
+ export function resolveCommandSurfaceCapability(toolId) {
13
+ if (CommandAdapterRegistry.has(toolId)) {
14
+ return 'adapter-backed';
15
+ }
16
+ if (toolId === 'codex' || toolId === 'warp') {
17
+ return 'skills-invocable';
18
+ }
19
+ return 'none';
20
+ }
21
+ export function shouldGenerateSkillsForTool(toolId, delivery) {
22
+ return delivery !== 'commands' || resolveCommandSurfaceCapability(toolId) === 'skills-invocable';
23
+ }
24
+ export function shouldRemoveSkillsForTool(toolId, delivery) {
25
+ return delivery === 'commands' && resolveCommandSurfaceCapability(toolId) !== 'skills-invocable';
26
+ }
27
+ export function shouldGenerateCommandsForTool(toolId, delivery) {
28
+ return delivery !== 'skills' && resolveCommandSurfaceCapability(toolId) === 'adapter-backed';
29
+ }
30
+ export function shouldReconcileCommandFilesForTool(toolId, delivery) {
31
+ return delivery === 'skills' && resolveCommandSurfaceCapability(toolId) === 'adapter-backed';
32
+ }
33
+ //# sourceMappingURL=command-surface.js.map
@@ -0,0 +1,9 @@
1
+ import type { ProjectConfig } from './project-config.js';
2
+ /**
3
+ * Serialize config to YAML string with helpful comments.
4
+ *
5
+ * @param config - Partial config object (schema required, other fields optional)
6
+ * @returns YAML string ready to write to file
7
+ */
8
+ export declare function serializeConfig(config: Partial<ProjectConfig>): string;
9
+ //# sourceMappingURL=config-prompts.d.ts.map
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Serialize config to YAML string with helpful comments.
3
+ *
4
+ * @param config - Partial config object (schema required, other fields optional)
5
+ * @returns YAML string ready to write to file
6
+ */
7
+ export function serializeConfig(config) {
8
+ const lines = [];
9
+ // Schema (required)
10
+ lines.push(`schema: ${config.schema}`);
11
+ lines.push('');
12
+ if (config.context !== undefined) {
13
+ lines.push('context: |');
14
+ for (const line of config.context.split('\n')) {
15
+ lines.push(` ${line}`);
16
+ }
17
+ lines.push('');
18
+ }
19
+ else {
20
+ // Context section with comments
21
+ lines.push('# Project context (optional)');
22
+ lines.push('# Add only constraints that should guide FreeSpec artifacts and workflows.');
23
+ lines.push('# Include constraints an agent cannot infer by reading the code.');
24
+ lines.push('# Keep general project documentation and discoverable codebase facts out.');
25
+ lines.push('# Example:');
26
+ lines.push('# context: |');
27
+ lines.push('# Designs and tasks must cover Windows, macOS, and Linux');
28
+ lines.push('# Write all artifacts in Spanish');
29
+ lines.push('');
30
+ }
31
+ // Rules section with comments
32
+ lines.push('# Per-artifact rules (optional)');
33
+ lines.push('# Add custom rules for specific artifacts.');
34
+ lines.push('# Example:');
35
+ lines.push('# rules:');
36
+ lines.push('# proposal:');
37
+ lines.push('# - Keep proposals under 500 words');
38
+ lines.push('# - Always state what is out of scope');
39
+ lines.push('# tasks:');
40
+ lines.push('# - Break tasks into chunks of max 2 hours');
41
+ lines.push('');
42
+ // Operation guidance section with comments
43
+ lines.push('# Per-operation guidance (optional)');
44
+ lines.push('# Add advisory guidance for how apply and archive work should be conducted.');
45
+ lines.push('# This is separate from artifact rules above.');
46
+ lines.push('# Example:');
47
+ lines.push('# operations:');
48
+ lines.push('# apply:');
49
+ lines.push('# guidance:');
50
+ lines.push('# - Keep test summaries concise');
51
+ lines.push('# archive:');
52
+ lines.push('# guidance:');
53
+ lines.push('# - Summarize the archive outcome before finishing');
54
+ return lines.join('\n') + '\n';
55
+ }
56
+ //# sourceMappingURL=config-prompts.js.map
@@ -0,0 +1,98 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for global FreeSpec configuration.
4
+ * Uses passthrough() to preserve unknown fields for forward compatibility.
5
+ */
6
+ export declare const GlobalConfigSchema: z.ZodObject<{
7
+ featureFlags: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>>;
8
+ profile: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
9
+ custom: "custom";
10
+ core: "core";
11
+ }>>>;
12
+ delivery: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
13
+ both: "both";
14
+ skills: "skills";
15
+ commands: "commands";
16
+ }>>>;
17
+ workflows: z.ZodOptional<z.ZodArray<z.ZodString>>;
18
+ defaultStore: z.ZodOptional<z.ZodString>;
19
+ telemetry: z.ZodOptional<z.ZodObject<{
20
+ enabled: z.ZodOptional<z.ZodBoolean>;
21
+ }, z.core.$loose>>;
22
+ completionTipSeen: z.ZodOptional<z.ZodBoolean>;
23
+ standaloneTipSeen: z.ZodOptional<z.ZodBoolean>;
24
+ }, z.core.$loose>;
25
+ export type GlobalConfigType = z.infer<typeof GlobalConfigSchema>;
26
+ /**
27
+ * Default configuration values.
28
+ */
29
+ export declare const DEFAULT_CONFIG: GlobalConfigType;
30
+ /**
31
+ * True when a dot-notation key path contains a prototype-reaching segment.
32
+ * Callers that bypass key validation (e.g. --allow-unknown) still must not bypass this.
33
+ */
34
+ export declare function hasUnsafeKeySegment(path: string): boolean;
35
+ /**
36
+ * Validate a config key path for CLI set operations.
37
+ * Unknown top-level keys are rejected unless explicitly allowed by the caller.
38
+ */
39
+ export declare function validateConfigKeyPath(path: string): {
40
+ valid: boolean;
41
+ reason?: string;
42
+ };
43
+ /**
44
+ * Get a nested value from an object using dot notation.
45
+ *
46
+ * @param obj - The object to access
47
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
48
+ * @returns The value at the path, or undefined if not found
49
+ */
50
+ export declare function getNestedValue(obj: Record<string, unknown>, path: string): unknown;
51
+ /**
52
+ * Set a nested value in an object using dot notation.
53
+ * Creates intermediate objects as needed.
54
+ *
55
+ * @param obj - The object to modify (mutated in place)
56
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
57
+ * @param value - The value to set
58
+ */
59
+ export declare function setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void;
60
+ /**
61
+ * Delete a nested value from an object using dot notation.
62
+ *
63
+ * @param obj - The object to modify (mutated in place)
64
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
65
+ * @returns true if the key existed and was deleted, false otherwise
66
+ */
67
+ export declare function deleteNestedValue(obj: Record<string, unknown>, path: string): boolean;
68
+ /**
69
+ * Coerce a string value to its appropriate type.
70
+ * - "true" / "false" -> boolean
71
+ * - Numeric strings -> number
72
+ * - JSON arrays/objects -> parsed containers
73
+ * - Everything else -> string
74
+ *
75
+ * @param value - The string value to coerce
76
+ * @param forceString - If true, always return the value as a string
77
+ * @returns The coerced value
78
+ */
79
+ export declare function coerceValue(value: string, forceString?: boolean): string | number | boolean | unknown[] | Record<string, unknown>;
80
+ /**
81
+ * Format a value for YAML-like display.
82
+ *
83
+ * @param value - The value to format
84
+ * @param indent - Current indentation level
85
+ * @returns Formatted string
86
+ */
87
+ export declare function formatValueYaml(value: unknown, indent?: number): string;
88
+ /**
89
+ * Validate a configuration object against the schema.
90
+ *
91
+ * @param config - The configuration to validate
92
+ * @returns Validation result with success status and optional error message
93
+ */
94
+ export declare function validateConfig(config: unknown): {
95
+ success: boolean;
96
+ error?: string;
97
+ };
98
+ //# sourceMappingURL=config-schema.d.ts.map
@@ -0,0 +1,308 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for global FreeSpec configuration.
4
+ * Uses passthrough() to preserve unknown fields for forward compatibility.
5
+ */
6
+ export const GlobalConfigSchema = z
7
+ .object({
8
+ featureFlags: z
9
+ .record(z.string(), z.boolean())
10
+ .optional()
11
+ .default({}),
12
+ profile: z
13
+ .enum(['core', 'custom'])
14
+ .optional()
15
+ .default('core'),
16
+ delivery: z
17
+ .enum(['both', 'skills', 'commands'])
18
+ .optional()
19
+ .default('both'),
20
+ workflows: z
21
+ .array(z.string())
22
+ .optional(),
23
+ defaultStore: z
24
+ .string()
25
+ .optional()
26
+ .describe('Store id used as fallback root when no explicit --store, local root, or project-level store: pointer resolves'),
27
+ // passthrough keeps runtime-managed fields (anonymousId, noticeSeen) valid
28
+ // under CLI validate when users only set telemetry.enabled.
29
+ telemetry: z
30
+ .object({
31
+ enabled: z.boolean().optional(),
32
+ })
33
+ .passthrough()
34
+ .optional(),
35
+ // Runtime-managed (like telemetry.noticeSeen); not user-settable via CLI set.
36
+ completionTipSeen: z.boolean().optional(),
37
+ standaloneTipSeen: z.boolean().optional(),
38
+ })
39
+ .passthrough();
40
+ /**
41
+ * Default configuration values.
42
+ */
43
+ export const DEFAULT_CONFIG = {
44
+ featureFlags: {},
45
+ profile: 'core',
46
+ delivery: 'both',
47
+ };
48
+ const KNOWN_TOP_LEVEL_KEYS = new Set([
49
+ ...Object.keys(DEFAULT_CONFIG),
50
+ 'workflows',
51
+ 'defaultStore',
52
+ 'telemetry',
53
+ ]);
54
+ /** Nested keys users may set under `telemetry` via the CLI. */
55
+ const TELEMETRY_SETTABLE_KEYS = new Set(['enabled']);
56
+ /**
57
+ * Key segments that would reach the prototype chain instead of the config object.
58
+ * Never valid as configuration keys, so rejecting them costs nothing.
59
+ */
60
+ const UNSAFE_KEY_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);
61
+ function hasUnsafeSegment(keys) {
62
+ return keys.some((key) => UNSAFE_KEY_SEGMENTS.has(key));
63
+ }
64
+ /**
65
+ * True when a dot-notation key path contains a prototype-reaching segment.
66
+ * Callers that bypass key validation (e.g. --allow-unknown) still must not bypass this.
67
+ */
68
+ export function hasUnsafeKeySegment(path) {
69
+ return hasUnsafeSegment(path.split('.'));
70
+ }
71
+ /**
72
+ * Validate a config key path for CLI set operations.
73
+ * Unknown top-level keys are rejected unless explicitly allowed by the caller.
74
+ */
75
+ export function validateConfigKeyPath(path) {
76
+ const rawKeys = path.split('.');
77
+ if (rawKeys.length === 0 || rawKeys.some((key) => key.trim() === '')) {
78
+ return { valid: false, reason: 'Key path must not be empty' };
79
+ }
80
+ const unsafeKey = rawKeys.find((key) => UNSAFE_KEY_SEGMENTS.has(key));
81
+ if (unsafeKey) {
82
+ return { valid: false, reason: `Key segment "${unsafeKey}" is not allowed` };
83
+ }
84
+ const rootKey = rawKeys[0];
85
+ if (!KNOWN_TOP_LEVEL_KEYS.has(rootKey)) {
86
+ return { valid: false, reason: `Unknown top-level key "${rootKey}"` };
87
+ }
88
+ if (rootKey === 'featureFlags') {
89
+ if (rawKeys.length > 2) {
90
+ return { valid: false, reason: 'featureFlags values are booleans and do not support nested keys' };
91
+ }
92
+ return { valid: true };
93
+ }
94
+ if (rootKey === 'telemetry') {
95
+ if (rawKeys.length === 1) {
96
+ return { valid: false, reason: 'Set nested keys under telemetry (e.g. telemetry.enabled)' };
97
+ }
98
+ if (rawKeys.length !== 2 || !TELEMETRY_SETTABLE_KEYS.has(rawKeys[1])) {
99
+ return {
100
+ valid: false,
101
+ reason: `Unknown telemetry key "${rawKeys.slice(1).join('.')}" (allowed: enabled)`,
102
+ };
103
+ }
104
+ return { valid: true };
105
+ }
106
+ if (rawKeys.length > 1) {
107
+ return { valid: false, reason: `"${rootKey}" does not support nested keys` };
108
+ }
109
+ return { valid: true };
110
+ }
111
+ /**
112
+ * Get a nested value from an object using dot notation.
113
+ *
114
+ * @param obj - The object to access
115
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
116
+ * @returns The value at the path, or undefined if not found
117
+ */
118
+ export function getNestedValue(obj, path) {
119
+ const keys = path.split('.');
120
+ if (hasUnsafeSegment(keys)) {
121
+ return undefined;
122
+ }
123
+ let current = obj;
124
+ for (const key of keys) {
125
+ if (current === null || current === undefined) {
126
+ return undefined;
127
+ }
128
+ if (typeof current !== 'object') {
129
+ return undefined;
130
+ }
131
+ current = current[key];
132
+ }
133
+ return current;
134
+ }
135
+ /**
136
+ * Set a nested value in an object using dot notation.
137
+ * Creates intermediate objects as needed.
138
+ *
139
+ * @param obj - The object to modify (mutated in place)
140
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
141
+ * @param value - The value to set
142
+ */
143
+ export function setNestedValue(obj, path, value) {
144
+ const keys = path.split('.');
145
+ // Compared literally rather than through a helper, so the guard is plain to a
146
+ // reader and to static analysis. Checked for the whole path before anything is
147
+ // written, so a rejected key never leaves half-created objects behind.
148
+ for (const key of keys) {
149
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
150
+ return;
151
+ }
152
+ }
153
+ let current = obj;
154
+ for (let i = 0; i < keys.length - 1; i++) {
155
+ const key = keys[i];
156
+ if (current[key] === undefined || current[key] === null || typeof current[key] !== 'object') {
157
+ current[key] = {};
158
+ }
159
+ current = current[key];
160
+ }
161
+ const lastKey = keys[keys.length - 1];
162
+ current[lastKey] = value;
163
+ }
164
+ /**
165
+ * Delete a nested value from an object using dot notation.
166
+ *
167
+ * @param obj - The object to modify (mutated in place)
168
+ * @param path - Dot-separated path (e.g., "featureFlags.someFlag")
169
+ * @returns true if the key existed and was deleted, false otherwise
170
+ */
171
+ export function deleteNestedValue(obj, path) {
172
+ const keys = path.split('.');
173
+ for (const key of keys) {
174
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
175
+ return false;
176
+ }
177
+ }
178
+ let current = obj;
179
+ for (let i = 0; i < keys.length - 1; i++) {
180
+ const key = keys[i];
181
+ if (current[key] === undefined || current[key] === null || typeof current[key] !== 'object') {
182
+ return false;
183
+ }
184
+ current = current[key];
185
+ }
186
+ const lastKey = keys[keys.length - 1];
187
+ if (lastKey in current) {
188
+ delete current[lastKey];
189
+ return true;
190
+ }
191
+ return false;
192
+ }
193
+ /**
194
+ * Coerce a string value to its appropriate type.
195
+ * - "true" / "false" -> boolean
196
+ * - Numeric strings -> number
197
+ * - JSON arrays/objects -> parsed containers
198
+ * - Everything else -> string
199
+ *
200
+ * @param value - The string value to coerce
201
+ * @param forceString - If true, always return the value as a string
202
+ * @returns The coerced value
203
+ */
204
+ export function coerceValue(value, forceString = false) {
205
+ if (forceString) {
206
+ return value;
207
+ }
208
+ // Boolean coercion
209
+ if (value === 'true') {
210
+ return true;
211
+ }
212
+ if (value === 'false') {
213
+ return false;
214
+ }
215
+ // Number coercion - must be a valid finite number
216
+ const num = Number(value);
217
+ if (!isNaN(num) && isFinite(num) && value.trim() !== '') {
218
+ return num;
219
+ }
220
+ const jsonContainer = parseJsonContainer(value);
221
+ if (jsonContainer !== undefined) {
222
+ return jsonContainer;
223
+ }
224
+ return value;
225
+ }
226
+ function parseJsonContainer(value) {
227
+ const trimmed = value.trim();
228
+ const looksLikeContainer = (trimmed.startsWith('[') && trimmed.endsWith(']')) ||
229
+ (trimmed.startsWith('{') && trimmed.endsWith('}'));
230
+ if (!looksLikeContainer) {
231
+ return undefined;
232
+ }
233
+ try {
234
+ const parsed = JSON.parse(trimmed);
235
+ if (Array.isArray(parsed)) {
236
+ return parsed;
237
+ }
238
+ if (parsed !== null && typeof parsed === 'object') {
239
+ return parsed;
240
+ }
241
+ }
242
+ catch {
243
+ return undefined;
244
+ }
245
+ return undefined;
246
+ }
247
+ /**
248
+ * Format a value for YAML-like display.
249
+ *
250
+ * @param value - The value to format
251
+ * @param indent - Current indentation level
252
+ * @returns Formatted string
253
+ */
254
+ export function formatValueYaml(value, indent = 0) {
255
+ const indentStr = ' '.repeat(indent);
256
+ if (value === null || value === undefined) {
257
+ return 'null';
258
+ }
259
+ if (typeof value === 'boolean' || typeof value === 'number') {
260
+ return String(value);
261
+ }
262
+ if (typeof value === 'string') {
263
+ return value;
264
+ }
265
+ if (Array.isArray(value)) {
266
+ if (value.length === 0) {
267
+ return '[]';
268
+ }
269
+ return value.map((item) => `${indentStr}- ${formatValueYaml(item, indent + 1)}`).join('\n');
270
+ }
271
+ if (typeof value === 'object') {
272
+ const entries = Object.entries(value);
273
+ if (entries.length === 0) {
274
+ return '{}';
275
+ }
276
+ return entries
277
+ .map(([key, val]) => {
278
+ const formattedVal = formatValueYaml(val, indent + 1);
279
+ if (typeof val === 'object' && val !== null && Object.keys(val).length > 0) {
280
+ return `${indentStr}${key}:\n${formattedVal}`;
281
+ }
282
+ return `${indentStr}${key}: ${formattedVal}`;
283
+ })
284
+ .join('\n');
285
+ }
286
+ return String(value);
287
+ }
288
+ /**
289
+ * Validate a configuration object against the schema.
290
+ *
291
+ * @param config - The configuration to validate
292
+ * @returns Validation result with success status and optional error message
293
+ */
294
+ export function validateConfig(config) {
295
+ try {
296
+ GlobalConfigSchema.parse(config);
297
+ return { success: true };
298
+ }
299
+ catch (error) {
300
+ if (error instanceof z.ZodError) {
301
+ const zodError = error;
302
+ const messages = zodError.issues.map((e) => `${e.path.join('.')}: ${e.message}`);
303
+ return { success: false, error: messages.join('; ') };
304
+ }
305
+ return { success: false, error: 'Unknown validation error' };
306
+ }
307
+ }
308
+ //# sourceMappingURL=config-schema.js.map