@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,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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/project-config.ts"],"sourcesContent":["import path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { readFile, fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport type {\n ProjectConfig,\n StackConfig,\n SkillAssignment,\n SkillEntry,\n AgentSkillConfig,\n ValidationResult,\n CustomAgentConfig,\n} from \"../../types\";\n\nconst CONFIG_PATH = \".claude/config.yaml\";\n\nexport interface LoadedProjectConfig {\n config: ProjectConfig;\n configPath: string;\n /** true if was StackConfig format (legacy) */\n isLegacy: boolean;\n}\n\n/**\n * Load project config from .claude/config.yaml\n */\nexport async function loadProjectConfig(\n projectDir: string,\n): Promise<LoadedProjectConfig | null> {\n const configPath = path.join(projectDir, CONFIG_PATH);\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\n if (!parsed || typeof parsed !== \"object\") {\n verbose(`Invalid project config structure at ${configPath}`);\n return null;\n }\n\n // Detect if this is legacy StackConfig format\n const isLegacy = isLegacyStackConfig(parsed);\n\n if (isLegacy) {\n verbose(`Detected legacy StackConfig format at ${configPath}`);\n const normalized = normalizeStackConfig(parsed as StackConfig);\n return {\n config: normalized,\n configPath,\n isLegacy: true,\n };\n }\n\n verbose(`Loaded project config from ${configPath}`);\n return {\n config: parsed as ProjectConfig,\n configPath,\n isLegacy: false,\n };\n } catch (error) {\n verbose(`Failed to parse project config: ${error}`);\n return null;\n }\n}\n\n/**\n * Check if a config object is in legacy StackConfig format.\n * Detection logic:\n * - If version is semver (e.g., \"1.0.0\") -> legacy\n * - If version is \"1\" -> new format\n * - If has 'id' field -> legacy\n * - If has 'created' or 'updated' fields -> legacy\n */\nexport function isLegacyStackConfig(config: unknown): boolean {\n if (!config || typeof config !== \"object\") return false;\n\n const obj = config as Record<string, unknown>;\n\n // If version looks like semver (x.y.z), it's legacy\n if (typeof obj.version === \"string\" && obj.version.includes(\".\")) {\n return true;\n }\n\n // If has legacy-only fields, it's legacy\n if (\n obj.id !== undefined ||\n obj.created !== undefined ||\n obj.updated !== undefined\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Normalize StackConfig to ProjectConfig (for backward compatibility)\n */\nexport function normalizeStackConfig(stackConfig: StackConfig): ProjectConfig {\n const config: ProjectConfig = {\n name: stackConfig.name,\n agents: stackConfig.agents,\n };\n\n // Copy optional fields\n if (stackConfig.description) {\n config.description = stackConfig.description;\n }\n\n if (stackConfig.skills && stackConfig.skills.length > 0) {\n config.skills = stackConfig.skills;\n }\n\n if (stackConfig.agent_skills) {\n // StackConfig agent_skills is always categorized format\n config.agent_skills = stackConfig.agent_skills;\n }\n\n if (stackConfig.hooks) {\n config.hooks = stackConfig.hooks;\n }\n\n if (stackConfig.author) {\n config.author = stackConfig.author;\n }\n\n if (stackConfig.framework) {\n config.framework = stackConfig.framework;\n }\n\n if (stackConfig.philosophy) {\n config.philosophy = stackConfig.philosophy;\n }\n\n if (stackConfig.principles && stackConfig.principles.length > 0) {\n config.principles = stackConfig.principles;\n }\n\n if (stackConfig.tags && stackConfig.tags.length > 0) {\n config.tags = stackConfig.tags;\n }\n\n return config;\n}\n\n/**\n * Validate project config structure.\n * Returns validation result with errors and warnings.\n */\nexport function validateProjectConfig(config: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!config || typeof config !== \"object\") {\n return { valid: false, errors: [\"Config must be an object\"], warnings: [] };\n }\n\n const c = config as Record<string, unknown>;\n\n // Required: name\n if (!c.name || typeof c.name !== \"string\") {\n errors.push(\"name is required and must be a string\");\n }\n\n // Required: agents (for compilation)\n if (!c.agents || !Array.isArray(c.agents)) {\n errors.push(\"agents is required and must be an array\");\n } else {\n for (const agent of c.agents) {\n if (typeof agent !== \"string\") {\n errors.push(`agents must contain strings, found: ${typeof agent}`);\n }\n }\n }\n\n // Optional: version\n if (c.version !== undefined && c.version !== \"1\") {\n errors.push('version must be \"1\" (or omitted for default)');\n }\n\n // Optional: skills\n if (c.skills !== undefined) {\n if (!Array.isArray(c.skills)) {\n errors.push(\"skills must be an array\");\n } else {\n for (const skill of c.skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n errors.push(skillError);\n }\n }\n }\n }\n\n // Optional: agent_skills\n if (c.agent_skills !== undefined) {\n if (typeof c.agent_skills !== \"object\" || c.agent_skills === null) {\n errors.push(\"agent_skills must be an object\");\n } else {\n for (const [agentName, agentSkills] of Object.entries(c.agent_skills)) {\n const agentSkillsError = validateAgentSkillConfig(\n agentName,\n agentSkills,\n );\n if (agentSkillsError) {\n errors.push(agentSkillsError);\n }\n }\n }\n }\n\n // Optional: preload_patterns\n if (c.preload_patterns !== undefined) {\n if (typeof c.preload_patterns !== \"object\" || c.preload_patterns === null) {\n errors.push(\"preload_patterns must be an object\");\n } else {\n for (const [agentName, patterns] of Object.entries(c.preload_patterns)) {\n if (!Array.isArray(patterns)) {\n errors.push(\n `preload_patterns.${agentName} must be an array of strings`,\n );\n } else {\n for (const pattern of patterns) {\n if (typeof pattern !== \"string\") {\n errors.push(\n `preload_patterns.${agentName} must contain only strings`,\n );\n break;\n }\n }\n }\n }\n }\n }\n\n // Optional: custom_agents\n if (c.custom_agents !== undefined) {\n const customAgentsErrors = validateCustomAgents(c.custom_agents, c.agents);\n errors.push(...customAgentsErrors);\n }\n\n // Warnings for deprecated patterns\n if (c.id !== undefined) {\n warnings.push(\"id field is deprecated in project config\");\n }\n if (c.created !== undefined) {\n warnings.push(\"created field is deprecated in project config\");\n }\n if (c.updated !== undefined) {\n warnings.push(\"updated field is deprecated in project config\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/** Maximum number of custom agents allowed per project */\nconst MAX_CUSTOM_AGENTS = 20;\n\n/** Valid model values for custom agents */\nconst VALID_MODELS = [\"sonnet\", \"opus\", \"haiku\", \"inherit\"];\n\n/** Valid permission modes for custom agents */\nconst VALID_PERMISSION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"dontAsk\",\n \"bypassPermissions\",\n \"plan\",\n \"delegate\",\n];\n\n/**\n * Validate custom_agents section of config\n */\nfunction validateCustomAgents(\n customAgents: unknown,\n agents: unknown,\n): string[] {\n const errors: string[] = [];\n\n if (typeof customAgents !== \"object\" || customAgents === null) {\n errors.push(\"custom_agents must be an object\");\n return errors;\n }\n\n const customAgentEntries = Object.entries(customAgents);\n\n // Check maximum limit\n if (customAgentEntries.length > MAX_CUSTOM_AGENTS) {\n errors.push(\n `custom_agents cannot exceed ${MAX_CUSTOM_AGENTS} agents (found ${customAgentEntries.length})`,\n );\n }\n\n // Collect custom agent names for circular reference check\n const customAgentNames = new Set(customAgentEntries.map(([name]) => name));\n\n for (const [agentName, agentConfig] of customAgentEntries) {\n const agentErrors = validateCustomAgentConfig(\n agentName,\n agentConfig,\n customAgentNames,\n );\n errors.push(...agentErrors);\n }\n\n return errors;\n}\n\n/**\n * Validate a single custom agent configuration\n */\nfunction validateCustomAgentConfig(\n agentName: string,\n config: unknown,\n customAgentNames: Set<string>,\n): string[] {\n const errors: string[] = [];\n const prefix = `custom_agents.${agentName}`;\n\n if (typeof config !== \"object\" || config === null) {\n errors.push(`${prefix} must be an object`);\n return errors;\n }\n\n const c = config as Record<string, unknown>;\n\n // Required: title\n if (!c.title || typeof c.title !== \"string\") {\n errors.push(`${prefix}.title is required and must be a string`);\n }\n\n // Required: description\n if (!c.description || typeof c.description !== \"string\") {\n errors.push(`${prefix}.description is required and must be a string`);\n }\n\n // Optional: extends\n if (c.extends !== undefined) {\n if (typeof c.extends !== \"string\") {\n errors.push(`${prefix}.extends must be a string`);\n } else if (customAgentNames.has(c.extends)) {\n // Custom agents cannot extend other custom agents\n errors.push(\n `${prefix}.extends cannot reference another custom agent \"${c.extends}\"`,\n );\n }\n }\n\n // Optional: model\n if (c.model !== undefined) {\n if (typeof c.model !== \"string\" || !VALID_MODELS.includes(c.model)) {\n errors.push(`${prefix}.model must be one of: ${VALID_MODELS.join(\", \")}`);\n }\n }\n\n // Optional: tools\n if (c.tools !== undefined) {\n if (!Array.isArray(c.tools)) {\n errors.push(`${prefix}.tools must be an array`);\n } else {\n for (const tool of c.tools) {\n if (typeof tool !== \"string\") {\n errors.push(`${prefix}.tools must contain only strings`);\n break;\n }\n }\n }\n }\n\n // Optional: disallowed_tools\n if (c.disallowed_tools !== undefined) {\n if (!Array.isArray(c.disallowed_tools)) {\n errors.push(`${prefix}.disallowed_tools must be an array`);\n } else {\n for (const tool of c.disallowed_tools) {\n if (typeof tool !== \"string\") {\n errors.push(`${prefix}.disallowed_tools must contain only strings`);\n break;\n }\n }\n }\n }\n\n // Optional: permission_mode\n if (c.permission_mode !== undefined) {\n if (\n typeof c.permission_mode !== \"string\" ||\n !VALID_PERMISSION_MODES.includes(c.permission_mode)\n ) {\n errors.push(\n `${prefix}.permission_mode must be one of: ${VALID_PERMISSION_MODES.join(\", \")}`,\n );\n }\n }\n\n // Optional: skills\n if (c.skills !== undefined) {\n if (!Array.isArray(c.skills)) {\n errors.push(`${prefix}.skills must be an array`);\n } else {\n for (const skill of c.skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n errors.push(`${prefix}.skills: ${skillError}`);\n }\n }\n }\n }\n\n // Optional: hooks\n if (c.hooks !== undefined) {\n if (typeof c.hooks !== \"object\" || c.hooks === null) {\n errors.push(`${prefix}.hooks must be an object`);\n }\n // Note: Detailed hook validation could be added later if needed\n }\n\n return errors;\n}\n\n/**\n * Validate a single skill entry\n */\nfunction validateSkillEntry(skill: unknown): string | null {\n if (typeof skill === \"string\") {\n return null; // String skill IDs are valid\n }\n\n if (typeof skill !== \"object\" || skill === null) {\n return \"skills must be strings or objects\";\n }\n\n const s = skill as Record<string, unknown>;\n\n if (!s.id || typeof s.id !== \"string\") {\n return \"skill object must have an id string\";\n }\n\n if (s.local === true && !s.path) {\n return `local skill \"${s.id}\" must have a path`;\n }\n\n if (s.preloaded !== undefined && typeof s.preloaded !== \"boolean\") {\n return `skill \"${s.id}\" preloaded must be a boolean`;\n }\n\n if (s.local !== undefined && typeof s.local !== \"boolean\") {\n return `skill \"${s.id}\" local must be a boolean`;\n }\n\n if (s.path !== undefined && typeof s.path !== \"string\") {\n return `skill \"${s.id}\" path must be a string`;\n }\n\n return null;\n}\n\n/**\n * Validate agent skill config (can be simple list or categorized)\n */\nfunction validateAgentSkillConfig(\n agentName: string,\n agentSkills: unknown,\n): string | null {\n // Check if it's a simple list (array)\n if (Array.isArray(agentSkills)) {\n for (const skill of agentSkills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n return `agent_skills.${agentName}: ${skillError}`;\n }\n }\n return null;\n }\n\n // Check if it's categorized (object with array values)\n if (typeof agentSkills === \"object\" && agentSkills !== null) {\n for (const [category, skills] of Object.entries(agentSkills)) {\n if (!Array.isArray(skills)) {\n return `agent_skills.${agentName}.${category} must be an array`;\n }\n for (const skill of skills) {\n const skillError = validateSkillEntry(skill);\n if (skillError) {\n return `agent_skills.${agentName}.${category}: ${skillError}`;\n }\n }\n }\n return null;\n }\n\n return `agent_skills.${agentName} must be an array or object`;\n}\n\n/**\n * Check if agent_skills value is in simple list format (array)\n */\nexport function isSimpleAgentSkills(value: unknown): value is SkillEntry[] {\n return Array.isArray(value);\n}\n\n/**\n * Normalize a skill entry to SkillAssignment\n */\nexport function normalizeSkillEntry(entry: SkillEntry): SkillAssignment {\n if (typeof entry === \"string\") {\n return { id: entry };\n }\n return entry;\n}\n\n/**\n * Normalize agent_skills to always be categorized format for internal use.\n * Simple lists are placed under an \"uncategorized\" key.\n */\nexport function normalizeAgentSkills(\n agentSkills: Record<string, AgentSkillConfig>,\n): Record<string, Record<string, SkillAssignment[]>> {\n const result: Record<string, Record<string, SkillAssignment[]>> = {};\n\n for (const [agentName, skills] of Object.entries(agentSkills)) {\n if (isSimpleAgentSkills(skills)) {\n // Simple list -> put under \"uncategorized\"\n result[agentName] = {\n uncategorized: skills.map(normalizeSkillEntry),\n };\n } else {\n // Already categorized -> normalize entries\n result[agentName] = {};\n for (const [category, categorySkills] of Object.entries(skills)) {\n result[agentName][category] = categorySkills.map(normalizeSkillEntry);\n }\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
hashFile
|
|
4
|
+
} from "./chunk-MJSFR562.js";
|
|
5
|
+
import {
|
|
6
|
+
copy,
|
|
7
|
+
ensureDir,
|
|
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/skill-copier.ts
|
|
16
|
+
init_esm_shims();
|
|
17
|
+
import path from "path";
|
|
18
|
+
import { stringify as stringifyYaml, parse as parseYaml } from "yaml";
|
|
19
|
+
var METADATA_FILE_NAME = "metadata.yaml";
|
|
20
|
+
function getSkillDestPath(skill, stackDir) {
|
|
21
|
+
const skillRelativePath = skill.path.replace(/^skills\//, "");
|
|
22
|
+
return path.join(stackDir, "skills", skillRelativePath);
|
|
23
|
+
}
|
|
24
|
+
async function generateSkillHash(skillSourcePath) {
|
|
25
|
+
const skillMdPath = path.join(skillSourcePath, "SKILL.md");
|
|
26
|
+
return hashFile(skillMdPath);
|
|
27
|
+
}
|
|
28
|
+
function getCurrentDate() {
|
|
29
|
+
return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
30
|
+
}
|
|
31
|
+
async function injectForkedFromMetadata(destPath, skillId, contentHash) {
|
|
32
|
+
const metadataPath = path.join(destPath, METADATA_FILE_NAME);
|
|
33
|
+
const rawContent = await readFile(metadataPath);
|
|
34
|
+
const lines = rawContent.split("\n");
|
|
35
|
+
let yamlContent = rawContent;
|
|
36
|
+
if (lines[0]?.startsWith("# yaml-language-server:")) {
|
|
37
|
+
yamlContent = lines.slice(1).join("\n");
|
|
38
|
+
}
|
|
39
|
+
const metadata = parseYaml(yamlContent);
|
|
40
|
+
metadata.forked_from = {
|
|
41
|
+
skill_id: skillId,
|
|
42
|
+
content_hash: contentHash,
|
|
43
|
+
date: getCurrentDate()
|
|
44
|
+
};
|
|
45
|
+
const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });
|
|
46
|
+
await writeFile(metadataPath, newYamlContent);
|
|
47
|
+
}
|
|
48
|
+
function getSkillSourcePathFromSource(skill, sourceResult) {
|
|
49
|
+
return path.join(sourceResult.sourcePath, "src", skill.path);
|
|
50
|
+
}
|
|
51
|
+
async function copySkillFromSource(skill, stackDir, sourceResult) {
|
|
52
|
+
const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);
|
|
53
|
+
const destPath = getSkillDestPath(skill, stackDir);
|
|
54
|
+
const contentHash = await generateSkillHash(sourcePath);
|
|
55
|
+
await ensureDir(path.dirname(destPath));
|
|
56
|
+
await copy(sourcePath, destPath);
|
|
57
|
+
await injectForkedFromMetadata(destPath, skill.id, contentHash);
|
|
58
|
+
return {
|
|
59
|
+
skillId: skill.id,
|
|
60
|
+
contentHash,
|
|
61
|
+
sourcePath,
|
|
62
|
+
destPath
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async function copySkillsToPluginFromSource(selectedSkillIds, pluginDir, matrix, sourceResult) {
|
|
66
|
+
const copiedSkills = [];
|
|
67
|
+
for (const skillId of selectedSkillIds) {
|
|
68
|
+
const skill = matrix.skills[skillId];
|
|
69
|
+
if (!skill) {
|
|
70
|
+
console.warn(`Warning: Skill not found in matrix: ${skillId}`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (skill.local && skill.localPath) {
|
|
74
|
+
const localSkillPath = path.join(process.cwd(), skill.localPath);
|
|
75
|
+
const contentHash = await generateSkillHash(localSkillPath);
|
|
76
|
+
copiedSkills.push({
|
|
77
|
+
skillId: skill.id,
|
|
78
|
+
sourcePath: skill.localPath,
|
|
79
|
+
destPath: skill.localPath,
|
|
80
|
+
contentHash,
|
|
81
|
+
local: true
|
|
82
|
+
});
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const copied = await copySkillFromSource(skill, pluginDir, sourceResult);
|
|
86
|
+
copiedSkills.push(copied);
|
|
87
|
+
}
|
|
88
|
+
return copiedSkills;
|
|
89
|
+
}
|
|
90
|
+
function getFlattenedSkillDestPath(skill, localSkillsDir) {
|
|
91
|
+
const skillFolderName = skill.alias || extractSkillNameFromId(skill.id);
|
|
92
|
+
return path.join(localSkillsDir, skillFolderName);
|
|
93
|
+
}
|
|
94
|
+
function extractSkillNameFromId(skillId) {
|
|
95
|
+
const withoutAuthor = skillId.replace(/\s*\(@\w+\)$/, "").trim();
|
|
96
|
+
return withoutAuthor;
|
|
97
|
+
}
|
|
98
|
+
async function copySkillToLocalFlattened(skill, localSkillsDir, sourceResult) {
|
|
99
|
+
const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);
|
|
100
|
+
const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);
|
|
101
|
+
const contentHash = await generateSkillHash(sourcePath);
|
|
102
|
+
await ensureDir(path.dirname(destPath));
|
|
103
|
+
await copy(sourcePath, destPath);
|
|
104
|
+
await injectForkedFromMetadata(destPath, skill.id, contentHash);
|
|
105
|
+
return {
|
|
106
|
+
skillId: skill.id,
|
|
107
|
+
contentHash,
|
|
108
|
+
sourcePath,
|
|
109
|
+
destPath
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function copySkillsToLocalFlattened(selectedSkillIds, localSkillsDir, matrix, sourceResult) {
|
|
113
|
+
const copiedSkills = [];
|
|
114
|
+
for (const skillId of selectedSkillIds) {
|
|
115
|
+
const skill = matrix.skills[skillId];
|
|
116
|
+
if (!skill) {
|
|
117
|
+
console.warn(`Warning: Skill not found in matrix: ${skillId}`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (skill.local && skill.localPath) {
|
|
121
|
+
const localSkillPath = path.join(process.cwd(), skill.localPath);
|
|
122
|
+
const contentHash = await generateSkillHash(localSkillPath);
|
|
123
|
+
copiedSkills.push({
|
|
124
|
+
skillId: skill.id,
|
|
125
|
+
sourcePath: skill.localPath,
|
|
126
|
+
destPath: skill.localPath,
|
|
127
|
+
contentHash,
|
|
128
|
+
local: true
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const copied = await copySkillToLocalFlattened(
|
|
133
|
+
skill,
|
|
134
|
+
localSkillsDir,
|
|
135
|
+
sourceResult
|
|
136
|
+
);
|
|
137
|
+
copiedSkills.push(copied);
|
|
138
|
+
}
|
|
139
|
+
return copiedSkills;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export {
|
|
143
|
+
copySkillsToPluginFromSource,
|
|
144
|
+
copySkillsToLocalFlattened
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=chunk-OSQDDJXX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/skill-copier.ts"],"sourcesContent":["import path from \"path\";\nimport { stringify as stringifyYaml, parse as parseYaml } from \"yaml\";\nimport { copy, ensureDir, readFile, writeFile } from \"../utils/fs\";\nimport { hashFile } from \"./versioning\";\nimport type { MergedSkillsMatrix, ResolvedSkill } from \"../types-matrix\";\nimport type { SourceLoadResult } from \"./source-loader\";\n\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\ninterface SkillMetadata {\n content_hash?: string;\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\nconst METADATA_FILE_NAME = \"metadata.yaml\";\n\nexport interface CopiedSkill {\n skillId: string;\n contentHash: string;\n sourcePath: string;\n destPath: string;\n local?: boolean;\n}\n\nfunction getSkillSourcePath(\n skill: ResolvedSkill,\n registryRoot: string,\n): string {\n return path.join(registryRoot, \"src\", skill.path);\n}\n\nfunction getSkillDestPath(skill: ResolvedSkill, stackDir: string): string {\n const skillRelativePath = skill.path.replace(/^skills\\//, \"\");\n return path.join(stackDir, \"skills\", skillRelativePath);\n}\n\nasync function generateSkillHash(skillSourcePath: string): Promise<string> {\n const skillMdPath = path.join(skillSourcePath, \"SKILL.md\");\n return hashFile(skillMdPath);\n}\n\nfunction getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\nasync function injectForkedFromMetadata(\n destPath: string,\n skillId: string,\n contentHash: string,\n): Promise<void> {\n const metadataPath = path.join(destPath, METADATA_FILE_NAME);\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as SkillMetadata;\n\n metadata.forked_from = {\n skill_id: skillId,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataPath, newYamlContent);\n}\n\nexport async function copySkill(\n skill: ResolvedSkill,\n stackDir: string,\n registryRoot: string,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePath(skill, registryRoot);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nfunction getSkillSourcePathFromSource(\n skill: ResolvedSkill,\n sourceResult: SourceLoadResult,\n): string {\n return path.join(sourceResult.sourcePath, \"src\", skill.path);\n}\n\nexport async function copySkillFromSource(\n skill: ResolvedSkill,\n stackDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport async function copySkillsToPluginFromSource(\n selectedSkillIds: string[],\n pluginDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n const copiedSkills: CopiedSkill[] = [];\n\n for (const skillId of selectedSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) {\n console.warn(`Warning: Skill not found in matrix: ${skillId}`);\n continue;\n }\n\n if (skill.local && skill.localPath) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n copiedSkills.push({\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n });\n continue;\n }\n\n const copied = await copySkillFromSource(skill, pluginDir, sourceResult);\n copiedSkills.push(copied);\n }\n\n return copiedSkills;\n}\n\nfunction getFlattenedSkillDestPath(\n skill: ResolvedSkill,\n localSkillsDir: string,\n): string {\n const skillFolderName = skill.alias || extractSkillNameFromId(skill.id);\n return path.join(localSkillsDir, skillFolderName);\n}\n\nfunction extractSkillNameFromId(skillId: string): string {\n const withoutAuthor = skillId.replace(/\\s*\\(@\\w+\\)$/, \"\").trim();\n return withoutAuthor;\n}\n\nasync function copySkillToLocalFlattened(\n skill: ResolvedSkill,\n localSkillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport async function copySkillsToLocalFlattened(\n selectedSkillIds: string[],\n localSkillsDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n const copiedSkills: CopiedSkill[] = [];\n\n for (const skillId of selectedSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) {\n console.warn(`Warning: Skill not found in matrix: ${skillId}`);\n continue;\n }\n\n if (skill.local && skill.localPath) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n copiedSkills.push({\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n });\n continue;\n }\n\n const copied = await copySkillToLocalFlattened(\n skill,\n localSkillsDir,\n sourceResult,\n );\n copiedSkills.push(copied);\n }\n\n return copiedSkills;\n}\n"],"mappings":"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","names":[]}
|