@agents-inc/cli 0.50.0 → 0.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +155 -5
- package/dist/{chunk-YDYRAXSY.js → chunk-52M2XF3W.js} +6 -6
- package/dist/{chunk-2BWCR762.js → chunk-52XO4ULK.js} +6 -8
- package/dist/chunk-52XO4ULK.js.map +1 -0
- package/dist/{chunk-KQOU4POU.js → chunk-6G3KZSO4.js} +72 -51
- package/dist/chunk-6G3KZSO4.js.map +1 -0
- package/dist/{chunk-AWP5A6IM.js → chunk-6OWHQ7HM.js} +14 -12
- package/dist/chunk-6OWHQ7HM.js.map +1 -0
- package/dist/{chunk-D72AFYQR.js → chunk-7FMEMXJ4.js} +71 -71
- package/dist/chunk-7FMEMXJ4.js.map +1 -0
- package/dist/{chunk-RA2IPRO2.js → chunk-AJJJE7F7.js} +2 -2
- package/dist/{chunk-4R52TQ3K.js → chunk-AX3SZZWA.js} +2 -2
- package/dist/{chunk-U2W5SENM.js → chunk-BFD5NZQ4.js} +5 -4
- package/dist/chunk-BFD5NZQ4.js.map +1 -0
- package/dist/{chunk-HYEUETIC.js → chunk-BKJHAJQW.js} +2 -2
- package/dist/{chunk-HYEUETIC.js.map → chunk-BKJHAJQW.js.map} +1 -1
- package/dist/{chunk-DCE423KO.js → chunk-BMJZBLP7.js} +5 -5
- package/dist/{chunk-GBOW6FUW.js → chunk-BNQ5O6LE.js} +2 -2
- package/dist/{chunk-KAO3LKB5.js → chunk-C577AJE7.js} +3 -3
- package/dist/{chunk-C3Q43WLC.js → chunk-CIG7IKX3.js} +4 -4
- package/dist/chunk-EC3UJRKZ.js +1534 -0
- package/dist/chunk-EC3UJRKZ.js.map +1 -0
- package/dist/{chunk-I6IOGZSZ.js → chunk-EMIUPGPL.js} +11 -15
- package/dist/chunk-EMIUPGPL.js.map +1 -0
- package/dist/{chunk-4QWDB2MD.js → chunk-G6WHCALR.js} +127 -105
- package/dist/chunk-G6WHCALR.js.map +1 -0
- package/dist/{chunk-JFF7P4LC.js → chunk-H7WJK7NJ.js} +22 -6
- package/dist/chunk-H7WJK7NJ.js.map +1 -0
- package/dist/chunk-HGTC76BX.js +16 -0
- package/dist/chunk-HGTC76BX.js.map +1 -0
- package/dist/{chunk-RDWGYKDY.js → chunk-K6OLORQL.js} +6 -6
- package/dist/{chunk-XDSVV5GZ.js → chunk-KIWFEBKH.js} +41 -11
- package/dist/chunk-KIWFEBKH.js.map +1 -0
- package/dist/{chunk-WBHPCBVN.js → chunk-LWXRUR6B.js} +66 -94
- package/dist/chunk-LWXRUR6B.js.map +1 -0
- package/dist/{chunk-CMNKHDOX.js → chunk-MGNYPVOJ.js} +2 -2
- package/dist/{chunk-5FPIKTSA.js → chunk-MKCHLXMY.js} +7 -7
- package/dist/{chunk-U7X4V4HE.js → chunk-MMFQNJPE.js} +2 -2
- package/dist/{chunk-WLZHCM7O.js → chunk-MR6OBL3B.js} +3 -11
- package/dist/{chunk-WLZHCM7O.js.map → chunk-MR6OBL3B.js.map} +1 -1
- package/dist/{chunk-RFKDGJAJ.js → chunk-O6BA7Q2B.js} +6 -6
- package/dist/chunk-O6BA7Q2B.js.map +1 -0
- package/dist/chunk-OCEFD7V6.js +201 -0
- package/dist/chunk-OCEFD7V6.js.map +1 -0
- package/dist/{chunk-YZTWZVGX.js → chunk-PUT7X3GA.js} +1 -1
- package/dist/chunk-PUT7X3GA.js.map +1 -0
- package/dist/{chunk-WFFV254H.js → chunk-RO6LX3UV.js} +110 -82
- package/dist/chunk-RO6LX3UV.js.map +1 -0
- package/dist/{chunk-QYLCINGC.js → chunk-SDKCQXWE.js} +2 -2
- package/dist/{chunk-M3GQ2R3E.js → chunk-SEJF7CGJ.js} +19 -7
- package/dist/chunk-SEJF7CGJ.js.map +1 -0
- package/dist/{chunk-SPFHPHYL.js → chunk-SZRK3VOR.js} +24 -14
- package/dist/chunk-SZRK3VOR.js.map +1 -0
- package/dist/{chunk-QB5HHTAA.js → chunk-TC3NHO34.js} +28 -12
- package/dist/chunk-TC3NHO34.js.map +1 -0
- package/dist/{chunk-5L724R4C.js → chunk-TGLRDEEL.js} +8 -13
- package/dist/chunk-TGLRDEEL.js.map +1 -0
- package/dist/{chunk-HMSHB5EQ.js → chunk-TZXYBG3R.js} +3544 -3037
- package/dist/chunk-TZXYBG3R.js.map +1 -0
- package/dist/{chunk-PGY5XROM.js → chunk-VR3CDXDT.js} +2 -6
- package/dist/chunk-VR3CDXDT.js.map +1 -0
- package/dist/{chunk-5FCHJLM7.js → chunk-WF6RM73R.js} +252 -38
- package/dist/chunk-WF6RM73R.js.map +1 -0
- package/dist/{chunk-3VOL4WEG.js → chunk-WYVDNGJB.js} +3 -3
- package/dist/{chunk-WJHFV6RI.js → chunk-X5EG4EFP.js} +2 -2
- package/dist/{chunk-JWYRXE6C.js → chunk-XUDTFI4M.js} +2 -2
- package/dist/{chunk-7LV4V6A4.js → chunk-YHCYKUA3.js} +14 -10
- package/dist/chunk-YHCYKUA3.js.map +1 -0
- package/dist/commands/build/marketplace.js +4 -4
- package/dist/commands/build/plugins.js +9 -7
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +13 -10
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +42 -71
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/index.js +7 -5
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +8 -6
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/show.js +7 -5
- package/dist/commands/diff.js +9 -7
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +20 -16
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +175 -79
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +20 -41
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +10 -18
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +21 -20
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +32 -31
- package/dist/commands/list.js +8 -6
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +23 -11
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +63 -46
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +11 -9
- package/dist/commands/outdated.js +9 -7
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +45 -35
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +93 -123
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +11 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +23 -27
- package/dist/commands/validate.js.map +1 -1
- package/dist/components/common/confirm.test.js +4 -4
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +3 -3
- package/dist/components/wizard/category-grid.test.js +4 -4
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/checkbox-grid.js +5 -5
- package/dist/components/wizard/checkbox-grid.test.js +6 -6
- package/dist/components/wizard/domain-selection.js +12 -11
- package/dist/components/wizard/help-modal.js +2 -2
- package/dist/components/wizard/menu-item.js +1 -1
- package/dist/components/wizard/search-modal.js +2 -2
- package/dist/components/wizard/search-modal.test.js +3 -3
- package/dist/components/wizard/search-modal.test.js.map +1 -1
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +4 -4
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/selection-card.js +2 -2
- package/dist/components/wizard/source-grid.js +4 -4
- package/dist/components/wizard/source-grid.test.js +5 -5
- package/dist/components/wizard/source-grid.test.js.map +1 -1
- package/dist/components/wizard/stack-selection.js +9 -8
- package/dist/components/wizard/step-agents.js +11 -10
- package/dist/components/wizard/step-agents.test.js +13 -12
- package/dist/components/wizard/step-agents.test.js.map +1 -1
- package/dist/components/wizard/step-build.js +11 -9
- package/dist/components/wizard/step-build.test.js +18 -22
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +4 -4
- package/dist/components/wizard/step-confirm.test.js +83 -23
- package/dist/components/wizard/step-confirm.test.js.map +1 -1
- package/dist/components/wizard/step-refine.js +2 -2
- package/dist/components/wizard/step-refine.test.js +3 -3
- package/dist/components/wizard/step-settings.js +9 -7
- package/dist/components/wizard/step-settings.test.js +13 -11
- package/dist/components/wizard/step-settings.test.js.map +1 -1
- package/dist/components/wizard/step-sources.js +13 -11
- package/dist/components/wizard/step-sources.test.js +19 -17
- package/dist/components/wizard/step-sources.test.js.map +1 -1
- package/dist/components/wizard/step-stack.js +15 -14
- package/dist/components/wizard/step-stack.test.js +17 -16
- package/dist/components/wizard/step-stack.test.js.map +1 -1
- package/dist/components/wizard/view-title.js +2 -2
- package/dist/components/wizard/wizard-layout.js +10 -8
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +2 -2
- package/dist/components/wizard/wizard.js +29 -27
- package/dist/config-exports.js +20 -0
- package/dist/config-exports.js.map +1 -0
- package/dist/hooks/init.js +34 -33
- package/dist/hooks/init.js.map +1 -1
- package/dist/loader-2O32KKAQ.js +19 -0
- package/dist/source-loader-A6B3NDI4.js +16 -0
- package/dist/source-loader-A6B3NDI4.js.map +1 -0
- package/dist/source-manager-Q7IQSGIX.js +18 -0
- package/dist/source-manager-Q7IQSGIX.js.map +1 -0
- package/dist/src/agents/meta/agent-summoner/workflow.md +3 -3
- package/dist/src/agents/meta/skill-summoner/critical-reminders.md +2 -2
- package/dist/src/agents/meta/skill-summoner/critical-requirements.md +1 -1
- package/dist/src/agents/meta/skill-summoner/intro.md +1 -1
- package/dist/src/agents/meta/skill-summoner/output-format.md +3 -3
- package/dist/src/agents/meta/skill-summoner/workflow.md +8 -8
- package/dist/stores/wizard-store.js +6 -5
- package/dist/stores/wizard-store.test.js +299 -59
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +5 -1
- package/src/agents/meta/agent-summoner/workflow.md +3 -3
- package/src/agents/meta/skill-summoner/critical-reminders.md +2 -2
- package/src/agents/meta/skill-summoner/critical-requirements.md +1 -1
- package/src/agents/meta/skill-summoner/intro.md +1 -1
- package/src/agents/meta/skill-summoner/output-format.md +3 -3
- package/src/agents/meta/skill-summoner/workflow.md +8 -8
- package/src/schemas/metadata.schema.json +6 -0
- package/src/schemas/stacks.schema.json +1 -1
- package/config/skill-categories.yaml +0 -344
- package/config/skill-rules.yaml +0 -740
- package/config/stacks.yaml +0 -1864
- package/dist/chunk-26MXZUHU.js +0 -183
- package/dist/chunk-26MXZUHU.js.map +0 -1
- package/dist/chunk-2BWCR762.js.map +0 -1
- package/dist/chunk-4QWDB2MD.js.map +0 -1
- package/dist/chunk-5FCHJLM7.js.map +0 -1
- package/dist/chunk-5L724R4C.js.map +0 -1
- package/dist/chunk-7LV4V6A4.js.map +0 -1
- package/dist/chunk-AWP5A6IM.js.map +0 -1
- package/dist/chunk-D72AFYQR.js.map +0 -1
- package/dist/chunk-HMSHB5EQ.js.map +0 -1
- package/dist/chunk-I6IOGZSZ.js.map +0 -1
- package/dist/chunk-JFF7P4LC.js.map +0 -1
- package/dist/chunk-KQOU4POU.js.map +0 -1
- package/dist/chunk-M3GQ2R3E.js.map +0 -1
- package/dist/chunk-PGY5XROM.js.map +0 -1
- package/dist/chunk-QB5HHTAA.js.map +0 -1
- package/dist/chunk-RFKDGJAJ.js.map +0 -1
- package/dist/chunk-SPFHPHYL.js.map +0 -1
- package/dist/chunk-U2W5SENM.js.map +0 -1
- package/dist/chunk-UAD3SC27.js +0 -107
- package/dist/chunk-UAD3SC27.js.map +0 -1
- package/dist/chunk-WBHPCBVN.js.map +0 -1
- package/dist/chunk-WFFV254H.js.map +0 -1
- package/dist/chunk-XDSVV5GZ.js.map +0 -1
- package/dist/chunk-YZTWZVGX.js.map +0 -1
- package/dist/commands/config/get.js +0 -61
- package/dist/commands/config/get.js.map +0 -1
- package/dist/commands/config/set-project.js +0 -61
- package/dist/commands/config/set-project.js.map +0 -1
- package/dist/commands/config/unset-project.js +0 -57
- package/dist/commands/config/unset-project.js.map +0 -1
- package/dist/config/skill-categories.yaml +0 -344
- package/dist/config/skill-rules.yaml +0 -740
- package/dist/config/stacks.yaml +0 -1864
- package/dist/source-manager-BVB2SG73.js +0 -16
- /package/dist/{chunk-YDYRAXSY.js.map → chunk-52M2XF3W.js.map} +0 -0
- /package/dist/{chunk-RA2IPRO2.js.map → chunk-AJJJE7F7.js.map} +0 -0
- /package/dist/{chunk-4R52TQ3K.js.map → chunk-AX3SZZWA.js.map} +0 -0
- /package/dist/{chunk-DCE423KO.js.map → chunk-BMJZBLP7.js.map} +0 -0
- /package/dist/{chunk-GBOW6FUW.js.map → chunk-BNQ5O6LE.js.map} +0 -0
- /package/dist/{chunk-KAO3LKB5.js.map → chunk-C577AJE7.js.map} +0 -0
- /package/dist/{chunk-C3Q43WLC.js.map → chunk-CIG7IKX3.js.map} +0 -0
- /package/dist/{chunk-RDWGYKDY.js.map → chunk-K6OLORQL.js.map} +0 -0
- /package/dist/{chunk-CMNKHDOX.js.map → chunk-MGNYPVOJ.js.map} +0 -0
- /package/dist/{chunk-5FPIKTSA.js.map → chunk-MKCHLXMY.js.map} +0 -0
- /package/dist/{chunk-U7X4V4HE.js.map → chunk-MMFQNJPE.js.map} +0 -0
- /package/dist/{chunk-QYLCINGC.js.map → chunk-SDKCQXWE.js.map} +0 -0
- /package/dist/{chunk-3VOL4WEG.js.map → chunk-WYVDNGJB.js.map} +0 -0
- /package/dist/{chunk-WJHFV6RI.js.map → chunk-X5EG4EFP.js.map} +0 -0
- /package/dist/{chunk-JWYRXE6C.js.map → chunk-XUDTFI4M.js.map} +0 -0
- /package/dist/{source-manager-BVB2SG73.js.map → loader-2O32KKAQ.js.map} +0 -0
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
Wizard
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6G3KZSO4.js";
|
|
5
5
|
import {
|
|
6
|
-
claudePluginInstall,
|
|
7
|
-
claudePluginMarketplaceAdd,
|
|
8
|
-
claudePluginMarketplaceExists
|
|
9
|
-
} from "./chunk-26MXZUHU.js";
|
|
10
|
-
import {
|
|
11
|
-
DRY_RUN_MESSAGES,
|
|
12
6
|
STATUS_MESSAGES,
|
|
13
7
|
SUCCESS_MESSAGES
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import {
|
|
16
|
-
BaseCommand,
|
|
17
|
-
EXIT_CODES
|
|
18
|
-
} from "./chunk-PGY5XROM.js";
|
|
8
|
+
} from "./chunk-MR6OBL3B.js";
|
|
19
9
|
import {
|
|
10
|
+
claudePluginInstall,
|
|
11
|
+
claudePluginMarketplaceAdd,
|
|
12
|
+
claudePluginMarketplaceExists,
|
|
13
|
+
deriveInstallMode,
|
|
14
|
+
detectGlobalInstallation,
|
|
20
15
|
detectProjectInstallation,
|
|
16
|
+
ensureBlankGlobalConfig,
|
|
21
17
|
getInstallationInfo,
|
|
22
18
|
getMarketplaceLabel,
|
|
23
19
|
hasIndividualPlugins,
|
|
@@ -25,28 +21,32 @@ import {
|
|
|
25
21
|
installPluginConfig,
|
|
26
22
|
loadProjectConfig,
|
|
27
23
|
loadSkillsMatrixFromSource
|
|
28
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-TZXYBG3R.js";
|
|
25
|
+
import {
|
|
26
|
+
BaseCommand,
|
|
27
|
+
EXIT_CODES
|
|
28
|
+
} from "./chunk-VR3CDXDT.js";
|
|
29
29
|
import {
|
|
30
30
|
disableBuffering,
|
|
31
31
|
drainBuffer,
|
|
32
32
|
enableBuffering,
|
|
33
33
|
fileExists,
|
|
34
34
|
getErrorMessage,
|
|
35
|
-
pushBufferMessage,
|
|
36
35
|
readFileSafe,
|
|
37
36
|
settingsFileSchema,
|
|
38
37
|
warn,
|
|
39
38
|
warnUnknownFields
|
|
40
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-LWXRUR6B.js";
|
|
41
40
|
import {
|
|
42
41
|
ASCII_LOGO,
|
|
43
42
|
CLAUDE_DIR,
|
|
43
|
+
CLAUDE_SRC_DIR,
|
|
44
44
|
CLI_BIN_NAME,
|
|
45
45
|
CLI_COLORS,
|
|
46
46
|
DEFAULT_BRANDING,
|
|
47
|
-
|
|
47
|
+
GLOBAL_INSTALL_ROOT,
|
|
48
48
|
MAX_CONFIG_FILE_SIZE
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-6OWHQ7HM.js";
|
|
50
50
|
import {
|
|
51
51
|
init_esm_shims
|
|
52
52
|
} from "./chunk-DHET7RCE.js";
|
|
@@ -150,7 +150,7 @@ var Dashboard = ({
|
|
|
150
150
|
}) => {
|
|
151
151
|
const { exit } = useApp();
|
|
152
152
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
153
|
-
useInput((
|
|
153
|
+
useInput((_input, key) => {
|
|
154
154
|
if (key.escape) {
|
|
155
155
|
onCancel();
|
|
156
156
|
exit();
|
|
@@ -208,11 +208,65 @@ var Dashboard = ({
|
|
|
208
208
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Use arrow keys to select, Enter to confirm, Esc to exit" })
|
|
209
209
|
] });
|
|
210
210
|
};
|
|
211
|
+
var GLOBAL_CONFIG_OPTIONS = [
|
|
212
|
+
{ label: "Edit global installation", choice: "edit-global" },
|
|
213
|
+
{ label: "Create new project installation", choice: "create-project" }
|
|
214
|
+
];
|
|
215
|
+
var GlobalConfigPrompt = ({
|
|
216
|
+
globalConfigDir,
|
|
217
|
+
onSelect,
|
|
218
|
+
onCancel
|
|
219
|
+
}) => {
|
|
220
|
+
const { exit } = useApp();
|
|
221
|
+
const [focusIndex, setFocusIndex] = useState(0);
|
|
222
|
+
useInput((_input, key) => {
|
|
223
|
+
if (key.escape) {
|
|
224
|
+
onCancel();
|
|
225
|
+
exit();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (key.return) {
|
|
229
|
+
onSelect(GLOBAL_CONFIG_OPTIONS[focusIndex].choice);
|
|
230
|
+
exit();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (key.leftArrow) {
|
|
234
|
+
setFocusIndex((i) => i > 0 ? i - 1 : GLOBAL_CONFIG_OPTIONS.length - 1);
|
|
235
|
+
}
|
|
236
|
+
if (key.rightArrow) {
|
|
237
|
+
setFocusIndex((i) => i < GLOBAL_CONFIG_OPTIONS.length - 1 ? i + 1 : 0);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
241
|
+
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
242
|
+
"A global installation was found at ",
|
|
243
|
+
globalConfigDir
|
|
244
|
+
] }),
|
|
245
|
+
/* @__PURE__ */ jsx2(Text2, { children: "What would you like to do?" }),
|
|
246
|
+
/* @__PURE__ */ jsx2(Text2, { children: " " }),
|
|
247
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
248
|
+
/* @__PURE__ */ jsx2(Text2, { children: " " }),
|
|
249
|
+
GLOBAL_CONFIG_OPTIONS.map((option, index) => /* @__PURE__ */ jsx2(Box2, { marginRight: 1, children: /* @__PURE__ */ jsxs2(
|
|
250
|
+
Text2,
|
|
251
|
+
{
|
|
252
|
+
color: index === focusIndex ? CLI_COLORS.FOCUS : void 0,
|
|
253
|
+
bold: index === focusIndex,
|
|
254
|
+
children: [
|
|
255
|
+
"[",
|
|
256
|
+
option.label,
|
|
257
|
+
"]"
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
) }, option.choice))
|
|
261
|
+
] }),
|
|
262
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Use arrow keys to select, Enter to confirm, Esc to exit" })
|
|
263
|
+
] });
|
|
264
|
+
};
|
|
211
265
|
async function getDashboardData(projectDir) {
|
|
212
266
|
const [info, loaded] = await Promise.all([getInstallationInfo(), loadProjectConfig(projectDir)]);
|
|
213
267
|
const skillCount = loaded?.config?.skills?.length ?? 0;
|
|
214
268
|
const agentCount = info?.agentCount ?? 0;
|
|
215
|
-
const mode = info?.mode ?? loaded?.config?.
|
|
269
|
+
const mode = info?.mode ?? (loaded?.config?.skills ? deriveInstallMode(loaded.config.skills) : "local");
|
|
216
270
|
const source = loaded?.config?.source;
|
|
217
271
|
return { skillCount, agentCount, mode, source };
|
|
218
272
|
}
|
|
@@ -268,18 +322,10 @@ var Init = class _Init extends BaseCommand {
|
|
|
268
322
|
description: "Start the setup wizard",
|
|
269
323
|
command: "<%= config.bin %> <%= command.id %>"
|
|
270
324
|
},
|
|
271
|
-
{
|
|
272
|
-
description: "Install globally to home directory",
|
|
273
|
-
command: "<%= config.bin %> <%= command.id %> --global"
|
|
274
|
-
},
|
|
275
325
|
{
|
|
276
326
|
description: "Initialize from a custom marketplace",
|
|
277
327
|
command: "<%= config.bin %> <%= command.id %> --source github:org/marketplace"
|
|
278
328
|
},
|
|
279
|
-
{
|
|
280
|
-
description: "Preview without creating files",
|
|
281
|
-
command: "<%= config.bin %> <%= command.id %> --dry-run"
|
|
282
|
-
},
|
|
283
329
|
{
|
|
284
330
|
description: "Force refresh skills from remote",
|
|
285
331
|
command: "<%= config.bin %> <%= command.id %> --refresh"
|
|
@@ -287,11 +333,6 @@ var Init = class _Init extends BaseCommand {
|
|
|
287
333
|
];
|
|
288
334
|
static flags = {
|
|
289
335
|
...BaseCommand.baseFlags,
|
|
290
|
-
global: Flags.boolean({
|
|
291
|
-
char: "g",
|
|
292
|
-
description: "Install globally to home directory (~/.claude-src/)",
|
|
293
|
-
default: false
|
|
294
|
-
}),
|
|
295
336
|
refresh: Flags.boolean({
|
|
296
337
|
description: "Force refresh from remote source",
|
|
297
338
|
default: false
|
|
@@ -299,7 +340,7 @@ var Init = class _Init extends BaseCommand {
|
|
|
299
340
|
};
|
|
300
341
|
async run() {
|
|
301
342
|
const { flags } = await this.parse(_Init);
|
|
302
|
-
const projectDir =
|
|
343
|
+
const projectDir = process.cwd();
|
|
303
344
|
const individualPluginsExist = await hasIndividualPlugins(projectDir);
|
|
304
345
|
const existingInstallation = await detectProjectInstallation(projectDir);
|
|
305
346
|
if (individualPluginsExist || existingInstallation) {
|
|
@@ -309,13 +350,45 @@ var Init = class _Init extends BaseCommand {
|
|
|
309
350
|
}
|
|
310
351
|
return;
|
|
311
352
|
}
|
|
312
|
-
|
|
313
|
-
|
|
353
|
+
const globalInstallation = await detectGlobalInstallation();
|
|
354
|
+
if (globalInstallation) {
|
|
355
|
+
const globalConfigDir = path2.join(os.homedir(), CLAUDE_SRC_DIR);
|
|
356
|
+
if (process.stdin.isTTY) {
|
|
357
|
+
let globalChoice = null;
|
|
358
|
+
const { waitUntilExit: waitForPrompt } = render(
|
|
359
|
+
/* @__PURE__ */ jsx2(
|
|
360
|
+
GlobalConfigPrompt,
|
|
361
|
+
{
|
|
362
|
+
globalConfigDir,
|
|
363
|
+
onSelect: (choice) => {
|
|
364
|
+
globalChoice = choice;
|
|
365
|
+
},
|
|
366
|
+
onCancel: () => {
|
|
367
|
+
globalChoice = null;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
await waitForPrompt();
|
|
373
|
+
if (globalChoice === "edit-global") {
|
|
374
|
+
const selectedCommand = await showDashboard(os.homedir(), (msg) => this.log(msg));
|
|
375
|
+
if (selectedCommand) {
|
|
376
|
+
await this.config.runCommand(selectedCommand);
|
|
377
|
+
}
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (globalChoice === null) {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (projectDir !== GLOBAL_INSTALL_ROOT) {
|
|
386
|
+
const created = await ensureBlankGlobalConfig();
|
|
387
|
+
if (created) {
|
|
388
|
+
this.log("Created blank global config at ~/" + CLAUDE_SRC_DIR);
|
|
389
|
+
}
|
|
314
390
|
}
|
|
315
391
|
enableBuffering();
|
|
316
|
-
if (flags["dry-run"]) {
|
|
317
|
-
pushBufferMessage("info", DRY_RUN_MESSAGES.PREVIEW_NO_FILES_CREATED);
|
|
318
|
-
}
|
|
319
392
|
let sourceResult;
|
|
320
393
|
let startupMessages = [];
|
|
321
394
|
try {
|
|
@@ -343,7 +416,6 @@ var Init = class _Init extends BaseCommand {
|
|
|
343
416
|
marketplaceLabel,
|
|
344
417
|
logo: ASCII_LOGO,
|
|
345
418
|
projectDir,
|
|
346
|
-
initialInstallMode: sourceResult.marketplace ? "plugin" : "local",
|
|
347
419
|
startupMessages,
|
|
348
420
|
onComplete: (result2) => {
|
|
349
421
|
wizardResult = result2;
|
|
@@ -359,74 +431,22 @@ var Init = class _Init extends BaseCommand {
|
|
|
359
431
|
if (!result || result.cancelled) {
|
|
360
432
|
this.exit(EXIT_CODES.CANCELLED);
|
|
361
433
|
}
|
|
362
|
-
if (result.
|
|
434
|
+
if (result.skills.length === 0) {
|
|
363
435
|
this.error("No skills selected", { exit: EXIT_CODES.ERROR });
|
|
364
436
|
}
|
|
365
437
|
await this.handleInstallation(result, sourceResult, flags);
|
|
366
438
|
}
|
|
367
439
|
async handleInstallation(result, sourceResult, flags) {
|
|
368
|
-
const projectDir =
|
|
369
|
-
const
|
|
370
|
-
const dryRun = flags["dry-run"];
|
|
440
|
+
const projectDir = process.cwd();
|
|
441
|
+
const installMode = deriveInstallMode(result.skills);
|
|
371
442
|
this.log("\n");
|
|
372
|
-
this.log(`Selected ${result.
|
|
443
|
+
this.log(`Selected ${result.skills.length} skills`);
|
|
373
444
|
this.log(
|
|
374
|
-
`Install mode: ${
|
|
445
|
+
`Install mode: ${installMode === "plugin" ? "Plugin (native install)" : "Local (copy to .claude/skills/)"}`
|
|
375
446
|
);
|
|
376
|
-
if (
|
|
377
|
-
if (result.installMode === "plugin" && result.selectedStackId) {
|
|
378
|
-
const useMarketplace = !!sourceResult.marketplace;
|
|
379
|
-
if (useMarketplace) {
|
|
380
|
-
this.log(
|
|
381
|
-
`[dry-run] Would install stack "${result.selectedStackId}" from marketplace "${sourceResult.marketplace}"`
|
|
382
|
-
);
|
|
383
|
-
this.log(
|
|
384
|
-
`[dry-run] claude plugin install ${result.selectedStackId}@${sourceResult.marketplace} --scope ${pluginScope}`
|
|
385
|
-
);
|
|
386
|
-
} else {
|
|
387
|
-
this.log(
|
|
388
|
-
`[dry-run] Would compile and install stack "${result.selectedStackId}" as a native plugin`
|
|
389
|
-
);
|
|
390
|
-
this.log(
|
|
391
|
-
`[dry-run] claude plugin install ./compiled-stack/${result.selectedStackId} --scope ${pluginScope}`
|
|
392
|
-
);
|
|
393
|
-
this.log(
|
|
394
|
-
`[dry-run] Stack includes ${result.selectedSkills.length} skills and agents bundled together`
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
} else if (result.installMode === "plugin" && sourceResult.marketplace) {
|
|
398
|
-
this.log(
|
|
399
|
-
`[dry-run] Would install ${result.selectedSkills.length} skills as individual plugins from "${sourceResult.marketplace}"`
|
|
400
|
-
);
|
|
401
|
-
for (const skillId of result.selectedSkills) {
|
|
402
|
-
this.log(
|
|
403
|
-
`[dry-run] claude plugin install ${skillId}@${sourceResult.marketplace} --scope ${pluginScope}`
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
const localAgentsDir = path2.join(projectDir, CLAUDE_DIR, "agents");
|
|
407
|
-
this.log(`[dry-run] Would compile agents to ${localAgentsDir}`);
|
|
408
|
-
this.log(`[dry-run] Would save config to .claude-src/config.yaml`);
|
|
409
|
-
} else {
|
|
410
|
-
if (result.installMode === "plugin") {
|
|
411
|
-
this.log(
|
|
412
|
-
`[dry-run] Plugin Mode requires a marketplace for individual skills \u2014 would fall back to Local Mode`
|
|
413
|
-
);
|
|
414
|
-
}
|
|
415
|
-
const localSkillsDir = path2.join(projectDir, LOCAL_SKILLS_PATH);
|
|
416
|
-
const localAgentsDir = path2.join(projectDir, CLAUDE_DIR, "agents");
|
|
417
|
-
this.log(
|
|
418
|
-
`[dry-run] Would copy ${result.selectedSkills.length} skills to ${localSkillsDir}`
|
|
419
|
-
);
|
|
420
|
-
this.log(`[dry-run] Would compile agents to ${localAgentsDir}`);
|
|
421
|
-
this.log(`[dry-run] Would save config to .claude-src/config.yaml`);
|
|
422
|
-
}
|
|
423
|
-
this.log(`
|
|
424
|
-
${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
if (result.installMode === "plugin") {
|
|
447
|
+
if (installMode === "plugin") {
|
|
428
448
|
if (sourceResult.marketplace) {
|
|
429
|
-
await this.installIndividualPlugins(result, sourceResult, flags, projectDir
|
|
449
|
+
await this.installIndividualPlugins(result, sourceResult, flags, projectDir);
|
|
430
450
|
} else {
|
|
431
451
|
this.warn("Plugin Mode requires a marketplace for individual skill installation.");
|
|
432
452
|
this.log(`Falling back to Local Mode (copying to .claude/skills/)...`);
|
|
@@ -437,7 +457,7 @@ ${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
|
437
457
|
}
|
|
438
458
|
await this.installLocalMode(result, sourceResult, flags, projectDir);
|
|
439
459
|
}
|
|
440
|
-
async installIndividualPlugins(result, sourceResult, flags, projectDir
|
|
460
|
+
async installIndividualPlugins(result, sourceResult, flags, projectDir) {
|
|
441
461
|
if (sourceResult.marketplace) {
|
|
442
462
|
const marketplaceExists = await claudePluginMarketplaceExists(sourceResult.marketplace);
|
|
443
463
|
if (!marketplaceExists) {
|
|
@@ -454,8 +474,9 @@ ${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
|
454
474
|
}
|
|
455
475
|
}
|
|
456
476
|
this.log("Installing skill plugins...");
|
|
457
|
-
for (const
|
|
458
|
-
const pluginRef = `${
|
|
477
|
+
for (const skill of result.skills.filter((s) => s.source !== "local")) {
|
|
478
|
+
const pluginRef = `${skill.id}@${sourceResult.marketplace}`;
|
|
479
|
+
const pluginScope = skill.scope === "global" ? "user" : "project";
|
|
459
480
|
try {
|
|
460
481
|
await claudePluginInstall(pluginRef, pluginScope, projectDir);
|
|
461
482
|
this.log(` Installed ${pluginRef}`);
|
|
@@ -465,7 +486,8 @@ ${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
|
465
486
|
});
|
|
466
487
|
}
|
|
467
488
|
}
|
|
468
|
-
|
|
489
|
+
const pluginSkillCount = result.skills.filter((s) => s.source !== "local").length;
|
|
490
|
+
this.log(`Installed ${pluginSkillCount} skill plugins
|
|
469
491
|
`);
|
|
470
492
|
this.log("Generating configuration...");
|
|
471
493
|
try {
|
|
@@ -495,7 +517,7 @@ ${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
|
495
517
|
this.log(` ${configResult.configPath}`);
|
|
496
518
|
this.log("");
|
|
497
519
|
this.log("To customize agent-skill assignments:");
|
|
498
|
-
this.log(` 1. Edit .claude-src/config.
|
|
520
|
+
this.log(` 1. Edit .claude-src/config.ts`);
|
|
499
521
|
this.log(` 2. Run '${CLI_BIN_NAME} compile' to regenerate agents`);
|
|
500
522
|
this.log("");
|
|
501
523
|
const permissionWarning = await checkPermissions(projectDir);
|
|
@@ -548,7 +570,7 @@ ${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);
|
|
|
548
570
|
this.log(` ${installResult.configPath}`);
|
|
549
571
|
this.log("");
|
|
550
572
|
this.log("To customize agent-skill assignments:");
|
|
551
|
-
this.log(` 1. Edit .claude-src/config.
|
|
573
|
+
this.log(` 1. Edit .claude-src/config.ts`);
|
|
552
574
|
this.log(` 2. Run '${CLI_BIN_NAME} compile' to regenerate agents`);
|
|
553
575
|
this.log("");
|
|
554
576
|
const permissionWarning = await checkPermissions(projectDir);
|
|
@@ -568,4 +590,4 @@ export {
|
|
|
568
590
|
showDashboard,
|
|
569
591
|
Init
|
|
570
592
|
};
|
|
571
|
-
//# sourceMappingURL=chunk-
|
|
593
|
+
//# sourceMappingURL=chunk-G6WHCALR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/init.tsx","../src/cli/lib/permission-checker.tsx"],"sourcesContent":["import React, { useState } from \"react\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp, useInput } from \"ink\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { Wizard, type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport {\n loadSkillsMatrixFromSource,\n getMarketplaceLabel,\n type SourceLoadResult,\n} from \"../lib/loading/index.js\";\nimport {\n installLocal,\n installPluginConfig,\n detectGlobalInstallation,\n detectProjectInstallation,\n deriveInstallMode,\n} from \"../lib/installation/index.js\";\nimport { checkPermissions } from \"../lib/permission-checker.js\";\nimport { getInstallationInfo } from \"../lib/plugins/plugin-info.js\";\nimport { hasIndividualPlugins } from \"../lib/plugins/index.js\";\nimport {\n claudePluginInstall,\n claudePluginMarketplaceExists,\n claudePluginMarketplaceAdd,\n} from \"../utils/exec.js\";\nimport {\n ASCII_LOGO,\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n CLI_COLORS,\n DEFAULT_BRANDING,\n GLOBAL_INSTALL_ROOT,\n} from \"../consts.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport {\n enableBuffering,\n drainBuffer,\n disableBuffering,\n type StartupMessage,\n} from \"../utils/logger.js\";\nimport { SUCCESS_MESSAGES, STATUS_MESSAGES } from \"../utils/messages.js\";\nimport { ensureBlankGlobalConfig } from \"../lib/configuration/config-writer.js\";\n\ntype DashboardOption = {\n label: string;\n command: string;\n};\n\nconst DASHBOARD_OPTIONS: DashboardOption[] = [\n { label: \"Edit\", command: \"edit\" },\n { label: \"Compile\", command: \"compile\" },\n { label: \"Doctor\", command: \"doctor\" },\n { label: \"List\", command: \"list\" },\n];\n\ntype DashboardProps = DashboardData & {\n onSelect: (command: string) => void;\n onCancel: () => void;\n};\n\nconst Dashboard: React.FC<DashboardProps> = ({\n skillCount,\n agentCount,\n source,\n mode,\n onSelect,\n onCancel,\n}) => {\n const { exit } = useApp();\n const [focusIndex, setFocusIndex] = useState(0);\n\n useInput((_input, key) => {\n if (key.escape) {\n onCancel();\n exit();\n return;\n }\n if (key.return) {\n onSelect(DASHBOARD_OPTIONS[focusIndex].command);\n exit();\n return;\n }\n if (key.leftArrow) {\n setFocusIndex((i) => (i > 0 ? i - 1 : DASHBOARD_OPTIONS.length - 1));\n }\n if (key.rightArrow) {\n setFocusIndex((i) => (i < DASHBOARD_OPTIONS.length - 1 ? i + 1 : 0));\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>{DEFAULT_BRANDING.NAME}</Text>\n <Text> </Text>\n <Text> Skills: {skillCount} installed</Text>\n <Text> Agents: {agentCount} compiled</Text>\n <Text> Mode: {mode === \"plugin\" ? \"Plugin\" : \"Local\"}</Text>\n {source && <Text> Source: {source}</Text>}\n <Text> </Text>\n <Box>\n <Text> </Text>\n {DASHBOARD_OPTIONS.map((option, index) => (\n <Box key={option.command} marginRight={1}>\n <Text\n color={index === focusIndex ? CLI_COLORS.FOCUS : undefined}\n bold={index === focusIndex}\n >\n [{option.label}]\n </Text>\n </Box>\n ))}\n </Box>\n <Text dimColor> Use arrow keys to select, Enter to confirm, Esc to exit</Text>\n </Box>\n );\n};\n\ntype GlobalConfigChoice = \"edit-global\" | \"create-project\";\n\nconst GLOBAL_CONFIG_OPTIONS: { label: string; choice: GlobalConfigChoice }[] = [\n { label: \"Edit global installation\", choice: \"edit-global\" },\n { label: \"Create new project installation\", choice: \"create-project\" },\n];\n\ntype GlobalConfigPromptProps = {\n globalConfigDir: string;\n onSelect: (choice: GlobalConfigChoice) => void;\n onCancel: () => void;\n};\n\nconst GlobalConfigPrompt: React.FC<GlobalConfigPromptProps> = ({\n globalConfigDir,\n onSelect,\n onCancel,\n}) => {\n const { exit } = useApp();\n const [focusIndex, setFocusIndex] = useState(0);\n\n useInput((_input, key) => {\n if (key.escape) {\n onCancel();\n exit();\n return;\n }\n if (key.return) {\n onSelect(GLOBAL_CONFIG_OPTIONS[focusIndex].choice);\n exit();\n return;\n }\n if (key.leftArrow) {\n setFocusIndex((i) => (i > 0 ? i - 1 : GLOBAL_CONFIG_OPTIONS.length - 1));\n }\n if (key.rightArrow) {\n setFocusIndex((i) => (i < GLOBAL_CONFIG_OPTIONS.length - 1 ? i + 1 : 0));\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n <Text>A global installation was found at {globalConfigDir}</Text>\n <Text>What would you like to do?</Text>\n <Text> </Text>\n <Box>\n <Text> </Text>\n {GLOBAL_CONFIG_OPTIONS.map((option, index) => (\n <Box key={option.choice} marginRight={1}>\n <Text\n color={index === focusIndex ? CLI_COLORS.FOCUS : undefined}\n bold={index === focusIndex}\n >\n [{option.label}]\n </Text>\n </Box>\n ))}\n </Box>\n <Text dimColor> Use arrow keys to select, Enter to confirm, Esc to exit</Text>\n </Box>\n );\n};\n\nexport type DashboardData = {\n skillCount: number;\n agentCount: number;\n mode: string;\n source?: string;\n};\n\n/** Gathers dashboard data from the installation and project config. */\nexport async function getDashboardData(projectDir: string): Promise<DashboardData> {\n const [info, loaded] = await Promise.all([getInstallationInfo(), loadProjectConfig(projectDir)]);\n\n // Skill count from config (canonical source of truth for installed skills)\n const skillCount = loaded?.config?.skills?.length ?? 0;\n // Agent count from filesystem (compiled .md files in agents dir)\n const agentCount = info?.agentCount ?? 0;\n const mode =\n info?.mode ?? (loaded?.config?.skills ? deriveInstallMode(loaded.config.skills) : \"local\");\n const source = loaded?.config?.source;\n\n return { skillCount, agentCount, mode, source };\n}\n\n/** Formats the dashboard summary as plain text lines (for non-interactive/test output). */\nexport function formatDashboardText(data: DashboardData): string {\n const modeLabel = data.mode === \"plugin\" ? \"Plugin\" : \"Local\";\n const lines = [\n DEFAULT_BRANDING.NAME,\n \"\",\n ` Skills: ${data.skillCount} installed`,\n ` Agents: ${data.agentCount} compiled`,\n ` Mode: ${modeLabel}`,\n ];\n if (data.source) {\n lines.push(` Source: ${data.source}`);\n }\n lines.push(\"\");\n lines.push(` [Edit] [Compile] [Doctor] [List]`);\n return lines.join(\"\\n\");\n}\n\n/**\n * Shows the project dashboard and returns the selected command (or null if cancelled).\n * In non-interactive environments (no TTY), prints the summary text and returns null.\n */\nexport async function showDashboard(\n projectDir: string,\n log?: (message: string) => void,\n): Promise<string | null> {\n const data = await getDashboardData(projectDir);\n\n // Non-interactive: print text summary and exit (CI, piped, tests)\n if (!process.stdin.isTTY) {\n const output = log ?? console.log;\n output(formatDashboardText(data));\n return null;\n }\n\n let selectedCommand: string | null = null;\n\n const { waitUntilExit } = render(\n <Dashboard\n skillCount={data.skillCount}\n agentCount={data.agentCount}\n source={data.source}\n mode={data.mode}\n onSelect={(command) => {\n selectedCommand = command;\n }}\n onCancel={() => {\n selectedCommand = null;\n }}\n />,\n );\n\n await waitUntilExit();\n\n return selectedCommand;\n}\n\nexport default class Init extends BaseCommand {\n static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;\n static description =\n \"Interactive wizard to set up skills and agents. Supports Plugin Mode (native install) and Local Mode (copy to .claude/).\";\n\n static examples = [\n {\n description: \"Start the setup wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Initialize from a custom marketplace\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n {\n description: \"Force refresh skills from remote\",\n command: \"<%= config.bin %> <%= command.id %> --refresh\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n refresh: Flags.boolean({\n description: \"Force refresh from remote source\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Init);\n const projectDir = process.cwd();\n\n // For \"already initialized\" check, only look at the target directory (no global fallback)\n const individualPluginsExist = await hasIndividualPlugins(projectDir);\n const existingInstallation = await detectProjectInstallation(projectDir);\n\n if (individualPluginsExist || existingInstallation) {\n const selectedCommand = await showDashboard(projectDir, (msg) => this.log(msg));\n if (selectedCommand) {\n await this.config.runCommand(selectedCommand);\n }\n return;\n }\n\n // No project config exists: check if a global installation exists\n const globalInstallation = await detectGlobalInstallation();\n if (globalInstallation) {\n const globalConfigDir = path.join(os.homedir(), CLAUDE_SRC_DIR);\n\n // Non-interactive: skip prompt and fall through to wizard\n if (process.stdin.isTTY) {\n let globalChoice: GlobalConfigChoice | null = null;\n\n const { waitUntilExit: waitForPrompt } = render(\n <GlobalConfigPrompt\n globalConfigDir={globalConfigDir}\n onSelect={(choice) => {\n globalChoice = choice;\n }}\n onCancel={() => {\n globalChoice = null;\n }}\n />,\n );\n\n await waitForPrompt();\n\n if (globalChoice === \"edit-global\") {\n const selectedCommand = await showDashboard(os.homedir(), (msg) => this.log(msg));\n if (selectedCommand) {\n await this.config.runCommand(selectedCommand);\n }\n return;\n }\n\n // User cancelled (Esc)\n if (globalChoice === null) {\n return;\n }\n\n // \"create-project\" falls through to wizard below\n }\n }\n\n // Auto-create blank global config on first init from a project directory.\n // This ensures the project config can always import from global.\n if (projectDir !== GLOBAL_INSTALL_ROOT) {\n const created = await ensureBlankGlobalConfig();\n if (created) {\n this.log(\"Created blank global config at ~/\" + CLAUDE_SRC_DIR);\n }\n }\n\n enableBuffering();\n\n let sourceResult: SourceLoadResult;\n let startupMessages: StartupMessage[] = [];\n try {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n });\n } catch (error) {\n disableBuffering();\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n startupMessages = drainBuffer();\n disableBuffering();\n\n let wizardResult: WizardResultV2 | null = null;\n\n const marketplaceLabel = getMarketplaceLabel(sourceResult);\n const { waitUntilExit } = render(\n <Wizard\n matrix={sourceResult.matrix}\n version={this.config.version}\n marketplaceLabel={marketplaceLabel}\n logo={ASCII_LOGO}\n projectDir={projectDir}\n startupMessages={startupMessages}\n onComplete={(result) => {\n // Boundary cast: Ink render callback returns unknown result type\n wizardResult = result as WizardResultV2;\n }}\n onCancel={() => {\n this.log(\"Setup cancelled\");\n }}\n />,\n );\n\n await waitUntilExit();\n\n // Boundary cast: re-narrow after Ink waitUntilExit()\n const result = wizardResult as WizardResultV2 | null;\n if (!result || result.cancelled) {\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (result.skills.length === 0) {\n this.error(\"No skills selected\", { exit: EXIT_CODES.ERROR });\n }\n\n await this.handleInstallation(result, sourceResult, flags);\n }\n\n private async handleInstallation(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: { source?: string; refresh: boolean },\n ): Promise<void> {\n const projectDir = process.cwd();\n const installMode = deriveInstallMode(result.skills);\n\n this.log(\"\\n\");\n this.log(`Selected ${result.skills.length} skills`);\n this.log(\n `Install mode: ${installMode === \"plugin\" ? \"Plugin (native install)\" : \"Local (copy to .claude/skills/)\"}`,\n );\n\n if (installMode === \"plugin\") {\n if (sourceResult.marketplace) {\n await this.installIndividualPlugins(result, sourceResult, flags, projectDir);\n } else {\n this.warn(\"Plugin Mode requires a marketplace for individual skill installation.\");\n this.log(`Falling back to Local Mode (copying to .claude/skills/)...`);\n this.log(\"To use Plugin Mode, either select a stack or configure a marketplace source.\\n\");\n await this.installLocalMode(result, sourceResult, flags, projectDir);\n }\n return;\n }\n\n await this.installLocalMode(result, sourceResult, flags, projectDir);\n }\n\n private async installIndividualPlugins(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: { source?: string },\n projectDir: string,\n ): Promise<void> {\n if (sourceResult.marketplace) {\n const marketplaceExists = await claudePluginMarketplaceExists(sourceResult.marketplace);\n\n if (!marketplaceExists) {\n this.log(`Registering marketplace \"${sourceResult.marketplace}\"...`);\n try {\n const marketplaceSource = sourceResult.sourceConfig.source.replace(/^github:/, \"\");\n await claudePluginMarketplaceAdd(marketplaceSource);\n this.log(`Registered marketplace: ${sourceResult.marketplace}`);\n } catch (error) {\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n }\n\n this.log(\"Installing skill plugins...\");\n for (const skill of result.skills.filter((s) => s.source !== \"local\")) {\n const pluginRef = `${skill.id}@${sourceResult.marketplace}`;\n const pluginScope = skill.scope === \"global\" ? \"user\" : \"project\";\n try {\n await claudePluginInstall(pluginRef, pluginScope, projectDir);\n this.log(` Installed ${pluginRef}`);\n } catch (error) {\n this.error(`Failed to install plugin ${pluginRef}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n const pluginSkillCount = result.skills.filter((s) => s.source !== \"local\").length;\n this.log(`Installed ${pluginSkillCount} skill plugins\\n`);\n\n this.log(\"Generating configuration...\");\n try {\n const configResult = await installPluginConfig({\n wizardResult: result,\n sourceResult,\n projectDir,\n sourceFlag: flags.source,\n });\n\n if (configResult.wasMerged) {\n this.log(`Merged with existing config at ${configResult.mergedConfigPath}`);\n }\n\n this.log(`Configuration saved (${configResult.config.agents.length} agents)\\n`);\n this.log(STATUS_MESSAGES.COMPILING_AGENTS);\n this.log(`Compiled ${configResult.compiledAgents.length} agents to .claude/agents/\\n`);\n\n this.log(`${SUCCESS_MESSAGES.INIT_SUCCESS}\\n`);\n this.log(\"Agents compiled to:\");\n this.log(` ${configResult.agentsDir}`);\n for (const agentName of configResult.compiledAgents) {\n this.log(` ${agentName}.md`);\n }\n this.log(\"\");\n this.log(\"Configuration:\");\n this.log(` ${configResult.configPath}`);\n this.log(\"\");\n this.log(\"To customize agent-skill assignments:\");\n this.log(` 1. Edit .claude-src/config.ts`);\n this.log(` 2. Run '${CLI_BIN_NAME} compile' to regenerate agents`);\n this.log(\"\");\n\n const permissionWarning = await checkPermissions(projectDir);\n if (permissionWarning) {\n const { waitUntilExit } = render(permissionWarning);\n await waitUntilExit();\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async installLocalMode(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: { source?: string },\n projectDir: string,\n ): Promise<void> {\n const matrix = sourceResult.matrix;\n\n this.log(\"Copying skills to local directory...\");\n try {\n const installResult = await installLocal({\n wizardResult: result,\n sourceResult,\n projectDir,\n sourceFlag: flags.source,\n });\n\n this.log(`Copied ${installResult.copiedSkills.length} skills to .claude/skills/\\n`);\n this.log(\"Generating configuration...\");\n\n if (installResult.wasMerged) {\n this.log(`Merged with existing config at ${installResult.mergedConfigPath}`);\n }\n\n this.log(`Configuration saved (${installResult.config.agents.length} agents)\\n`);\n this.log(STATUS_MESSAGES.COMPILING_AGENTS);\n this.log(`Compiled ${installResult.compiledAgents.length} agents to .claude/agents/\\n`);\n\n this.log(`${SUCCESS_MESSAGES.INIT_SUCCESS}\\n`);\n this.log(\"Skills copied to:\");\n this.log(` ${installResult.skillsDir}`);\n for (const copiedSkill of installResult.copiedSkills) {\n const skill = matrix.skills[copiedSkill.skillId];\n const displayName = skill?.displayName || copiedSkill.skillId;\n this.log(` ${displayName}/`);\n }\n this.log(\"\");\n this.log(\"Agents compiled to:\");\n this.log(` ${installResult.agentsDir}`);\n for (const agentName of installResult.compiledAgents) {\n this.log(` ${agentName}.md`);\n }\n this.log(\"\");\n this.log(\"Configuration:\");\n this.log(` ${installResult.configPath}`);\n this.log(\"\");\n this.log(\"To customize agent-skill assignments:\");\n this.log(` 1. Edit .claude-src/config.ts`);\n this.log(` 2. Run '${CLI_BIN_NAME} compile' to regenerate agents`);\n this.log(\"\");\n\n const permissionWarning = await checkPermissions(projectDir);\n if (permissionWarning) {\n const { waitUntilExit } = render(permissionWarning);\n await waitUntilExit();\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n","import React from \"react\";\n\nimport { Text, Box } from \"ink\";\nimport path from \"path\";\n\nimport { CLAUDE_DIR, CLI_COLORS, MAX_CONFIG_FILE_SIZE } from \"../consts\";\nimport { fileExists, readFileSafe } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport { settingsFileSchema, warnUnknownFields } from \"./schemas\";\n\ntype PermissionConfig = {\n allow?: string[];\n deny?: string[];\n};\n\ntype SettingsFile = {\n permissions?: PermissionConfig;\n};\n\nexport async function checkPermissions(projectRoot: string): Promise<React.ReactElement | null> {\n const settingsPath = path.join(projectRoot, CLAUDE_DIR, \"settings.json\");\n const localSettingsPath = path.join(projectRoot, CLAUDE_DIR, \"settings.local.json\");\n\n let permissions: PermissionConfig | undefined;\n\n for (const filePath of [localSettingsPath, settingsPath]) {\n if (await fileExists(filePath)) {\n try {\n const content = await readFileSafe(filePath, MAX_CONFIG_FILE_SIZE);\n const raw = JSON.parse(content);\n if (typeof raw === \"object\" && raw !== null && !Array.isArray(raw)) {\n // Known Claude CLI settings.json fields (permissions is ours; the rest are managed by Claude CLI)\n const EXPECTED_SETTINGS_KEYS = [\n \"permissions\",\n \"enabledPlugins\",\n \"env\",\n \"allowedTools\",\n \"customInstructions\",\n \"defaultModel\",\n ] as const;\n warnUnknownFields(\n raw as Record<string, unknown>,\n EXPECTED_SETTINGS_KEYS,\n `settings file '${filePath}'`,\n );\n }\n const result = settingsFileSchema.safeParse(raw);\n const parsed: SettingsFile = result.success ? (result.data as SettingsFile) : {};\n if (parsed.permissions) {\n permissions = parsed.permissions;\n break;\n }\n } catch {\n warn(`Malformed settings file at '${filePath}' — skipping`);\n }\n }\n }\n\n if (!permissions) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Notice\n </Text>\n <Text>No permissions configured in .claude/settings.json</Text>\n <Text>Agents will prompt for approval on each tool use.</Text>\n <Text> </Text>\n <Text>For autonomous operation, add to .claude/settings.json:</Text>\n <Text> </Text>\n <Text color=\"dim\">{\"{\"}</Text>\n <Text color=\"dim\">{' \"permissions\": {'}</Text>\n <Text color=\"dim\">{' \"allow\": ['}</Text>\n <Text color=\"dim\">{' \"Read(*)\",'}</Text>\n <Text color=\"dim\">{' \"Bash(git *)\",'}</Text>\n <Text color=\"dim\">{' \"Bash(bun *)\"'}</Text>\n <Text color=\"dim\">{\" ]\"}</Text>\n <Text color=\"dim\">{\" }\"}</Text>\n <Text color=\"dim\">{\"}\"}</Text>\n </Box>\n );\n }\n\n const hasRestrictiveBash = permissions.deny?.some(\n (rule) => rule === \"Bash(*)\" || rule === \"Bash\",\n );\n const hasNoAllows = !permissions.allow || permissions.allow.length === 0;\n\n if (hasRestrictiveBash || hasNoAllows) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Warnings\n </Text>\n {hasRestrictiveBash && (\n <Text>\n ⚠ Bash is denied in permissions. Some agents require Bash for git, testing, and build\n commands.\n </Text>\n )}\n {hasNoAllows && (\n <Text>⚠ No allow rules configured. Agents will prompt for each tool use.</Text>\n )}\n </Box>\n );\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAgB,gBAAgB;AAEhC,SAAS,aAAa;AACtB,SAAS,QAAQ,OAAAA,MAAK,QAAAC,OAAM,QAAQ,gBAAgB;AACpD,OAAO,QAAQ;AACf,OAAOC,WAAU;;;ACLjB;AAEA,SAAS,MAAM,WAAW;AAC1B,OAAO,UAAU;AAyDX,SACE,KADF;AAzCN,eAAsB,iBAAiB,aAAyD;AAC9F,QAAM,eAAe,KAAK,KAAK,aAAa,YAAY,eAAe;AACvE,QAAM,oBAAoB,KAAK,KAAK,aAAa,YAAY,qBAAqB;AAElF,MAAI;AAEJ,aAAW,YAAY,CAAC,mBAAmB,YAAY,GAAG;AACxD,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,UAAI;AACF,cAAM,UAAU,MAAM,aAAa,UAAU,oBAAoB;AACjE,cAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,YAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,GAAG,GAAG;AAElE,gBAAM,yBAAyB;AAAA,YAC7B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA;AAAA,YACE;AAAA,YACA;AAAA,YACA,kBAAkB,QAAQ;AAAA,UAC5B;AAAA,QACF;AACA,cAAM,SAAS,mBAAmB,UAAU,GAAG;AAC/C,cAAM,SAAuB,OAAO,UAAW,OAAO,OAAwB,CAAC;AAC/E,YAAI,OAAO,aAAa;AACtB,wBAAc,OAAO;AACrB;AAAA,QACF;AAAA,MACF,QAAQ;AACN,aAAK,+BAA+B,QAAQ,mBAAc;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,aAAa;AAChB,WACE,qBAAC,OAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,WAAW,SAAS,SAAS,GACxF;AAAA,0BAAC,QAAK,MAAI,MAAC,OAAO,WAAW,SAAS,+BAEtC;AAAA,MACA,oBAAC,QAAK,gEAAkD;AAAA,MACxD,oBAAC,QAAK,+DAAiD;AAAA,MACvD,oBAAC,QAAK,eAAC;AAAA,MACP,oBAAC,QAAK,qEAAuD;AAAA,MAC7D,oBAAC,QAAK,eAAC;AAAA,MACP,oBAAC,QAAK,OAAM,OAAO,eAAI;AAAA,MACvB,oBAAC,QAAK,OAAM,OAAO,gCAAqB;AAAA,MACxC,oBAAC,QAAK,OAAM,OAAO,4BAAiB;AAAA,MACpC,oBAAC,QAAK,OAAM,OAAO,8BAAmB;AAAA,MACtC,oBAAC,QAAK,OAAM,OAAO,kCAAuB;AAAA,MAC1C,oBAAC,QAAK,OAAM,OAAO,iCAAsB;AAAA,MACzC,oBAAC,QAAK,OAAM,OAAO,mBAAQ;AAAA,MAC3B,oBAAC,QAAK,OAAM,OAAO,iBAAM;AAAA,MACzB,oBAAC,QAAK,OAAM,OAAO,eAAI;AAAA,OACzB;AAAA,EAEJ;AAEA,QAAM,qBAAqB,YAAY,MAAM;AAAA,IAC3C,CAAC,SAAS,SAAS,aAAa,SAAS;AAAA,EAC3C;AACA,QAAM,cAAc,CAAC,YAAY,SAAS,YAAY,MAAM,WAAW;AAEvE,MAAI,sBAAsB,aAAa;AACrC,WACE,qBAAC,OAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,WAAW,SAAS,SAAS,GACxF;AAAA,0BAAC,QAAK,MAAI,MAAC,OAAO,WAAW,SAAS,iCAEtC;AAAA,MACC,sBACC,oBAAC,QAAK,kHAGN;AAAA,MAED,eACC,oBAAC,QAAK,qFAAkE;AAAA,OAE5E;AAAA,EAEJ;AAEA,SAAO;AACT;;;ADTM,gBAAAC,MAEA,QAAAC,aAFA;AA5CN,IAAM,oBAAuC;AAAA,EAC3C,EAAE,OAAO,QAAQ,SAAS,OAAO;AAAA,EACjC,EAAE,OAAO,WAAW,SAAS,UAAU;AAAA,EACvC,EAAE,OAAO,UAAU,SAAS,SAAS;AAAA,EACrC,EAAE,OAAO,QAAQ,SAAS,OAAO;AACnC;AAOA,IAAM,YAAsC,CAAC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,KAAK,IAAI,OAAO;AACxB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAE9C,WAAS,CAAC,QAAQ,QAAQ;AACxB,QAAI,IAAI,QAAQ;AACd,eAAS;AACT,WAAK;AACL;AAAA,IACF;AACA,QAAI,IAAI,QAAQ;AACd,eAAS,kBAAkB,UAAU,EAAE,OAAO;AAC9C,WAAK;AACL;AAAA,IACF;AACA,QAAI,IAAI,WAAW;AACjB,oBAAc,CAAC,MAAO,IAAI,IAAI,IAAI,IAAI,kBAAkB,SAAS,CAAE;AAAA,IACrE;AACA,QAAI,IAAI,YAAY;AAClB,oBAAc,CAAC,MAAO,IAAI,kBAAkB,SAAS,IAAI,IAAI,IAAI,CAAE;AAAA,IACrE;AAAA,EACF,CAAC;AAED,SACE,gBAAAA,MAACC,MAAA,EAAI,eAAc,UACjB;AAAA,oBAAAF,KAACG,OAAA,EAAK,MAAI,MAAE,2BAAiB,MAAK;AAAA,IAClC,gBAAAH,KAACG,OAAA,EAAK,eAAC;AAAA,IACP,gBAAAF,MAACE,OAAA,EAAK;AAAA;AAAA,MAAU;AAAA,MAAW;AAAA,OAAU;AAAA,IACrC,gBAAAF,MAACE,OAAA,EAAK;AAAA;AAAA,MAAU;AAAA,MAAW;AAAA,OAAS;AAAA,IACpC,gBAAAF,MAACE,OAAA,EAAK;AAAA;AAAA,MAAQ,SAAS,WAAW,WAAW;AAAA,OAAQ;AAAA,IACpD,UAAU,gBAAAF,MAACE,OAAA,EAAK;AAAA;AAAA,MAAU;AAAA,OAAO;AAAA,IAClC,gBAAAH,KAACG,OAAA,EAAK,eAAC;AAAA,IACP,gBAAAF,MAACC,MAAA,EACC;AAAA,sBAAAF,KAACG,OAAA,EAAK,eAAC;AAAA,MACN,kBAAkB,IAAI,CAAC,QAAQ,UAC9B,gBAAAH,KAACE,MAAA,EAAyB,aAAa,GACrC,0BAAAD;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,OAAO,UAAU,aAAa,WAAW,QAAQ;AAAA,UACjD,MAAM,UAAU;AAAA,UACjB;AAAA;AAAA,YACG,OAAO;AAAA,YAAM;AAAA;AAAA;AAAA,MACjB,KANQ,OAAO,OAOjB,CACD;AAAA,OACH;AAAA,IACA,gBAAAH,KAACG,OAAA,EAAK,UAAQ,MAAC,sEAAwD;AAAA,KACzE;AAEJ;AAIA,IAAM,wBAAyE;AAAA,EAC7E,EAAE,OAAO,4BAA4B,QAAQ,cAAc;AAAA,EAC3D,EAAE,OAAO,mCAAmC,QAAQ,iBAAiB;AACvE;AAQA,IAAM,qBAAwD,CAAC;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,KAAK,IAAI,OAAO;AACxB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAE9C,WAAS,CAAC,QAAQ,QAAQ;AACxB,QAAI,IAAI,QAAQ;AACd,eAAS;AACT,WAAK;AACL;AAAA,IACF;AACA,QAAI,IAAI,QAAQ;AACd,eAAS,sBAAsB,UAAU,EAAE,MAAM;AACjD,WAAK;AACL;AAAA,IACF;AACA,QAAI,IAAI,WAAW;AACjB,oBAAc,CAAC,MAAO,IAAI,IAAI,IAAI,IAAI,sBAAsB,SAAS,CAAE;AAAA,IACzE;AACA,QAAI,IAAI,YAAY;AAClB,oBAAc,CAAC,MAAO,IAAI,sBAAsB,SAAS,IAAI,IAAI,IAAI,CAAE;AAAA,IACzE;AAAA,EACF,CAAC;AAED,SACE,gBAAAF,MAACC,MAAA,EAAI,eAAc,UACjB;AAAA,oBAAAD,MAACE,OAAA,EAAK;AAAA;AAAA,MAAoC;AAAA,OAAgB;AAAA,IAC1D,gBAAAH,KAACG,OAAA,EAAK,wCAA0B;AAAA,IAChC,gBAAAH,KAACG,OAAA,EAAK,eAAC;AAAA,IACP,gBAAAF,MAACC,MAAA,EACC;AAAA,sBAAAF,KAACG,OAAA,EAAK,eAAC;AAAA,MACN,sBAAsB,IAAI,CAAC,QAAQ,UAClC,gBAAAH,KAACE,MAAA,EAAwB,aAAa,GACpC,0BAAAD;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,OAAO,UAAU,aAAa,WAAW,QAAQ;AAAA,UACjD,MAAM,UAAU;AAAA,UACjB;AAAA;AAAA,YACG,OAAO;AAAA,YAAM;AAAA;AAAA;AAAA,MACjB,KANQ,OAAO,MAOjB,CACD;AAAA,OACH;AAAA,IACA,gBAAAH,KAACG,OAAA,EAAK,UAAQ,MAAC,sEAAwD;AAAA,KACzE;AAEJ;AAUA,eAAsB,iBAAiB,YAA4C;AACjF,QAAM,CAAC,MAAM,MAAM,IAAI,MAAM,QAAQ,IAAI,CAAC,oBAAoB,GAAG,kBAAkB,UAAU,CAAC,CAAC;AAG/F,QAAM,aAAa,QAAQ,QAAQ,QAAQ,UAAU;AAErD,QAAM,aAAa,MAAM,cAAc;AACvC,QAAM,OACJ,MAAM,SAAS,QAAQ,QAAQ,SAAS,kBAAkB,OAAO,OAAO,MAAM,IAAI;AACpF,QAAM,SAAS,QAAQ,QAAQ;AAE/B,SAAO,EAAE,YAAY,YAAY,MAAM,OAAO;AAChD;AAGO,SAAS,oBAAoB,MAA6B;AAC/D,QAAM,YAAY,KAAK,SAAS,WAAW,WAAW;AACtD,QAAM,QAAQ;AAAA,IACZ,iBAAiB;AAAA,IACjB;AAAA,IACA,cAAc,KAAK,UAAU;AAAA,IAC7B,cAAc,KAAK,UAAU;AAAA,IAC7B,cAAc,SAAS;AAAA,EACzB;AACA,MAAI,KAAK,QAAQ;AACf,UAAM,KAAK,cAAc,KAAK,MAAM,EAAE;AAAA,EACxC;AACA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uCAAuC;AAClD,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,eAAsB,cACpB,YACA,KACwB;AACxB,QAAM,OAAO,MAAM,iBAAiB,UAAU;AAG9C,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,UAAM,SAAS,OAAO,QAAQ;AAC9B,WAAO,oBAAoB,IAAI,CAAC;AAChC,WAAO;AAAA,EACT;AAEA,MAAI,kBAAiC;AAErC,QAAM,EAAE,cAAc,IAAI;AAAA,IACxB,gBAAAH;AAAA,MAAC;AAAA;AAAA,QACC,YAAY,KAAK;AAAA,QACjB,YAAY,KAAK;AAAA,QACjB,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX,UAAU,CAAC,YAAY;AACrB,4BAAkB;AAAA,QACpB;AAAA,QACA,UAAU,MAAM;AACd,4BAAkB;AAAA,QACpB;AAAA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc;AAEpB,SAAO;AACT;AAEA,IAAqB,OAArB,MAAqB,cAAa,YAAY;AAAA,EAC5C,OAAO,UAAU,cAAc,iBAAiB,IAAI;AAAA,EACpD,OAAO,cACL;AAAA,EAEF,OAAO,WAAW;AAAA,IAChB;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,SAAS,MAAM,QAAQ;AAAA,MACrB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,KAAI;AACvC,UAAM,aAAa,QAAQ,IAAI;AAG/B,UAAM,yBAAyB,MAAM,qBAAqB,UAAU;AACpE,UAAM,uBAAuB,MAAM,0BAA0B,UAAU;AAEvE,QAAI,0BAA0B,sBAAsB;AAClD,YAAM,kBAAkB,MAAM,cAAc,YAAY,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC;AAC9E,UAAI,iBAAiB;AACnB,cAAM,KAAK,OAAO,WAAW,eAAe;AAAA,MAC9C;AACA;AAAA,IACF;AAGA,UAAM,qBAAqB,MAAM,yBAAyB;AAC1D,QAAI,oBAAoB;AACtB,YAAM,kBAAkBI,MAAK,KAAK,GAAG,QAAQ,GAAG,cAAc;AAG9D,UAAI,QAAQ,MAAM,OAAO;AACvB,YAAI,eAA0C;AAE9C,cAAM,EAAE,eAAe,cAAc,IAAI;AAAA,UACvC,gBAAAJ;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,UAAU,CAAC,WAAW;AACpB,+BAAe;AAAA,cACjB;AAAA,cACA,UAAU,MAAM;AACd,+BAAe;AAAA,cACjB;AAAA;AAAA,UACF;AAAA,QACF;AAEA,cAAM,cAAc;AAEpB,YAAI,iBAAiB,eAAe;AAClC,gBAAM,kBAAkB,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC;AAChF,cAAI,iBAAiB;AACnB,kBAAM,KAAK,OAAO,WAAW,eAAe;AAAA,UAC9C;AACA;AAAA,QACF;AAGA,YAAI,iBAAiB,MAAM;AACzB;AAAA,QACF;AAAA,MAGF;AAAA,IACF;AAIA,QAAI,eAAe,qBAAqB;AACtC,YAAM,UAAU,MAAM,wBAAwB;AAC9C,UAAI,SAAS;AACX,aAAK,IAAI,sCAAsC,cAAc;AAAA,MAC/D;AAAA,IACF;AAEA,oBAAgB;AAEhB,QAAI;AACJ,QAAI,kBAAoC,CAAC;AACzC,QAAI;AACF,qBAAe,MAAM,2BAA2B;AAAA,QAC9C,YAAY,MAAM;AAAA,QAClB;AAAA,QACA,cAAc,MAAM;AAAA,MACtB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,uBAAiB;AACjB,WAAK,MAAM,gBAAgB,KAAK,GAAG;AAAA,QACjC,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,sBAAkB,YAAY;AAC9B,qBAAiB;AAEjB,QAAI,eAAsC;AAE1C,UAAM,mBAAmB,oBAAoB,YAAY;AACzD,UAAM,EAAE,cAAc,IAAI;AAAA,MACxB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ,aAAa;AAAA,UACrB,SAAS,KAAK,OAAO;AAAA,UACrB;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,YAAY,CAACK,YAAW;AAEtB,2BAAeA;AAAA,UACjB;AAAA,UACA,UAAU,MAAM;AACd,iBAAK,IAAI,iBAAiB;AAAA,UAC5B;AAAA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc;AAGpB,UAAM,SAAS;AACf,QAAI,CAAC,UAAU,OAAO,WAAW;AAC/B,WAAK,KAAK,WAAW,SAAS;AAAA,IAChC;AAEA,QAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,WAAK,MAAM,sBAAsB,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC7D;AAEA,UAAM,KAAK,mBAAmB,QAAQ,cAAc,KAAK;AAAA,EAC3D;AAAA,EAEA,MAAc,mBACZ,QACA,cACA,OACe;AACf,UAAM,aAAa,QAAQ,IAAI;AAC/B,UAAM,cAAc,kBAAkB,OAAO,MAAM;AAEnD,SAAK,IAAI,IAAI;AACb,SAAK,IAAI,YAAY,OAAO,OAAO,MAAM,SAAS;AAClD,SAAK;AAAA,MACH,iBAAiB,gBAAgB,WAAW,4BAA4B,iCAAiC;AAAA,IAC3G;AAEA,QAAI,gBAAgB,UAAU;AAC5B,UAAI,aAAa,aAAa;AAC5B,cAAM,KAAK,yBAAyB,QAAQ,cAAc,OAAO,UAAU;AAAA,MAC7E,OAAO;AACL,aAAK,KAAK,uEAAuE;AACjF,aAAK,IAAI,4DAA4D;AACrE,aAAK,IAAI,gFAAgF;AACzF,cAAM,KAAK,iBAAiB,QAAQ,cAAc,OAAO,UAAU;AAAA,MACrE;AACA;AAAA,IACF;AAEA,UAAM,KAAK,iBAAiB,QAAQ,cAAc,OAAO,UAAU;AAAA,EACrE;AAAA,EAEA,MAAc,yBACZ,QACA,cACA,OACA,YACe;AACf,QAAI,aAAa,aAAa;AAC5B,YAAM,oBAAoB,MAAM,8BAA8B,aAAa,WAAW;AAEtF,UAAI,CAAC,mBAAmB;AACtB,aAAK,IAAI,4BAA4B,aAAa,WAAW,MAAM;AACnE,YAAI;AACF,gBAAM,oBAAoB,aAAa,aAAa,OAAO,QAAQ,YAAY,EAAE;AACjF,gBAAM,2BAA2B,iBAAiB;AAClD,eAAK,IAAI,2BAA2B,aAAa,WAAW,EAAE;AAAA,QAChE,SAAS,OAAO;AACd,eAAK,MAAM,gBAAgB,KAAK,GAAG;AAAA,YACjC,MAAM,WAAW;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,SAAK,IAAI,6BAA6B;AACtC,eAAW,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,GAAG;AACrE,YAAM,YAAY,GAAG,MAAM,EAAE,IAAI,aAAa,WAAW;AACzD,YAAM,cAAc,MAAM,UAAU,WAAW,SAAS;AACxD,UAAI;AACF,cAAM,oBAAoB,WAAW,aAAa,UAAU;AAC5D,aAAK,IAAI,eAAe,SAAS,EAAE;AAAA,MACrC,SAAS,OAAO;AACd,aAAK,MAAM,4BAA4B,SAAS,KAAK,gBAAgB,KAAK,CAAC,IAAI;AAAA,UAC7E,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,mBAAmB,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,EAAE;AAC3E,SAAK,IAAI,aAAa,gBAAgB;AAAA,CAAkB;AAExD,SAAK,IAAI,6BAA6B;AACtC,QAAI;AACF,YAAM,eAAe,MAAM,oBAAoB;AAAA,QAC7C,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,YAAY,MAAM;AAAA,MACpB,CAAC;AAED,UAAI,aAAa,WAAW;AAC1B,aAAK,IAAI,kCAAkC,aAAa,gBAAgB,EAAE;AAAA,MAC5E;AAEA,WAAK,IAAI,wBAAwB,aAAa,OAAO,OAAO,MAAM;AAAA,CAAY;AAC9E,WAAK,IAAI,gBAAgB,gBAAgB;AACzC,WAAK,IAAI,YAAY,aAAa,eAAe,MAAM;AAAA,CAA8B;AAErF,WAAK,IAAI,GAAG,iBAAiB,YAAY;AAAA,CAAI;AAC7C,WAAK,IAAI,qBAAqB;AAC9B,WAAK,IAAI,KAAK,aAAa,SAAS,EAAE;AACtC,iBAAW,aAAa,aAAa,gBAAgB;AACnD,aAAK,IAAI,OAAO,SAAS,KAAK;AAAA,MAChC;AACA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,gBAAgB;AACzB,WAAK,IAAI,KAAK,aAAa,UAAU,EAAE;AACvC,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,uCAAuC;AAChD,WAAK,IAAI,iCAAiC;AAC1C,WAAK,IAAI,aAAa,YAAY,gCAAgC;AAClE,WAAK,IAAI,EAAE;AAEX,YAAM,oBAAoB,MAAM,iBAAiB,UAAU;AAC3D,UAAI,mBAAmB;AACrB,cAAM,EAAE,cAAc,IAAI,OAAO,iBAAiB;AAClD,cAAM,cAAc;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,QACA,cACA,OACA,YACe;AACf,UAAM,SAAS,aAAa;AAE5B,SAAK,IAAI,sCAAsC;AAC/C,QAAI;AACF,YAAM,gBAAgB,MAAM,aAAa;AAAA,QACvC,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,YAAY,MAAM;AAAA,MACpB,CAAC;AAED,WAAK,IAAI,UAAU,cAAc,aAAa,MAAM;AAAA,CAA8B;AAClF,WAAK,IAAI,6BAA6B;AAEtC,UAAI,cAAc,WAAW;AAC3B,aAAK,IAAI,kCAAkC,cAAc,gBAAgB,EAAE;AAAA,MAC7E;AAEA,WAAK,IAAI,wBAAwB,cAAc,OAAO,OAAO,MAAM;AAAA,CAAY;AAC/E,WAAK,IAAI,gBAAgB,gBAAgB;AACzC,WAAK,IAAI,YAAY,cAAc,eAAe,MAAM;AAAA,CAA8B;AAEtF,WAAK,IAAI,GAAG,iBAAiB,YAAY;AAAA,CAAI;AAC7C,WAAK,IAAI,mBAAmB;AAC5B,WAAK,IAAI,KAAK,cAAc,SAAS,EAAE;AACvC,iBAAW,eAAe,cAAc,cAAc;AACpD,cAAM,QAAQ,OAAO,OAAO,YAAY,OAAO;AAC/C,cAAM,cAAc,OAAO,eAAe,YAAY;AACtD,aAAK,IAAI,OAAO,WAAW,GAAG;AAAA,MAChC;AACA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,qBAAqB;AAC9B,WAAK,IAAI,KAAK,cAAc,SAAS,EAAE;AACvC,iBAAW,aAAa,cAAc,gBAAgB;AACpD,aAAK,IAAI,OAAO,SAAS,KAAK;AAAA,MAChC;AACA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,gBAAgB;AACzB,WAAK,IAAI,KAAK,cAAc,UAAU,EAAE;AACxC,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,uCAAuC;AAChD,WAAK,IAAI,iCAAiC;AAC1C,WAAK,IAAI,aAAa,YAAY,gCAAgC;AAClE,WAAK,IAAI,EAAE;AAEX,YAAM,oBAAoB,MAAM,iBAAiB,UAAU;AAC3D,UAAI,mBAAmB;AACrB,cAAM,EAAE,cAAc,IAAI,OAAO,iBAAiB;AAClD,cAAM,cAAc;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AACF;","names":["Box","Text","path","jsx","jsxs","Box","Text","path","result"]}
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
} from "./chunk-GG4BSB6S.js";
|
|
5
5
|
import {
|
|
6
6
|
useSectionScroll
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BNQ5O6LE.js";
|
|
8
8
|
import {
|
|
9
9
|
CLI_COLORS
|
|
10
|
-
} from "./chunk-
|
|
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:
|
|
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-
|
|
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,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
BaseCommand
|
|
4
|
-
} from "./chunk-PGY5XROM.js";
|
|
5
2
|
import {
|
|
6
3
|
DEFAULT_SOURCE,
|
|
7
4
|
SOURCE_ENV_VAR,
|
|
@@ -10,10 +7,13 @@ import {
|
|
|
10
7
|
loadProjectSourceConfig,
|
|
11
8
|
resolveAgentsSource,
|
|
12
9
|
resolveSource
|
|
13
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-TZXYBG3R.js";
|
|
11
|
+
import {
|
|
12
|
+
BaseCommand
|
|
13
|
+
} from "./chunk-VR3CDXDT.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_BRANDING
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-6OWHQ7HM.js";
|
|
17
17
|
import {
|
|
18
18
|
init_esm_shims
|
|
19
19
|
} from "./chunk-DHET7RCE.js";
|
|
@@ -90,4 +90,4 @@ ${DEFAULT_BRANDING.NAME} Configuration
|
|
|
90
90
|
export {
|
|
91
91
|
ConfigShow
|
|
92
92
|
};
|
|
93
|
-
//# sourceMappingURL=chunk-
|
|
93
|
+
//# sourceMappingURL=chunk-K6OLORQL.js.map
|