agents-inc 0.149.2 → 0.151.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 (572) hide show
  1. package/CHANGELOG.md +2287 -0
  2. package/LICENSE +21 -0
  3. package/README.md +136 -19
  4. package/assets/demo.gif +0 -0
  5. package/assets/demo.tape +266 -0
  6. package/assets/logo.svg +75 -0
  7. package/dist/chunk-2RSNKBXC.js +84 -0
  8. package/dist/chunk-2RSNKBXC.js.map +1 -0
  9. package/dist/chunk-3LIU2ZEF.js +1355 -0
  10. package/dist/chunk-3LIU2ZEF.js.map +1 -0
  11. package/dist/chunk-3XFUQ6OL.js +68 -0
  12. package/dist/chunk-3XFUQ6OL.js.map +1 -0
  13. package/dist/chunk-3YGUHWLR.js +258 -0
  14. package/dist/chunk-3YGUHWLR.js.map +1 -0
  15. package/dist/chunk-44LLPS2N.js +1135 -0
  16. package/dist/chunk-44LLPS2N.js.map +1 -0
  17. package/dist/chunk-4R6PGHQQ.js +300 -0
  18. package/dist/chunk-4R6PGHQQ.js.map +1 -0
  19. package/dist/chunk-5V2O6C3T.js +112 -0
  20. package/dist/chunk-5V2O6C3T.js.map +1 -0
  21. package/dist/chunk-6RBQBOBS.js +287 -0
  22. package/dist/chunk-6RBQBOBS.js.map +1 -0
  23. package/dist/chunk-7QIHKQL5.js +181 -0
  24. package/dist/chunk-7QIHKQL5.js.map +1 -0
  25. package/dist/chunk-BNE4HHIH.js +28 -0
  26. package/dist/chunk-BNE4HHIH.js.map +1 -0
  27. package/dist/chunk-C55DN7GE.js +35 -0
  28. package/dist/chunk-C55DN7GE.js.map +1 -0
  29. package/dist/chunk-DAG2ULNF.js +125 -0
  30. package/dist/chunk-DAG2ULNF.js.map +1 -0
  31. package/dist/chunk-DG2NGZ7S.js +10929 -0
  32. package/dist/chunk-DG2NGZ7S.js.map +1 -0
  33. package/dist/chunk-DIBCRIMR.js +36 -0
  34. package/dist/chunk-DIBCRIMR.js.map +1 -0
  35. package/dist/chunk-DUVWGO6E.js +54 -0
  36. package/dist/chunk-DUVWGO6E.js.map +1 -0
  37. package/dist/chunk-EKWAUOQB.js +96 -0
  38. package/dist/chunk-EKWAUOQB.js.map +1 -0
  39. package/dist/chunk-ES3NJZON.js +31 -0
  40. package/dist/chunk-ES3NJZON.js.map +1 -0
  41. package/dist/chunk-EVXG3X6G.js +179 -0
  42. package/dist/chunk-EVXG3X6G.js.map +1 -0
  43. package/dist/chunk-EZ7STXUV.js +349 -0
  44. package/dist/chunk-EZ7STXUV.js.map +1 -0
  45. package/dist/chunk-FYPUUYSG.js +31 -0
  46. package/dist/chunk-FYPUUYSG.js.map +1 -0
  47. package/dist/chunk-GYG5SE2D.js +81 -0
  48. package/dist/chunk-GYG5SE2D.js.map +1 -0
  49. package/dist/chunk-I3XKEGHM.js +16383 -0
  50. package/dist/chunk-I3XKEGHM.js.map +1 -0
  51. package/dist/chunk-IHO75PMZ.js +40 -0
  52. package/dist/chunk-IHO75PMZ.js.map +1 -0
  53. package/dist/chunk-IOJR5TOY.js +47 -0
  54. package/dist/chunk-IOJR5TOY.js.map +1 -0
  55. package/dist/chunk-K3OU6TGX.js +77 -0
  56. package/dist/chunk-K3OU6TGX.js.map +1 -0
  57. package/dist/chunk-KIR7VYQD.js +63 -0
  58. package/dist/chunk-KIR7VYQD.js.map +1 -0
  59. package/dist/chunk-KOPEM3Q7.js +27 -0
  60. package/dist/chunk-KOPEM3Q7.js.map +1 -0
  61. package/dist/chunk-KSZ6PCY4.js +43 -0
  62. package/dist/chunk-KSZ6PCY4.js.map +1 -0
  63. package/dist/chunk-LAXAQ3PZ.js +235 -0
  64. package/dist/chunk-LAXAQ3PZ.js.map +1 -0
  65. package/dist/chunk-LYYXX2W5.js +87 -0
  66. package/dist/chunk-LYYXX2W5.js.map +1 -0
  67. package/dist/chunk-NGLQ5W7U.js +339 -0
  68. package/dist/chunk-NGLQ5W7U.js.map +1 -0
  69. package/dist/chunk-NHCGC6DG.js +111 -0
  70. package/dist/chunk-NHCGC6DG.js.map +1 -0
  71. package/dist/chunk-NIKUMXE7.js +24 -0
  72. package/dist/chunk-NIKUMXE7.js.map +1 -0
  73. package/dist/chunk-NM3EDGB5.js +300 -0
  74. package/dist/chunk-NM3EDGB5.js.map +1 -0
  75. package/dist/chunk-O5ASLZ2K.js +270 -0
  76. package/dist/chunk-O5ASLZ2K.js.map +1 -0
  77. package/dist/chunk-OJIESW5B.js +174 -0
  78. package/dist/chunk-OJIESW5B.js.map +1 -0
  79. package/dist/chunk-OZZGXBCN.js +15 -0
  80. package/dist/chunk-OZZGXBCN.js.map +1 -0
  81. package/dist/chunk-P3PN5SVI.js +27 -0
  82. package/dist/chunk-P3PN5SVI.js.map +1 -0
  83. package/dist/chunk-P56WJ5FA.js +50 -0
  84. package/dist/chunk-P56WJ5FA.js.map +1 -0
  85. package/dist/chunk-PG4G4IIK.js +24 -0
  86. package/dist/chunk-PG4G4IIK.js.map +1 -0
  87. package/dist/chunk-PV2HNW4I.js +382 -0
  88. package/dist/chunk-PV2HNW4I.js.map +1 -0
  89. package/dist/chunk-QQLRX4KI.js +41 -0
  90. package/dist/chunk-QQLRX4KI.js.map +1 -0
  91. package/dist/chunk-QTFQEYDA.js +789 -0
  92. package/dist/chunk-QTFQEYDA.js.map +1 -0
  93. package/dist/chunk-RBHYLCUB.js +31 -0
  94. package/dist/chunk-RBHYLCUB.js.map +1 -0
  95. package/dist/chunk-SHHOMVWC.js +62 -0
  96. package/dist/chunk-SHHOMVWC.js.map +1 -0
  97. package/dist/chunk-SI5FOARI.js +42 -0
  98. package/dist/chunk-SI5FOARI.js.map +1 -0
  99. package/dist/chunk-SYUOXSPU.js +510 -0
  100. package/dist/chunk-SYUOXSPU.js.map +1 -0
  101. package/dist/chunk-THKIOI32.js +939 -0
  102. package/dist/chunk-THKIOI32.js.map +1 -0
  103. package/dist/chunk-TVHRMRD3.js +6014 -0
  104. package/dist/chunk-TVHRMRD3.js.map +1 -0
  105. package/dist/chunk-TYJLR32W.js +128 -0
  106. package/dist/chunk-TYJLR32W.js.map +1 -0
  107. package/dist/chunk-UFURYGD3.js +20 -0
  108. package/dist/chunk-UFURYGD3.js.map +1 -0
  109. package/dist/chunk-UTFN6UJS.js +253 -0
  110. package/dist/chunk-UTFN6UJS.js.map +1 -0
  111. package/dist/chunk-V7QOSGQA.js +298 -0
  112. package/dist/chunk-V7QOSGQA.js.map +1 -0
  113. package/dist/chunk-VEP23B5W.js +27 -0
  114. package/dist/chunk-VEP23B5W.js.map +1 -0
  115. package/dist/chunk-VG2TVBFN.js +52 -0
  116. package/dist/chunk-VG2TVBFN.js.map +1 -0
  117. package/dist/chunk-WFWCZEMS.js +92 -0
  118. package/dist/chunk-WFWCZEMS.js.map +1 -0
  119. package/dist/chunk-WK4J2CHH.js +430 -0
  120. package/dist/chunk-WK4J2CHH.js.map +1 -0
  121. package/dist/chunk-XA57SX4T.js +115 -0
  122. package/dist/chunk-XA57SX4T.js.map +1 -0
  123. package/dist/chunk-Y4CXDA3I.js +181 -0
  124. package/dist/chunk-Y4CXDA3I.js.map +1 -0
  125. package/dist/chunk-YA4QQKKE.js +51 -0
  126. package/dist/chunk-YA4QQKKE.js.map +1 -0
  127. package/dist/chunk-YBVA7GPW.js +27 -0
  128. package/dist/chunk-YBVA7GPW.js.map +1 -0
  129. package/dist/chunk-YU2VGX5R.js +4205 -0
  130. package/dist/chunk-YU2VGX5R.js.map +1 -0
  131. package/dist/commands/build/marketplace.js +250 -0
  132. package/dist/commands/build/marketplace.js.map +1 -0
  133. package/dist/commands/build/plugins.js +176 -0
  134. package/dist/commands/build/plugins.js.map +1 -0
  135. package/dist/commands/compile.js +331 -0
  136. package/dist/commands/compile.js.map +1 -0
  137. package/dist/commands/doctor.js +475 -0
  138. package/dist/commands/doctor.js.map +1 -0
  139. package/dist/commands/edit.js +765 -0
  140. package/dist/commands/edit.js.map +1 -0
  141. package/dist/commands/eject.js +393 -0
  142. package/dist/commands/eject.js.map +1 -0
  143. package/dist/commands/import/skill.js +349 -0
  144. package/dist/commands/import/skill.js.map +1 -0
  145. package/dist/commands/init.js +66 -0
  146. package/dist/commands/init.js.map +1 -0
  147. package/dist/commands/list.js +115 -0
  148. package/dist/commands/list.js.map +1 -0
  149. package/dist/commands/new/agent.js +304 -0
  150. package/dist/commands/new/agent.js.map +1 -0
  151. package/dist/commands/new/marketplace.js +315 -0
  152. package/dist/commands/new/marketplace.js.map +1 -0
  153. package/dist/commands/new/skill.js +28 -0
  154. package/dist/commands/new/skill.js.map +1 -0
  155. package/dist/commands/search.js +176 -0
  156. package/dist/commands/search.js.map +1 -0
  157. package/dist/commands/uninstall.js +570 -0
  158. package/dist/commands/uninstall.js.map +1 -0
  159. package/dist/commands/update.js +368 -0
  160. package/dist/commands/update.js.map +1 -0
  161. package/dist/commands/validate.js +581 -0
  162. package/dist/commands/validate.js.map +1 -0
  163. package/dist/components/common/confirm.js +9 -0
  164. package/dist/components/common/confirm.js.map +1 -0
  165. package/dist/components/common/confirm.test.js +203 -0
  166. package/dist/components/common/confirm.test.js.map +1 -0
  167. package/dist/components/common/prompt-confirm.js +11 -0
  168. package/dist/components/common/prompt-confirm.js.map +1 -0
  169. package/dist/components/common/select-list.js +11 -0
  170. package/dist/components/common/select-list.js.map +1 -0
  171. package/dist/components/common/spinner.js +9 -0
  172. package/dist/components/common/spinner.js.map +1 -0
  173. package/dist/components/wizard/category-grid.js +16 -0
  174. package/dist/components/wizard/category-grid.js.map +1 -0
  175. package/dist/components/wizard/category-grid.test.js +1253 -0
  176. package/dist/components/wizard/category-grid.test.js.map +1 -0
  177. package/dist/components/wizard/checkbox-grid.js +14 -0
  178. package/dist/components/wizard/checkbox-grid.js.map +1 -0
  179. package/dist/components/wizard/checkbox-grid.test.js +264 -0
  180. package/dist/components/wizard/checkbox-grid.test.js.map +1 -0
  181. package/dist/components/wizard/domain-selection.js +22 -0
  182. package/dist/components/wizard/domain-selection.js.map +1 -0
  183. package/dist/components/wizard/run-wizard-session.js +47 -0
  184. package/dist/components/wizard/run-wizard-session.js.map +1 -0
  185. package/dist/components/wizard/scroll-affordance.js +10 -0
  186. package/dist/components/wizard/scroll-affordance.js.map +1 -0
  187. package/dist/components/wizard/search-modal.js +14 -0
  188. package/dist/components/wizard/search-modal.js.map +1 -0
  189. package/dist/components/wizard/search-modal.test.js +212 -0
  190. package/dist/components/wizard/search-modal.test.js.map +1 -0
  191. package/dist/components/wizard/selection-card.js +10 -0
  192. package/dist/components/wizard/selection-card.js.map +1 -0
  193. package/dist/components/wizard/skill-agent-summary.js +16 -0
  194. package/dist/components/wizard/skill-agent-summary.js.map +1 -0
  195. package/dist/components/wizard/source-grid.js +23 -0
  196. package/dist/components/wizard/source-grid.js.map +1 -0
  197. package/dist/components/wizard/source-grid.test.js +1094 -0
  198. package/dist/components/wizard/source-grid.test.js.map +1 -0
  199. package/dist/components/wizard/stack-selection.js +20 -0
  200. package/dist/components/wizard/stack-selection.js.map +1 -0
  201. package/dist/components/wizard/step-agents.js +22 -0
  202. package/dist/components/wizard/step-agents.js.map +1 -0
  203. package/dist/components/wizard/step-agents.test.js +204 -0
  204. package/dist/components/wizard/step-agents.test.js.map +1 -0
  205. package/dist/components/wizard/step-build.js +22 -0
  206. package/dist/components/wizard/step-build.js.map +1 -0
  207. package/dist/components/wizard/step-build.test.js +552 -0
  208. package/dist/components/wizard/step-build.test.js.map +1 -0
  209. package/dist/components/wizard/step-confirm.js +21 -0
  210. package/dist/components/wizard/step-confirm.js.map +1 -0
  211. package/dist/components/wizard/step-confirm.test.js +744 -0
  212. package/dist/components/wizard/step-confirm.test.js.map +1 -0
  213. package/dist/components/wizard/step-settings.js +19 -0
  214. package/dist/components/wizard/step-settings.js.map +1 -0
  215. package/dist/components/wizard/step-settings.test.js +244 -0
  216. package/dist/components/wizard/step-settings.test.js.map +1 -0
  217. package/dist/components/wizard/step-sources.js +28 -0
  218. package/dist/components/wizard/step-sources.js.map +1 -0
  219. package/dist/components/wizard/step-sources.test.js +155 -0
  220. package/dist/components/wizard/step-sources.test.js.map +1 -0
  221. package/dist/components/wizard/step-stack.js +21 -0
  222. package/dist/components/wizard/step-stack.js.map +1 -0
  223. package/dist/components/wizard/step-stack.test.js +262 -0
  224. package/dist/components/wizard/step-stack.test.js.map +1 -0
  225. package/dist/components/wizard/summary-panel.js +20 -0
  226. package/dist/components/wizard/summary-panel.js.map +1 -0
  227. package/dist/components/wizard/summary-panel.test.js +317 -0
  228. package/dist/components/wizard/summary-panel.test.js.map +1 -0
  229. package/dist/components/wizard/toast.js +10 -0
  230. package/dist/components/wizard/toast.js.map +1 -0
  231. package/dist/components/wizard/wizard-layout.js +26 -0
  232. package/dist/components/wizard/wizard-layout.js.map +1 -0
  233. package/dist/components/wizard/wizard-layout.test.js +200 -0
  234. package/dist/components/wizard/wizard-layout.test.js.map +1 -0
  235. package/dist/components/wizard/wizard-tabs.js +20 -0
  236. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  237. package/dist/components/wizard/wizard-tabs.test.js +290 -0
  238. package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
  239. package/dist/components/wizard/wizard.js +48 -0
  240. package/dist/components/wizard/wizard.js.map +1 -0
  241. package/dist/config-exports.js +20 -0
  242. package/dist/config-exports.js.map +1 -0
  243. package/dist/copy-local-skills-UPA2GUZV.js +15 -0
  244. package/dist/copy-local-skills-UPA2GUZV.js.map +1 -0
  245. package/dist/dist-VNJNNJK7.js +550 -0
  246. package/dist/dist-VNJNNJK7.js.map +1 -0
  247. package/dist/hooks/init.js +90 -0
  248. package/dist/hooks/init.js.map +1 -0
  249. package/dist/index.js +10 -0
  250. package/dist/index.js.map +1 -0
  251. package/dist/load-agent-defs-SB4XAOVB.js +16 -0
  252. package/dist/load-agent-defs-SB4XAOVB.js.map +1 -0
  253. package/dist/loader-E2ERJYVA.js +23 -0
  254. package/dist/loader-E2ERJYVA.js.map +1 -0
  255. package/dist/magic-string.es-5TV73NJD.js +1316 -0
  256. package/dist/magic-string.es-5TV73NJD.js.map +1 -0
  257. package/dist/recompile-project-agents-U4ZY2GDX.js +20 -0
  258. package/dist/recompile-project-agents-U4ZY2GDX.js.map +1 -0
  259. package/dist/source-loader-5UNRU7EZ.js +20 -0
  260. package/dist/source-loader-5UNRU7EZ.js.map +1 -0
  261. package/dist/source-manager-3O54SIIB.js +18 -0
  262. package/dist/source-manager-3O54SIIB.js.map +1 -0
  263. package/dist/src/agents/_templates/agent.liquid +161 -0
  264. package/dist/src/agents/_templates/methodologies/anti-over-engineering.liquid +121 -0
  265. package/dist/src/agents/_templates/methodologies/context-management.liquid +162 -0
  266. package/dist/src/agents/_templates/methodologies/improvement-protocol.liquid +150 -0
  267. package/dist/src/agents/_templates/methodologies/investigation-requirements.liquid +49 -0
  268. package/dist/src/agents/_templates/methodologies/success-criteria.liquid +111 -0
  269. package/dist/src/agents/_templates/methodologies/write-verification.liquid +43 -0
  270. package/dist/src/agents/developer/ai-developer/critical-reminders.md +54 -0
  271. package/dist/src/agents/developer/ai-developer/critical-requirements.md +59 -0
  272. package/dist/src/agents/developer/ai-developer/identity.md +51 -0
  273. package/dist/src/agents/developer/ai-developer/metadata.yaml +12 -0
  274. package/dist/src/agents/developer/ai-developer/output.md +366 -0
  275. package/dist/src/agents/developer/ai-developer/playbook.md +335 -0
  276. package/dist/src/agents/developer/api-developer/critical-reminders.md +46 -0
  277. package/dist/src/agents/developer/api-developer/critical-requirements.md +44 -0
  278. package/dist/src/agents/developer/api-developer/identity.md +49 -0
  279. package/dist/src/agents/developer/api-developer/metadata.yaml +12 -0
  280. package/dist/src/agents/developer/api-developer/output.md +432 -0
  281. package/dist/src/agents/developer/api-developer/playbook.md +352 -0
  282. package/dist/src/agents/developer/cli-developer/critical-reminders.md +51 -0
  283. package/dist/src/agents/developer/cli-developer/critical-requirements.md +51 -0
  284. package/dist/src/agents/developer/cli-developer/identity.md +51 -0
  285. package/dist/src/agents/developer/cli-developer/metadata.yaml +12 -0
  286. package/dist/src/agents/developer/cli-developer/output.md +285 -0
  287. package/dist/src/agents/developer/cli-developer/playbook.md +386 -0
  288. package/dist/src/agents/developer/web-architecture/critical-reminders.md +48 -0
  289. package/dist/src/agents/developer/web-architecture/critical-requirements.md +65 -0
  290. package/dist/src/agents/developer/web-architecture/identity.md +64 -0
  291. package/dist/src/agents/developer/web-architecture/metadata.yaml +12 -0
  292. package/dist/src/agents/developer/web-architecture/output.md +449 -0
  293. package/dist/src/agents/developer/web-architecture/playbook.md +481 -0
  294. package/dist/src/agents/developer/web-developer/critical-reminders.md +40 -0
  295. package/dist/src/agents/developer/web-developer/critical-requirements.md +39 -0
  296. package/dist/src/agents/developer/web-developer/identity.md +32 -0
  297. package/dist/src/agents/developer/web-developer/metadata.yaml +12 -0
  298. package/dist/src/agents/developer/web-developer/output.md +323 -0
  299. package/dist/src/agents/developer/web-developer/playbook.md +349 -0
  300. package/dist/src/agents/meta/agent-summoner/critical-reminders.md +45 -0
  301. package/dist/src/agents/meta/agent-summoner/critical-requirements.md +52 -0
  302. package/dist/src/agents/meta/agent-summoner/identity.md +34 -0
  303. package/dist/src/agents/meta/agent-summoner/metadata.yaml +12 -0
  304. package/dist/src/agents/meta/agent-summoner/output.md +296 -0
  305. package/dist/src/agents/meta/agent-summoner/playbook.md +1469 -0
  306. package/dist/src/agents/meta/codex-keeper/critical-reminders.md +39 -0
  307. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +29 -0
  308. package/dist/src/agents/meta/codex-keeper/identity.md +45 -0
  309. package/dist/src/agents/meta/codex-keeper/metadata.yaml +12 -0
  310. package/dist/src/agents/meta/codex-keeper/output.md +384 -0
  311. package/dist/src/agents/meta/codex-keeper/playbook.md +1183 -0
  312. package/dist/src/agents/meta/convention-keeper/critical-reminders.md +32 -0
  313. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +32 -0
  314. package/dist/src/agents/meta/convention-keeper/identity.md +33 -0
  315. package/dist/src/agents/meta/convention-keeper/metadata.yaml +12 -0
  316. package/dist/src/agents/meta/convention-keeper/output.md +206 -0
  317. package/dist/src/agents/meta/convention-keeper/playbook.md +180 -0
  318. package/dist/src/agents/meta/skill-summoner/critical-reminders.md +112 -0
  319. package/dist/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
  320. package/dist/src/agents/meta/skill-summoner/identity.md +31 -0
  321. package/dist/src/agents/meta/skill-summoner/metadata.yaml +13 -0
  322. package/dist/src/agents/meta/skill-summoner/output.md +390 -0
  323. package/dist/src/agents/meta/skill-summoner/playbook.md +1457 -0
  324. package/dist/src/agents/pattern/pattern-scout/critical-reminders.md +71 -0
  325. package/dist/src/agents/pattern/pattern-scout/critical-requirements.md +31 -0
  326. package/dist/src/agents/pattern/pattern-scout/identity.md +25 -0
  327. package/dist/src/agents/pattern/pattern-scout/metadata.yaml +10 -0
  328. package/dist/src/agents/pattern/pattern-scout/output.md +290 -0
  329. package/dist/src/agents/pattern/pattern-scout/playbook.md +1806 -0
  330. package/dist/src/agents/pattern/web-pattern-critique/critical-reminders.md +30 -0
  331. package/dist/src/agents/pattern/web-pattern-critique/critical-requirements.md +28 -0
  332. package/dist/src/agents/pattern/web-pattern-critique/identity.md +41 -0
  333. package/dist/src/agents/pattern/web-pattern-critique/metadata.yaml +12 -0
  334. package/dist/src/agents/pattern/web-pattern-critique/output.md +314 -0
  335. package/dist/src/agents/pattern/web-pattern-critique/playbook.md +572 -0
  336. package/dist/src/agents/planning/api-pm/critical-reminders.md +48 -0
  337. package/dist/src/agents/planning/api-pm/critical-requirements.md +41 -0
  338. package/dist/src/agents/planning/api-pm/identity.md +39 -0
  339. package/dist/src/agents/planning/api-pm/metadata.yaml +12 -0
  340. package/dist/src/agents/planning/api-pm/output.md +475 -0
  341. package/dist/src/agents/planning/api-pm/playbook.md +129 -0
  342. package/dist/src/agents/planning/web-pm/critical-reminders.md +36 -0
  343. package/dist/src/agents/planning/web-pm/critical-requirements.md +32 -0
  344. package/dist/src/agents/planning/web-pm/identity.md +26 -0
  345. package/dist/src/agents/planning/web-pm/metadata.yaml +12 -0
  346. package/dist/src/agents/planning/web-pm/output.md +314 -0
  347. package/dist/src/agents/planning/web-pm/playbook.md +318 -0
  348. package/dist/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
  349. package/dist/src/agents/researcher/api-researcher/critical-requirements.md +28 -0
  350. package/dist/src/agents/researcher/api-researcher/identity.md +71 -0
  351. package/dist/src/agents/researcher/api-researcher/metadata.yaml +10 -0
  352. package/dist/src/agents/researcher/api-researcher/output.md +254 -0
  353. package/dist/src/agents/researcher/api-researcher/playbook.md +201 -0
  354. package/dist/src/agents/researcher/web-researcher/critical-reminders.md +39 -0
  355. package/dist/src/agents/researcher/web-researcher/critical-requirements.md +26 -0
  356. package/dist/src/agents/researcher/web-researcher/identity.md +69 -0
  357. package/dist/src/agents/researcher/web-researcher/metadata.yaml +10 -0
  358. package/dist/src/agents/researcher/web-researcher/output.md +241 -0
  359. package/dist/src/agents/researcher/web-researcher/playbook.md +217 -0
  360. package/dist/src/agents/reviewer/ai-reviewer/critical-reminders.md +40 -0
  361. package/dist/src/agents/reviewer/ai-reviewer/critical-requirements.md +37 -0
  362. package/dist/src/agents/reviewer/ai-reviewer/identity.md +51 -0
  363. package/dist/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  364. package/dist/src/agents/reviewer/ai-reviewer/output.md +395 -0
  365. package/dist/src/agents/reviewer/ai-reviewer/playbook.md +90 -0
  366. package/dist/src/agents/reviewer/api-reviewer/critical-reminders.md +31 -0
  367. package/dist/src/agents/reviewer/api-reviewer/critical-requirements.md +27 -0
  368. package/dist/src/agents/reviewer/api-reviewer/identity.md +51 -0
  369. package/dist/src/agents/reviewer/api-reviewer/metadata.yaml +12 -0
  370. package/dist/src/agents/reviewer/api-reviewer/output.md +343 -0
  371. package/dist/src/agents/reviewer/api-reviewer/playbook.md +288 -0
  372. package/dist/src/agents/reviewer/cli-reviewer/critical-reminders.md +33 -0
  373. package/dist/src/agents/reviewer/cli-reviewer/critical-requirements.md +30 -0
  374. package/dist/src/agents/reviewer/cli-reviewer/identity.md +44 -0
  375. package/dist/src/agents/reviewer/cli-reviewer/metadata.yaml +12 -0
  376. package/dist/src/agents/reviewer/cli-reviewer/output.md +414 -0
  377. package/dist/src/agents/reviewer/cli-reviewer/playbook.md +218 -0
  378. package/dist/src/agents/reviewer/infra-reviewer/critical-reminders.md +38 -0
  379. package/dist/src/agents/reviewer/infra-reviewer/critical-requirements.md +38 -0
  380. package/dist/src/agents/reviewer/infra-reviewer/identity.md +53 -0
  381. package/dist/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  382. package/dist/src/agents/reviewer/infra-reviewer/output.md +364 -0
  383. package/dist/src/agents/reviewer/infra-reviewer/playbook.md +161 -0
  384. package/dist/src/agents/reviewer/web-reviewer/critical-reminders.md +31 -0
  385. package/dist/src/agents/reviewer/web-reviewer/critical-requirements.md +26 -0
  386. package/dist/src/agents/reviewer/web-reviewer/identity.md +40 -0
  387. package/dist/src/agents/reviewer/web-reviewer/metadata.yaml +12 -0
  388. package/dist/src/agents/reviewer/web-reviewer/output.md +333 -0
  389. package/dist/src/agents/reviewer/web-reviewer/playbook.md +156 -0
  390. package/dist/src/agents/tester/api-tester/critical-reminders.md +41 -0
  391. package/dist/src/agents/tester/api-tester/critical-requirements.md +41 -0
  392. package/dist/src/agents/tester/api-tester/identity.md +47 -0
  393. package/dist/src/agents/tester/api-tester/metadata.yaml +12 -0
  394. package/dist/src/agents/tester/api-tester/output.md +284 -0
  395. package/dist/src/agents/tester/api-tester/playbook.md +275 -0
  396. package/dist/src/agents/tester/cli-tester/critical-reminders.md +36 -0
  397. package/dist/src/agents/tester/cli-tester/critical-requirements.md +36 -0
  398. package/dist/src/agents/tester/cli-tester/identity.md +43 -0
  399. package/dist/src/agents/tester/cli-tester/metadata.yaml +12 -0
  400. package/dist/src/agents/tester/cli-tester/output.md +313 -0
  401. package/dist/src/agents/tester/cli-tester/playbook.md +221 -0
  402. package/dist/src/agents/tester/web-tester/critical-reminders.md +31 -0
  403. package/dist/src/agents/tester/web-tester/critical-requirements.md +28 -0
  404. package/dist/src/agents/tester/web-tester/identity.md +41 -0
  405. package/dist/src/agents/tester/web-tester/metadata.yaml +12 -0
  406. package/dist/src/agents/tester/web-tester/output.md +321 -0
  407. package/dist/src/agents/tester/web-tester/playbook.md +428 -0
  408. package/dist/stores/d227-same-scope-tombstone-duplicate.test.js +118 -0
  409. package/dist/stores/d227-same-scope-tombstone-duplicate.test.js.map +1 -0
  410. package/dist/stores/wizard-store.js +21 -0
  411. package/dist/stores/wizard-store.js.map +1 -0
  412. package/dist/stores/wizard-store.test.js +3053 -0
  413. package/dist/stores/wizard-store.test.js.map +1 -0
  414. package/package.json +130 -12
  415. package/src/agents/_templates/agent.liquid +161 -0
  416. package/src/agents/_templates/methodologies/anti-over-engineering.liquid +121 -0
  417. package/src/agents/_templates/methodologies/context-management.liquid +162 -0
  418. package/src/agents/_templates/methodologies/improvement-protocol.liquid +150 -0
  419. package/src/agents/_templates/methodologies/investigation-requirements.liquid +49 -0
  420. package/src/agents/_templates/methodologies/success-criteria.liquid +111 -0
  421. package/src/agents/_templates/methodologies/write-verification.liquid +43 -0
  422. package/src/agents/developer/ai-developer/critical-reminders.md +54 -0
  423. package/src/agents/developer/ai-developer/critical-requirements.md +59 -0
  424. package/src/agents/developer/ai-developer/identity.md +51 -0
  425. package/src/agents/developer/ai-developer/metadata.yaml +12 -0
  426. package/src/agents/developer/ai-developer/output.md +366 -0
  427. package/src/agents/developer/ai-developer/playbook.md +335 -0
  428. package/src/agents/developer/api-developer/critical-reminders.md +46 -0
  429. package/src/agents/developer/api-developer/critical-requirements.md +44 -0
  430. package/src/agents/developer/api-developer/identity.md +49 -0
  431. package/src/agents/developer/api-developer/metadata.yaml +12 -0
  432. package/src/agents/developer/api-developer/output.md +432 -0
  433. package/src/agents/developer/api-developer/playbook.md +352 -0
  434. package/src/agents/developer/cli-developer/critical-reminders.md +51 -0
  435. package/src/agents/developer/cli-developer/critical-requirements.md +51 -0
  436. package/src/agents/developer/cli-developer/identity.md +51 -0
  437. package/src/agents/developer/cli-developer/metadata.yaml +12 -0
  438. package/src/agents/developer/cli-developer/output.md +285 -0
  439. package/src/agents/developer/cli-developer/playbook.md +386 -0
  440. package/src/agents/developer/web-architecture/critical-reminders.md +48 -0
  441. package/src/agents/developer/web-architecture/critical-requirements.md +65 -0
  442. package/src/agents/developer/web-architecture/identity.md +64 -0
  443. package/src/agents/developer/web-architecture/metadata.yaml +12 -0
  444. package/src/agents/developer/web-architecture/output.md +449 -0
  445. package/src/agents/developer/web-architecture/playbook.md +481 -0
  446. package/src/agents/developer/web-developer/critical-reminders.md +40 -0
  447. package/src/agents/developer/web-developer/critical-requirements.md +39 -0
  448. package/src/agents/developer/web-developer/identity.md +32 -0
  449. package/src/agents/developer/web-developer/metadata.yaml +12 -0
  450. package/src/agents/developer/web-developer/output.md +323 -0
  451. package/src/agents/developer/web-developer/playbook.md +349 -0
  452. package/src/agents/meta/agent-summoner/critical-reminders.md +45 -0
  453. package/src/agents/meta/agent-summoner/critical-requirements.md +52 -0
  454. package/src/agents/meta/agent-summoner/identity.md +34 -0
  455. package/src/agents/meta/agent-summoner/metadata.yaml +12 -0
  456. package/src/agents/meta/agent-summoner/output.md +296 -0
  457. package/src/agents/meta/agent-summoner/playbook.md +1469 -0
  458. package/src/agents/meta/codex-keeper/critical-reminders.md +39 -0
  459. package/src/agents/meta/codex-keeper/critical-requirements.md +29 -0
  460. package/src/agents/meta/codex-keeper/identity.md +45 -0
  461. package/src/agents/meta/codex-keeper/metadata.yaml +12 -0
  462. package/src/agents/meta/codex-keeper/output.md +384 -0
  463. package/src/agents/meta/codex-keeper/playbook.md +1183 -0
  464. package/src/agents/meta/convention-keeper/critical-reminders.md +32 -0
  465. package/src/agents/meta/convention-keeper/critical-requirements.md +32 -0
  466. package/src/agents/meta/convention-keeper/identity.md +33 -0
  467. package/src/agents/meta/convention-keeper/metadata.yaml +12 -0
  468. package/src/agents/meta/convention-keeper/output.md +206 -0
  469. package/src/agents/meta/convention-keeper/playbook.md +180 -0
  470. package/src/agents/meta/skill-summoner/critical-reminders.md +112 -0
  471. package/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
  472. package/src/agents/meta/skill-summoner/identity.md +31 -0
  473. package/src/agents/meta/skill-summoner/metadata.yaml +13 -0
  474. package/src/agents/meta/skill-summoner/output.md +390 -0
  475. package/src/agents/meta/skill-summoner/playbook.md +1457 -0
  476. package/src/agents/pattern/pattern-scout/critical-reminders.md +71 -0
  477. package/src/agents/pattern/pattern-scout/critical-requirements.md +31 -0
  478. package/src/agents/pattern/pattern-scout/identity.md +25 -0
  479. package/src/agents/pattern/pattern-scout/metadata.yaml +10 -0
  480. package/src/agents/pattern/pattern-scout/output.md +290 -0
  481. package/src/agents/pattern/pattern-scout/playbook.md +1806 -0
  482. package/src/agents/pattern/web-pattern-critique/critical-reminders.md +30 -0
  483. package/src/agents/pattern/web-pattern-critique/critical-requirements.md +28 -0
  484. package/src/agents/pattern/web-pattern-critique/identity.md +41 -0
  485. package/src/agents/pattern/web-pattern-critique/metadata.yaml +12 -0
  486. package/src/agents/pattern/web-pattern-critique/output.md +314 -0
  487. package/src/agents/pattern/web-pattern-critique/playbook.md +572 -0
  488. package/src/agents/planning/api-pm/critical-reminders.md +48 -0
  489. package/src/agents/planning/api-pm/critical-requirements.md +41 -0
  490. package/src/agents/planning/api-pm/identity.md +39 -0
  491. package/src/agents/planning/api-pm/metadata.yaml +12 -0
  492. package/src/agents/planning/api-pm/output.md +475 -0
  493. package/src/agents/planning/api-pm/playbook.md +129 -0
  494. package/src/agents/planning/web-pm/critical-reminders.md +36 -0
  495. package/src/agents/planning/web-pm/critical-requirements.md +32 -0
  496. package/src/agents/planning/web-pm/identity.md +26 -0
  497. package/src/agents/planning/web-pm/metadata.yaml +12 -0
  498. package/src/agents/planning/web-pm/output.md +314 -0
  499. package/src/agents/planning/web-pm/playbook.md +318 -0
  500. package/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
  501. package/src/agents/researcher/api-researcher/critical-requirements.md +28 -0
  502. package/src/agents/researcher/api-researcher/identity.md +71 -0
  503. package/src/agents/researcher/api-researcher/metadata.yaml +10 -0
  504. package/src/agents/researcher/api-researcher/output.md +254 -0
  505. package/src/agents/researcher/api-researcher/playbook.md +201 -0
  506. package/src/agents/researcher/web-researcher/critical-reminders.md +39 -0
  507. package/src/agents/researcher/web-researcher/critical-requirements.md +26 -0
  508. package/src/agents/researcher/web-researcher/identity.md +69 -0
  509. package/src/agents/researcher/web-researcher/metadata.yaml +10 -0
  510. package/src/agents/researcher/web-researcher/output.md +241 -0
  511. package/src/agents/researcher/web-researcher/playbook.md +217 -0
  512. package/src/agents/reviewer/ai-reviewer/critical-reminders.md +40 -0
  513. package/src/agents/reviewer/ai-reviewer/critical-requirements.md +37 -0
  514. package/src/agents/reviewer/ai-reviewer/identity.md +51 -0
  515. package/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  516. package/src/agents/reviewer/ai-reviewer/output.md +395 -0
  517. package/src/agents/reviewer/ai-reviewer/playbook.md +90 -0
  518. package/src/agents/reviewer/api-reviewer/critical-reminders.md +31 -0
  519. package/src/agents/reviewer/api-reviewer/critical-requirements.md +27 -0
  520. package/src/agents/reviewer/api-reviewer/identity.md +51 -0
  521. package/src/agents/reviewer/api-reviewer/metadata.yaml +12 -0
  522. package/src/agents/reviewer/api-reviewer/output.md +343 -0
  523. package/src/agents/reviewer/api-reviewer/playbook.md +288 -0
  524. package/src/agents/reviewer/cli-reviewer/critical-reminders.md +33 -0
  525. package/src/agents/reviewer/cli-reviewer/critical-requirements.md +30 -0
  526. package/src/agents/reviewer/cli-reviewer/identity.md +44 -0
  527. package/src/agents/reviewer/cli-reviewer/metadata.yaml +12 -0
  528. package/src/agents/reviewer/cli-reviewer/output.md +414 -0
  529. package/src/agents/reviewer/cli-reviewer/playbook.md +218 -0
  530. package/src/agents/reviewer/infra-reviewer/critical-reminders.md +38 -0
  531. package/src/agents/reviewer/infra-reviewer/critical-requirements.md +38 -0
  532. package/src/agents/reviewer/infra-reviewer/identity.md +53 -0
  533. package/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  534. package/src/agents/reviewer/infra-reviewer/output.md +364 -0
  535. package/src/agents/reviewer/infra-reviewer/playbook.md +161 -0
  536. package/src/agents/reviewer/web-reviewer/critical-reminders.md +31 -0
  537. package/src/agents/reviewer/web-reviewer/critical-requirements.md +26 -0
  538. package/src/agents/reviewer/web-reviewer/identity.md +40 -0
  539. package/src/agents/reviewer/web-reviewer/metadata.yaml +12 -0
  540. package/src/agents/reviewer/web-reviewer/output.md +333 -0
  541. package/src/agents/reviewer/web-reviewer/playbook.md +156 -0
  542. package/src/agents/tester/api-tester/critical-reminders.md +41 -0
  543. package/src/agents/tester/api-tester/critical-requirements.md +41 -0
  544. package/src/agents/tester/api-tester/identity.md +47 -0
  545. package/src/agents/tester/api-tester/metadata.yaml +12 -0
  546. package/src/agents/tester/api-tester/output.md +284 -0
  547. package/src/agents/tester/api-tester/playbook.md +275 -0
  548. package/src/agents/tester/cli-tester/critical-reminders.md +36 -0
  549. package/src/agents/tester/cli-tester/critical-requirements.md +36 -0
  550. package/src/agents/tester/cli-tester/identity.md +43 -0
  551. package/src/agents/tester/cli-tester/metadata.yaml +12 -0
  552. package/src/agents/tester/cli-tester/output.md +313 -0
  553. package/src/agents/tester/cli-tester/playbook.md +221 -0
  554. package/src/agents/tester/web-tester/critical-reminders.md +31 -0
  555. package/src/agents/tester/web-tester/critical-requirements.md +28 -0
  556. package/src/agents/tester/web-tester/identity.md +41 -0
  557. package/src/agents/tester/web-tester/metadata.yaml +12 -0
  558. package/src/agents/tester/web-tester/output.md +321 -0
  559. package/src/agents/tester/web-tester/playbook.md +428 -0
  560. package/src/schemas/agent-frontmatter.schema.json +88 -0
  561. package/src/schemas/agent.schema.json +103 -0
  562. package/src/schemas/custom-metadata.schema.json +74 -0
  563. package/src/schemas/hooks.schema.json +47 -0
  564. package/src/schemas/marketplace.schema.json +119 -0
  565. package/src/schemas/metadata.schema.json +387 -0
  566. package/src/schemas/plugin.schema.json +127 -0
  567. package/src/schemas/project-config.schema.json +189 -0
  568. package/src/schemas/project-source-config.schema.json +96 -0
  569. package/src/schemas/skill-frontmatter.schema.json +42 -0
  570. package/src/schemas/stack.schema.json +191 -0
  571. package/src/schemas/stacks.schema.json +107 -0
  572. package/bin/run.js +0 -3
@@ -0,0 +1,430 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ useModalState
4
+ } from "./chunk-NIKUMXE7.js";
5
+ import {
6
+ ScrollAffordance
7
+ } from "./chunk-KOPEM3Q7.js";
8
+ import {
9
+ SearchModal
10
+ } from "./chunk-2RSNKBXC.js";
11
+ import {
12
+ useFocusedListItem
13
+ } from "./chunk-LYYXX2W5.js";
14
+ import {
15
+ useSectionScroll
16
+ } from "./chunk-DAG2ULNF.js";
17
+ import {
18
+ KEY_SPACE
19
+ } from "./chunk-VG2TVBFN.js";
20
+ import {
21
+ getSkillById,
22
+ matrix
23
+ } from "./chunk-DG2NGZ7S.js";
24
+ import {
25
+ CLI_COLORS,
26
+ SOURCE_DISPLAY_NAMES,
27
+ SOURCE_HEADER_NAMES,
28
+ UI_SYMBOLS
29
+ } from "./chunk-O5ASLZ2K.js";
30
+ import {
31
+ init_esm_shims
32
+ } from "./chunk-P56WJ5FA.js";
33
+
34
+ // src/cli/components/wizard/source-grid.tsx
35
+ init_esm_shims();
36
+ import { useCallback as useCallback2, useMemo } from "react";
37
+ import { Box, Text, useInput } from "ink";
38
+
39
+ // src/cli/components/hooks/use-source-grid-search-modal.ts
40
+ init_esm_shims();
41
+ import { useCallback, useState } from "react";
42
+ function useSourceGridSearchModal({
43
+ rows,
44
+ onSearch,
45
+ onBind,
46
+ onSearchStateChange
47
+ }) {
48
+ const searchModal = useModalState();
49
+ const [searchResults, setSearchResults] = useState([]);
50
+ const [searchAlias, setSearchAlias] = useState("");
51
+ const resetSearch = useCallback(() => {
52
+ searchModal.close();
53
+ setSearchResults([]);
54
+ setSearchAlias("");
55
+ onSearchStateChange?.(false);
56
+ }, [onSearchStateChange, searchModal]);
57
+ const handleSearchTrigger = useCallback(
58
+ async (rowIndex) => {
59
+ const row = rows[rowIndex];
60
+ if (!row || !onSearch) return;
61
+ const alias = matrix.slugMap.idToSlug[row.skillId];
62
+ if (!alias) return;
63
+ setSearchAlias(alias);
64
+ searchModal.open(rowIndex);
65
+ onSearchStateChange?.(true);
66
+ const results = await onSearch(alias);
67
+ setSearchResults(results);
68
+ },
69
+ [rows, onSearch, onSearchStateChange, searchModal]
70
+ );
71
+ const handleBind = useCallback(
72
+ (candidate) => {
73
+ onBind?.(candidate);
74
+ resetSearch();
75
+ },
76
+ [onBind, resetSearch]
77
+ );
78
+ const handleCloseSearch = useCallback(() => {
79
+ resetSearch();
80
+ }, [resetSearch]);
81
+ return {
82
+ searchModal: { isOpen: searchModal.isOpen },
83
+ searchResults,
84
+ searchAlias,
85
+ handleSearchTrigger,
86
+ handleBind,
87
+ handleCloseSearch
88
+ };
89
+ }
90
+
91
+ // src/cli/components/wizard/source-grid.tsx
92
+ import { jsx, jsxs } from "react/jsx-runtime";
93
+ var SEARCH_PILL_LABEL = "\u2315 Search";
94
+ var SKILL_NAME_WIDTH = 26;
95
+ var SOURCE_COL_WIDTH = 18;
96
+ var SCOPE_COL_WIDTH = 11;
97
+ var SCOPE_ROW_HEADERS = {
98
+ global: "Global",
99
+ project: "Project"
100
+ };
101
+ var ROW_MARKER_BLANK = " ";
102
+ var SOURCE_GRID_MIN_VIEWPORT_ROWS = 1;
103
+ var SOURCE_GRID_HEADER_MIN_HEIGHT = 4;
104
+ function isRowInert(row) {
105
+ return !!row.readOnly || !!row.disabled;
106
+ }
107
+ function rowStatusMarker(row) {
108
+ if (row.readOnly) return `${UI_SYMBOLS.LOCK} `;
109
+ if (row.disabled) return `${UI_SYMBOLS.REMOVED} `;
110
+ if (row.added) return `${UI_SYMBOLS.ADDED} `;
111
+ return ROW_MARKER_BLANK;
112
+ }
113
+ function rowDiffColor(row) {
114
+ if (row.disabled) return CLI_COLORS.ERROR;
115
+ if (row.added) return CLI_COLORS.SUCCESS;
116
+ return void 0;
117
+ }
118
+ function rowLabelColor(row) {
119
+ return rowDiffColor(row) ?? CLI_COLORS.NEUTRAL;
120
+ }
121
+ function focusedRowLabelColor(row) {
122
+ return rowDiffColor(row) ?? CLI_COLORS.WHITE;
123
+ }
124
+ var SearchPill = ({ isFocused }) => {
125
+ return /* @__PURE__ */ jsx(Box, { marginRight: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: !isFocused, bold: isFocused, children: SEARCH_PILL_LABEL }) });
126
+ };
127
+ function formatSourceLabel(option) {
128
+ return SOURCE_DISPLAY_NAMES[option.id] ?? option.id;
129
+ }
130
+ var SourceTag = ({ option, isFocused, readOnly, disabled }) => {
131
+ if (readOnly || disabled) {
132
+ return /* @__PURE__ */ jsx(Box, { width: SOURCE_COL_WIDTH, children: /* @__PURE__ */ jsxs(
133
+ Text,
134
+ {
135
+ color: disabled ? CLI_COLORS.ERROR : void 0,
136
+ bold: option.selected,
137
+ dimColor: !disabled && !option.selected,
138
+ children: [
139
+ `${UI_SYMBOLS.CHEVRON_SPACER} `,
140
+ formatSourceLabel(option)
141
+ ]
142
+ }
143
+ ) });
144
+ }
145
+ const textColor = option.selected ? CLI_COLORS.PRIMARY : CLI_COLORS.WHITE;
146
+ const isBold = isFocused || option.selected;
147
+ const prefix = isFocused ? `${UI_SYMBOLS.CHEVRON} ` : `${UI_SYMBOLS.CHEVRON_SPACER} `;
148
+ return /* @__PURE__ */ jsx(Box, { width: SOURCE_COL_WIDTH, children: /* @__PURE__ */ jsxs(Text, { color: textColor, bold: isBold, dimColor: !option.selected && !isFocused, children: [
149
+ prefix,
150
+ formatSourceLabel(option)
151
+ ] }) });
152
+ };
153
+ var SourceSection = ({
154
+ row,
155
+ isFocused,
156
+ focusedOptionIndex,
157
+ showSearchPill
158
+ }) => {
159
+ const searchPillIndex = row.options.length;
160
+ const isInert = isRowInert(row);
161
+ const effectiveFocused = isInert ? false : isFocused;
162
+ const effectiveShowSearchPill = isInert ? false : showSearchPill;
163
+ const statusMarker = rowStatusMarker(row);
164
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
165
+ /* @__PURE__ */ jsx(Box, { width: SKILL_NAME_WIDTH, children: effectiveFocused ? (
166
+ // The marker sits INSIDE the highlight, and the marker's own separating space is the only
167
+ // one before the name — so the band is the same width on every focused row and the name
168
+ // does not shift a column when focus arrives.
169
+ /* @__PURE__ */ jsxs(Text, { color: focusedRowLabelColor(row), backgroundColor: CLI_COLORS.LABEL_BG, children: [
170
+ statusMarker,
171
+ `${getSkillById(row.skillId).displayName} `
172
+ ] })
173
+ ) : /* @__PURE__ */ jsxs(Text, { color: rowLabelColor(row), dimColor: !!row.readOnly, children: [
174
+ statusMarker,
175
+ getSkillById(row.skillId).displayName
176
+ ] }) }),
177
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [
178
+ row.options.map((option, index) => /* @__PURE__ */ jsx(
179
+ SourceTag,
180
+ {
181
+ option,
182
+ isFocused: effectiveFocused && index === focusedOptionIndex,
183
+ readOnly: row.readOnly,
184
+ disabled: row.disabled
185
+ },
186
+ option.id
187
+ )),
188
+ effectiveShowSearchPill && /* @__PURE__ */ jsx(SearchPill, { isFocused: effectiveFocused && focusedOptionIndex === searchPillIndex })
189
+ ] })
190
+ ] });
191
+ };
192
+ var getNavigableCount = (row, showSearchPill) => {
193
+ return row.options.length + (showSearchPill ? 1 : 0);
194
+ };
195
+ var ScopeRowHeader = ({
196
+ scope,
197
+ isGroupStart
198
+ }) => /* @__PURE__ */ jsx(Box, { width: SCOPE_COL_WIDTH, children: isGroupStart && /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, bold: true, children: SCOPE_ROW_HEADERS[scope] }) });
199
+ function firstFocusableRowIndex(rows, startRow) {
200
+ const cyclicRowOrder = rows.map((_, offset) => (startRow + offset) % rows.length);
201
+ return cyclicRowOrder.find((row) => {
202
+ const candidate = rows[row];
203
+ return candidate && !isRowInert(candidate);
204
+ }) ?? startRow;
205
+ }
206
+ function lastFocusableRowIndex(rows) {
207
+ for (let i = rows.length - 1; i >= 0; i--) {
208
+ const candidate = rows[i];
209
+ if (candidate && !isRowInert(candidate)) return i;
210
+ }
211
+ return -1;
212
+ }
213
+ function groupRowsByScope(rows) {
214
+ const indexed = rows.map((row, i) => ({ row, originalIndex: i }));
215
+ const globalRows = indexed.filter(({ row }) => row.scope === "global");
216
+ const projectRows = indexed.filter(({ row }) => row.scope !== "global");
217
+ if (globalRows.length === 0 || projectRows.length === 0) return [];
218
+ return [
219
+ { scope: "global", rows: globalRows },
220
+ { scope: "project", rows: projectRows }
221
+ ];
222
+ }
223
+ var SourceGrid = ({
224
+ rows,
225
+ availableHeight = 0,
226
+ onSelect,
227
+ onSearch,
228
+ onBind,
229
+ onSearchStateChange,
230
+ defaultFocusedRow = 0,
231
+ defaultFocusedCol = 0,
232
+ onFocusChange
233
+ }) => {
234
+ const {
235
+ searchModal,
236
+ searchResults,
237
+ searchAlias,
238
+ handleSearchTrigger,
239
+ handleBind,
240
+ handleCloseSearch
241
+ } = useSourceGridSearchModal({ rows, onSearch, onBind, onSearchStateChange });
242
+ const showSearchPill = !!onSearch;
243
+ const getColCount = useCallback2(
244
+ (row) => {
245
+ const rowData = rows[row];
246
+ return rowData ? getNavigableCount(rowData, showSearchPill) : 0;
247
+ },
248
+ [rows, showSearchPill]
249
+ );
250
+ const skipRow = useCallback2(
251
+ (row) => {
252
+ const candidate = rows[row];
253
+ return !!candidate && isRowInert(candidate);
254
+ },
255
+ [rows]
256
+ );
257
+ const effectiveDefaultRow = firstFocusableRowIndex(rows, defaultFocusedRow);
258
+ const { focusedRow, focusedCol, moveFocus } = useFocusedListItem(rows.length, getColCount, {
259
+ wrap: true,
260
+ onChange: onFocusChange,
261
+ initialRow: effectiveDefaultRow,
262
+ initialCol: defaultFocusedCol,
263
+ skipRow
264
+ });
265
+ const {
266
+ setSectionRef,
267
+ setViewportRef,
268
+ setContentRef,
269
+ scrollEnabled,
270
+ scrollTopPx,
271
+ hiddenAbove,
272
+ hiddenBelow,
273
+ scrollBy
274
+ } = useSectionScroll({
275
+ sectionCount: rows.length,
276
+ focusedIndex: focusedRow,
277
+ availableHeight,
278
+ minViewportRows: SOURCE_GRID_MIN_VIEWPORT_ROWS
279
+ });
280
+ const lastFocusableRow = useMemo(() => lastFocusableRowIndex(rows), [rows]);
281
+ useInput(
282
+ useCallback2(
283
+ (input, key) => {
284
+ if (input === KEY_SPACE) {
285
+ const currentRow = rows[focusedRow];
286
+ if (!currentRow || isRowInert(currentRow)) return;
287
+ if (showSearchPill && focusedCol === currentRow.options.length) {
288
+ void handleSearchTrigger(focusedRow);
289
+ return;
290
+ }
291
+ if (focusedCol < currentRow.options.length) {
292
+ const currentOption = currentRow.options[focusedCol];
293
+ if (currentOption) {
294
+ onSelect(currentRow.skillId, currentOption.id);
295
+ }
296
+ }
297
+ return;
298
+ }
299
+ const noFocusableRow = lastFocusableRow === -1;
300
+ const atLastFocusableRow = focusedRow === lastFocusableRow;
301
+ if (key.leftArrow) {
302
+ moveFocus("left");
303
+ } else if (key.rightArrow) {
304
+ moveFocus("right");
305
+ } else if (key.upArrow) {
306
+ if (scrollEnabled && noFocusableRow && hiddenAbove > 0) {
307
+ scrollBy(-1);
308
+ } else {
309
+ moveFocus("up");
310
+ }
311
+ } else if (key.downArrow) {
312
+ if (scrollEnabled && (noFocusableRow || atLastFocusableRow) && hiddenBelow > 0) {
313
+ scrollBy(1);
314
+ } else {
315
+ moveFocus("down");
316
+ }
317
+ }
318
+ },
319
+ [
320
+ rows,
321
+ focusedRow,
322
+ focusedCol,
323
+ onSelect,
324
+ showSearchPill,
325
+ handleSearchTrigger,
326
+ moveFocus,
327
+ scrollEnabled,
328
+ lastFocusableRow,
329
+ hiddenAbove,
330
+ hiddenBelow,
331
+ scrollBy
332
+ ]
333
+ ),
334
+ { isActive: !searchModal.isOpen }
335
+ );
336
+ if (rows.length === 0) {
337
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No skills to display." }) });
338
+ }
339
+ const noShrink = scrollEnabled ? { flexShrink: 0 } : {};
340
+ const scopeGroups = groupRowsByScope(rows);
341
+ const headerSources = rows[0]?.options ?? [];
342
+ const headerMarginBottom = scrollEnabled || scopeGroups.length > 0 ? 0 : 1;
343
+ const showPinnedHeader = !scrollEnabled || availableHeight >= SOURCE_GRID_HEADER_MIN_HEIGHT;
344
+ const headerElement = /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginBottom: headerMarginBottom, ...noShrink, children: [
345
+ scopeGroups.length > 0 && /* @__PURE__ */ jsx(Box, { width: SCOPE_COL_WIDTH }),
346
+ /* @__PURE__ */ jsx(Box, { width: SKILL_NAME_WIDTH }),
347
+ headerSources.map((option) => /* @__PURE__ */ jsx(Box, { width: SOURCE_COL_WIDTH, children: /* @__PURE__ */ jsx(
348
+ Text,
349
+ {
350
+ color: CLI_COLORS.WARNING,
351
+ bold: true,
352
+ children: `${UI_SYMBOLS.CHEVRON_SPACER} ${SOURCE_HEADER_NAMES[option.id] ?? option.id}`
353
+ }
354
+ ) }, option.id))
355
+ ] });
356
+ const sectionElements = scopeGroups.length > 0 ? scopeGroups.map((group) => /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, ...noShrink, children: group.rows.map(({ row, originalIndex }, rowIndexInGroup) => /* @__PURE__ */ jsxs(
357
+ Box,
358
+ {
359
+ flexDirection: "row",
360
+ ref: (el) => setSectionRef(originalIndex, el),
361
+ ...noShrink,
362
+ children: [
363
+ /* @__PURE__ */ jsx(ScopeRowHeader, { scope: group.scope, isGroupStart: rowIndexInGroup === 0 }),
364
+ /* @__PURE__ */ jsx(
365
+ SourceSection,
366
+ {
367
+ row,
368
+ isFocused: originalIndex === focusedRow,
369
+ focusedOptionIndex: focusedCol,
370
+ showSearchPill
371
+ }
372
+ )
373
+ ]
374
+ },
375
+ `${row.skillId}-${row.scope ?? "default"}`
376
+ )) }, group.scope)) : rows.map((row, rowIndex) => /* @__PURE__ */ jsx(
377
+ Box,
378
+ {
379
+ ref: (el) => setSectionRef(rowIndex, el),
380
+ ...noShrink,
381
+ children: /* @__PURE__ */ jsx(
382
+ SourceSection,
383
+ {
384
+ row,
385
+ isFocused: rowIndex === focusedRow,
386
+ focusedOptionIndex: focusedCol,
387
+ showSearchPill
388
+ }
389
+ )
390
+ },
391
+ `${row.skillId}-${row.scope ?? "default"}`
392
+ ));
393
+ const searchModalElement = searchModal.isOpen && /* @__PURE__ */ jsx(
394
+ SearchModal,
395
+ {
396
+ results: searchResults,
397
+ alias: searchAlias,
398
+ onBind: handleBind,
399
+ onClose: handleCloseSearch
400
+ }
401
+ );
402
+ return /* @__PURE__ */ jsxs(
403
+ Box,
404
+ {
405
+ flexDirection: "column",
406
+ ...scrollEnabled ? { height: availableHeight, overflow: "hidden" } : { flexGrow: 1 },
407
+ children: [
408
+ showPinnedHeader && headerElement,
409
+ /* @__PURE__ */ jsx(Box, { ref: setViewportRef, flexDirection: "column", overflow: "hidden", flexGrow: 1, children: /* @__PURE__ */ jsx(
410
+ Box,
411
+ {
412
+ ref: setContentRef,
413
+ flexDirection: "column",
414
+ marginTop: scrollTopPx > 0 ? -scrollTopPx : 0,
415
+ ...noShrink,
416
+ children: sectionElements
417
+ }
418
+ ) }),
419
+ /* @__PURE__ */ jsx(ScrollAffordance, { hiddenAbove, hiddenBelow }),
420
+ searchModalElement
421
+ ]
422
+ }
423
+ );
424
+ };
425
+
426
+ export {
427
+ isRowInert,
428
+ SourceGrid
429
+ };
430
+ //# sourceMappingURL=chunk-WK4J2CHH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/source-grid.tsx","../src/cli/components/hooks/use-source-grid-search-modal.ts"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { Box, Text, useInput, type Key } from \"ink\";\nimport type { BoundSkillCandidate, SkillAlias, SkillId, SkillScope } from \"../../types/index.js\";\nimport { CLI_COLORS, SOURCE_DISPLAY_NAMES, SOURCE_HEADER_NAMES, UI_SYMBOLS } from \"../../consts.js\";\nimport { getSkillById } from \"../../lib/matrix/matrix-provider.js\";\nimport { useFocusedListItem } from \"../hooks/use-focused-list-item.js\";\nimport { useSectionScroll } from \"../hooks/use-section-scroll.js\";\nimport { useSourceGridSearchModal } from \"../hooks/use-source-grid-search-modal.js\";\nimport { KEY_SPACE } from \"./hotkeys.js\";\nimport { ScrollAffordance } from \"./scroll-affordance.js\";\nimport { SearchModal } from \"./search-modal.js\";\n\nconst SEARCH_PILL_LABEL = \"\\u2315 Search\";\n\n/**\n * Skill-name cell: the 24 columns the name itself gets, plus the fixed 2-column marker cell that\n * shares the box (see `rowStatusMarker`). Widening by exactly the marker width keeps every name\n * that fitted before the marker was reserved fitting still.\n */\nconst SKILL_NAME_WIDTH = 26;\nconst SOURCE_COL_WIDTH = 18;\n\n/**\n * Scope gutter: the column of `Global` / `Project` row headers down the left of a scope-grouped\n * grid. Present only in the grouped layout — a single-scope grid has nothing to head, and renders\n * flat with no gutter at all. The header row reserves the width but prints no caption in it: the\n * labels below already name the column, so a caption over them would only repeat them.\n */\nconst SCOPE_COL_WIDTH = 11;\n\n/** Row-header label each scope block is headed by. */\nconst SCOPE_ROW_HEADERS: Record<SkillScope, string> = {\n global: \"Global\",\n project: \"Project\",\n};\n\n/** Blank marker cell — the same two columns a `${glyph} ` marker costs, so names never shift. */\nconst ROW_MARKER_BLANK = \" \";\n\n/**\n * Sources always clips-and-signals rather than bleeding, even at the very short viewports the wizard\n * still renders at (the Sources step is squeezed by the tab bar, dropdown card and footer): a single\n * clipped row plus the overflow affordance beats a bled grid. Distinct from the grid views that fall\n * back to a flex layout below SCROLL_VIEWPORT.MIN_VIEWPORT_ROWS.\n */\nconst SOURCE_GRID_MIN_VIEWPORT_ROWS = 1;\n\n/**\n * The pinned column header and the overflow affordance each cost one row of the clipped viewport.\n * Below this height there is no room for the header AND a readable pair of content rows, so the\n * column labels yield to content — a header row = column labels (1) + content (2) + affordance (1).\n */\nconst SOURCE_GRID_HEADER_MIN_HEIGHT = 4;\n\nexport type SourceOption = {\n id: string;\n selected: boolean;\n installed: boolean;\n};\n\nexport type SourceRow = {\n skillId: SkillId;\n options: SourceOption[];\n scope?: SkillScope;\n readOnly?: boolean;\n /**\n * Saved skill deselected this session — still shown so the user can see what saving removes,\n * but inert. Distinct from `readOnly`, which means \"locked because it is installed globally\".\n */\n disabled?: boolean;\n /**\n * Skill selected this session but absent from the hydration snapshot (D-258). Renders inline in\n * its normal position with the info panel's added marker (`+`) in green, and stays a normal\n * selectable/editable row — unlike `disabled`/`readOnly`, an added row is NOT inert.\n */\n added?: boolean;\n};\n\n/** Rows the user cannot act on: globally locked (`readOnly`) or pending removal (`disabled`). */\nexport function isRowInert(row: SourceRow): boolean {\n return !!row.readOnly || !!row.disabled;\n}\n\n/**\n * Status marker before the skill name. Lock = \"installed globally, not yours to change here\".\n * The removal marker + red colour and the added marker + green colour mirror the info panel's\n * removed/added-diff treatment (DIFF_PREFIX/DIFF_COLOR in skill-agent-summary.tsx) so a\n * pending-removal or added row reads the same on both surfaces. The marker (not the colour) is\n * what carries the meaning in no-color terminals.\n *\n * ALWAYS two columns wide — glyph plus one separating space, or `ROW_MARKER_BLANK` on a row with no\n * status — so every skill name starts in the same column whether or not its row is marked. Same\n * contract as DIFF_PREFIX, which gives even `unchanged` a 2-char prefix. `UI_SYMBOLS.LOCK` is\n * double-width and still renders a locked row one column wider; known and accepted.\n */\nfunction rowStatusMarker(row: SourceRow): string {\n if (row.readOnly) return `${UI_SYMBOLS.LOCK} `;\n if (row.disabled) return `${UI_SYMBOLS.REMOVED} `;\n if (row.added) return `${UI_SYMBOLS.ADDED} `;\n return ROW_MARKER_BLANK;\n}\n\n/**\n * Diff colour for a row's skill name, matching the info panel's palette (DIFF_COLOR in\n * skill-agent-summary.tsx): red = pending removal, green = added. `undefined` means the row carries\n * no diff status, so each caller supplies its own default.\n */\nfunction rowDiffColor(row: SourceRow): string | undefined {\n if (row.disabled) return CLI_COLORS.ERROR;\n if (row.added) return CLI_COLORS.SUCCESS;\n return undefined;\n}\n\n/** Skill-name colour for an unfocused row: its diff colour, or the neutral default. */\nfunction rowLabelColor(row: SourceRow): string {\n return rowDiffColor(row) ?? CLI_COLORS.NEUTRAL;\n}\n\n/**\n * Skill-name colour for the FOCUSED row, which renders on the dark LABEL_BG highlight. A diff row\n * keeps its diff colour — focus is not a reason to lose the added/removed signal. An ordinary row\n * deliberately stays plain WHITE rather than falling through to `rowLabelColor`: NEUTRAL grey on\n * LABEL_BG is the low-contrast pairing, so reusing it here would dim every ordinary focused row to\n * fix rows that have no diff to show in the first place.\n */\nfunction focusedRowLabelColor(row: SourceRow): string {\n return rowDiffColor(row) ?? CLI_COLORS.WHITE;\n}\n\nexport type SourceGridProps = {\n rows: SourceRow[];\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n onSelect: (skillId: SkillId, sourceId: string) => void;\n onSearch?: (alias: SkillAlias) => Promise<BoundSkillCandidate[]>;\n onBind?: (candidate: BoundSkillCandidate) => void;\n onSearchStateChange?: (active: boolean) => void;\n /** Optional initial focus row (default: 0). Use with React `key` to reset. */\n defaultFocusedRow?: number;\n /** Optional initial focus col (default: 0). Use with React `key` to reset. */\n defaultFocusedCol?: number;\n /** Optional callback fired whenever the focused position changes */\n onFocusChange?: (row: number, col: number) => void;\n};\n\ntype SearchPillProps = {\n isFocused: boolean;\n};\n\nconst SearchPill: React.FC<SearchPillProps> = ({ isFocused }) => {\n return (\n <Box marginRight={1}>\n <Text dimColor={!isFocused} bold={isFocused}>\n {SEARCH_PILL_LABEL}\n </Text>\n </Box>\n );\n};\n\ntype SourceSectionProps = {\n row: SourceRow;\n isFocused: boolean;\n focusedOptionIndex: number;\n showSearchPill: boolean;\n};\n\nfunction formatSourceLabel(option: SourceOption): string {\n return SOURCE_DISPLAY_NAMES[option.id] ?? option.id;\n}\n\nconst SourceTag: React.FC<{\n option: SourceOption;\n isFocused: boolean;\n readOnly?: boolean;\n disabled?: boolean;\n}> = ({ option, isFocused, readOnly, disabled }) => {\n if (readOnly || disabled) {\n // Inert rows carry selection in the same vocabulary editable ones do — weight, plus brightness\n // on the locked row whose cells are otherwise all dimmed. Never a glyph: a check appears nowhere\n // else in the grid, and on a pending-removal row it would tick the source the row is losing. The\n // prefix slot stays a blank spacer so the source labels line up with every other row's.\n return (\n <Box width={SOURCE_COL_WIDTH}>\n <Text\n color={disabled ? CLI_COLORS.ERROR : undefined}\n bold={option.selected}\n dimColor={!disabled && !option.selected}\n >\n {`${UI_SYMBOLS.CHEVRON_SPACER} `}\n {formatSourceLabel(option)}\n </Text>\n </Box>\n );\n }\n\n const textColor = option.selected ? CLI_COLORS.PRIMARY : CLI_COLORS.WHITE;\n const isBold = isFocused || option.selected;\n const prefix = isFocused ? `${UI_SYMBOLS.CHEVRON} ` : `${UI_SYMBOLS.CHEVRON_SPACER} `;\n\n return (\n <Box width={SOURCE_COL_WIDTH}>\n <Text color={textColor} bold={isBold} dimColor={!option.selected && !isFocused}>\n {prefix}\n {formatSourceLabel(option)}\n </Text>\n </Box>\n );\n};\n\nconst SourceSection: React.FC<SourceSectionProps> = ({\n row,\n isFocused,\n focusedOptionIndex,\n showSearchPill,\n}) => {\n const searchPillIndex = row.options.length;\n const isInert = isRowInert(row);\n const effectiveFocused = isInert ? false : isFocused;\n const effectiveShowSearchPill = isInert ? false : showSearchPill;\n // Unlike removal, an added row stays a normal editable row — only its marker/colour differ.\n const statusMarker = rowStatusMarker(row);\n\n return (\n <Box flexDirection=\"row\">\n <Box width={SKILL_NAME_WIDTH}>\n {effectiveFocused ? (\n // The marker sits INSIDE the highlight, and the marker's own separating space is the only\n // one before the name — so the band is the same width on every focused row and the name\n // does not shift a column when focus arrives.\n <Text color={focusedRowLabelColor(row)} backgroundColor={CLI_COLORS.LABEL_BG}>\n {statusMarker}\n {`${getSkillById(row.skillId).displayName} `}\n </Text>\n ) : (\n <Text color={rowLabelColor(row)} dimColor={!!row.readOnly}>\n {statusMarker}\n {getSkillById(row.skillId).displayName}\n </Text>\n )}\n </Box>\n\n <Box flexDirection=\"row\" flexWrap=\"wrap\">\n {row.options.map((option, index) => (\n <SourceTag\n key={option.id}\n option={option}\n isFocused={effectiveFocused && index === focusedOptionIndex}\n readOnly={row.readOnly}\n disabled={row.disabled}\n />\n ))}\n {effectiveShowSearchPill && (\n <SearchPill isFocused={effectiveFocused && focusedOptionIndex === searchPillIndex} />\n )}\n </Box>\n </Box>\n );\n};\n\n/** Total navigable columns for a row (options + search pill if applicable) */\nconst getNavigableCount = (row: SourceRow, showSearchPill: boolean): number => {\n return row.options.length + (showSearchPill ? 1 : 0);\n};\n\ntype ScopeGroup = {\n scope: SkillScope;\n rows: { row: SourceRow; originalIndex: number }[];\n};\n\n/**\n * One row's cell in the scope gutter. Only the first row of a block prints the block's label; every\n * other row reserves the same width empty, which is what indents the rest of the block under its\n * header.\n */\nconst ScopeRowHeader: React.FC<{ scope: SkillScope; isGroupStart: boolean }> = ({\n scope,\n isGroupStart,\n}) => (\n <Box width={SCOPE_COL_WIDTH}>\n {isGroupStart && (\n <Text color={CLI_COLORS.WARNING} bold>\n {SCOPE_ROW_HEADERS[scope]}\n </Text>\n )}\n </Box>\n);\n\n/** First focusable row index at or cyclically after `startRow`; `startRow` when every row is inert. */\nfunction firstFocusableRowIndex(rows: SourceRow[], startRow: number): number {\n const cyclicRowOrder = rows.map((_, offset) => (startRow + offset) % rows.length);\n return (\n cyclicRowOrder.find((row) => {\n const candidate = rows[row];\n return candidate && !isRowInert(candidate);\n }) ?? startRow\n );\n}\n\n/** Index of the last focusable (non-inert) row, or -1 when every row is inert. */\nfunction lastFocusableRowIndex(rows: SourceRow[]): number {\n for (let i = rows.length - 1; i >= 0; i--) {\n const candidate = rows[i];\n if (candidate && !isRowInert(candidate)) return i;\n }\n return -1;\n}\n\n/**\n * Groups rows by scope so the two blocks render separated by a blank line, each headed by its scope\n * in the gutter. Returns an empty array when all rows share the same scope: one block needs no\n * header to tell it from another, so that grid renders flat with no gutter at all.\n */\nfunction groupRowsByScope(rows: SourceRow[]): ScopeGroup[] {\n const indexed = rows.map((row, i) => ({ row, originalIndex: i }));\n const globalRows = indexed.filter(({ row }) => row.scope === \"global\");\n const projectRows = indexed.filter(({ row }) => row.scope !== \"global\");\n\n if (globalRows.length === 0 || projectRows.length === 0) return [];\n\n return [\n { scope: \"global\", rows: globalRows },\n { scope: \"project\", rows: projectRows },\n ];\n}\n\nexport const SourceGrid: React.FC<SourceGridProps> = ({\n rows,\n availableHeight = 0,\n onSelect,\n onSearch,\n onBind,\n onSearchStateChange,\n defaultFocusedRow = 0,\n defaultFocusedCol = 0,\n onFocusChange,\n}) => {\n const {\n searchModal,\n searchResults,\n searchAlias,\n handleSearchTrigger,\n handleBind,\n handleCloseSearch,\n } = useSourceGridSearchModal({ rows, onSearch, onBind, onSearchStateChange });\n\n const showSearchPill = !!onSearch;\n\n const getColCount = useCallback(\n (row: number): number => {\n const rowData = rows[row];\n return rowData ? getNavigableCount(rowData, showSearchPill) : 0;\n },\n [rows, showSearchPill],\n );\n\n const skipRow = useCallback(\n (row: number): boolean => {\n const candidate = rows[row];\n return !!candidate && isRowInert(candidate);\n },\n [rows],\n );\n\n const effectiveDefaultRow = firstFocusableRowIndex(rows, defaultFocusedRow);\n\n const { focusedRow, focusedCol, moveFocus } = useFocusedListItem(rows.length, getColCount, {\n wrap: true,\n onChange: onFocusChange,\n initialRow: effectiveDefaultRow,\n initialCol: defaultFocusedCol,\n skipRow,\n });\n\n const {\n setSectionRef,\n setViewportRef,\n setContentRef,\n scrollEnabled,\n scrollTopPx,\n hiddenAbove,\n hiddenBelow,\n scrollBy,\n } = useSectionScroll({\n sectionCount: rows.length,\n focusedIndex: focusedRow,\n availableHeight,\n minViewportRows: SOURCE_GRID_MIN_VIEWPORT_ROWS,\n });\n\n const lastFocusableRow = useMemo(() => lastFocusableRowIndex(rows), [rows]);\n\n useInput(\n useCallback(\n (input: string, key: Key) => {\n if (input === KEY_SPACE) {\n const currentRow = rows[focusedRow];\n if (!currentRow || isRowInert(currentRow)) return;\n if (showSearchPill && focusedCol === currentRow.options.length) {\n void handleSearchTrigger(focusedRow);\n return;\n }\n if (focusedCol < currentRow.options.length) {\n const currentOption = currentRow.options[focusedCol];\n if (currentOption) {\n onSelect(currentRow.skillId, currentOption.id);\n }\n }\n return;\n }\n\n // With no focusable row (every row inert — a run of locked-global rows plus the\n // pending-removal row) there is no focus to move or to anchor overscroll on, so\n // vertical keys drive the viewport directly. Otherwise, overscroll only kicks in\n // once focus sits on the last focusable row (below it are only inert rows).\n const noFocusableRow = lastFocusableRow === -1;\n const atLastFocusableRow = focusedRow === lastFocusableRow;\n\n if (key.leftArrow) {\n moveFocus(\"left\");\n } else if (key.rightArrow) {\n moveFocus(\"right\");\n } else if (key.upArrow) {\n if (scrollEnabled && noFocusableRow && hiddenAbove > 0) {\n scrollBy(-1);\n } else {\n moveFocus(\"up\");\n }\n } else if (key.downArrow) {\n // Keep scrolling the viewport to reveal trailing inert rows (e.g. the\n // pending-removal row) instead of wrapping. Focus never lands on them, so the\n // viewport travels past the last focusable row (or scrolls on its own when\n // nothing is focusable).\n if (scrollEnabled && (noFocusableRow || atLastFocusableRow) && hiddenBelow > 0) {\n scrollBy(1);\n } else {\n moveFocus(\"down\");\n }\n }\n },\n [\n rows,\n focusedRow,\n focusedCol,\n onSelect,\n showSearchPill,\n handleSearchTrigger,\n moveFocus,\n scrollEnabled,\n lastFocusableRow,\n hiddenAbove,\n hiddenBelow,\n scrollBy,\n ],\n ),\n { isActive: !searchModal.isOpen },\n );\n\n if (rows.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>No skills to display.</Text>\n </Box>\n );\n }\n\n const noShrink = scrollEnabled ? { flexShrink: 0 } : {};\n\n const scopeGroups = groupRowsByScope(rows);\n\n const headerSources = rows[0]?.options ?? [];\n // Drop the header's spacer row while clipping so the squeezed viewport keeps a content row for the\n // pinned column header plus the affordance; the spacer is cosmetic and only shows when not scrolling.\n const headerMarginBottom = scrollEnabled || scopeGroups.length > 0 ? 0 : 1;\n // At the shortest viewports the pinned column header would starve the content of readable rows, so\n // the labels give way — every row still shows its own source cells, only the column caption is lost.\n const showPinnedHeader = !scrollEnabled || availableHeight >= SOURCE_GRID_HEADER_MIN_HEIGHT;\n const headerElement = (\n <Box flexDirection=\"row\" marginBottom={headerMarginBottom} {...noShrink}>\n {/* Neither the scope gutter nor the skill-name column carries a caption; both boxes reserve\n their width so the source headers stay above the source cells. */}\n {scopeGroups.length > 0 && <Box width={SCOPE_COL_WIDTH} />}\n <Box width={SKILL_NAME_WIDTH} />\n {headerSources.map((option) => (\n <Box key={option.id} width={SOURCE_COL_WIDTH}>\n <Text\n color={CLI_COLORS.WARNING}\n bold\n >{`${UI_SYMBOLS.CHEVRON_SPACER} ${SOURCE_HEADER_NAMES[option.id] ?? option.id}`}</Text>\n </Box>\n ))}\n </Box>\n );\n\n const sectionElements =\n scopeGroups.length > 0\n ? scopeGroups.map((group) => (\n <Box key={group.scope} flexDirection=\"column\" marginTop={1} {...noShrink}>\n {group.rows.map(({ row, originalIndex }, rowIndexInGroup) => (\n <Box\n key={`${row.skillId}-${row.scope ?? \"default\"}`}\n flexDirection=\"row\"\n ref={(el) => setSectionRef(originalIndex, el)}\n {...noShrink}\n >\n <ScopeRowHeader scope={group.scope} isGroupStart={rowIndexInGroup === 0} />\n <SourceSection\n row={row}\n isFocused={originalIndex === focusedRow}\n focusedOptionIndex={focusedCol}\n showSearchPill={showSearchPill}\n />\n </Box>\n ))}\n </Box>\n ))\n : rows.map((row, rowIndex) => (\n <Box\n key={`${row.skillId}-${row.scope ?? \"default\"}`}\n ref={(el) => setSectionRef(rowIndex, el)}\n {...noShrink}\n >\n <SourceSection\n row={row}\n isFocused={rowIndex === focusedRow}\n focusedOptionIndex={focusedCol}\n showSearchPill={showSearchPill}\n />\n </Box>\n ));\n\n const searchModalElement = searchModal.isOpen && (\n <SearchModal\n results={searchResults}\n alias={searchAlias}\n onBind={handleBind}\n onClose={handleCloseSearch}\n />\n );\n\n return (\n <Box\n flexDirection=\"column\"\n {...(scrollEnabled\n ? { height: availableHeight, overflow: \"hidden\" as const }\n : { flexGrow: 1 })}\n >\n {showPinnedHeader && headerElement}\n <Box ref={setViewportRef} flexDirection=\"column\" overflow=\"hidden\" flexGrow={1}>\n <Box\n ref={setContentRef}\n flexDirection=\"column\"\n marginTop={scrollTopPx > 0 ? -scrollTopPx : 0}\n {...noShrink}\n >\n {sectionElements}\n </Box>\n </Box>\n <ScrollAffordance hiddenAbove={hiddenAbove} hiddenBelow={hiddenBelow} />\n {searchModalElement}\n </Box>\n );\n};\n","import { useCallback, useState } from \"react\";\nimport type { BoundSkillCandidate, SkillAlias } from \"../../types/index.js\";\nimport { matrix } from \"../../lib/matrix/matrix-provider.js\";\nimport { useModalState } from \"./use-modal-state.js\";\nimport type { SourceRow } from \"../wizard/source-grid.js\";\n\ntype UseSourceGridSearchModalOptions = {\n rows: SourceRow[];\n onSearch?: (alias: SkillAlias) => Promise<BoundSkillCandidate[]>;\n onBind?: (candidate: BoundSkillCandidate) => void;\n onSearchStateChange?: (active: boolean) => void;\n};\n\ntype UseSourceGridSearchModalResult = {\n searchModal: { isOpen: boolean };\n searchResults: BoundSkillCandidate[];\n searchAlias: string;\n handleSearchTrigger: (rowIndex: number) => Promise<void>;\n handleBind: (candidate: BoundSkillCandidate) => void;\n handleCloseSearch: () => void;\n};\n\nexport function useSourceGridSearchModal({\n rows,\n onSearch,\n onBind,\n onSearchStateChange,\n}: UseSourceGridSearchModalOptions): UseSourceGridSearchModalResult {\n const searchModal = useModalState<number>();\n const [searchResults, setSearchResults] = useState<BoundSkillCandidate[]>([]);\n const [searchAlias, setSearchAlias] = useState(\"\");\n\n const resetSearch = useCallback(() => {\n searchModal.close();\n setSearchResults([]);\n setSearchAlias(\"\");\n onSearchStateChange?.(false);\n }, [onSearchStateChange, searchModal]);\n\n const handleSearchTrigger = useCallback(\n async (rowIndex: number) => {\n const row = rows[rowIndex];\n if (!row || !onSearch) return;\n\n const alias = matrix.slugMap.idToSlug[row.skillId];\n if (!alias) return;\n setSearchAlias(alias);\n searchModal.open(rowIndex);\n onSearchStateChange?.(true);\n\n const results = await onSearch(alias);\n setSearchResults(results);\n },\n [rows, onSearch, onSearchStateChange, searchModal],\n );\n\n const handleBind = useCallback(\n (candidate: BoundSkillCandidate) => {\n onBind?.(candidate);\n resetSearch();\n },\n [onBind, resetSearch],\n );\n\n const handleCloseSearch = useCallback(() => {\n resetSearch();\n }, [resetSearch]);\n\n return {\n searchModal: { isOpen: searchModal.isOpen },\n searchResults,\n searchAlias,\n handleSearchTrigger,\n handleBind,\n handleCloseSearch,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAgB,eAAAA,cAAa,eAAe;AAC5C,SAAS,KAAK,MAAM,gBAA0B;;;ACD9C;AAAA,SAAS,aAAa,gBAAgB;AAsB/B,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoE;AAClE,QAAM,cAAc,cAAsB;AAC1C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAgC,CAAC,CAAC;AAC5E,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AAEjD,QAAM,cAAc,YAAY,MAAM;AACpC,gBAAY,MAAM;AAClB,qBAAiB,CAAC,CAAC;AACnB,mBAAe,EAAE;AACjB,0BAAsB,KAAK;AAAA,EAC7B,GAAG,CAAC,qBAAqB,WAAW,CAAC;AAErC,QAAM,sBAAsB;AAAA,IAC1B,OAAO,aAAqB;AAC1B,YAAM,MAAM,KAAK,QAAQ;AACzB,UAAI,CAAC,OAAO,CAAC,SAAU;AAEvB,YAAM,QAAQ,OAAO,QAAQ,SAAS,IAAI,OAAO;AACjD,UAAI,CAAC,MAAO;AACZ,qBAAe,KAAK;AACpB,kBAAY,KAAK,QAAQ;AACzB,4BAAsB,IAAI;AAE1B,YAAM,UAAU,MAAM,SAAS,KAAK;AACpC,uBAAiB,OAAO;AAAA,IAC1B;AAAA,IACA,CAAC,MAAM,UAAU,qBAAqB,WAAW;AAAA,EACnD;AAEA,QAAM,aAAa;AAAA,IACjB,CAAC,cAAmC;AAClC,eAAS,SAAS;AAClB,kBAAY;AAAA,IACd;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,QAAM,oBAAoB,YAAY,MAAM;AAC1C,gBAAY;AAAA,EACd,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO;AAAA,IACL,aAAa,EAAE,QAAQ,YAAY,OAAO;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AD4EM,cA+BE,YA/BF;AA5IN,IAAM,oBAAoB;AAO1B,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAQzB,IAAM,kBAAkB;AAGxB,IAAM,oBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,SAAS;AACX;AAGA,IAAM,mBAAmB;AAQzB,IAAM,gCAAgC;AAOtC,IAAM,gCAAgC;AA2B/B,SAAS,WAAW,KAAyB;AAClD,SAAO,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,IAAI;AACjC;AAcA,SAAS,gBAAgB,KAAwB;AAC/C,MAAI,IAAI,SAAU,QAAO,GAAG,WAAW,IAAI;AAC3C,MAAI,IAAI,SAAU,QAAO,GAAG,WAAW,OAAO;AAC9C,MAAI,IAAI,MAAO,QAAO,GAAG,WAAW,KAAK;AACzC,SAAO;AACT;AAOA,SAAS,aAAa,KAAoC;AACxD,MAAI,IAAI,SAAU,QAAO,WAAW;AACpC,MAAI,IAAI,MAAO,QAAO,WAAW;AACjC,SAAO;AACT;AAGA,SAAS,cAAc,KAAwB;AAC7C,SAAO,aAAa,GAAG,KAAK,WAAW;AACzC;AASA,SAAS,qBAAqB,KAAwB;AACpD,SAAO,aAAa,GAAG,KAAK,WAAW;AACzC;AAsBA,IAAM,aAAwC,CAAC,EAAE,UAAU,MAAM;AAC/D,SACE,oBAAC,OAAI,aAAa,GAChB,8BAAC,QAAK,UAAU,CAAC,WAAW,MAAM,WAC/B,6BACH,GACF;AAEJ;AASA,SAAS,kBAAkB,QAA8B;AACvD,SAAO,qBAAqB,OAAO,EAAE,KAAK,OAAO;AACnD;AAEA,IAAM,YAKD,CAAC,EAAE,QAAQ,WAAW,UAAU,SAAS,MAAM;AAClD,MAAI,YAAY,UAAU;AAKxB,WACE,oBAAC,OAAI,OAAO,kBACV;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,WAAW,WAAW,QAAQ;AAAA,QACrC,MAAM,OAAO;AAAA,QACb,UAAU,CAAC,YAAY,CAAC,OAAO;AAAA,QAE9B;AAAA,aAAG,WAAW,cAAc;AAAA,UAC5B,kBAAkB,MAAM;AAAA;AAAA;AAAA,IAC3B,GACF;AAAA,EAEJ;AAEA,QAAM,YAAY,OAAO,WAAW,WAAW,UAAU,WAAW;AACpE,QAAM,SAAS,aAAa,OAAO;AACnC,QAAM,SAAS,YAAY,GAAG,WAAW,OAAO,MAAM,GAAG,WAAW,cAAc;AAElF,SACE,oBAAC,OAAI,OAAO,kBACV,+BAAC,QAAK,OAAO,WAAW,MAAM,QAAQ,UAAU,CAAC,OAAO,YAAY,CAAC,WAClE;AAAA;AAAA,IACA,kBAAkB,MAAM;AAAA,KAC3B,GACF;AAEJ;AAEA,IAAM,gBAA8C,CAAC;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,kBAAkB,IAAI,QAAQ;AACpC,QAAM,UAAU,WAAW,GAAG;AAC9B,QAAM,mBAAmB,UAAU,QAAQ;AAC3C,QAAM,0BAA0B,UAAU,QAAQ;AAElD,QAAM,eAAe,gBAAgB,GAAG;AAExC,SACE,qBAAC,OAAI,eAAc,OACjB;AAAA,wBAAC,OAAI,OAAO,kBACT;AAAA;AAAA;AAAA;AAAA,MAIC,qBAAC,QAAK,OAAO,qBAAqB,GAAG,GAAG,iBAAiB,WAAW,UACjE;AAAA;AAAA,QACA,GAAG,aAAa,IAAI,OAAO,EAAE,WAAW;AAAA,SAC3C;AAAA,QAEA,qBAAC,QAAK,OAAO,cAAc,GAAG,GAAG,UAAU,CAAC,CAAC,IAAI,UAC9C;AAAA;AAAA,MACA,aAAa,IAAI,OAAO,EAAE;AAAA,OAC7B,GAEJ;AAAA,IAEA,qBAAC,OAAI,eAAc,OAAM,UAAS,QAC/B;AAAA,UAAI,QAAQ,IAAI,CAAC,QAAQ,UACxB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,WAAW,oBAAoB,UAAU;AAAA,UACzC,UAAU,IAAI;AAAA,UACd,UAAU,IAAI;AAAA;AAAA,QAJT,OAAO;AAAA,MAKd,CACD;AAAA,MACA,2BACC,oBAAC,cAAW,WAAW,oBAAoB,uBAAuB,iBAAiB;AAAA,OAEvF;AAAA,KACF;AAEJ;AAGA,IAAM,oBAAoB,CAAC,KAAgB,mBAAoC;AAC7E,SAAO,IAAI,QAAQ,UAAU,iBAAiB,IAAI;AACpD;AAYA,IAAM,iBAAyE,CAAC;AAAA,EAC9E;AAAA,EACA;AACF,MACE,oBAAC,OAAI,OAAO,iBACT,0BACC,oBAAC,QAAK,OAAO,WAAW,SAAS,MAAI,MAClC,4BAAkB,KAAK,GAC1B,GAEJ;AAIF,SAAS,uBAAuB,MAAmB,UAA0B;AAC3E,QAAM,iBAAiB,KAAK,IAAI,CAAC,GAAG,YAAY,WAAW,UAAU,KAAK,MAAM;AAChF,SACE,eAAe,KAAK,CAAC,QAAQ;AAC3B,UAAM,YAAY,KAAK,GAAG;AAC1B,WAAO,aAAa,CAAC,WAAW,SAAS;AAAA,EAC3C,CAAC,KAAK;AAEV;AAGA,SAAS,sBAAsB,MAA2B;AACxD,WAAS,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;AACzC,UAAM,YAAY,KAAK,CAAC;AACxB,QAAI,aAAa,CAAC,WAAW,SAAS,EAAG,QAAO;AAAA,EAClD;AACA,SAAO;AACT;AAOA,SAAS,iBAAiB,MAAiC;AACzD,QAAM,UAAU,KAAK,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,EAAE;AAChE,QAAM,aAAa,QAAQ,OAAO,CAAC,EAAE,IAAI,MAAM,IAAI,UAAU,QAAQ;AACrE,QAAM,cAAc,QAAQ,OAAO,CAAC,EAAE,IAAI,MAAM,IAAI,UAAU,QAAQ;AAEtE,MAAI,WAAW,WAAW,KAAK,YAAY,WAAW,EAAG,QAAO,CAAC;AAEjE,SAAO;AAAA,IACL,EAAE,OAAO,UAAU,MAAM,WAAW;AAAA,IACpC,EAAE,OAAO,WAAW,MAAM,YAAY;AAAA,EACxC;AACF;AAEO,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB;AACF,MAAM;AACJ,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,yBAAyB,EAAE,MAAM,UAAU,QAAQ,oBAAoB,CAAC;AAE5E,QAAM,iBAAiB,CAAC,CAAC;AAEzB,QAAM,cAAcC;AAAA,IAClB,CAAC,QAAwB;AACvB,YAAM,UAAU,KAAK,GAAG;AACxB,aAAO,UAAU,kBAAkB,SAAS,cAAc,IAAI;AAAA,IAChE;AAAA,IACA,CAAC,MAAM,cAAc;AAAA,EACvB;AAEA,QAAM,UAAUA;AAAA,IACd,CAAC,QAAyB;AACxB,YAAM,YAAY,KAAK,GAAG;AAC1B,aAAO,CAAC,CAAC,aAAa,WAAW,SAAS;AAAA,IAC5C;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,sBAAsB,uBAAuB,MAAM,iBAAiB;AAE1E,QAAM,EAAE,YAAY,YAAY,UAAU,IAAI,mBAAmB,KAAK,QAAQ,aAAa;AAAA,IACzF,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAED,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,iBAAiB;AAAA,IACnB,cAAc,KAAK;AAAA,IACnB,cAAc;AAAA,IACd;AAAA,IACA,iBAAiB;AAAA,EACnB,CAAC;AAED,QAAM,mBAAmB,QAAQ,MAAM,sBAAsB,IAAI,GAAG,CAAC,IAAI,CAAC;AAE1E;AAAA,IACEA;AAAA,MACE,CAAC,OAAe,QAAa;AAC3B,YAAI,UAAU,WAAW;AACvB,gBAAM,aAAa,KAAK,UAAU;AAClC,cAAI,CAAC,cAAc,WAAW,UAAU,EAAG;AAC3C,cAAI,kBAAkB,eAAe,WAAW,QAAQ,QAAQ;AAC9D,iBAAK,oBAAoB,UAAU;AACnC;AAAA,UACF;AACA,cAAI,aAAa,WAAW,QAAQ,QAAQ;AAC1C,kBAAM,gBAAgB,WAAW,QAAQ,UAAU;AACnD,gBAAI,eAAe;AACjB,uBAAS,WAAW,SAAS,cAAc,EAAE;AAAA,YAC/C;AAAA,UACF;AACA;AAAA,QACF;AAMA,cAAM,iBAAiB,qBAAqB;AAC5C,cAAM,qBAAqB,eAAe;AAE1C,YAAI,IAAI,WAAW;AACjB,oBAAU,MAAM;AAAA,QAClB,WAAW,IAAI,YAAY;AACzB,oBAAU,OAAO;AAAA,QACnB,WAAW,IAAI,SAAS;AACtB,cAAI,iBAAiB,kBAAkB,cAAc,GAAG;AACtD,qBAAS,EAAE;AAAA,UACb,OAAO;AACL,sBAAU,IAAI;AAAA,UAChB;AAAA,QACF,WAAW,IAAI,WAAW;AAKxB,cAAI,kBAAkB,kBAAkB,uBAAuB,cAAc,GAAG;AAC9E,qBAAS,CAAC;AAAA,UACZ,OAAO;AACL,sBAAU,MAAM;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,EAAE,UAAU,CAAC,YAAY,OAAO;AAAA,EAClC;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,WACE,oBAAC,OAAI,eAAc,UACjB,8BAAC,QAAK,UAAQ,MAAC,mCAAqB,GACtC;AAAA,EAEJ;AAEA,QAAM,WAAW,gBAAgB,EAAE,YAAY,EAAE,IAAI,CAAC;AAEtD,QAAM,cAAc,iBAAiB,IAAI;AAEzC,QAAM,gBAAgB,KAAK,CAAC,GAAG,WAAW,CAAC;AAG3C,QAAM,qBAAqB,iBAAiB,YAAY,SAAS,IAAI,IAAI;AAGzE,QAAM,mBAAmB,CAAC,iBAAiB,mBAAmB;AAC9D,QAAM,gBACJ,qBAAC,OAAI,eAAc,OAAM,cAAc,oBAAqB,GAAG,UAG5D;AAAA,gBAAY,SAAS,KAAK,oBAAC,OAAI,OAAO,iBAAiB;AAAA,IACxD,oBAAC,OAAI,OAAO,kBAAkB;AAAA,IAC7B,cAAc,IAAI,CAAC,WAClB,oBAAC,OAAoB,OAAO,kBAC1B;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,WAAW;AAAA,QAClB,MAAI;AAAA,QACJ,aAAG,WAAW,cAAc,IAAI,oBAAoB,OAAO,EAAE,KAAK,OAAO,EAAE;AAAA;AAAA,IAAG,KAJxE,OAAO,EAKjB,CACD;AAAA,KACH;AAGF,QAAM,kBACJ,YAAY,SAAS,IACjB,YAAY,IAAI,CAAC,UACf,oBAAC,OAAsB,eAAc,UAAS,WAAW,GAAI,GAAG,UAC7D,gBAAM,KAAK,IAAI,CAAC,EAAE,KAAK,cAAc,GAAG,oBACvC;AAAA,IAAC;AAAA;AAAA,MAEC,eAAc;AAAA,MACd,KAAK,CAAC,OAAO,cAAc,eAAe,EAAE;AAAA,MAC3C,GAAG;AAAA,MAEJ;AAAA,4BAAC,kBAAe,OAAO,MAAM,OAAO,cAAc,oBAAoB,GAAG;AAAA,QACzE;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,WAAW,kBAAkB;AAAA,YAC7B,oBAAoB;AAAA,YACpB;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,IAXK,GAAG,IAAI,OAAO,IAAI,IAAI,SAAS,SAAS;AAAA,EAY/C,CACD,KAhBO,MAAM,KAiBhB,CACD,IACD,KAAK,IAAI,CAAC,KAAK,aACb;AAAA,IAAC;AAAA;AAAA,MAEC,KAAK,CAAC,OAAO,cAAc,UAAU,EAAE;AAAA,MACtC,GAAG;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,aAAa;AAAA,UACxB,oBAAoB;AAAA,UACpB;AAAA;AAAA,MACF;AAAA;AAAA,IATK,GAAG,IAAI,OAAO,IAAI,IAAI,SAAS,SAAS;AAAA,EAU/C,CACD;AAEP,QAAM,qBAAqB,YAAY,UACrC;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA;AAAA,EACX;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACb,GAAI,gBACD,EAAE,QAAQ,iBAAiB,UAAU,SAAkB,IACvD,EAAE,UAAU,EAAE;AAAA,MAEjB;AAAA,4BAAoB;AAAA,QACrB,oBAAC,OAAI,KAAK,gBAAgB,eAAc,UAAS,UAAS,UAAS,UAAU,GAC3E;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,eAAc;AAAA,YACd,WAAW,cAAc,IAAI,CAAC,cAAc;AAAA,YAC3C,GAAG;AAAA,YAEH;AAAA;AAAA,QACH,GACF;AAAA,QACA,oBAAC,oBAAiB,aAA0B,aAA0B;AAAA,QACrE;AAAA;AAAA;AAAA,EACH;AAEJ;","names":["useCallback","useCallback"]}
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ useRowScroll
4
+ } from "./chunk-FYPUUYSG.js";
5
+ import {
6
+ KEY_SPACE
7
+ } from "./chunk-VG2TVBFN.js";
8
+ import {
9
+ CLI_COLORS,
10
+ UI_SYMBOLS
11
+ } from "./chunk-O5ASLZ2K.js";
12
+ import {
13
+ init_esm_shims
14
+ } from "./chunk-P56WJ5FA.js";
15
+
16
+ // src/cli/components/wizard/checkbox-grid.tsx
17
+ init_esm_shims();
18
+ import { Box, Text, useInput } from "ink";
19
+ import { useState } from "react";
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ var CheckboxGrid = ({
22
+ subtitle,
23
+ items,
24
+ selectedIds,
25
+ availableHeight = 0,
26
+ onToggle,
27
+ onContinue,
28
+ onBack,
29
+ emptyMessage = "Please select at least one item"
30
+ }) => {
31
+ const totalItems = items.length + 1;
32
+ const [focusedIndex, setFocusedIndex] = useState(0);
33
+ useInput((input, key) => {
34
+ if (key.escape) {
35
+ onBack();
36
+ return;
37
+ }
38
+ if (key.upArrow || input === "k") {
39
+ setFocusedIndex((prev) => prev <= 0 ? totalItems - 1 : prev - 1);
40
+ return;
41
+ }
42
+ if (key.downArrow || input === "j") {
43
+ setFocusedIndex((prev) => prev >= totalItems - 1 ? 0 : prev + 1);
44
+ return;
45
+ }
46
+ if (key.return) {
47
+ onContinue();
48
+ return;
49
+ }
50
+ if (input === KEY_SPACE) {
51
+ const item = items[focusedIndex];
52
+ if (item) {
53
+ onToggle(item.id);
54
+ }
55
+ }
56
+ });
57
+ const effectiveRow = focusedIndex >= items.length ? items.length - 1 : focusedIndex;
58
+ const { scrollEnabled, scrollTop } = useRowScroll({
59
+ focusedIndex: effectiveRow,
60
+ itemCount: items.length,
61
+ availableHeight
62
+ });
63
+ const itemElements = items.map((item, index) => {
64
+ const isFocused = index === focusedIndex;
65
+ const isSelected = selectedIds.includes(item.id);
66
+ const checkbox = isSelected ? "[\u2713]" : "[ ]";
67
+ const pointer = isFocused ? UI_SYMBOLS.CHEVRON : UI_SYMBOLS.CHEVRON_SPACER;
68
+ return /* @__PURE__ */ jsxs(Text, { children: [
69
+ /* @__PURE__ */ jsx(Text, { color: isFocused ? CLI_COLORS.PRIMARY : void 0, children: pointer }),
70
+ /* @__PURE__ */ jsxs(Text, { color: isSelected || isFocused ? CLI_COLORS.PRIMARY : void 0, bold: isFocused, children: [
71
+ " ",
72
+ checkbox,
73
+ " ",
74
+ item.label
75
+ ] }),
76
+ item.description && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
77
+ " ",
78
+ item.description
79
+ ] })
80
+ ] }, item.id);
81
+ });
82
+ const footerElement = selectedIds.length > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
83
+ "\n",
84
+ "Selected: ",
85
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, children: selectedIds.join(", ") })
86
+ ] }) : emptyMessage ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
87
+ "\n",
88
+ emptyMessage
89
+ ] }) : null;
90
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
91
+ subtitle && /* @__PURE__ */ jsx(Text, { dimColor: true, children: subtitle }),
92
+ /* @__PURE__ */ jsx(
93
+ Box,
94
+ {
95
+ flexDirection: "column",
96
+ ...scrollEnabled && { height: availableHeight, overflow: "hidden" },
97
+ children: /* @__PURE__ */ jsx(
98
+ Box,
99
+ {
100
+ flexDirection: "column",
101
+ marginTop: scrollTop > 0 ? -scrollTop : 0,
102
+ ...scrollEnabled && { flexShrink: 0 },
103
+ children: itemElements
104
+ }
105
+ )
106
+ }
107
+ ),
108
+ footerElement
109
+ ] });
110
+ };
111
+
112
+ export {
113
+ CheckboxGrid
114
+ };
115
+ //# sourceMappingURL=chunk-XA57SX4T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/checkbox-grid.tsx"],"sourcesContent":["import { Box, Text, useInput } from \"ink\";\nimport React, { useState } from \"react\";\nimport { CLI_COLORS, UI_SYMBOLS } from \"../../consts.js\";\nimport { useRowScroll } from \"../hooks/use-row-scroll.js\";\nimport { KEY_SPACE } from \"./hotkeys.js\";\n\nexport type CheckboxItem<T extends string = string> = {\n id: T;\n label: string;\n description: string;\n};\n\nexport type CheckboxGridProps<T extends string = string> = {\n subtitle?: string;\n items: CheckboxItem<T>[];\n selectedIds: T[];\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n onToggle: (id: T) => void;\n onContinue: () => void;\n onBack: () => void;\n /** Message shown when nothing is selected */\n emptyMessage?: string;\n};\n\nexport const CheckboxGrid = <T extends string = string>({\n subtitle,\n items,\n selectedIds,\n availableHeight = 0,\n onToggle,\n onContinue,\n onBack,\n emptyMessage = \"Please select at least one item\",\n}: CheckboxGridProps<T>): React.ReactElement => {\n // Items + continue option at the end\n const totalItems = items.length + 1;\n const [focusedIndex, setFocusedIndex] = useState(0);\n\n useInput((input, key) => {\n if (key.escape) {\n onBack();\n return;\n }\n\n if (key.upArrow || input === \"k\") {\n setFocusedIndex((prev) => (prev <= 0 ? totalItems - 1 : prev - 1));\n return;\n }\n\n if (key.downArrow || input === \"j\") {\n setFocusedIndex((prev) => (prev >= totalItems - 1 ? 0 : prev + 1));\n return;\n }\n\n if (key.return) {\n onContinue();\n return;\n }\n\n if (input === KEY_SPACE) {\n const item = items[focusedIndex];\n if (item) {\n onToggle(item.id);\n }\n }\n });\n\n // The Domains grid clips silently: `useRowScroll` exposes no hidden-line\n // counts and this view renders no `ScrollAffordance`, by owner decision — see\n // the hook's doc comment.\n // When focus is on continue (past items), scroll to show last items\n const effectiveRow = focusedIndex >= items.length ? items.length - 1 : focusedIndex;\n const { scrollEnabled, scrollTop } = useRowScroll({\n focusedIndex: effectiveRow,\n itemCount: items.length,\n availableHeight,\n });\n\n const itemElements = items.map((item, index) => {\n const isFocused = index === focusedIndex;\n const isSelected = selectedIds.includes(item.id);\n const checkbox = isSelected ? \"[\\u2713]\" : \"[ ]\";\n const pointer = isFocused ? UI_SYMBOLS.CHEVRON : UI_SYMBOLS.CHEVRON_SPACER;\n\n return (\n <Text key={item.id}>\n <Text color={isFocused ? CLI_COLORS.PRIMARY : undefined}>{pointer}</Text>\n <Text color={isSelected || isFocused ? CLI_COLORS.PRIMARY : undefined} bold={isFocused}>\n {\" \"}\n {checkbox} {item.label}\n </Text>\n {item.description && (\n <Text dimColor>\n {\" \"}\n {item.description}\n </Text>\n )}\n </Text>\n );\n });\n\n const footerElement =\n selectedIds.length > 0 ? (\n <Text>\n {\"\\n\"}Selected: <Text color={CLI_COLORS.WARNING}>{selectedIds.join(\", \")}</Text>\n </Text>\n ) : emptyMessage ? (\n <Text dimColor>\n {\"\\n\"}\n {emptyMessage}\n </Text>\n ) : null;\n\n return (\n <Box flexDirection=\"column\">\n {subtitle && <Text dimColor>{subtitle}</Text>}\n <Box\n flexDirection=\"column\"\n {...(scrollEnabled && { height: availableHeight, overflow: \"hidden\" as const })}\n >\n <Box\n flexDirection=\"column\"\n marginTop={scrollTop > 0 ? -scrollTop : 0}\n {...(scrollEnabled && { flexShrink: 0 })}\n >\n {itemElements}\n </Box>\n </Box>\n {footerElement}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,KAAK,MAAM,gBAAgB;AACpC,SAAgB,gBAAgB;AAsFxB,cACA,YADA;AA9DD,IAAM,eAAe,CAA4B;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,MAAgD;AAE9C,QAAM,aAAa,MAAM,SAAS;AAClC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,CAAC;AAElD,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,aAAO;AACP;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,UAAU,KAAK;AAChC,sBAAgB,CAAC,SAAU,QAAQ,IAAI,aAAa,IAAI,OAAO,CAAE;AACjE;AAAA,IACF;AAEA,QAAI,IAAI,aAAa,UAAU,KAAK;AAClC,sBAAgB,CAAC,SAAU,QAAQ,aAAa,IAAI,IAAI,OAAO,CAAE;AACjE;AAAA,IACF;AAEA,QAAI,IAAI,QAAQ;AACd,iBAAW;AACX;AAAA,IACF;AAEA,QAAI,UAAU,WAAW;AACvB,YAAM,OAAO,MAAM,YAAY;AAC/B,UAAI,MAAM;AACR,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAAA,EACF,CAAC;AAMD,QAAM,eAAe,gBAAgB,MAAM,SAAS,MAAM,SAAS,IAAI;AACvE,QAAM,EAAE,eAAe,UAAU,IAAI,aAAa;AAAA,IAChD,cAAc;AAAA,IACd,WAAW,MAAM;AAAA,IACjB;AAAA,EACF,CAAC;AAED,QAAM,eAAe,MAAM,IAAI,CAAC,MAAM,UAAU;AAC9C,UAAM,YAAY,UAAU;AAC5B,UAAM,aAAa,YAAY,SAAS,KAAK,EAAE;AAC/C,UAAM,WAAW,aAAa,aAAa;AAC3C,UAAM,UAAU,YAAY,WAAW,UAAU,WAAW;AAE5D,WACE,qBAAC,QACC;AAAA,0BAAC,QAAK,OAAO,YAAY,WAAW,UAAU,QAAY,mBAAQ;AAAA,MAClE,qBAAC,QAAK,OAAO,cAAc,YAAY,WAAW,UAAU,QAAW,MAAM,WAC1E;AAAA;AAAA,QACA;AAAA,QAAS;AAAA,QAAE,KAAK;AAAA,SACnB;AAAA,MACC,KAAK,eACJ,qBAAC,QAAK,UAAQ,MACX;AAAA;AAAA,QACA,KAAK;AAAA,SACR;AAAA,SAVO,KAAK,EAYhB;AAAA,EAEJ,CAAC;AAED,QAAM,gBACJ,YAAY,SAAS,IACnB,qBAAC,QACE;AAAA;AAAA,IAAK;AAAA,IAAU,oBAAC,QAAK,OAAO,WAAW,SAAU,sBAAY,KAAK,IAAI,GAAE;AAAA,KAC3E,IACE,eACF,qBAAC,QAAK,UAAQ,MACX;AAAA;AAAA,IACA;AAAA,KACH,IACE;AAEN,SACE,qBAAC,OAAI,eAAc,UAChB;AAAA,gBAAY,oBAAC,QAAK,UAAQ,MAAE,oBAAS;AAAA,IACtC;AAAA,MAAC;AAAA;AAAA,QACC,eAAc;AAAA,QACb,GAAI,iBAAiB,EAAE,QAAQ,iBAAiB,UAAU,SAAkB;AAAA,QAE7E;AAAA,UAAC;AAAA;AAAA,YACC,eAAc;AAAA,YACd,WAAW,YAAY,IAAI,CAAC,YAAY;AAAA,YACvC,GAAI,iBAAiB,EAAE,YAAY,EAAE;AAAA,YAErC;AAAA;AAAA,QACH;AAAA;AAAA,IACF;AAAA,IACC;AAAA,KACH;AAEJ;","names":[]}