@claude-collective/cli 0.2.0 → 0.8.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 +178 -0
- package/README.md +1 -1
- package/dist/chunk-3HBTELJN.js +114 -0
- package/dist/chunk-3HBTELJN.js.map +1 -0
- package/dist/chunk-3ZCB5K33.js +54 -0
- package/dist/chunk-3ZCB5K33.js.map +1 -0
- package/dist/chunk-66UDJBF6.js +96 -0
- package/dist/chunk-66UDJBF6.js.map +1 -0
- package/dist/chunk-6LS7XO3H.js +31 -0
- package/dist/chunk-6LS7XO3H.js.map +1 -0
- package/dist/chunk-A3J6IAXK.js +57 -0
- package/dist/chunk-A3J6IAXK.js.map +1 -0
- package/dist/chunk-A65SBAAJ.js +69 -0
- package/dist/chunk-A65SBAAJ.js.map +1 -0
- package/dist/chunk-ALEPJ6YN.js +80 -0
- package/dist/chunk-ALEPJ6YN.js.map +1 -0
- package/dist/chunk-C4ZTIYFR.js +84 -0
- package/dist/chunk-C4ZTIYFR.js.map +1 -0
- package/dist/chunk-CIY5UBRB.js +453 -0
- package/dist/chunk-CIY5UBRB.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-DKGL77IY.js +307 -0
- package/dist/chunk-DKGL77IY.js.map +1 -0
- package/dist/chunk-ED73HCW2.js +315 -0
- package/dist/chunk-ED73HCW2.js.map +1 -0
- package/dist/chunk-FNOYEXUE.js +308 -0
- package/dist/chunk-FNOYEXUE.js.map +1 -0
- package/dist/chunk-G2FBJOZG.js +141 -0
- package/dist/chunk-G2FBJOZG.js.map +1 -0
- package/dist/chunk-HNDT5QRB.js +120 -0
- package/dist/chunk-HNDT5QRB.js.map +1 -0
- package/dist/chunk-K7PTOVX4.js +158 -0
- package/dist/chunk-K7PTOVX4.js.map +1 -0
- package/dist/chunk-LQTST4WY.js +91 -0
- package/dist/chunk-LQTST4WY.js.map +1 -0
- package/dist/chunk-LVKRVFYR.js +54 -0
- package/dist/chunk-LVKRVFYR.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-NGBFJJ7Q.js +124 -0
- package/dist/chunk-NGBFJJ7Q.js.map +1 -0
- package/dist/chunk-OLBOTK3O.js +64 -0
- package/dist/chunk-OLBOTK3O.js.map +1 -0
- package/dist/chunk-PPNTD5LO.js +330 -0
- package/dist/chunk-PPNTD5LO.js.map +1 -0
- package/dist/chunk-Q2LH2DAB.js +392 -0
- package/dist/chunk-Q2LH2DAB.js.map +1 -0
- package/dist/chunk-Q6DR5QUH.js +547 -0
- package/dist/chunk-Q6DR5QUH.js.map +1 -0
- package/dist/chunk-QESUUPOE.js +241 -0
- package/dist/chunk-QESUUPOE.js.map +1 -0
- package/dist/chunk-QGGSLMO3.js +607 -0
- package/dist/chunk-QGGSLMO3.js.map +1 -0
- package/dist/chunk-SEBPPFUW.js +478 -0
- package/dist/chunk-SEBPPFUW.js.map +1 -0
- package/dist/chunk-SYQ7R2JO.js +95 -0
- package/dist/chunk-SYQ7R2JO.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-UOWHJ6BE.js +83 -0
- package/dist/chunk-UOWHJ6BE.js.map +1 -0
- package/dist/chunk-XKEG3SCV.js +86 -0
- package/dist/chunk-XKEG3SCV.js.map +1 -0
- package/dist/chunk-XY3XDVMI.js +15599 -0
- package/dist/chunk-XY3XDVMI.js.map +1 -0
- package/dist/chunk-Y3V43XCU.js +76 -0
- package/dist/chunk-Y3V43XCU.js.map +1 -0
- package/dist/chunk-YKXBGCFD.js +129 -0
- package/dist/chunk-YKXBGCFD.js.map +1 -0
- package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
- package/dist/commands/build/marketplace.js +254 -0
- package/dist/commands/build/marketplace.js.map +1 -0
- package/dist/commands/build/plugins.js +324 -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 +254 -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 +915 -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 +309 -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/category-grid.js +9 -0
- package/dist/components/wizard/category-grid.js.map +1 -0
- package/dist/components/wizard/category-grid.test.js +728 -0
- package/dist/components/wizard/category-grid.test.js.map +1 -0
- package/dist/components/wizard/section-progress.js +9 -0
- package/dist/components/wizard/section-progress.js.map +1 -0
- package/dist/components/wizard/section-progress.test.js +281 -0
- package/dist/components/wizard/section-progress.test.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-build.js +15 -0
- package/dist/components/wizard/step-build.js.map +1 -0
- package/dist/components/wizard/step-build.test.js +729 -0
- package/dist/components/wizard/step-build.test.js.map +1 -0
- package/dist/components/wizard/step-confirm.js +9 -0
- package/dist/components/wizard/step-confirm.js.map +1 -0
- package/dist/components/wizard/step-refine.js +9 -0
- package/dist/components/wizard/step-refine.js.map +1 -0
- package/dist/components/wizard/step-refine.test.js +235 -0
- package/dist/components/wizard/step-refine.test.js.map +1 -0
- package/dist/components/wizard/step-stack-options.js +11 -0
- package/dist/components/wizard/step-stack-options.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/wizard-tabs.js +11 -0
- package/dist/components/wizard/wizard-tabs.js.map +1 -0
- package/dist/components/wizard/wizard.js +20 -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 +405 -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,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/components/wizard/section-progress.tsx
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import { Box, Text } from "ink";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var SectionProgress = ({
|
|
11
|
+
label,
|
|
12
|
+
current,
|
|
13
|
+
index,
|
|
14
|
+
total,
|
|
15
|
+
next
|
|
16
|
+
}) => {
|
|
17
|
+
const isLast = index === total;
|
|
18
|
+
const rightText = isLast ? "Last step" : `Next: ${next}`;
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
Box,
|
|
21
|
+
{
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
justifyContent: "space-between",
|
|
24
|
+
paddingX: 2,
|
|
25
|
+
marginBottom: 1,
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
28
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
29
|
+
label,
|
|
30
|
+
":"
|
|
31
|
+
] }),
|
|
32
|
+
" ",
|
|
33
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: current })
|
|
34
|
+
] }),
|
|
35
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
36
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
37
|
+
"[",
|
|
38
|
+
index,
|
|
39
|
+
"/",
|
|
40
|
+
total,
|
|
41
|
+
"]"
|
|
42
|
+
] }),
|
|
43
|
+
" ",
|
|
44
|
+
/* @__PURE__ */ jsx(Text, { dimColor: isLast, children: rightText })
|
|
45
|
+
] })
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
SectionProgress
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=chunk-LVKRVFYR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/components/wizard/section-progress.tsx"],"sourcesContent":["import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface SectionProgressProps {\n /** Section label (e.g., \"Domain\" or \"Skill\") */\n label: string;\n /** Current item name (e.g., \"Web\" or \"react\") */\n current: string;\n /** 1-based index */\n index: number;\n /** Total count */\n total: number;\n /** Next item name, or undefined if last */\n next?: string;\n}\n\nexport const SectionProgress: React.FC<SectionProgressProps> = ({\n label,\n current,\n index,\n total,\n next,\n}) => {\n const isLast = index === total;\n const rightText = isLast ? \"Last step\" : `Next: ${next}`;\n\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n paddingX={2}\n marginBottom={1}\n >\n <Text>\n <Text bold>{label}:</Text> <Text color=\"cyan\">{current}</Text>\n </Text>\n <Text>\n <Text dimColor>\n [{index}/{total}]\n </Text>{\" \"}\n <Text dimColor={isLast}>{rightText}</Text>\n </Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AACA,SAAS,KAAK,YAAY;AAiClB,SAA2B,KAA3B;AAlBD,IAAM,kBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,SAAS,cAAc,SAAS,IAAI;AAEtD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,UAAU;AAAA,MACV,cAAc;AAAA,MAEd;AAAA,6BAAC,QACC;AAAA,+BAAC,QAAK,MAAI,MAAE;AAAA;AAAA,YAAM;AAAA,aAAC;AAAA,UAAO;AAAA,UAAC,oBAAC,QAAK,OAAM,QAAQ,mBAAQ;AAAA,WACzD;AAAA,QACA,qBAAC,QACC;AAAA,+BAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,YACX;AAAA,YAAM;AAAA,YAAE;AAAA,YAAM;AAAA,aAClB;AAAA,UAAQ;AAAA,UACR,oBAAC,QAAK,UAAU,QAAS,qBAAU;AAAA,WACrC;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/utils/exec.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import { spawn } from "child_process";
|
|
9
|
+
async function execCommand(command, args, options) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const proc = spawn(command, args, {
|
|
12
|
+
cwd: options?.cwd,
|
|
13
|
+
env: { ...process.env, ...options?.env },
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
15
|
+
});
|
|
16
|
+
let stdout = "";
|
|
17
|
+
let stderr = "";
|
|
18
|
+
proc.stdout.on("data", (data) => {
|
|
19
|
+
stdout += data.toString();
|
|
20
|
+
});
|
|
21
|
+
proc.stderr.on("data", (data) => {
|
|
22
|
+
stderr += data.toString();
|
|
23
|
+
});
|
|
24
|
+
proc.on("close", (code) => {
|
|
25
|
+
resolve({
|
|
26
|
+
stdout,
|
|
27
|
+
stderr,
|
|
28
|
+
exitCode: code ?? 1
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
proc.on("error", (err) => {
|
|
32
|
+
reject(err);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function claudePluginInstall(pluginPath, scope, projectDir) {
|
|
37
|
+
const args = ["plugin", "install", pluginPath, "--scope", scope];
|
|
38
|
+
const result = await execCommand("claude", args, { cwd: projectDir });
|
|
39
|
+
if (result.exitCode !== 0) {
|
|
40
|
+
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
41
|
+
throw new Error(`Plugin installation failed: ${errorMessage.trim()}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function isClaudeCLIAvailable() {
|
|
45
|
+
try {
|
|
46
|
+
const result = await execCommand("claude", ["--version"], {});
|
|
47
|
+
return result.exitCode === 0;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function claudePluginMarketplaceList() {
|
|
53
|
+
try {
|
|
54
|
+
const result = await execCommand(
|
|
55
|
+
"claude",
|
|
56
|
+
["plugin", "marketplace", "list", "--json"],
|
|
57
|
+
{}
|
|
58
|
+
);
|
|
59
|
+
if (result.exitCode !== 0) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return JSON.parse(result.stdout);
|
|
63
|
+
} catch {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function claudePluginMarketplaceExists(name) {
|
|
68
|
+
const marketplaces = await claudePluginMarketplaceList();
|
|
69
|
+
return marketplaces.some((m) => m.name === name);
|
|
70
|
+
}
|
|
71
|
+
async function claudePluginMarketplaceAdd(githubRepo, name) {
|
|
72
|
+
const args = ["plugin", "marketplace", "add", githubRepo, "--name", name];
|
|
73
|
+
let result;
|
|
74
|
+
try {
|
|
75
|
+
result = await execCommand("claude", args, {});
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Failed to add marketplace: ${err instanceof Error ? err.message : "Unknown error"}`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (result.exitCode !== 0) {
|
|
82
|
+
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
83
|
+
if (errorMessage.includes("already installed")) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Failed to add marketplace: ${errorMessage.trim()}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function claudePluginUninstall(pluginName, scope, projectDir) {
|
|
90
|
+
const args = ["plugin", "uninstall", pluginName, "--scope", scope];
|
|
91
|
+
const result = await execCommand("claude", args, { cwd: projectDir });
|
|
92
|
+
if (result.exitCode !== 0) {
|
|
93
|
+
const errorMessage = result.stderr || result.stdout || "Unknown error";
|
|
94
|
+
if (errorMessage.includes("not installed") || errorMessage.includes("not found")) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
throw new Error(`Plugin uninstall failed: ${errorMessage.trim()}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
claudePluginInstall,
|
|
103
|
+
isClaudeCLIAvailable,
|
|
104
|
+
claudePluginMarketplaceExists,
|
|
105
|
+
claudePluginMarketplaceAdd,
|
|
106
|
+
claudePluginUninstall
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=chunk-M7YCPFIX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/utils/exec.ts"],"sourcesContent":["import { spawn } from \"child_process\";\n\nexport interface ExecResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\n/**\n * Execute a command and return the result\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\n/**\n * Install a plugin using the native claude CLI\n */\nexport async function claudePluginInstall(\n pluginPath: string,\n scope: \"project\" | \"user\",\n projectDir: string,\n): Promise<void> {\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\n/**\n * Check if the claude CLI is available\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 interface MarketplaceInfo {\n name: string;\n source: string;\n repo?: string;\n path?: string;\n}\n\n/**\n * List configured marketplaces in Claude Code\n */\nexport async function claudePluginMarketplaceList(): Promise<\n MarketplaceInfo[]\n> {\n try {\n const result = await execCommand(\n \"claude\",\n [\"plugin\", \"marketplace\", \"list\", \"--json\"],\n {},\n );\n\n if (result.exitCode !== 0) {\n return [];\n }\n\n return JSON.parse(result.stdout);\n } catch {\n // Returns empty array if claude CLI is not available or parsing fails\n return [];\n }\n}\n\n/**\n * Check if a marketplace with the given name exists\n */\nexport async function claudePluginMarketplaceExists(\n name: string,\n): Promise<boolean> {\n const marketplaces = await claudePluginMarketplaceList();\n return marketplaces.some((m) => m.name === name);\n}\n\n/**\n * Add a marketplace to Claude Code from a GitHub repository\n */\nexport async function claudePluginMarketplaceAdd(\n githubRepo: string,\n name: string,\n): Promise<void> {\n const args = [\"plugin\", \"marketplace\", \"add\", githubRepo, \"--name\", name];\n let result;\n try {\n result = await execCommand(\"claude\", args, {});\n } catch (err) {\n throw new Error(\n `Failed to add marketplace: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n );\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\n/**\n * Uninstall a plugin using the native claude CLI\n */\nexport async function claudePluginUninstall(\n pluginName: string,\n scope: \"project\" | \"user\",\n projectDir: string,\n): Promise<void> {\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 (\n errorMessage.includes(\"not installed\") ||\n errorMessage.includes(\"not found\")\n ) {\n return;\n }\n throw new Error(`Plugin uninstall failed: ${errorMessage.trim()}`);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
fileExists,
|
|
4
|
+
glob,
|
|
5
|
+
readFile
|
|
6
|
+
} from "./chunk-MMDXNZPF.js";
|
|
7
|
+
import {
|
|
8
|
+
init_esm_shims
|
|
9
|
+
} from "./chunk-DHET7RCE.js";
|
|
10
|
+
|
|
11
|
+
// src/cli-v2/lib/versioning.ts
|
|
12
|
+
init_esm_shims();
|
|
13
|
+
import { createHash } from "crypto";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { stringify as stringifyYaml, parse as parseYaml } from "yaml";
|
|
16
|
+
var HASH_PREFIX_LENGTH = 7;
|
|
17
|
+
var HASHABLE_FILES = ["SKILL.md", "reference.md"];
|
|
18
|
+
var HASHABLE_DIRS = ["examples", "scripts"];
|
|
19
|
+
function hashString(content) {
|
|
20
|
+
const hash = createHash("sha256");
|
|
21
|
+
hash.update(content);
|
|
22
|
+
return hash.digest("hex").slice(0, HASH_PREFIX_LENGTH);
|
|
23
|
+
}
|
|
24
|
+
async function hashFile(filePath) {
|
|
25
|
+
const content = await readFile(filePath);
|
|
26
|
+
return hashString(content);
|
|
27
|
+
}
|
|
28
|
+
async function hashSkillFolder(skillPath) {
|
|
29
|
+
const contents = [];
|
|
30
|
+
for (const fileName of HASHABLE_FILES) {
|
|
31
|
+
const filePath = path.join(skillPath, fileName);
|
|
32
|
+
if (await fileExists(filePath)) {
|
|
33
|
+
const content = await readFile(filePath);
|
|
34
|
+
contents.push(`${fileName}:${content}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const dirName of HASHABLE_DIRS) {
|
|
38
|
+
const dirPath = path.join(skillPath, dirName);
|
|
39
|
+
if (await fileExists(dirPath)) {
|
|
40
|
+
const files = await glob("**/*", dirPath);
|
|
41
|
+
for (const file of files.sort()) {
|
|
42
|
+
const filePath = path.join(dirPath, file);
|
|
43
|
+
const content = await readFile(filePath);
|
|
44
|
+
contents.push(`${dirName}/${file}:${content}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const combined = contents.join("\n---\n");
|
|
49
|
+
return hashString(combined);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
hashString,
|
|
54
|
+
hashFile,
|
|
55
|
+
hashSkillFolder
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=chunk-MJSFR562.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/versioning.ts"],"sourcesContent":["import { createHash } from \"crypto\";\nimport path from \"path\";\nimport { stringify as stringifyYaml, parse as parseYaml } from \"yaml\";\nimport { readFile, writeFile, glob, fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\n\nconst HASH_PREFIX_LENGTH = 7;\n\nconst METADATA_FILE_NAME = \"metadata.yaml\";\n\nconst HASHABLE_FILES = [\"SKILL.md\", \"reference.md\"];\n\nconst HASHABLE_DIRS = [\"examples\", \"scripts\"];\n\ninterface VersionedMetadata {\n version: number;\n content_hash?: string;\n updated?: string;\n [key: string]: unknown;\n}\n\nexport interface VersionCheckResult {\n skillPath: string;\n previousVersion: number;\n newVersion: number;\n previousHash: string | undefined;\n newHash: string;\n changed: boolean;\n}\n\nexport function getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\nexport function hashString(content: string): string {\n const hash = createHash(\"sha256\");\n hash.update(content);\n return hash.digest(\"hex\").slice(0, HASH_PREFIX_LENGTH);\n}\n\nexport async function hashFile(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return hashString(content);\n}\n\nexport async function hashSkillFolder(skillPath: string): Promise<string> {\n const contents: string[] = [];\n\n for (const fileName of HASHABLE_FILES) {\n const filePath = path.join(skillPath, fileName);\n if (await fileExists(filePath)) {\n const content = await readFile(filePath);\n contents.push(`${fileName}:${content}`);\n }\n }\n\n for (const dirName of HASHABLE_DIRS) {\n const dirPath = path.join(skillPath, dirName);\n if (await fileExists(dirPath)) {\n const files = await glob(\"**/*\", dirPath);\n for (const file of files.sort()) {\n const filePath = path.join(dirPath, file);\n const content = await readFile(filePath);\n contents.push(`${dirName}/${file}:${content}`);\n }\n }\n }\n\n const combined = contents.join(\"\\n---\\n\");\n return hashString(combined);\n}\n\nasync function readMetadata(\n skillPath: string,\n): Promise<{ metadata: VersionedMetadata; schemaComment: string }> {\n const metadataPath = path.join(skillPath, METADATA_FILE_NAME);\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let schemaComment = \"\";\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = lines[0] + \"\\n\";\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as VersionedMetadata;\n return { metadata, schemaComment };\n}\n\nasync function writeMetadata(\n skillPath: string,\n metadata: VersionedMetadata,\n schemaComment: string,\n): Promise<void> {\n const metadataPath = path.join(skillPath, METADATA_FILE_NAME);\n const yamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataPath, schemaComment + yamlContent);\n}\n\nexport async function versionSkill(\n skillPath: string,\n): Promise<VersionCheckResult> {\n const newHash = await hashSkillFolder(skillPath);\n\n const { metadata, schemaComment } = await readMetadata(skillPath);\n const previousVersion = metadata.version;\n const previousHash = metadata.content_hash;\n\n const changed = previousHash !== newHash;\n\n if (changed) {\n metadata.version = previousVersion + 1;\n metadata.content_hash = newHash;\n metadata.updated = getCurrentDate();\n\n await writeMetadata(skillPath, metadata, schemaComment);\n\n verbose(\n ` Version bumped: ${skillPath} (v${previousVersion} -> v${metadata.version})`,\n );\n }\n\n return {\n skillPath,\n previousVersion,\n newVersion: changed ? previousVersion + 1 : previousVersion,\n previousHash,\n newHash,\n changed,\n };\n}\n\nexport async function versionAllSkills(\n skillsDir: string,\n): Promise<VersionCheckResult[]> {\n const results: VersionCheckResult[] = [];\n\n const metadataFiles = await glob(\"**/metadata.yaml\", skillsDir);\n\n for (const metadataFile of metadataFiles) {\n const skillPath = path.join(skillsDir, path.dirname(metadataFile));\n\n try {\n const result = await versionSkill(skillPath);\n results.push(result);\n } catch (error) {\n console.warn(\n ` Warning: Failed to version skill at ${skillPath}: ${error}`,\n );\n }\n }\n\n return results;\n}\n\nexport function printVersionResults(results: VersionCheckResult[]): void {\n const changed = results.filter((r) => r.changed);\n const unchanged = results.filter((r) => !r.changed);\n\n if (changed.length > 0) {\n console.log(`\\n Version Updates:`);\n for (const result of changed) {\n const skillName = path.basename(result.skillPath);\n console.log(\n ` ✓ ${skillName}: v${result.previousVersion} -> v${result.newVersion}`,\n );\n }\n }\n\n console.log(\n `\\n Summary: ${changed.length} updated, ${unchanged.length} unchanged`,\n );\n}\n"],"mappings":";;;;;;;;;;;AAAA;AAAA,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,aAAa,eAAe,SAAS,iBAAiB;AAI/D,IAAM,qBAAqB;AAI3B,IAAM,iBAAiB,CAAC,YAAY,cAAc;AAElD,IAAM,gBAAgB,CAAC,YAAY,SAAS;AAsBrC,SAAS,WAAW,SAAyB;AAClD,QAAM,OAAO,WAAW,QAAQ;AAChC,OAAK,OAAO,OAAO;AACnB,SAAO,KAAK,OAAO,KAAK,EAAE,MAAM,GAAG,kBAAkB;AACvD;AAEA,eAAsB,SAAS,UAAmC;AAChE,QAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,SAAO,WAAW,OAAO;AAC3B;AAEA,eAAsB,gBAAgB,WAAoC;AACxE,QAAM,WAAqB,CAAC;AAE5B,aAAW,YAAY,gBAAgB;AACrC,UAAM,WAAW,KAAK,KAAK,WAAW,QAAQ;AAC9C,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,YAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,eAAS,KAAK,GAAG,QAAQ,IAAI,OAAO,EAAE;AAAA,IACxC;AAAA,EACF;AAEA,aAAW,WAAW,eAAe;AACnC,UAAM,UAAU,KAAK,KAAK,WAAW,OAAO;AAC5C,QAAI,MAAM,WAAW,OAAO,GAAG;AAC7B,YAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO;AACxC,iBAAW,QAAQ,MAAM,KAAK,GAAG;AAC/B,cAAM,WAAW,KAAK,KAAK,SAAS,IAAI;AACxC,cAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,iBAAS,KAAK,GAAG,OAAO,IAAI,IAAI,IAAI,OAAO,EAAE;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,KAAK,SAAS;AACxC,SAAO,WAAW,QAAQ;AAC5B;","names":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/utils/fs.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
import fg from "fast-glob";
|
|
10
|
+
import path from "path";
|
|
11
|
+
async function readFile(filePath) {
|
|
12
|
+
return fs.readFile(filePath, "utf-8");
|
|
13
|
+
}
|
|
14
|
+
async function readFileOptional(filePath, fallback = "") {
|
|
15
|
+
try {
|
|
16
|
+
return await fs.readFile(filePath, "utf-8");
|
|
17
|
+
} catch {
|
|
18
|
+
return fallback;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function fileExists(filePath) {
|
|
22
|
+
return fs.pathExists(filePath);
|
|
23
|
+
}
|
|
24
|
+
async function directoryExists(dirPath) {
|
|
25
|
+
try {
|
|
26
|
+
const stat = await fs.stat(dirPath);
|
|
27
|
+
return stat.isDirectory();
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function listDirectories(dirPath) {
|
|
33
|
+
try {
|
|
34
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
35
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
36
|
+
} catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function glob(pattern, cwd) {
|
|
41
|
+
return fg(pattern, { cwd, onlyFiles: true });
|
|
42
|
+
}
|
|
43
|
+
async function writeFile(filePath, content) {
|
|
44
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
45
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
async function ensureDir(dirPath) {
|
|
48
|
+
await fs.ensureDir(dirPath);
|
|
49
|
+
}
|
|
50
|
+
async function remove(filePath) {
|
|
51
|
+
await fs.remove(filePath);
|
|
52
|
+
}
|
|
53
|
+
async function copy(src, dest) {
|
|
54
|
+
await fs.copy(src, dest);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
readFile,
|
|
59
|
+
readFileOptional,
|
|
60
|
+
fileExists,
|
|
61
|
+
directoryExists,
|
|
62
|
+
listDirectories,
|
|
63
|
+
glob,
|
|
64
|
+
writeFile,
|
|
65
|
+
ensureDir,
|
|
66
|
+
remove,
|
|
67
|
+
copy
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=chunk-MMDXNZPF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/utils/fs.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport fg from \"fast-glob\";\nimport path from \"path\";\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, \"utf-8\");\n}\n\nexport async function readFileOptional(\n filePath: string,\n fallback = \"\",\n): Promise<string> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return fallback;\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n return fs.pathExists(filePath);\n}\n\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(dirPath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function listDirectories(dirPath: string): Promise<string[]> {\n try {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nexport async function glob(pattern: string, cwd: string): Promise<string[]> {\n return fg(pattern, { cwd, onlyFiles: true });\n}\n\nexport async function writeFile(\n filePath: string,\n content: string,\n): Promise<void> {\n await fs.ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, \"utf-8\");\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\nexport async function remove(filePath: string): Promise<void> {\n await fs.remove(filePath);\n}\n\nexport async function copy(src: string, dest: string): Promise<void> {\n await fs.copy(src, dest);\n}\n"],"mappings":";;;;;;AAAA;AAAA,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAsB,SAAS,UAAmC;AAChE,SAAO,GAAG,SAAS,UAAU,OAAO;AACtC;AAEA,eAAsB,iBACpB,UACA,WAAW,IACM;AACjB,MAAI;AACF,WAAO,MAAM,GAAG,SAAS,UAAU,OAAO;AAAA,EAC5C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,WAAW,UAAoC;AACnE,SAAO,GAAG,WAAW,QAAQ;AAC/B;AAEA,eAAsB,gBAAgB,SAAmC;AACvE,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,KAAK,OAAO;AAClC,WAAO,KAAK,YAAY;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBAAgB,SAAoC;AACxE,MAAI;AACF,UAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AACjE,WAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACjE,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAsB,KAAK,SAAiB,KAAgC;AAC1E,SAAO,GAAG,SAAS,EAAE,KAAK,WAAW,KAAK,CAAC;AAC7C;AAEA,eAAsB,UACpB,UACA,SACe;AACf,QAAM,GAAG,UAAU,KAAK,QAAQ,QAAQ,CAAC;AACzC,QAAM,GAAG,UAAU,UAAU,SAAS,OAAO;AAC/C;AAEA,eAAsB,UAAU,SAAgC;AAC9D,QAAM,GAAG,UAAU,OAAO;AAC5B;AAEA,eAAsB,OAAO,UAAiC;AAC5D,QAAM,GAAG,OAAO,QAAQ;AAC1B;AAEA,eAAsB,KAAK,KAAa,MAA6B;AACnE,QAAM,GAAG,KAAK,KAAK,IAAI;AACzB;","names":[]}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
verbose
|
|
4
|
+
} from "./chunk-TOPAIL5W.js";
|
|
5
|
+
import {
|
|
6
|
+
fileExists,
|
|
7
|
+
readFile
|
|
8
|
+
} from "./chunk-MMDXNZPF.js";
|
|
9
|
+
import {
|
|
10
|
+
init_esm_shims
|
|
11
|
+
} from "./chunk-DHET7RCE.js";
|
|
12
|
+
|
|
13
|
+
// src/cli-v2/lib/project-config.ts
|
|
14
|
+
init_esm_shims();
|
|
15
|
+
import path from "path";
|
|
16
|
+
import { parse as parseYaml } from "yaml";
|
|
17
|
+
var CONFIG_PATH = ".claude/config.yaml";
|
|
18
|
+
async function loadProjectConfig(projectDir) {
|
|
19
|
+
const configPath = path.join(projectDir, CONFIG_PATH);
|
|
20
|
+
if (!await fileExists(configPath)) {
|
|
21
|
+
verbose(`Project config not found at ${configPath}`);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const content = await readFile(configPath);
|
|
26
|
+
const parsed = parseYaml(content);
|
|
27
|
+
if (!parsed || typeof parsed !== "object") {
|
|
28
|
+
verbose(`Invalid project config structure at ${configPath}`);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const isLegacy = isLegacyStackConfig(parsed);
|
|
32
|
+
if (isLegacy) {
|
|
33
|
+
verbose(`Detected legacy StackConfig format at ${configPath}`);
|
|
34
|
+
const normalized = normalizeStackConfig(parsed);
|
|
35
|
+
return {
|
|
36
|
+
config: normalized,
|
|
37
|
+
configPath,
|
|
38
|
+
isLegacy: true
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
verbose(`Loaded project config from ${configPath}`);
|
|
42
|
+
return {
|
|
43
|
+
config: parsed,
|
|
44
|
+
configPath,
|
|
45
|
+
isLegacy: false
|
|
46
|
+
};
|
|
47
|
+
} catch (error) {
|
|
48
|
+
verbose(`Failed to parse project config: ${error}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isLegacyStackConfig(config) {
|
|
53
|
+
if (!config || typeof config !== "object") return false;
|
|
54
|
+
const obj = config;
|
|
55
|
+
if (typeof obj.version === "string" && obj.version.includes(".")) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (obj.id !== void 0 || obj.created !== void 0 || obj.updated !== void 0) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function normalizeStackConfig(stackConfig) {
|
|
64
|
+
const config = {
|
|
65
|
+
name: stackConfig.name,
|
|
66
|
+
agents: stackConfig.agents
|
|
67
|
+
};
|
|
68
|
+
if (stackConfig.description) {
|
|
69
|
+
config.description = stackConfig.description;
|
|
70
|
+
}
|
|
71
|
+
if (stackConfig.skills && stackConfig.skills.length > 0) {
|
|
72
|
+
config.skills = stackConfig.skills;
|
|
73
|
+
}
|
|
74
|
+
if (stackConfig.agent_skills) {
|
|
75
|
+
config.agent_skills = stackConfig.agent_skills;
|
|
76
|
+
}
|
|
77
|
+
if (stackConfig.hooks) {
|
|
78
|
+
config.hooks = stackConfig.hooks;
|
|
79
|
+
}
|
|
80
|
+
if (stackConfig.author) {
|
|
81
|
+
config.author = stackConfig.author;
|
|
82
|
+
}
|
|
83
|
+
if (stackConfig.framework) {
|
|
84
|
+
config.framework = stackConfig.framework;
|
|
85
|
+
}
|
|
86
|
+
if (stackConfig.philosophy) {
|
|
87
|
+
config.philosophy = stackConfig.philosophy;
|
|
88
|
+
}
|
|
89
|
+
if (stackConfig.principles && stackConfig.principles.length > 0) {
|
|
90
|
+
config.principles = stackConfig.principles;
|
|
91
|
+
}
|
|
92
|
+
if (stackConfig.tags && stackConfig.tags.length > 0) {
|
|
93
|
+
config.tags = stackConfig.tags;
|
|
94
|
+
}
|
|
95
|
+
return config;
|
|
96
|
+
}
|
|
97
|
+
function validateProjectConfig(config) {
|
|
98
|
+
const errors = [];
|
|
99
|
+
const warnings = [];
|
|
100
|
+
if (!config || typeof config !== "object") {
|
|
101
|
+
return { valid: false, errors: ["Config must be an object"], warnings: [] };
|
|
102
|
+
}
|
|
103
|
+
const c = config;
|
|
104
|
+
if (!c.name || typeof c.name !== "string") {
|
|
105
|
+
errors.push("name is required and must be a string");
|
|
106
|
+
}
|
|
107
|
+
if (!c.agents || !Array.isArray(c.agents)) {
|
|
108
|
+
errors.push("agents is required and must be an array");
|
|
109
|
+
} else {
|
|
110
|
+
for (const agent of c.agents) {
|
|
111
|
+
if (typeof agent !== "string") {
|
|
112
|
+
errors.push(`agents must contain strings, found: ${typeof agent}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (c.version !== void 0 && c.version !== "1") {
|
|
117
|
+
errors.push('version must be "1" (or omitted for default)');
|
|
118
|
+
}
|
|
119
|
+
if (c.skills !== void 0) {
|
|
120
|
+
if (!Array.isArray(c.skills)) {
|
|
121
|
+
errors.push("skills must be an array");
|
|
122
|
+
} else {
|
|
123
|
+
for (const skill of c.skills) {
|
|
124
|
+
const skillError = validateSkillEntry(skill);
|
|
125
|
+
if (skillError) {
|
|
126
|
+
errors.push(skillError);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (c.agent_skills !== void 0) {
|
|
132
|
+
if (typeof c.agent_skills !== "object" || c.agent_skills === null) {
|
|
133
|
+
errors.push("agent_skills must be an object");
|
|
134
|
+
} else {
|
|
135
|
+
for (const [agentName, agentSkills] of Object.entries(c.agent_skills)) {
|
|
136
|
+
const agentSkillsError = validateAgentSkillConfig(
|
|
137
|
+
agentName,
|
|
138
|
+
agentSkills
|
|
139
|
+
);
|
|
140
|
+
if (agentSkillsError) {
|
|
141
|
+
errors.push(agentSkillsError);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (c.preload_patterns !== void 0) {
|
|
147
|
+
if (typeof c.preload_patterns !== "object" || c.preload_patterns === null) {
|
|
148
|
+
errors.push("preload_patterns must be an object");
|
|
149
|
+
} else {
|
|
150
|
+
for (const [agentName, patterns] of Object.entries(c.preload_patterns)) {
|
|
151
|
+
if (!Array.isArray(patterns)) {
|
|
152
|
+
errors.push(
|
|
153
|
+
`preload_patterns.${agentName} must be an array of strings`
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
for (const pattern of patterns) {
|
|
157
|
+
if (typeof pattern !== "string") {
|
|
158
|
+
errors.push(
|
|
159
|
+
`preload_patterns.${agentName} must contain only strings`
|
|
160
|
+
);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (c.custom_agents !== void 0) {
|
|
169
|
+
const customAgentsErrors = validateCustomAgents(c.custom_agents, c.agents);
|
|
170
|
+
errors.push(...customAgentsErrors);
|
|
171
|
+
}
|
|
172
|
+
if (c.id !== void 0) {
|
|
173
|
+
warnings.push("id field is deprecated in project config");
|
|
174
|
+
}
|
|
175
|
+
if (c.created !== void 0) {
|
|
176
|
+
warnings.push("created field is deprecated in project config");
|
|
177
|
+
}
|
|
178
|
+
if (c.updated !== void 0) {
|
|
179
|
+
warnings.push("updated field is deprecated in project config");
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
valid: errors.length === 0,
|
|
183
|
+
errors,
|
|
184
|
+
warnings
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
var MAX_CUSTOM_AGENTS = 20;
|
|
188
|
+
var VALID_MODELS = ["sonnet", "opus", "haiku", "inherit"];
|
|
189
|
+
var VALID_PERMISSION_MODES = [
|
|
190
|
+
"default",
|
|
191
|
+
"acceptEdits",
|
|
192
|
+
"dontAsk",
|
|
193
|
+
"bypassPermissions",
|
|
194
|
+
"plan",
|
|
195
|
+
"delegate"
|
|
196
|
+
];
|
|
197
|
+
function validateCustomAgents(customAgents, agents) {
|
|
198
|
+
const errors = [];
|
|
199
|
+
if (typeof customAgents !== "object" || customAgents === null) {
|
|
200
|
+
errors.push("custom_agents must be an object");
|
|
201
|
+
return errors;
|
|
202
|
+
}
|
|
203
|
+
const customAgentEntries = Object.entries(customAgents);
|
|
204
|
+
if (customAgentEntries.length > MAX_CUSTOM_AGENTS) {
|
|
205
|
+
errors.push(
|
|
206
|
+
`custom_agents cannot exceed ${MAX_CUSTOM_AGENTS} agents (found ${customAgentEntries.length})`
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
const customAgentNames = new Set(customAgentEntries.map(([name]) => name));
|
|
210
|
+
for (const [agentName, agentConfig] of customAgentEntries) {
|
|
211
|
+
const agentErrors = validateCustomAgentConfig(
|
|
212
|
+
agentName,
|
|
213
|
+
agentConfig,
|
|
214
|
+
customAgentNames
|
|
215
|
+
);
|
|
216
|
+
errors.push(...agentErrors);
|
|
217
|
+
}
|
|
218
|
+
return errors;
|
|
219
|
+
}
|
|
220
|
+
function validateCustomAgentConfig(agentName, config, customAgentNames) {
|
|
221
|
+
const errors = [];
|
|
222
|
+
const prefix = `custom_agents.${agentName}`;
|
|
223
|
+
if (typeof config !== "object" || config === null) {
|
|
224
|
+
errors.push(`${prefix} must be an object`);
|
|
225
|
+
return errors;
|
|
226
|
+
}
|
|
227
|
+
const c = config;
|
|
228
|
+
if (!c.title || typeof c.title !== "string") {
|
|
229
|
+
errors.push(`${prefix}.title is required and must be a string`);
|
|
230
|
+
}
|
|
231
|
+
if (!c.description || typeof c.description !== "string") {
|
|
232
|
+
errors.push(`${prefix}.description is required and must be a string`);
|
|
233
|
+
}
|
|
234
|
+
if (c.extends !== void 0) {
|
|
235
|
+
if (typeof c.extends !== "string") {
|
|
236
|
+
errors.push(`${prefix}.extends must be a string`);
|
|
237
|
+
} else if (customAgentNames.has(c.extends)) {
|
|
238
|
+
errors.push(
|
|
239
|
+
`${prefix}.extends cannot reference another custom agent "${c.extends}"`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (c.model !== void 0) {
|
|
244
|
+
if (typeof c.model !== "string" || !VALID_MODELS.includes(c.model)) {
|
|
245
|
+
errors.push(`${prefix}.model must be one of: ${VALID_MODELS.join(", ")}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (c.tools !== void 0) {
|
|
249
|
+
if (!Array.isArray(c.tools)) {
|
|
250
|
+
errors.push(`${prefix}.tools must be an array`);
|
|
251
|
+
} else {
|
|
252
|
+
for (const tool of c.tools) {
|
|
253
|
+
if (typeof tool !== "string") {
|
|
254
|
+
errors.push(`${prefix}.tools must contain only strings`);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (c.disallowed_tools !== void 0) {
|
|
261
|
+
if (!Array.isArray(c.disallowed_tools)) {
|
|
262
|
+
errors.push(`${prefix}.disallowed_tools must be an array`);
|
|
263
|
+
} else {
|
|
264
|
+
for (const tool of c.disallowed_tools) {
|
|
265
|
+
if (typeof tool !== "string") {
|
|
266
|
+
errors.push(`${prefix}.disallowed_tools must contain only strings`);
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (c.permission_mode !== void 0) {
|
|
273
|
+
if (typeof c.permission_mode !== "string" || !VALID_PERMISSION_MODES.includes(c.permission_mode)) {
|
|
274
|
+
errors.push(
|
|
275
|
+
`${prefix}.permission_mode must be one of: ${VALID_PERMISSION_MODES.join(", ")}`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (c.skills !== void 0) {
|
|
280
|
+
if (!Array.isArray(c.skills)) {
|
|
281
|
+
errors.push(`${prefix}.skills must be an array`);
|
|
282
|
+
} else {
|
|
283
|
+
for (const skill of c.skills) {
|
|
284
|
+
const skillError = validateSkillEntry(skill);
|
|
285
|
+
if (skillError) {
|
|
286
|
+
errors.push(`${prefix}.skills: ${skillError}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (c.hooks !== void 0) {
|
|
292
|
+
if (typeof c.hooks !== "object" || c.hooks === null) {
|
|
293
|
+
errors.push(`${prefix}.hooks must be an object`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return errors;
|
|
297
|
+
}
|
|
298
|
+
function validateSkillEntry(skill) {
|
|
299
|
+
if (typeof skill === "string") {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
if (typeof skill !== "object" || skill === null) {
|
|
303
|
+
return "skills must be strings or objects";
|
|
304
|
+
}
|
|
305
|
+
const s = skill;
|
|
306
|
+
if (!s.id || typeof s.id !== "string") {
|
|
307
|
+
return "skill object must have an id string";
|
|
308
|
+
}
|
|
309
|
+
if (s.local === true && !s.path) {
|
|
310
|
+
return `local skill "${s.id}" must have a path`;
|
|
311
|
+
}
|
|
312
|
+
if (s.preloaded !== void 0 && typeof s.preloaded !== "boolean") {
|
|
313
|
+
return `skill "${s.id}" preloaded must be a boolean`;
|
|
314
|
+
}
|
|
315
|
+
if (s.local !== void 0 && typeof s.local !== "boolean") {
|
|
316
|
+
return `skill "${s.id}" local must be a boolean`;
|
|
317
|
+
}
|
|
318
|
+
if (s.path !== void 0 && typeof s.path !== "string") {
|
|
319
|
+
return `skill "${s.id}" path must be a string`;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
function validateAgentSkillConfig(agentName, agentSkills) {
|
|
324
|
+
if (Array.isArray(agentSkills)) {
|
|
325
|
+
for (const skill of agentSkills) {
|
|
326
|
+
const skillError = validateSkillEntry(skill);
|
|
327
|
+
if (skillError) {
|
|
328
|
+
return `agent_skills.${agentName}: ${skillError}`;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
if (typeof agentSkills === "object" && agentSkills !== null) {
|
|
334
|
+
for (const [category, skills] of Object.entries(agentSkills)) {
|
|
335
|
+
if (!Array.isArray(skills)) {
|
|
336
|
+
return `agent_skills.${agentName}.${category} must be an array`;
|
|
337
|
+
}
|
|
338
|
+
for (const skill of skills) {
|
|
339
|
+
const skillError = validateSkillEntry(skill);
|
|
340
|
+
if (skillError) {
|
|
341
|
+
return `agent_skills.${agentName}.${category}: ${skillError}`;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
return `agent_skills.${agentName} must be an array or object`;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export {
|
|
351
|
+
loadProjectConfig,
|
|
352
|
+
isLegacyStackConfig,
|
|
353
|
+
normalizeStackConfig,
|
|
354
|
+
validateProjectConfig
|
|
355
|
+
};
|
|
356
|
+
//# sourceMappingURL=chunk-MYAVQ23U.js.map
|