@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.
- package/CHANGELOG.md +167 -5
- package/dist/{chunk-KQOU4POU.js → chunk-46DQG2N7.js} +72 -51
- package/dist/chunk-46DQG2N7.js.map +1 -0
- package/dist/{chunk-2BWCR762.js → chunk-52XO4ULK.js} +6 -8
- package/dist/chunk-52XO4ULK.js.map +1 -0
- package/dist/{chunk-DCE423KO.js → chunk-6DAZG54T.js} +5 -5
- 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-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-HMSHB5EQ.js → chunk-FWMWWE3X.js} +3543 -3037
- package/dist/chunk-FWMWWE3X.js.map +1 -0
- package/dist/{chunk-YDYRAXSY.js → chunk-GH2RQ4MI.js} +6 -6
- package/dist/{chunk-5FPIKTSA.js → chunk-H5DASUX5.js} +7 -7
- 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-WFFV254H.js → chunk-IEEVXLJB.js} +110 -82
- package/dist/chunk-IEEVXLJB.js.map +1 -0
- package/dist/{chunk-5FCHJLM7.js → chunk-IGM6HA3S.js} +252 -38
- package/dist/chunk-IGM6HA3S.js.map +1 -0
- package/dist/{chunk-QB5HHTAA.js → chunk-KD2YS76O.js} +28 -12
- package/dist/chunk-KD2YS76O.js.map +1 -0
- package/dist/{chunk-5L724R4C.js → chunk-KDO6WU76.js} +8 -13
- package/dist/chunk-KDO6WU76.js.map +1 -0
- 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-SPFHPHYL.js → chunk-M6YWRMXH.js} +24 -14
- package/dist/chunk-M6YWRMXH.js.map +1 -0
- package/dist/{chunk-CMNKHDOX.js → chunk-MGNYPVOJ.js} +2 -2
- 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-QYLCINGC.js → chunk-SDKCQXWE.js} +2 -2
- package/dist/{chunk-RDWGYKDY.js → chunk-SDLDPFNV.js} +6 -6
- package/dist/{chunk-7LV4V6A4.js → chunk-SRBN6RRD.js} +14 -10
- package/dist/chunk-SRBN6RRD.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-I6IOGZSZ.js → chunk-WHISPMAQ.js} +11 -15
- package/dist/chunk-WHISPMAQ.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-4QWDB2MD.js → chunk-YHOHLNHM.js} +127 -105
- package/dist/chunk-YHOHLNHM.js.map +1 -0
- package/dist/{chunk-M3GQ2R3E.js → chunk-Z3TM4N37.js} +19 -7
- package/dist/chunk-Z3TM4N37.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 +110 -129
- 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-KMEBBZCQ.js +16 -0
- package/dist/source-loader-KMEBBZCQ.js.map +1 -0
- package/dist/source-manager-5XBSPJNR.js +18 -0
- package/dist/source-manager-5XBSPJNR.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-DCE423KO.js.map → chunk-6DAZG54T.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-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-YDYRAXSY.js.map → chunk-GH2RQ4MI.js.map} +0 -0
- /package/dist/{chunk-5FPIKTSA.js.map → chunk-H5DASUX5.js.map} +0 -0
- /package/dist/{chunk-CMNKHDOX.js.map → chunk-MGNYPVOJ.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-RDWGYKDY.js.map → chunk-SDLDPFNV.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
package/dist/chunk-26MXZUHU.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
getErrorMessage,
|
|
4
|
-
warn
|
|
5
|
-
} from "./chunk-WBHPCBVN.js";
|
|
6
|
-
import {
|
|
7
|
-
init_esm_shims
|
|
8
|
-
} from "./chunk-DHET7RCE.js";
|
|
9
|
-
|
|
10
|
-
// src/cli/utils/exec.ts
|
|
11
|
-
init_esm_shims();
|
|
12
|
-
import { spawn } from "child_process";
|
|
13
|
-
var MAX_PLUGIN_PATH_LENGTH = 1024;
|
|
14
|
-
var MAX_PLUGIN_NAME_LENGTH = 256;
|
|
15
|
-
var MAX_MARKETPLACE_SOURCE_LENGTH = 1024;
|
|
16
|
-
var SAFE_NAME_PATTERN = /^[a-zA-Z0-9._@/-]+$/;
|
|
17
|
-
var SAFE_PLUGIN_PATH_PATTERN = /^[a-zA-Z0-9._@/:~-]+$/;
|
|
18
|
-
var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0E-\x1F\x7F]/u;
|
|
19
|
-
function validatePluginPath(pluginPath) {
|
|
20
|
-
if (!pluginPath || pluginPath.trim().length === 0) {
|
|
21
|
-
throw new Error("Plugin path must not be empty.");
|
|
22
|
-
}
|
|
23
|
-
if (pluginPath.length > MAX_PLUGIN_PATH_LENGTH) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`Plugin path is too long (${pluginPath.length} characters, max ${MAX_PLUGIN_PATH_LENGTH}).`
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
if (CONTROL_CHAR_PATTERN.test(pluginPath)) {
|
|
29
|
-
throw new Error("Plugin path contains invalid control characters.");
|
|
30
|
-
}
|
|
31
|
-
if (!SAFE_PLUGIN_PATH_PATTERN.test(pluginPath)) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Plugin path contains invalid characters: "${pluginPath}"
|
|
34
|
-
Plugin paths may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.`
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function validateMarketplaceSource(source) {
|
|
39
|
-
if (!source || source.trim().length === 0) {
|
|
40
|
-
throw new Error("Marketplace source must not be empty.");
|
|
41
|
-
}
|
|
42
|
-
if (source.length > MAX_MARKETPLACE_SOURCE_LENGTH) {
|
|
43
|
-
throw new Error(
|
|
44
|
-
`Marketplace source is too long (${source.length} characters, max ${MAX_MARKETPLACE_SOURCE_LENGTH}).`
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
if (CONTROL_CHAR_PATTERN.test(source)) {
|
|
48
|
-
throw new Error("Marketplace source contains invalid control characters.");
|
|
49
|
-
}
|
|
50
|
-
if (!SAFE_PLUGIN_PATH_PATTERN.test(source)) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
`Marketplace source contains invalid characters: "${source}"
|
|
53
|
-
Source may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function validatePluginName(pluginName) {
|
|
58
|
-
if (!pluginName || pluginName.trim().length === 0) {
|
|
59
|
-
throw new Error("Plugin name must not be empty.");
|
|
60
|
-
}
|
|
61
|
-
if (pluginName.length > MAX_PLUGIN_NAME_LENGTH) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Plugin name is too long (${pluginName.length} characters, max ${MAX_PLUGIN_NAME_LENGTH}).`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
if (CONTROL_CHAR_PATTERN.test(pluginName)) {
|
|
67
|
-
throw new Error("Plugin name contains invalid control characters.");
|
|
68
|
-
}
|
|
69
|
-
if (!SAFE_NAME_PATTERN.test(pluginName)) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Plugin name contains invalid characters: "${pluginName}"
|
|
72
|
-
Names may only contain alphanumeric characters, dashes, underscores, dots, @, and slashes.`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async function execCommand(command, args, options) {
|
|
77
|
-
return new Promise((resolve, reject) => {
|
|
78
|
-
const proc = spawn(command, args, {
|
|
79
|
-
cwd: options?.cwd,
|
|
80
|
-
env: { ...process.env, ...options?.env },
|
|
81
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
82
|
-
});
|
|
83
|
-
let stdout = "";
|
|
84
|
-
let stderr = "";
|
|
85
|
-
proc.stdout.on("data", (data) => {
|
|
86
|
-
stdout += data.toString();
|
|
87
|
-
});
|
|
88
|
-
proc.stderr.on("data", (data) => {
|
|
89
|
-
stderr += data.toString();
|
|
90
|
-
});
|
|
91
|
-
proc.on("close", (code) => {
|
|
92
|
-
resolve({
|
|
93
|
-
stdout,
|
|
94
|
-
stderr,
|
|
95
|
-
exitCode: code ?? 1
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
proc.on("error", (err) => {
|
|
99
|
-
reject(err);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
async function claudePluginInstall(pluginPath, scope, projectDir) {
|
|
104
|
-
validatePluginPath(pluginPath);
|
|
105
|
-
const args = ["plugin", "install", pluginPath, "--scope", scope];
|
|
106
|
-
const result = await execCommand("claude", args, { cwd: projectDir });
|
|
107
|
-
if (result.exitCode !== 0) {
|
|
108
|
-
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
109
|
-
throw new Error(`Plugin installation failed: ${errorMessage.trim()}`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async function isClaudeCLIAvailable() {
|
|
113
|
-
try {
|
|
114
|
-
const result = await execCommand("claude", ["--version"], {});
|
|
115
|
-
return result.exitCode === 0;
|
|
116
|
-
} catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async function claudePluginMarketplaceList() {
|
|
121
|
-
try {
|
|
122
|
-
const result = await execCommand("claude", ["plugin", "marketplace", "list", "--json"], {});
|
|
123
|
-
if (result.exitCode !== 0) {
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
let parsed;
|
|
127
|
-
try {
|
|
128
|
-
parsed = JSON.parse(result.stdout);
|
|
129
|
-
} catch {
|
|
130
|
-
warn("Failed to parse marketplace list output as JSON");
|
|
131
|
-
return [];
|
|
132
|
-
}
|
|
133
|
-
if (!Array.isArray(parsed)) {
|
|
134
|
-
warn("Unexpected marketplace list format \u2014 expected an array");
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
return parsed;
|
|
138
|
-
} catch {
|
|
139
|
-
return [];
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
async function claudePluginMarketplaceExists(name) {
|
|
143
|
-
const marketplaces = await claudePluginMarketplaceList();
|
|
144
|
-
return marketplaces.some((m) => m.name === name);
|
|
145
|
-
}
|
|
146
|
-
async function claudePluginMarketplaceAdd(source) {
|
|
147
|
-
validateMarketplaceSource(source);
|
|
148
|
-
const args = ["plugin", "marketplace", "add", source];
|
|
149
|
-
let result;
|
|
150
|
-
try {
|
|
151
|
-
result = await execCommand("claude", args, {});
|
|
152
|
-
} catch (err) {
|
|
153
|
-
throw new Error(`Failed to add marketplace: ${getErrorMessage(err)}`);
|
|
154
|
-
}
|
|
155
|
-
if (result.exitCode !== 0) {
|
|
156
|
-
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
157
|
-
if (errorMessage.includes("already installed")) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
throw new Error(`Failed to add marketplace: ${errorMessage.trim()}`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
async function claudePluginUninstall(pluginName, scope, projectDir) {
|
|
164
|
-
validatePluginName(pluginName);
|
|
165
|
-
const args = ["plugin", "uninstall", pluginName, "--scope", scope];
|
|
166
|
-
const result = await execCommand("claude", args, { cwd: projectDir });
|
|
167
|
-
if (result.exitCode !== 0) {
|
|
168
|
-
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
169
|
-
if (errorMessage.includes("not installed") || errorMessage.includes("not found")) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
throw new Error(`Plugin uninstall failed: ${errorMessage.trim()}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export {
|
|
177
|
-
claudePluginInstall,
|
|
178
|
-
isClaudeCLIAvailable,
|
|
179
|
-
claudePluginMarketplaceExists,
|
|
180
|
-
claudePluginMarketplaceAdd,
|
|
181
|
-
claudePluginUninstall
|
|
182
|
-
};
|
|
183
|
-
//# sourceMappingURL=chunk-26MXZUHU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/utils/exec.ts"],"sourcesContent":["import { spawn } from \"child_process\";\nimport { getErrorMessage } from \"./errors\";\nimport { warn } from \"./logger\";\n\n// Argument length limits to prevent oversized CLI arguments\nconst MAX_PLUGIN_PATH_LENGTH = 1024;\nconst MAX_PLUGIN_NAME_LENGTH = 256;\nconst MAX_MARKETPLACE_SOURCE_LENGTH = 1024;\n\n// Marketplace/plugin names: alphanumeric, dashes, underscores, dots, @\nconst SAFE_NAME_PATTERN = /^[a-zA-Z0-9._@/-]+$/;\n\n// Plugin path/ref: alphanumeric, dashes, underscores, dots, slashes, @, colons (for marketplace refs like skill@marketplace)\nconst SAFE_PLUGIN_PATH_PATTERN = /^[a-zA-Z0-9._@/:~-]+$/;\n\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHAR_PATTERN = /[\\x00-\\x08\\x0E-\\x1F\\x7F]/u;\n\nfunction validatePluginPath(pluginPath: string): void {\n if (!pluginPath || pluginPath.trim().length === 0) {\n throw new Error(\"Plugin path must not be empty.\");\n }\n\n if (pluginPath.length > MAX_PLUGIN_PATH_LENGTH) {\n throw new Error(\n `Plugin path is too long (${pluginPath.length} characters, max ${MAX_PLUGIN_PATH_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(pluginPath)) {\n throw new Error(\"Plugin path contains invalid control characters.\");\n }\n\n if (!SAFE_PLUGIN_PATH_PATTERN.test(pluginPath)) {\n throw new Error(\n `Plugin path contains invalid characters: \"${pluginPath}\"\\n` +\n \"Plugin paths may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.\",\n );\n }\n}\n\nfunction validateMarketplaceSource(source: string): void {\n if (!source || source.trim().length === 0) {\n throw new Error(\"Marketplace source must not be empty.\");\n }\n\n if (source.length > MAX_MARKETPLACE_SOURCE_LENGTH) {\n throw new Error(\n `Marketplace source is too long (${source.length} characters, max ${MAX_MARKETPLACE_SOURCE_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(source)) {\n throw new Error(\"Marketplace source contains invalid control characters.\");\n }\n\n if (!SAFE_PLUGIN_PATH_PATTERN.test(source)) {\n throw new Error(\n `Marketplace source contains invalid characters: \"${source}\"\\n` +\n \"Source may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.\",\n );\n }\n}\n\nfunction validatePluginName(pluginName: string): void {\n if (!pluginName || pluginName.trim().length === 0) {\n throw new Error(\"Plugin name must not be empty.\");\n }\n\n if (pluginName.length > MAX_PLUGIN_NAME_LENGTH) {\n throw new Error(\n `Plugin name is too long (${pluginName.length} characters, max ${MAX_PLUGIN_NAME_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(pluginName)) {\n throw new Error(\"Plugin name contains invalid control characters.\");\n }\n\n if (!SAFE_NAME_PATTERN.test(pluginName)) {\n throw new Error(\n `Plugin name contains invalid characters: \"${pluginName}\"\\n` +\n \"Names may only contain alphanumeric characters, dashes, underscores, dots, @, and slashes.\",\n );\n }\n}\n\nexport type ExecResult = {\n stdout: string;\n stderr: string;\n exitCode: number;\n};\n\nexport async function execCommand(\n command: string,\n args: string[],\n options?: { cwd?: string; env?: NodeJS.ProcessEnv },\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, {\n cwd: options?.cwd,\n env: { ...process.env, ...options?.env },\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout.on(\"data\", (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on(\"data\", (data) => {\n stderr += data.toString();\n });\n\n proc.on(\"close\", (code) => {\n resolve({\n stdout,\n stderr,\n exitCode: code ?? 1,\n });\n });\n\n proc.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\nexport async function claudePluginInstall(\n pluginPath: string,\n scope: \"project\" | \"user\",\n projectDir: string,\n): Promise<void> {\n validatePluginPath(pluginPath);\n\n const args = [\"plugin\", \"install\", pluginPath, \"--scope\", scope];\n const result = await execCommand(\"claude\", args, { cwd: projectDir });\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n throw new Error(`Plugin installation failed: ${errorMessage.trim()}`);\n }\n}\n\nexport async function isClaudeCLIAvailable(): Promise<boolean> {\n try {\n const result = await execCommand(\"claude\", [\"--version\"], {});\n return result.exitCode === 0;\n } catch {\n return false;\n }\n}\n\nexport type MarketplaceInfo = {\n name: string;\n source: string;\n repo?: string;\n path?: string;\n};\n\nexport async function claudePluginMarketplaceList(): Promise<MarketplaceInfo[]> {\n try {\n const result = await execCommand(\"claude\", [\"plugin\", \"marketplace\", \"list\", \"--json\"], {});\n\n if (result.exitCode !== 0) {\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n warn(\"Failed to parse marketplace list output as JSON\");\n return [];\n }\n\n if (!Array.isArray(parsed)) {\n warn(\"Unexpected marketplace list format — expected an array\");\n return [];\n }\n\n return parsed as MarketplaceInfo[];\n } catch {\n return [];\n }\n}\n\nexport async function claudePluginMarketplaceExists(name: string): Promise<boolean> {\n const marketplaces = await claudePluginMarketplaceList();\n return marketplaces.some((m) => m.name === name);\n}\n\nexport async function claudePluginMarketplaceAdd(source: string): Promise<void> {\n validateMarketplaceSource(source);\n\n const args = [\"plugin\", \"marketplace\", \"add\", source];\n let result;\n try {\n result = await execCommand(\"claude\", args, {});\n } catch (err) {\n throw new Error(`Failed to add marketplace: ${getErrorMessage(err)}`);\n }\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n if (errorMessage.includes(\"already installed\")) {\n return;\n }\n throw new Error(`Failed to add marketplace: ${errorMessage.trim()}`);\n }\n}\n\nexport async function claudePluginUninstall(\n pluginName: string,\n scope: \"project\" | \"user\",\n projectDir: string,\n): Promise<void> {\n validatePluginName(pluginName);\n\n const args = [\"plugin\", \"uninstall\", pluginName, \"--scope\", scope];\n const result = await execCommand(\"claude\", args, { cwd: projectDir });\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n // Ignore \"not installed\" errors - plugin may already be removed\n if (errorMessage.includes(\"not installed\") || errorMessage.includes(\"not found\")) {\n return;\n }\n throw new Error(`Plugin uninstall failed: ${errorMessage.trim()}`);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/help-modal.tsx"],"sourcesContent":["import { Box, Text } from \"ink\";\nimport React from \"react\";\nimport { CLI_COLORS } from \"../../consts.js\";\nimport type { WizardStep } from \"../../stores/wizard-store.js\";\n\ntype HelpSection = {\n title: string;\n keys: { key: string; description: string }[];\n};\n\nconst GLOBAL_KEYS: HelpSection = {\n title: \"Navigation\",\n keys: [\n { key: \"Arrow keys\", description: \"Move focus\" },\n { key: \"SPACE\", description: \"Toggle selection\" },\n { key: \"ENTER\", description: \"Confirm / continue\" },\n { key: \"ESC\", description: \"Go back\" },\n { key: \"TAB\", description: \"Jump to next section\" },\n ],\n};\n\nconst GLOBAL_TOGGLES: HelpSection = {\n title: \"Global Toggles\",\n keys: [\n { key: \"P\", description: \"Toggle plugin/local install mode\" },\n { key: \"?\", description: \"Toggle this help\" },\n ],\n};\n\nconst BUILD_KEYS: HelpSection = {\n title: \"Build Step\",\n keys: [\n { key: \"D\", description: \"Toggle compatibility labels\" },\n { key: \"A\", description: \"Accept stack defaults (stack path only)\" },\n { key: \"h/j/k/l\", description: \"Vim-style navigation\" },\n ],\n};\n\nconst SOURCES_KEYS: HelpSection = {\n title: \"Sources Step\",\n keys: [{ key: \"G\", description: \"Toggle source settings\" }],\n};\n\nconst AGENTS_KEYS: HelpSection = {\n title: \"Agents Step\",\n keys: [],\n};\n\nconst STEP_SECTIONS: Partial<Record<WizardStep, HelpSection>> = {\n build: BUILD_KEYS,\n sources: SOURCES_KEYS,\n agents: AGENTS_KEYS,\n};\n\nconst KEY_COLUMN_WIDTH = 14;\n\ntype HelpSectionViewProps = {\n section: HelpSection;\n};\n\nconst HelpSectionView: React.FC<HelpSectionViewProps> = ({ section }) => (\n <Box flexDirection=\"column\" marginTop={1} marginBottom={1}>\n <Text bold>{section.title}</Text>\n {section.keys.map(({ key, description }) => (\n <Box key={key} marginTop={1}>\n <Box width={KEY_COLUMN_WIDTH}>\n <Text backgroundColor=\"black\" color={CLI_COLORS.UNFOCUSED}>\n {\" \"}\n {key}{\" \"}\n </Text>\n </Box>\n <Text>{description}</Text>\n </Box>\n ))}\n </Box>\n);\n\nexport type HelpModalProps = {\n currentStep: WizardStep;\n};\n\nexport const HelpModal: React.FC<HelpModalProps> = ({ currentStep }) => {\n const stepSection = STEP_SECTIONS[currentStep];\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={CLI_COLORS.PRIMARY}\n paddingX={2}\n paddingY={1}\n marginTop={1}\n >\n <Text bold color={CLI_COLORS.PRIMARY}>\n Keyboard Shortcuts\n </Text>\n <Text> </Text>\n\n <HelpSectionView section={GLOBAL_KEYS} />\n <HelpSectionView section={GLOBAL_TOGGLES} />\n {stepSection && <HelpSectionView section={stepSection} />}\n\n <Text dimColor>Press ESC or ? to close</Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;AAAA;AAAA,SAAS,KAAK,YAAY;AA8DtB,cAIM,YAJN;AApDJ,IAAM,cAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,EAAE,KAAK,cAAc,aAAa,aAAa;AAAA,IAC/C,EAAE,KAAK,SAAS,aAAa,mBAAmB;AAAA,IAChD,EAAE,KAAK,SAAS,aAAa,qBAAqB;AAAA,IAClD,EAAE,KAAK,OAAO,aAAa,UAAU;AAAA,IACrC,EAAE,KAAK,OAAO,aAAa,uBAAuB;AAAA,EACpD;AACF;AAEA,IAAM,iBAA8B;AAAA,EAClC,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,EAAE,KAAK,KAAK,aAAa,mCAAmC;AAAA,IAC5D,EAAE,KAAK,KAAK,aAAa,mBAAmB;AAAA,EAC9C;AACF;AAEA,IAAM,aAA0B;AAAA,EAC9B,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,EAAE,KAAK,KAAK,aAAa,8BAA8B;AAAA,IACvD,EAAE,KAAK,KAAK,aAAa,0CAA0C;AAAA,IACnE,EAAE,KAAK,WAAW,aAAa,uBAAuB;AAAA,EACxD;AACF;AAEA,IAAM,eAA4B;AAAA,EAChC,OAAO;AAAA,EACP,MAAM,CAAC,EAAE,KAAK,KAAK,aAAa,yBAAyB,CAAC;AAC5D;AAEA,IAAM,cAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM,CAAC;AACT;AAEA,IAAM,gBAA0D;AAAA,EAC9D,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,IAAM,mBAAmB;AAMzB,IAAM,kBAAkD,CAAC,EAAE,QAAQ,MACjE,qBAAC,OAAI,eAAc,UAAS,WAAW,GAAG,cAAc,GACtD;AAAA,sBAAC,QAAK,MAAI,MAAE,kBAAQ,OAAM;AAAA,EACzB,QAAQ,KAAK,IAAI,CAAC,EAAE,KAAK,YAAY,MACpC,qBAAC,OAAc,WAAW,GACxB;AAAA,wBAAC,OAAI,OAAO,kBACV,+BAAC,QAAK,iBAAgB,SAAQ,OAAO,WAAW,WAC7C;AAAA;AAAA,MACA;AAAA,MAAK;AAAA,OACR,GACF;AAAA,IACA,oBAAC,QAAM,uBAAY;AAAA,OAPX,GAQV,CACD;AAAA,GACH;AAOK,IAAM,YAAsC,CAAC,EAAE,YAAY,MAAM;AACtE,QAAM,cAAc,cAAc,WAAW;AAE7C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,aAAY;AAAA,MACZ,aAAa,WAAW;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,WAAW;AAAA,MAEX;AAAA,4BAAC,QAAK,MAAI,MAAC,OAAO,WAAW,SAAS,gCAEtC;AAAA,QACA,oBAAC,QAAK,eAAC;AAAA,QAEP,oBAAC,mBAAgB,SAAS,aAAa;AAAA,QACvC,oBAAC,mBAAgB,SAAS,gBAAgB;AAAA,QACzC,eAAe,oBAAC,mBAAgB,SAAS,aAAa;AAAA,QAEvD,oBAAC,QAAK,UAAQ,MAAC,qCAAuB;AAAA;AAAA;AAAA,EACxC;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
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 detectProjectInstallation,\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_DIR,\n CLI_BIN_NAME,\n CLI_COLORS,\n DEFAULT_BRANDING,\n LOCAL_SKILLS_PATH,\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 pushBufferMessage,\n type StartupMessage,\n} from \"../utils/logger.js\";\nimport { SUCCESS_MESSAGES, STATUS_MESSAGES, DRY_RUN_MESSAGES } from \"../utils/messages.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 = {\n skillCount: number;\n agentCount: number;\n source?: string;\n mode: string;\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\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 = info?.mode ?? loaded?.config?.installMode ?? \"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: \"Install globally to home directory\",\n command: \"<%= config.bin %> <%= command.id %> --global\",\n },\n {\n description: \"Initialize from a custom marketplace\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n {\n description: \"Preview without creating files\",\n command: \"<%= config.bin %> <%= command.id %> --dry-run\",\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 global: Flags.boolean({\n char: \"g\",\n description: \"Install globally to home directory (~/.claude-src/)\",\n default: false,\n }),\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 = flags.global ? os.homedir() : 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 if (flags.global) {\n this.log(\"Installing globally to home directory...\");\n }\n\n enableBuffering();\n\n if (flags[\"dry-run\"]) {\n pushBufferMessage(\"info\", DRY_RUN_MESSAGES.PREVIEW_NO_FILES_CREATED);\n }\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 initialInstallMode={sourceResult.marketplace ? \"plugin\" : \"local\"}\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.selectedSkills.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: { \"dry-run\": boolean; source?: string; refresh: boolean; global: boolean },\n ): Promise<void> {\n const projectDir = flags.global ? os.homedir() : process.cwd();\n const pluginScope = flags.global ? \"user\" : \"project\";\n const dryRun = flags[\"dry-run\"];\n\n this.log(\"\\n\");\n this.log(`Selected ${result.selectedSkills.length} skills`);\n this.log(\n `Install mode: ${result.installMode === \"plugin\" ? \"Plugin (native install)\" : \"Local (copy to .claude/skills/)\"}`,\n );\n\n if (dryRun) {\n if (result.installMode === \"plugin\" && result.selectedStackId) {\n const useMarketplace = !!sourceResult.marketplace;\n if (useMarketplace) {\n this.log(\n `[dry-run] Would install stack \"${result.selectedStackId}\" from marketplace \"${sourceResult.marketplace}\"`,\n );\n this.log(\n `[dry-run] claude plugin install ${result.selectedStackId}@${sourceResult.marketplace} --scope ${pluginScope}`,\n );\n } else {\n this.log(\n `[dry-run] Would compile and install stack \"${result.selectedStackId}\" as a native plugin`,\n );\n this.log(\n `[dry-run] claude plugin install ./compiled-stack/${result.selectedStackId} --scope ${pluginScope}`,\n );\n this.log(\n `[dry-run] Stack includes ${result.selectedSkills.length} skills and agents bundled together`,\n );\n }\n } else if (result.installMode === \"plugin\" && sourceResult.marketplace) {\n this.log(\n `[dry-run] Would install ${result.selectedSkills.length} skills as individual plugins from \"${sourceResult.marketplace}\"`,\n );\n for (const skillId of result.selectedSkills) {\n this.log(\n `[dry-run] claude plugin install ${skillId}@${sourceResult.marketplace} --scope ${pluginScope}`,\n );\n }\n const localAgentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n this.log(`[dry-run] Would compile agents to ${localAgentsDir}`);\n this.log(`[dry-run] Would save config to .claude-src/config.yaml`);\n } else {\n if (result.installMode === \"plugin\") {\n this.log(\n `[dry-run] Plugin Mode requires a marketplace for individual skills — would fall back to Local Mode`,\n );\n }\n const localSkillsDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n const localAgentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n this.log(\n `[dry-run] Would copy ${result.selectedSkills.length} skills to ${localSkillsDir}`,\n );\n this.log(`[dry-run] Would compile agents to ${localAgentsDir}`);\n this.log(`[dry-run] Would save config to .claude-src/config.yaml`);\n }\n this.log(`\\n${DRY_RUN_MESSAGES.COMPLETE_NO_FILES_CREATED}`);\n return;\n }\n\n if (result.installMode === \"plugin\") {\n if (sourceResult.marketplace) {\n await this.installIndividualPlugins(result, sourceResult, flags, projectDir, pluginScope);\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 pluginScope: \"project\" | \"user\",\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 skillId of result.selectedSkills) {\n const pluginRef = `${skillId}@${sourceResult.marketplace}`;\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 this.log(`Installed ${result.selectedSkills.length} 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.yaml`);\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.yaml`);\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":"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","names":["Box","Text","path","jsx","jsxs","Box","Text","result","path"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/stores/wizard-store.ts"],"sourcesContent":["import { unique } from \"remeda\";\nimport { create } from \"zustand\";\nimport {\n BUILT_IN_DOMAIN_ORDER,\n DEFAULT_PRESELECTED_SKILLS,\n DEFAULT_PUBLIC_SOURCE_NAME,\n SOURCE_DISPLAY_NAMES,\n} from \"../consts.js\";\nimport { resolveAlias } from \"../lib/matrix/index.js\";\nimport { getSkillDisplayLabel } from \"../lib/wizard/build-step-logic.js\";\nimport type {\n AgentName,\n BoundSkill,\n Domain,\n DomainSelections,\n MergedSkillsMatrix,\n SkillAlias,\n SkillAssignment,\n SkillId,\n SkillSource,\n Subcategory,\n SubcategorySelections,\n} from \"../types/index.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { typedEntries, typedKeys } from \"../utils/typed-object.js\";\n\nconst BUILT_IN_DOMAINS: Domain[] = [\"web\", \"api\", \"cli\", \"mobile\", \"shared\"];\n\n/** Derive all unique domains from a categories map, preserving built-in order then appending custom. */\nfunction getAllDomainsFromCategories(\n categories: Partial<Record<Subcategory, { domain?: Domain }>>,\n): Domain[] {\n const allDomains = unique(\n Object.values(categories)\n .map((cat) => cat?.domain)\n .filter((d): d is Domain => d != null),\n );\n return [...BUILT_IN_DOMAINS, ...allDomains.filter((d) => !BUILT_IN_DOMAINS.includes(d))];\n}\n\n/** Sort domains into canonical order: built-in domains per BUILT_IN_DOMAIN_ORDER, then custom domains alphabetically. */\nfunction sortDomainsCanonically(domains: Domain[]): Domain[] {\n const builtInSet = new Set<Domain>(BUILT_IN_DOMAIN_ORDER);\n return [\n ...BUILT_IN_DOMAIN_ORDER.filter((d) => domains.includes(d)),\n ...domains.filter((d) => !builtInSet.has(d)).sort(),\n ];\n}\n\n/** Built-in agent names grouped by domain prefix. Custom domains return no preselected agents. */\nconst DOMAIN_AGENTS: Partial<Record<string, AgentName[]>> = {\n web: [\n \"web-developer\",\n \"web-reviewer\",\n \"web-researcher\",\n \"web-tester\",\n \"web-pm\",\n \"web-architecture\",\n ],\n api: [\"api-developer\", \"api-reviewer\", \"api-researcher\"],\n cli: [\"cli-developer\", \"cli-tester\", \"cli-reviewer\"],\n};\n\n/**\n * Fixed source sort tiers (lower = higher priority):\n * 1 = local/global (installed on disk -- type \"local\" or installed via plugin)\n * 2 = scoped marketplace (primary source from --source flag)\n * 3 = default public marketplace (Agents Inc)\n * 4 = third-party marketplaces (extra configured sources)\n */\nconst SOURCE_SORT_TIER_LOCAL = 1;\nconst SOURCE_SORT_TIER_SCOPED = 2;\nconst SOURCE_SORT_TIER_PUBLIC = 3;\nconst SOURCE_SORT_TIER_THIRD_PARTY = 4;\n\nfunction getSourceSortTier(source: SkillSource): number {\n if (source.type === \"local\") return SOURCE_SORT_TIER_LOCAL;\n if (source.primary) return SOURCE_SORT_TIER_SCOPED;\n if (source.type === \"public\") return SOURCE_SORT_TIER_PUBLIC;\n return SOURCE_SORT_TIER_THIRD_PARTY;\n}\n\nfunction formatSourceLabel(source: { name: string; installed?: boolean }): string {\n const displayName = SOURCE_DISPLAY_NAMES[source.name] ?? source.name;\n const prefix = source.installed ? \"\\u2713 \" : \"\";\n return `${prefix}${displayName}`;\n}\n\ntype SkillLookupEntry = { category: string; displayName?: string };\n\nfunction resolveSkillForPopulation(\n skillId: SkillId,\n skills: Partial<Record<SkillId, SkillLookupEntry>>,\n categories: Partial<Record<Subcategory, { domain?: Domain }>>,\n): { domain: Domain; subcat: Subcategory; techId: SkillId } | null {\n const skill = skills[skillId];\n if (!skill?.category) {\n warn(\n `Installed skill '${skillId}' is missing from the marketplace — it may have been removed or renamed`,\n );\n return null;\n }\n\n // Boundary cast: category is a Subcategory at the data boundary\n const subcat = skill.category as Subcategory;\n const domain = categories[subcat]?.domain;\n if (!domain) {\n warn(`Installed skill '${skillId}' has unknown category '${skill.category}' — skipping`);\n return null;\n }\n\n return { domain, subcat, techId: skillId };\n}\n\nfunction buildBoundSkillOptions(\n boundSkills: BoundSkill[],\n alias: SkillAlias,\n selectedSource: string,\n): { id: string; label: string; selected: boolean; installed: boolean }[] {\n return boundSkills\n .filter((b) => b.boundTo === alias)\n .map((bound) => ({\n id: bound.sourceName,\n label: formatSourceLabel({\n name: bound.sourceName,\n installed: false,\n }),\n selected: selectedSource === bound.sourceName,\n installed: false,\n }));\n}\n\nfunction getSkillAlias(skillId: SkillId, matrix: MergedSkillsMatrix): SkillAlias {\n const displayName = matrix.displayNames?.[skillId];\n if (displayName) return displayName;\n // Fallback: use the last segment of the skill ID (e.g., \"web-framework-react\" -> \"react\")\n const segments = skillId.split(\"-\");\n const fallback = segments[segments.length - 1] || skillId;\n warn(`No display name found for skill '${skillId}', using fallback alias '${fallback}'`);\n return fallback;\n}\n\n/**\n * Wizard step identifiers for the multi-step init/edit flow.\n *\n * Progression: stack -> build -> sources -> agents -> confirm\n * The \"stack\" step shows all stacks + \"Start from scratch\" in a unified list.\n * Navigation is tracked via the `history` stack for goBack() support.\n */\nexport type WizardStep =\n | \"stack\" // Unified first step: select stack or \"Start from scratch\", then domain selection\n | \"build\" // CategoryGrid for technology selection\n | \"sources\" // Choose skill sources (recommended vs custom)\n | \"agents\" // Select which agents to compile\n | \"confirm\"; // Final confirmation\n\n/**\n * Wizard store state and actions.\n *\n * The store uses a composition pattern: small, focused actions that each mutate\n * one or two state fields. Wizard step components compose these actions to build\n * up the full selection state incrementally (domains -> subcategories -> skills -> sources).\n *\n * State flow: unified stack/scratch selection -> domain selection -> per-domain skill\n * selection (build step) -> source customization -> confirmation.\n */\nexport type WizardState = {\n step: WizardStep;\n\n approach: \"stack\" | \"scratch\" | null;\n selectedStackId: string | null;\n stackAction: \"defaults\" | \"customize\" | null;\n\n selectedDomains: Domain[];\n\n currentDomainIndex: number;\n domainSelections: DomainSelections;\n /** Snapshot of stack-provided domain selections for restoration on domain re-toggle */\n _stackDomainSelections: DomainSelections | null;\n\n showLabels: boolean;\n\n installMode: \"plugin\" | \"local\";\n\n sourceSelections: Partial<Record<SkillId, string>>;\n customizeSources: boolean;\n\n showSettings: boolean;\n showHelp: boolean;\n enabledSources: Record<string, boolean>;\n\n selectedAgents: AgentName[];\n\n boundSkills: BoundSkill[];\n\n history: WizardStep[];\n\n /**\n * Navigate to a wizard step, pushing the current step onto history.\n * @param step - Target step to navigate to\n *\n * Side effects: sets `step`, appends previous step to `history`\n */\n setStep: (step: WizardStep) => void;\n /**\n * Set the wizard approach (stack-based or build-from-scratch).\n * @param approach - \"stack\" to use a pre-built template, \"scratch\" to select skills manually, null to reset\n *\n * Side effects: sets `approach`\n */\n setApproach: (approach: \"stack\" | \"scratch\" | null) => void;\n /**\n * Select a stack by ID, or null to deselect.\n * @param stackId - Stack identifier from suggestedStacks, or null to clear\n *\n * Side effects: sets `selectedStackId`\n */\n selectStack: (stackId: string | null) => void;\n /**\n * Set how to apply the selected stack.\n * @param action - \"defaults\" to use stack as-is, \"customize\" to enter the build step\n *\n * Side effects: sets `stackAction`\n */\n setStackAction: (action: \"defaults\" | \"customize\") => void;\n /**\n * Pre-populate domainSelections from a stack's agent-to-skill mappings.\n *\n * Iterates all agents in the stack, resolving each subcategory's skill assignments\n * to the appropriate domain. Enables all domains and deduplicates skill IDs.\n *\n * @param stack - Stack definition with agent-level skill assignments\n * @param stack.agents - Record of agent name to `{ subcategory: SkillAssignment[] }` mappings\n * @param categories - Category definitions used to resolve subcategory -> domain mapping\n *\n * Side effects: sets `domainSelections`, sets `selectedDomains` to ALL_DOMAINS\n */\n populateFromStack: (\n stack: { agents: Record<string, Partial<Record<Subcategory, SkillAssignment[]>>> },\n categories: Partial<Record<Subcategory, { domain?: Domain }>>,\n ) => void;\n /**\n * Pre-populate domainSelections from a flat list of installed skill IDs.\n *\n * Used by `agentsinc edit` to restore wizard state from existing project config.\n * Looks up each skill's category and domain, warns for unresolvable skills.\n *\n * @param skillIds - Flat array of currently installed skill IDs\n * @param skills - Skill lookup providing category and displayName per skill ID\n * @param categories - Category definitions used to resolve subcategory -> domain mapping\n *\n * Side effects: sets `domainSelections`, sets `selectedDomains` to domains found in the provided skill IDs\n */\n populateFromSkillIds: (\n skillIds: SkillId[],\n skills: Partial<Record<SkillId, { category: string; displayName?: string }>>,\n categories: Partial<Record<Subcategory, { domain?: Domain }>>,\n ) => void;\n /**\n * Toggle a domain on or off in the selectedDomains list.\n * @param domain - Domain to toggle\n *\n * Side effects: adds or removes from `selectedDomains`\n */\n toggleDomain: (domain: Domain) => void;\n /**\n * Toggle a skill selection within a domain's subcategory.\n *\n * When exclusive is true (radio behavior), selecting a new skill replaces any\n * existing selection in that subcategory. When false (checkbox behavior),\n * the skill is added to or removed from the selection array.\n *\n * @param domain - Domain containing the subcategory\n * @param subcategory - Subcategory within the domain\n * @param technology - Skill ID to toggle\n * @param exclusive - If true, only one skill can be selected per subcategory (radio)\n *\n * Side effects: updates `domainSelections[domain][subcategory]`\n */\n toggleTechnology: (\n domain: Domain,\n subcategory: Subcategory,\n technology: SkillId,\n exclusive: boolean,\n ) => void;\n /**\n * Advance to the next domain in the build step.\n * @returns true if advanced, false if already at the last domain\n *\n * Side effects: increments `currentDomainIndex`\n */\n nextDomain: () => boolean;\n /**\n * Go back to the previous domain in the build step.\n * @returns true if moved back, false if already at the first domain\n *\n * Side effects: decrements `currentDomainIndex`\n */\n prevDomain: () => boolean;\n /** Toggle compatibility label visibility on skill tags in the build step grid. */\n toggleShowLabels: () => void;\n /** Toggle between \"plugin\" and \"local\" install modes. */\n toggleInstallMode: () => void;\n /**\n * Set which source provides a specific skill.\n * @param skillId - Skill to configure the source for\n * @param sourceId - Source identifier (e.g., \"public\", \"local\", marketplace name)\n *\n * Side effects: updates `sourceSelections[skillId]`. No-op with warning if either param is empty.\n */\n setSourceSelection: (skillId: SkillId, sourceId: string) => void;\n /**\n * Enable or disable source customization on the sources step.\n * @param customize - true to show per-skill source pickers\n *\n * Side effects: sets `customizeSources`\n */\n setCustomizeSources: (customize: boolean) => void;\n /** Toggle the settings overlay (source management). */\n toggleSettings: () => void;\n /** Toggle the help overlay (hotkey reference). */\n toggleHelp: () => void;\n /**\n * Replace the full set of enabled/disabled sources.\n * @param sources - Record of source name to enabled boolean. Empty-string keys are filtered out.\n *\n * Side effects: sets `enabledSources`\n */\n setEnabledSources: (sources: Record<string, boolean>) => void;\n /**\n * Add a bound skill from search to the wizard's bound skills list.\n * Duplicates (same id + sourceUrl) are silently skipped with a warning.\n *\n * @param skill - Bound skill to add (foreign skill tied to a subcategory alias)\n *\n * Side effects: appends to `boundSkills`\n */\n bindSkill: (skill: BoundSkill) => void;\n /**\n * Navigate to the previous wizard step using the history stack.\n * Falls back to \"stack\" if history is empty.\n *\n * Side effects: pops from `history`, sets `step` to the popped value\n */\n goBack: () => void;\n /**\n * Toggle an agent on or off in the selectedAgents list.\n * @param agent - Agent name to toggle\n *\n * Side effects: adds or removes from `selectedAgents`\n */\n toggleAgent: (agent: AgentName) => void;\n /**\n * Preselect agents based on selected domains from the first wizard step.\n * Matches domains against DOMAIN_AGENTS mapping.\n * Optional agents (meta/pattern) are excluded.\n *\n * Side effects: replaces `selectedAgents` with computed preselection\n */\n preselectAgentsFromDomains: () => void;\n /** Reset all wizard state to initial values. */\n reset: () => void;\n\n /**\n * Collect all selected skill IDs across all domains and subcategories.\n * @returns Flat array of every selected SkillId (may contain duplicates if shared across domains)\n */\n getAllSelectedTechnologies: () => SkillId[];\n /**\n * Group selected skill IDs by domain.\n * @returns Partial record mapping each domain with selections to its skill ID array\n */\n getSelectedTechnologiesPerDomain: () => Partial<Record<Domain, SkillId[]>>;\n /**\n * Get the domain currently visible in the build step.\n * @returns The domain at currentDomainIndex, or null if no domains are selected\n */\n getCurrentDomain: () => Domain | null;\n /** Returns the foundational methodology skills that are always preselected (DEFAULT_PRESELECTED_SKILLS). */\n getDefaultMethodologySkills: () => SkillId[];\n /**\n * Count total selected technologies across all domains.\n * @returns Number of selected skill IDs\n */\n getTechnologyCount: () => number;\n /**\n * Compute which wizard steps are completed and which are skipped.\n * Used by WizardTabs to render step progress indicators.\n * @returns Object with completedSteps and skippedSteps string arrays\n */\n getStepProgress: () => { completedSteps: WizardStep[]; skippedSteps: WizardStep[] };\n /** @returns true if there is a next domain after the current one */\n canGoToNextDomain: () => boolean;\n /** @returns true if there is a previous domain before the current one */\n canGoToPreviousDomain: () => boolean;\n /**\n * Build the source selection rows for the sources step UI.\n *\n * For each selected technology, resolves the canonical skill ID, looks up available\n * sources from the matrix, merges in any bound skills from search, and determines\n * which source is currently selected. Sources are sorted: local first, then public,\n * then private/other.\n *\n * @param matrix - Merged skills matrix with resolved skills and their available sources\n * @returns Array of row objects, one per selected technology, each containing:\n * - `skillId` - Canonical resolved skill ID\n * - `displayName` - Human-readable skill alias\n * - `alias` - Search-friendly display name used by source grid search\n * - `options` - Available sources with selection state and install status\n */\n buildSourceRows: (matrix: MergedSkillsMatrix) => {\n skillId: SkillId;\n displayName: SkillAlias;\n alias: SkillAlias;\n options: { id: string; label: string; selected: boolean; installed: boolean }[];\n }[];\n};\n\nconst createInitialState = () => ({\n step: \"stack\" as WizardStep,\n approach: null as \"stack\" | \"scratch\" | null,\n selectedStackId: null as string | null,\n stackAction: null as \"defaults\" | \"customize\" | null,\n selectedDomains: [] as Domain[],\n currentDomainIndex: 0,\n domainSelections: {} as DomainSelections,\n /** Snapshot of domainSelections from populateFromStack/populateFromSkillIds, used to restore on domain re-toggle */\n _stackDomainSelections: null as DomainSelections | null,\n showLabels: false,\n installMode: \"local\" as \"plugin\" | \"local\",\n sourceSelections: {} as Partial<Record<SkillId, string>>,\n customizeSources: false,\n showSettings: false,\n showHelp: false,\n enabledSources: {} as Record<string, boolean>,\n selectedAgents: [] as AgentName[],\n boundSkills: [] as BoundSkill[],\n history: [] as WizardStep[],\n});\n\nexport const useWizardStore = create<WizardState>((set, get) => ({\n ...createInitialState(),\n\n setStep: (step) =>\n set((state) => ({\n step,\n history: [...state.history, state.step],\n })),\n\n setApproach: (approach) => set({ approach }),\n\n selectStack: (stackId) => set({ selectedStackId: stackId }),\n\n setStackAction: (action) => set({ stackAction: action }),\n\n populateFromStack: (stack, categories) =>\n set(() => {\n const domainSelections: DomainSelections = {};\n const domains = new Set<Domain>();\n\n for (const agentConfig of Object.values(stack.agents)) {\n for (const [subcat, assignments] of typedEntries<Subcategory, SkillAssignment[]>(\n agentConfig,\n )) {\n const category = categories[subcat];\n const domain = category?.domain;\n\n if (!domain || !assignments) {\n continue;\n }\n\n domains.add(domain);\n\n if (!domainSelections[domain]) {\n domainSelections[domain] = {};\n }\n\n if (!domainSelections[domain][subcat]) {\n domainSelections[domain][subcat] = [];\n }\n\n for (const assignment of assignments) {\n if (!domainSelections[domain][subcat].includes(assignment.id)) {\n domainSelections[domain][subcat].push(assignment.id);\n }\n }\n }\n }\n\n return {\n domainSelections,\n _stackDomainSelections: structuredClone(domainSelections),\n selectedDomains: sortDomainsCanonically(getAllDomainsFromCategories(categories)),\n };\n }),\n\n populateFromSkillIds: (skillIds, skills, categories) =>\n set(() => {\n const domainSelections: DomainSelections = {};\n let skippedCount = 0;\n\n for (const skillId of skillIds) {\n const resolved = resolveSkillForPopulation(skillId, skills, categories);\n if (!resolved) {\n skippedCount++;\n continue;\n }\n\n const { domain, subcat, techId } = resolved;\n if (!domainSelections[domain]) domainSelections[domain] = {};\n if (!domainSelections[domain][subcat]) domainSelections[domain][subcat] = [];\n\n if (!domainSelections[domain][subcat].includes(techId)) {\n domainSelections[domain][subcat].push(techId);\n }\n }\n\n if (skippedCount > 0) {\n warn(`${skippedCount} installed skill(s) could not be resolved and were skipped`);\n }\n\n const selectedDomains = sortDomainsCanonically(typedKeys<Domain>(domainSelections));\n\n return {\n domainSelections,\n _stackDomainSelections: structuredClone(domainSelections),\n selectedDomains,\n };\n }),\n\n toggleDomain: (domain) =>\n set((state) => {\n const isSelected = state.selectedDomains.includes(domain);\n if (isSelected) {\n const { [domain]: _removed, ...remainingSelections } = state.domainSelections;\n return {\n selectedDomains: state.selectedDomains.filter((d) => d !== domain),\n domainSelections: remainingSelections,\n };\n }\n\n // Restore stack selections for this domain if a stack snapshot exists\n const stackSelections = state._stackDomainSelections?.[domain];\n return {\n selectedDomains: sortDomainsCanonically([...state.selectedDomains, domain]),\n ...(stackSelections\n ? {\n domainSelections: {\n ...state.domainSelections,\n [domain]: structuredClone(stackSelections),\n },\n }\n : {}),\n };\n }),\n\n toggleTechnology: (domain, subcategory, technology, exclusive) =>\n set((state) => {\n const currentSelections = state.domainSelections[domain]?.[subcategory] || [];\n const isSelected = currentSelections.includes(technology);\n\n let newSelections: SkillId[];\n if (exclusive) {\n newSelections = isSelected ? [] : [technology];\n } else {\n newSelections = isSelected\n ? currentSelections.filter((t) => t !== technology)\n : [...currentSelections, technology];\n }\n\n return {\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [subcategory]: newSelections,\n },\n },\n };\n }),\n\n nextDomain: () => {\n const state = get();\n if (state.currentDomainIndex < state.selectedDomains.length - 1) {\n set({\n currentDomainIndex: state.currentDomainIndex + 1,\n });\n return true;\n }\n return false;\n },\n\n prevDomain: () => {\n const state = get();\n if (state.currentDomainIndex > 0) {\n set({\n currentDomainIndex: state.currentDomainIndex - 1,\n });\n return true;\n }\n return false;\n },\n\n toggleShowLabels: () => set((state) => ({ showLabels: !state.showLabels })),\n\n toggleInstallMode: () =>\n set((state) => ({\n installMode: state.installMode === \"plugin\" ? \"local\" : \"plugin\",\n })),\n\n setSourceSelection: (skillId, sourceId) =>\n set((state) => {\n if (!skillId) {\n warn(\"Ignoring setSourceSelection call with empty skillId\");\n return state;\n }\n if (!sourceId) {\n warn(`Ignoring setSourceSelection call with empty sourceId for skill '${skillId}'`);\n return state;\n }\n return {\n sourceSelections: { ...state.sourceSelections, [skillId]: sourceId },\n };\n }),\n\n setCustomizeSources: (customize) => set({ customizeSources: customize }),\n\n toggleSettings: () => set((state) => ({ showSettings: !state.showSettings })),\n\n toggleHelp: () => set((state) => ({ showHelp: !state.showHelp })),\n\n setEnabledSources: (sources) => {\n const invalidKeys = Object.keys(sources).filter((key) => !key.trim());\n if (invalidKeys.length > 0) {\n warn(\"Ignoring setEnabledSources call with empty source name(s)\");\n }\n const validSources = Object.fromEntries(Object.entries(sources).filter(([key]) => key.trim()));\n return set({ enabledSources: validSources });\n },\n\n bindSkill: (skill) =>\n set((state) => {\n const exists = state.boundSkills.some(\n (b) => b.id === skill.id && b.sourceUrl === skill.sourceUrl,\n );\n if (exists) {\n warn(`Skill '${skill.id}' from '${skill.sourceUrl}' is already bound — skipping duplicate`);\n return state;\n }\n return { boundSkills: [...state.boundSkills, skill] };\n }),\n\n goBack: () =>\n set((state) => {\n const history = [...state.history];\n const previousStep = history.pop();\n return {\n step: previousStep || \"stack\",\n history,\n };\n }),\n\n toggleAgent: (agent) =>\n set((state) => {\n const isSelected = state.selectedAgents.includes(agent);\n return {\n selectedAgents: isSelected\n ? state.selectedAgents.filter((a) => a !== agent)\n : [...state.selectedAgents, agent],\n };\n }),\n\n preselectAgentsFromDomains: () =>\n set(() => {\n const agents: AgentName[] = [];\n for (const domain of get().selectedDomains) {\n const domainAgents = DOMAIN_AGENTS[domain];\n if (domainAgents) {\n agents.push(...domainAgents);\n }\n }\n return { selectedAgents: agents.sort() };\n }),\n\n reset: () => set(createInitialState()),\n\n getAllSelectedTechnologies: () => {\n const state = get();\n const technologies: SkillId[] = [];\n for (const domain of typedKeys<Domain>(state.domainSelections)) {\n const domainSel = state.domainSelections[domain];\n if (!domainSel) continue;\n for (const subcategory of typedKeys<Subcategory>(domainSel)) {\n const techs = domainSel[subcategory];\n if (techs) technologies.push(...techs);\n }\n }\n return technologies;\n },\n\n getSelectedTechnologiesPerDomain: () => {\n const state = get();\n const result: Partial<Record<Domain, SkillId[]>> = {};\n for (const domain of typedKeys<Domain>(state.domainSelections)) {\n const domainSel = state.domainSelections[domain];\n if (!domainSel) continue;\n const techs: SkillId[] = [];\n for (const subcategory of typedKeys<Subcategory>(domainSel)) {\n const subTechs = domainSel[subcategory];\n if (subTechs) techs.push(...subTechs);\n }\n if (techs.length > 0) {\n result[domain] = techs;\n }\n }\n return result;\n },\n\n getCurrentDomain: () => {\n const state = get();\n return state.selectedDomains[state.currentDomainIndex] || null;\n },\n\n getDefaultMethodologySkills: () => {\n return [...DEFAULT_PRESELECTED_SKILLS];\n },\n\n getTechnologyCount: () => {\n return get().getAllSelectedTechnologies().length;\n },\n\n getStepProgress: () => {\n const state = get();\n const completed: WizardStep[] = [];\n const skipped: WizardStep[] = [];\n\n if (state.step !== \"stack\") {\n completed.push(\"stack\");\n }\n\n if (state.approach === \"stack\" && state.selectedStackId && state.stackAction === \"defaults\") {\n skipped.push(\"build\");\n skipped.push(\"sources\");\n skipped.push(\"agents\");\n } else if (state.step === \"confirm\") {\n completed.push(\"build\");\n completed.push(\"sources\");\n completed.push(\"agents\");\n } else if (state.step === \"agents\") {\n completed.push(\"build\");\n completed.push(\"sources\");\n } else if (state.step === \"sources\") {\n completed.push(\"build\");\n }\n\n return { completedSteps: completed, skippedSteps: skipped };\n },\n\n canGoToNextDomain: () => {\n const state = get();\n return state.currentDomainIndex < state.selectedDomains.length - 1;\n },\n\n canGoToPreviousDomain: () => {\n const state = get();\n return state.currentDomainIndex > 0;\n },\n\n buildSourceRows: (matrix) => {\n const state = get();\n const selectedTechnologies = get().getAllSelectedTechnologies();\n const { sourceSelections, boundSkills } = state;\n\n return selectedTechnologies.map((tech) => {\n const skillId = resolveAlias(tech, matrix);\n const skill = matrix.skills[skillId];\n const selectedSource =\n sourceSelections[skillId] || skill?.activeSource?.name || DEFAULT_PUBLIC_SOURCE_NAME;\n const alias = getSkillAlias(skillId, matrix);\n const displayLabel = skill ? getSkillDisplayLabel(skill) : skillId;\n\n const sortedSources = [...(skill?.availableSources || [])].sort(\n (a, b) => getSourceSortTier(a) - getSourceSortTier(b),\n );\n\n const options =\n sortedSources.length > 0\n ? sortedSources.map((source) => ({\n id: source.name,\n label: formatSourceLabel({\n name: source.name,\n installed: source.installed,\n }),\n selected: selectedSource === source.name,\n installed: source.installed,\n }))\n : [\n {\n id: DEFAULT_PUBLIC_SOURCE_NAME,\n label: DEFAULT_PUBLIC_SOURCE_NAME,\n selected: selectedSource === DEFAULT_PUBLIC_SOURCE_NAME,\n installed: false,\n },\n ];\n\n options.push(...buildBoundSkillOptions(boundSkills, alias, selectedSource));\n\n return { skillId, displayName: displayLabel, alias, options };\n });\n },\n}));\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/domain-selection.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { unique } from \"remeda\";\nimport { BUILT_IN_DOMAIN_ORDER } from \"../../consts.js\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport type { Domain, MergedSkillsMatrix } from \"../../types/index.js\";\nimport { typedEntries } from \"../../utils/typed-object.js\";\nimport { CheckboxGrid, type CheckboxItem } from \"./checkbox-grid.js\";\nimport { getDomainDisplayName } from \"./utils.js\";\n\nconst BUILT_IN_DOMAIN_DESCRIPTIONS: Record<Domain, string> = {\n web: \"Frontend web applications\",\n api: \"Backend APIs and services\",\n cli: \"Command-line tools\",\n mobile: \"Mobile applications\",\n shared: \"Shared utilities and methodology\",\n};\n\ntype DomainSelectionProps = {\n matrix: MergedSkillsMatrix;\n};\n\nexport const DomainSelection: React.FC<DomainSelectionProps> = ({ matrix }) => {\n const { selectedDomains, toggleDomain, setStep, setApproach, selectStack } = useWizardStore();\n\n const availableDomains = useMemo((): CheckboxItem<Domain>[] => {\n const matrixDomains = unique(\n typedEntries(matrix.categories)\n .map(([, cat]) => cat?.domain)\n .filter((d): d is Domain => d != null && d !== \"shared\"),\n );\n\n const ordered: Domain[] = [\n ...BUILT_IN_DOMAIN_ORDER.filter((d) => matrixDomains.includes(d)),\n ...matrixDomains.filter((d) => !BUILT_IN_DOMAIN_ORDER.includes(d)),\n ];\n\n return ordered.map((domain) => ({\n id: domain,\n label: getDomainDisplayName(domain),\n description: BUILT_IN_DOMAIN_DESCRIPTIONS[domain] ?? `${getDomainDisplayName(domain)} skills`,\n }));\n }, [matrix]);\n\n const handleBack = () => {\n setApproach(null);\n selectStack(null);\n };\n\n return (\n <CheckboxGrid\n title=\"Select domains to configure\"\n // subtitle=\"Select one or more domains, then continue\"\n items={availableDomains}\n selectedIds={selectedDomains}\n onToggle={toggleDomain}\n onContinue={() => setStep(\"build\")}\n onBack={handleBack}\n emptyMessage=\"Please select at least one domain\"\n />\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAgB,eAAe;AAC/B,SAAS,cAAc;AAgDnB;AAxCJ,IAAM,+BAAuD;AAAA,EAC3D,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,QAAQ;AACV;AAMO,IAAM,kBAAkD,CAAC,EAAE,OAAO,MAAM;AAC7E,QAAM,EAAE,iBAAiB,cAAc,SAAS,aAAa,YAAY,IAAI,eAAe;AAE5F,QAAM,mBAAmB,QAAQ,MAA8B;AAC7D,UAAM,gBAAgB;AAAA,MACpB,aAAa,OAAO,UAAU,EAC3B,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,KAAK,MAAM,EAC5B,OAAO,CAAC,MAAmB,KAAK,QAAQ,MAAM,QAAQ;AAAA,IAC3D;AAEA,UAAM,UAAoB;AAAA,MACxB,GAAG,sBAAsB,OAAO,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC;AAAA,MAChE,GAAG,cAAc,OAAO,CAAC,MAAM,CAAC,sBAAsB,SAAS,CAAC,CAAC;AAAA,IACnE;AAEA,WAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,MAC9B,IAAI;AAAA,MACJ,OAAO,qBAAqB,MAAM;AAAA,MAClC,aAAa,6BAA6B,MAAM,KAAK,GAAG,qBAAqB,MAAM,CAAC;AAAA,IACtF,EAAE;AAAA,EACJ,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAa,MAAM;AACvB,gBAAY,IAAI;AAChB,gBAAY,IAAI;AAAA,EAClB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MAEN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,YAAY,MAAM,QAAQ,OAAO;AAAA,MACjC,QAAQ;AAAA,MACR,cAAa;AAAA;AAAA,EACf;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/agents/agent-fetcher.ts","../src/cli/lib/agents/agent-recompiler.ts","../src/cli/lib/agents/agent-plugin-compiler.ts","../src/cli/lib/agents/index.ts"],"sourcesContent":["import path from \"path\";\nimport { directoryExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { PROJECT_ROOT, DIRS, CLAUDE_DIR } from \"../../consts\";\nimport { fetchFromSource, type FetchOptions } from \"../loading\";\nimport { loadProjectSourceConfig } from \"../configuration\";\nimport type { AgentSourcePaths } from \"../../types\";\n\nexport type AgentDefinitionOptions = FetchOptions & {\n projectDir?: string;\n};\n\nexport async function getAgentDefinitions(\n remoteSource?: string,\n options: AgentDefinitionOptions = {},\n): Promise<AgentSourcePaths> {\n if (remoteSource) {\n return fetchAgentDefinitionsFromRemote(remoteSource, options);\n }\n return getLocalAgentDefinitions(options);\n}\n\nexport async function getLocalAgentDefinitions(\n options: AgentDefinitionOptions = {},\n): Promise<AgentSourcePaths> {\n const agentsDir = path.join(PROJECT_ROOT, DIRS.agents);\n let templatesDir = path.join(PROJECT_ROOT, DIRS.templates);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(\n `Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`,\n );\n }\n\n if (options.projectDir) {\n const localTemplatesDir = path.join(options.projectDir, CLAUDE_DIR, \"templates\");\n if (await directoryExists(localTemplatesDir)) {\n verbose(`Using local templates from: ${localTemplatesDir}`);\n templatesDir = localTemplatesDir;\n }\n }\n\n if (!(await directoryExists(templatesDir))) {\n verbose(`Templates directory not found: ${templatesDir}`);\n }\n\n verbose(`Agent partials loaded from CLI: ${agentsDir}`);\n verbose(`Templates directory: ${templatesDir}`);\n\n return {\n agentsDir,\n templatesDir,\n sourcePath: PROJECT_ROOT,\n };\n}\n\nexport async function fetchAgentDefinitionsFromRemote(\n source: string,\n options: FetchOptions & { agentsDir?: string } = {},\n): Promise<AgentSourcePaths> {\n verbose(`Fetching agent partials from remote: ${source}`);\n\n const result = await fetchFromSource(source, {\n forceRefresh: options.forceRefresh,\n subdir: \"\",\n });\n\n let agentsDirRelPath = options.agentsDir;\n if (!agentsDirRelPath) {\n const sourceProjectConfig = await loadProjectSourceConfig(result.path);\n agentsDirRelPath = sourceProjectConfig?.agentsDir ?? DIRS.agents;\n if (sourceProjectConfig?.agentsDir) {\n verbose(`Using agentsDir from source config: ${sourceProjectConfig.agentsDir}`);\n }\n }\n\n const agentsDir = path.join(result.path, agentsDirRelPath);\n const templatesDir = path.join(agentsDir, \"_templates\");\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(`Agent partials not found at '${agentsDir}'`);\n }\n\n if (!(await directoryExists(templatesDir))) {\n verbose(`Templates directory not found: ${templatesDir}`);\n }\n\n verbose(`Agent partials fetched from: ${result.path}`);\n\n return {\n agentsDir,\n templatesDir,\n sourcePath: result.path,\n };\n}\n","import type { Liquid } from \"liquidjs\";\nimport path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n ProjectConfig,\n SkillDefinition,\n SkillId,\n} from \"../../types\";\nimport { glob, writeFile, ensureDir } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\nimport { createLiquidEngine } from \"../compiler\";\nimport { loadProjectConfig } from \"../configuration\";\nimport { loadAllAgents, loadProjectAgents } from \"../loading\";\nimport { getPluginAgentsDir } from \"../plugins\";\nimport { discoverAllPluginSkills } from \"../plugins/plugin-discovery\";\nimport { resolveAgents, buildSkillRefsFromConfig } from \"../resolver\";\nimport { compileAgentForPlugin } from \"../stacks\";\n\nexport type RecompileAgentsOptions = {\n pluginDir: string;\n sourcePath: string;\n agents?: AgentName[];\n skills?: Partial<Record<SkillId, SkillDefinition>>;\n projectDir?: string;\n outputDir?: string;\n};\n\nexport type RecompileAgentsResult = {\n compiled: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nasync function getExistingAgentNames(pluginDir: string): Promise<AgentName[]> {\n const agentsDir = getPluginAgentsDir(pluginDir);\n const files = await glob(\"*.md\", agentsDir);\n // Boundary cast: directory names from filesystem are agent names by convention\n return files.map((f) => path.basename(f, \".md\") as AgentName);\n}\n\ntype ResolveAgentNamesParams = {\n specifiedAgents?: AgentName[];\n projectConfig: ProjectConfig | null;\n allAgents: Record<AgentName, AgentDefinition>;\n outputDir?: string;\n pluginDir: string;\n};\n\nasync function resolveAgentNames(params: ResolveAgentNamesParams): Promise<AgentName[]> {\n const { specifiedAgents, projectConfig, allAgents, outputDir, pluginDir } = params;\n\n if (specifiedAgents) {\n return specifiedAgents;\n }\n\n if (projectConfig?.agents) {\n verbose(`Using agents from config.yaml: ${projectConfig.agents.join(\", \")}`);\n return projectConfig.agents;\n }\n\n if (outputDir) {\n const names = typedKeys<AgentName>(allAgents);\n verbose(`Using all available agents from source: ${names.join(\", \")}`);\n return names;\n }\n\n return getExistingAgentNames(pluginDir);\n}\n\ntype BuildCompileConfigParams = {\n agentNames: AgentName[];\n allAgents: Record<AgentName, AgentDefinition>;\n projectConfig: ProjectConfig | null;\n pluginDir: string;\n};\n\ntype BuildCompileConfigResult = {\n compileConfig: CompileConfig;\n warnings: string[];\n};\n\nfunction buildCompileConfig(params: BuildCompileConfigParams): BuildCompileConfigResult {\n const { agentNames, allAgents, projectConfig, pluginDir } = params;\n const warnings: string[] = [];\n\n // Store initialization: accumulator filled below for each agent in agentNames\n const compileAgents = {} as Record<AgentName, CompileAgentConfig>;\n for (const agentName of agentNames) {\n if (allAgents[agentName]) {\n const agentStack = projectConfig?.stack?.[agentName];\n compileAgents[agentName] = agentStack ? { skills: buildSkillRefsFromConfig(agentStack) } : {};\n } else {\n warnings.push(`Agent \"${agentName}\" not found in source definitions`);\n }\n }\n\n const compileConfig: CompileConfig = {\n name: projectConfig?.name || path.basename(pluginDir),\n description: projectConfig?.description || \"Recompiled plugin\",\n agents: compileAgents,\n };\n\n return { compileConfig, warnings };\n}\n\ntype CompileAndWriteParams = {\n resolvedAgents: Record<AgentName, AgentConfig>;\n agentsDir: string;\n sourcePath: string;\n engine: Liquid;\n installMode: ProjectConfig[\"installMode\"];\n};\n\nasync function compileAndWriteAgents(\n params: CompileAndWriteParams,\n result: RecompileAgentsResult,\n): Promise<void> {\n const { resolvedAgents, agentsDir, sourcePath, engine, installMode } = params;\n\n for (const [agentName, agent] of typedEntries<AgentName, AgentConfig>(resolvedAgents)) {\n try {\n const output = await compileAgentForPlugin(agentName, agent, sourcePath, engine, installMode);\n await writeFile(path.join(agentsDir, `${agentName}.md`), output);\n result.compiled.push(agentName);\n verbose(` Recompiled: ${agentName}`);\n } catch (error) {\n result.failed.push(agentName);\n result.warnings.push(`Failed to compile ${agentName}: ${getErrorMessage(error)}`);\n }\n }\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const { pluginDir, sourcePath, skills: providedSkills, projectDir, outputDir } = options;\n\n const result: RecompileAgentsResult = {\n compiled: [],\n failed: [],\n warnings: [],\n };\n\n const configDir = projectDir ?? pluginDir;\n const loadedConfig = await loadProjectConfig(configDir);\n const projectConfig = loadedConfig?.config ?? null;\n\n const builtinAgents = await loadAllAgents(sourcePath);\n const projectAgents = projectDir ? await loadProjectAgents(projectDir) : {};\n\n // Boundary cast: loadAllAgents returns Record<string, AgentDefinition>, agent dirs are AgentName by convention\n // Priority: project agents > built-in agents\n const allAgents = {\n ...builtinAgents,\n ...projectAgents,\n } as Record<AgentName, AgentDefinition>;\n\n const agentNames = await resolveAgentNames({\n specifiedAgents: options.agents,\n projectConfig,\n allAgents,\n outputDir,\n pluginDir,\n });\n\n if (agentNames.length === 0) {\n result.warnings.push(\"No agents found to recompile\");\n return result;\n }\n\n verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);\n\n // When skills are not provided, discover from all plugin directories.\n let pluginSkills: Partial<Record<SkillId, SkillDefinition>>;\n if (providedSkills) {\n pluginSkills = providedSkills;\n } else {\n pluginSkills = await discoverAllPluginSkills(projectDir ?? pluginDir);\n }\n\n const { compileConfig, warnings } = buildCompileConfig({\n agentNames,\n allAgents,\n projectConfig,\n pluginDir,\n });\n result.warnings.push(...warnings);\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n await compileAndWriteAgents(\n {\n resolvedAgents,\n agentsDir,\n sourcePath,\n engine,\n installMode: projectConfig?.installMode,\n },\n result,\n );\n\n return result;\n}\n","import path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, ensureDir, glob, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateAgentPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { computeStringHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport type { PluginManifest } from \"../../types\";\nimport { agentFrontmatterValidationSchema, formatZodErrors } from \"../schemas\";\n\nexport type AgentPluginOptions = {\n agentPath: string;\n outputDir: string;\n};\n\nexport type CompiledAgentPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n agentName: string;\n};\n\nfunction parseAgentFrontmatter(\n content: string,\n filePath: string,\n): { name: string; description: string } | null {\n const raw = extractFrontmatter(content);\n if (!raw) {\n return null;\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(raw);\n if (!result.success) {\n warn(`Invalid agent frontmatter in ${filePath}: ${formatZodErrors(result.error.issues)}`);\n return null;\n }\n\n return { name: result.data.name, description: result.data.description };\n}\n\nexport async function compileAgentPlugin(\n options: AgentPluginOptions,\n): Promise<CompiledAgentPlugin> {\n const { agentPath, outputDir } = options;\n const fileName = path.basename(agentPath);\n\n const content = await readFile(agentPath);\n const frontmatter = parseAgentFrontmatter(content, agentPath);\n\n if (!frontmatter) {\n throw new Error(\n `Agent '${fileName}' has invalid or missing YAML frontmatter. ` +\n `Required fields: 'name' and 'description'. File: ${agentPath}`,\n );\n }\n\n const agentName = frontmatter.name;\n\n verbose(`Compiling agent plugin: ${agentName} from ${agentPath}`);\n\n const pluginDir = path.join(outputDir, `agent-${agentName}`);\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await ensureDir(pluginDir);\n await ensureDir(agentsDir);\n\n const newHash = computeStringHash(content);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateAgentPluginManifest({\n agentName,\n description: frontmatter.description,\n version,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${agentName} (v${version})`);\n\n await copy(agentPath, path.join(agentsDir, `${agentName}.md`));\n verbose(` Copied agent ${fileName} -> agents/${agentName}.md`);\n\n return {\n pluginPath: pluginDir,\n manifest,\n agentName,\n };\n}\n\nexport async function compileAllAgentPlugins(\n agentsDir: string,\n outputDir: string,\n): Promise<CompiledAgentPlugin[]> {\n const results: CompiledAgentPlugin[] = [];\n\n const agentMdFiles = await glob(\"*.md\", agentsDir);\n\n for (const agentFile of agentMdFiles) {\n const agentPath = path.join(agentsDir, agentFile);\n\n try {\n const result = await compileAgentPlugin({\n agentPath,\n outputDir,\n });\n results.push(result);\n log(` [OK] agent-${result.agentName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile agent from '${agentFile}': ${errorMessage}`);\n }\n }\n\n return results;\n}\n\nexport function printAgentCompilationSummary(results: CompiledAgentPlugin[]): void {\n log(`\\nCompiled ${results.length} agent plugins:`);\n for (const result of results) {\n log(` - agent-${result.agentName} (v${result.manifest.version})`);\n }\n}\n","export {\n type AgentDefinitionOptions,\n getAgentDefinitions,\n getLocalAgentDefinitions,\n fetchAgentDefinitionsFromRemote,\n} from \"./agent-fetcher\";\n\nexport {\n type RecompileAgentsOptions,\n type RecompileAgentsResult,\n recompileAgents,\n} from \"./agent-recompiler\";\n\nexport {\n type AgentPluginOptions,\n type CompiledAgentPlugin,\n compileAgentPlugin,\n compileAllAgentPlugins,\n printAgentCompilationSummary,\n} from \"./agent-plugin-compiler\";\n"],"mappings":"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","names":["path","path","path","path"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/consts.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { Domain, SkillId } from \"./types/index.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// After tsup build, dist/ is flat, so we go up one level from dist/ to get CLI root\n// In development (src/cli/consts.ts), we go up two levels\nconst isInDist = __dirname.includes(\"/dist\");\nconst CLI_ROOT = isInDist ? path.resolve(__dirname, \"..\") : path.resolve(__dirname, \"../..\");\nexport const PROJECT_ROOT = CLI_ROOT;\n\nexport const CLAUDE_DIR = \".claude\";\nexport const CLAUDE_SRC_DIR = \".claude-src\";\nexport const PLUGINS_SUBDIR = \"plugins\";\nexport const PLUGIN_MANIFEST_DIR = \".claude-plugin\";\nexport const PLUGIN_MANIFEST_FILE = \"plugin.json\";\nexport const DEFAULT_PLUGIN_NAME = \"agents-inc\";\n\n/** Home directory used as the root for global installations */\nexport const GLOBAL_INSTALL_ROOT = os.homedir();\n\nexport const CACHE_DIR = path.join(os.homedir(), \".cache\", DEFAULT_PLUGIN_NAME);\n\nexport const CLI_BIN_NAME = \"agentsinc\";\n\nexport const SKILL_CATEGORIES_YAML_PATH = \"config/skill-categories.yaml\";\nexport const SKILL_RULES_YAML_PATH = \"config/skill-rules.yaml\";\nexport const STACKS_FILE_PATH = \"config/stacks.yaml\";\nexport const SKILLS_DIR_PATH = \"src/skills\";\nexport const LOCAL_SKILLS_PATH = \".claude/skills\";\nexport const ARCHIVED_SKILLS_DIR_NAME = \"_archived\";\n\nexport const DIRS = {\n agents: \"src/agents\",\n skills: \"src/skills\",\n stacks: \"src/stacks\",\n templates: \"src/agents/_templates\",\n commands: \"src/commands\",\n} as const;\n\nexport const STANDARD_FILES = {\n SKILL_MD: \"SKILL.md\",\n METADATA_YAML: \"metadata.yaml\",\n METADATA_JSON: \"metadata.json\",\n CONFIG_YAML: \"config.yaml\",\n SKILL_CATEGORIES_YAML: \"skill-categories.yaml\",\n SKILL_RULES_YAML: \"skill-rules.yaml\",\n AGENT_METADATA_YAML: \"metadata.yaml\",\n PLUGIN_JSON: \"plugin.json\",\n CLAUDE_MD: \"CLAUDE.md\",\n REFERENCE_MD: \"reference.md\",\n INTRO_MD: \"intro.md\",\n WORKFLOW_MD: \"workflow.md\",\n EXAMPLES_MD: \"examples.md\",\n OUTPUT_FORMAT_MD: \"output-format.md\",\n CRITICAL_REQUIREMENTS_MD: \"critical-requirements.md\",\n CRITICAL_REMINDERS_MD: \"critical-reminders.md\",\n} as const;\n\nexport const STANDARD_DIRS = {\n EXAMPLES: \"examples\",\n SCRIPTS: \"scripts\",\n SKILLS: \"skills\",\n} as const;\n\nexport const DEFAULT_VERSION = \"1.0.0\";\n\n// \"0.0.0\" indicates no version was explicitly set\nexport const DEFAULT_DISPLAY_VERSION = \"0.0.0\";\n\n// JSON Schema URLs for yaml-language-server $schema comments.\n// Uses raw.githubusercontent.com so schemas resolve without requiring the CLI as a dependency.\nconst SCHEMA_PKG_PREFIX = \"https://raw.githubusercontent.com/agents-inc/cli/main/src/schemas\";\n\nexport const SCHEMA_PATHS = {\n agent: `${SCHEMA_PKG_PREFIX}/agent.schema.json`,\n metadata: `${SCHEMA_PKG_PREFIX}/metadata.schema.json`,\n marketplace: `${SCHEMA_PKG_PREFIX}/marketplace.schema.json`,\n projectConfig: `${SCHEMA_PKG_PREFIX}/project-config.schema.json`,\n projectSourceConfig: `${SCHEMA_PKG_PREFIX}/project-source-config.schema.json`,\n stacks: `${SCHEMA_PKG_PREFIX}/stacks.schema.json`,\n} as const;\n\n/** Generates a yaml-language-server schema comment for the top of YAML files. */\nexport function yamlSchemaComment(schemaPath: string): string {\n return `# yaml-language-server: $schema=${schemaPath}`;\n}\n\nexport const YAML_FORMATTING = {\n INDENT: 2,\n LINE_WIDTH: 120,\n /** lineWidth: 0 disables wrapping — used for metadata files */\n LINE_WIDTH_NONE: 0,\n} as const;\n\nexport const UI_SYMBOLS = {\n CHECKBOX_CHECKED: \"[x]\",\n CHECKBOX_UNCHECKED: \"[ ]\",\n CHEVRON: \"\\u276F\",\n CHEVRON_SPACER: \" \",\n SELECTED: \"\\u2713\",\n UNSELECTED: \"\\u25CB\",\n CURRENT: \"\\u25CF\",\n SKIPPED: \"\\u2013\",\n DISCOURAGED: \"!\",\n DISABLED: \"\\u2013\",\n SCROLL_UP: \"\\u25B2\",\n SCROLL_DOWN: \"\\u25BC\",\n} as const;\n\nexport const UI_LAYOUT = {\n MAX_VISIBLE_RESULTS: 10,\n DESCRIPTION_WIDTH: 30,\n COPIED_MESSAGE_TIMEOUT_MS: 2000,\n FALLBACK_MESSAGE_TIMEOUT_MS: 3000,\n} as const;\n\nexport const GITHUB_SOURCE = {\n HTTPS_PREFIX: \"https://github.com/\",\n GITHUB_PREFIX: \"github:\",\n GH_PREFIX: \"gh:\",\n} as const;\n\nexport const DEFAULT_SKILLS_SUBDIR = \"skills\";\n\n/** Strict kebab-case: starts with letter, segments separated by single hyphens, no trailing hyphens */\nexport const KEBAB_CASE_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\nexport const HASH_PREFIX_LENGTH = 7;\n\n/** Hex chars from SHA-256 hash used in cache directory names (64 bits of collision resistance) */\nexport const CACHE_HASH_LENGTH = 16;\n\n/** Max chars of human-readable prefix in cache directory names (for debugging) */\nexport const CACHE_READABLE_PREFIX_LENGTH = 32;\n\n// File size limits for parsing boundaries (DoS prevention)\nconst ONE_MB = 1024 * 1024;\nexport const MAX_MARKETPLACE_FILE_SIZE = 10 * ONE_MB;\nexport const MAX_PLUGIN_FILE_SIZE = ONE_MB;\nexport const MAX_CONFIG_FILE_SIZE = ONE_MB;\n\nexport const MAX_JSON_NESTING_DEPTH = 10;\nexport const MAX_MARKETPLACE_PLUGINS = 10_000;\n\nexport const SCROLL_VIEWPORT = {\n /** Height of the \"N more above\" scroll indicator */\n SCROLL_INDICATOR_HEIGHT: 1,\n /** Estimated lines per category name row (including top margin) */\n CATEGORY_NAME_LINES: 2,\n /** Margin between category sections (marginTop on CategorySection) */\n CATEGORY_MARGIN_LINES: 1,\n /** Minimum rows to show at least 1 category before enabling scroll */\n MIN_VIEWPORT_ROWS: 5,\n /** Minimum terminal height to show the wizard at all */\n MIN_TERMINAL_HEIGHT: 15,\n} as const;\n\nexport const DEFAULT_BRANDING = {\n NAME: \"Agents Inc.\",\n TAGLINE: \"AI-powered development tools\",\n} as const;\n\n/** Fallback name for the default public marketplace when marketplace.json is unavailable */\nexport const DEFAULT_PUBLIC_SOURCE_NAME = \"Agents Inc\";\n\n/** Human-readable labels for skill source types shown in the wizard and edit command */\nexport const SOURCE_DISPLAY_NAMES: Record<string, string> = {\n public: \"Public\",\n local: \"Local\",\n};\n\nexport const CLI_COLORS = {\n PRIMARY: \"cyan\",\n SUCCESS: \"green\",\n ERROR: \"red\",\n WARNING: \"yellow\",\n INFO: \"blue\",\n NEUTRAL: \"gray\",\n FOCUS: \"cyan\",\n UNFOCUSED: \"white\",\n WHITE: \"white\",\n} as const;\n\n/** Canonical display order for built-in domains. Custom domains appear before these, alphabetically. */\nexport const BUILT_IN_DOMAIN_ORDER: readonly Domain[] = [\"web\", \"api\", \"mobile\", \"cli\", \"shared\"];\n\n/** Default domains pre-selected when \"Start from scratch\" is chosen (all except CLI) */\nexport const DEFAULT_SCRATCH_DOMAINS: readonly Domain[] = [\"web\", \"api\", \"mobile\"];\n\nexport const ASCII_LOGO = ` █████╗ ██████╗ ███████╗███╗ ██╗████████╗███████╗ ██╗███╗ ██╗ ██████╗\n██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██╔════╝ ██║████╗ ██║██╔════╝\n███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ███████╗ ██║██╔██╗ ██║██║\n██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║ ██║██║╚██╗██║██║\n██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████║ ██║██║ ╚████║╚██████╗\n╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝`;\n\nexport const DEFAULT_PRESELECTED_SKILLS: readonly SkillId[] = [\n \"meta-methodology-anti-over-engineering\",\n \"meta-methodology-context-management\",\n \"meta-methodology-improvement-protocol\",\n \"meta-methodology-investigation-requirements\",\n \"meta-methodology-success-criteria\",\n \"meta-methodology-write-verification\",\n];\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/__tests__/test-fixtures.ts","../src/cli/lib/__tests__/helpers.ts"],"sourcesContent":["import type {\n CategoryPath,\n MergedSkillsMatrix,\n ResolvedSkill,\n SkillDisplayName,\n SkillId,\n} from \"../../types\";\nimport { createMockSkill, createMockCategory, createMockMatrix } from \"./helpers\";\n\ninterface SkillFixtureConfig {\n id: SkillId;\n category: CategoryPath;\n displayName?: SkillDisplayName;\n description: string;\n tags: string[];\n}\n\nconst SKILL_FIXTURES: Record<string, SkillFixtureConfig> = {\n react: {\n id: \"web-framework-react\",\n category: \"web-framework\",\n displayName: \"react\",\n description: \"React framework for building user interfaces\",\n tags: [\"react\", \"web\", \"ui\", \"component\"],\n },\n zustand: {\n id: \"web-state-zustand\",\n category: \"web-client-state\",\n displayName: \"zustand\",\n description: \"Bear necessities state management\",\n tags: [\"state\", \"react\", \"zustand\"],\n },\n hono: {\n id: \"api-framework-hono\",\n category: \"api-api\",\n displayName: \"hono\",\n description: \"Lightweight web framework for the edge\",\n tags: [\"api\", \"api\", \"edge\", \"serverless\"],\n },\n vitest: {\n id: \"web-testing-vitest\",\n category: \"web-testing\",\n displayName: \"vitest\",\n description: \"Next generation testing framework\",\n tags: [\"testing\", \"vitest\", \"unit\"],\n },\n vue: {\n id: \"web-framework-vue\",\n category: \"web-framework\",\n displayName: \"vue\",\n description: \"Progressive JavaScript framework\",\n tags: [\"vue\", \"web\", \"reactive\"],\n },\n \"auth-patterns\": {\n id: \"api-security-auth-patterns\",\n category: \"api-security\",\n description: \"Authentication and authorization patterns\",\n tags: [\"auth\", \"security\", \"jwt\", \"oauth\"],\n },\n drizzle: {\n id: \"api-database-drizzle\",\n category: \"api-database\",\n displayName: \"drizzle\",\n description: \"TypeScript ORM for SQL databases\",\n tags: [\"database\", \"orm\", \"sql\"],\n },\n methodology: {\n id: \"meta-methodology-anti-over-engineering\",\n category: \"shared-methodology\",\n description: \"Surgical implementation, not architectural innovation\",\n tags: [\"methodology\", \"foundational\"],\n },\n \"scss-modules\": {\n id: \"web-styling-scss-modules\",\n category: \"web-styling\",\n displayName: \"scss-modules\",\n description: \"CSS Modules with SCSS\",\n tags: [\"css\", \"scss\", \"modules\"],\n },\n} as const;\n\nexport type TestSkillName = keyof typeof SKILL_FIXTURES;\n\nexport function getTestSkill(\n name: TestSkillName,\n overrides?: Partial<ResolvedSkill>,\n): ResolvedSkill {\n const config = SKILL_FIXTURES[name];\n const { id, category, ...defaults } = config;\n return createMockSkill(id, category, { ...defaults, ...overrides });\n}\n\n// ---------------------------------------------------------------------------\n// Shared base skill fixtures — canonical defaults with no overrides.\n// Use spread for per-test customization: `{ ...TEST_SKILLS.react, displayName: \"react\" }`\n// ---------------------------------------------------------------------------\n\nexport const TEST_SKILLS = {\n react: createMockSkill(\"web-framework-react\", \"web-framework\"),\n vue: createMockSkill(\"web-framework-vue\", \"web-framework\"),\n zustand: createMockSkill(\"web-state-zustand\", \"web-client-state\", {\n compatibleWith: [\"web-framework-react\"],\n }),\n pinia: createMockSkill(\"web-state-pinia\", \"web-client-state\", {\n compatibleWith: [\"web-framework-vue\"],\n }),\n hono: createMockSkill(\"api-framework-hono\", \"api-api\"),\n vitest: createMockSkill(\"web-testing-vitest\", \"web-testing\"),\n scssModules: createMockSkill(\"web-styling-scss-modules\", \"web-styling\"),\n drizzle: createMockSkill(\"api-database-drizzle\", \"api-database\"),\n // Methodology skills (DEFAULT_PRESELECTED_SKILLS) — used by createComprehensiveMatrix\n investigationRequirements: createMockSkill(\n \"meta-methodology-investigation-requirements\",\n \"shared-methodology\",\n { description: \"Never speculate - read actual code first\" },\n ),\n antiOverEngineering: createMockSkill(\n \"meta-methodology-anti-over-engineering\",\n \"shared-methodology\",\n {\n description: \"Surgical implementation, not architectural innovation\",\n },\n ),\n successCriteria: createMockSkill(\"meta-methodology-success-criteria\", \"shared-methodology\", {\n description: \"Explicit, measurable criteria defining done\",\n }),\n writeVerification: createMockSkill(\"meta-methodology-write-verification\", \"shared-methodology\", {\n description: \"Verify work was actually saved\",\n }),\n improvementProtocol: createMockSkill(\n \"meta-methodology-improvement-protocol\",\n \"shared-methodology\",\n { description: \"Evidence-based self-improvement\" },\n ),\n contextManagement: createMockSkill(\"meta-methodology-context-management\", \"shared-methodology\", {\n description: \"Maintain project continuity across sessions\",\n }),\n};\n\n// ---------------------------------------------------------------------------\n// Shared base category fixtures — canonical defaults with no overrides.\n// Use spread for per-test customization: `{ ...TEST_CATEGORIES.framework, required: true }`\n// ---------------------------------------------------------------------------\n\nexport const TEST_CATEGORIES = {\n framework: createMockCategory(\"web-framework\", \"Framework\"),\n clientState: createMockCategory(\"web-client-state\", \"Client State\"),\n styling: createMockCategory(\"web-styling\", \"Styling\"),\n testing: createMockCategory(\"web-testing\", \"Testing\"),\n api: createMockCategory(\"api-api\", \"Backend Framework\"),\n database: createMockCategory(\"api-database\", \"Database\"),\n methodology: createMockCategory(\"shared-methodology\", \"Methodology\"),\n tooling: createMockCategory(\"shared-tooling\", \"Tooling\"),\n};\n\n// ---------------------------------------------------------------------------\n// Shared matrix fixtures — common skill combinations used across test files.\n// Use createMockMatrix overrides for per-test customization:\n// `createMockMatrix(TEST_MATRICES.react.skills, { suggestedStacks: [...] })`\n// ---------------------------------------------------------------------------\n\nexport const TEST_MATRICES: Record<string, MergedSkillsMatrix> = {\n empty: createMockMatrix({}),\n react: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n }),\n reactAndZustand: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n \"web-state-zustand\": TEST_SKILLS.zustand,\n }),\n reactAndHono: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n \"api-framework-hono\": TEST_SKILLS.hono,\n }),\n reactAndScss: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n \"web-styling-scss-modules\": TEST_SKILLS.scssModules,\n }),\n reactScssAndHono: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n \"web-styling-scss-modules\": TEST_SKILLS.scssModules,\n \"api-framework-hono\": TEST_SKILLS.hono,\n }),\n reactZustandAndHono: createMockMatrix({\n \"web-framework-react\": TEST_SKILLS.react,\n \"web-state-zustand\": TEST_SKILLS.zustand,\n \"api-framework-hono\": TEST_SKILLS.hono,\n }),\n};\n","import path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { mkdir, writeFile, readFile } from \"fs/promises\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { run, Errors } from \"@oclif/core\";\nimport ansis from \"ansis\";\nimport { DEFAULT_BRANDING, DEFAULT_PLUGIN_NAME, STANDARD_FILES } from \"../../consts\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { computeSkillFolderHash } from \"../versioning\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport const CLI_ROOT = path.resolve(__dirname, \"../../../..\");\n\nexport const OUTPUT_STRINGS = {\n CONFIG_HEADER: `${DEFAULT_BRANDING.NAME} Configuration`,\n CONFIG_PATHS_HEADER: \"Configuration File Paths\",\n CONFIG_LAYERS_HEADER: \"Configuration Layers:\",\n CONFIG_PRECEDENCE: \"Precedence: flag > env > project > global > default\",\n SOURCE_LABEL: \"Source:\",\n MARKETPLACE_LABEL: \"Marketplace:\",\n AGENTS_SOURCE_LABEL: \"Agents Source:\",\n GLOBAL_LABEL: \"Global:\",\n PROJECT_LABEL: \"Project:\",\n\n // Setup/Init outputs\n INIT_HEADER: `${DEFAULT_BRANDING.NAME} Setup`,\n INIT_SUCCESS: `${DEFAULT_BRANDING.NAME} initialized successfully!`,\n LOADING_MATRIX: \"Loading skills matrix...\",\n LOADING_SKILLS: \"Loading skills...\",\n LOADING_AGENTS: \"Loading agent partials...\",\n\n // Plugin/installation outputs\n NO_PLUGIN_FOUND: \"No plugin found\",\n NO_INSTALLATION_FOUND: \"No installation found\",\n NO_PLUGIN_INSTALLATION: \"No plugin installation found\",\n NOT_INSTALLED: `${DEFAULT_BRANDING.NAME} is not installed`,\n UNINSTALL_HEADER: `${DEFAULT_BRANDING.NAME} Uninstall`,\n UNINSTALL_COMPLETE: `${DEFAULT_BRANDING.NAME} has been uninstalled`,\n EJECT_HEADER: `${DEFAULT_BRANDING.NAME} Eject`,\n\n // Doctor command outputs\n DOCTOR_HEADER: `${DEFAULT_BRANDING.NAME} Doctor`,\n\n // Error message patterns (lowercase for case-insensitive matching)\n ERROR_MISSING_ARG: \"missing required arg\",\n ERROR_UNEXPECTED_ARG: \"unexpected argument\",\n ERROR_UNKNOWN_FLAG: \"unknown flag\",\n ERROR_PARSE: \"parse\",\n} as const;\n\n/**\n * Run a CLI command and capture its output.\n *\n * Bun's `console.log` does not go through `process.stdout.write`, so\n * `@oclif/test`'s `runCommand` (which only intercepts `process.stdout.write`)\n * returns empty stdout/stderr in bun. This helper intercepts both layers\n * to work correctly in both Node.js and bun environments.\n */\nexport async function runCliCommand(args: string[]) {\n const origStdoutWrite = process.stdout.write;\n const origStderrWrite = process.stderr.write;\n const origLog = console.log;\n const origWarn = console.warn;\n const origError = console.error;\n\n const stdoutBuf: string[] = [];\n const stderrBuf: string[] = [];\n\n // Intercept process.stdout/stderr.write (Node.js path)\n process.stdout.write = function (str: unknown, encoding?: unknown, cb?: unknown): boolean {\n stdoutBuf.push(String(str));\n if (typeof encoding === \"function\") {\n (encoding as () => void)();\n } else if (typeof cb === \"function\") {\n (cb as () => void)();\n }\n return true;\n } as typeof process.stdout.write;\n\n process.stderr.write = function (str: unknown, encoding?: unknown, cb?: unknown): boolean {\n stderrBuf.push(String(str));\n if (typeof encoding === \"function\") {\n (encoding as () => void)();\n } else if (typeof cb === \"function\") {\n (cb as () => void)();\n }\n return true;\n } as typeof process.stderr.write;\n\n // Intercept console methods (bun path — console.log bypasses process.stdout.write)\n console.log = (...logArgs: unknown[]) => {\n stdoutBuf.push(logArgs.map(String).join(\" \") + \"\\n\");\n };\n console.warn = (...warnArgs: unknown[]) => {\n stderrBuf.push(warnArgs.map(String).join(\" \") + \"\\n\");\n };\n console.error = (...errArgs: unknown[]) => {\n stderrBuf.push(errArgs.map(String).join(\" \") + \"\\n\");\n };\n\n let error: (Error & Partial<Errors.CLIError>) | undefined;\n try {\n await run(args, { root: CLI_ROOT });\n } catch (e) {\n if (e instanceof Error) {\n error = Object.assign(e, { message: ansis.strip(e.message) }) as Error &\n Partial<Errors.CLIError>;\n }\n } finally {\n process.stdout.write = origStdoutWrite;\n process.stderr.write = origStderrWrite;\n console.log = origLog;\n console.warn = origWarn;\n console.error = origError;\n }\n\n return {\n stdout: stdoutBuf.map((s) => ansis.strip(s)).join(\"\"),\n stderr: stderrBuf.map((s) => ansis.strip(s)).join(\"\"),\n error,\n };\n}\nimport type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CategoryDefinition,\n CategoryPath,\n CompileAgentConfig,\n CompileConfig,\n CompileContext,\n Domain,\n DomainSelections,\n ExtractedSkillMetadata,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n Skill,\n SkillAssignment,\n SkillDefinition,\n SkillDisplayName,\n SkillId,\n SkillSource,\n SkillSourceType,\n RelationshipDefinitions,\n Stack,\n StackAgentConfig,\n Subcategory,\n} from \"../../types\";\nimport type { CompiledStackPlugin } from \"../stacks/stack-plugin-compiler\";\nimport type { WizardResultV2 } from \"../../components/wizard/wizard\";\nimport type { SourceLoadResult } from \"../loading/source-loader\";\nimport type { ResolvedConfig } from \"../configuration/config\";\nimport { useWizardStore } from \"../../stores/wizard-store\";\nimport { resolveAlias, validateSelection } from \"../matrix\";\nimport type { TestProjectConfig } from \"./fixtures/create-test-source\";\nimport { getTestSkill, TEST_SKILLS, TEST_CATEGORIES } from \"./test-fixtures\";\n\nexport { fileExists, directoryExists } from \"./test-fs-utils\";\n\nexport async function readTestYaml<T>(filePath: string): Promise<T> {\n const content = await readFile(filePath, \"utf-8\");\n // Boundary cast: YAML parse returns `unknown`, caller provides expected type\n return parseYaml(content) as T;\n}\n\nexport function buildWizardResult(\n selectedSkills: SkillId[],\n overrides?: Partial<WizardResultV2>,\n): WizardResultV2 {\n return {\n selectedSkills,\n selectedAgents: [],\n selectedStackId: null,\n domainSelections: {} as DomainSelections,\n selectedDomains: [],\n sourceSelections: {},\n installMode: \"local\",\n cancelled: false,\n validation: { valid: true, errors: [], warnings: [] },\n ...overrides,\n };\n}\n\nexport function buildSourceResult(\n matrix: MergedSkillsMatrix,\n sourcePath: string,\n overrides?: Partial<SourceLoadResult>,\n): SourceLoadResult {\n const sourceConfig: ResolvedConfig = {\n source: sourcePath,\n sourceOrigin: \"flag\",\n };\n return {\n matrix,\n sourceConfig,\n sourcePath,\n isLocal: true,\n ...overrides,\n };\n}\n\n/**\n * Lightweight frontmatter parser for test assertions.\n * Returns raw key-value pairs (unlike the production parseFrontmatter which\n * returns typed SkillFrontmatter with Zod validation).\n */\nexport function parseTestFrontmatter(content: string): Record<string, unknown> | null {\n if (!content.startsWith(\"---\")) {\n return null;\n }\n\n const endIndex = content.indexOf(\"---\", 3);\n if (endIndex === -1) {\n return null;\n }\n\n const yamlContent = content.slice(3, endIndex).trim();\n try {\n // Boundary cast: YAML parse returns `unknown`\n return parseYaml(yamlContent) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nimport { createTempDir, cleanupTempDir } from \"./test-fs-utils\";\nexport { createTempDir, cleanupTempDir };\n\nexport interface TestDirs {\n tempDir: string;\n projectDir: string;\n pluginDir: string;\n skillsDir: string;\n agentsDir: string;\n}\n\nexport async function createTestDirs(prefix = \"ai-test-\"): Promise<TestDirs> {\n const tempDir = await createTempDir(prefix);\n const projectDir = path.join(tempDir, \"project\");\n const pluginDir = path.join(projectDir, \".claude\", \"plugins\", DEFAULT_PLUGIN_NAME);\n const skillsDir = path.join(pluginDir, \"skills\");\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await mkdir(skillsDir, { recursive: true });\n await mkdir(agentsDir, { recursive: true });\n\n return { tempDir, projectDir, pluginDir, skillsDir, agentsDir };\n}\n\nexport async function cleanupTestDirs(dirs: TestDirs): Promise<void> {\n await cleanupTempDir(dirs.tempDir);\n}\n\nexport function createMockSkill(\n id: SkillId,\n category: CategoryPath,\n overrides?: Partial<ResolvedSkill>,\n): ResolvedSkill {\n return {\n id,\n description: `${id} skill`,\n category,\n tags: [],\n author: \"@test\",\n conflictsWith: [],\n recommends: [],\n requires: [],\n alternatives: [],\n discourages: [],\n compatibleWith: [],\n requiresSetup: [],\n providesSetupFor: [],\n path: `skills/${category}/${id}/`,\n ...overrides,\n };\n}\n\nexport function createMockSkillSource(\n type: SkillSourceType,\n overrides?: Partial<SkillSource>,\n): SkillSource {\n const defaults: Record<SkillSourceType, SkillSource> = {\n public: { name: \"public\", type: \"public\", installed: false },\n private: {\n name: \"private-source\",\n type: \"private\",\n url: \"github:org/skills\",\n installed: false,\n },\n local: { name: \"local\", type: \"local\", installed: true, installMode: \"local\" },\n };\n return { ...defaults[type], ...overrides };\n}\n\n/**\n * Creates a mock ExtractedSkillMetadata for testing.\n * Used when mocking extractAllSkills() return values.\n */\nexport function createMockExtractedSkill(\n id: SkillId,\n overrides?: Partial<ExtractedSkillMetadata>,\n): ExtractedSkillMetadata {\n // Derive directory path and category from the skill ID convention: \"domain-subcategory-name\"\n const segments = id.split(\"-\");\n const domain = segments[0] ?? \"web\";\n const subcategory = segments[1] ?? \"framework\";\n const name = segments.slice(2).join(\"-\") || \"skill\";\n const directoryPath = `${domain}/${subcategory}/${name}`;\n\n return {\n id,\n directoryPath,\n description: `${id} skill`,\n category: `${domain}-${subcategory}` as CategoryPath,\n author: \"@test\",\n tags: [],\n path: `skills/${directoryPath}/`,\n ...overrides,\n };\n}\n\nexport function createMockMatrix(\n skills: Record<string, ResolvedSkill>,\n overrides?: Partial<MergedSkillsMatrix>,\n): MergedSkillsMatrix {\n // Auto-generate displayNames and displayNameToId from skills\n const autoDisplayNames = {} as Record<SkillId, SkillDisplayName>;\n const autoDisplayNameToId = {} as Record<SkillDisplayName, SkillId>;\n for (const [id, skill] of typedEntries(skills)) {\n if (skill.displayName) {\n autoDisplayNames[id as SkillId] = skill.displayName;\n autoDisplayNameToId[skill.displayName] = id as SkillId;\n }\n }\n\n return {\n version: \"1.0.0\",\n categories: {} as Record<Subcategory, import(\"../../types\").CategoryDefinition>,\n skills,\n suggestedStacks: [],\n displayNameToId: autoDisplayNameToId,\n displayNames: autoDisplayNames,\n generatedAt: new Date().toISOString(),\n ...overrides,\n };\n}\n\nexport function createMockAgent(\n name: string,\n overrides?: Partial<AgentDefinition>,\n): AgentDefinition {\n return {\n title: name,\n description: `${name} agent`,\n tools: [\"Read\", \"Write\", \"Edit\", \"Grep\", \"Glob\", \"Bash\"],\n model: \"opus\",\n permissionMode: \"default\",\n ...overrides,\n };\n}\n\nexport function createMockAgentConfig(\n name: string,\n skills: Skill[] = [],\n overrides?: Partial<AgentConfig>,\n): AgentConfig {\n return {\n name,\n title: `${name} agent`,\n description: `Test ${name}`,\n tools: [\"Read\", \"Write\"],\n skills,\n path: name,\n ...overrides,\n };\n}\n\nexport function createMockSkillEntry(\n id: SkillId,\n preloaded = false,\n overrides?: Partial<Skill>,\n): Skill {\n return {\n id,\n path: `skills/${id}/`,\n description: `${id} skill`,\n usage: `when working with ${id}`,\n preloaded,\n ...overrides,\n };\n}\n\nexport function createCompileContext(overrides?: Partial<CompileContext>): CompileContext {\n return {\n stackId: \"test-stack\",\n verbose: false,\n projectRoot: \"/project\",\n outputDir: `/project/.claude/plugins/${DEFAULT_PLUGIN_NAME}`,\n ...overrides,\n };\n}\n\nexport function createSkillContent(name: string, description = \"A test skill\"): string {\n return `---\nname: ${name}\ndescription: ${description}\ncategory: test\n---\n\n# ${name}\n\nThis is a test skill.\n`;\n}\n\nfunction createMetadataContent(author = \"@test\"): string {\n return `author: \"${author}\"\n`;\n}\n\nexport function createAgentYamlContent(name: string, description = `Test ${name} agent`): string {\n return `id: ${name}\ntitle: ${name} Agent\ndescription: ${description}\ntools:\n - Read\n - Write`;\n}\n\nexport async function writeTestSkill(\n skillsDir: string,\n skillName: string,\n options?: {\n author?: string;\n description?: string;\n /** Extra fields to merge into metadata.yaml (e.g., forkedFrom, displayName) */\n extraMetadata?: Record<string, unknown>;\n /** Skip metadata.yaml creation entirely */\n skipMetadata?: boolean;\n /** Custom SKILL.md content (overrides default generated content) */\n skillContent?: string;\n },\n): Promise<string> {\n const skillDir = path.join(skillsDir, skillName);\n await mkdir(skillDir, { recursive: true });\n\n await writeFile(\n path.join(skillDir, STANDARD_FILES.SKILL_MD),\n options?.skillContent ?? createSkillContent(skillName, options?.description),\n );\n\n if (!options?.skipMetadata) {\n const contentHash = await computeSkillFolderHash(skillDir);\n if (options?.extraMetadata) {\n const metadata = {\n author: options?.author ?? \"@test\",\n contentHash,\n ...options?.extraMetadata,\n };\n await writeFile(path.join(skillDir, STANDARD_FILES.METADATA_YAML), stringifyYaml(metadata));\n } else {\n const metadata = {\n author: options?.author ?? \"@test\",\n contentHash,\n };\n await writeFile(path.join(skillDir, STANDARD_FILES.METADATA_YAML), stringifyYaml(metadata));\n }\n }\n\n return skillDir;\n}\n\n/**\n * Creates a source-level skill directory with SKILL.md and rich metadata.yaml.\n * Use this when testing `extractAllSkills()` and `mergeMatrixWithSkills()`.\n *\n * Unlike `writeTestSkill()` which creates installed skills, this writes skills\n * in the source directory layout (under `src/skills/<domain>/<subcategory>/<name>/`).\n */\nexport async function writeSourceSkill(\n skillsDir: string,\n directoryPath: string,\n config: {\n id: string;\n description: string;\n category: string;\n author?: string;\n tags?: string[];\n content?: string;\n },\n): Promise<string> {\n const skillDir = path.join(skillsDir, directoryPath);\n await mkdir(skillDir, { recursive: true });\n\n await writeFile(\n path.join(skillDir, STANDARD_FILES.SKILL_MD),\n createSkillContent(config.id, config.description),\n );\n\n const metadata: Record<string, unknown> = {\n displayName: config.id,\n category: config.category,\n author: config.author ?? \"@test\",\n };\n if (config.tags) {\n metadata.tags = config.tags;\n }\n\n await writeFile(path.join(skillDir, STANDARD_FILES.METADATA_YAML), stringifyYaml(metadata));\n\n return skillDir;\n}\n\nexport async function writeTestAgent(\n agentsDir: string,\n agentName: string,\n options?: { description?: string },\n): Promise<string> {\n const agentDir = path.join(agentsDir, agentName);\n await mkdir(agentDir, { recursive: true });\n\n await writeFile(\n path.join(agentDir, STANDARD_FILES.AGENT_METADATA_YAML),\n createAgentYamlContent(agentName, options?.description),\n );\n\n return agentDir;\n}\n\nexport function createMockCategory(\n id: Subcategory,\n displayName: string,\n overrides?: Partial<CategoryDefinition>,\n): CategoryDefinition {\n return {\n id,\n displayName,\n description: `${displayName} category`,\n domain: \"web\",\n exclusive: true,\n required: false,\n order: 0,\n ...overrides,\n };\n}\n\nexport function createMockResolvedStack(\n id: string,\n name: string,\n overrides?: Partial<ResolvedStack>,\n): ResolvedStack {\n return {\n id,\n name,\n description: `${name} stack`,\n skills: {},\n allSkillIds: [],\n philosophy: \"\",\n ...overrides,\n };\n}\n\n/**\n * Builds a comprehensive test matrix with 13 skills across 7 categories,\n * 2 suggested stacks, display name mappings, and relationship data\n * (conflicts, recommends). Includes all 6 DEFAULT_PRESELECTED_SKILLS\n * (methodology) so wizard handleComplete can resolve them.\n * @returns A fully populated MergedSkillsMatrix with realistic test data\n */\nexport function createComprehensiveMatrix(\n overrides?: Partial<MergedSkillsMatrix>,\n): MergedSkillsMatrix {\n // Skill categories use domain-prefixed Subcategory IDs (matching production\n // metadata.yaml and the categories map keys, e.g., \"web-framework\", \"api-api\").\n const skills = {\n \"web-framework-react\": getTestSkill(\"react\", { category: \"web-framework\" }),\n \"web-framework-vue\": getTestSkill(\"vue\", {\n category: \"web-framework\",\n conflictsWith: [{ skillId: \"web-framework-react\", reason: \"Choose one framework\" }],\n }),\n \"web-state-zustand\": getTestSkill(\"zustand\", {\n category: \"web-client-state\",\n recommends: [{ skillId: \"web-framework-react\", reason: \"Works great with React\" }],\n }),\n \"web-styling-scss-modules\": getTestSkill(\"scss-modules\", { category: \"web-styling\" }),\n \"api-framework-hono\": getTestSkill(\"hono\", { category: \"api-api\" }),\n \"api-database-drizzle\": getTestSkill(\"drizzle\", { category: \"api-database\" }),\n \"web-testing-vitest\": getTestSkill(\"vitest\", { category: \"web-testing\" }),\n // Methodology skills (DEFAULT_PRESELECTED_SKILLS) — auto-injected by wizard\n \"meta-methodology-investigation-requirements\": TEST_SKILLS.investigationRequirements,\n \"meta-methodology-anti-over-engineering\": TEST_SKILLS.antiOverEngineering,\n \"meta-methodology-success-criteria\": TEST_SKILLS.successCriteria,\n \"meta-methodology-write-verification\": TEST_SKILLS.writeVerification,\n \"meta-methodology-improvement-protocol\": TEST_SKILLS.improvementProtocol,\n \"meta-methodology-context-management\": TEST_SKILLS.contextManagement,\n };\n\n const categories = {\n \"web-framework\": {\n ...TEST_CATEGORIES.framework,\n domain: \"web\" as Domain,\n exclusive: true,\n required: true,\n },\n \"web-client-state\": { ...TEST_CATEGORIES.clientState, domain: \"web\" as Domain, order: 1 },\n \"web-styling\": { ...TEST_CATEGORIES.styling, domain: \"web\" as Domain, order: 2 },\n \"api-api\": { ...TEST_CATEGORIES.api, domain: \"api\" as Domain, exclusive: true, required: true },\n \"api-database\": { ...TEST_CATEGORIES.database, domain: \"api\" as Domain, order: 1 },\n \"web-testing\": {\n ...TEST_CATEGORIES.testing,\n domain: \"shared\" as Domain,\n exclusive: false,\n order: 10,\n },\n \"shared-methodology\": {\n ...TEST_CATEGORIES.methodology,\n domain: \"shared\" as Domain,\n exclusive: false,\n required: false,\n order: 11,\n },\n } as Record<Subcategory, CategoryDefinition>;\n\n const suggestedStacks: ResolvedStack[] = [\n createMockResolvedStack(\"nextjs-fullstack\", \"Next.js Fullstack\", {\n description: \"Complete Next.js stack with React and Hono\",\n skills: {\n \"web-developer\": {\n \"web-framework\": [\"web-framework-react\"],\n \"web-client-state\": [\"web-state-zustand\"],\n \"web-styling\": [\"web-styling-scss-modules\"],\n },\n \"api-developer\": {\n \"api-api\": [\"api-framework-hono\"],\n \"api-database\": [\"api-database-drizzle\"],\n },\n } as ResolvedStack[\"skills\"],\n allSkillIds: [\n \"web-framework-react\",\n \"web-state-zustand\",\n \"web-styling-scss-modules\",\n \"api-framework-hono\",\n \"api-database-drizzle\",\n ],\n philosophy: \"Modern, type-safe fullstack development\",\n }),\n createMockResolvedStack(\"vue-stack\", \"Vue Stack\", {\n description: \"Vue.js frontend stack\",\n skills: {\n \"web-developer\": {\n \"web-framework\": [\"web-framework-vue\"],\n },\n } as ResolvedStack[\"skills\"],\n allSkillIds: [\"web-framework-vue\"],\n philosophy: \"Progressive framework approach\",\n }),\n ];\n\n const displayNameToId = {\n react: \"web-framework-react\",\n vue: \"web-framework-vue\",\n zustand: \"web-state-zustand\",\n \"scss-modules\": \"web-styling-scss-modules\",\n hono: \"api-framework-hono\",\n drizzle: \"api-database-drizzle\",\n vitest: \"web-testing-vitest\",\n \"investigation-requirements\": \"meta-methodology-investigation-requirements\",\n \"anti-over-engineering\": \"meta-methodology-anti-over-engineering\",\n \"success-criteria\": \"meta-methodology-success-criteria\",\n \"write-verification\": \"meta-methodology-write-verification\",\n \"improvement-protocol\": \"meta-methodology-improvement-protocol\",\n \"context-management\": \"meta-methodology-context-management\",\n // Double cast needed: object literal's string keys are not assignable to branded\n // SkillDisplayName/SkillId types without going through `unknown` first (boundary cast)\n } as unknown as Record<SkillDisplayName, SkillId>;\n\n const displayNames = {} as Record<SkillId, SkillDisplayName>;\n for (const [displayName, fullId] of typedEntries(displayNameToId)) {\n (displayNames as Record<string, string>)[fullId] = displayName;\n }\n\n return createMockMatrix(skills, {\n categories,\n suggestedStacks,\n displayNameToId,\n displayNames,\n ...overrides,\n });\n}\n\n/**\n * Builds a lightweight test matrix with 4 skills, 4 categories, and 2 stacks.\n * Use instead of createComprehensiveMatrix when relationship data is not needed.\n * @returns A minimal MergedSkillsMatrix for basic integration tests\n */\nexport function createBasicMatrix(overrides?: Partial<MergedSkillsMatrix>): MergedSkillsMatrix {\n // Domain-prefixed Subcategory IDs — see createComprehensiveMatrix comment\n const skills = {\n \"web-framework-react\": getTestSkill(\"react\", { category: \"web-framework\" }),\n \"web-state-zustand\": getTestSkill(\"zustand\", { category: \"web-client-state\" }),\n \"api-framework-hono\": getTestSkill(\"hono\", { category: \"api-api\" }),\n \"web-testing-vitest\": getTestSkill(\"vitest\", { category: \"web-testing\" }),\n };\n\n const suggestedStacks: ResolvedStack[] = [\n createMockResolvedStack(\"react-fullstack\", \"React Fullstack\", {\n allSkillIds: [\"web-framework-react\", \"web-state-zustand\", \"api-framework-hono\"],\n }),\n createMockResolvedStack(\"testing-stack\", \"Testing Stack\", {\n allSkillIds: [\"web-testing-vitest\"],\n }),\n ];\n\n return createMockMatrix(skills, {\n suggestedStacks,\n categories: {\n \"web-framework\": {\n ...TEST_CATEGORIES.framework,\n domain: \"web\" as Domain,\n exclusive: true,\n required: true,\n },\n \"web-client-state\": { ...TEST_CATEGORIES.clientState, domain: \"web\" as Domain, order: 1 },\n \"api-api\": {\n ...TEST_CATEGORIES.api,\n domain: \"api\" as Domain,\n exclusive: true,\n required: true,\n },\n \"web-testing\": {\n ...TEST_CATEGORIES.testing,\n displayName: \"Testing Framework\",\n domain: \"shared\" as Domain,\n exclusive: false,\n },\n } as Record<Subcategory, CategoryDefinition>,\n ...overrides,\n });\n}\n\n/**\n * Replicates `handleComplete` from wizard.tsx for the \"customize\" path.\n *\n * Given the wizard store state (after simulated user selections), this\n * builds the same WizardResultV2 that the real wizard produces:\n * 1. Collects all selected technologies from domainSelections\n * 2. Resolves aliases to canonical skill IDs\n * 3. Adds methodology skills (DEFAULT_PRESELECTED_SKILLS)\n * 4. Runs validation\n */\nexport function buildWizardResultFromStore(\n matrix: MergedSkillsMatrix,\n overrides?: Partial<WizardResultV2>,\n): WizardResultV2 {\n const store = useWizardStore.getState();\n\n let allSkills: SkillId[];\n\n if (store.selectedStackId && store.stackAction === \"defaults\") {\n const stack = matrix.suggestedStacks.find((s) => s.id === store.selectedStackId);\n allSkills = [...(stack?.allSkillIds || [])];\n } else {\n const techNames = store.getAllSelectedTechnologies();\n allSkills = techNames.map((tech) => resolveAlias(tech, matrix));\n }\n\n const methodologySkills = store.getDefaultMethodologySkills();\n for (const skill of methodologySkills) {\n if (!allSkills.includes(skill)) {\n allSkills.push(skill);\n }\n }\n\n const validation = validateSelection(allSkills, matrix);\n\n return {\n selectedSkills: allSkills,\n selectedAgents: store.selectedAgents,\n selectedStackId: store.selectedStackId,\n domainSelections: store.domainSelections,\n selectedDomains: store.selectedDomains,\n sourceSelections: store.sourceSelections,\n installMode: store.installMode,\n cancelled: false,\n validation,\n ...overrides,\n };\n}\n\n/**\n * Simulates a user selecting specific skills via the wizard store.\n *\n * Sets up domainSelections as if the user toggled each skill in the build step,\n * using the matrix to look up the correct domain and subcategory per skill.\n */\nexport function simulateSkillSelections(\n skillIds: SkillId[],\n matrix: MergedSkillsMatrix,\n selectedDomains: string[],\n): void {\n const domainSelections: DomainSelections = {};\n\n for (const skillId of skillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n // Boundary cast: skill.category is a Subcategory at runtime\n const subcategory = skill.category as Subcategory;\n const categoryDef = matrix.categories[subcategory];\n const domain = categoryDef?.domain;\n if (!domain) continue;\n\n if (!domainSelections[domain]) {\n domainSelections[domain] = {};\n }\n if (!domainSelections[domain][subcategory]) {\n domainSelections[domain][subcategory] = [];\n }\n if (!domainSelections[domain][subcategory].includes(skillId)) {\n domainSelections[domain][subcategory].push(skillId);\n }\n }\n\n useWizardStore.setState({\n domainSelections,\n selectedDomains: selectedDomains as Domain[],\n approach: \"scratch\",\n step: \"confirm\",\n });\n}\n\n/**\n * Extracts skill IDs from a stack assignment value, which may be:\n * - A bare string (e.g., \"web-framework-react\")\n * - An object with .id (e.g., { id: \"web-framework-react\", preloaded: true })\n * - An array of strings or objects\n */\nexport function extractSkillIdsFromAssignment(assignment: unknown): string[] {\n if (typeof assignment === \"string\") {\n return [assignment];\n }\n if (Array.isArray(assignment)) {\n return assignment.flatMap((item) => extractSkillIdsFromAssignment(item));\n }\n if (typeof assignment === \"object\" && assignment !== null && \"id\" in assignment) {\n return [String((assignment as { id: string }).id)];\n }\n return [];\n}\n\nexport function buildTestProjectConfig(\n agents: string[],\n skills: Array<string | { id: string }>,\n overrides?: Partial<TestProjectConfig>,\n): TestProjectConfig {\n return {\n name: \"test-project\",\n description: \"Test project\",\n agents,\n skills,\n ...overrides,\n };\n}\n\nexport function createMockSkillDefinition(\n id: SkillId,\n overrides?: Partial<SkillDefinition>,\n): SkillDefinition {\n return {\n id,\n path: `skills/${id}/`,\n description: `${id} skill`,\n ...overrides,\n };\n}\n\n/** Decomposed matrix config returned by createMockMatrixConfig (replaces SkillsMatrixConfig) */\nexport type MockMatrixConfig = {\n categories: Record<string, CategoryDefinition>;\n relationships: RelationshipDefinitions;\n aliases: Partial<Record<SkillDisplayName, SkillId>>;\n};\n\nexport function createMockMatrixConfig(\n categories: Record<string, CategoryDefinition>,\n overrides?: {\n relationships?: RelationshipDefinitions;\n skillAliases?: Partial<Record<SkillDisplayName, SkillId>>;\n },\n): MockMatrixConfig {\n return {\n categories,\n relationships: overrides?.relationships ?? {\n conflicts: [],\n discourages: [],\n recommends: [],\n requires: [],\n alternatives: [],\n },\n aliases: overrides?.skillAliases ?? {},\n };\n}\n\nexport function createMockStack(\n id: string,\n config: {\n name: string;\n description?: string;\n agents: Record<string, StackAgentConfig>;\n philosophy?: string;\n },\n): Stack {\n return {\n id,\n name: config.name,\n description: config.description ?? \"\",\n // Boundary cast: test callers may pass arbitrary agent names (e.g., \"nonexistent-agent\")\n agents: config.agents as Stack[\"agents\"],\n philosophy: config.philosophy,\n };\n}\n\nexport function createMockCompileConfig(\n agents: Record<string, CompileAgentConfig>,\n overrides?: Partial<CompileConfig>,\n): CompileConfig {\n return {\n name: \"Test Plugin\",\n description: \"Test description\",\n agents,\n ...overrides,\n };\n}\n\nexport function createMockCompiledStackPlugin(\n overrides?: Partial<CompiledStackPlugin>,\n): CompiledStackPlugin {\n return {\n pluginPath: \"/tmp/cc-stack-123456/test-stack\",\n manifest: { name: \"test-stack\", version: \"1.0.0\" },\n stackName: \"Test Stack\",\n agents: [\"web-developer\"] as AgentName[],\n skillPlugins: [\"web-framework-react\"] as SkillId[],\n hasHooks: false,\n ...overrides,\n };\n}\n\nexport function createMockSkillAssignment(id: SkillId, preloaded = false): SkillAssignment {\n return { id, preloaded };\n}\n\nexport { getTestSkill, TEST_SKILLS, TEST_CATEGORIES, TEST_MATRICES } from \"./test-fixtures\";\nexport type { TestSkillName } from \"./test-fixtures\";\n"],"mappings":";;;;;;;;;;;;AAAA;;;ACAA;AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,SAAS,SAAS,WAAW,aAAa,qBAAqB;AAC/D,SAAS,WAAmB;AAM5B,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,KAAK,QAAQ,UAAU;AAElC,IAAM,WAAW,KAAK,QAAQ,WAAW,aAAa;AAEtD,IAAM,iBAAiB;AAAA,EAC5B,eAAe,GAAG,iBAAiB,IAAI;AAAA,EACvC,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,eAAe;AAAA;AAAA,EAGf,aAAa,GAAG,iBAAiB,IAAI;AAAA,EACrC,cAAc,GAAG,iBAAiB,IAAI;AAAA,EACtC,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AAAA,EACjB,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,eAAe,GAAG,iBAAiB,IAAI;AAAA,EACvC,kBAAkB,GAAG,iBAAiB,IAAI;AAAA,EAC1C,oBAAoB,GAAG,iBAAiB,IAAI;AAAA,EAC5C,cAAc,GAAG,iBAAiB,IAAI;AAAA;AAAA,EAGtC,eAAe,GAAG,iBAAiB,IAAI;AAAA;AAAA,EAGvC,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,aAAa;AACf;AA8MO,SAAS,gBACd,IACA,UACA,WACe;AACf,SAAO;AAAA,IACL;AAAA,IACA,aAAa,GAAG,EAAE;AAAA,IAClB;AAAA,IACA,MAAM,CAAC;AAAA,IACP,QAAQ;AAAA,IACR,eAAe,CAAC;AAAA,IAChB,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,cAAc,CAAC;AAAA,IACf,aAAa,CAAC;AAAA,IACd,gBAAgB,CAAC;AAAA,IACjB,eAAe,CAAC;AAAA,IAChB,kBAAkB,CAAC;AAAA,IACnB,MAAM,UAAU,QAAQ,IAAI,EAAE;AAAA,IAC9B,GAAG;AAAA,EACL;AACF;AA8CO,SAAS,iBACd,QACA,WACoB;AAEpB,QAAM,mBAAmB,CAAC;AAC1B,QAAM,sBAAsB,CAAC;AAC7B,aAAW,CAAC,IAAI,KAAK,KAAK,aAAa,MAAM,GAAG;AAC9C,QAAI,MAAM,aAAa;AACrB,uBAAiB,EAAa,IAAI,MAAM;AACxC,0BAAoB,MAAM,WAAW,IAAI;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC;AAAA,IACb;AAAA,IACA,iBAAiB,CAAC;AAAA,IAClB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,GAAG;AAAA,EACL;AACF;AAwLO,SAAS,mBACd,IACA,aACA,WACoB;AACpB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,GAAG,WAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AACF;AAEO,SAAS,wBACd,IACA,MACA,WACe;AACf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,GAAG,IAAI;AAAA,IACpB,QAAQ,CAAC;AAAA,IACT,aAAa,CAAC;AAAA,IACd,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;;;ADliBA,IAAM,iBAAqD;AAAA,EACzD,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,SAAS,OAAO,MAAM,WAAW;AAAA,EAC1C;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,SAAS,SAAS,SAAS;AAAA,EACpC;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,OAAO,OAAO,QAAQ,YAAY;AAAA,EAC3C;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,WAAW,UAAU,MAAM;AAAA,EACpC;AAAA,EACA,KAAK;AAAA,IACH,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,OAAO,OAAO,UAAU;AAAA,EACjC;AAAA,EACA,iBAAiB;AAAA,IACf,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAM,CAAC,QAAQ,YAAY,OAAO,OAAO;AAAA,EAC3C;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,YAAY,OAAO,KAAK;AAAA,EACjC;AAAA,EACA,aAAa;AAAA,IACX,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAM,CAAC,eAAe,cAAc;AAAA,EACtC;AAAA,EACA,gBAAgB;AAAA,IACd,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,OAAO,QAAQ,SAAS;AAAA,EACjC;AACF;AAIO,SAAS,aACd,MACA,WACe;AACf,QAAM,SAAS,eAAe,IAAI;AAClC,QAAM,EAAE,IAAI,UAAU,GAAG,SAAS,IAAI;AACtC,SAAO,gBAAgB,IAAI,UAAU,EAAE,GAAG,UAAU,GAAG,UAAU,CAAC;AACpE;AAOO,IAAM,cAAc;AAAA,EACzB,OAAO,gBAAgB,uBAAuB,eAAe;AAAA,EAC7D,KAAK,gBAAgB,qBAAqB,eAAe;AAAA,EACzD,SAAS,gBAAgB,qBAAqB,oBAAoB;AAAA,IAChE,gBAAgB,CAAC,qBAAqB;AAAA,EACxC,CAAC;AAAA,EACD,OAAO,gBAAgB,mBAAmB,oBAAoB;AAAA,IAC5D,gBAAgB,CAAC,mBAAmB;AAAA,EACtC,CAAC;AAAA,EACD,MAAM,gBAAgB,sBAAsB,SAAS;AAAA,EACrD,QAAQ,gBAAgB,sBAAsB,aAAa;AAAA,EAC3D,aAAa,gBAAgB,4BAA4B,aAAa;AAAA,EACtE,SAAS,gBAAgB,wBAAwB,cAAc;AAAA;AAAA,EAE/D,2BAA2B;AAAA,IACzB;AAAA,IACA;AAAA,IACA,EAAE,aAAa,2CAA2C;AAAA,EAC5D;AAAA,EACA,qBAAqB;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,MACE,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,iBAAiB,gBAAgB,qCAAqC,sBAAsB;AAAA,IAC1F,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,gBAAgB,uCAAuC,sBAAsB;AAAA,IAC9F,aAAa;AAAA,EACf,CAAC;AAAA,EACD,qBAAqB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,EAAE,aAAa,kCAAkC;AAAA,EACnD;AAAA,EACA,mBAAmB,gBAAgB,uCAAuC,sBAAsB;AAAA,IAC9F,aAAa;AAAA,EACf,CAAC;AACH;AAOO,IAAM,kBAAkB;AAAA,EAC7B,WAAW,mBAAmB,iBAAiB,WAAW;AAAA,EAC1D,aAAa,mBAAmB,oBAAoB,cAAc;AAAA,EAClE,SAAS,mBAAmB,eAAe,SAAS;AAAA,EACpD,SAAS,mBAAmB,eAAe,SAAS;AAAA,EACpD,KAAK,mBAAmB,WAAW,mBAAmB;AAAA,EACtD,UAAU,mBAAmB,gBAAgB,UAAU;AAAA,EACvD,aAAa,mBAAmB,sBAAsB,aAAa;AAAA,EACnE,SAAS,mBAAmB,kBAAkB,SAAS;AACzD;AAQO,IAAM,gBAAoD;AAAA,EAC/D,OAAO,iBAAiB,CAAC,CAAC;AAAA,EAC1B,OAAO,iBAAiB;AAAA,IACtB,uBAAuB,YAAY;AAAA,EACrC,CAAC;AAAA,EACD,iBAAiB,iBAAiB;AAAA,IAChC,uBAAuB,YAAY;AAAA,IACnC,qBAAqB,YAAY;AAAA,EACnC,CAAC;AAAA,EACD,cAAc,iBAAiB;AAAA,IAC7B,uBAAuB,YAAY;AAAA,IACnC,sBAAsB,YAAY;AAAA,EACpC,CAAC;AAAA,EACD,cAAc,iBAAiB;AAAA,IAC7B,uBAAuB,YAAY;AAAA,IACnC,4BAA4B,YAAY;AAAA,EAC1C,CAAC;AAAA,EACD,kBAAkB,iBAAiB;AAAA,IACjC,uBAAuB,YAAY;AAAA,IACnC,4BAA4B,YAAY;AAAA,IACxC,sBAAsB,YAAY;AAAA,EACpC,CAAC;AAAA,EACD,qBAAqB,iBAAiB;AAAA,IACpC,uBAAuB,YAAY;AAAA,IACnC,qBAAqB,YAAY;AAAA,IACjC,sBAAsB,YAAY;AAAA,EACpC,CAAC;AACH;","names":[]}
|