@claude-collective/cli 0.2.0 → 0.6.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 +113 -0
- package/README.md +1 -1
- package/dist/chunk-367K3JB3.js +84 -0
- package/dist/chunk-367K3JB3.js.map +1 -0
- package/dist/chunk-6ESUJMM7.js +54 -0
- package/dist/chunk-6ESUJMM7.js.map +1 -0
- package/dist/chunk-6OY6ZYQF.js +93 -0
- package/dist/chunk-6OY6ZYQF.js.map +1 -0
- package/dist/chunk-6WEQADPL.js +307 -0
- package/dist/chunk-6WEQADPL.js.map +1 -0
- package/dist/chunk-AU7XVCLO.js +91 -0
- package/dist/chunk-AU7XVCLO.js.map +1 -0
- package/dist/chunk-AZP2AA5M.js +425 -0
- package/dist/chunk-AZP2AA5M.js.map +1 -0
- package/dist/chunk-D4IQAT27.js +114 -0
- package/dist/chunk-D4IQAT27.js.map +1 -0
- package/dist/chunk-DHET7RCE.js +50 -0
- package/dist/chunk-DHET7RCE.js.map +1 -0
- package/dist/chunk-DHFFRMF6.js +31 -0
- package/dist/chunk-DHFFRMF6.js.map +1 -0
- package/dist/chunk-FKU7VSUD.js +453 -0
- package/dist/chunk-FKU7VSUD.js.map +1 -0
- package/dist/chunk-J2Y4A3LP.js +478 -0
- package/dist/chunk-J2Y4A3LP.js.map +1 -0
- package/dist/chunk-JMQGWQZU.js +607 -0
- package/dist/chunk-JMQGWQZU.js.map +1 -0
- package/dist/chunk-JY4RO76L.js +73 -0
- package/dist/chunk-JY4RO76L.js.map +1 -0
- package/dist/chunk-M7YCPFIX.js +108 -0
- package/dist/chunk-M7YCPFIX.js.map +1 -0
- package/dist/chunk-MJSFR562.js +57 -0
- package/dist/chunk-MJSFR562.js.map +1 -0
- package/dist/chunk-MMDXNZPF.js +69 -0
- package/dist/chunk-MMDXNZPF.js.map +1 -0
- package/dist/chunk-MYAVQ23U.js +356 -0
- package/dist/chunk-MYAVQ23U.js.map +1 -0
- package/dist/chunk-OSQDDJXX.js +146 -0
- package/dist/chunk-OSQDDJXX.js.map +1 -0
- package/dist/chunk-QESUUPOE.js +241 -0
- package/dist/chunk-QESUUPOE.js.map +1 -0
- package/dist/chunk-SJYG4EJZ.js +57 -0
- package/dist/chunk-SJYG4EJZ.js.map +1 -0
- package/dist/chunk-SYQ7R2JO.js +95 -0
- package/dist/chunk-SYQ7R2JO.js.map +1 -0
- package/dist/chunk-TD643KB3.js +245 -0
- package/dist/chunk-TD643KB3.js.map +1 -0
- package/dist/chunk-TFV6Z7F7.js +129 -0
- package/dist/chunk-TFV6Z7F7.js.map +1 -0
- package/dist/chunk-TGOHJCQ4.js +83 -0
- package/dist/chunk-TGOHJCQ4.js.map +1 -0
- package/dist/chunk-TOPAIL5W.js +22 -0
- package/dist/chunk-TOPAIL5W.js.map +1 -0
- package/dist/chunk-U4VYHKPM.js +110 -0
- package/dist/chunk-U4VYHKPM.js.map +1 -0
- package/dist/chunk-UFWNMW3G.js +392 -0
- package/dist/chunk-UFWNMW3G.js.map +1 -0
- package/dist/chunk-UNHCZRO4.js +64 -0
- package/dist/chunk-UNHCZRO4.js.map +1 -0
- package/dist/chunk-URDV4OCP.js +308 -0
- package/dist/chunk-URDV4OCP.js.map +1 -0
- package/dist/chunk-YI6JVSFO.js +43 -0
- package/dist/chunk-YI6JVSFO.js.map +1 -0
- package/dist/chunk-YNSNRR5D.js +184 -0
- package/dist/chunk-YNSNRR5D.js.map +1 -0
- package/dist/chunk-Z6DLWTBY.js +46 -0
- package/dist/chunk-Z6DLWTBY.js.map +1 -0
- package/dist/chunk-ZDQIUHAM.js +89 -0
- package/dist/chunk-ZDQIUHAM.js.map +1 -0
- package/dist/chunk-ZSKHDU5P.js +124 -0
- package/dist/chunk-ZSKHDU5P.js.map +1 -0
- package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
- package/dist/commands/build/marketplace.js +295 -0
- package/dist/commands/build/marketplace.js.map +1 -0
- package/dist/commands/build/plugins.js +362 -0
- package/dist/commands/build/plugins.js.map +1 -0
- package/dist/commands/build/stack.js +169 -0
- package/dist/commands/build/stack.js.map +1 -0
- package/dist/commands/compile.js +461 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/config/get.js +60 -0
- package/dist/commands/config/get.js.map +1 -0
- package/dist/commands/config/index.js +22 -0
- package/dist/commands/config/index.js.map +1 -0
- package/dist/commands/config/path.js +35 -0
- package/dist/commands/config/path.js.map +1 -0
- package/dist/commands/config/set-project.js +61 -0
- package/dist/commands/config/set-project.js.map +1 -0
- package/dist/commands/config/set.js +60 -0
- package/dist/commands/config/set.js.map +1 -0
- package/dist/commands/config/show.js +13 -0
- package/dist/commands/config/show.js.map +1 -0
- package/dist/commands/config/unset-project.js +57 -0
- package/dist/commands/config/unset-project.js.map +1 -0
- package/dist/commands/config/unset.js +56 -0
- package/dist/commands/config/unset.js.map +1 -0
- package/dist/commands/diff.js +755 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.js +413 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/edit.js +253 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/eject.js +208 -0
- package/dist/commands/eject.js.map +1 -0
- package/dist/commands/info.js +205 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.js +914 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.js +44 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/new/agent.js +230 -0
- package/dist/commands/new/agent.js.map +1 -0
- package/dist/commands/new/skill.js +204 -0
- package/dist/commands/new/skill.js.map +1 -0
- package/dist/commands/outdated.js +242 -0
- package/dist/commands/outdated.js.map +1 -0
- package/dist/commands/search.js +115 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/test-imports.js +92 -0
- package/dist/commands/test-imports.js.map +1 -0
- package/dist/commands/uninstall.js +302 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.js +428 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.js +375 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/version/bump.js +95 -0
- package/dist/commands/version/bump.js.map +1 -0
- package/dist/commands/version/index.js +70 -0
- package/dist/commands/version/index.js.map +1 -0
- package/dist/commands/version/set.js +101 -0
- package/dist/commands/version/set.js.map +1 -0
- package/dist/commands/version/show.js +70 -0
- package/dist/commands/version/show.js.map +1 -0
- package/dist/components/common/confirm.js +9 -0
- package/dist/components/common/confirm.js.map +1 -0
- package/dist/components/common/message.js +24 -0
- package/dist/components/common/message.js.map +1 -0
- package/dist/components/common/spinner.js +14 -0
- package/dist/components/common/spinner.js.map +1 -0
- package/dist/components/wizard/selection-header.js +11 -0
- package/dist/components/wizard/selection-header.js.map +1 -0
- package/dist/components/wizard/step-approach.js +11 -0
- package/dist/components/wizard/step-approach.js.map +1 -0
- package/dist/components/wizard/step-category.js +12 -0
- package/dist/components/wizard/step-category.js.map +1 -0
- package/dist/components/wizard/step-confirm.js +12 -0
- package/dist/components/wizard/step-confirm.js.map +1 -0
- package/dist/components/wizard/step-stack.js +11 -0
- package/dist/components/wizard/step-stack.js.map +1 -0
- package/dist/components/wizard/step-subcategory.js +13 -0
- package/dist/components/wizard/step-subcategory.js.map +1 -0
- package/dist/components/wizard/wizard.js +19 -0
- package/dist/components/wizard/wizard.js.map +1 -0
- package/dist/hooks/init.js +41 -0
- package/dist/hooks/init.js.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/magic-string.es-RGXYGAW3.js +1316 -0
- package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
- package/dist/stores/wizard-store.js +10 -0
- package/dist/stores/wizard-store.js.map +1 -0
- package/dist/stores/wizard-store.test.js +15991 -0
- package/dist/stores/wizard-store.test.js.map +1 -0
- package/package.json +44 -25
- package/dist/cli/index.js +0 -6314
- package/dist/cli/index.js.map +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
verbose
|
|
4
|
+
} from "./chunk-TOPAIL5W.js";
|
|
5
|
+
import {
|
|
6
|
+
ensureDir,
|
|
7
|
+
fileExists,
|
|
8
|
+
readFile,
|
|
9
|
+
writeFile
|
|
10
|
+
} from "./chunk-MMDXNZPF.js";
|
|
11
|
+
import {
|
|
12
|
+
init_esm_shims
|
|
13
|
+
} from "./chunk-DHET7RCE.js";
|
|
14
|
+
|
|
15
|
+
// src/cli-v2/lib/config.ts
|
|
16
|
+
init_esm_shims();
|
|
17
|
+
import path from "path";
|
|
18
|
+
import os from "os";
|
|
19
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
20
|
+
var PROJECT_CONFIG_DIR = ".claude-collective";
|
|
21
|
+
var DEFAULT_SOURCE = "github:claude-collective/skills";
|
|
22
|
+
var SOURCE_ENV_VAR = "CC_SOURCE";
|
|
23
|
+
var CONFIG_HOME_ENV_VAR = "CC_CONFIG_HOME";
|
|
24
|
+
var GLOBAL_CONFIG_FILE = "config.yaml";
|
|
25
|
+
var PROJECT_CONFIG_FILE = "config.yaml";
|
|
26
|
+
function getGlobalConfigDir() {
|
|
27
|
+
return process.env[CONFIG_HOME_ENV_VAR] || path.join(os.homedir(), ".claude-collective");
|
|
28
|
+
}
|
|
29
|
+
var GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".claude-collective");
|
|
30
|
+
function isValidGlobalConfig(obj) {
|
|
31
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
32
|
+
const config = obj;
|
|
33
|
+
if (config.source !== void 0 && typeof config.source !== "string")
|
|
34
|
+
return false;
|
|
35
|
+
if (config.author !== void 0 && typeof config.author !== "string")
|
|
36
|
+
return false;
|
|
37
|
+
if (config.marketplace !== void 0 && typeof config.marketplace !== "string")
|
|
38
|
+
return false;
|
|
39
|
+
if (config.agents_source !== void 0 && typeof config.agents_source !== "string")
|
|
40
|
+
return false;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
function isValidProjectConfig(obj) {
|
|
44
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
45
|
+
const config = obj;
|
|
46
|
+
if (config.source !== void 0 && typeof config.source !== "string")
|
|
47
|
+
return false;
|
|
48
|
+
if (config.marketplace !== void 0 && typeof config.marketplace !== "string")
|
|
49
|
+
return false;
|
|
50
|
+
if (config.agents_source !== void 0 && typeof config.agents_source !== "string")
|
|
51
|
+
return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function getGlobalConfigPath() {
|
|
55
|
+
return path.join(getGlobalConfigDir(), GLOBAL_CONFIG_FILE);
|
|
56
|
+
}
|
|
57
|
+
function getProjectConfigPath(projectDir) {
|
|
58
|
+
return path.join(projectDir, PROJECT_CONFIG_DIR, PROJECT_CONFIG_FILE);
|
|
59
|
+
}
|
|
60
|
+
async function loadGlobalConfig() {
|
|
61
|
+
const configPath = getGlobalConfigPath();
|
|
62
|
+
if (!await fileExists(configPath)) {
|
|
63
|
+
verbose(`Global config not found at ${configPath}`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const content = await readFile(configPath);
|
|
68
|
+
const parsed = parseYaml(content);
|
|
69
|
+
if (!isValidGlobalConfig(parsed)) {
|
|
70
|
+
verbose(`Invalid global config structure at ${configPath}`);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
verbose(`Loaded global config from ${configPath}`);
|
|
74
|
+
return parsed;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
verbose(`Failed to parse global config: ${error}`);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function loadProjectConfig(projectDir) {
|
|
81
|
+
const configPath = getProjectConfigPath(projectDir);
|
|
82
|
+
if (!await fileExists(configPath)) {
|
|
83
|
+
verbose(`Project config not found at ${configPath}`);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const content = await readFile(configPath);
|
|
88
|
+
const parsed = parseYaml(content);
|
|
89
|
+
if (!isValidProjectConfig(parsed)) {
|
|
90
|
+
verbose(`Invalid project config structure at ${configPath}`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
verbose(`Loaded project config from ${configPath}`);
|
|
94
|
+
return parsed;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
verbose(`Failed to parse project config: ${error}`);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function saveGlobalConfig(config) {
|
|
101
|
+
const configPath = getGlobalConfigPath();
|
|
102
|
+
await ensureDir(getGlobalConfigDir());
|
|
103
|
+
const content = stringifyYaml(config, { lineWidth: 0 });
|
|
104
|
+
await writeFile(configPath, content);
|
|
105
|
+
verbose(`Saved global config to ${configPath}`);
|
|
106
|
+
}
|
|
107
|
+
async function saveProjectConfig(projectDir, config) {
|
|
108
|
+
const configPath = getProjectConfigPath(projectDir);
|
|
109
|
+
await ensureDir(path.join(projectDir, PROJECT_CONFIG_DIR));
|
|
110
|
+
const content = stringifyYaml(config, { lineWidth: 0 });
|
|
111
|
+
await writeFile(configPath, content);
|
|
112
|
+
verbose(`Saved project config to ${configPath}`);
|
|
113
|
+
}
|
|
114
|
+
async function resolveSource(flagValue, projectDir) {
|
|
115
|
+
const projectConfig = projectDir ? await loadProjectConfig(projectDir) : null;
|
|
116
|
+
const globalConfig = await loadGlobalConfig();
|
|
117
|
+
const marketplace = projectConfig?.marketplace || globalConfig?.marketplace;
|
|
118
|
+
if (flagValue !== void 0) {
|
|
119
|
+
if (flagValue === "" || flagValue.trim() === "") {
|
|
120
|
+
throw new Error("--source flag cannot be empty");
|
|
121
|
+
}
|
|
122
|
+
verbose(`Source from --source flag: ${flagValue}`);
|
|
123
|
+
return { source: flagValue, sourceOrigin: "flag", marketplace };
|
|
124
|
+
}
|
|
125
|
+
const envValue = process.env[SOURCE_ENV_VAR];
|
|
126
|
+
if (envValue) {
|
|
127
|
+
verbose(`Source from ${SOURCE_ENV_VAR} env var: ${envValue}`);
|
|
128
|
+
return { source: envValue, sourceOrigin: "env", marketplace };
|
|
129
|
+
}
|
|
130
|
+
if (projectConfig?.source) {
|
|
131
|
+
verbose(`Source from project config: ${projectConfig.source}`);
|
|
132
|
+
return {
|
|
133
|
+
source: projectConfig.source,
|
|
134
|
+
sourceOrigin: "project",
|
|
135
|
+
marketplace
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (globalConfig?.source) {
|
|
139
|
+
verbose(`Source from global config: ${globalConfig.source}`);
|
|
140
|
+
return { source: globalConfig.source, sourceOrigin: "global", marketplace };
|
|
141
|
+
}
|
|
142
|
+
verbose(`Using default source: ${DEFAULT_SOURCE}`);
|
|
143
|
+
return { source: DEFAULT_SOURCE, sourceOrigin: "default", marketplace };
|
|
144
|
+
}
|
|
145
|
+
async function resolveAgentsSource(flagValue, projectDir) {
|
|
146
|
+
if (flagValue !== void 0) {
|
|
147
|
+
if (flagValue === "" || flagValue.trim() === "") {
|
|
148
|
+
throw new Error("--agent-source flag cannot be empty");
|
|
149
|
+
}
|
|
150
|
+
verbose(`Agents source from --agent-source flag: ${flagValue}`);
|
|
151
|
+
return { agentsSource: flagValue, agentsSourceOrigin: "flag" };
|
|
152
|
+
}
|
|
153
|
+
const projectConfig = projectDir ? await loadProjectConfig(projectDir) : null;
|
|
154
|
+
if (projectConfig?.agents_source) {
|
|
155
|
+
verbose(
|
|
156
|
+
`Agents source from project config: ${projectConfig.agents_source}`
|
|
157
|
+
);
|
|
158
|
+
return {
|
|
159
|
+
agentsSource: projectConfig.agents_source,
|
|
160
|
+
agentsSourceOrigin: "project"
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const globalConfig = await loadGlobalConfig();
|
|
164
|
+
if (globalConfig?.agents_source) {
|
|
165
|
+
verbose(`Agents source from global config: ${globalConfig.agents_source}`);
|
|
166
|
+
return {
|
|
167
|
+
agentsSource: globalConfig.agents_source,
|
|
168
|
+
agentsSourceOrigin: "global"
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
verbose("Using default agents source (local CLI)");
|
|
172
|
+
return { agentsSource: void 0, agentsSourceOrigin: "default" };
|
|
173
|
+
}
|
|
174
|
+
function formatAgentsSourceOrigin(origin) {
|
|
175
|
+
switch (origin) {
|
|
176
|
+
case "flag":
|
|
177
|
+
return "--agent-source flag";
|
|
178
|
+
case "project":
|
|
179
|
+
return "project config (.claude-collective/config.yaml)";
|
|
180
|
+
case "global":
|
|
181
|
+
return "global config (~/.claude-collective/config.yaml)";
|
|
182
|
+
case "default":
|
|
183
|
+
return "default (local CLI)";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function formatSourceOrigin(origin) {
|
|
187
|
+
switch (origin) {
|
|
188
|
+
case "flag":
|
|
189
|
+
return "--source flag";
|
|
190
|
+
case "env":
|
|
191
|
+
return `${SOURCE_ENV_VAR} environment variable`;
|
|
192
|
+
case "project":
|
|
193
|
+
return "project config (.claude-collective/config.yaml)";
|
|
194
|
+
case "global":
|
|
195
|
+
return "global config (~/.claude-collective/config.yaml)";
|
|
196
|
+
case "default":
|
|
197
|
+
return "default";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function isLocalSource(source) {
|
|
201
|
+
if (source.startsWith("/") || source.startsWith(".")) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
const remoteProtocols = [
|
|
205
|
+
"github:",
|
|
206
|
+
"gh:",
|
|
207
|
+
"gitlab:",
|
|
208
|
+
"bitbucket:",
|
|
209
|
+
"sourcehut:",
|
|
210
|
+
"https://",
|
|
211
|
+
"http://"
|
|
212
|
+
];
|
|
213
|
+
const hasRemoteProtocol = remoteProtocols.some(
|
|
214
|
+
(prefix) => source.startsWith(prefix)
|
|
215
|
+
);
|
|
216
|
+
if (!hasRemoteProtocol) {
|
|
217
|
+
if (source.includes("..") || source.includes("~")) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Invalid source path: ${source}. Path traversal patterns are not allowed.`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return !hasRemoteProtocol;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export {
|
|
227
|
+
DEFAULT_SOURCE,
|
|
228
|
+
SOURCE_ENV_VAR,
|
|
229
|
+
getGlobalConfigPath,
|
|
230
|
+
getProjectConfigPath,
|
|
231
|
+
loadGlobalConfig,
|
|
232
|
+
loadProjectConfig,
|
|
233
|
+
saveGlobalConfig,
|
|
234
|
+
saveProjectConfig,
|
|
235
|
+
resolveSource,
|
|
236
|
+
resolveAgentsSource,
|
|
237
|
+
formatAgentsSourceOrigin,
|
|
238
|
+
formatSourceOrigin,
|
|
239
|
+
isLocalSource
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=chunk-QESUUPOE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/config.ts"],"sourcesContent":["import path from \"path\";\nimport os from \"os\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { readFile, writeFile, fileExists, ensureDir } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\n\nconst PROJECT_CONFIG_DIR = \".claude-collective\";\n\nexport const DEFAULT_SOURCE = \"github:claude-collective/skills\";\nexport const SOURCE_ENV_VAR = \"CC_SOURCE\";\n/** Environment variable to override global config directory (used for testing) */\nexport const CONFIG_HOME_ENV_VAR = \"CC_CONFIG_HOME\";\nexport const GLOBAL_CONFIG_FILE = \"config.yaml\";\nexport const PROJECT_CONFIG_FILE = \"config.yaml\";\n\n/**\n * Get global config directory path.\n * Can be overridden via CC_CONFIG_HOME environment variable for testing isolation.\n * This is a function (not constant) to allow tests to set the env var after module load.\n */\nexport function getGlobalConfigDir(): string {\n return (\n process.env[CONFIG_HOME_ENV_VAR] ||\n path.join(os.homedir(), \".claude-collective\")\n );\n}\n\n/**\n * @deprecated Use getGlobalConfigDir() instead. This constant is kept for backwards compatibility\n * but won't respect CC_CONFIG_HOME set after module load.\n */\nexport const GLOBAL_CONFIG_DIR = path.join(os.homedir(), \".claude-collective\");\n\nexport interface GlobalConfig {\n source?: string;\n author?: string;\n marketplace?: string;\n agents_source?: string;\n}\n\nexport interface ProjectConfig {\n source?: string;\n marketplace?: string;\n agents_source?: string;\n}\n\nexport interface ResolvedConfig {\n source: string;\n sourceOrigin: \"flag\" | \"env\" | \"project\" | \"global\" | \"default\";\n marketplace?: string;\n}\n\nfunction isValidGlobalConfig(obj: unknown): obj is GlobalConfig {\n if (typeof obj !== \"object\" || obj === null) return false;\n const config = obj as Record<string, unknown>;\n if (config.source !== undefined && typeof config.source !== \"string\")\n return false;\n if (config.author !== undefined && typeof config.author !== \"string\")\n return false;\n if (\n config.marketplace !== undefined &&\n typeof config.marketplace !== \"string\"\n )\n return false;\n if (\n config.agents_source !== undefined &&\n typeof config.agents_source !== \"string\"\n )\n return false;\n return true;\n}\n\nfunction isValidProjectConfig(obj: unknown): obj is ProjectConfig {\n if (typeof obj !== \"object\" || obj === null) return false;\n const config = obj as Record<string, unknown>;\n if (config.source !== undefined && typeof config.source !== \"string\")\n return false;\n if (\n config.marketplace !== undefined &&\n typeof config.marketplace !== \"string\"\n )\n return false;\n if (\n config.agents_source !== undefined &&\n typeof config.agents_source !== \"string\"\n )\n return false;\n return true;\n}\n\nexport function getGlobalConfigPath(): string {\n return path.join(getGlobalConfigDir(), GLOBAL_CONFIG_FILE);\n}\n\nexport function getProjectConfigPath(projectDir: string): string {\n return path.join(projectDir, PROJECT_CONFIG_DIR, PROJECT_CONFIG_FILE);\n}\n\nexport async function loadGlobalConfig(): Promise<GlobalConfig | null> {\n const configPath = getGlobalConfigPath();\n\n if (!(await fileExists(configPath))) {\n verbose(`Global config not found at ${configPath}`);\n return null;\n }\n\n try {\n const content = await readFile(configPath);\n const parsed = parseYaml(content);\n if (!isValidGlobalConfig(parsed)) {\n verbose(`Invalid global config structure at ${configPath}`);\n return null;\n }\n verbose(`Loaded global config from ${configPath}`);\n return parsed;\n } catch (error) {\n verbose(`Failed to parse global config: ${error}`);\n return null;\n }\n}\n\nexport async function loadProjectConfig(\n projectDir: string,\n): Promise<ProjectConfig | null> {\n const configPath = getProjectConfigPath(projectDir);\n\n if (!(await fileExists(configPath))) {\n verbose(`Project config not found at ${configPath}`);\n return null;\n }\n\n try {\n const content = await readFile(configPath);\n const parsed = parseYaml(content);\n if (!isValidProjectConfig(parsed)) {\n verbose(`Invalid project config structure at ${configPath}`);\n return null;\n }\n verbose(`Loaded project config from ${configPath}`);\n return parsed;\n } catch (error) {\n verbose(`Failed to parse project config: ${error}`);\n return null;\n }\n}\n\nexport async function saveGlobalConfig(config: GlobalConfig): Promise<void> {\n const configPath = getGlobalConfigPath();\n await ensureDir(getGlobalConfigDir());\n const content = stringifyYaml(config, { lineWidth: 0 });\n await writeFile(configPath, content);\n verbose(`Saved global config to ${configPath}`);\n}\n\nexport async function saveProjectConfig(\n projectDir: string,\n config: ProjectConfig,\n): Promise<void> {\n const configPath = getProjectConfigPath(projectDir);\n await ensureDir(path.join(projectDir, PROJECT_CONFIG_DIR));\n const content = stringifyYaml(config, { lineWidth: 0 });\n await writeFile(configPath, content);\n verbose(`Saved project config to ${configPath}`);\n}\n\n/** Resolve source with precedence: flag > env > project > global > default */\nexport async function resolveSource(\n flagValue?: string,\n projectDir?: string,\n): Promise<ResolvedConfig> {\n // Load configs to get marketplace (marketplace is resolved separately from source)\n const projectConfig = projectDir ? await loadProjectConfig(projectDir) : null;\n const globalConfig = await loadGlobalConfig();\n\n // Resolve marketplace: project > global (no flag/env support for marketplace)\n const marketplace = projectConfig?.marketplace || globalConfig?.marketplace;\n\n if (flagValue !== undefined) {\n if (flagValue === \"\" || flagValue.trim() === \"\") {\n throw new Error(\"--source flag cannot be empty\");\n }\n verbose(`Source from --source flag: ${flagValue}`);\n return { source: flagValue, sourceOrigin: \"flag\", marketplace };\n }\n\n const envValue = process.env[SOURCE_ENV_VAR];\n if (envValue) {\n verbose(`Source from ${SOURCE_ENV_VAR} env var: ${envValue}`);\n return { source: envValue, sourceOrigin: \"env\", marketplace };\n }\n\n if (projectConfig?.source) {\n verbose(`Source from project config: ${projectConfig.source}`);\n return {\n source: projectConfig.source,\n sourceOrigin: \"project\",\n marketplace,\n };\n }\n\n if (globalConfig?.source) {\n verbose(`Source from global config: ${globalConfig.source}`);\n return { source: globalConfig.source, sourceOrigin: \"global\", marketplace };\n }\n\n verbose(`Using default source: ${DEFAULT_SOURCE}`);\n return { source: DEFAULT_SOURCE, sourceOrigin: \"default\", marketplace };\n}\n\nexport type AgentsSourceOrigin = \"flag\" | \"project\" | \"global\" | \"default\";\n\nexport interface ResolvedAgentsSource {\n agentsSource?: string;\n agentsSourceOrigin: AgentsSourceOrigin;\n}\n\n/** Resolve agents_source with precedence: flag > project > global > default (undefined) */\nexport async function resolveAgentsSource(\n flagValue?: string,\n projectDir?: string,\n): Promise<ResolvedAgentsSource> {\n if (flagValue !== undefined) {\n if (flagValue === \"\" || flagValue.trim() === \"\") {\n throw new Error(\"--agent-source flag cannot be empty\");\n }\n verbose(`Agents source from --agent-source flag: ${flagValue}`);\n return { agentsSource: flagValue, agentsSourceOrigin: \"flag\" };\n }\n\n const projectConfig = projectDir ? await loadProjectConfig(projectDir) : null;\n if (projectConfig?.agents_source) {\n verbose(\n `Agents source from project config: ${projectConfig.agents_source}`,\n );\n return {\n agentsSource: projectConfig.agents_source,\n agentsSourceOrigin: \"project\",\n };\n }\n\n const globalConfig = await loadGlobalConfig();\n if (globalConfig?.agents_source) {\n verbose(`Agents source from global config: ${globalConfig.agents_source}`);\n return {\n agentsSource: globalConfig.agents_source,\n agentsSourceOrigin: \"global\",\n };\n }\n\n verbose(\"Using default agents source (local CLI)\");\n return { agentsSource: undefined, agentsSourceOrigin: \"default\" };\n}\n\nexport function formatAgentsSourceOrigin(origin: AgentsSourceOrigin): string {\n switch (origin) {\n case \"flag\":\n return \"--agent-source flag\";\n case \"project\":\n return \"project config (.claude-collective/config.yaml)\";\n case \"global\":\n return \"global config (~/.claude-collective/config.yaml)\";\n case \"default\":\n return \"default (local CLI)\";\n }\n}\n\nexport function formatSourceOrigin(\n origin: ResolvedConfig[\"sourceOrigin\"],\n): string {\n switch (origin) {\n case \"flag\":\n return \"--source flag\";\n case \"env\":\n return `${SOURCE_ENV_VAR} environment variable`;\n case \"project\":\n return \"project config (.claude-collective/config.yaml)\";\n case \"global\":\n return \"global config (~/.claude-collective/config.yaml)\";\n case \"default\":\n return \"default\";\n }\n}\n\nexport function isLocalSource(source: string): boolean {\n if (source.startsWith(\"/\") || source.startsWith(\".\")) {\n return true;\n }\n\n const remoteProtocols = [\n \"github:\",\n \"gh:\",\n \"gitlab:\",\n \"bitbucket:\",\n \"sourcehut:\",\n \"https://\",\n \"http://\",\n ];\n\n const hasRemoteProtocol = remoteProtocols.some((prefix) =>\n source.startsWith(prefix),\n );\n\n if (!hasRemoteProtocol) {\n if (source.includes(\"..\") || source.includes(\"~\")) {\n throw new Error(\n `Invalid source path: ${source}. Path traversal patterns are not allowed.`,\n );\n }\n }\n\n return !hasRemoteProtocol;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/consts.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import path from "path";
|
|
9
|
+
import os from "os";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
var __dirname = path.dirname(__filename);
|
|
13
|
+
var isInDist = __dirname.includes("/dist");
|
|
14
|
+
var CLI_ROOT = isInDist ? path.resolve(__dirname, "..") : path.resolve(__dirname, "../..");
|
|
15
|
+
var PROJECT_ROOT = CLI_ROOT;
|
|
16
|
+
var CLAUDE_DIR = ".claude";
|
|
17
|
+
var PLUGINS_SUBDIR = "plugins";
|
|
18
|
+
var PLUGIN_MANIFEST_DIR = ".claude-plugin";
|
|
19
|
+
var PLUGIN_MANIFEST_FILE = "plugin.json";
|
|
20
|
+
var CACHE_DIR = path.join(os.homedir(), ".cache", "claude-collective");
|
|
21
|
+
var SKILLS_MATRIX_PATH = "config/skills-matrix.yaml";
|
|
22
|
+
var SKILLS_DIR_PATH = "src/skills";
|
|
23
|
+
var LOCAL_SKILLS_PATH = ".claude/skills";
|
|
24
|
+
var DIRS = {
|
|
25
|
+
agents: "src/agents",
|
|
26
|
+
skills: "src/skills",
|
|
27
|
+
stacks: "src/stacks",
|
|
28
|
+
templates: "src/agents/_templates",
|
|
29
|
+
commands: "src/commands"
|
|
30
|
+
};
|
|
31
|
+
var DEFAULT_VERSION = "1.0.0";
|
|
32
|
+
var DEFAULT_DISPLAY_VERSION = "0.0.0";
|
|
33
|
+
var DEFAULT_PRESELECTED_SKILLS = [
|
|
34
|
+
"meta/methodology/anti-over-engineering (@vince)",
|
|
35
|
+
"meta/methodology/context-management (@vince)",
|
|
36
|
+
"meta/methodology/improvement-protocol (@vince)",
|
|
37
|
+
"meta/methodology/investigation-requirements (@vince)",
|
|
38
|
+
"meta/methodology/success-criteria (@vince)",
|
|
39
|
+
"meta/methodology/write-verification (@vince)"
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
PROJECT_ROOT,
|
|
44
|
+
CLAUDE_DIR,
|
|
45
|
+
PLUGINS_SUBDIR,
|
|
46
|
+
PLUGIN_MANIFEST_DIR,
|
|
47
|
+
PLUGIN_MANIFEST_FILE,
|
|
48
|
+
CACHE_DIR,
|
|
49
|
+
SKILLS_MATRIX_PATH,
|
|
50
|
+
SKILLS_DIR_PATH,
|
|
51
|
+
LOCAL_SKILLS_PATH,
|
|
52
|
+
DIRS,
|
|
53
|
+
DEFAULT_VERSION,
|
|
54
|
+
DEFAULT_DISPLAY_VERSION,
|
|
55
|
+
DEFAULT_PRESELECTED_SKILLS
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=chunk-SJYG4EJZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/consts.ts"],"sourcesContent":["import path from \"path\";\nimport os from \"os\";\nimport { fileURLToPath } from \"url\";\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-v2/consts.ts), we go up two levels\nconst isInDist = __dirname.includes(\"/dist\");\nexport const CLI_ROOT = isInDist\n ? path.resolve(__dirname, \"..\")\n : path.resolve(__dirname, \"../..\");\nexport const PROJECT_ROOT = CLI_ROOT;\n\nexport const OUTPUT_DIR = \".claude\";\nexport const GITHUB_REPO = \"claude-collective/skills\";\nexport const DEFAULT_MATRIX_PATH = \"src/config/skills-matrix.yaml\";\n\nexport const PLUGIN_NAME = \"claude-collective\";\n\nexport const CLAUDE_DIR = \".claude\";\nexport const PLUGINS_SUBDIR = \"plugins\";\nexport const PLUGIN_MANIFEST_DIR = \".claude-plugin\";\nexport const PLUGIN_MANIFEST_FILE = \"plugin.json\";\n\nexport const CACHE_DIR = path.join(os.homedir(), \".cache\", \"claude-collective\");\n\nexport const SKILLS_MATRIX_PATH = \"config/skills-matrix.yaml\";\nexport const SKILLS_DIR_PATH = \"src/skills\";\nexport const LOCAL_SKILLS_PATH = \".claude/skills\";\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 DEFAULT_VERSION = \"1.0.0\";\n\n/** Uses \"0.0.0\" to clearly indicate \"no version was explicitly set\" */\nexport const DEFAULT_DISPLAY_VERSION = \"0.0.0\";\n\n/**\n * Skills that are preselected by default in the wizard.\n * These are foundational methodology skills that apply to all projects.\n */\nexport const DEFAULT_PRESELECTED_SKILLS = [\n \"meta/methodology/anti-over-engineering (@vince)\",\n \"meta/methodology/context-management (@vince)\",\n \"meta/methodology/improvement-protocol (@vince)\",\n \"meta/methodology/investigation-requirements (@vince)\",\n \"meta/methodology/success-criteria (@vince)\",\n \"meta/methodology/write-verification (@vince)\",\n] as const;\n"],"mappings":";;;;;;AAAA;AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,qBAAqB;AAE9B,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,KAAK,QAAQ,UAAU;AAIzC,IAAM,WAAW,UAAU,SAAS,OAAO;AACpC,IAAM,WAAW,WACpB,KAAK,QAAQ,WAAW,IAAI,IAC5B,KAAK,QAAQ,WAAW,OAAO;AAC5B,IAAM,eAAe;AAQrB,IAAM,aAAa;AACnB,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAE7B,IAAM,YAAY,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU,mBAAmB;AAEvE,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAE1B,IAAM,OAAO;AAAA,EAClB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AACZ;AAEO,IAAM,kBAAkB;AAGxB,IAAM,0BAA0B;AAMhC,IAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/lib/exit-codes.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
var EXIT_CODES = {
|
|
9
|
+
/** Operation completed successfully */
|
|
10
|
+
SUCCESS: 0,
|
|
11
|
+
/** General error - operation failed */
|
|
12
|
+
ERROR: 1,
|
|
13
|
+
/** Invalid command-line arguments or options */
|
|
14
|
+
INVALID_ARGS: 2,
|
|
15
|
+
/** Network request failed (connection, timeout, etc.) */
|
|
16
|
+
NETWORK_ERROR: 3,
|
|
17
|
+
/** User cancelled the operation (Ctrl+C or prompt cancel) */
|
|
18
|
+
CANCELLED: 4
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/cli-v2/base-command.ts
|
|
22
|
+
init_esm_shims();
|
|
23
|
+
import { Command, Flags } from "@oclif/core";
|
|
24
|
+
var BaseCommand = class extends Command {
|
|
25
|
+
/**
|
|
26
|
+
* Base flags available to all commands.
|
|
27
|
+
* Commands should merge these with their own flags using spread syntax.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* static flags = {
|
|
31
|
+
* ...BaseCommand.baseFlags,
|
|
32
|
+
* myFlag: Flags.string({ description: "My custom flag" }),
|
|
33
|
+
* };
|
|
34
|
+
*/
|
|
35
|
+
static baseFlags = {
|
|
36
|
+
"dry-run": Flags.boolean({
|
|
37
|
+
description: "Preview operations without executing",
|
|
38
|
+
default: false
|
|
39
|
+
}),
|
|
40
|
+
source: Flags.string({
|
|
41
|
+
char: "s",
|
|
42
|
+
description: "Skills source path or URL",
|
|
43
|
+
required: false
|
|
44
|
+
})
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Loaded configuration - set by init hook and stored in config object.
|
|
48
|
+
* Available after command initialization.
|
|
49
|
+
*/
|
|
50
|
+
get sourceConfig() {
|
|
51
|
+
return this.config.sourceConfig;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Handle errors with proper exit codes.
|
|
55
|
+
* Logs the error message and exits the process.
|
|
56
|
+
*
|
|
57
|
+
* @param error - The error to handle
|
|
58
|
+
* @returns Never returns (exits process)
|
|
59
|
+
*/
|
|
60
|
+
handleError(error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
this.error(message, { exit: EXIT_CODES.ERROR });
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Log a success message with a green checkmark.
|
|
66
|
+
*
|
|
67
|
+
* @param message - The success message to display
|
|
68
|
+
*/
|
|
69
|
+
logSuccess(message) {
|
|
70
|
+
this.log(`\u2713 ${message}`);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Log a warning message.
|
|
74
|
+
* Uses oclif's warn method which outputs to stderr.
|
|
75
|
+
*
|
|
76
|
+
* @param message - The warning message to display
|
|
77
|
+
*/
|
|
78
|
+
logWarning(message) {
|
|
79
|
+
this.warn(message);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Log an informational message.
|
|
83
|
+
*
|
|
84
|
+
* @param message - The info message to display
|
|
85
|
+
*/
|
|
86
|
+
logInfo(message) {
|
|
87
|
+
this.log(message);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
EXIT_CODES,
|
|
93
|
+
BaseCommand
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=chunk-SYQ7R2JO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/exit-codes.ts","../src/cli-v2/base-command.ts"],"sourcesContent":["/**\n * CLI exit codes for standardized process termination.\n *\n * These follow Unix conventions where 0 = success, non-zero = error.\n * Use named constants instead of magic numbers for clarity and consistency.\n */\nexport const EXIT_CODES = {\n /** Operation completed successfully */\n SUCCESS: 0,\n /** General error - operation failed */\n ERROR: 1,\n /** Invalid command-line arguments or options */\n INVALID_ARGS: 2,\n /** Network request failed (connection, timeout, etc.) */\n NETWORK_ERROR: 3,\n /** User cancelled the operation (Ctrl+C or prompt cancel) */\n CANCELLED: 4,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n","/**\n * Base command class for all oclif commands in CLI v2.\n *\n * Provides:\n * - Shared flags (--dry-run, --source)\n * - Error handling with proper exit codes\n * - Common logging utilities\n * - Config access (set by init hook)\n */\nimport { Command, Flags } from \"@oclif/core\";\nimport { EXIT_CODES } from \"./lib/exit-codes.js\";\nimport type { ResolvedConfig } from \"./lib/config.js\";\n\nexport abstract class BaseCommand extends Command {\n /**\n * Base flags available to all commands.\n * Commands should merge these with their own flags using spread syntax.\n *\n * @example\n * static flags = {\n * ...BaseCommand.baseFlags,\n * myFlag: Flags.string({ description: \"My custom flag\" }),\n * };\n */\n static baseFlags = {\n \"dry-run\": Flags.boolean({\n description: \"Preview operations without executing\",\n default: false,\n }),\n source: Flags.string({\n char: \"s\",\n description: \"Skills source path or URL\",\n required: false,\n }),\n };\n\n /**\n * Loaded configuration - set by init hook and stored in config object.\n * Available after command initialization.\n */\n public get sourceConfig(): ResolvedConfig | undefined {\n return (this.config as any).sourceConfig;\n }\n\n /**\n * Handle errors with proper exit codes.\n * Logs the error message and exits the process.\n *\n * @param error - The error to handle\n * @returns Never returns (exits process)\n */\n protected handleError(error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n this.error(message, { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * Log a success message with a green checkmark.\n *\n * @param message - The success message to display\n */\n protected logSuccess(message: string): void {\n this.log(`✓ ${message}`);\n }\n\n /**\n * Log a warning message.\n * Uses oclif's warn method which outputs to stderr.\n *\n * @param message - The warning message to display\n */\n protected logWarning(message: string): void {\n this.warn(message);\n }\n\n /**\n * Log an informational message.\n *\n * @param message - The info message to display\n */\n protected logInfo(message: string): void {\n this.log(message);\n }\n}\n"],"mappings":";;;;;;AAAA;AAMO,IAAM,aAAa;AAAA;AAAA,EAExB,SAAS;AAAA;AAAA,EAET,OAAO;AAAA;AAAA,EAEP,cAAc;AAAA;AAAA,EAEd,eAAe;AAAA;AAAA,EAEf,WAAW;AACb;;;ACjBA;AASA,SAAS,SAAS,aAAa;AAIxB,IAAe,cAAf,cAAmC,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWhD,OAAO,YAAY;AAAA,IACjB,WAAW,MAAM,QAAQ;AAAA,MACvB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,eAA2C;AACpD,WAAQ,KAAK,OAAe;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,YAAY,OAAuB;AAC3C,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,WAAW,SAAuB;AAC1C,SAAK,IAAI,UAAK,OAAO,EAAE;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,WAAW,SAAuB;AAC1C,SAAK,KAAK,OAAO;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,QAAQ,SAAuB;AACvC,SAAK,IAAI,OAAO;AAAA,EAClB;AACF;","names":[]}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getAvailableSkills,
|
|
4
|
+
getDependentSkills,
|
|
5
|
+
getSubcategories,
|
|
6
|
+
isCategoryAllDisabled,
|
|
7
|
+
resolveAlias
|
|
8
|
+
} from "./chunk-AZP2AA5M.js";
|
|
9
|
+
import {
|
|
10
|
+
useWizardStore
|
|
11
|
+
} from "./chunk-6OY6ZYQF.js";
|
|
12
|
+
import {
|
|
13
|
+
Confirm
|
|
14
|
+
} from "./chunk-DHFFRMF6.js";
|
|
15
|
+
import {
|
|
16
|
+
init_esm_shims
|
|
17
|
+
} from "./chunk-DHET7RCE.js";
|
|
18
|
+
|
|
19
|
+
// src/cli-v2/components/wizard/step-subcategory.tsx
|
|
20
|
+
init_esm_shims();
|
|
21
|
+
import { useState } from "react";
|
|
22
|
+
import { Box, Text } from "ink";
|
|
23
|
+
import { Select } from "@inkjs/ui";
|
|
24
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
25
|
+
var BACK_VALUE = "__back__";
|
|
26
|
+
function collectAllDependents(skillId, currentSelections, matrix) {
|
|
27
|
+
const allDependents = [];
|
|
28
|
+
const visited = /* @__PURE__ */ new Set();
|
|
29
|
+
const queue = [skillId];
|
|
30
|
+
while (queue.length > 0) {
|
|
31
|
+
const current = queue.shift();
|
|
32
|
+
if (visited.has(current)) continue;
|
|
33
|
+
visited.add(current);
|
|
34
|
+
const directDependents = getDependentSkills(
|
|
35
|
+
current,
|
|
36
|
+
currentSelections,
|
|
37
|
+
matrix
|
|
38
|
+
);
|
|
39
|
+
for (const dependent of directDependents) {
|
|
40
|
+
if (!visited.has(dependent) && !allDependents.includes(dependent)) {
|
|
41
|
+
allDependents.push(dependent);
|
|
42
|
+
queue.push(dependent);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return allDependents;
|
|
47
|
+
}
|
|
48
|
+
function formatSkillOption(skill) {
|
|
49
|
+
let label = skill.name;
|
|
50
|
+
if (skill.selected) {
|
|
51
|
+
label = `\u2713 ${skill.name}`;
|
|
52
|
+
} else if (skill.disabled) {
|
|
53
|
+
const shortReason = skill.disabledReason?.split(" (")[0]?.toLowerCase() || "requirements not met";
|
|
54
|
+
label = `${skill.name} (disabled, ${shortReason})`;
|
|
55
|
+
} else if (skill.discouraged) {
|
|
56
|
+
label = `${skill.name} (not recommended)`;
|
|
57
|
+
} else if (skill.recommended) {
|
|
58
|
+
label = `${skill.name} (recommended)`;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
value: skill.id,
|
|
62
|
+
label
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var StepSubcategory = ({ matrix }) => {
|
|
66
|
+
const {
|
|
67
|
+
currentTopCategory,
|
|
68
|
+
currentSubcategory,
|
|
69
|
+
selectedSkills,
|
|
70
|
+
expertMode,
|
|
71
|
+
setStep,
|
|
72
|
+
setSubcategory,
|
|
73
|
+
toggleSkill,
|
|
74
|
+
goBack,
|
|
75
|
+
setLastSelectedSubcategory,
|
|
76
|
+
setLastSelectedSkill,
|
|
77
|
+
markCategoryVisited
|
|
78
|
+
} = useWizardStore();
|
|
79
|
+
const [viewMode, setViewMode] = useState(
|
|
80
|
+
currentSubcategory ? "skill" : "subcategory"
|
|
81
|
+
);
|
|
82
|
+
const [confirmDeselect, setConfirmDeselect] = useState(null);
|
|
83
|
+
if (!currentTopCategory) {
|
|
84
|
+
goBack();
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const topCategory = matrix.categories[currentTopCategory];
|
|
88
|
+
const subcategoryIds = getSubcategories(currentTopCategory, matrix);
|
|
89
|
+
const checkOptions = { expertMode };
|
|
90
|
+
if (viewMode === "subcategory") {
|
|
91
|
+
const subcategoryOptions = subcategoryIds.map((subId) => {
|
|
92
|
+
const sub = matrix.categories[subId];
|
|
93
|
+
const skills2 = getAvailableSkills(
|
|
94
|
+
subId,
|
|
95
|
+
selectedSkills,
|
|
96
|
+
matrix,
|
|
97
|
+
checkOptions
|
|
98
|
+
);
|
|
99
|
+
const selectedInCategory = skills2.filter((s) => s.selected);
|
|
100
|
+
const hasSelection = selectedInCategory.length > 0;
|
|
101
|
+
const categoryDisabled = isCategoryAllDisabled(
|
|
102
|
+
subId,
|
|
103
|
+
selectedSkills,
|
|
104
|
+
matrix,
|
|
105
|
+
checkOptions
|
|
106
|
+
);
|
|
107
|
+
let label;
|
|
108
|
+
if (hasSelection) {
|
|
109
|
+
label = `${sub.name} (${selectedInCategory[0].name} selected)`;
|
|
110
|
+
} else if (categoryDisabled.disabled) {
|
|
111
|
+
const shortReason = categoryDisabled.reason?.toLowerCase() || "requirements not met";
|
|
112
|
+
label = `${sub.name} (disabled, ${shortReason})`;
|
|
113
|
+
} else if (sub.required) {
|
|
114
|
+
label = `${sub.name} (required)`;
|
|
115
|
+
} else {
|
|
116
|
+
label = sub.name;
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
value: subId,
|
|
120
|
+
label
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
const options2 = [
|
|
124
|
+
{ value: BACK_VALUE, label: "\u2190 Back" },
|
|
125
|
+
...subcategoryOptions
|
|
126
|
+
];
|
|
127
|
+
const handleSubcategorySelect = (value) => {
|
|
128
|
+
if (value === BACK_VALUE) {
|
|
129
|
+
if (currentTopCategory) {
|
|
130
|
+
markCategoryVisited(currentTopCategory);
|
|
131
|
+
}
|
|
132
|
+
setSubcategory(null);
|
|
133
|
+
setLastSelectedSubcategory(null);
|
|
134
|
+
goBack();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
setLastSelectedSubcategory(value);
|
|
138
|
+
setSubcategory(value);
|
|
139
|
+
setViewMode("skill");
|
|
140
|
+
};
|
|
141
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
142
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
143
|
+
topCategory.name,
|
|
144
|
+
" - Select a subcategory:"
|
|
145
|
+
] }),
|
|
146
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Select, { options: options2, onChange: handleSubcategorySelect }) })
|
|
147
|
+
] });
|
|
148
|
+
}
|
|
149
|
+
if (!currentSubcategory) {
|
|
150
|
+
setViewMode("subcategory");
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const subcategory = matrix.categories[currentSubcategory];
|
|
154
|
+
const skills = getAvailableSkills(
|
|
155
|
+
currentSubcategory,
|
|
156
|
+
selectedSkills,
|
|
157
|
+
matrix,
|
|
158
|
+
checkOptions
|
|
159
|
+
);
|
|
160
|
+
const skillOptions = skills.map(formatSkillOption);
|
|
161
|
+
const options = [{ value: BACK_VALUE, label: "\u2190 Back" }, ...skillOptions];
|
|
162
|
+
const handleSkillSelect = (value) => {
|
|
163
|
+
if (value === BACK_VALUE) {
|
|
164
|
+
setSubcategory(null);
|
|
165
|
+
setLastSelectedSkill(null);
|
|
166
|
+
setViewMode("subcategory");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const selectedSkillId = value;
|
|
170
|
+
setLastSelectedSkill(selectedSkillId);
|
|
171
|
+
const selectedOption = skills.find((s) => s.id === selectedSkillId);
|
|
172
|
+
if (selectedOption?.disabled) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const alreadySelected = selectedSkills.includes(selectedSkillId);
|
|
176
|
+
if (alreadySelected) {
|
|
177
|
+
const allDependents = collectAllDependents(
|
|
178
|
+
selectedSkillId,
|
|
179
|
+
selectedSkills,
|
|
180
|
+
matrix
|
|
181
|
+
);
|
|
182
|
+
if (allDependents.length > 0) {
|
|
183
|
+
const skillName = matrix.skills[resolveAlias(selectedSkillId, matrix)]?.name || selectedSkillId;
|
|
184
|
+
setConfirmDeselect({
|
|
185
|
+
skillId: selectedSkillId,
|
|
186
|
+
skillName,
|
|
187
|
+
dependents: allDependents
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
toggleSkill(selectedSkillId);
|
|
192
|
+
} else {
|
|
193
|
+
if (subcategory?.exclusive) {
|
|
194
|
+
const skillsToRemove = selectedSkills.filter((id) => {
|
|
195
|
+
const skill = matrix.skills[id];
|
|
196
|
+
return skill?.category === currentSubcategory;
|
|
197
|
+
});
|
|
198
|
+
skillsToRemove.forEach((id) => {
|
|
199
|
+
if (selectedSkills.includes(id)) {
|
|
200
|
+
toggleSkill(id);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
toggleSkill(selectedSkillId);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
if (confirmDeselect) {
|
|
208
|
+
const dependentNames = confirmDeselect.dependents.map((id) => matrix.skills[id]?.name || id).join(", ");
|
|
209
|
+
const message = `Deselecting ${confirmDeselect.skillName} will also remove: ${dependentNames}. Continue?`;
|
|
210
|
+
return /* @__PURE__ */ jsx(
|
|
211
|
+
Confirm,
|
|
212
|
+
{
|
|
213
|
+
message,
|
|
214
|
+
defaultValue: false,
|
|
215
|
+
onConfirm: () => {
|
|
216
|
+
const toRemove = /* @__PURE__ */ new Set([
|
|
217
|
+
confirmDeselect.skillId,
|
|
218
|
+
...confirmDeselect.dependents
|
|
219
|
+
]);
|
|
220
|
+
toRemove.forEach((id) => {
|
|
221
|
+
if (selectedSkills.includes(id)) {
|
|
222
|
+
toggleSkill(id);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
setConfirmDeselect(null);
|
|
226
|
+
},
|
|
227
|
+
onCancel: () => {
|
|
228
|
+
setConfirmDeselect(null);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
234
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
235
|
+
subcategory.name,
|
|
236
|
+
":"
|
|
237
|
+
] }),
|
|
238
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Select, { options, onChange: handleSkillSelect }) })
|
|
239
|
+
] });
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
export {
|
|
243
|
+
StepSubcategory
|
|
244
|
+
};
|
|
245
|
+
//# sourceMappingURL=chunk-TD643KB3.js.map
|