@agents-inc/cli 0.50.0 → 0.61.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 (237) hide show
  1. package/CHANGELOG.md +167 -5
  2. package/dist/{chunk-KQOU4POU.js → chunk-46DQG2N7.js} +72 -51
  3. package/dist/chunk-46DQG2N7.js.map +1 -0
  4. package/dist/{chunk-2BWCR762.js → chunk-52XO4ULK.js} +6 -8
  5. package/dist/chunk-52XO4ULK.js.map +1 -0
  6. package/dist/{chunk-DCE423KO.js → chunk-6DAZG54T.js} +5 -5
  7. package/dist/{chunk-AWP5A6IM.js → chunk-6OWHQ7HM.js} +14 -12
  8. package/dist/chunk-6OWHQ7HM.js.map +1 -0
  9. package/dist/{chunk-D72AFYQR.js → chunk-7FMEMXJ4.js} +71 -71
  10. package/dist/chunk-7FMEMXJ4.js.map +1 -0
  11. package/dist/{chunk-RA2IPRO2.js → chunk-AJJJE7F7.js} +2 -2
  12. package/dist/{chunk-4R52TQ3K.js → chunk-AX3SZZWA.js} +2 -2
  13. package/dist/{chunk-U2W5SENM.js → chunk-BFD5NZQ4.js} +5 -4
  14. package/dist/chunk-BFD5NZQ4.js.map +1 -0
  15. package/dist/{chunk-HYEUETIC.js → chunk-BKJHAJQW.js} +2 -2
  16. package/dist/{chunk-HYEUETIC.js.map → chunk-BKJHAJQW.js.map} +1 -1
  17. package/dist/{chunk-GBOW6FUW.js → chunk-BNQ5O6LE.js} +2 -2
  18. package/dist/{chunk-KAO3LKB5.js → chunk-C577AJE7.js} +3 -3
  19. package/dist/{chunk-C3Q43WLC.js → chunk-CIG7IKX3.js} +4 -4
  20. package/dist/chunk-EC3UJRKZ.js +1534 -0
  21. package/dist/chunk-EC3UJRKZ.js.map +1 -0
  22. package/dist/{chunk-HMSHB5EQ.js → chunk-FWMWWE3X.js} +3543 -3037
  23. package/dist/chunk-FWMWWE3X.js.map +1 -0
  24. package/dist/{chunk-YDYRAXSY.js → chunk-GH2RQ4MI.js} +6 -6
  25. package/dist/{chunk-5FPIKTSA.js → chunk-H5DASUX5.js} +7 -7
  26. package/dist/{chunk-JFF7P4LC.js → chunk-H7WJK7NJ.js} +22 -6
  27. package/dist/chunk-H7WJK7NJ.js.map +1 -0
  28. package/dist/chunk-HGTC76BX.js +16 -0
  29. package/dist/chunk-HGTC76BX.js.map +1 -0
  30. package/dist/{chunk-WFFV254H.js → chunk-IEEVXLJB.js} +110 -82
  31. package/dist/chunk-IEEVXLJB.js.map +1 -0
  32. package/dist/{chunk-5FCHJLM7.js → chunk-IGM6HA3S.js} +252 -38
  33. package/dist/chunk-IGM6HA3S.js.map +1 -0
  34. package/dist/{chunk-QB5HHTAA.js → chunk-KD2YS76O.js} +28 -12
  35. package/dist/chunk-KD2YS76O.js.map +1 -0
  36. package/dist/{chunk-5L724R4C.js → chunk-KDO6WU76.js} +8 -13
  37. package/dist/chunk-KDO6WU76.js.map +1 -0
  38. package/dist/{chunk-XDSVV5GZ.js → chunk-KIWFEBKH.js} +41 -11
  39. package/dist/chunk-KIWFEBKH.js.map +1 -0
  40. package/dist/{chunk-WBHPCBVN.js → chunk-LWXRUR6B.js} +66 -94
  41. package/dist/chunk-LWXRUR6B.js.map +1 -0
  42. package/dist/{chunk-SPFHPHYL.js → chunk-M6YWRMXH.js} +24 -14
  43. package/dist/chunk-M6YWRMXH.js.map +1 -0
  44. package/dist/{chunk-CMNKHDOX.js → chunk-MGNYPVOJ.js} +2 -2
  45. package/dist/{chunk-U7X4V4HE.js → chunk-MMFQNJPE.js} +2 -2
  46. package/dist/{chunk-WLZHCM7O.js → chunk-MR6OBL3B.js} +3 -11
  47. package/dist/{chunk-WLZHCM7O.js.map → chunk-MR6OBL3B.js.map} +1 -1
  48. package/dist/{chunk-RFKDGJAJ.js → chunk-O6BA7Q2B.js} +6 -6
  49. package/dist/chunk-O6BA7Q2B.js.map +1 -0
  50. package/dist/chunk-OCEFD7V6.js +201 -0
  51. package/dist/chunk-OCEFD7V6.js.map +1 -0
  52. package/dist/{chunk-YZTWZVGX.js → chunk-PUT7X3GA.js} +1 -1
  53. package/dist/chunk-PUT7X3GA.js.map +1 -0
  54. package/dist/{chunk-QYLCINGC.js → chunk-SDKCQXWE.js} +2 -2
  55. package/dist/{chunk-RDWGYKDY.js → chunk-SDLDPFNV.js} +6 -6
  56. package/dist/{chunk-7LV4V6A4.js → chunk-SRBN6RRD.js} +14 -10
  57. package/dist/chunk-SRBN6RRD.js.map +1 -0
  58. package/dist/{chunk-PGY5XROM.js → chunk-VR3CDXDT.js} +2 -6
  59. package/dist/chunk-VR3CDXDT.js.map +1 -0
  60. package/dist/{chunk-I6IOGZSZ.js → chunk-WHISPMAQ.js} +11 -15
  61. package/dist/chunk-WHISPMAQ.js.map +1 -0
  62. package/dist/{chunk-3VOL4WEG.js → chunk-WYVDNGJB.js} +3 -3
  63. package/dist/{chunk-WJHFV6RI.js → chunk-X5EG4EFP.js} +2 -2
  64. package/dist/{chunk-JWYRXE6C.js → chunk-XUDTFI4M.js} +2 -2
  65. package/dist/{chunk-4QWDB2MD.js → chunk-YHOHLNHM.js} +127 -105
  66. package/dist/chunk-YHOHLNHM.js.map +1 -0
  67. package/dist/{chunk-M3GQ2R3E.js → chunk-Z3TM4N37.js} +19 -7
  68. package/dist/chunk-Z3TM4N37.js.map +1 -0
  69. package/dist/commands/build/marketplace.js +4 -4
  70. package/dist/commands/build/plugins.js +9 -7
  71. package/dist/commands/build/plugins.js.map +1 -1
  72. package/dist/commands/build/stack.js +13 -10
  73. package/dist/commands/build/stack.js.map +1 -1
  74. package/dist/commands/compile.js +110 -129
  75. package/dist/commands/compile.js.map +1 -1
  76. package/dist/commands/config/index.js +7 -5
  77. package/dist/commands/config/index.js.map +1 -1
  78. package/dist/commands/config/path.js +8 -6
  79. package/dist/commands/config/path.js.map +1 -1
  80. package/dist/commands/config/show.js +7 -5
  81. package/dist/commands/diff.js +9 -7
  82. package/dist/commands/diff.js.map +1 -1
  83. package/dist/commands/doctor.js +20 -16
  84. package/dist/commands/doctor.js.map +1 -1
  85. package/dist/commands/edit.js +175 -79
  86. package/dist/commands/edit.js.map +1 -1
  87. package/dist/commands/eject.js +20 -41
  88. package/dist/commands/eject.js.map +1 -1
  89. package/dist/commands/import/skill.js +10 -18
  90. package/dist/commands/import/skill.js.map +1 -1
  91. package/dist/commands/info.js +21 -20
  92. package/dist/commands/info.js.map +1 -1
  93. package/dist/commands/init.js +32 -31
  94. package/dist/commands/list.js +8 -6
  95. package/dist/commands/list.js.map +1 -1
  96. package/dist/commands/new/agent.js +23 -11
  97. package/dist/commands/new/agent.js.map +1 -1
  98. package/dist/commands/new/marketplace.js +63 -46
  99. package/dist/commands/new/marketplace.js.map +1 -1
  100. package/dist/commands/new/skill.js +11 -9
  101. package/dist/commands/outdated.js +9 -7
  102. package/dist/commands/outdated.js.map +1 -1
  103. package/dist/commands/search.js +45 -35
  104. package/dist/commands/search.js.map +1 -1
  105. package/dist/commands/uninstall.js +93 -123
  106. package/dist/commands/uninstall.js.map +1 -1
  107. package/dist/commands/update.js +11 -9
  108. package/dist/commands/update.js.map +1 -1
  109. package/dist/commands/validate.js +23 -27
  110. package/dist/commands/validate.js.map +1 -1
  111. package/dist/components/common/confirm.test.js +4 -4
  112. package/dist/components/skill-search/skill-search.js +3 -3
  113. package/dist/components/wizard/category-grid.js +3 -3
  114. package/dist/components/wizard/category-grid.test.js +4 -4
  115. package/dist/components/wizard/category-grid.test.js.map +1 -1
  116. package/dist/components/wizard/checkbox-grid.js +5 -5
  117. package/dist/components/wizard/checkbox-grid.test.js +6 -6
  118. package/dist/components/wizard/domain-selection.js +12 -11
  119. package/dist/components/wizard/help-modal.js +2 -2
  120. package/dist/components/wizard/menu-item.js +1 -1
  121. package/dist/components/wizard/search-modal.js +2 -2
  122. package/dist/components/wizard/search-modal.test.js +3 -3
  123. package/dist/components/wizard/search-modal.test.js.map +1 -1
  124. package/dist/components/wizard/section-progress.js +2 -2
  125. package/dist/components/wizard/section-progress.test.js +4 -4
  126. package/dist/components/wizard/section-progress.test.js.map +1 -1
  127. package/dist/components/wizard/selection-card.js +2 -2
  128. package/dist/components/wizard/source-grid.js +4 -4
  129. package/dist/components/wizard/source-grid.test.js +5 -5
  130. package/dist/components/wizard/source-grid.test.js.map +1 -1
  131. package/dist/components/wizard/stack-selection.js +9 -8
  132. package/dist/components/wizard/step-agents.js +11 -10
  133. package/dist/components/wizard/step-agents.test.js +13 -12
  134. package/dist/components/wizard/step-agents.test.js.map +1 -1
  135. package/dist/components/wizard/step-build.js +11 -9
  136. package/dist/components/wizard/step-build.test.js +18 -22
  137. package/dist/components/wizard/step-build.test.js.map +1 -1
  138. package/dist/components/wizard/step-confirm.js +4 -4
  139. package/dist/components/wizard/step-confirm.test.js +83 -23
  140. package/dist/components/wizard/step-confirm.test.js.map +1 -1
  141. package/dist/components/wizard/step-refine.js +2 -2
  142. package/dist/components/wizard/step-refine.test.js +3 -3
  143. package/dist/components/wizard/step-settings.js +9 -7
  144. package/dist/components/wizard/step-settings.test.js +13 -11
  145. package/dist/components/wizard/step-settings.test.js.map +1 -1
  146. package/dist/components/wizard/step-sources.js +13 -11
  147. package/dist/components/wizard/step-sources.test.js +19 -17
  148. package/dist/components/wizard/step-sources.test.js.map +1 -1
  149. package/dist/components/wizard/step-stack.js +15 -14
  150. package/dist/components/wizard/step-stack.test.js +17 -16
  151. package/dist/components/wizard/step-stack.test.js.map +1 -1
  152. package/dist/components/wizard/view-title.js +2 -2
  153. package/dist/components/wizard/wizard-layout.js +10 -8
  154. package/dist/components/wizard/wizard-tabs.js +2 -2
  155. package/dist/components/wizard/wizard-tabs.test.js +2 -2
  156. package/dist/components/wizard/wizard.js +29 -27
  157. package/dist/config-exports.js +20 -0
  158. package/dist/config-exports.js.map +1 -0
  159. package/dist/hooks/init.js +34 -33
  160. package/dist/hooks/init.js.map +1 -1
  161. package/dist/loader-2O32KKAQ.js +19 -0
  162. package/dist/source-loader-KMEBBZCQ.js +16 -0
  163. package/dist/source-loader-KMEBBZCQ.js.map +1 -0
  164. package/dist/source-manager-5XBSPJNR.js +18 -0
  165. package/dist/source-manager-5XBSPJNR.js.map +1 -0
  166. package/dist/src/agents/meta/agent-summoner/workflow.md +3 -3
  167. package/dist/src/agents/meta/skill-summoner/critical-reminders.md +2 -2
  168. package/dist/src/agents/meta/skill-summoner/critical-requirements.md +1 -1
  169. package/dist/src/agents/meta/skill-summoner/intro.md +1 -1
  170. package/dist/src/agents/meta/skill-summoner/output-format.md +3 -3
  171. package/dist/src/agents/meta/skill-summoner/workflow.md +8 -8
  172. package/dist/stores/wizard-store.js +6 -5
  173. package/dist/stores/wizard-store.test.js +299 -59
  174. package/dist/stores/wizard-store.test.js.map +1 -1
  175. package/package.json +5 -1
  176. package/src/agents/meta/agent-summoner/workflow.md +3 -3
  177. package/src/agents/meta/skill-summoner/critical-reminders.md +2 -2
  178. package/src/agents/meta/skill-summoner/critical-requirements.md +1 -1
  179. package/src/agents/meta/skill-summoner/intro.md +1 -1
  180. package/src/agents/meta/skill-summoner/output-format.md +3 -3
  181. package/src/agents/meta/skill-summoner/workflow.md +8 -8
  182. package/src/schemas/metadata.schema.json +6 -0
  183. package/src/schemas/stacks.schema.json +1 -1
  184. package/config/skill-categories.yaml +0 -344
  185. package/config/skill-rules.yaml +0 -740
  186. package/config/stacks.yaml +0 -1864
  187. package/dist/chunk-26MXZUHU.js +0 -183
  188. package/dist/chunk-26MXZUHU.js.map +0 -1
  189. package/dist/chunk-2BWCR762.js.map +0 -1
  190. package/dist/chunk-4QWDB2MD.js.map +0 -1
  191. package/dist/chunk-5FCHJLM7.js.map +0 -1
  192. package/dist/chunk-5L724R4C.js.map +0 -1
  193. package/dist/chunk-7LV4V6A4.js.map +0 -1
  194. package/dist/chunk-AWP5A6IM.js.map +0 -1
  195. package/dist/chunk-D72AFYQR.js.map +0 -1
  196. package/dist/chunk-HMSHB5EQ.js.map +0 -1
  197. package/dist/chunk-I6IOGZSZ.js.map +0 -1
  198. package/dist/chunk-JFF7P4LC.js.map +0 -1
  199. package/dist/chunk-KQOU4POU.js.map +0 -1
  200. package/dist/chunk-M3GQ2R3E.js.map +0 -1
  201. package/dist/chunk-PGY5XROM.js.map +0 -1
  202. package/dist/chunk-QB5HHTAA.js.map +0 -1
  203. package/dist/chunk-RFKDGJAJ.js.map +0 -1
  204. package/dist/chunk-SPFHPHYL.js.map +0 -1
  205. package/dist/chunk-U2W5SENM.js.map +0 -1
  206. package/dist/chunk-UAD3SC27.js +0 -107
  207. package/dist/chunk-UAD3SC27.js.map +0 -1
  208. package/dist/chunk-WBHPCBVN.js.map +0 -1
  209. package/dist/chunk-WFFV254H.js.map +0 -1
  210. package/dist/chunk-XDSVV5GZ.js.map +0 -1
  211. package/dist/chunk-YZTWZVGX.js.map +0 -1
  212. package/dist/commands/config/get.js +0 -61
  213. package/dist/commands/config/get.js.map +0 -1
  214. package/dist/commands/config/set-project.js +0 -61
  215. package/dist/commands/config/set-project.js.map +0 -1
  216. package/dist/commands/config/unset-project.js +0 -57
  217. package/dist/commands/config/unset-project.js.map +0 -1
  218. package/dist/config/skill-categories.yaml +0 -344
  219. package/dist/config/skill-rules.yaml +0 -740
  220. package/dist/config/stacks.yaml +0 -1864
  221. package/dist/source-manager-BVB2SG73.js +0 -16
  222. /package/dist/{chunk-DCE423KO.js.map → chunk-6DAZG54T.js.map} +0 -0
  223. /package/dist/{chunk-RA2IPRO2.js.map → chunk-AJJJE7F7.js.map} +0 -0
  224. /package/dist/{chunk-4R52TQ3K.js.map → chunk-AX3SZZWA.js.map} +0 -0
  225. /package/dist/{chunk-GBOW6FUW.js.map → chunk-BNQ5O6LE.js.map} +0 -0
  226. /package/dist/{chunk-KAO3LKB5.js.map → chunk-C577AJE7.js.map} +0 -0
  227. /package/dist/{chunk-C3Q43WLC.js.map → chunk-CIG7IKX3.js.map} +0 -0
  228. /package/dist/{chunk-YDYRAXSY.js.map → chunk-GH2RQ4MI.js.map} +0 -0
  229. /package/dist/{chunk-5FPIKTSA.js.map → chunk-H5DASUX5.js.map} +0 -0
  230. /package/dist/{chunk-CMNKHDOX.js.map → chunk-MGNYPVOJ.js.map} +0 -0
  231. /package/dist/{chunk-U7X4V4HE.js.map → chunk-MMFQNJPE.js.map} +0 -0
  232. /package/dist/{chunk-QYLCINGC.js.map → chunk-SDKCQXWE.js.map} +0 -0
  233. /package/dist/{chunk-RDWGYKDY.js.map → chunk-SDLDPFNV.js.map} +0 -0
  234. /package/dist/{chunk-3VOL4WEG.js.map → chunk-WYVDNGJB.js.map} +0 -0
  235. /package/dist/{chunk-WJHFV6RI.js.map → chunk-X5EG4EFP.js.map} +0 -0
  236. /package/dist/{chunk-JWYRXE6C.js.map → chunk-XUDTFI4M.js.map} +0 -0
  237. /package/dist/{source-manager-BVB2SG73.js.map → loader-2O32KKAQ.js.map} +0 -0
@@ -7,10 +7,10 @@ import {
7
7
  } from "./chunk-KUV24B5M.js";
8
8
  import {
9
9
  useRowScroll
10
- } from "./chunk-3VOL4WEG.js";
10
+ } from "./chunk-WYVDNGJB.js";
11
11
  import {
12
12
  ViewTitle
13
- } from "./chunk-CMNKHDOX.js";
13
+ } from "./chunk-MGNYPVOJ.js";
14
14
  import {
15
15
  useTextInput
16
16
  } from "./chunk-U3IGFMCY.js";
@@ -19,14 +19,14 @@ import {
19
19
  addSource,
20
20
  getSourceSummary,
21
21
  removeSource
22
- } from "./chunk-HMSHB5EQ.js";
22
+ } from "./chunk-FWMWWE3X.js";
23
23
  import {
24
24
  getErrorMessage,
25
25
  verbose
26
- } from "./chunk-WBHPCBVN.js";
26
+ } from "./chunk-LWXRUR6B.js";
27
27
  import {
28
28
  CLI_COLORS
29
- } from "./chunk-AWP5A6IM.js";
29
+ } from "./chunk-6OWHQ7HM.js";
30
30
  import {
31
31
  init_esm_shims
32
32
  } from "./chunk-DHET7RCE.js";
@@ -262,4 +262,4 @@ var StepSettings = ({
262
262
  export {
263
263
  StepSettings
264
264
  };
265
- //# sourceMappingURL=chunk-YDYRAXSY.js.map
265
+ //# sourceMappingURL=chunk-GH2RQ4MI.js.map
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- StackSelection
4
- } from "./chunk-DCE423KO.js";
5
2
  import {
6
3
  useMeasuredHeight
7
4
  } from "./chunk-K77I4XGL.js";
5
+ import {
6
+ StackSelection
7
+ } from "./chunk-6DAZG54T.js";
8
8
  import {
9
9
  DomainSelection
10
- } from "./chunk-5L724R4C.js";
10
+ } from "./chunk-KDO6WU76.js";
11
11
  import {
12
12
  ViewTitle
13
- } from "./chunk-CMNKHDOX.js";
13
+ } from "./chunk-MGNYPVOJ.js";
14
14
  import {
15
15
  useWizardStore
16
- } from "./chunk-5FCHJLM7.js";
16
+ } from "./chunk-IGM6HA3S.js";
17
17
  import {
18
18
  init_esm_shims
19
19
  } from "./chunk-DHET7RCE.js";
@@ -37,4 +37,4 @@ var StepStack = ({ matrix, onCancel }) => {
37
37
  export {
38
38
  StepStack
39
39
  };
40
- //# sourceMappingURL=chunk-5FPIKTSA.js.map
40
+ //# sourceMappingURL=chunk-H5DASUX5.js.map
@@ -4,17 +4,17 @@ import {
4
4
  } from "./chunk-GG4BSB6S.js";
5
5
  import {
6
6
  useSectionScroll
7
- } from "./chunk-GBOW6FUW.js";
7
+ } from "./chunk-BNQ5O6LE.js";
8
8
  import {
9
9
  CLI_COLORS
10
- } from "./chunk-AWP5A6IM.js";
10
+ } from "./chunk-6OWHQ7HM.js";
11
11
  import {
12
12
  init_esm_shims
13
13
  } from "./chunk-DHET7RCE.js";
14
14
 
15
15
  // src/cli/components/wizard/category-grid.tsx
16
16
  init_esm_shims();
17
- import { useCallback as useCallback2, useMemo } from "react";
17
+ import { useCallback as useCallback2, useMemo, useRef as useRef2 } from "react";
18
18
  import { Box, Text } from "ink";
19
19
 
20
20
  // src/cli/components/hooks/use-category-grid-input.ts
@@ -182,6 +182,7 @@ var SkillTag = ({ option, isFocused, isLocked, showLabels }) => {
182
182
  option.label,
183
183
  " "
184
184
  ] }),
185
+ option.scope === "global" && /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, children: "G " }),
185
186
  compatibilityLabel && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
186
187
  compatibilityLabel,
187
188
  " "
@@ -233,7 +234,8 @@ var CategoryGrid = ({
233
234
  onToggleLabels,
234
235
  defaultFocusedRow = 0,
235
236
  defaultFocusedCol = 0,
236
- onFocusChange
237
+ onFocusChange,
238
+ onFocusedSkillChange
237
239
  }) => {
238
240
  const processedCategories = useMemo(
239
241
  () => categories.map((category) => ({ ...category, sortedOptions: category.options })),
@@ -259,6 +261,14 @@ var CategoryGrid = ({
259
261
  },
260
262
  [processedCategories, categories]
261
263
  );
264
+ const handleFocusChange = useCallback2(
265
+ (row, col) => {
266
+ onFocusChange?.(row, col);
267
+ const skill = processedCategories[row]?.sortedOptions[col];
268
+ onFocusedSkillChange?.(skill?.id ?? null);
269
+ },
270
+ [onFocusChange, processedCategories, onFocusedSkillChange]
271
+ );
262
272
  const { focusedRow, focusedCol, setFocused, moveFocus } = useFocusedListItem(
263
273
  processedCategories.length,
264
274
  getColCount,
@@ -266,11 +276,17 @@ var CategoryGrid = ({
266
276
  wrap: true,
267
277
  isRowLocked,
268
278
  findValidCol,
269
- onChange: onFocusChange,
279
+ onChange: handleFocusChange,
270
280
  initialRow: defaultFocusedRow,
271
281
  initialCol: defaultFocusedCol
272
282
  }
273
283
  );
284
+ const mountedRef = useRef2(false);
285
+ if (!mountedRef.current) {
286
+ mountedRef.current = true;
287
+ const skill = processedCategories[defaultFocusedRow]?.sortedOptions[defaultFocusedCol];
288
+ onFocusedSkillChange?.(skill?.id ?? null);
289
+ }
274
290
  useCategoryGridInput({
275
291
  processedCategories,
276
292
  categories,
@@ -318,4 +334,4 @@ var CategoryGrid = ({
318
334
  export {
319
335
  CategoryGrid
320
336
  };
321
- //# sourceMappingURL=chunk-JFF7P4LC.js.map
337
+ //# sourceMappingURL=chunk-H7WJK7NJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/category-grid.tsx","../src/cli/components/hooks/use-category-grid-input.ts"],"sourcesContent":["import React, { useCallback, useMemo, useRef } from \"react\";\n\nimport { Box, Text } from \"ink\";\n\nimport { CLI_COLORS } from \"../../consts.js\";\nimport type { SkillId, Category } from \"../../types/index.js\";\nimport { isSectionLocked, useCategoryGridInput } from \"../hooks/use-category-grid-input.js\";\nimport { useFocusedListItem } from \"../hooks/use-focused-list-item.js\";\nimport { useSectionScroll } from \"../hooks/use-section-scroll.js\";\n\nexport type OptionState = \"normal\" | \"recommended\" | \"discouraged\";\n\nexport type CategoryOption = {\n id: SkillId;\n label: string;\n state: OptionState;\n stateReason?: string;\n selected: boolean;\n local?: boolean;\n installed?: boolean;\n scope?: \"project\" | \"global\";\n};\n\nexport type CategoryRow = {\n id: Category;\n displayName: string;\n required: boolean;\n exclusive: boolean;\n options: CategoryOption[];\n};\n\nexport type CategoryGridProps = {\n categories: CategoryRow[];\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n showLabels: boolean;\n onToggle: (categoryId: Category, technologyId: SkillId) => void;\n onToggleLabels: () => void;\n /** Optional initial focus row (default: 0). Use with React `key` to reset. */\n defaultFocusedRow?: number;\n /** Optional initial focus col (default: 0). Use with React `key` to reset. */\n defaultFocusedCol?: number;\n /** Optional callback fired whenever the focused position changes */\n onFocusChange?: (row: number, col: number) => void;\n /** Optional callback fired with the resolved SkillId of the focused cell */\n onFocusedSkillChange?: (skillId: SkillId | null) => void;\n};\n\nconst SYMBOL_REQUIRED = \"*\";\n\nconst findNextValidOption = (\n options: CategoryOption[],\n currentIndex: number,\n direction: 1 | -1,\n wrap = true,\n): number => {\n const length = options.length;\n if (length === 0) return currentIndex;\n\n let index = currentIndex + direction;\n\n if (wrap) {\n if (index < 0) index = length - 1;\n if (index >= length) index = 0;\n } else {\n if (index < 0) index = 0;\n if (index >= length) index = length - 1;\n }\n\n return index;\n};\n\ntype SkillTagProps = {\n option: CategoryOption;\n isFocused: boolean;\n isLocked: boolean;\n showLabels: boolean;\n};\n\nconst getCompatibilityLabel = (option: CategoryOption, isLocked: boolean): string | null => {\n if (option.selected) return \"(selected)\";\n if (isLocked) return \"(disabled)\";\n if (option.state === \"recommended\") return \"(recommended)\";\n if (option.state === \"discouraged\") return \"(discouraged)\";\n return null;\n};\n\nconst SkillTag: React.FC<SkillTagProps> = ({ option, isFocused, isLocked, showLabels }) => {\n const getTextColor = (): string => {\n if (isLocked) return CLI_COLORS.NEUTRAL;\n if (option.selected) return CLI_COLORS.PRIMARY;\n if (option.state === \"recommended\") return CLI_COLORS.UNFOCUSED;\n if (option.state === \"discouraged\") return CLI_COLORS.WARNING;\n\n return CLI_COLORS.NEUTRAL;\n };\n\n const getStateBorderColor = (): string => {\n if (isLocked) return CLI_COLORS.NEUTRAL;\n if (option.selected) return CLI_COLORS.PRIMARY;\n if (option.state === \"recommended\") return CLI_COLORS.UNFOCUSED;\n if (option.state === \"discouraged\") return CLI_COLORS.WARNING;\n return CLI_COLORS.UNFOCUSED;\n };\n\n const textColor = getTextColor();\n const compatibilityLabel = showLabels ? getCompatibilityLabel(option, isLocked) : null;\n\n return (\n <Box\n marginRight={1}\n borderColor={isFocused ? getStateBorderColor() : CLI_COLORS.NEUTRAL}\n borderStyle=\"single\"\n flexShrink={0}\n >\n <>\n <Text color={textColor} bold>\n {\" \"}\n {option.label}{\" \"}\n </Text>\n {option.scope === \"global\" && <Text color={CLI_COLORS.WARNING}>G </Text>}\n {compatibilityLabel && <Text dimColor>{compatibilityLabel} </Text>}\n </>\n </Box>\n );\n};\n\ntype CategorySectionProps = {\n isFirst: boolean;\n category: CategoryRow;\n options: CategoryOption[];\n isLocked: boolean;\n isFocused: boolean;\n focusedOptionIndex: number;\n showLabels: boolean;\n};\n\nconst CategorySection: React.FC<CategorySectionProps> = ({\n isFirst,\n category,\n options,\n isLocked,\n isFocused,\n focusedOptionIndex,\n showLabels,\n}) => {\n const selectedCount = options.filter((o) => o.selected).length;\n\n const selectionCounter = category.exclusive\n ? `(${selectedCount} of 1)`\n : `(${selectedCount} selected)`;\n\n return (\n <Box flexDirection=\"column\" marginTop={isFirst ? 0 : 1}>\n <Box flexDirection=\"row\">\n <Text dimColor={isLocked} color={isFocused ? \"#fff\" : \"gray\"}>\n {category.displayName}\n </Text>\n {category.required && (\n <Text color={isLocked ? CLI_COLORS.NEUTRAL : CLI_COLORS.ERROR} dimColor={isLocked}>\n {\" \"}\n {SYMBOL_REQUIRED}\n </Text>\n )}\n {selectionCounter && <Text dimColor> {selectionCounter}</Text>}\n </Box>\n\n <Box flexDirection=\"row\" flexWrap=\"wrap\" marginTop={0}>\n {options.map((option, index) => (\n <SkillTag\n key={option.id}\n option={option}\n isFocused={isFocused && index === focusedOptionIndex && !isLocked}\n isLocked={isLocked}\n showLabels={showLabels}\n />\n ))}\n </Box>\n </Box>\n );\n};\n\ntype ProcessedCategory = CategoryRow & { sortedOptions: CategoryOption[] };\n\nexport const CategoryGrid: React.FC<CategoryGridProps> = ({\n categories,\n availableHeight = 0,\n showLabels,\n onToggle,\n onToggleLabels,\n defaultFocusedRow = 0,\n defaultFocusedCol = 0,\n onFocusChange,\n onFocusedSkillChange,\n}) => {\n const processedCategories = useMemo(\n () => categories.map((category) => ({ ...category, sortedOptions: category.options })),\n [categories],\n );\n\n const getColCount = useCallback(\n (row: number): number => processedCategories[row]?.sortedOptions.length ?? 0,\n [processedCategories],\n );\n\n const isRowLocked = useCallback(\n (row: number): boolean => {\n const cat = processedCategories[row];\n return cat ? isSectionLocked(cat.id, categories) : false;\n },\n [processedCategories, categories],\n );\n\n const findValidCol = useCallback(\n (row: number, currentCol: number, direction: 1 | -1): number => {\n const options = processedCategories[row]?.sortedOptions || [];\n const catId = processedCategories[row]?.id;\n if (catId && isSectionLocked(catId, categories)) return currentCol;\n return findNextValidOption(options, currentCol, direction, true);\n },\n [processedCategories, categories],\n );\n\n const handleFocusChange = useCallback(\n (row: number, col: number) => {\n onFocusChange?.(row, col);\n const skill = processedCategories[row]?.sortedOptions[col];\n onFocusedSkillChange?.(skill?.id ?? null);\n },\n [onFocusChange, processedCategories, onFocusedSkillChange],\n );\n\n const { focusedRow, focusedCol, setFocused, moveFocus } = useFocusedListItem(\n processedCategories.length,\n getColCount,\n {\n wrap: true,\n isRowLocked,\n findValidCol,\n onChange: handleFocusChange,\n initialRow: defaultFocusedRow,\n initialCol: defaultFocusedCol,\n },\n );\n\n const mountedRef = useRef(false);\n if (!mountedRef.current) {\n mountedRef.current = true;\n const skill = processedCategories[defaultFocusedRow]?.sortedOptions[defaultFocusedCol];\n onFocusedSkillChange?.(skill?.id ?? null);\n }\n\n useCategoryGridInput({\n processedCategories,\n categories,\n focusedRow,\n focusedCol,\n setFocused,\n moveFocus,\n onToggle,\n onToggleLabels,\n });\n\n const { setSectionRef, scrollEnabled, scrollTopPx } = useSectionScroll({\n sectionCount: processedCategories.length,\n focusedIndex: focusedRow,\n availableHeight,\n });\n\n if (categories.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>No categories to display.</Text>\n </Box>\n );\n }\n\n const noShrink = scrollEnabled ? { flexShrink: 0 } : {};\n\n const sectionElements = processedCategories.map((category, index) => {\n const isLocked = isSectionLocked(category.id, categories);\n\n return (\n <Box key={category.id} ref={(el) => setSectionRef(index, el)} {...noShrink}>\n <CategorySection\n category={category}\n options={category.sortedOptions}\n isLocked={isLocked}\n isFocused={index === focusedRow}\n focusedOptionIndex={focusedCol}\n showLabels={showLabels}\n isFirst={index === 0}\n />\n </Box>\n );\n });\n\n return (\n <Box\n flexDirection=\"column\"\n {...(scrollEnabled\n ? { height: availableHeight, overflow: \"hidden\" as const }\n : { flexGrow: 1 })}\n >\n <Box flexDirection=\"column\" marginTop={scrollTopPx > 0 ? -scrollTopPx : 0} {...noShrink}>\n {sectionElements}\n </Box>\n </Box>\n );\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useInput } from \"ink\";\n\nimport type { Category, SkillId } from \"../../types/index.js\";\nimport type { CategoryOption, CategoryRow } from \"../wizard/category-grid.js\";\n\nconst FRAMEWORK_CATEGORY_ID = \"web-framework\";\n\n// Locked = non-framework section when no framework is selected\nexport const isSectionLocked = (categoryId: Category, categories: CategoryRow[]): boolean => {\n if (categoryId === FRAMEWORK_CATEGORY_ID) {\n return false;\n }\n\n const frameworkCategory = categories.find((cat) => cat.id === FRAMEWORK_CATEGORY_ID);\n if (!frameworkCategory) return false;\n\n return !frameworkCategory.options.some((opt) => opt.selected);\n};\n\nexport const findValidStartColumn = (_options: CategoryOption[]): number => {\n return 0;\n};\n\n/** Find next unlocked section index (wrapping, direction: forward) */\nexport const findNextUnlockedIndex = (\n processed: { id: Category; sortedOptions: CategoryOption[] }[],\n currentIndex: number,\n allCategories: CategoryRow[],\n): number => {\n const length = processed.length;\n if (length === 0) return currentIndex;\n\n let index = currentIndex;\n let attempts = 0;\n\n while (attempts < length) {\n index += 1;\n if (index >= length) index = 0;\n\n const category = processed[index];\n if (category && !isSectionLocked(category.id, allCategories)) {\n return index;\n }\n\n attempts++;\n }\n\n return currentIndex;\n};\n\ntype ProcessedCategory = CategoryRow & { sortedOptions: CategoryOption[] };\n\ntype UseCategoryGridInputOptions = {\n processedCategories: ProcessedCategory[];\n categories: CategoryRow[];\n focusedRow: number;\n focusedCol: number;\n setFocused: (row: number, col: number) => void;\n moveFocus: (direction: \"up\" | \"down\" | \"left\" | \"right\") => void;\n onToggle: (categoryId: Category, technologyId: SkillId) => void;\n onToggleLabels: () => void;\n};\n\nexport function useCategoryGridInput({\n processedCategories,\n categories,\n focusedRow,\n focusedCol,\n setFocused,\n moveFocus,\n onToggle,\n onToggleLabels,\n}: UseCategoryGridInputOptions): void {\n const currentRow = processedCategories[focusedRow];\n const currentOptions = currentRow?.sortedOptions || [];\n const currentLocked = currentRow ? isSectionLocked(currentRow.id, categories) : false;\n\n // Adjust column when current row's options change externally (e.g. option becomes disabled)\n useEffect(() => {\n if (!currentRow) return;\n\n const maxCol = currentOptions.length - 1;\n if (focusedCol > maxCol) {\n const newCol = Math.max(0, maxCol);\n setFocused(focusedRow, newCol);\n }\n }, [focusedRow, currentOptions, focusedCol, setFocused, currentRow]);\n\n // Bounce off locked sections when a section becomes locked (e.g. framework deselected)\n useEffect(() => {\n if (currentRow && currentLocked) {\n const nextUnlocked = findNextUnlockedIndex(processedCategories, focusedRow, categories);\n if (nextUnlocked !== focusedRow) {\n const newRowOptions = processedCategories[nextUnlocked]?.sortedOptions || [];\n const newCol = findValidStartColumn(newRowOptions);\n setFocused(nextUnlocked, newCol);\n }\n }\n }, [currentRow, currentLocked, focusedRow, processedCategories, categories, setFocused]);\n\n // Store the latest handler in a ref so that the useInput effect never needs to\n // re-register on the event emitter. This avoids a stale-closure race condition\n // where, after a domain switch (CategoryGrid remount via key={activeDomain}),\n // the useInput effect may not yet have re-registered the updated handler when\n // the first keypress arrives — causing the first space press to be silently lost.\n type InputKey = {\n leftArrow: boolean;\n rightArrow: boolean;\n upArrow: boolean;\n downArrow: boolean;\n tab: boolean;\n shift: boolean;\n };\n\n const handlerRef = useRef<((input: string, key: InputKey) => void) | null>(null);\n handlerRef.current = (input: string, key: InputKey) => {\n if (key.tab && key.shift) {\n onToggleLabels();\n return;\n }\n\n if (key.tab && !key.shift) {\n const nextSection = findNextUnlockedIndex(processedCategories, focusedRow, categories);\n if (nextSection !== focusedRow) {\n const newRowOptions = processedCategories[nextSection]?.sortedOptions || [];\n const newCol = findValidStartColumn(newRowOptions);\n setFocused(nextSection, newCol);\n }\n return;\n }\n\n if (input === \"d\" || input === \"D\") {\n onToggleLabels();\n return;\n }\n\n if (input === \" \") {\n if (currentLocked) return;\n const currentOption = currentOptions[focusedCol];\n if (currentOption) {\n onToggle(currentRow.id, currentOption.id);\n }\n return;\n }\n\n const isLeft = key.leftArrow || input === \"h\";\n const isRight = key.rightArrow || input === \"l\";\n const isUp = key.upArrow || input === \"k\";\n const isDown = key.downArrow || input === \"j\";\n\n if (isLeft) {\n if (currentLocked) return;\n moveFocus(\"left\");\n } else if (isRight) {\n if (currentLocked) return;\n moveFocus(\"right\");\n } else if (isUp) {\n moveFocus(\"up\");\n } else if (isDown) {\n moveFocus(\"down\");\n }\n };\n\n // Stable handler reference — never changes, so useInput's effect registers once\n const stableHandler = useCallback((input: string, key: InputKey) => {\n handlerRef.current?.(input, key);\n }, []);\n\n useInput(stableHandler);\n}\n"],"mappings":"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","names":["useCallback","useRef","useCallback","useRef"]}
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-DHET7RCE.js";
5
+
6
+ // src/cli/lib/feature-flags.ts
7
+ init_esm_shims();
8
+ var FEATURE_FLAGS = {
9
+ // Controls whether the search pill appears in the source grid (step-sources)
10
+ SOURCE_SEARCH: false
11
+ };
12
+
13
+ export {
14
+ FEATURE_FLAGS
15
+ };
16
+ //# sourceMappingURL=chunk-HGTC76BX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/feature-flags.ts"],"sourcesContent":["export const FEATURE_FLAGS = {\n // Controls whether the search pill appears in the source grid (step-sources)\n SOURCE_SEARCH: false,\n} as const;\n"],"mappings":";;;;;;AAAA;AAAO,IAAM,gBAAgB;AAAA;AAAA,EAE3B,eAAe;AACjB;","names":[]}
@@ -1,32 +1,36 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- BaseCommand,
4
- EXIT_CODES
5
- } from "./chunk-PGY5XROM.js";
6
2
  import {
7
3
  LOCAL_DEFAULTS,
8
4
  computeSkillFolderHash,
5
+ detectInstallation,
6
+ loadConfig,
7
+ loadConfigTypesDataInBackground,
8
+ regenerateConfigTypes,
9
9
  resolveAuthor
10
- } from "./chunk-HMSHB5EQ.js";
10
+ } from "./chunk-FWMWWE3X.js";
11
+ import {
12
+ BaseCommand,
13
+ EXIT_CODES
14
+ } from "./chunk-VR3CDXDT.js";
11
15
  import {
12
16
  directoryExists,
13
17
  ensureDir,
14
18
  fileExists,
15
19
  getErrorMessage,
16
- readFile,
17
20
  verbose,
18
21
  writeFile
19
- } from "./chunk-WBHPCBVN.js";
22
+ } from "./chunk-LWXRUR6B.js";
20
23
  import {
21
24
  CLI_BIN_NAME,
25
+ DEFAULT_VERSION,
22
26
  KEBAB_CASE_PATTERN,
23
27
  LOCAL_SKILLS_PATH,
24
28
  PLUGIN_MANIFEST_DIR,
25
29
  SKILLS_DIR_PATH,
26
- SKILL_CATEGORIES_YAML_PATH,
27
- SKILL_RULES_YAML_PATH,
30
+ SKILL_CATEGORIES_PATH,
31
+ SKILL_RULES_PATH,
28
32
  STANDARD_FILES
29
- } from "./chunk-AWP5A6IM.js";
33
+ } from "./chunk-6OWHQ7HM.js";
30
34
  import {
31
35
  init_esm_shims
32
36
  } from "./chunk-DHET7RCE.js";
@@ -35,7 +39,6 @@ import {
35
39
  init_esm_shims();
36
40
  import { Args, Flags } from "@oclif/core";
37
41
  import path from "path";
38
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
39
42
  function validateSkillName(name) {
40
43
  if (!name || name.trim() === "") {
41
44
  return "Skill name is required";
@@ -102,12 +105,14 @@ Add your patterns here.
102
105
  </critical_reminders>
103
106
  `;
104
107
  }
105
- function generateMetadataYaml(name, author, category, contentHash) {
108
+ function generateMetadataYaml(name, author, category, contentHash, domain) {
106
109
  const titleName = toTitleCase(name);
107
110
  return `custom: true
111
+ domain: ${domain}
108
112
  category: ${category}
109
113
  author: "${author}"
110
114
  displayName: ${titleName}
115
+ slug: ${name}
111
116
  cliDescription: Brief description
112
117
  usageGuidance: Use when <guidance>.
113
118
  contentHash: ${contentHash}
@@ -116,35 +121,51 @@ tags:
116
121
  - custom
117
122
  `;
118
123
  }
119
- var KNOWN_DOMAINS = /* @__PURE__ */ new Set(["web", "api", "mobile", "cli", "shared"]);
120
124
  var DEFAULT_CATEGORY_ORDER = 99;
121
- function generateSkillCategoriesYaml(category) {
122
- const prefix = category.split("-")[0];
123
- const subcategoryPart = category.includes("-") ? category.slice(category.indexOf("-") + 1) : category;
124
- const displayName = toTitleCase(subcategoryPart);
125
- const domainLine = KNOWN_DOMAINS.has(prefix) ? `
126
- domain: ${prefix}` : "";
127
- return `version: "1.0.0"
128
-
129
- categories:
130
- ${category}:
131
- id: ${category}
132
- displayName: ${displayName}
133
- description: Skills for ${displayName}${domainLine}
134
- exclusive: true
135
- required: false
136
- order: ${DEFAULT_CATEGORY_ORDER}
137
- custom: true
125
+ var CATEGORIES_TS_COMMENT = "// Skill category definitions";
126
+ var RULES_TS_COMMENT = "// Skill rules configuration";
127
+ function formatTsExport(comment, data) {
128
+ const body = JSON.stringify(data, null, 2);
129
+ return `${comment}
130
+ export default ${body};
138
131
  `;
139
132
  }
140
- function generateSkillRulesYaml(skillName) {
141
- return `version: "1.0.0"
142
-
143
- # Short aliases mapping to canonical skill IDs
144
- # Example: react: "web-framework-react"
145
- aliases:
146
- ${skillName}: "${skillName}"
147
- `;
133
+ function buildCategoryEntry(category, domain) {
134
+ const categoryPart = category.includes("-") ? category.slice(category.indexOf("-") + 1) : category;
135
+ const entry = {
136
+ id: category,
137
+ displayName: toTitleCase(categoryPart),
138
+ description: `Skills for ${toTitleCase(categoryPart)}`,
139
+ exclusive: true,
140
+ required: false,
141
+ order: DEFAULT_CATEGORY_ORDER,
142
+ custom: true
143
+ };
144
+ entry.domain = domain;
145
+ return entry;
146
+ }
147
+ function generateSkillCategoriesTs(category, domain) {
148
+ const entry = buildCategoryEntry(category, domain);
149
+ const data = {
150
+ version: DEFAULT_VERSION,
151
+ categories: {
152
+ [category]: entry
153
+ }
154
+ };
155
+ return formatTsExport(CATEGORIES_TS_COMMENT, data);
156
+ }
157
+ function generateSkillRulesTs() {
158
+ const data = {
159
+ version: DEFAULT_VERSION,
160
+ relationships: {
161
+ conflicts: [],
162
+ discourages: [],
163
+ recommends: [],
164
+ requires: [],
165
+ alternatives: []
166
+ }
167
+ };
168
+ return formatTsExport(RULES_TS_COMMENT, data);
148
169
  }
149
170
  var NewSkill = class _NewSkill extends BaseCommand {
150
171
  static summary = "Create a new local skill with proper structure";
@@ -167,6 +188,11 @@ var NewSkill = class _NewSkill extends BaseCommand {
167
188
  description: "Skill category",
168
189
  default: LOCAL_DEFAULTS.CATEGORY
169
190
  }),
191
+ domain: Flags.string({
192
+ char: "d",
193
+ description: "Domain for the skill (e.g., web, api, cli)",
194
+ required: false
195
+ }),
170
196
  force: Flags.boolean({
171
197
  char: "f",
172
198
  description: "Overwrite existing skill directory",
@@ -180,6 +206,15 @@ var NewSkill = class _NewSkill extends BaseCommand {
180
206
  async run() {
181
207
  const { args, flags } = await this.parse(_NewSkill);
182
208
  const projectDir = process.cwd();
209
+ if (!flags.output) {
210
+ const installation = await detectInstallation(projectDir);
211
+ if (!installation) {
212
+ this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {
213
+ exit: EXIT_CODES.ERROR
214
+ });
215
+ }
216
+ }
217
+ const configTypesReady = flags.output ? null : loadConfigTypesDataInBackground(flags.source, projectDir);
183
218
  this.log("");
184
219
  this.log("Create New Skill");
185
220
  this.log("");
@@ -192,6 +227,7 @@ var NewSkill = class _NewSkill extends BaseCommand {
192
227
  author = await resolveAuthor(projectDir) || LOCAL_DEFAULTS.AUTHOR;
193
228
  }
194
229
  const category = flags.category;
230
+ const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;
195
231
  let skillsBasePath;
196
232
  if (flags.output) {
197
233
  skillsBasePath = path.resolve(flags.output);
@@ -219,10 +255,6 @@ Use --force to overwrite.`, {
219
255
  this.log(`Category: ${category}`);
220
256
  this.log(`Directory: ${skillDir}`);
221
257
  this.log("");
222
- if (flags["dry-run"]) {
223
- this.log("[DRY RUN] Would create skill files");
224
- return;
225
- }
226
258
  this.log("Creating skill files...");
227
259
  try {
228
260
  const skillMdContent = generateSkillMd(args.name);
@@ -230,7 +262,13 @@ Use --force to overwrite.`, {
230
262
  const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);
231
263
  await writeFile(skillMdPath, skillMdContent);
232
264
  const contentHash = await computeSkillFolderHash(skillDir);
233
- const metadataContent = generateMetadataYaml(args.name, author, category, contentHash);
265
+ const metadataContent = generateMetadataYaml(
266
+ args.name,
267
+ author,
268
+ category,
269
+ contentHash,
270
+ domain
271
+ );
234
272
  await writeFile(metadataPath, metadataContent);
235
273
  this.log("");
236
274
  this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${skillMdPath}`);
@@ -239,12 +277,25 @@ Use --force to overwrite.`, {
239
277
  const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, "marketplace.json");
240
278
  if (await fileExists(marketplacePath)) {
241
279
  try {
242
- await this.updateConfigFiles(projectDir, args.name, category);
280
+ await this.updateConfigFiles(projectDir, args.name, category, domain);
243
281
  } catch (error) {
244
282
  this.warn(`Could not update config files: ${getErrorMessage(error)}`);
245
283
  }
246
284
  }
247
285
  }
286
+ if (configTypesReady) {
287
+ try {
288
+ await regenerateConfigTypes(projectDir, configTypesReady, {
289
+ extraSkillIds: [args.name],
290
+ extraDomains: [domain],
291
+ extraCategories: [category]
292
+ });
293
+ } catch (error) {
294
+ this.warn(
295
+ `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`
296
+ );
297
+ }
298
+ }
248
299
  this.log("");
249
300
  this.log(
250
301
  `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`
@@ -254,50 +305,27 @@ Use --force to overwrite.`, {
254
305
  this.handleError(error);
255
306
  }
256
307
  }
257
- async updateConfigFiles(projectRoot, skillName, category) {
258
- const categoriesPath = path.join(projectRoot, SKILL_CATEGORIES_YAML_PATH);
259
- const rulesPath = path.join(projectRoot, SKILL_RULES_YAML_PATH);
308
+ async updateConfigFiles(projectRoot, skillName, category, domain) {
309
+ const categoriesPath = path.join(projectRoot, SKILL_CATEGORIES_PATH);
310
+ const rulesPath = path.join(projectRoot, SKILL_RULES_PATH);
260
311
  if (await fileExists(categoriesPath)) {
261
- const content = await readFile(categoriesPath);
262
- const parsed = parseYaml(content);
312
+ const parsed = await loadConfig(categoriesPath) ?? {};
263
313
  const categories = parsed.categories ?? {};
264
314
  if (!categories[category]) {
265
- const prefix = category.split("-")[0];
266
- const subcategoryPart = category.includes("-") ? category.slice(category.indexOf("-") + 1) : category;
267
- const entry = {
268
- id: category,
269
- displayName: toTitleCase(subcategoryPart),
270
- description: `Skills for ${toTitleCase(subcategoryPart)}`,
271
- exclusive: true,
272
- required: false,
273
- order: DEFAULT_CATEGORY_ORDER,
274
- custom: true
275
- };
276
- if (KNOWN_DOMAINS.has(prefix)) entry.domain = prefix;
277
- categories[category] = entry;
315
+ categories[category] = buildCategoryEntry(category, domain);
278
316
  parsed.categories = categories;
279
- await writeFile(categoriesPath, stringifyYaml(parsed));
280
- verbose(`Added category '${category}' to ${SKILL_CATEGORIES_YAML_PATH}`);
317
+ await writeFile(categoriesPath, formatTsExport(CATEGORIES_TS_COMMENT, parsed));
318
+ verbose(`Added category '${category}' to ${SKILL_CATEGORIES_PATH}`);
281
319
  }
282
320
  } else {
283
321
  await ensureDir(path.dirname(categoriesPath));
284
- await writeFile(categoriesPath, generateSkillCategoriesYaml(category));
285
- verbose(`Created ${SKILL_CATEGORIES_YAML_PATH}`);
322
+ await writeFile(categoriesPath, generateSkillCategoriesTs(category, domain));
323
+ verbose(`Created ${SKILL_CATEGORIES_PATH}`);
286
324
  }
287
- if (await fileExists(rulesPath)) {
288
- const content = await readFile(rulesPath);
289
- const parsed = parseYaml(content);
290
- const aliases = parsed.aliases ?? {};
291
- if (!aliases[skillName]) {
292
- aliases[skillName] = skillName;
293
- parsed.aliases = aliases;
294
- await writeFile(rulesPath, stringifyYaml(parsed));
295
- verbose(`Added alias '${skillName}' to ${SKILL_RULES_YAML_PATH}`);
296
- }
297
- } else {
325
+ if (!await fileExists(rulesPath)) {
298
326
  await ensureDir(path.dirname(rulesPath));
299
- await writeFile(rulesPath, generateSkillRulesYaml(skillName));
300
- verbose(`Created ${SKILL_RULES_YAML_PATH}`);
327
+ await writeFile(rulesPath, generateSkillRulesTs());
328
+ verbose(`Created ${SKILL_RULES_PATH}`);
301
329
  }
302
330
  }
303
331
  };
@@ -307,8 +335,8 @@ export {
307
335
  toTitleCase,
308
336
  generateSkillMd,
309
337
  generateMetadataYaml,
310
- generateSkillCategoriesYaml,
311
- generateSkillRulesYaml,
338
+ generateSkillCategoriesTs,
339
+ generateSkillRulesTs,
312
340
  NewSkill
313
341
  };
314
- //# sourceMappingURL=chunk-WFFV254H.js.map
342
+ //# sourceMappingURL=chunk-IEEVXLJB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/new/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { resolveAuthor } from \"../../lib/configuration/index.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { loadConfig } from \"../../lib/configuration/config-loader.js\";\nimport { writeFile, directoryExists, fileExists, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { verbose } from \"../../utils/logger.js\";\nimport {\n CLI_BIN_NAME,\n DEFAULT_VERSION,\n KEBAB_CASE_PATTERN,\n LOCAL_SKILLS_PATH,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { detectInstallation } from \"../../lib/installation/index.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { computeSkillFolderHash } from \"../../lib/versioning.js\";\nimport type { CategoryPath } from \"../../types/index.js\";\n\nexport function validateSkillName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Skill name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Skill name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function toTitleCase(kebabCase: string): string {\n return kebabCase\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\nexport function generateSkillMd(name: string): string {\n const titleName = toTitleCase(name);\n\n return `---\nname: ${name}\ndescription: Brief description of this skill\n---\n\n# ${titleName}\n\n> **Quick Guide:** Add a brief summary of what this skill teaches.\n\n---\n\n<critical_requirements>\n\n## CRITICAL: Before Using This Skill\n\n**(Add critical requirements here)**\n\n</critical_requirements>\n\n---\n\n**When to use:**\n\n- Add use cases here\n\n**Key patterns covered:**\n\n- Add patterns here\n\n---\n\n<patterns>\n\n## Core Patterns\n\n### Pattern 1: Example Pattern\n\nAdd your patterns here.\n\n</patterns>\n\n---\n\n<critical_reminders>\n\n## CRITICAL REMINDERS\n\n**(Repeat critical requirements here)**\n\n</critical_reminders>\n`;\n}\n\nexport function generateMetadataYaml(\n name: string,\n author: string,\n category: CategoryPath,\n contentHash: string,\n domain: string,\n): string {\n const titleName = toTitleCase(name);\n\n return `custom: true\ndomain: ${domain}\ncategory: ${category}\nauthor: \"${author}\"\ndisplayName: ${titleName}\nslug: ${name}\ncliDescription: Brief description\nusageGuidance: Use when <guidance>.\ncontentHash: ${contentHash}\ntags:\n - local\n - custom\n`;\n}\n\nconst DEFAULT_CATEGORY_ORDER = 99;\n\nconst CATEGORIES_TS_COMMENT = \"// Skill category definitions\";\nconst RULES_TS_COMMENT = \"// Skill rules configuration\";\n\nfunction formatTsExport(comment: string, data: unknown): string {\n const body = JSON.stringify(data, null, 2);\n return `${comment}\\nexport default ${body};\\n`;\n}\n\nfunction buildCategoryEntry(category: CategoryPath, domain: string): Record<string, unknown> {\n const categoryPart = category.includes(\"-\")\n ? category.slice(category.indexOf(\"-\") + 1)\n : category;\n const entry: Record<string, unknown> = {\n id: category,\n displayName: toTitleCase(categoryPart),\n description: `Skills for ${toTitleCase(categoryPart)}`,\n exclusive: true,\n required: false,\n order: DEFAULT_CATEGORY_ORDER,\n custom: true,\n };\n entry.domain = domain;\n return entry;\n}\n\nexport function generateSkillCategoriesTs(category: CategoryPath, domain: string): string {\n const entry = buildCategoryEntry(category, domain);\n const data = {\n version: DEFAULT_VERSION,\n categories: {\n [category]: entry,\n },\n };\n return formatTsExport(CATEGORIES_TS_COMMENT, data);\n}\n\nexport function generateSkillRulesTs(): string {\n const data = {\n version: DEFAULT_VERSION,\n relationships: {\n conflicts: [],\n discourages: [],\n recommends: [],\n requires: [],\n alternatives: [],\n },\n };\n return formatTsExport(RULES_TS_COMMENT, data);\n}\n\nexport default class NewSkill extends BaseCommand {\n static summary = \"Create a new local skill with proper structure\";\n static description = \"Create a new local skill scaffold with SKILL.md and metadata.yaml files\";\n\n static args = {\n name: Args.string({\n description: \"Name of the skill to create (kebab-case)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n author: Flags.string({\n char: \"a\",\n description: \"Author identifier (e.g., @myhandle)\",\n required: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Skill category\",\n default: LOCAL_DEFAULTS.CATEGORY,\n }),\n domain: Flags.string({\n char: \"d\",\n description: \"Domain for the skill (e.g., web, api, cli)\",\n required: false,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skill directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory for the skill (overrides marketplace detection)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewSkill);\n const projectDir = process.cwd();\n\n if (!flags.output) {\n const installation = await detectInstallation(projectDir);\n if (!installation) {\n this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n // Kick off background loading for config-types.ts regeneration (non-blocking)\n const configTypesReady = flags.output\n ? null\n : loadConfigTypesDataInBackground(flags.source, projectDir);\n\n this.log(\"\");\n this.log(\"Create New Skill\");\n this.log(\"\");\n\n const validationError = validateSkillName(args.name);\n if (validationError) {\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Determine author: flag > project config > default\n let author = flags.author;\n if (!author) {\n author = (await resolveAuthor(projectDir)) || LOCAL_DEFAULTS.AUTHOR;\n }\n\n // CLI flag is an untyped string — cast at data boundary\n const category = flags.category as CategoryPath;\n\n const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;\n\n // Determine skill output path: --output flag > marketplace detection > local default\n let skillsBasePath: string;\n if (flags.output) {\n skillsBasePath = path.resolve(flags.output);\n } else {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);\n skillsBasePath = path.join(projectDir, SKILLS_DIR_PATH);\n } else {\n skillsBasePath = path.join(projectDir, LOCAL_SKILLS_PATH);\n }\n }\n\n const skillDir = path.join(skillsBasePath, args.name);\n\n if (await directoryExists(skillDir)) {\n if (!flags.force) {\n this.error(`Skill directory already exists: ${skillDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing skill at ${skillDir}`);\n }\n\n this.log(`Skill name: ${args.name}`);\n this.log(`Author: ${author}`);\n this.log(`Category: ${category}`);\n this.log(`Directory: ${skillDir}`);\n this.log(\"\");\n\n this.log(\"Creating skill files...\");\n\n try {\n const skillMdContent = generateSkillMd(args.name);\n\n const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n\n await writeFile(skillMdPath, skillMdContent);\n\n const contentHash = await computeSkillFolderHash(skillDir);\n const metadataContent = generateMetadataYaml(\n args.name,\n author,\n category,\n contentHash,\n domain,\n );\n await writeFile(metadataPath, metadataContent);\n\n this.log(\"\");\n this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${skillMdPath}`);\n this.logSuccess(`Created ${STANDARD_FILES.METADATA_YAML} at ${metadataPath}`);\n\n // Update config files when in marketplace context\n if (!flags.output) {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n try {\n await this.updateConfigFiles(projectDir, args.name, category, domain);\n } catch (error) {\n this.warn(`Could not update config files: ${getErrorMessage(error)}`);\n }\n }\n }\n\n // Regenerate config-types.ts to include the new skill\n if (configTypesReady) {\n try {\n await regenerateConfigTypes(projectDir, configTypesReady, {\n extraSkillIds: [args.name],\n extraDomains: [domain],\n extraCategories: [category],\n });\n } catch (error) {\n this.warn(\n `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`,\n );\n }\n }\n\n this.log(\"\");\n this.log(\n `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async updateConfigFiles(\n projectRoot: string,\n skillName: string,\n category: CategoryPath,\n domain: string,\n ): Promise<void> {\n const categoriesPath = path.join(projectRoot, SKILL_CATEGORIES_PATH);\n const rulesPath = path.join(projectRoot, SKILL_RULES_PATH);\n\n // Update skill-categories.ts\n if (await fileExists(categoriesPath)) {\n // Boundary cast: loadConfig returns unknown structure from TS file\n const parsed = (await loadConfig<Record<string, unknown>>(categoriesPath)) ?? {};\n const categories = (parsed.categories ?? {}) as Record<string, unknown>;\n if (!categories[category]) {\n categories[category] = buildCategoryEntry(category, domain);\n parsed.categories = categories;\n await writeFile(categoriesPath, formatTsExport(CATEGORIES_TS_COMMENT, parsed));\n verbose(`Added category '${category}' to ${SKILL_CATEGORIES_PATH}`);\n }\n } else {\n await ensureDir(path.dirname(categoriesPath));\n await writeFile(categoriesPath, generateSkillCategoriesTs(category, domain));\n verbose(`Created ${SKILL_CATEGORIES_PATH}`);\n }\n\n // Create skill-rules.ts if it doesn't exist (no aliases to update — slugs are in metadata.yaml)\n if (!(await fileExists(rulesPath))) {\n await ensureDir(path.dirname(rulesPath));\n await writeFile(rulesPath, generateSkillRulesTs());\n verbose(`Created ${SKILL_RULES_PATH}`);\n }\n }\n}\n"],"mappings":"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","names":[]}