@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,36 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- compileAgentForPlugin
4
- } from "./chunk-DRXPNNPB.js";
5
- import {
3
+ compileAgentForPlugin,
6
4
  createLiquidEngine,
7
5
  resolveAgents,
8
6
  resolveStackSkills
9
- } from "./chunk-I4TPKIYX.js";
7
+ } from "./chunk-7SLV7CMF.js";
10
8
  import {
11
9
  getPluginAgentsDir
12
- } from "./chunk-ED4E6Q2T.js";
10
+ } from "./chunk-HPGFY5ZN.js";
13
11
  import {
14
- isLegacyStackConfig,
15
- loadProjectConfig,
16
- normalizeAgentSkills,
17
- normalizeStackConfig
18
- } from "./chunk-ZFPSUQOU.js";
12
+ loadProjectConfig
13
+ } from "./chunk-VFHWU7JU.js";
19
14
  import {
20
15
  loadAllAgents,
21
16
  loadPluginSkills,
22
17
  loadProjectAgents
23
- } from "./chunk-B7CCVP6Q.js";
18
+ } from "./chunk-BQX23RBV.js";
24
19
  import {
25
20
  verbose
26
- } from "./chunk-3U3R4NCG.js";
21
+ } from "./chunk-T25OEQFI.js";
27
22
  import {
28
23
  ensureDir,
29
24
  fileExists,
30
25
  glob,
31
26
  readFile,
32
27
  writeFile
33
- } from "./chunk-TKFPKEV3.js";
28
+ } from "./chunk-AL74GBW4.js";
34
29
  import {
35
30
  init_esm_shims
36
31
  } from "./chunk-DHET7RCE.js";
@@ -127,14 +122,6 @@ async function loadConfigWithFallback(pluginDir) {
127
122
  const parsed = parseYaml(content);
128
123
  if (parsed && typeof parsed === "object") {
129
124
  verbose(`Loaded config.yaml from ${legacyConfigPath}`);
130
- if (isLegacyStackConfig(parsed)) {
131
- const normalized = normalizeStackConfig(parsed);
132
- return {
133
- config: normalized,
134
- configPath: legacyConfigPath,
135
- isLegacy: true
136
- };
137
- }
138
125
  return {
139
126
  config: parsed,
140
127
  configPath: legacyConfigPath,
@@ -147,22 +134,6 @@ async function loadConfigWithFallback(pluginDir) {
147
134
  }
148
135
  return loadProjectConfig(pluginDir);
149
136
  }
150
- function projectConfigToStackLike(config) {
151
- return {
152
- name: config.name,
153
- version: "1.0.0",
154
- author: config.author ?? "@unknown",
155
- description: config.description,
156
- skills: config.skills?.map((s) => typeof s === "string" ? { id: s } : s) ?? [],
157
- agents: config.agents,
158
- agent_skills: config.agent_skills ? normalizeAgentSkills(config.agent_skills) : void 0,
159
- hooks: config.hooks,
160
- framework: config.framework,
161
- philosophy: config.philosophy,
162
- principles: config.principles,
163
- tags: config.tags
164
- };
165
- }
166
137
  async function recompileAgents(options) {
167
138
  const {
168
139
  pluginDir,
@@ -189,36 +160,27 @@ async function recompileAgents(options) {
189
160
  ...projectAgents
190
161
  };
191
162
  if (projectConfig?.custom_agents) {
192
- const idConflicts = validateCustomAgentIds(
193
- projectConfig.custom_agents,
194
- builtinAgents
195
- );
163
+ const idConflicts = validateCustomAgentIds(projectConfig.custom_agents, builtinAgents);
196
164
  if (idConflicts.length > 0) {
197
165
  for (const error of idConflicts) {
198
166
  result.warnings.push(error);
199
167
  }
200
168
  }
201
169
  try {
202
- const resolvedCustomAgents = resolveCustomAgents(
203
- projectConfig.custom_agents,
204
- builtinAgents
205
- );
170
+ const resolvedCustomAgents = resolveCustomAgents(projectConfig.custom_agents, builtinAgents);
206
171
  allAgents = { ...builtinAgents, ...resolvedCustomAgents };
207
- verbose(
208
- `Resolved ${Object.keys(resolvedCustomAgents).length} custom agents`
209
- );
172
+ verbose(`Resolved ${Object.keys(resolvedCustomAgents).length} custom agents`);
210
173
  } catch (error) {
211
174
  result.warnings.push(
212
175
  `Failed to resolve custom agents: ${error instanceof Error ? error.message : String(error)}`
213
176
  );
214
177
  }
215
178
  }
216
- const pluginConfig = projectConfig ? projectConfigToStackLike(projectConfig) : null;
217
179
  let agentNames;
218
180
  if (specifiedAgents) {
219
181
  agentNames = specifiedAgents;
220
- } else if (pluginConfig?.agents) {
221
- agentNames = pluginConfig.agents;
182
+ } else if (projectConfig?.agents) {
183
+ agentNames = projectConfig.agents;
222
184
  verbose(`Using agents from config.yaml: ${agentNames.join(", ")}`);
223
185
  } else if (outputDir) {
224
186
  agentNames = Object.keys(allAgents);
@@ -230,74 +192,56 @@ async function recompileAgents(options) {
230
192
  result.warnings.push("No agents found to recompile");
231
193
  return result;
232
194
  }
233
- verbose(
234
- `Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`
235
- );
195
+ verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);
236
196
  const pluginSkills = providedSkills ?? await loadPluginSkills(pluginDir);
237
197
  const compileAgents = {};
238
198
  for (const agentName of agentNames) {
239
199
  if (allAgents[agentName]) {
240
200
  const customAgentConfig = projectConfig?.custom_agents?.[agentName];
241
201
  if (customAgentConfig?.skills && customAgentConfig.skills.length > 0) {
242
- const skillRefs = customAgentConfig.skills.map(
243
- (s) => ({
244
- id: typeof s === "string" ? s : s.id,
245
- usage: `when working with ${(typeof s === "string" ? s : s.id).split(" ")[0]}`,
246
- preloaded: (typeof s === "object" && "preloaded" in s && s.preloaded) ?? false
247
- })
248
- );
202
+ const skillRefs = customAgentConfig.skills.map((s) => ({
203
+ id: typeof s === "string" ? s : s.id,
204
+ usage: `when working with ${(typeof s === "string" ? s : s.id).split(" ")[0]}`,
205
+ preloaded: (typeof s === "object" && "preloaded" in s && s.preloaded) ?? false
206
+ }));
249
207
  compileAgents[agentName] = { skills: skillRefs };
250
- verbose(
251
- ` Agent ${agentName}: ${skillRefs.length} skills from custom_agents`
252
- );
253
- } else if (pluginConfig?.agent_skills?.[agentName]) {
254
- const skillRefs = resolveStackSkills(
255
- pluginConfig,
256
- agentName,
257
- pluginSkills
258
- );
208
+ verbose(` Agent ${agentName}: ${skillRefs.length} skills from custom_agents`);
209
+ } else if (projectConfig?.agent_skills?.[agentName]) {
210
+ const skillRefs = resolveStackSkills(projectConfig, agentName, pluginSkills);
259
211
  compileAgents[agentName] = { skills: skillRefs };
260
212
  verbose(` Agent ${agentName}: ${skillRefs.length} skills from config`);
261
- } else if (pluginConfig?.skills) {
262
- const skillRefs = pluginConfig.skills.map((s) => ({
263
- id: s.id,
264
- usage: `when working with ${s.id.split(" ")[0]}`,
265
- preloaded: s.preloaded ?? false
266
- }));
213
+ } else if (projectConfig?.skills) {
214
+ const skillRefs = projectConfig.skills.map((s) => {
215
+ const id = typeof s === "string" ? s : s.id;
216
+ const preloaded = typeof s === "object" && "preloaded" in s ? s.preloaded ?? false : false;
217
+ return {
218
+ id,
219
+ usage: `when working with ${id.split(" ")[0]}`,
220
+ preloaded
221
+ };
222
+ });
267
223
  compileAgents[agentName] = { skills: skillRefs };
268
224
  verbose(` Agent ${agentName}: ${skillRefs.length} skills (all)`);
269
225
  } else {
270
226
  compileAgents[agentName] = {};
271
227
  }
272
228
  } else {
273
- result.warnings.push(
274
- `Agent "${agentName}" not found in source definitions`
275
- );
229
+ result.warnings.push(`Agent "${agentName}" not found in source definitions`);
276
230
  }
277
231
  }
278
232
  const compileConfig = {
279
- name: pluginConfig?.name || path.basename(pluginDir),
280
- description: pluginConfig?.description || "Recompiled plugin",
233
+ name: projectConfig?.name || path.basename(pluginDir),
234
+ description: projectConfig?.description || "Recompiled plugin",
281
235
  claude_md: "",
282
236
  agents: compileAgents
283
237
  };
284
238
  const engine = await createLiquidEngine(projectDir);
285
- const resolvedAgents = await resolveAgents(
286
- allAgents,
287
- pluginSkills,
288
- compileConfig,
289
- sourcePath
290
- );
239
+ const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);
291
240
  const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);
292
241
  await ensureDir(agentsDir);
293
242
  for (const [name, agent] of Object.entries(resolvedAgents)) {
294
243
  try {
295
- const output = await compileAgentForPlugin(
296
- name,
297
- agent,
298
- sourcePath,
299
- engine
300
- );
244
+ const output = await compileAgentForPlugin(name, agent, sourcePath, engine);
301
245
  await writeFile(path.join(agentsDir, `${name}.md`), output);
302
246
  result.compiled.push(name);
303
247
  verbose(` Recompiled: ${name}`);
@@ -314,4 +258,4 @@ async function recompileAgents(options) {
314
258
  export {
315
259
  recompileAgents
316
260
  };
317
- //# sourceMappingURL=chunk-4K4ZXQRM.js.map
261
+ //# sourceMappingURL=chunk-N6JNE326.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/agent-recompiler.ts","../src/cli/lib/custom-agent-resolver.ts"],"sourcesContent":["import path from \"path\";\nimport { glob, writeFile, ensureDir, readFile, fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { loadAllAgents, loadPluginSkills, loadProjectAgents } from \"./loader\";\nimport { resolveAgents, resolveStackSkills } from \"./resolver\";\nimport { compileAgentForPlugin } from \"./stack-plugin-compiler\";\nimport { getPluginAgentsDir } from \"./plugin-finder\";\nimport { createLiquidEngine } from \"./compiler\";\nimport { loadProjectConfig, type LoadedProjectConfig } from \"./project-config\";\nimport { resolveCustomAgents, validateCustomAgentIds } from \"./custom-agent-resolver\";\nimport { parse as parseYaml } from \"yaml\";\nimport type {\n CompileConfig,\n CompileAgentConfig,\n SkillReference,\n SkillDefinition,\n ProjectConfig,\n AgentDefinition,\n} from \"../../types\";\n\nexport interface RecompileAgentsOptions {\n pluginDir: string;\n sourcePath: string;\n agents?: string[];\n skills?: Record<string, SkillDefinition>;\n projectDir?: string;\n outputDir?: string;\n}\n\nexport interface RecompileAgentsResult {\n compiled: string[];\n failed: string[];\n warnings: string[];\n}\n\nasync function getExistingAgentNames(pluginDir: string): Promise<string[]> {\n const agentsDir = getPluginAgentsDir(pluginDir);\n const files = await glob(\"*.md\", agentsDir);\n return files.map((f) => path.basename(f, \".md\"));\n}\n\n/**\n * Load config from either:\n * 1. pluginDir/config.yaml (legacy plugin location)\n * 2. pluginDir/.claude/config.yaml (new project config location)\n *\n * This provides backward compatibility with existing plugins.\n */\nasync function loadConfigWithFallback(pluginDir: string): Promise<LoadedProjectConfig | null> {\n // First try the legacy plugin location (pluginDir/config.yaml)\n const legacyConfigPath = path.join(pluginDir, \"config.yaml\");\n if (await fileExists(legacyConfigPath)) {\n try {\n const content = await readFile(legacyConfigPath);\n const parsed = parseYaml(content);\n\n if (parsed && typeof parsed === \"object\") {\n verbose(`Loaded config.yaml from ${legacyConfigPath}`);\n return {\n config: parsed as ProjectConfig,\n configPath: legacyConfigPath,\n isLegacy: false,\n };\n }\n } catch (error) {\n verbose(`Failed to parse config.yaml: ${error}`);\n }\n }\n\n // Fall back to project config location (.claude/config.yaml)\n return loadProjectConfig(pluginDir);\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const {\n pluginDir,\n sourcePath,\n agents: specifiedAgents,\n skills: providedSkills,\n projectDir,\n outputDir,\n } = options;\n\n const result: RecompileAgentsResult = {\n compiled: [],\n failed: [],\n warnings: [],\n };\n\n // Load project config (handles both legacy plugin config and new ProjectConfig)\n // Try plugin dir first, then fall back to project dir for local mode\n let loadedConfig = await loadConfigWithFallback(pluginDir);\n if (!loadedConfig && projectDir) {\n loadedConfig = await loadConfigWithFallback(projectDir);\n }\n const projectConfig = loadedConfig?.config ?? null;\n\n // Load built-in agents from source\n const builtinAgents = await loadAllAgents(sourcePath);\n\n // Load project agents from .claude-src/agents/ (if projectDir provided)\n const projectAgents = projectDir ? await loadProjectAgents(projectDir) : {};\n\n // Resolve custom agents and merge with built-in agents\n // Priority: custom_agents > project agents > built-in agents\n let allAgents: Record<string, AgentDefinition> = {\n ...builtinAgents,\n ...projectAgents,\n };\n if (projectConfig?.custom_agents) {\n // Validate custom agent IDs don't conflict with built-in agents\n const idConflicts = validateCustomAgentIds(projectConfig.custom_agents, builtinAgents);\n if (idConflicts.length > 0) {\n for (const error of idConflicts) {\n result.warnings.push(error);\n }\n }\n\n // Resolve custom agents to AgentDefinition\n try {\n const resolvedCustomAgents = resolveCustomAgents(projectConfig.custom_agents, builtinAgents);\n // Merge: custom agents can override built-in if same name (though we warn above)\n allAgents = { ...builtinAgents, ...resolvedCustomAgents };\n verbose(`Resolved ${Object.keys(resolvedCustomAgents).length} custom agents`);\n } catch (error) {\n result.warnings.push(\n `Failed to resolve custom agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n let agentNames: string[];\n if (specifiedAgents) {\n agentNames = specifiedAgents;\n } else if (projectConfig?.agents) {\n agentNames = projectConfig.agents;\n verbose(`Using agents from config.yaml: ${agentNames.join(\", \")}`);\n } else if (outputDir) {\n agentNames = Object.keys(allAgents);\n verbose(`Using all available agents from source: ${agentNames.join(\", \")}`);\n } else {\n agentNames = await getExistingAgentNames(pluginDir);\n }\n\n if (agentNames.length === 0) {\n result.warnings.push(\"No agents found to recompile\");\n return result;\n }\n\n verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);\n\n const pluginSkills = providedSkills ?? (await loadPluginSkills(pluginDir));\n\n const compileAgents: Record<string, CompileAgentConfig> = {};\n for (const agentName of agentNames) {\n if (allAgents[agentName]) {\n // Check if this is a custom agent with its own skills defined\n const customAgentConfig = projectConfig?.custom_agents?.[agentName];\n if (customAgentConfig?.skills && customAgentConfig.skills.length > 0) {\n // Custom agent has explicit skills defined\n const skillRefs: SkillReference[] = customAgentConfig.skills.map((s) => ({\n id: typeof s === \"string\" ? s : s.id,\n usage: `when working with ${(typeof s === \"string\" ? s : s.id).split(\" \")[0]}`,\n preloaded: (typeof s === \"object\" && \"preloaded\" in s && s.preloaded) ?? false,\n }));\n compileAgents[agentName] = { skills: skillRefs };\n verbose(` Agent ${agentName}: ${skillRefs.length} skills from custom_agents`);\n } else if (projectConfig?.agent_skills?.[agentName]) {\n const skillRefs = resolveStackSkills(projectConfig, agentName, pluginSkills);\n compileAgents[agentName] = { skills: skillRefs };\n verbose(` Agent ${agentName}: ${skillRefs.length} skills from config`);\n } else if (projectConfig?.skills) {\n // Fall back to all skills in the config\n const skillRefs: SkillReference[] = projectConfig.skills.map((s) => {\n const id = typeof s === \"string\" ? s : s.id;\n const preloaded =\n typeof s === \"object\" && \"preloaded\" in s ? (s.preloaded ?? false) : false;\n return {\n id,\n usage: `when working with ${id.split(\" \")[0]}`,\n preloaded,\n };\n });\n compileAgents[agentName] = { skills: skillRefs };\n verbose(` Agent ${agentName}: ${skillRefs.length} skills (all)`);\n } else {\n compileAgents[agentName] = {};\n }\n } else {\n result.warnings.push(`Agent \"${agentName}\" not found in source definitions`);\n }\n }\n\n const compileConfig: CompileConfig = {\n name: projectConfig?.name || path.basename(pluginDir),\n description: projectConfig?.description || \"Recompiled plugin\",\n claude_md: \"\",\n agents: compileAgents,\n };\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n for (const [name, agent] of Object.entries(resolvedAgents)) {\n try {\n const output = await compileAgentForPlugin(name, agent, sourcePath, engine);\n await writeFile(path.join(agentsDir, `${name}.md`), output);\n result.compiled.push(name);\n verbose(` Recompiled: ${name}`);\n } catch (error) {\n result.failed.push(name);\n result.warnings.push(\n `Failed to compile ${name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return result;\n}\n","import type { CustomAgentConfig, AgentDefinition } from \"../../types\";\n\n/** Default tools for standalone custom agents (no extends) */\nconst DEFAULT_TOOLS = [\"Read\", \"Grep\", \"Glob\"];\n\n/** Marker path for standalone custom agents (no extends) */\nconst CUSTOM_AGENT_PATH = \"_custom\";\n\n/**\n * Resolve a custom agent config to a full AgentDefinition.\n * If extends is specified, inherit from the base agent.\n *\n * @param agentId - The custom agent's identifier\n * @param customConfig - The custom agent configuration from config.yaml\n * @param builtinAgents - Record of built-in agent definitions to extend from\n * @returns Fully resolved AgentDefinition\n * @throws Error if extends references an unknown agent\n */\nexport function resolveCustomAgent(\n agentId: string,\n customConfig: CustomAgentConfig,\n builtinAgents: Record<string, AgentDefinition>,\n): AgentDefinition {\n let baseAgent: Partial<AgentDefinition> = {};\n\n if (customConfig.extends) {\n const base = builtinAgents[customConfig.extends];\n if (!base) {\n const availableAgents = Object.keys(builtinAgents);\n const agentList =\n availableAgents.length > 0\n ? `Available agents: ${availableAgents.slice(0, 5).join(\", \")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : \"\"}`\n : \"No built-in agents found\";\n throw new Error(\n `Custom agent \"${agentId}\" extends unknown agent \"${customConfig.extends}\". ${agentList}`,\n );\n }\n baseAgent = { ...base };\n }\n\n // Merge disallowed_tools: custom + inherited\n let disallowedTools: string[] | undefined;\n if (customConfig.disallowed_tools || baseAgent.disallowed_tools) {\n const merged = new Set<string>([\n ...(baseAgent.disallowed_tools || []),\n ...(customConfig.disallowed_tools || []),\n ]);\n disallowedTools = [...merged];\n }\n\n // Merge hooks: custom hooks added to inherited\n let hooks: AgentDefinition[\"hooks\"] | undefined;\n if (customConfig.hooks || baseAgent.hooks) {\n hooks = { ...baseAgent.hooks };\n if (customConfig.hooks) {\n for (const [hookType, hookDefs] of Object.entries(customConfig.hooks)) {\n if (hooks[hookType]) {\n hooks[hookType] = [...hooks[hookType], ...hookDefs];\n } else {\n hooks[hookType] = hookDefs;\n }\n }\n }\n }\n\n return {\n title: customConfig.title,\n description: customConfig.description,\n model: customConfig.model || baseAgent.model,\n tools: customConfig.tools || baseAgent.tools || DEFAULT_TOOLS,\n disallowed_tools: disallowedTools,\n permission_mode: customConfig.permission_mode || baseAgent.permission_mode,\n hooks,\n // Use extended agent's path for template resolution, or _custom for standalone\n path: baseAgent.path || CUSTOM_AGENT_PATH,\n sourceRoot: baseAgent.sourceRoot,\n };\n}\n\n/**\n * Resolve all custom agents from config to AgentDefinition records.\n *\n * @param customAgents - Record of custom agent configs from config.yaml\n * @param builtinAgents - Record of built-in agent definitions\n * @returns Record of resolved AgentDefinitions keyed by custom agent ID\n */\nexport function resolveCustomAgents(\n customAgents: Record<string, CustomAgentConfig>,\n builtinAgents: Record<string, AgentDefinition>,\n): Record<string, AgentDefinition> {\n const resolved: Record<string, AgentDefinition> = {};\n\n for (const [id, config] of Object.entries(customAgents)) {\n resolved[id] = resolveCustomAgent(id, config, builtinAgents);\n }\n\n return resolved;\n}\n\n/**\n * Check if a custom agent ID conflicts with a built-in agent ID.\n *\n * @param customAgentId - The custom agent's identifier\n * @param builtinAgents - Record of built-in agent definitions\n * @returns true if there's a conflict\n */\nexport function hasAgentIdConflict(\n customAgentId: string,\n builtinAgents: Record<string, AgentDefinition>,\n): boolean {\n return customAgentId in builtinAgents;\n}\n\n/**\n * Validate custom agents don't conflict with built-in agents.\n *\n * @param customAgents - Record of custom agent configs\n * @param builtinAgents - Record of built-in agent definitions\n * @returns Array of error messages (empty if no conflicts)\n */\nexport function validateCustomAgentIds(\n customAgents: Record<string, CustomAgentConfig>,\n builtinAgents: Record<string, AgentDefinition>,\n): string[] {\n const errors: string[] = [];\n\n for (const customId of Object.keys(customAgents)) {\n if (hasAgentIdConflict(customId, builtinAgents)) {\n errors.push(\n `Custom agent \"${customId}\" conflicts with built-in agent of the same name. Choose a unique name.`,\n );\n }\n }\n\n return errors;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ensureDir,
4
+ fileExists,
5
+ readFile,
6
+ writeFile
7
+ } from "./chunk-AL74GBW4.js";
8
+ import {
9
+ CLAUDE_SRC_DIR
10
+ } from "./chunk-FJFEKPXF.js";
11
+ import {
12
+ init_esm_shims
13
+ } from "./chunk-DHET7RCE.js";
14
+
15
+ // src/cli/lib/config-saver.ts
16
+ init_esm_shims();
17
+ import path from "path";
18
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
19
+ var YAML_INDENT = 2;
20
+ async function saveSourceToProjectConfig(projectDir, source) {
21
+ const configPath = path.join(projectDir, CLAUDE_SRC_DIR, "config.yaml");
22
+ let config = {};
23
+ if (await fileExists(configPath)) {
24
+ const content = await readFile(configPath);
25
+ config = parseYaml(content) || {};
26
+ }
27
+ config.source = source;
28
+ await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));
29
+ const configYaml = stringifyYaml(config, { indent: YAML_INDENT });
30
+ await writeFile(configPath, configYaml);
31
+ }
32
+
33
+ export {
34
+ saveSourceToProjectConfig
35
+ };
36
+ //# sourceMappingURL=chunk-NAGU7TVZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/config-saver.ts"],"sourcesContent":["import path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { fileExists, readFile, writeFile, ensureDir } from \"../utils/fs\";\nimport { CLAUDE_SRC_DIR } from \"../consts\";\n\nconst YAML_INDENT = 2;\n\n/**\n * Save source to project-level .claude-src/config.yaml.\n * Creates the config file if it doesn't exist, or merges with existing config.\n */\nexport async function saveSourceToProjectConfig(projectDir: string, source: string): Promise<void> {\n const configPath = path.join(projectDir, CLAUDE_SRC_DIR, \"config.yaml\");\n\n let config: Record<string, unknown> = {};\n if (await fileExists(configPath)) {\n const content = await readFile(configPath);\n config = (parseYaml(content) as Record<string, unknown>) || {};\n }\n\n config.source = source;\n\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n const configYaml = stringifyYaml(config, { indent: YAML_INDENT });\n await writeFile(configPath, configYaml);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AACjB,SAAS,SAAS,WAAW,aAAa,qBAAqB;AAI/D,IAAM,cAAc;AAMpB,eAAsB,0BAA0B,YAAoB,QAA+B;AACjG,QAAM,aAAa,KAAK,KAAK,YAAY,gBAAgB,aAAa;AAEtE,MAAI,SAAkC,CAAC;AACvC,MAAI,MAAM,WAAW,UAAU,GAAG;AAChC,UAAM,UAAU,MAAM,SAAS,UAAU;AACzC,aAAU,UAAU,OAAO,KAAiC,CAAC;AAAA,EAC/D;AAEA,SAAO,SAAS;AAEhB,QAAM,UAAU,KAAK,KAAK,YAAY,cAAc,CAAC;AACrD,QAAM,aAAa,cAAc,QAAQ,EAAE,QAAQ,YAAY,CAAC;AAChE,QAAM,UAAU,YAAY,UAAU;AACxC;","names":[]}
@@ -7,10 +7,8 @@ import {
7
7
  init_esm_shims();
8
8
  import { useCallback, useEffect } from "react";
9
9
  import { Box, Text, useInput } from "ink";
10
- import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
11
  var SYMBOL_REQUIRED = "*";
12
- var BG_SELECTED = "cyan";
13
- var BG_FOCUSED = "#333333";
14
12
  var FRAMEWORK_CATEGORY_ID = "framework";
15
13
  var sortOptions = (options, expertMode) => {
16
14
  if (expertMode) {
@@ -59,15 +57,11 @@ var isSectionLocked = (categoryId, categories) => {
59
57
  if (categoryId === FRAMEWORK_CATEGORY_ID) {
60
58
  return false;
61
59
  }
62
- const frameworkCategory = categories.find(
63
- (cat) => cat.id === FRAMEWORK_CATEGORY_ID
64
- );
60
+ const frameworkCategory = categories.find((cat) => cat.id === FRAMEWORK_CATEGORY_ID);
65
61
  if (!frameworkCategory) {
66
62
  return false;
67
63
  }
68
- const hasFrameworkSelected = frameworkCategory.options.some(
69
- (opt) => opt.selected
70
- );
64
+ const hasFrameworkSelected = frameworkCategory.options.some((opt) => opt.selected);
71
65
  return !hasFrameworkSelected;
72
66
  };
73
67
  var findNextUnlockedSection = (categories, currentIndex, direction, allCategories) => {
@@ -87,52 +81,55 @@ var findNextUnlockedSection = (categories, currentIndex, direction, allCategorie
87
81
  }
88
82
  return currentIndex;
89
83
  };
90
- var HeaderRow = ({
91
- showDescriptions,
92
- expertMode
93
- }) => {
94
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "flex-end", marginBottom: 1, gap: 2, children: [
95
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
96
- "[d] Descriptions: ",
97
- showDescriptions ? "ON" : "OFF"
98
- ] }),
99
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
100
- "[e] Expert Mode: ",
101
- expertMode ? "ON" : "OFF"
102
- ] })
103
- ] });
104
- };
105
84
  var SkillTag = ({ option, isFocused, isLocked }) => {
106
- const getBackground = () => {
107
- if (isLocked) return void 0;
108
- if (option.selected) return BG_SELECTED;
109
- if (isFocused) return BG_FOCUSED;
110
- return void 0;
111
- };
112
85
  const getColor = () => {
113
- if (isLocked) return "gray";
114
- if (option.selected) return "black";
115
- if (option.state === "recommended") return "cyan";
116
- if (option.state === "disabled") return "gray";
117
- if (option.state === "discouraged") return "yellow";
86
+ if (isLocked || option.state === "disabled") {
87
+ return {
88
+ text: "gray",
89
+ border: "gray"
90
+ };
91
+ }
92
+ if (option.selected) {
93
+ return {
94
+ text: "cyan",
95
+ border: "cyan"
96
+ };
97
+ }
98
+ if (option.state === "recommended") {
99
+ return {
100
+ text: "white",
101
+ border: "gray"
102
+ };
103
+ }
104
+ if (option.state === "discouraged") {
105
+ return {
106
+ text: "yellow",
107
+ border: "yellow"
108
+ };
109
+ }
118
110
  return void 0;
119
111
  };
112
+ const isBold = isFocused || option.selected;
120
113
  const isDimmed = isLocked || option.state === "disabled";
121
- const isBold = isFocused && !isLocked;
122
- return /* @__PURE__ */ jsx(Box, { marginRight: 1, children: /* @__PURE__ */ jsxs(
123
- Text,
114
+ const focusBorderColor = option.selected ? "cyan" : "white";
115
+ return /* @__PURE__ */ jsx(
116
+ Box,
124
117
  {
125
- backgroundColor: getBackground(),
126
- color: getColor(),
127
- dimColor: isDimmed,
128
- bold: isBold,
129
- children: [
118
+ marginRight: 1,
119
+ borderColor: isFocused ? focusBorderColor : getColor()?.border,
120
+ borderStyle: "single",
121
+ borderDimColor: isDimmed,
122
+ children: /* @__PURE__ */ jsxs(Text, { color: getColor()?.text, bold: isBold, dimColor: false, children: [
130
123
  " ",
124
+ option.local && /* @__PURE__ */ jsxs(Fragment, { children: [
125
+ /* @__PURE__ */ jsx(Text, { backgroundColor: "gray", children: " L " }),
126
+ " "
127
+ ] }),
131
128
  option.label,
132
129
  " "
133
- ]
130
+ ] })
134
131
  }
135
- ) });
132
+ );
136
133
  };
137
134
  var CategorySection = ({
138
135
  category,
@@ -142,26 +139,14 @@ var CategorySection = ({
142
139
  focusedOptionIndex,
143
140
  showDescriptions
144
141
  }) => {
145
- const underline = "\u2500".repeat(
146
- category.name.length + (category.required ? 2 : 0)
147
- );
148
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
142
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
149
143
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
150
- /* @__PURE__ */ jsx(
151
- Text,
152
- {
153
- bold: isFocused && !isLocked,
154
- color: isLocked ? "gray" : isFocused ? "cyan" : void 0,
155
- dimColor: isLocked,
156
- children: category.name
157
- }
158
- ),
144
+ /* @__PURE__ */ jsx(Text, { dimColor: isLocked, children: category.name }),
159
145
  category.required && /* @__PURE__ */ jsxs(Text, { color: isLocked ? "gray" : "red", dimColor: isLocked, children: [
160
146
  " ",
161
147
  SYMBOL_REQUIRED
162
148
  ] })
163
149
  ] }),
164
- /* @__PURE__ */ jsx(Text, { dimColor: isLocked, color: isLocked ? "gray" : void 0, children: underline }),
165
150
  /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", marginTop: 0, children: options.map((option, index) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
166
151
  /* @__PURE__ */ jsx(
167
152
  SkillTag,
@@ -175,23 +160,6 @@ var CategorySection = ({
175
160
  ] }, option.id)) })
176
161
  ] });
177
162
  };
178
- var LegendRow = () => {
179
- return /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
180
- "Legend:",
181
- " ",
182
- /* @__PURE__ */ jsxs(Text, { backgroundColor: BG_SELECTED, color: "black", children: [
183
- " ",
184
- "selected",
185
- " "
186
- ] }),
187
- " ",
188
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: "recommended" }),
189
- " ",
190
- /* @__PURE__ */ jsx(Text, { color: "yellow", children: "discouraged" }),
191
- " ",
192
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "disabled" })
193
- ] }) });
194
- };
195
163
  var CategoryGrid = ({
196
164
  categories,
197
165
  focusedRow,
@@ -200,8 +168,7 @@ var CategoryGrid = ({
200
168
  expertMode,
201
169
  onToggle,
202
170
  onFocusChange,
203
- onToggleDescriptions,
204
- onToggleExpertMode
171
+ onToggleDescriptions
205
172
  }) => {
206
173
  const processedCategories = categories.map((category) => ({
207
174
  ...category,
@@ -225,26 +192,14 @@ var CategoryGrid = ({
225
192
  }, [focusedRow, currentOptions, focusedCol, onFocusChange, currentRow]);
226
193
  useEffect(() => {
227
194
  if (currentRow && currentLocked) {
228
- const unlockedIndex = findNextUnlockedSection(
229
- processedCategories,
230
- focusedRow,
231
- 1,
232
- categories
233
- );
195
+ const unlockedIndex = findNextUnlockedSection(processedCategories, focusedRow, 1, categories);
234
196
  if (unlockedIndex !== focusedRow) {
235
197
  const newRowOptions = processedCategories[unlockedIndex]?.sortedOptions || [];
236
198
  const newCol = findValidStartColumn(newRowOptions);
237
199
  onFocusChange(unlockedIndex, newCol);
238
200
  }
239
201
  }
240
- }, [
241
- currentRow,
242
- currentLocked,
243
- focusedRow,
244
- processedCategories,
245
- categories,
246
- onFocusChange
247
- ]);
202
+ }, [currentRow, currentLocked, focusedRow, processedCategories, categories, onFocusChange]);
248
203
  useInput(
249
204
  useCallback(
250
205
  (input, key) => {
@@ -266,10 +221,6 @@ var CategoryGrid = ({
266
221
  }
267
222
  return;
268
223
  }
269
- if (input === "e" || input === "E") {
270
- onToggleExpertMode();
271
- return;
272
- }
273
224
  if (input === "d" || input === "D") {
274
225
  onToggleDescriptions();
275
226
  return;
@@ -288,29 +239,14 @@ var CategoryGrid = ({
288
239
  const isDown = key.downArrow || input === "j";
289
240
  if (isLeft) {
290
241
  if (currentLocked) return;
291
- const newCol = findNextValidOption(
292
- currentOptions,
293
- focusedCol,
294
- -1,
295
- true
296
- );
242
+ const newCol = findNextValidOption(currentOptions, focusedCol, -1, true);
297
243
  onFocusChange(focusedRow, newCol);
298
244
  } else if (isRight) {
299
245
  if (currentLocked) return;
300
- const newCol = findNextValidOption(
301
- currentOptions,
302
- focusedCol,
303
- 1,
304
- true
305
- );
246
+ const newCol = findNextValidOption(currentOptions, focusedCol, 1, true);
306
247
  onFocusChange(focusedRow, newCol);
307
248
  } else if (isUp) {
308
- const newRow = findNextUnlockedSection(
309
- processedCategories,
310
- focusedRow,
311
- -1,
312
- categories
313
- );
249
+ const newRow = findNextUnlockedSection(processedCategories, focusedRow, -1, categories);
314
250
  const newRowOptions = processedCategories[newRow]?.sortedOptions || [];
315
251
  let newCol = Math.min(focusedCol, newRowOptions.length - 1);
316
252
  if (newRowOptions[newCol]?.state === "disabled") {
@@ -318,12 +254,7 @@ var CategoryGrid = ({
318
254
  }
319
255
  onFocusChange(newRow, newCol);
320
256
  } else if (isDown) {
321
- const newRow = findNextUnlockedSection(
322
- processedCategories,
323
- focusedRow,
324
- 1,
325
- categories
326
- );
257
+ const newRow = findNextUnlockedSection(processedCategories, focusedRow, 1, categories);
327
258
  const newRowOptions = processedCategories[newRow]?.sortedOptions || [];
328
259
  let newCol = Math.min(focusedCol, newRowOptions.length - 1);
329
260
  if (newRowOptions[newCol]?.state === "disabled") {
@@ -342,36 +273,31 @@ var CategoryGrid = ({
342
273
  categories,
343
274
  onToggle,
344
275
  onFocusChange,
345
- onToggleDescriptions,
346
- onToggleExpertMode
276
+ onToggleDescriptions
347
277
  ]
348
278
  )
349
279
  );
350
280
  if (categories.length === 0) {
351
281
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No categories to display." }) });
352
282
  }
353
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
354
- /* @__PURE__ */ jsx(HeaderRow, { showDescriptions, expertMode }),
355
- processedCategories.map((category, rowIndex) => {
356
- const isLocked = isSectionLocked(category.id, categories);
357
- return /* @__PURE__ */ jsx(
358
- CategorySection,
359
- {
360
- category,
361
- options: category.sortedOptions,
362
- isLocked,
363
- isFocused: rowIndex === focusedRow,
364
- focusedOptionIndex: focusedCol,
365
- showDescriptions
366
- },
367
- category.id
368
- );
369
- }),
370
- /* @__PURE__ */ jsx(LegendRow, {})
371
- ] });
283
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: processedCategories.map((category, rowIndex) => {
284
+ const isLocked = isSectionLocked(category.id, categories);
285
+ return /* @__PURE__ */ jsx(
286
+ CategorySection,
287
+ {
288
+ category,
289
+ options: category.sortedOptions,
290
+ isLocked,
291
+ isFocused: rowIndex === focusedRow,
292
+ focusedOptionIndex: focusedCol,
293
+ showDescriptions
294
+ },
295
+ category.id
296
+ );
297
+ }) });
372
298
  };
373
299
 
374
300
  export {
375
301
  CategoryGrid
376
302
  };
377
- //# sourceMappingURL=chunk-Z7G4B5HJ.js.map
303
+ //# sourceMappingURL=chunk-OQYYMQJR.js.map