@thiagodiogo/pastelsdd 1.0.0-beta.1

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 (369) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +3 -0
  3. package/bin/pastelsdd.js +5 -0
  4. package/dist/cli/index.d.ts +5 -0
  5. package/dist/cli/index.js +526 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +277 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +264 -0
  10. package/dist/commands/config.d.ts +36 -0
  11. package/dist/commands/config.js +611 -0
  12. package/dist/commands/context-store.d.ts +3 -0
  13. package/dist/commands/context-store.js +282 -0
  14. package/dist/commands/feedback.d.ts +9 -0
  15. package/dist/commands/feedback.js +183 -0
  16. package/dist/commands/initiative.d.ts +13 -0
  17. package/dist/commands/initiative.js +318 -0
  18. package/dist/commands/schema.d.ts +6 -0
  19. package/dist/commands/schema.js +869 -0
  20. package/dist/commands/show.d.ts +14 -0
  21. package/dist/commands/show.js +132 -0
  22. package/dist/commands/spec.d.ts +15 -0
  23. package/dist/commands/spec.js +225 -0
  24. package/dist/commands/validate.d.ts +24 -0
  25. package/dist/commands/validate.js +294 -0
  26. package/dist/commands/workflow/index.d.ts +19 -0
  27. package/dist/commands/workflow/index.js +13 -0
  28. package/dist/commands/workflow/initiative-link.d.ts +24 -0
  29. package/dist/commands/workflow/initiative-link.js +47 -0
  30. package/dist/commands/workflow/instructions.d.ts +29 -0
  31. package/dist/commands/workflow/instructions.js +344 -0
  32. package/dist/commands/workflow/new-change.d.ts +17 -0
  33. package/dist/commands/workflow/new-change.js +141 -0
  34. package/dist/commands/workflow/schemas.d.ts +10 -0
  35. package/dist/commands/workflow/schemas.js +34 -0
  36. package/dist/commands/workflow/set-change.d.ts +13 -0
  37. package/dist/commands/workflow/set-change.js +87 -0
  38. package/dist/commands/workflow/shared.d.ts +59 -0
  39. package/dist/commands/workflow/shared.js +116 -0
  40. package/dist/commands/workflow/status.d.ts +14 -0
  41. package/dist/commands/workflow/status.js +90 -0
  42. package/dist/commands/workflow/templates.d.ts +16 -0
  43. package/dist/commands/workflow/templates.js +69 -0
  44. package/dist/commands/workspace/context-status.d.ts +4 -0
  45. package/dist/commands/workspace/context-status.js +59 -0
  46. package/dist/commands/workspace/open-view.d.ts +62 -0
  47. package/dist/commands/workspace/open-view.js +228 -0
  48. package/dist/commands/workspace/open.d.ts +37 -0
  49. package/dist/commands/workspace/open.js +102 -0
  50. package/dist/commands/workspace/opener-selection.d.ts +11 -0
  51. package/dist/commands/workspace/opener-selection.js +93 -0
  52. package/dist/commands/workspace/operations.d.ts +28 -0
  53. package/dist/commands/workspace/operations.js +543 -0
  54. package/dist/commands/workspace/prompt-theme.d.ts +29 -0
  55. package/dist/commands/workspace/prompt-theme.js +24 -0
  56. package/dist/commands/workspace/registration.d.ts +13 -0
  57. package/dist/commands/workspace/registration.js +84 -0
  58. package/dist/commands/workspace/selection.d.ts +6 -0
  59. package/dist/commands/workspace/selection.js +122 -0
  60. package/dist/commands/workspace/types.d.ts +103 -0
  61. package/dist/commands/workspace/types.js +36 -0
  62. package/dist/commands/workspace.d.ts +6 -0
  63. package/dist/commands/workspace.js +678 -0
  64. package/dist/core/archive.d.ts +11 -0
  65. package/dist/core/archive.js +318 -0
  66. package/dist/core/artifact-graph/graph.d.ts +56 -0
  67. package/dist/core/artifact-graph/graph.js +141 -0
  68. package/dist/core/artifact-graph/index.d.ts +9 -0
  69. package/dist/core/artifact-graph/index.js +14 -0
  70. package/dist/core/artifact-graph/instruction-loader.d.ts +183 -0
  71. package/dist/core/artifact-graph/instruction-loader.js +256 -0
  72. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  73. package/dist/core/artifact-graph/outputs.js +39 -0
  74. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  75. package/dist/core/artifact-graph/resolver.js +257 -0
  76. package/dist/core/artifact-graph/schema.d.ts +13 -0
  77. package/dist/core/artifact-graph/schema.js +108 -0
  78. package/dist/core/artifact-graph/state.d.ts +12 -0
  79. package/dist/core/artifact-graph/state.js +31 -0
  80. package/dist/core/artifact-graph/types.d.ts +40 -0
  81. package/dist/core/artifact-graph/types.js +29 -0
  82. package/dist/core/available-tools.d.ts +17 -0
  83. package/dist/core/available-tools.js +43 -0
  84. package/dist/core/change-metadata/index.d.ts +2 -0
  85. package/dist/core/change-metadata/index.js +2 -0
  86. package/dist/core/change-metadata/schema.d.ts +18 -0
  87. package/dist/core/change-metadata/schema.js +28 -0
  88. package/dist/core/change-status-policy.d.ts +50 -0
  89. package/dist/core/change-status-policy.js +70 -0
  90. package/dist/core/collections/index.d.ts +3 -0
  91. package/dist/core/collections/index.js +3 -0
  92. package/dist/core/collections/initiatives/collection.d.ts +4 -0
  93. package/dist/core/collections/initiatives/collection.js +17 -0
  94. package/dist/core/collections/initiatives/index.d.ts +6 -0
  95. package/dist/core/collections/initiatives/index.js +6 -0
  96. package/dist/core/collections/initiatives/operations.d.ts +49 -0
  97. package/dist/core/collections/initiatives/operations.js +175 -0
  98. package/dist/core/collections/initiatives/resolution.d.ts +87 -0
  99. package/dist/core/collections/initiatives/resolution.js +374 -0
  100. package/dist/core/collections/initiatives/schema.d.ts +41 -0
  101. package/dist/core/collections/initiatives/schema.js +134 -0
  102. package/dist/core/collections/initiatives/templates.d.ts +12 -0
  103. package/dist/core/collections/initiatives/templates.js +90 -0
  104. package/dist/core/collections/runtime.d.ts +46 -0
  105. package/dist/core/collections/runtime.js +194 -0
  106. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  108. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  109. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  110. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  111. package/dist/core/command-generation/adapters/auggie.js +27 -0
  112. package/dist/core/command-generation/adapters/bob.d.ts +14 -0
  113. package/dist/core/command-generation/adapters/bob.js +45 -0
  114. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  115. package/dist/core/command-generation/adapters/claude.js +50 -0
  116. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  117. package/dist/core/command-generation/adapters/cline.js +27 -0
  118. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  119. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  120. package/dist/core/command-generation/adapters/codex.d.ts +16 -0
  121. package/dist/core/command-generation/adapters/codex.js +39 -0
  122. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  123. package/dist/core/command-generation/adapters/continue.js +28 -0
  124. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  125. package/dist/core/command-generation/adapters/costrict.js +27 -0
  126. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  127. package/dist/core/command-generation/adapters/crush.js +30 -0
  128. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  129. package/dist/core/command-generation/adapters/cursor.js +44 -0
  130. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  131. package/dist/core/command-generation/adapters/factory.js +27 -0
  132. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  133. package/dist/core/command-generation/adapters/gemini.js +26 -0
  134. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  135. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  136. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  137. package/dist/core/command-generation/adapters/iflow.js +29 -0
  138. package/dist/core/command-generation/adapters/index.d.ts +32 -0
  139. package/dist/core/command-generation/adapters/index.js +32 -0
  140. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  141. package/dist/core/command-generation/adapters/junie.js +26 -0
  142. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  143. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  144. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  145. package/dist/core/command-generation/adapters/kiro.js +26 -0
  146. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  147. package/dist/core/command-generation/adapters/lingma.js +30 -0
  148. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  149. package/dist/core/command-generation/adapters/opencode.js +29 -0
  150. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  151. package/dist/core/command-generation/adapters/pi.js +55 -0
  152. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  153. package/dist/core/command-generation/adapters/qoder.js +30 -0
  154. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  155. package/dist/core/command-generation/adapters/qwen.js +26 -0
  156. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  157. package/dist/core/command-generation/adapters/roocode.js +27 -0
  158. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  159. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  160. package/dist/core/command-generation/generator.d.ts +21 -0
  161. package/dist/core/command-generation/generator.js +27 -0
  162. package/dist/core/command-generation/index.d.ts +22 -0
  163. package/dist/core/command-generation/index.js +24 -0
  164. package/dist/core/command-generation/registry.d.ts +36 -0
  165. package/dist/core/command-generation/registry.js +98 -0
  166. package/dist/core/command-generation/types.d.ts +56 -0
  167. package/dist/core/command-generation/types.js +8 -0
  168. package/dist/core/completions/command-registry.d.ts +3 -0
  169. package/dist/core/completions/command-registry.js +939 -0
  170. package/dist/core/completions/completion-provider.d.ts +71 -0
  171. package/dist/core/completions/completion-provider.js +129 -0
  172. package/dist/core/completions/factory.d.ts +64 -0
  173. package/dist/core/completions/factory.js +75 -0
  174. package/dist/core/completions/generators/bash-generator.d.ts +35 -0
  175. package/dist/core/completions/generators/bash-generator.js +230 -0
  176. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  177. package/dist/core/completions/generators/fish-generator.js +160 -0
  178. package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
  179. package/dist/core/completions/generators/powershell-generator.js +266 -0
  180. package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
  181. package/dist/core/completions/generators/zsh-generator.js +274 -0
  182. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  183. package/dist/core/completions/installers/bash-installer.js +318 -0
  184. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  185. package/dist/core/completions/installers/fish-installer.js +143 -0
  186. package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
  187. package/dist/core/completions/installers/powershell-installer.js +387 -0
  188. package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
  189. package/dist/core/completions/installers/zsh-installer.js +421 -0
  190. package/dist/core/completions/shared-flags.d.ts +12 -0
  191. package/dist/core/completions/shared-flags.js +28 -0
  192. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  193. package/dist/core/completions/templates/bash-templates.js +30 -0
  194. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  195. package/dist/core/completions/templates/fish-templates.js +45 -0
  196. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  197. package/dist/core/completions/templates/powershell-templates.js +34 -0
  198. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  199. package/dist/core/completions/templates/zsh-templates.js +45 -0
  200. package/dist/core/completions/types.d.ts +101 -0
  201. package/dist/core/completions/types.js +2 -0
  202. package/dist/core/config-prompts.d.ts +9 -0
  203. package/dist/core/config-prompts.js +34 -0
  204. package/dist/core/config-schema.d.ts +86 -0
  205. package/dist/core/config-schema.js +213 -0
  206. package/dist/core/config.d.ts +18 -0
  207. package/dist/core/config.js +38 -0
  208. package/dist/core/context-store/binding.d.ts +53 -0
  209. package/dist/core/context-store/binding.js +197 -0
  210. package/dist/core/context-store/errors.d.ts +20 -0
  211. package/dist/core/context-store/errors.js +22 -0
  212. package/dist/core/context-store/foundation.d.ts +54 -0
  213. package/dist/core/context-store/foundation.js +318 -0
  214. package/dist/core/context-store/index.d.ts +6 -0
  215. package/dist/core/context-store/index.js +6 -0
  216. package/dist/core/context-store/operations.d.ts +62 -0
  217. package/dist/core/context-store/operations.js +352 -0
  218. package/dist/core/context-store/registry.d.ts +35 -0
  219. package/dist/core/context-store/registry.js +158 -0
  220. package/dist/core/converters/json-converter.d.ts +6 -0
  221. package/dist/core/converters/json-converter.js +51 -0
  222. package/dist/core/global-config.d.ts +49 -0
  223. package/dist/core/global-config.js +124 -0
  224. package/dist/core/index.d.ts +6 -0
  225. package/dist/core/index.js +7 -0
  226. package/dist/core/init.d.ts +37 -0
  227. package/dist/core/init.js +593 -0
  228. package/dist/core/legacy-cleanup.d.ts +162 -0
  229. package/dist/core/legacy-cleanup.js +514 -0
  230. package/dist/core/list.d.ts +9 -0
  231. package/dist/core/list.js +171 -0
  232. package/dist/core/migration.d.ts +23 -0
  233. package/dist/core/migration.js +108 -0
  234. package/dist/core/parsers/change-parser.d.ts +13 -0
  235. package/dist/core/parsers/change-parser.js +197 -0
  236. package/dist/core/parsers/markdown-parser.d.ts +26 -0
  237. package/dist/core/parsers/markdown-parser.js +227 -0
  238. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  239. package/dist/core/parsers/requirement-blocks.js +201 -0
  240. package/dist/core/parsers/spec-structure.d.ts +9 -0
  241. package/dist/core/parsers/spec-structure.js +88 -0
  242. package/dist/core/planning-home.d.ts +21 -0
  243. package/dist/core/planning-home.js +108 -0
  244. package/dist/core/profile-sync-drift.d.ts +38 -0
  245. package/dist/core/profile-sync-drift.js +200 -0
  246. package/dist/core/profiles.d.ts +26 -0
  247. package/dist/core/profiles.js +40 -0
  248. package/dist/core/project-config.d.ts +64 -0
  249. package/dist/core/project-config.js +223 -0
  250. package/dist/core/schemas/base.schema.d.ts +13 -0
  251. package/dist/core/schemas/base.schema.js +13 -0
  252. package/dist/core/schemas/change.schema.d.ts +73 -0
  253. package/dist/core/schemas/change.schema.js +31 -0
  254. package/dist/core/schemas/index.d.ts +4 -0
  255. package/dist/core/schemas/index.js +4 -0
  256. package/dist/core/schemas/spec.schema.d.ts +18 -0
  257. package/dist/core/schemas/spec.schema.js +15 -0
  258. package/dist/core/shared/index.d.ts +8 -0
  259. package/dist/core/shared/index.js +8 -0
  260. package/dist/core/shared/skill-generation.d.ts +49 -0
  261. package/dist/core/shared/skill-generation.js +96 -0
  262. package/dist/core/shared/tool-detection.d.ts +71 -0
  263. package/dist/core/shared/tool-detection.js +158 -0
  264. package/dist/core/specs-apply.d.ts +73 -0
  265. package/dist/core/specs-apply.js +392 -0
  266. package/dist/core/styles/palette.d.ts +7 -0
  267. package/dist/core/styles/palette.js +8 -0
  268. package/dist/core/templates/index.d.ts +8 -0
  269. package/dist/core/templates/index.js +9 -0
  270. package/dist/core/templates/skill-templates.d.ts +19 -0
  271. package/dist/core/templates/skill-templates.js +18 -0
  272. package/dist/core/templates/types.d.ts +19 -0
  273. package/dist/core/templates/types.js +5 -0
  274. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  275. package/dist/core/templates/workflows/apply-change.js +314 -0
  276. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  277. package/dist/core/templates/workflows/archive-change.js +277 -0
  278. package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
  279. package/dist/core/templates/workflows/bulk-archive-change.js +492 -0
  280. package/dist/core/templates/workflows/continue-change.d.ts +10 -0
  281. package/dist/core/templates/workflows/continue-change.js +234 -0
  282. package/dist/core/templates/workflows/explore.d.ts +10 -0
  283. package/dist/core/templates/workflows/explore.js +459 -0
  284. package/dist/core/templates/workflows/feedback.d.ts +9 -0
  285. package/dist/core/templates/workflows/feedback.js +108 -0
  286. package/dist/core/templates/workflows/ff-change.d.ts +10 -0
  287. package/dist/core/templates/workflows/ff-change.js +200 -0
  288. package/dist/core/templates/workflows/new-change.d.ts +10 -0
  289. package/dist/core/templates/workflows/new-change.js +143 -0
  290. package/dist/core/templates/workflows/onboard.d.ts +10 -0
  291. package/dist/core/templates/workflows/onboard.js +563 -0
  292. package/dist/core/templates/workflows/propose.d.ts +10 -0
  293. package/dist/core/templates/workflows/propose.js +218 -0
  294. package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
  295. package/dist/core/templates/workflows/sync-specs.js +290 -0
  296. package/dist/core/templates/workflows/verify-change.d.ts +10 -0
  297. package/dist/core/templates/workflows/verify-change.js +338 -0
  298. package/dist/core/update.d.ts +82 -0
  299. package/dist/core/update.js +557 -0
  300. package/dist/core/validation/constants.d.ts +34 -0
  301. package/dist/core/validation/constants.js +40 -0
  302. package/dist/core/validation/types.d.ts +18 -0
  303. package/dist/core/validation/types.js +2 -0
  304. package/dist/core/validation/validator.d.ts +33 -0
  305. package/dist/core/validation/validator.js +418 -0
  306. package/dist/core/view.d.ts +8 -0
  307. package/dist/core/view.js +168 -0
  308. package/dist/core/workspace/foundation.d.ts +62 -0
  309. package/dist/core/workspace/foundation.js +274 -0
  310. package/dist/core/workspace/index.d.ts +8 -0
  311. package/dist/core/workspace/index.js +8 -0
  312. package/dist/core/workspace/legacy-state.d.ts +28 -0
  313. package/dist/core/workspace/legacy-state.js +200 -0
  314. package/dist/core/workspace/link-input.d.ts +9 -0
  315. package/dist/core/workspace/link-input.js +32 -0
  316. package/dist/core/workspace/open-surface.d.ts +43 -0
  317. package/dist/core/workspace/open-surface.js +214 -0
  318. package/dist/core/workspace/openers.d.ts +21 -0
  319. package/dist/core/workspace/openers.js +119 -0
  320. package/dist/core/workspace/registry.d.ts +24 -0
  321. package/dist/core/workspace/registry.js +146 -0
  322. package/dist/core/workspace/skills.d.ts +57 -0
  323. package/dist/core/workspace/skills.js +334 -0
  324. package/dist/core/workspace/state-io.d.ts +10 -0
  325. package/dist/core/workspace/state-io.js +119 -0
  326. package/dist/index.d.ts +3 -0
  327. package/dist/index.js +3 -0
  328. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  329. package/dist/prompts/searchable-multi-select.js +159 -0
  330. package/dist/telemetry/config.d.ts +38 -0
  331. package/dist/telemetry/config.js +136 -0
  332. package/dist/telemetry/index.d.ts +31 -0
  333. package/dist/telemetry/index.js +164 -0
  334. package/dist/ui/ascii-patterns.d.ts +16 -0
  335. package/dist/ui/ascii-patterns.js +133 -0
  336. package/dist/ui/welcome-screen.d.ts +10 -0
  337. package/dist/ui/welcome-screen.js +146 -0
  338. package/dist/utils/change-metadata.d.ts +54 -0
  339. package/dist/utils/change-metadata.js +141 -0
  340. package/dist/utils/change-utils.d.ts +71 -0
  341. package/dist/utils/change-utils.js +123 -0
  342. package/dist/utils/command-references.d.ts +18 -0
  343. package/dist/utils/command-references.js +20 -0
  344. package/dist/utils/file-system.d.ts +41 -0
  345. package/dist/utils/file-system.js +301 -0
  346. package/dist/utils/index.d.ts +6 -0
  347. package/dist/utils/index.js +9 -0
  348. package/dist/utils/interactive.d.ts +18 -0
  349. package/dist/utils/interactive.js +21 -0
  350. package/dist/utils/item-discovery.d.ts +4 -0
  351. package/dist/utils/item-discovery.js +72 -0
  352. package/dist/utils/match.d.ts +3 -0
  353. package/dist/utils/match.js +22 -0
  354. package/dist/utils/shell-detection.d.ts +20 -0
  355. package/dist/utils/shell-detection.js +41 -0
  356. package/dist/utils/task-progress.d.ts +8 -0
  357. package/dist/utils/task-progress.js +36 -0
  358. package/package.json +84 -0
  359. package/schemas/spec-driven/schema.yaml +153 -0
  360. package/schemas/spec-driven/templates/design.md +19 -0
  361. package/schemas/spec-driven/templates/proposal.md +23 -0
  362. package/schemas/spec-driven/templates/spec.md +8 -0
  363. package/schemas/spec-driven/templates/tasks.md +9 -0
  364. package/schemas/workspace-planning/schema.yaml +72 -0
  365. package/schemas/workspace-planning/templates/design.md +33 -0
  366. package/schemas/workspace-planning/templates/proposal.md +28 -0
  367. package/schemas/workspace-planning/templates/spec.md +9 -0
  368. package/schemas/workspace-planning/templates/tasks.md +15 -0
  369. package/scripts/postinstall.js +83 -0
@@ -0,0 +1,334 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { FileSystemUtils } from '../../utils/file-system.js';
4
+ import { transformToHyphenCommands } from '../../utils/command-references.js';
5
+ import { AI_TOOLS } from '../config.js';
6
+ import { getGlobalConfig } from '../global-config.js';
7
+ import { getProfileWorkflows } from '../profiles.js';
8
+ import { generateSkillContent, getSkillTemplates, getToolSkillStatus, getToolsWithSkillsDir, extractGeneratedByVersion, } from '../shared/index.js';
9
+ const require = createRequire(import.meta.url);
10
+ const { version: PASTELSDD_VERSION } = require('../../../package.json');
11
+ const fs = nodeFs.promises;
12
+ function resolveWorkspaceSkillProfileContext() {
13
+ const globalConfig = getGlobalConfig();
14
+ const profile = globalConfig.profile ?? 'core';
15
+ const delivery = globalConfig.delivery ?? 'both';
16
+ const workflowIds = [...getProfileWorkflows(profile, globalConfig.workflows)];
17
+ const deliveryNotice = delivery === 'skills'
18
+ ? null
19
+ : 'Workspace setup installs skills only; workspace command generation is not part of this slice.';
20
+ return {
21
+ profile,
22
+ delivery,
23
+ workflowIds,
24
+ deliveryNotice,
25
+ };
26
+ }
27
+ export function getCurrentWorkspaceSkillProfileSelection() {
28
+ const profileContext = resolveWorkspaceSkillProfileContext();
29
+ return {
30
+ profile: profileContext.profile,
31
+ delivery: profileContext.delivery,
32
+ workflow_ids: profileContext.workflowIds,
33
+ };
34
+ }
35
+ function arraysEqual(left, right) {
36
+ const leftValues = left ?? [];
37
+ if (leftValues.length !== right.length) {
38
+ return false;
39
+ }
40
+ const leftSet = new Set(leftValues);
41
+ const rightSet = new Set(right);
42
+ if (leftSet.size !== rightSet.size) {
43
+ return false;
44
+ }
45
+ return [...leftSet].every((value) => rightSet.has(value));
46
+ }
47
+ export function hasWorkspaceSkillProfileDrift(state) {
48
+ const workspaceSkills = state?.workspace_skills;
49
+ if (!workspaceSkills) {
50
+ return false;
51
+ }
52
+ const current = getCurrentWorkspaceSkillProfileSelection();
53
+ return (workspaceSkills.last_applied_profile !== current.profile ||
54
+ workspaceSkills.last_applied_delivery !== current.delivery ||
55
+ !arraysEqual(workspaceSkills.last_applied_workflow_ids, current.workflow_ids));
56
+ }
57
+ function makeBaseWorkspaceSkillReport(selectedAgentIds, profileContext = resolveWorkspaceSkillProfileContext()) {
58
+ return {
59
+ profile: profileContext.profile,
60
+ delivery: profileContext.delivery,
61
+ workflow_ids: profileContext.workflowIds,
62
+ selected_agents: selectedAgentIds,
63
+ skills_only: true,
64
+ delivery_notice: profileContext.deliveryNotice,
65
+ generated: [],
66
+ added: [],
67
+ refreshed: [],
68
+ removed: [],
69
+ skipped: [],
70
+ failed: [],
71
+ };
72
+ }
73
+ export function getWorkspaceSkillCapableTools() {
74
+ return AI_TOOLS.filter((tool) => Boolean(tool.skillsDir));
75
+ }
76
+ export function getWorkspaceSkillToolIds() {
77
+ return getToolsWithSkillsDir();
78
+ }
79
+ export function parseWorkspaceSkillToolsValue(rawTools) {
80
+ const raw = rawTools.trim();
81
+ if (raw.length === 0) {
82
+ throw new Error('The --tools option requires a value. Use "all", "none", or a comma-separated list of agent IDs.');
83
+ }
84
+ const availableTools = getWorkspaceSkillToolIds();
85
+ const availableSet = new Set(availableTools);
86
+ const availableList = ['all', 'none', ...availableTools].join(', ');
87
+ const lowerRaw = raw.toLowerCase();
88
+ if (lowerRaw === 'all') {
89
+ return availableTools;
90
+ }
91
+ if (lowerRaw === 'none') {
92
+ return [];
93
+ }
94
+ const tokens = raw
95
+ .split(',')
96
+ .map((token) => token.trim())
97
+ .filter((token) => token.length > 0);
98
+ if (tokens.length === 0) {
99
+ throw new Error('The --tools option requires at least one agent ID when not using "all" or "none".');
100
+ }
101
+ const normalizedTokens = tokens.map((token) => token.toLowerCase());
102
+ if (normalizedTokens.some((token) => token === 'all' || token === 'none')) {
103
+ throw new Error('Cannot combine reserved values "all" or "none" with specific agent IDs.');
104
+ }
105
+ const invalidTokens = tokens.filter((_token, index) => !availableSet.has(normalizedTokens[index]));
106
+ if (invalidTokens.length > 0) {
107
+ throw new Error(`Invalid agent(s): ${invalidTokens.join(', ')}. Available values: ${availableList}`);
108
+ }
109
+ const deduped = [];
110
+ for (const token of normalizedTokens) {
111
+ if (!deduped.includes(token)) {
112
+ deduped.push(token);
113
+ }
114
+ }
115
+ return deduped;
116
+ }
117
+ export function createWorkspaceSkillSkippedReport(reason, message) {
118
+ const report = makeBaseWorkspaceSkillReport([]);
119
+ report.skipped.push({
120
+ reason,
121
+ message,
122
+ });
123
+ return report;
124
+ }
125
+ function getWorkspaceSkillTool(toolId) {
126
+ const tool = getWorkspaceSkillCapableTools().find((candidate) => candidate.value === toolId);
127
+ if (!tool) {
128
+ throw new Error(`Unknown workspace skill agent '${toolId}'.`);
129
+ }
130
+ return tool;
131
+ }
132
+ function getWorkspaceSkillDirectoryForTool(workspaceRoot, tool) {
133
+ return FileSystemUtils.joinPath(workspaceRoot, tool.skillsDir, 'skills');
134
+ }
135
+ export function getWorkspaceSkillDirectory(workspaceRoot, toolId) {
136
+ return getWorkspaceSkillDirectoryForTool(workspaceRoot, getWorkspaceSkillTool(toolId));
137
+ }
138
+ function makeAgentResult(workspaceRoot, tool, workflowIds) {
139
+ return {
140
+ tool_id: tool.value,
141
+ name: tool.name,
142
+ skills_path: getWorkspaceSkillDirectoryForTool(workspaceRoot, tool),
143
+ workflow_ids: workflowIds,
144
+ };
145
+ }
146
+ function getManagedWorkspaceSkillEntries() {
147
+ return getSkillTemplates().map(({ workflowId, dirName }) => ({ workflowId, dirName }));
148
+ }
149
+ async function pathExists(targetPath) {
150
+ try {
151
+ await fs.access(targetPath);
152
+ return true;
153
+ }
154
+ catch {
155
+ return false;
156
+ }
157
+ }
158
+ function isPastelsddManagedSkillDir(skillDir) {
159
+ const skillFile = FileSystemUtils.joinPath(skillDir, 'SKILL.md');
160
+ return extractGeneratedByVersion(skillFile) !== null;
161
+ }
162
+ async function removeManagedWorkflowSkillDirs(workspaceRoot, tool, desiredWorkflowIds, reason) {
163
+ const desiredSet = new Set(desiredWorkflowIds);
164
+ const skillsDir = getWorkspaceSkillDirectoryForTool(workspaceRoot, tool);
165
+ const removedWorkflowIds = [];
166
+ for (const { workflowId, dirName } of getManagedWorkspaceSkillEntries()) {
167
+ if (desiredSet.has(workflowId)) {
168
+ continue;
169
+ }
170
+ const skillDir = FileSystemUtils.joinPath(skillsDir, dirName);
171
+ if (!(await pathExists(skillDir))) {
172
+ continue;
173
+ }
174
+ if (!isPastelsddManagedSkillDir(skillDir)) {
175
+ continue;
176
+ }
177
+ await fs.rm(skillDir, { recursive: true, force: true });
178
+ removedWorkflowIds.push(workflowId);
179
+ }
180
+ if (removedWorkflowIds.length === 0) {
181
+ return null;
182
+ }
183
+ return {
184
+ ...makeAgentResult(workspaceRoot, tool, removedWorkflowIds),
185
+ reason,
186
+ };
187
+ }
188
+ export async function generateWorkspaceAgentSkills(workspaceRoot, selectedAgentIds) {
189
+ const profileContext = resolveWorkspaceSkillProfileContext();
190
+ const report = makeBaseWorkspaceSkillReport(selectedAgentIds, profileContext);
191
+ if (selectedAgentIds.length === 0) {
192
+ report.skipped.push({
193
+ reason: 'no_agents_selected',
194
+ message: 'No workspace agent skills were selected.',
195
+ });
196
+ return report;
197
+ }
198
+ const skillTemplates = getSkillTemplates(profileContext.workflowIds);
199
+ if (skillTemplates.length === 0) {
200
+ for (const toolId of selectedAgentIds) {
201
+ const tool = getWorkspaceSkillTool(toolId);
202
+ report.skipped.push({
203
+ tool_id: tool.value,
204
+ name: tool.name,
205
+ reason: 'no_profile_workflows',
206
+ message: 'The active global profile does not select any workflows.',
207
+ });
208
+ }
209
+ return report;
210
+ }
211
+ for (const toolId of selectedAgentIds) {
212
+ const tool = getWorkspaceSkillTool(toolId);
213
+ const wasConfigured = getToolSkillStatus(workspaceRoot, tool.value).configured;
214
+ try {
215
+ const skillsDir = getWorkspaceSkillDirectoryForTool(workspaceRoot, tool);
216
+ const transformer = tool.value === 'opencode' || tool.value === 'pi' ? transformToHyphenCommands : undefined;
217
+ for (const { template, dirName } of skillTemplates) {
218
+ const skillFile = FileSystemUtils.joinPath(skillsDir, dirName, 'SKILL.md');
219
+ const skillContent = generateSkillContent(template, PASTELSDD_VERSION, transformer);
220
+ await FileSystemUtils.writeFile(skillFile, skillContent);
221
+ }
222
+ const result = makeAgentResult(workspaceRoot, tool, profileContext.workflowIds);
223
+ if (wasConfigured) {
224
+ report.refreshed.push(result);
225
+ }
226
+ else {
227
+ report.generated.push(result);
228
+ }
229
+ }
230
+ catch (error) {
231
+ report.failed.push({
232
+ tool_id: tool.value,
233
+ name: tool.name,
234
+ error: error instanceof Error ? error.message : String(error),
235
+ });
236
+ }
237
+ }
238
+ return report;
239
+ }
240
+ export async function updateWorkspaceAgentSkills(workspaceRoot, selectedAgentIds, previousSkillState) {
241
+ const profileContext = resolveWorkspaceSkillProfileContext();
242
+ const report = makeBaseWorkspaceSkillReport(selectedAgentIds, profileContext);
243
+ const previousSelectedAgentIds = previousSkillState?.selected_agents ?? [];
244
+ const previousSelectedSet = new Set(previousSelectedAgentIds);
245
+ const selectedSet = new Set(selectedAgentIds);
246
+ const skillTemplates = getSkillTemplates(profileContext.workflowIds);
247
+ for (const toolId of previousSelectedAgentIds) {
248
+ if (selectedSet.has(toolId)) {
249
+ continue;
250
+ }
251
+ const tool = getWorkspaceSkillTool(toolId);
252
+ try {
253
+ const removed = await removeManagedWorkflowSkillDirs(workspaceRoot, tool, [], 'agent_unselected');
254
+ if (removed) {
255
+ report.removed.push(removed);
256
+ }
257
+ }
258
+ catch (error) {
259
+ report.failed.push({
260
+ tool_id: tool.value,
261
+ name: tool.name,
262
+ error: error instanceof Error ? error.message : String(error),
263
+ });
264
+ }
265
+ }
266
+ if (selectedAgentIds.length === 0) {
267
+ if (report.removed.length === 0) {
268
+ report.skipped.push({
269
+ reason: previousSkillState ? 'no_agents_selected' : 'no_stored_agent_selection',
270
+ message: previousSkillState
271
+ ? 'No workspace agent skills were selected.'
272
+ : 'No workspace agent skill selection is stored. Pass --tools <ids> to install skills.',
273
+ });
274
+ }
275
+ return report;
276
+ }
277
+ if (skillTemplates.length === 0) {
278
+ for (const toolId of selectedAgentIds) {
279
+ const tool = getWorkspaceSkillTool(toolId);
280
+ try {
281
+ const removed = await removeManagedWorkflowSkillDirs(workspaceRoot, tool, [], 'workflow_unselected');
282
+ if (removed) {
283
+ report.removed.push(removed);
284
+ }
285
+ }
286
+ catch (error) {
287
+ report.failed.push({
288
+ tool_id: tool.value,
289
+ name: tool.name,
290
+ error: error instanceof Error ? error.message : String(error),
291
+ });
292
+ }
293
+ report.skipped.push({
294
+ tool_id: tool.value,
295
+ name: tool.name,
296
+ reason: 'no_profile_workflows',
297
+ message: 'The active global profile does not select any workflows.',
298
+ });
299
+ }
300
+ return report;
301
+ }
302
+ for (const toolId of selectedAgentIds) {
303
+ const tool = getWorkspaceSkillTool(toolId);
304
+ try {
305
+ const skillsDir = getWorkspaceSkillDirectoryForTool(workspaceRoot, tool);
306
+ const transformer = tool.value === 'opencode' || tool.value === 'pi' ? transformToHyphenCommands : undefined;
307
+ for (const { template, dirName } of skillTemplates) {
308
+ const skillFile = FileSystemUtils.joinPath(skillsDir, dirName, 'SKILL.md');
309
+ const skillContent = generateSkillContent(template, PASTELSDD_VERSION, transformer);
310
+ await FileSystemUtils.writeFile(skillFile, skillContent);
311
+ }
312
+ const removed = await removeManagedWorkflowSkillDirs(workspaceRoot, tool, profileContext.workflowIds, 'workflow_unselected');
313
+ if (removed) {
314
+ report.removed.push(removed);
315
+ }
316
+ const result = makeAgentResult(workspaceRoot, tool, profileContext.workflowIds);
317
+ if (previousSelectedSet.has(toolId)) {
318
+ report.refreshed.push(result);
319
+ }
320
+ else {
321
+ report.added.push(result);
322
+ }
323
+ }
324
+ catch (error) {
325
+ report.failed.push({
326
+ tool_id: tool.value,
327
+ name: tool.name,
328
+ error: error instanceof Error ? error.message : String(error),
329
+ });
330
+ }
331
+ }
332
+ return report;
333
+ }
334
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1,10 @@
1
+ import { type WorkspaceViewState } from './foundation.js';
2
+ export declare function isWorkspaceRoot(candidateRoot: string): Promise<boolean>;
3
+ export declare function findWorkspaceRoot(startPath?: string): Promise<string | null>;
4
+ export declare function workspaceStateFileExistsSync(workspaceRoot: string): boolean;
5
+ export declare function readWorkspaceViewState(workspaceRoot: string): Promise<WorkspaceViewState>;
6
+ export declare function readWorkspaceViewStateSync(workspaceRoot: string): WorkspaceViewState | null;
7
+ export declare function readOptionalWorkspaceViewState(workspaceRoot: string): Promise<WorkspaceViewState | null>;
8
+ export declare function writeWorkspaceViewState(workspaceRoot: string, state: WorkspaceViewState): Promise<void>;
9
+ export declare function workspaceChangesDirExists(workspaceRoot: string): Promise<boolean>;
10
+ //# sourceMappingURL=state-io.d.ts.map
@@ -0,0 +1,119 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { FileSystemUtils } from '../../utils/file-system.js';
4
+ import { getWorkspaceChangesDir, getWorkspaceViewStatePath, parseWorkspaceViewState, serializeWorkspaceViewState, } from './foundation.js';
5
+ import { getWorkspaceLegacyLocalStatePath, getWorkspaceLegacySharedStatePath, parseWorkspaceLocalState, parseWorkspaceSharedState, workspaceStatePartsToViewState, } from './legacy-state.js';
6
+ const fs = nodeFs.promises;
7
+ async function pathIsFile(filePath) {
8
+ try {
9
+ return (await fs.stat(filePath)).isFile();
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ async function pathIsDirectory(dirPath) {
16
+ try {
17
+ return (await fs.stat(dirPath)).isDirectory();
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ function pathExistsAsFile(filePath) {
24
+ try {
25
+ return nodeFs.statSync(filePath).isFile();
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ function isFileNotFoundError(error) {
32
+ return (typeof error === 'object' &&
33
+ error !== null &&
34
+ 'code' in error &&
35
+ error.code === 'ENOENT');
36
+ }
37
+ async function getSearchStartDirectory(startPath) {
38
+ const resolvedStart = path.resolve(startPath);
39
+ try {
40
+ const stats = await fs.stat(resolvedStart);
41
+ const searchStart = stats.isDirectory() ? resolvedStart : path.dirname(resolvedStart);
42
+ return FileSystemUtils.canonicalizeExistingPath(searchStart);
43
+ }
44
+ catch {
45
+ return resolvedStart;
46
+ }
47
+ }
48
+ export async function isWorkspaceRoot(candidateRoot) {
49
+ return ((await pathIsFile(getWorkspaceViewStatePath(candidateRoot))) ||
50
+ (await pathIsFile(getWorkspaceLegacySharedStatePath(candidateRoot))));
51
+ }
52
+ export async function findWorkspaceRoot(startPath = process.cwd()) {
53
+ let currentDir = await getSearchStartDirectory(startPath);
54
+ while (true) {
55
+ if (await isWorkspaceRoot(currentDir)) {
56
+ return FileSystemUtils.canonicalizeExistingPath(currentDir);
57
+ }
58
+ const parentDir = path.dirname(currentDir);
59
+ if (parentDir === currentDir) {
60
+ return null;
61
+ }
62
+ currentDir = parentDir;
63
+ }
64
+ }
65
+ export function workspaceStateFileExistsSync(workspaceRoot) {
66
+ return (pathExistsAsFile(getWorkspaceViewStatePath(workspaceRoot)) ||
67
+ pathExistsAsFile(getWorkspaceLegacySharedStatePath(workspaceRoot)));
68
+ }
69
+ export async function readWorkspaceViewState(workspaceRoot) {
70
+ const viewStatePath = getWorkspaceViewStatePath(workspaceRoot);
71
+ if (await pathIsFile(viewStatePath)) {
72
+ return parseWorkspaceViewState(await fs.readFile(viewStatePath, 'utf-8'));
73
+ }
74
+ const legacySharedState = parseWorkspaceSharedState(await fs.readFile(getWorkspaceLegacySharedStatePath(workspaceRoot), 'utf-8'));
75
+ let legacyLocalState = null;
76
+ try {
77
+ legacyLocalState = parseWorkspaceLocalState(await fs.readFile(getWorkspaceLegacyLocalStatePath(workspaceRoot), 'utf-8'));
78
+ }
79
+ catch (error) {
80
+ if (!isFileNotFoundError(error)) {
81
+ throw error;
82
+ }
83
+ }
84
+ return workspaceStatePartsToViewState(legacySharedState, legacyLocalState);
85
+ }
86
+ export function readWorkspaceViewStateSync(workspaceRoot) {
87
+ const viewStatePath = getWorkspaceViewStatePath(workspaceRoot);
88
+ if (pathExistsAsFile(viewStatePath)) {
89
+ return parseWorkspaceViewState(nodeFs.readFileSync(viewStatePath, 'utf-8'));
90
+ }
91
+ const legacySharedPath = getWorkspaceLegacySharedStatePath(workspaceRoot);
92
+ if (!pathExistsAsFile(legacySharedPath)) {
93
+ return null;
94
+ }
95
+ const legacySharedState = parseWorkspaceSharedState(nodeFs.readFileSync(legacySharedPath, 'utf-8'));
96
+ const legacyLocalPath = getWorkspaceLegacyLocalStatePath(workspaceRoot);
97
+ const legacyLocalState = pathExistsAsFile(legacyLocalPath)
98
+ ? parseWorkspaceLocalState(nodeFs.readFileSync(legacyLocalPath, 'utf-8'))
99
+ : null;
100
+ return workspaceStatePartsToViewState(legacySharedState, legacyLocalState);
101
+ }
102
+ export async function readOptionalWorkspaceViewState(workspaceRoot) {
103
+ try {
104
+ return await readWorkspaceViewState(workspaceRoot);
105
+ }
106
+ catch (error) {
107
+ if (isFileNotFoundError(error)) {
108
+ return null;
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+ export async function writeWorkspaceViewState(workspaceRoot, state) {
114
+ await FileSystemUtils.writeFile(getWorkspaceViewStatePath(workspaceRoot), serializeWorkspaceViewState(state));
115
+ }
116
+ export async function workspaceChangesDirExists(workspaceRoot) {
117
+ return pathIsDirectory(getWorkspaceChangesDir(workspaceRoot));
118
+ }
119
+ //# sourceMappingURL=state-io.js.map
@@ -0,0 +1,3 @@
1
+ export * from './cli/index.js';
2
+ export * from './core/index.js';
3
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './cli/index.js';
2
+ export * from './core/index.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,28 @@
1
+ interface Choice {
2
+ name: string;
3
+ value: string;
4
+ description?: string;
5
+ configured?: boolean;
6
+ detected?: boolean;
7
+ configuredLabel?: string;
8
+ preSelected?: boolean;
9
+ }
10
+ interface Config {
11
+ message: string;
12
+ choices: Choice[];
13
+ pageSize?: number;
14
+ validate?: (selected: string[]) => boolean | string;
15
+ }
16
+ /**
17
+ * A searchable multi-select prompt with visible search box,
18
+ * selected items display, and intuitive keyboard navigation.
19
+ *
20
+ * - Type to filter choices
21
+ * - ↑↓ to navigate
22
+ * - Space to toggle highlighted item selection
23
+ * - Backspace to remove last selected item (or delete search char)
24
+ * - Enter to confirm selections
25
+ */
26
+ export declare function searchableMultiSelect(config: Config): Promise<string[]>;
27
+ export default searchableMultiSelect;
28
+ //# sourceMappingURL=searchable-multi-select.d.ts.map
@@ -0,0 +1,159 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Create the searchable multi-select prompt.
4
+ * Uses dynamic import to prevent pre-commit hook hangs (see #367).
5
+ */
6
+ async function createSearchableMultiSelect() {
7
+ const { createPrompt, useState, useKeypress, useMemo, usePrefix, isEnterKey, isBackspaceKey, isUpKey, isDownKey, } = await import('@inquirer/core');
8
+ return createPrompt((config, done) => {
9
+ const { message, choices, pageSize = 15, validate } = config;
10
+ const [searchText, setSearchText] = useState('');
11
+ const [selectedValues, setSelectedValues] = useState(() => choices.filter(c => c.preSelected).map(c => c.value));
12
+ const [cursor, setCursor] = useState(0);
13
+ const [status, setStatus] = useState('idle');
14
+ const [error, setError] = useState(null);
15
+ const prefix = usePrefix({ status });
16
+ // Filter choices by search
17
+ const filteredChoices = useMemo(() => {
18
+ if (!searchText.trim())
19
+ return choices;
20
+ const term = searchText.toLowerCase();
21
+ return choices.filter((c) => c.name.toLowerCase().includes(term) ||
22
+ c.value.toLowerCase().includes(term));
23
+ }, [searchText, choices]);
24
+ const selectedSet = useMemo(() => new Set(selectedValues), [selectedValues]);
25
+ const choiceMap = useMemo(() => new Map(choices.map((c) => [c.value, c])), [choices]);
26
+ useKeypress((key) => {
27
+ if (status === 'done')
28
+ return;
29
+ // Enter to confirm/submit
30
+ if (isEnterKey(key)) {
31
+ if (validate) {
32
+ const result = validate(selectedValues);
33
+ if (result !== true) {
34
+ setError(typeof result === 'string' ? result : 'Invalid');
35
+ return;
36
+ }
37
+ }
38
+ setStatus('done');
39
+ done(selectedValues);
40
+ return;
41
+ }
42
+ // Space to toggle selection
43
+ if (key.name === 'space') {
44
+ const choice = filteredChoices[cursor];
45
+ if (choice) {
46
+ if (selectedSet.has(choice.value)) {
47
+ setSelectedValues(selectedValues.filter(v => v !== choice.value));
48
+ }
49
+ else {
50
+ setSelectedValues([...selectedValues, choice.value]);
51
+ }
52
+ }
53
+ return;
54
+ }
55
+ // Backspace to remove or delete search char
56
+ if (isBackspaceKey(key)) {
57
+ if (searchText === '' && selectedValues.length > 0) {
58
+ setSelectedValues(selectedValues.slice(0, -1));
59
+ }
60
+ else {
61
+ setSearchText(searchText.slice(0, -1));
62
+ setCursor(0);
63
+ }
64
+ return;
65
+ }
66
+ // Navigation
67
+ if (isUpKey(key)) {
68
+ setCursor(Math.max(0, cursor - 1));
69
+ return;
70
+ }
71
+ if (isDownKey(key)) {
72
+ setCursor(Math.min(filteredChoices.length - 1, cursor + 1));
73
+ return;
74
+ }
75
+ // Character input - handle printable characters
76
+ if (key.name && key.name.length === 1 && !key.ctrl) {
77
+ setSearchText(searchText + key.name);
78
+ setCursor(0);
79
+ }
80
+ });
81
+ // Render done state
82
+ if (status === 'done') {
83
+ const names = selectedValues
84
+ .map((v) => choiceMap.get(v)?.name ?? v)
85
+ .join(', ');
86
+ return `${prefix} ${chalk.bold(message)} ${chalk.cyan(names || '(none)')}`;
87
+ }
88
+ // Render active state
89
+ const lines = [];
90
+ lines.push(`${prefix} ${chalk.bold(message)}`);
91
+ // Selected chips
92
+ const chips = selectedValues.length > 0
93
+ ? selectedValues
94
+ .map((v) => chalk.bgCyan.black(` ${choiceMap.get(v)?.name} `))
95
+ .join(' ')
96
+ : chalk.dim('(none selected)');
97
+ lines.push(` Selected: ${chips}`);
98
+ // Search box
99
+ lines.push(` Search: ${chalk.yellow('[')}${searchText || chalk.dim('type to filter')}${chalk.yellow(']')}`);
100
+ // Instructions
101
+ lines.push(` ${chalk.cyan('↑↓')} navigate • ${chalk.cyan('Space')} toggle • ${chalk.cyan('Backspace')} remove • ${chalk.cyan('Enter')} confirm`);
102
+ // List
103
+ if (filteredChoices.length === 0) {
104
+ lines.push(chalk.yellow(' No matches'));
105
+ }
106
+ else {
107
+ // Calculate pagination
108
+ const startIndex = Math.max(0, Math.min(cursor - Math.floor(pageSize / 2), filteredChoices.length - pageSize));
109
+ const endIndex = Math.min(startIndex + pageSize, filteredChoices.length);
110
+ const visibleChoices = filteredChoices.slice(startIndex, endIndex);
111
+ for (let i = 0; i < visibleChoices.length; i++) {
112
+ const item = visibleChoices[i];
113
+ const actualIndex = startIndex + i;
114
+ const isActive = actualIndex === cursor;
115
+ const selected = selectedSet.has(item.value);
116
+ const icon = selected ? chalk.green('◉') : chalk.dim('○');
117
+ const arrow = isActive ? chalk.cyan('›') : ' ';
118
+ const name = isActive ? chalk.cyan(item.name) : item.name;
119
+ const isRefresh = selected && item.configured;
120
+ const statusLabel = !selected
121
+ ? item.configured
122
+ ? ' (configured)'
123
+ : item.detected
124
+ ? ' (detected)'
125
+ : ''
126
+ : '';
127
+ const suffix = selected
128
+ ? chalk.dim(isRefresh ? ' (refresh)' : ' (selected)')
129
+ : chalk.dim(statusLabel);
130
+ lines.push(` ${arrow} ${icon} ${name}${suffix}`);
131
+ }
132
+ // Show pagination indicator if needed
133
+ if (filteredChoices.length > pageSize) {
134
+ const currentPage = Math.floor(cursor / pageSize) + 1;
135
+ const totalPages = Math.ceil(filteredChoices.length / pageSize);
136
+ lines.push(chalk.dim(` (${currentPage}/${totalPages})`));
137
+ }
138
+ }
139
+ if (error)
140
+ lines.push(chalk.red(` ${error}`));
141
+ return lines.join('\n');
142
+ });
143
+ }
144
+ /**
145
+ * A searchable multi-select prompt with visible search box,
146
+ * selected items display, and intuitive keyboard navigation.
147
+ *
148
+ * - Type to filter choices
149
+ * - ↑↓ to navigate
150
+ * - Space to toggle highlighted item selection
151
+ * - Backspace to remove last selected item (or delete search char)
152
+ * - Enter to confirm selections
153
+ */
154
+ export async function searchableMultiSelect(config) {
155
+ const prompt = await createSearchableMultiSelect();
156
+ return prompt(config);
157
+ }
158
+ export default searchableMultiSelect;
159
+ //# sourceMappingURL=searchable-multi-select.js.map