@claude-collective/cli 0.13.3 → 0.21.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 (228) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/config/skills-matrix.yaml +180 -113
  3. package/config/stacks.yaml +6 -6
  4. package/dist/{chunk-6DCSSORF.js → chunk-2LSGX6R4.js} +54 -119
  5. package/dist/chunk-2LSGX6R4.js.map +1 -0
  6. package/dist/chunk-2OKUEELH.js +32 -0
  7. package/dist/chunk-2OKUEELH.js.map +1 -0
  8. package/dist/{chunk-V46GGCCI.js → chunk-374JNMR6.js} +14 -96
  9. package/dist/chunk-374JNMR6.js.map +1 -0
  10. package/dist/chunk-3EHUF54X.js +133 -0
  11. package/dist/chunk-3EHUF54X.js.map +1 -0
  12. package/dist/{chunk-7Q44DMSP.js → chunk-3XR4PALU.js} +92 -145
  13. package/dist/chunk-3XR4PALU.js.map +1 -0
  14. package/dist/{chunk-IAUAQJQ2.js → chunk-5K2ZLUO5.js} +5 -5
  15. package/dist/{chunk-IAUAQJQ2.js.map → chunk-5K2ZLUO5.js.map} +1 -1
  16. package/dist/{chunk-ACNBKXXJ.js → chunk-5KXUDHAB.js} +8 -36
  17. package/dist/chunk-5KXUDHAB.js.map +1 -0
  18. package/dist/chunk-7SLV7CMF.js +615 -0
  19. package/dist/chunk-7SLV7CMF.js.map +1 -0
  20. package/dist/{chunk-CDX4W4DM.js → chunk-A46TPNBJ.js} +61 -32
  21. package/dist/chunk-A46TPNBJ.js.map +1 -0
  22. package/dist/{chunk-TKFPKEV3.js → chunk-AL74GBW4.js} +1 -1
  23. package/dist/chunk-AL74GBW4.js.map +1 -0
  24. package/dist/chunk-BQX23RBV.js +191 -0
  25. package/dist/chunk-BQX23RBV.js.map +1 -0
  26. package/dist/{chunk-IMDW5ZUP.js → chunk-CA4LH4LI.js} +5 -5
  27. package/dist/chunk-CA4LH4LI.js.map +1 -0
  28. package/dist/{chunk-D237EVNB.js → chunk-CBLPAMZO.js} +5 -8
  29. package/dist/chunk-CBLPAMZO.js.map +1 -0
  30. package/dist/{chunk-B7CCVP6Q.js → chunk-CKPQHGXR.js} +52 -274
  31. package/dist/chunk-CKPQHGXR.js.map +1 -0
  32. package/dist/{chunk-SVYPSDWY.js → chunk-CXOFOJCN.js} +6 -10
  33. package/dist/chunk-CXOFOJCN.js.map +1 -0
  34. package/dist/{chunk-UQTEPWU7.js → chunk-EHGD7HIE.js} +2 -6
  35. package/dist/chunk-EHGD7HIE.js.map +1 -0
  36. package/dist/{chunk-76DWXGQE.js → chunk-FJFEKPXF.js} +1 -1
  37. package/dist/chunk-FJFEKPXF.js.map +1 -0
  38. package/dist/{chunk-E3FJH4TF.js → chunk-HEOHU5EZ.js} +2 -13
  39. package/dist/chunk-HEOHU5EZ.js.map +1 -0
  40. package/dist/{chunk-JIPWV2FX.js → chunk-HGCBZUH5.js} +6 -27
  41. package/dist/chunk-HGCBZUH5.js.map +1 -0
  42. package/dist/{chunk-ED4E6Q2T.js → chunk-HPGFY5ZN.js} +4 -4
  43. package/dist/chunk-HPGFY5ZN.js.map +1 -0
  44. package/dist/chunk-INJ2EFRW.js +127 -0
  45. package/dist/chunk-INJ2EFRW.js.map +1 -0
  46. package/dist/{chunk-KAAEN2PO.js → chunk-IOBFMF6X.js} +6 -2
  47. package/dist/{chunk-KAAEN2PO.js.map → chunk-IOBFMF6X.js.map} +1 -1
  48. package/dist/{chunk-K7EVM5LY.js → chunk-KH3HA7J7.js} +8 -33
  49. package/dist/chunk-KH3HA7J7.js.map +1 -0
  50. package/dist/{chunk-4K4ZXQRM.js → chunk-N6JNE326.js} +38 -94
  51. package/dist/chunk-N6JNE326.js.map +1 -0
  52. package/dist/chunk-NAGU7TVZ.js +36 -0
  53. package/dist/chunk-NAGU7TVZ.js.map +1 -0
  54. package/dist/{chunk-Z7G4B5HJ.js → chunk-OQYYMQJR.js} +68 -142
  55. package/dist/chunk-OQYYMQJR.js.map +1 -0
  56. package/dist/{chunk-CPZOTVCI.js → chunk-PLZOUVDD.js} +185 -74
  57. package/dist/chunk-PLZOUVDD.js.map +1 -0
  58. package/dist/chunk-Q3J43SF3.js +21 -0
  59. package/dist/chunk-Q3J43SF3.js.map +1 -0
  60. package/dist/{chunk-3U3R4NCG.js → chunk-T25OEQFI.js} +6 -2
  61. package/dist/chunk-T25OEQFI.js.map +1 -0
  62. package/dist/chunk-UMORK7OK.js +29 -0
  63. package/dist/chunk-UMORK7OK.js.map +1 -0
  64. package/dist/{chunk-ZFPSUQOU.js → chunk-VFHWU7JU.js} +12 -121
  65. package/dist/chunk-VFHWU7JU.js.map +1 -0
  66. package/dist/{chunk-GDH553MV.js → chunk-VS4GVTZE.js} +3 -3
  67. package/dist/chunk-VS4GVTZE.js.map +1 -0
  68. package/dist/chunk-WFEFICFM.js +67 -0
  69. package/dist/chunk-WFEFICFM.js.map +1 -0
  70. package/dist/{chunk-P26A2K5N.js → chunk-WG6KIAPK.js} +6 -16
  71. package/dist/chunk-WG6KIAPK.js.map +1 -0
  72. package/dist/{chunk-X6QONICW.js → chunk-ZEI3ZUDU.js} +3 -7
  73. package/dist/chunk-ZEI3ZUDU.js.map +1 -0
  74. package/dist/chunk-ZNIDWLL5.js +68 -0
  75. package/dist/chunk-ZNIDWLL5.js.map +1 -0
  76. package/dist/chunk-ZSVMS677.js +45 -0
  77. package/dist/chunk-ZSVMS677.js.map +1 -0
  78. package/dist/cli/defaults/agent-mappings.yaml +13 -13
  79. package/dist/commands/build/marketplace.js +8 -14
  80. package/dist/commands/build/marketplace.js.map +1 -1
  81. package/dist/commands/build/plugins.js +10 -21
  82. package/dist/commands/build/plugins.js.map +1 -1
  83. package/dist/commands/build/stack.js +13 -18
  84. package/dist/commands/build/stack.js.map +1 -1
  85. package/dist/commands/compile.js +25 -40
  86. package/dist/commands/compile.js.map +1 -1
  87. package/dist/commands/config/get.js +7 -7
  88. package/dist/commands/config/get.js.map +1 -1
  89. package/dist/commands/config/index.js +6 -6
  90. package/dist/commands/config/index.js.map +1 -1
  91. package/dist/commands/config/path.js +5 -7
  92. package/dist/commands/config/path.js.map +1 -1
  93. package/dist/commands/config/set-project.js +8 -9
  94. package/dist/commands/config/set-project.js.map +1 -1
  95. package/dist/commands/config/show.js +5 -5
  96. package/dist/commands/config/unset-project.js +8 -9
  97. package/dist/commands/config/unset-project.js.map +1 -1
  98. package/dist/commands/diff.js +17 -40
  99. package/dist/commands/diff.js.map +1 -1
  100. package/dist/commands/doctor.js +14 -25
  101. package/dist/commands/doctor.js.map +1 -1
  102. package/dist/commands/edit.js +41 -54
  103. package/dist/commands/edit.js.map +1 -1
  104. package/dist/commands/eject.js +24 -44
  105. package/dist/commands/eject.js.map +1 -1
  106. package/dist/commands/import/skill.js +19 -39
  107. package/dist/commands/import/skill.js.map +1 -1
  108. package/dist/commands/info.js +10 -15
  109. package/dist/commands/info.js.map +1 -1
  110. package/dist/commands/init.js +452 -451
  111. package/dist/commands/init.js.map +1 -1
  112. package/dist/commands/list.js +85 -9
  113. package/dist/commands/list.js.map +1 -1
  114. package/dist/commands/new/agent.js +9 -10
  115. package/dist/commands/new/agent.js.map +1 -1
  116. package/dist/commands/new/skill.js +12 -16
  117. package/dist/commands/new/skill.js.map +1 -1
  118. package/dist/commands/outdated.js +12 -89
  119. package/dist/commands/outdated.js.map +1 -1
  120. package/dist/commands/search.js +12 -18
  121. package/dist/commands/search.js.map +1 -1
  122. package/dist/commands/uninstall.js +12 -21
  123. package/dist/commands/uninstall.js.map +1 -1
  124. package/dist/commands/update.js +26 -146
  125. package/dist/commands/update.js.map +1 -1
  126. package/dist/commands/validate.js +407 -15
  127. package/dist/commands/validate.js.map +1 -1
  128. package/dist/commands/version/bump.js +7 -23
  129. package/dist/commands/version/bump.js.map +1 -1
  130. package/dist/commands/version/index.js +6 -21
  131. package/dist/commands/version/index.js.map +1 -1
  132. package/dist/commands/version/set.js +6 -23
  133. package/dist/commands/version/set.js.map +1 -1
  134. package/dist/commands/version/show.js +6 -21
  135. package/dist/commands/version/show.js.map +1 -1
  136. package/dist/components/common/message.js +2 -6
  137. package/dist/components/common/message.js.map +1 -1
  138. package/dist/components/common/spinner.js.map +1 -1
  139. package/dist/components/skill-search/skill-search.js +1 -1
  140. package/dist/components/wizard/category-grid.js +1 -1
  141. package/dist/components/wizard/category-grid.test.js +20 -92
  142. package/dist/components/wizard/category-grid.test.js.map +1 -1
  143. package/dist/components/wizard/menu-item.js +9 -0
  144. package/dist/components/wizard/section-progress.js +1 -1
  145. package/dist/components/wizard/section-progress.test.js +13 -103
  146. package/dist/components/wizard/section-progress.test.js.map +1 -1
  147. package/dist/components/wizard/step-approach.js +5 -4
  148. package/dist/components/wizard/step-build.js +3 -4
  149. package/dist/components/wizard/step-build.test.js +81 -186
  150. package/dist/components/wizard/step-build.test.js.map +1 -1
  151. package/dist/components/wizard/step-confirm.js +1 -2
  152. package/dist/components/wizard/step-refine.js +1 -2
  153. package/dist/components/wizard/step-refine.test.js +6 -14
  154. package/dist/components/wizard/step-refine.test.js.map +1 -1
  155. package/dist/components/wizard/step-stack.js +5 -3
  156. package/dist/components/wizard/view-title.js +9 -0
  157. package/dist/components/wizard/wizard-layout.js +16 -0
  158. package/dist/components/wizard/wizard-layout.js.map +1 -0
  159. package/dist/components/wizard/wizard-tabs.js +1 -1
  160. package/dist/components/wizard/wizard.js +12 -13
  161. package/dist/config/skills-matrix.yaml +180 -113
  162. package/dist/config/stacks.yaml +6 -6
  163. package/dist/hooks/init.js +5 -7
  164. package/dist/hooks/init.js.map +1 -1
  165. package/dist/src/agents/developer/web-developer/examples.md +1 -6
  166. package/dist/src/agents/meta/documentor/workflow.md +1 -5
  167. package/dist/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  168. package/dist/src/agents/tester/web-tester/output-format.md +1 -3
  169. package/dist/stores/wizard-store.js +2 -2
  170. package/dist/stores/wizard-store.test.js +60 -23
  171. package/dist/stores/wizard-store.test.js.map +1 -1
  172. package/package.json +1 -1
  173. package/src/agents/developer/web-developer/examples.md +1 -6
  174. package/src/agents/meta/documentor/workflow.md +1 -5
  175. package/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
  176. package/src/agents/tester/web-tester/output-format.md +1 -3
  177. package/dist/chunk-3U3R4NCG.js.map +0 -1
  178. package/dist/chunk-4K4ZXQRM.js.map +0 -1
  179. package/dist/chunk-6DCSSORF.js.map +0 -1
  180. package/dist/chunk-76DWXGQE.js.map +0 -1
  181. package/dist/chunk-7Q44DMSP.js.map +0 -1
  182. package/dist/chunk-ACNBKXXJ.js.map +0 -1
  183. package/dist/chunk-B7CCVP6Q.js.map +0 -1
  184. package/dist/chunk-BDLUZVKU.js +0 -54
  185. package/dist/chunk-BDLUZVKU.js.map +0 -1
  186. package/dist/chunk-CDX4W4DM.js.map +0 -1
  187. package/dist/chunk-CPZOTVCI.js.map +0 -1
  188. package/dist/chunk-D237EVNB.js.map +0 -1
  189. package/dist/chunk-DRXPNNPB.js +0 -393
  190. package/dist/chunk-DRXPNNPB.js.map +0 -1
  191. package/dist/chunk-E3FJH4TF.js.map +0 -1
  192. package/dist/chunk-ED4E6Q2T.js.map +0 -1
  193. package/dist/chunk-GDH553MV.js.map +0 -1
  194. package/dist/chunk-HLJX2FTL.js +0 -95
  195. package/dist/chunk-HLJX2FTL.js.map +0 -1
  196. package/dist/chunk-I2DSLOXZ.js +0 -75
  197. package/dist/chunk-I2DSLOXZ.js.map +0 -1
  198. package/dist/chunk-I4TPKIYX.js +0 -493
  199. package/dist/chunk-I4TPKIYX.js.map +0 -1
  200. package/dist/chunk-IBE7JIAG.js +0 -129
  201. package/dist/chunk-IBE7JIAG.js.map +0 -1
  202. package/dist/chunk-IMDW5ZUP.js.map +0 -1
  203. package/dist/chunk-JIPWV2FX.js.map +0 -1
  204. package/dist/chunk-K7EVM5LY.js.map +0 -1
  205. package/dist/chunk-NDY25DTL.js +0 -453
  206. package/dist/chunk-NDY25DTL.js.map +0 -1
  207. package/dist/chunk-P26A2K5N.js.map +0 -1
  208. package/dist/chunk-SVYPSDWY.js.map +0 -1
  209. package/dist/chunk-TKFPKEV3.js.map +0 -1
  210. package/dist/chunk-UQTEPWU7.js.map +0 -1
  211. package/dist/chunk-V46GGCCI.js.map +0 -1
  212. package/dist/chunk-X6QONICW.js.map +0 -1
  213. package/dist/chunk-Y2LW7R3Y.js +0 -23
  214. package/dist/chunk-Y2LW7R3Y.js.map +0 -1
  215. package/dist/chunk-Z7G4B5HJ.js.map +0 -1
  216. package/dist/chunk-ZENYS6KW.js +0 -90
  217. package/dist/chunk-ZENYS6KW.js.map +0 -1
  218. package/dist/chunk-ZFPSUQOU.js.map +0 -1
  219. package/dist/commands/config/set.js +0 -61
  220. package/dist/commands/config/set.js.map +0 -1
  221. package/dist/commands/config/unset.js +0 -57
  222. package/dist/commands/config/unset.js.map +0 -1
  223. package/dist/commands/test-imports.js +0 -92
  224. package/dist/commands/test-imports.js.map +0 -1
  225. package/dist/components/wizard/step-stack-options.js +0 -11
  226. package/dist/components/wizard/wizard-footer.js +0 -9
  227. /package/dist/components/wizard/{step-stack-options.js.map → menu-item.js.map} +0 -0
  228. /package/dist/components/wizard/{wizard-footer.js.map → view-title.js.map} +0 -0
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  verbose
4
- } from "./chunk-3U3R4NCG.js";
4
+ } from "./chunk-T25OEQFI.js";
5
5
  import {
6
6
  fileExists,
7
7
  readFile
8
- } from "./chunk-TKFPKEV3.js";
8
+ } from "./chunk-AL74GBW4.js";
9
9
  import {
10
10
  CLAUDE_DIR,
11
11
  CLAUDE_SRC_DIR
12
- } from "./chunk-76DWXGQE.js";
12
+ } from "./chunk-FJFEKPXF.js";
13
13
  import {
14
14
  init_esm_shims
15
15
  } from "./chunk-DHET7RCE.js";
@@ -29,9 +29,7 @@ async function loadProjectConfig(projectDir) {
29
29
  configPath = legacyConfigPath;
30
30
  verbose(`Using legacy config location: ${legacyConfigPath}`);
31
31
  } else {
32
- verbose(
33
- `Project config not found at ${srcConfigPath} or ${legacyConfigPath}`
34
- );
32
+ verbose(`Project config not found at ${srcConfigPath} or ${legacyConfigPath}`);
35
33
  return null;
36
34
  }
37
35
  }
@@ -42,16 +40,6 @@ async function loadProjectConfig(projectDir) {
42
40
  verbose(`Invalid project config structure at ${configPath}`);
43
41
  return null;
44
42
  }
45
- const isLegacy = isLegacyStackConfig(parsed);
46
- if (isLegacy) {
47
- verbose(`Detected legacy StackConfig format at ${configPath}`);
48
- const normalized = normalizeStackConfig(parsed);
49
- return {
50
- config: normalized,
51
- configPath,
52
- isLegacy: true
53
- };
54
- }
55
43
  verbose(`Loaded project config from ${configPath}`);
56
44
  return {
57
45
  config: parsed,
@@ -63,51 +51,6 @@ async function loadProjectConfig(projectDir) {
63
51
  return null;
64
52
  }
65
53
  }
66
- function isLegacyStackConfig(config) {
67
- if (!config || typeof config !== "object") return false;
68
- const obj = config;
69
- if (typeof obj.version === "string" && obj.version.includes(".")) {
70
- return true;
71
- }
72
- if (obj.id !== void 0 || obj.created !== void 0 || obj.updated !== void 0) {
73
- return true;
74
- }
75
- return false;
76
- }
77
- function normalizeStackConfig(stackConfig) {
78
- const config = {
79
- name: stackConfig.name,
80
- agents: stackConfig.agents
81
- };
82
- if (stackConfig.description) {
83
- config.description = stackConfig.description;
84
- }
85
- if (stackConfig.skills && stackConfig.skills.length > 0) {
86
- config.skills = stackConfig.skills;
87
- }
88
- if (stackConfig.agent_skills) {
89
- config.agent_skills = stackConfig.agent_skills;
90
- }
91
- if (stackConfig.hooks) {
92
- config.hooks = stackConfig.hooks;
93
- }
94
- if (stackConfig.author) {
95
- config.author = stackConfig.author;
96
- }
97
- if (stackConfig.framework) {
98
- config.framework = stackConfig.framework;
99
- }
100
- if (stackConfig.philosophy) {
101
- config.philosophy = stackConfig.philosophy;
102
- }
103
- if (stackConfig.principles && stackConfig.principles.length > 0) {
104
- config.principles = stackConfig.principles;
105
- }
106
- if (stackConfig.tags && stackConfig.tags.length > 0) {
107
- config.tags = stackConfig.tags;
108
- }
109
- return config;
110
- }
111
54
  function validateProjectConfig(config) {
112
55
  const errors = [];
113
56
  const warnings = [];
@@ -147,10 +90,7 @@ function validateProjectConfig(config) {
147
90
  errors.push("agent_skills must be an object");
148
91
  } else {
149
92
  for (const [agentName, agentSkills] of Object.entries(c.agent_skills)) {
150
- const agentSkillsError = validateAgentSkillConfig(
151
- agentName,
152
- agentSkills
153
- );
93
+ const agentSkillsError = validateAgentSkillConfig(agentName, agentSkills);
154
94
  if (agentSkillsError) {
155
95
  errors.push(agentSkillsError);
156
96
  }
@@ -163,15 +103,11 @@ function validateProjectConfig(config) {
163
103
  } else {
164
104
  for (const [agentName, patterns] of Object.entries(c.preload_patterns)) {
165
105
  if (!Array.isArray(patterns)) {
166
- errors.push(
167
- `preload_patterns.${agentName} must be an array of strings`
168
- );
106
+ errors.push(`preload_patterns.${agentName} must be an array of strings`);
169
107
  } else {
170
108
  for (const pattern of patterns) {
171
109
  if (typeof pattern !== "string") {
172
- errors.push(
173
- `preload_patterns.${agentName} must contain only strings`
174
- );
110
+ errors.push(`preload_patterns.${agentName} must contain only strings`);
175
111
  break;
176
112
  }
177
113
  }
@@ -183,15 +119,6 @@ function validateProjectConfig(config) {
183
119
  const customAgentsErrors = validateCustomAgents(c.custom_agents, c.agents);
184
120
  errors.push(...customAgentsErrors);
185
121
  }
186
- if (c.id !== void 0) {
187
- warnings.push("id field is deprecated in project config");
188
- }
189
- if (c.created !== void 0) {
190
- warnings.push("created field is deprecated in project config");
191
- }
192
- if (c.updated !== void 0) {
193
- warnings.push("updated field is deprecated in project config");
194
- }
195
122
  return {
196
123
  valid: errors.length === 0,
197
124
  errors,
@@ -222,11 +149,7 @@ function validateCustomAgents(customAgents, agents) {
222
149
  }
223
150
  const customAgentNames = new Set(customAgentEntries.map(([name]) => name));
224
151
  for (const [agentName, agentConfig] of customAgentEntries) {
225
- const agentErrors = validateCustomAgentConfig(
226
- agentName,
227
- agentConfig,
228
- customAgentNames
229
- );
152
+ const agentErrors = validateCustomAgentConfig(agentName, agentConfig, customAgentNames);
230
153
  errors.push(...agentErrors);
231
154
  }
232
155
  return errors;
@@ -249,9 +172,7 @@ function validateCustomAgentConfig(agentName, config, customAgentNames) {
249
172
  if (typeof c.extends !== "string") {
250
173
  errors.push(`${prefix}.extends must be a string`);
251
174
  } else if (customAgentNames.has(c.extends)) {
252
- errors.push(
253
- `${prefix}.extends cannot reference another custom agent "${c.extends}"`
254
- );
175
+ errors.push(`${prefix}.extends cannot reference another custom agent "${c.extends}"`);
255
176
  }
256
177
  }
257
178
  if (c.model !== void 0) {
@@ -285,9 +206,7 @@ function validateCustomAgentConfig(agentName, config, customAgentNames) {
285
206
  }
286
207
  if (c.permission_mode !== void 0) {
287
208
  if (typeof c.permission_mode !== "string" || !VALID_PERMISSION_MODES.includes(c.permission_mode)) {
288
- errors.push(
289
- `${prefix}.permission_mode must be one of: ${VALID_PERMISSION_MODES.join(", ")}`
290
- );
209
+ errors.push(`${prefix}.permission_mode must be one of: ${VALID_PERMISSION_MODES.join(", ")}`);
291
210
  }
292
211
  }
293
212
  if (c.skills !== void 0) {
@@ -360,37 +279,9 @@ function validateAgentSkillConfig(agentName, agentSkills) {
360
279
  }
361
280
  return `agent_skills.${agentName} must be an array or object`;
362
281
  }
363
- function isSimpleAgentSkills(value) {
364
- return Array.isArray(value);
365
- }
366
- function normalizeSkillEntry(entry) {
367
- if (typeof entry === "string") {
368
- return { id: entry };
369
- }
370
- return entry;
371
- }
372
- function normalizeAgentSkills(agentSkills) {
373
- const result = {};
374
- for (const [agentName, skills] of Object.entries(agentSkills)) {
375
- if (isSimpleAgentSkills(skills)) {
376
- result[agentName] = {
377
- uncategorized: skills.map(normalizeSkillEntry)
378
- };
379
- } else {
380
- result[agentName] = {};
381
- for (const [category, categorySkills] of Object.entries(skills)) {
382
- result[agentName][category] = categorySkills.map(normalizeSkillEntry);
383
- }
384
- }
385
- }
386
- return result;
387
- }
388
282
 
389
283
  export {
390
284
  loadProjectConfig,
391
- isLegacyStackConfig,
392
- normalizeStackConfig,
393
- validateProjectConfig,
394
- normalizeAgentSkills
285
+ validateProjectConfig
395
286
  };
396
- //# sourceMappingURL=chunk-ZFPSUQOU.js.map
287
+ //# sourceMappingURL=chunk-VFHWU7JU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/project-config.ts"],"sourcesContent":["import path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { readFile, fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR } from \"../consts\";\nimport type {\n ProjectConfig,\n SkillAssignment,\n SkillEntry,\n AgentSkillConfig,\n ValidationResult,\n CustomAgentConfig,\n} from \"../../types\";\n\nconst CONFIG_PATH = `${CLAUDE_SRC_DIR}/config.yaml`;\nconst LEGACY_CONFIG_PATH = `${CLAUDE_DIR}/config.yaml`;\n\nexport interface LoadedProjectConfig {\n config: ProjectConfig;\n configPath: string;\n /** true if was StackConfig format (legacy) */\n isLegacy: boolean;\n}\n\n/**\n * Load project config from .claude-src/config.yaml (with fallback to .claude/config.yaml)\n */\nexport async function loadProjectConfig(projectDir: string): Promise<LoadedProjectConfig | null> {\n // Check .claude-src/config.yaml first (new location)\n const srcConfigPath = path.join(projectDir, CONFIG_PATH);\n // Fall back to .claude/config.yaml (legacy location)\n const legacyConfigPath = path.join(projectDir, LEGACY_CONFIG_PATH);\n\n let configPath = srcConfigPath;\n if (!(await fileExists(srcConfigPath))) {\n if (await fileExists(legacyConfigPath)) {\n configPath = legacyConfigPath;\n verbose(`Using legacy config location: ${legacyConfigPath}`);\n } else {\n verbose(`Project config not found at ${srcConfigPath} or ${legacyConfigPath}`);\n return null;\n }\n }\n\n try {\n const content = await readFile(configPath);\n const parsed = parseYaml(content);\n\n if (!parsed || typeof parsed !== \"object\") {\n verbose(`Invalid project config structure at ${configPath}`);\n return null;\n }\n\n verbose(`Loaded project config from ${configPath}`);\n return {\n config: parsed as ProjectConfig,\n configPath,\n isLegacy: false,\n };\n } catch (error) {\n verbose(`Failed to parse project config: ${error}`);\n return null;\n }\n}\n\n/**\n * Validate project config structure.\n * Returns validation result with errors and warnings.\n */\nexport function validateProjectConfig(config: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!config || typeof config !== \"object\") {\n return { valid: false, errors: [\"Config must be an object\"], warnings: [] };\n }\n\n const c = config as Record<string, unknown>;\n\n // Required: name\n if (!c.name || typeof c.name !== \"string\") {\n errors.push(\"name is required and must be a string\");\n }\n\n // Required: agents (for compilation)\n if (!c.agents || !Array.isArray(c.agents)) {\n errors.push(\"agents is required and must be an array\");\n } else {\n for (const agent of c.agents) {\n if (typeof agent !== \"string\") {\n errors.push(`agents must contain strings, found: ${typeof agent}`);\n }\n }\n }\n\n // Optional: version\n if (c.version !== undefined && c.version !== \"1\") {\n errors.push('version must be \"1\" (or omitted for default)');\n }\n\n // Optional: skills\n if (c.skills !== undefined) {\n if (!Array.isArray(c.skills)) {\n errors.push(\"skills must be an array\");\n } else {\n for (const skill of c.skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n errors.push(skillError);\n }\n }\n }\n }\n\n // Optional: agent_skills\n if (c.agent_skills !== undefined) {\n if (typeof c.agent_skills !== \"object\" || c.agent_skills === null) {\n errors.push(\"agent_skills must be an object\");\n } else {\n for (const [agentName, agentSkills] of Object.entries(c.agent_skills)) {\n const agentSkillsError = validateAgentSkillConfig(agentName, agentSkills);\n if (agentSkillsError) {\n errors.push(agentSkillsError);\n }\n }\n }\n }\n\n // Optional: preload_patterns\n if (c.preload_patterns !== undefined) {\n if (typeof c.preload_patterns !== \"object\" || c.preload_patterns === null) {\n errors.push(\"preload_patterns must be an object\");\n } else {\n for (const [agentName, patterns] of Object.entries(c.preload_patterns)) {\n if (!Array.isArray(patterns)) {\n errors.push(`preload_patterns.${agentName} must be an array of strings`);\n } else {\n for (const pattern of patterns) {\n if (typeof pattern !== \"string\") {\n errors.push(`preload_patterns.${agentName} must contain only strings`);\n break;\n }\n }\n }\n }\n }\n }\n\n // Optional: custom_agents\n if (c.custom_agents !== undefined) {\n const customAgentsErrors = validateCustomAgents(c.custom_agents, c.agents);\n errors.push(...customAgentsErrors);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/** Maximum number of custom agents allowed per project */\nconst MAX_CUSTOM_AGENTS = 20;\n\n/** Valid model values for custom agents */\nconst VALID_MODELS = [\"sonnet\", \"opus\", \"haiku\", \"inherit\"];\n\n/** Valid permission modes for custom agents */\nconst VALID_PERMISSION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"dontAsk\",\n \"bypassPermissions\",\n \"plan\",\n \"delegate\",\n];\n\n/**\n * Validate custom_agents section of config\n */\nfunction validateCustomAgents(customAgents: unknown, agents: unknown): string[] {\n const errors: string[] = [];\n\n if (typeof customAgents !== \"object\" || customAgents === null) {\n errors.push(\"custom_agents must be an object\");\n return errors;\n }\n\n const customAgentEntries = Object.entries(customAgents);\n\n // Check maximum limit\n if (customAgentEntries.length > MAX_CUSTOM_AGENTS) {\n errors.push(\n `custom_agents cannot exceed ${MAX_CUSTOM_AGENTS} agents (found ${customAgentEntries.length})`,\n );\n }\n\n // Collect custom agent names for circular reference check\n const customAgentNames = new Set(customAgentEntries.map(([name]) => name));\n\n for (const [agentName, agentConfig] of customAgentEntries) {\n const agentErrors = validateCustomAgentConfig(agentName, agentConfig, customAgentNames);\n errors.push(...agentErrors);\n }\n\n return errors;\n}\n\n/**\n * Validate a single custom agent configuration\n */\nfunction validateCustomAgentConfig(\n agentName: string,\n config: unknown,\n customAgentNames: Set<string>,\n): string[] {\n const errors: string[] = [];\n const prefix = `custom_agents.${agentName}`;\n\n if (typeof config !== \"object\" || config === null) {\n errors.push(`${prefix} must be an object`);\n return errors;\n }\n\n const c = config as Record<string, unknown>;\n\n // Required: title\n if (!c.title || typeof c.title !== \"string\") {\n errors.push(`${prefix}.title is required and must be a string`);\n }\n\n // Required: description\n if (!c.description || typeof c.description !== \"string\") {\n errors.push(`${prefix}.description is required and must be a string`);\n }\n\n // Optional: extends\n if (c.extends !== undefined) {\n if (typeof c.extends !== \"string\") {\n errors.push(`${prefix}.extends must be a string`);\n } else if (customAgentNames.has(c.extends)) {\n // Custom agents cannot extend other custom agents\n errors.push(`${prefix}.extends cannot reference another custom agent \"${c.extends}\"`);\n }\n }\n\n // Optional: model\n if (c.model !== undefined) {\n if (typeof c.model !== \"string\" || !VALID_MODELS.includes(c.model)) {\n errors.push(`${prefix}.model must be one of: ${VALID_MODELS.join(\", \")}`);\n }\n }\n\n // Optional: tools\n if (c.tools !== undefined) {\n if (!Array.isArray(c.tools)) {\n errors.push(`${prefix}.tools must be an array`);\n } else {\n for (const tool of c.tools) {\n if (typeof tool !== \"string\") {\n errors.push(`${prefix}.tools must contain only strings`);\n break;\n }\n }\n }\n }\n\n // Optional: disallowed_tools\n if (c.disallowed_tools !== undefined) {\n if (!Array.isArray(c.disallowed_tools)) {\n errors.push(`${prefix}.disallowed_tools must be an array`);\n } else {\n for (const tool of c.disallowed_tools) {\n if (typeof tool !== \"string\") {\n errors.push(`${prefix}.disallowed_tools must contain only strings`);\n break;\n }\n }\n }\n }\n\n // Optional: permission_mode\n if (c.permission_mode !== undefined) {\n if (\n typeof c.permission_mode !== \"string\" ||\n !VALID_PERMISSION_MODES.includes(c.permission_mode)\n ) {\n errors.push(`${prefix}.permission_mode must be one of: ${VALID_PERMISSION_MODES.join(\", \")}`);\n }\n }\n\n // Optional: skills\n if (c.skills !== undefined) {\n if (!Array.isArray(c.skills)) {\n errors.push(`${prefix}.skills must be an array`);\n } else {\n for (const skill of c.skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n errors.push(`${prefix}.skills: ${skillError}`);\n }\n }\n }\n }\n\n // Optional: hooks\n if (c.hooks !== undefined) {\n if (typeof c.hooks !== \"object\" || c.hooks === null) {\n errors.push(`${prefix}.hooks must be an object`);\n }\n // Note: Detailed hook validation could be added later if needed\n }\n\n return errors;\n}\n\n/**\n * Validate a single skill entry\n */\nfunction validateSkillEntry(skill: unknown): string | null {\n if (typeof skill === \"string\") {\n return null; // String skill IDs are valid\n }\n\n if (typeof skill !== \"object\" || skill === null) {\n return \"skills must be strings or objects\";\n }\n\n const s = skill as Record<string, unknown>;\n\n if (!s.id || typeof s.id !== \"string\") {\n return \"skill object must have an id string\";\n }\n\n if (s.local === true && !s.path) {\n return `local skill \"${s.id}\" must have a path`;\n }\n\n if (s.preloaded !== undefined && typeof s.preloaded !== \"boolean\") {\n return `skill \"${s.id}\" preloaded must be a boolean`;\n }\n\n if (s.local !== undefined && typeof s.local !== \"boolean\") {\n return `skill \"${s.id}\" local must be a boolean`;\n }\n\n if (s.path !== undefined && typeof s.path !== \"string\") {\n return `skill \"${s.id}\" path must be a string`;\n }\n\n return null;\n}\n\n/**\n * Validate agent skill config (can be simple list or categorized)\n */\nfunction validateAgentSkillConfig(agentName: string, agentSkills: unknown): string | null {\n // Check if it's a simple list (array)\n if (Array.isArray(agentSkills)) {\n for (const skill of agentSkills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n return `agent_skills.${agentName}: ${skillError}`;\n }\n }\n return null;\n }\n\n // Check if it's categorized (object with array values)\n if (typeof agentSkills === \"object\" && agentSkills !== null) {\n for (const [category, skills] of Object.entries(agentSkills)) {\n if (!Array.isArray(skills)) {\n return `agent_skills.${agentName}.${category} must be an array`;\n }\n for (const skill of skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n return `agent_skills.${agentName}.${category}: ${skillError}`;\n }\n }\n }\n return null;\n }\n\n return `agent_skills.${agentName} must be an array or object`;\n}\n\n/**\n * Check if agent_skills value is in simple list format (array)\n */\nexport function isSimpleAgentSkills(value: unknown): value is SkillEntry[] {\n return Array.isArray(value);\n}\n\n/**\n * Normalize a skill entry to SkillAssignment\n */\nexport function normalizeSkillEntry(entry: SkillEntry): SkillAssignment {\n if (typeof entry === \"string\") {\n return { id: entry };\n }\n return entry;\n}\n\n/**\n * Normalize agent_skills to always be categorized format for internal use.\n * Simple lists are placed under an \"uncategorized\" key.\n */\nexport function normalizeAgentSkills(\n agentSkills: Record<string, AgentSkillConfig>,\n): Record<string, Record<string, SkillAssignment[]>> {\n const result: Record<string, Record<string, SkillAssignment[]>> = {};\n\n for (const [agentName, skills] of Object.entries(agentSkills)) {\n if (isSimpleAgentSkills(skills)) {\n // Simple list -> put under \"uncategorized\"\n result[agentName] = {\n uncategorized: skills.map(normalizeSkillEntry),\n };\n } else {\n // Already categorized -> normalize entries\n result[agentName] = {};\n for (const [category, categorySkills] of Object.entries(skills)) {\n result[agentName][category] = categorySkills.map(normalizeSkillEntry);\n }\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  ensureDir,
4
4
  writeFile
5
- } from "./chunk-TKFPKEV3.js";
5
+ } from "./chunk-AL74GBW4.js";
6
6
  import {
7
7
  DEFAULT_VERSION
8
- } from "./chunk-76DWXGQE.js";
8
+ } from "./chunk-FJFEKPXF.js";
9
9
  import {
10
10
  init_esm_shims
11
11
  } from "./chunk-DHET7RCE.js";
@@ -88,4 +88,4 @@ export {
88
88
  writePluginManifest,
89
89
  getPluginManifestPath
90
90
  };
91
- //# sourceMappingURL=chunk-GDH553MV.js.map
91
+ //# sourceMappingURL=chunk-VS4GVTZE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/plugin-manifest.ts"],"sourcesContent":["import path from \"path\";\nimport { ensureDir, writeFile } from \"../utils/fs\";\nimport { DEFAULT_VERSION } from \"../consts\";\nimport type { PluginManifest, PluginAuthor } from \"../../types\";\n\nconst DEFAULT_LICENSE = \"MIT\";\nconst PLUGIN_DIR_NAME = \".claude-plugin\";\nconst PLUGIN_MANIFEST_FILE = \"plugin.json\";\nconst SKILL_PLUGIN_PREFIX = \"skill-\";\n\nexport interface SkillManifestOptions {\n skillName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n}\n\nexport interface StackManifestOptions {\n stackName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n hasSkills?: boolean;\n hasAgents?: boolean;\n hasHooks?: boolean;\n}\n\nfunction buildAuthor(name?: string, email?: string): PluginAuthor | undefined {\n if (!name) {\n return undefined;\n }\n const author: PluginAuthor = { name };\n if (email) {\n author.email = email;\n }\n return author;\n}\n\nexport function generateSkillPluginManifest(options: SkillManifestOptions): PluginManifest {\n const manifest: PluginManifest = {\n name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n skills: \"./skills/\",\n };\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n return manifest;\n}\n\nexport function generateStackPluginManifest(options: StackManifestOptions): PluginManifest {\n const manifest: PluginManifest = {\n name: options.stackName,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n };\n\n if (options.hasSkills) {\n manifest.skills = \"./skills/\";\n }\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n // Note: Claude Code plugins don't support agents field in manifest\n // Agents are discovered from ./agents/ directory automatically\n\n if (options.hasHooks) {\n manifest.hooks = \"./hooks/hooks.json\";\n }\n\n return manifest;\n}\n\nexport async function writePluginManifest(\n outputDir: string,\n manifest: PluginManifest,\n): Promise<string> {\n const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);\n\n await ensureDir(pluginDir);\n\n const content = JSON.stringify(manifest, null, 2);\n await writeFile(manifestPath, content);\n\n return manifestPath;\n}\n\nexport function getPluginDir(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME);\n}\n\nexport function getPluginManifestPath(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AAKjB,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAuB5B,SAAS,YAAY,MAAe,OAA0C;AAC5E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,QAAM,SAAuB,EAAE,KAAK;AACpC,MAAI,OAAO;AACT,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAEO,SAAS,4BAA4B,SAA+C;AACzF,QAAM,WAA2B;AAAA,IAC/B,MAAM,GAAG,mBAAmB,GAAG,QAAQ,SAAS;AAAA,IAChD,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAEA,SAAO;AACT;AAEO,SAAS,4BAA4B,SAA+C;AACzF,QAAM,WAA2B;AAAA,IAC/B,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,EACX;AAEA,MAAI,QAAQ,WAAW;AACrB,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAKA,MAAI,QAAQ,UAAU;AACpB,aAAS,QAAQ;AAAA,EACnB;AAEA,SAAO;AACT;AAEA,eAAsB,oBACpB,WACA,UACiB;AACjB,QAAM,YAAY,KAAK,KAAK,WAAW,eAAe;AACtD,QAAM,eAAe,KAAK,KAAK,WAAW,oBAAoB;AAE9D,QAAM,UAAU,SAAS;AAEzB,QAAM,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC;AAChD,QAAM,UAAU,cAAc,OAAO;AAErC,SAAO;AACT;AAMO,SAAS,sBAAsB,WAA2B;AAC/D,SAAO,KAAK,KAAK,WAAW,iBAAiB,oBAAoB;AACnE;","names":[]}
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ViewTitle
4
+ } from "./chunk-Q3J43SF3.js";
5
+ import {
6
+ MenuItem
7
+ } from "./chunk-UMORK7OK.js";
8
+ import {
9
+ useWizardStore
10
+ } from "./chunk-CBLPAMZO.js";
11
+ import {
12
+ init_esm_shims
13
+ } from "./chunk-DHET7RCE.js";
14
+
15
+ // src/cli/components/wizard/step-approach.tsx
16
+ init_esm_shims();
17
+ import { useState } from "react";
18
+ import { Box, useInput } from "ink";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ var INITIAL_FOCUSED_INDEX = 0;
21
+ var APPROACH_OPTIONS = [
22
+ {
23
+ value: "stack",
24
+ label: "Use a pre-built template"
25
+ },
26
+ {
27
+ value: "scratch",
28
+ label: "Start from scratch"
29
+ }
30
+ ];
31
+ var StepApproach = () => {
32
+ const { setStep, setApproach } = useWizardStore();
33
+ const [focusedIndex, setFocusedIndex] = useState(INITIAL_FOCUSED_INDEX);
34
+ const optionCount = APPROACH_OPTIONS.length;
35
+ useInput((input, key) => {
36
+ if (key.return) {
37
+ const option = APPROACH_OPTIONS[focusedIndex];
38
+ if (option) {
39
+ if (option.value === "stack") {
40
+ setApproach("stack");
41
+ setStep("stack");
42
+ } else if (option.value === "scratch") {
43
+ setApproach("scratch");
44
+ setStep("stack");
45
+ }
46
+ }
47
+ return;
48
+ }
49
+ if (key.upArrow || input === "k") {
50
+ setFocusedIndex((prev) => (prev - 1 + optionCount) % optionCount);
51
+ return;
52
+ }
53
+ if (key.downArrow || input === "j") {
54
+ setFocusedIndex((prev) => (prev + 1) % optionCount);
55
+ return;
56
+ }
57
+ });
58
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
59
+ /* @__PURE__ */ jsx(ViewTitle, { children: "How would you like to set up your stack?" }),
60
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: APPROACH_OPTIONS.map((option, index) => /* @__PURE__ */ jsx(MenuItem, { label: option.label, isFocused: index === focusedIndex }, option.value)) })
61
+ ] });
62
+ };
63
+
64
+ export {
65
+ StepApproach
66
+ };
67
+ //# sourceMappingURL=chunk-WFEFICFM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/step-approach.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { Box, useInput } from \"ink\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport { MenuItem } from \"./menu-item.js\";\nimport { ViewTitle } from \"./view-title.js\";\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Initial focused index for approach options */\nconst INITIAL_FOCUSED_INDEX = 0;\n\n/** Approach options for the wizard intro step */\nconst APPROACH_OPTIONS = [\n {\n value: \"stack\",\n label: \"Use a pre-built template\",\n },\n {\n value: \"scratch\",\n label: \"Start from scratch\",\n },\n] as const;\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport const StepApproach: React.FC = () => {\n const { setStep, setApproach } = useWizardStore();\n const [focusedIndex, setFocusedIndex] = useState(INITIAL_FOCUSED_INDEX);\n\n const optionCount = APPROACH_OPTIONS.length;\n\n useInput((input, key) => {\n // Enter to select the focused option\n if (key.return) {\n const option = APPROACH_OPTIONS[focusedIndex];\n if (option) {\n if (option.value === \"stack\") {\n setApproach(\"stack\");\n setStep(\"stack\");\n } else if (option.value === \"scratch\") {\n setApproach(\"scratch\");\n setStep(\"stack\");\n }\n }\n return;\n }\n\n // Arrow key navigation (wrapping)\n if (key.upArrow || input === \"k\") {\n setFocusedIndex((prev) => (prev - 1 + optionCount) % optionCount);\n return;\n }\n if (key.downArrow || input === \"j\") {\n setFocusedIndex((prev) => (prev + 1) % optionCount);\n return;\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n <ViewTitle>How would you like to set up your stack?</ViewTitle>\n <Box flexDirection=\"column\" marginTop={1}>\n {APPROACH_OPTIONS.map((option, index) => (\n <MenuItem key={option.value} label={option.label} isFocused={index === focusedIndex} />\n ))}\n </Box>\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA,SAAgB,gBAAgB;AAChC,SAAS,KAAK,gBAAgB;AA8D1B,SACE,KADF;AApDJ,IAAM,wBAAwB;AAG9B,IAAM,mBAAmB;AAAA,EACvB;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AACF;AAMO,IAAM,eAAyB,MAAM;AAC1C,QAAM,EAAE,SAAS,YAAY,IAAI,eAAe;AAChD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,qBAAqB;AAEtE,QAAM,cAAc,iBAAiB;AAErC,WAAS,CAAC,OAAO,QAAQ;AAEvB,QAAI,IAAI,QAAQ;AACd,YAAM,SAAS,iBAAiB,YAAY;AAC5C,UAAI,QAAQ;AACV,YAAI,OAAO,UAAU,SAAS;AAC5B,sBAAY,OAAO;AACnB,kBAAQ,OAAO;AAAA,QACjB,WAAW,OAAO,UAAU,WAAW;AACrC,sBAAY,SAAS;AACrB,kBAAQ,OAAO;AAAA,QACjB;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,UAAU,KAAK;AAChC,sBAAgB,CAAC,UAAU,OAAO,IAAI,eAAe,WAAW;AAChE;AAAA,IACF;AACA,QAAI,IAAI,aAAa,UAAU,KAAK;AAClC,sBAAgB,CAAC,UAAU,OAAO,KAAK,WAAW;AAClD;AAAA,IACF;AAAA,EACF,CAAC;AAED,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,wBAAC,aAAU,sDAAwC;AAAA,IACnD,oBAAC,OAAI,eAAc,UAAS,WAAW,GACpC,2BAAiB,IAAI,CAAC,QAAQ,UAC7B,oBAAC,YAA4B,OAAO,OAAO,OAAO,WAAW,UAAU,gBAAxD,OAAO,KAA+D,CACtF,GACH;AAAA,KACF;AAEJ;","names":[]}
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  readFile,
4
4
  writeFile
5
- } from "./chunk-TKFPKEV3.js";
5
+ } from "./chunk-AL74GBW4.js";
6
6
  import {
7
7
  DEFAULT_VERSION,
8
8
  PLUGIN_MANIFEST_DIR,
9
9
  PLUGIN_MANIFEST_FILE
10
- } from "./chunk-76DWXGQE.js";
10
+ } from "./chunk-FJFEKPXF.js";
11
11
  import {
12
12
  init_esm_shims
13
13
  } from "./chunk-DHET7RCE.js";
@@ -20,16 +20,10 @@ function parseVersion(version) {
20
20
  return [parts[0] || 1, parts[1] || 0, parts[2] || 0];
21
21
  }
22
22
  async function bumpPluginVersion(pluginDir, type) {
23
- const manifestPath = path.join(
24
- pluginDir,
25
- PLUGIN_MANIFEST_DIR,
26
- PLUGIN_MANIFEST_FILE
27
- );
23
+ const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);
28
24
  const content = await readFile(manifestPath);
29
25
  const manifest = JSON.parse(content);
30
- const [major, minor, patch] = parseVersion(
31
- manifest.version || DEFAULT_VERSION
32
- );
26
+ const [major, minor, patch] = parseVersion(manifest.version || DEFAULT_VERSION);
33
27
  let newVersion;
34
28
  switch (type) {
35
29
  case "major":
@@ -47,11 +41,7 @@ async function bumpPluginVersion(pluginDir, type) {
47
41
  return newVersion;
48
42
  }
49
43
  async function getPluginVersion(pluginDir) {
50
- const manifestPath = path.join(
51
- pluginDir,
52
- PLUGIN_MANIFEST_DIR,
53
- PLUGIN_MANIFEST_FILE
54
- );
44
+ const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);
55
45
  const content = await readFile(manifestPath);
56
46
  const manifest = JSON.parse(content);
57
47
  return manifest.version || DEFAULT_VERSION;
@@ -61,4 +51,4 @@ export {
61
51
  bumpPluginVersion,
62
52
  getPluginVersion
63
53
  };
64
- //# sourceMappingURL=chunk-P26A2K5N.js.map
54
+ //# sourceMappingURL=chunk-WG6KIAPK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/plugin-version.ts"],"sourcesContent":["import path from \"path\";\nimport { readFile, writeFile } from \"../utils/fs\";\nimport { PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE, DEFAULT_VERSION } from \"../consts\";\nimport type { PluginManifest } from \"../../types\";\n\nexport type VersionBumpType = \"major\" | \"minor\" | \"patch\";\n\nfunction parseVersion(version: string): [number, number, number] {\n const parts = version.split(\".\").map(Number);\n return [parts[0] || 1, parts[1] || 0, parts[2] || 0];\n}\n\nexport async function bumpPluginVersion(pluginDir: string, type: VersionBumpType): Promise<string> {\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n const content = await readFile(manifestPath);\n const manifest = JSON.parse(content) as PluginManifest;\n\n const [major, minor, patch] = parseVersion(manifest.version || DEFAULT_VERSION);\n\n let newVersion: string;\n switch (type) {\n case \"major\":\n newVersion = `${major + 1}.0.0`;\n break;\n case \"minor\":\n newVersion = `${major}.${minor + 1}.0`;\n break;\n case \"patch\":\n newVersion = `${major}.${minor}.${patch + 1}`;\n break;\n }\n\n manifest.version = newVersion;\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n\n return newVersion;\n}\n\nexport async function getPluginVersion(pluginDir: string): Promise<string> {\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n const content = await readFile(manifestPath);\n const manifest = JSON.parse(content) as PluginManifest;\n return manifest.version || DEFAULT_VERSION;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AAOjB,SAAS,aAAa,SAA2C;AAC/D,QAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AAC3C,SAAO,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;AACrD;AAEA,eAAsB,kBAAkB,WAAmB,MAAwC;AACjG,QAAM,eAAe,KAAK,KAAK,WAAW,qBAAqB,oBAAoB;AACnF,QAAM,UAAU,MAAM,SAAS,YAAY;AAC3C,QAAM,WAAW,KAAK,MAAM,OAAO;AAEnC,QAAM,CAAC,OAAO,OAAO,KAAK,IAAI,aAAa,SAAS,WAAW,eAAe;AAE9E,MAAI;AACJ,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,mBAAa,GAAG,QAAQ,CAAC;AACzB;AAAA,IACF,KAAK;AACH,mBAAa,GAAG,KAAK,IAAI,QAAQ,CAAC;AAClC;AAAA,IACF,KAAK;AACH,mBAAa,GAAG,KAAK,IAAI,KAAK,IAAI,QAAQ,CAAC;AAC3C;AAAA,EACJ;AAEA,WAAS,UAAU;AACnB,QAAM,UAAU,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAE/D,SAAO;AACT;AAEA,eAAsB,iBAAiB,WAAoC;AACzE,QAAM,eAAe,KAAK,KAAK,WAAW,qBAAqB,oBAAoB;AACnF,QAAM,UAAU,MAAM,SAAS,YAAY;AAC3C,QAAM,WAAW,KAAK,MAAM,OAAO;AACnC,SAAO,SAAS,WAAW;AAC7B;","names":[]}
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- WizardFooter
4
- } from "./chunk-Y2LW7R3Y.js";
5
2
  import {
6
3
  init_esm_shims
7
4
  } from "./chunk-DHET7RCE.js";
@@ -13,6 +10,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
13
10
  var formatDomainName = (domain) => {
14
11
  const names = {
15
12
  web: "Web",
13
+ "web-extras": "Web Extras",
16
14
  api: "API",
17
15
  cli: "CLI",
18
16
  mobile: "Mobile"
@@ -74,13 +72,11 @@ var StepConfirm = ({
74
72
  " ",
75
73
  /* @__PURE__ */ jsx(Text, { bold: true, children: installMode === "plugin" ? "Plugin" : "Local" })
76
74
  ] })
77
- ] }),
78
- /* @__PURE__ */ jsx(Text, { children: " " }),
79
- /* @__PURE__ */ jsx(WizardFooter, { navigation: "ENTER confirm", action: "ESC back" })
75
+ ] })
80
76
  ] });
81
77
  };
82
78
 
83
79
  export {
84
80
  StepConfirm
85
81
  };
86
- //# sourceMappingURL=chunk-X6QONICW.js.map
82
+ //# sourceMappingURL=chunk-ZEI3ZUDU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/step-confirm.tsx"],"sourcesContent":["import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { MergedSkillsMatrix } from \"../../types-matrix.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StepConfirmProps {\n matrix: MergedSkillsMatrix;\n onComplete: () => void;\n stackName?: string;\n selectedDomains?: string[];\n domainSelections?: Record<string, Record<string, string[]>>;\n technologyCount?: number;\n skillCount?: number;\n installMode?: \"plugin\" | \"local\";\n onBack?: () => void;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Format domain name for display.\n */\nconst formatDomainName = (domain: string): string => {\n const names: Record<string, string> = {\n web: \"Web\",\n \"web-extras\": \"Web Extras\",\n api: \"API\",\n cli: \"CLI\",\n mobile: \"Mobile\",\n };\n return names[domain] || domain.charAt(0).toUpperCase() + domain.slice(1);\n};\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport const StepConfirm: React.FC<StepConfirmProps> = ({\n matrix,\n onComplete,\n stackName,\n selectedDomains,\n domainSelections,\n technologyCount,\n skillCount,\n installMode,\n onBack,\n}) => {\n useInput((input, key) => {\n if (key.return) {\n onComplete();\n }\n if (key.escape && onBack) {\n onBack();\n }\n });\n\n // Build title based on stack vs scratch path\n const domainsText = selectedDomains?.map(formatDomainName).join(\" + \") || \"\";\n const title = stackName\n ? `Ready to install ${stackName}`\n : `Ready to install your custom stack${domainsText ? ` (${domainsText})` : \"\"}`;\n\n return (\n <Box flexDirection=\"column\" paddingX={2}>\n <Text bold color=\"green\">\n {title}\n </Text>\n <Text> </Text>\n\n {/* Domain breakdown (for scratch path) */}\n {domainSelections && selectedDomains && !stackName && (\n <Box flexDirection=\"column\" marginBottom={1}>\n {selectedDomains.map((domain) => {\n const selections = domainSelections[domain] || {};\n const techs = Object.values(selections).flat();\n if (techs.length === 0) return null;\n return (\n <Text key={domain}>\n <Text bold>{formatDomainName(domain)}:</Text> <Text>{techs.join(\", \")}</Text>\n </Text>\n );\n })}\n </Box>\n )}\n\n {/* Summary stats */}\n <Box flexDirection=\"column\" marginY={1}>\n {technologyCount !== undefined && (\n <Text>\n <Text dimColor>Technologies:</Text> <Text bold>{technologyCount}</Text>\n </Text>\n )}\n {skillCount !== undefined && (\n <Text>\n <Text dimColor>Skills:</Text> <Text bold>{skillCount}</Text>{\" \"}\n <Text color=\"green\">(all verified)</Text>\n </Text>\n )}\n {installMode && (\n <Text>\n <Text dimColor>Install mode:</Text>{\" \"}\n <Text bold>{installMode === \"plugin\" ? \"Plugin\" : \"Local\"}</Text>\n </Text>\n )}\n </Box>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AACA,SAAS,KAAK,MAAM,gBAAgB;AAqE9B,cAcU,YAdV;AA3CN,IAAM,mBAAmB,CAAC,WAA2B;AACnD,QAAM,QAAgC;AAAA,IACpC,KAAK;AAAA,IACL,cAAc;AAAA,IACd,KAAK;AAAA,IACL,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACA,SAAO,MAAM,MAAM,KAAK,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AACzE;AAMO,IAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,iBAAW;AAAA,IACb;AACA,QAAI,IAAI,UAAU,QAAQ;AACxB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAGD,QAAM,cAAc,iBAAiB,IAAI,gBAAgB,EAAE,KAAK,KAAK,KAAK;AAC1E,QAAM,QAAQ,YACV,oBAAoB,SAAS,KAC7B,qCAAqC,cAAc,KAAK,WAAW,MAAM,EAAE;AAE/E,SACE,qBAAC,OAAI,eAAc,UAAS,UAAU,GACpC;AAAA,wBAAC,QAAK,MAAI,MAAC,OAAM,SACd,iBACH;AAAA,IACA,oBAAC,QAAK,eAAC;AAAA,IAGN,oBAAoB,mBAAmB,CAAC,aACvC,oBAAC,OAAI,eAAc,UAAS,cAAc,GACvC,0BAAgB,IAAI,CAAC,WAAW;AAC/B,YAAM,aAAa,iBAAiB,MAAM,KAAK,CAAC;AAChD,YAAM,QAAQ,OAAO,OAAO,UAAU,EAAE,KAAK;AAC7C,UAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,aACE,qBAAC,QACC;AAAA,6BAAC,QAAK,MAAI,MAAE;AAAA,2BAAiB,MAAM;AAAA,UAAE;AAAA,WAAC;AAAA,QAAO;AAAA,QAAC,oBAAC,QAAM,gBAAM,KAAK,IAAI,GAAE;AAAA,WAD7D,MAEX;AAAA,IAEJ,CAAC,GACH;AAAA,IAIF,qBAAC,OAAI,eAAc,UAAS,SAAS,GAClC;AAAA,0BAAoB,UACnB,qBAAC,QACC;AAAA,4BAAC,QAAK,UAAQ,MAAC,2BAAa;AAAA,QAAO;AAAA,QAAC,oBAAC,QAAK,MAAI,MAAE,2BAAgB;AAAA,SAClE;AAAA,MAED,eAAe,UACd,qBAAC,QACC;AAAA,4BAAC,QAAK,UAAQ,MAAC,qBAAO;AAAA,QAAO;AAAA,QAAC,oBAAC,QAAK,MAAI,MAAE,sBAAW;AAAA,QAAQ;AAAA,QAC7D,oBAAC,QAAK,OAAM,SAAQ,4BAAc;AAAA,SACpC;AAAA,MAED,eACC,qBAAC,QACC;AAAA,4BAAC,QAAK,UAAQ,MAAC,2BAAa;AAAA,QAAQ;AAAA,QACpC,oBAAC,QAAK,MAAI,MAAE,0BAAgB,WAAW,WAAW,SAAQ;AAAA,SAC5D;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-DHET7RCE.js";
5
+
6
+ // src/cli/components/wizard/wizard-tabs.tsx
7
+ init_esm_shims();
8
+ import { Box, Text } from "ink";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var WIZARD_STEPS = [
11
+ { id: "approach", label: "Intro", number: 1 },
12
+ { id: "stack", label: "Stack", number: 2 },
13
+ { id: "build", label: "Build", number: 3 },
14
+ { id: "confirm", label: "Confirm", number: 4 }
15
+ ];
16
+ var getStepState = (stepId, currentStep, completedSteps, skippedSteps) => {
17
+ if (completedSteps.includes(stepId)) return "completed";
18
+ if (stepId === currentStep) return "current";
19
+ if (skippedSteps.includes(stepId)) return "skipped";
20
+ return "pending";
21
+ };
22
+ var Tab = ({ step, state }) => {
23
+ const label = `[${step.number}] ${step.label}`;
24
+ switch (state) {
25
+ case "current":
26
+ return /* @__PURE__ */ jsx(Text, { color: "cyan", children: label });
27
+ case "completed":
28
+ return /* @__PURE__ */ jsx(Text, { children: label });
29
+ case "skipped":
30
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: label });
31
+ case "pending":
32
+ default:
33
+ return /* @__PURE__ */ jsx(Text, { color: "white", children: label });
34
+ }
35
+ };
36
+ var WizardTabs = ({
37
+ steps,
38
+ currentStep,
39
+ completedSteps,
40
+ skippedSteps = [],
41
+ version
42
+ }) => {
43
+ return /* @__PURE__ */ jsxs(
44
+ Box,
45
+ {
46
+ flexDirection: "row",
47
+ columnGap: 2,
48
+ borderRight: false,
49
+ borderLeft: false,
50
+ borderColor: "blackBright",
51
+ borderStyle: "single",
52
+ paddingRight: 1,
53
+ children: [
54
+ steps.map((step) => {
55
+ const state = getStepState(step.id, currentStep, completedSteps, skippedSteps);
56
+ return /* @__PURE__ */ jsx(Tab, { step, state }, step.id);
57
+ }),
58
+ /* @__PURE__ */ jsx(Box, { flexGrow: 1, justifyContent: "flex-end", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: `v${version}` }) })
59
+ ]
60
+ }
61
+ );
62
+ };
63
+
64
+ export {
65
+ WIZARD_STEPS,
66
+ WizardTabs
67
+ };
68
+ //# sourceMappingURL=chunk-ZNIDWLL5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/wizard-tabs.tsx"],"sourcesContent":["import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface WizardTabStep {\n id: string;\n label: string;\n number: number;\n}\n\nexport interface WizardTabsProps {\n steps: WizardTabStep[];\n currentStep: string;\n completedSteps: string[];\n skippedSteps?: string[];\n version?: string;\n}\n\nexport const WIZARD_STEPS: WizardTabStep[] = [\n { id: \"approach\", label: \"Intro\", number: 1 },\n { id: \"stack\", label: \"Stack\", number: 2 },\n { id: \"build\", label: \"Build\", number: 3 },\n { id: \"confirm\", label: \"Confirm\", number: 4 },\n];\n\ntype StepState = \"completed\" | \"current\" | \"pending\" | \"skipped\";\n\nconst getStepState = (\n stepId: string,\n currentStep: string,\n completedSteps: string[],\n skippedSteps: string[],\n): StepState => {\n if (completedSteps.includes(stepId)) return \"completed\";\n if (stepId === currentStep) return \"current\";\n if (skippedSteps.includes(stepId)) return \"skipped\";\n return \"pending\";\n};\n\ninterface TabProps {\n step: WizardTabStep;\n state: StepState;\n}\n\nconst Tab: React.FC<TabProps> = ({ step, state }) => {\n const label = `[${step.number}] ${step.label}`;\n\n switch (state) {\n case \"current\":\n return <Text color=\"cyan\">{label}</Text>;\n case \"completed\":\n return <Text>{label}</Text>;\n case \"skipped\":\n return <Text dimColor>{label}</Text>;\n case \"pending\":\n default:\n return <Text color=\"white\">{label}</Text>;\n }\n};\n\nexport const WizardTabs: React.FC<WizardTabsProps> = ({\n steps,\n currentStep,\n completedSteps,\n skippedSteps = [],\n version,\n}) => {\n return (\n <Box\n flexDirection=\"row\"\n columnGap={2}\n borderRight={false}\n borderLeft={false}\n borderColor=\"blackBright\"\n borderStyle=\"single\"\n paddingRight={1}\n >\n {steps.map((step) => {\n const state = getStepState(step.id, currentStep, completedSteps, skippedSteps);\n\n return <Tab key={step.id} step={step} state={state} />;\n })}\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text dimColor>{`v${version}`}</Text>\n </Box>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AACA,SAAS,KAAK,YAAY;AA+Cb,cAmBT,YAnBS;AA/BN,IAAM,eAAgC;AAAA,EAC3C,EAAE,IAAI,YAAY,OAAO,SAAS,QAAQ,EAAE;AAAA,EAC5C,EAAE,IAAI,SAAS,OAAO,SAAS,QAAQ,EAAE;AAAA,EACzC,EAAE,IAAI,SAAS,OAAO,SAAS,QAAQ,EAAE;AAAA,EACzC,EAAE,IAAI,WAAW,OAAO,WAAW,QAAQ,EAAE;AAC/C;AAIA,IAAM,eAAe,CACnB,QACA,aACA,gBACA,iBACc;AACd,MAAI,eAAe,SAAS,MAAM,EAAG,QAAO;AAC5C,MAAI,WAAW,YAAa,QAAO;AACnC,MAAI,aAAa,SAAS,MAAM,EAAG,QAAO;AAC1C,SAAO;AACT;AAOA,IAAM,MAA0B,CAAC,EAAE,MAAM,MAAM,MAAM;AACnD,QAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,KAAK,KAAK;AAE5C,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,oBAAC,QAAK,OAAM,QAAQ,iBAAM;AAAA,IACnC,KAAK;AACH,aAAO,oBAAC,QAAM,iBAAM;AAAA,IACtB,KAAK;AACH,aAAO,oBAAC,QAAK,UAAQ,MAAE,iBAAM;AAAA,IAC/B,KAAK;AAAA,IACL;AACE,aAAO,oBAAC,QAAK,OAAM,SAAS,iBAAM;AAAA,EACtC;AACF;AAEO,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,CAAC;AAAA,EAChB;AACF,MAAM;AACJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,WAAW;AAAA,MACX,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,cAAc;AAAA,MAEb;AAAA,cAAM,IAAI,CAAC,SAAS;AACnB,gBAAM,QAAQ,aAAa,KAAK,IAAI,aAAa,gBAAgB,YAAY;AAE7E,iBAAO,oBAAC,OAAkB,MAAY,SAArB,KAAK,EAA8B;AAAA,QACtD,CAAC;AAAA,QACD,oBAAC,OAAI,UAAU,GAAG,gBAAe,YAC/B,8BAAC,QAAK,UAAQ,MAAE,cAAI,OAAO,IAAG,GAChC;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-DHET7RCE.js";
5
+
6
+ // src/cli/components/wizard/section-progress.tsx
7
+ init_esm_shims();
8
+ import { Box, Text } from "ink";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var SectionProgress = ({
11
+ label,
12
+ current,
13
+ index,
14
+ total,
15
+ next
16
+ }) => {
17
+ const isLast = index === total;
18
+ const rightText = isLast ? "Last step" : `Next: ${next}`;
19
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [
20
+ /* @__PURE__ */ jsxs(Text, { children: [
21
+ /* @__PURE__ */ jsxs(Text, { bold: true, children: [
22
+ label,
23
+ ":"
24
+ ] }),
25
+ " ",
26
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: current })
27
+ ] }),
28
+ /* @__PURE__ */ jsxs(Text, { children: [
29
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
30
+ "[",
31
+ index,
32
+ "/",
33
+ total,
34
+ "]"
35
+ ] }),
36
+ " ",
37
+ /* @__PURE__ */ jsx(Text, { dimColor: isLast, children: rightText })
38
+ ] })
39
+ ] });
40
+ };
41
+
42
+ export {
43
+ SectionProgress
44
+ };
45
+ //# sourceMappingURL=chunk-ZSVMS677.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/section-progress.tsx"],"sourcesContent":["import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface SectionProgressProps {\n /** Section label (e.g., \"Domain\" or \"Skill\") */\n label: string;\n /** Current item name (e.g., \"Web\" or \"react\") */\n current: string;\n /** 1-based index */\n index: number;\n /** Total count */\n total: number;\n /** Next item name, or undefined if last */\n next?: string;\n}\n\nexport const SectionProgress: React.FC<SectionProgressProps> = ({\n label,\n current,\n index,\n total,\n next,\n}) => {\n const isLast = index === total;\n const rightText = isLast ? \"Last step\" : `Next: ${next}`;\n\n return (\n <Box flexDirection=\"row\" justifyContent=\"space-between\" marginBottom={1}>\n <Text>\n <Text bold>{label}:</Text> <Text color=\"cyan\">{current}</Text>\n </Text>\n <Text>\n <Text dimColor>\n [{index}/{total}]\n </Text>{\" \"}\n <Text dimColor={isLast}>{rightText}</Text>\n </Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AACA,SAAS,KAAK,YAAY;AA4BlB,SAA2B,KAA3B;AAbD,IAAM,kBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,SAAS,cAAc,SAAS,IAAI;AAEtD,SACE,qBAAC,OAAI,eAAc,OAAM,gBAAe,iBAAgB,cAAc,GACpE;AAAA,yBAAC,QACC;AAAA,2BAAC,QAAK,MAAI,MAAE;AAAA;AAAA,QAAM;AAAA,SAAC;AAAA,MAAO;AAAA,MAAC,oBAAC,QAAK,OAAM,QAAQ,mBAAQ;AAAA,OACzD;AAAA,IACA,qBAAC,QACC;AAAA,2BAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QACX;AAAA,QAAM;AAAA,QAAE;AAAA,QAAM;AAAA,SAClB;AAAA,MAAQ;AAAA,MACR,oBAAC,QAAK,UAAU,QAAS,qBAAU;AAAA,OACrC;AAAA,KACF;AAEJ;","names":[]}