@agents-inc/cli 0.85.0 → 0.86.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 +10 -0
- package/dist/{chunk-6VGBO6SZ.js → chunk-5M6Q5UQO.js} +2 -2
- package/dist/{chunk-YJ2URWF7.js → chunk-B6MYECV6.js} +2 -2
- package/dist/{chunk-FT46LN7K.js → chunk-BV2MIQ3O.js} +7 -8
- package/dist/chunk-BV2MIQ3O.js.map +1 -0
- package/dist/{chunk-G2MINRWX.js → chunk-C5IYJ42F.js} +2 -2
- package/dist/{chunk-7UZUDHP7.js → chunk-CXWBVBDM.js} +2 -2
- package/dist/chunk-DCVCFBQ7.js +1800 -0
- package/dist/chunk-DCVCFBQ7.js.map +1 -0
- package/dist/{chunk-CYPCJ536.js → chunk-FBZR46GC.js} +92 -92
- package/dist/chunk-FBZR46GC.js.map +1 -0
- package/dist/{chunk-TXW257CU.js → chunk-GED2F75H.js} +90 -167
- package/dist/chunk-GED2F75H.js.map +1 -0
- package/dist/{chunk-LTFGEVTM.js → chunk-HH3AWXF4.js} +3 -3
- package/dist/{chunk-2XVLQDNI.js → chunk-HSLVCKVQ.js} +3 -3
- package/dist/{chunk-TAQGYJIS.js → chunk-HZ2IBXVQ.js} +3 -3
- package/dist/{chunk-LN76TJJP.js → chunk-HZQOFFKA.js} +10 -10
- package/dist/{chunk-W7LHI54P.js → chunk-I44YG6VI.js} +2 -2
- package/dist/{chunk-L7COG2EX.js → chunk-LZ7XQ3IU.js} +2 -2
- package/dist/{chunk-LMR7VAP3.js → chunk-MMTMXLI4.js} +2 -2
- package/dist/chunk-N6A7A4RA.js +16 -0
- package/dist/chunk-N6A7A4RA.js.map +1 -0
- package/dist/{chunk-WJKD6EGK.js → chunk-NUU3U43A.js} +5 -6
- package/dist/chunk-NUU3U43A.js.map +1 -0
- package/dist/chunk-O5ZWS26C.js +166 -0
- package/dist/chunk-O5ZWS26C.js.map +1 -0
- package/dist/{chunk-YYIWB42G.js → chunk-Q4DMIPZB.js} +2 -2
- package/dist/{chunk-YSLDMYWP.js → chunk-SGZOFIFF.js} +2 -2
- package/dist/{chunk-FKXD3EXJ.js → chunk-TMTUTUEV.js} +42 -228
- package/dist/chunk-TMTUTUEV.js.map +1 -0
- package/dist/{chunk-WCCWQ56J.js → chunk-UNEJKTLP.js} +3 -3
- package/dist/chunk-XQK4S22C.js +202 -0
- package/dist/chunk-XQK4S22C.js.map +1 -0
- package/dist/{chunk-ZGD7PLLC.js → chunk-ZOWRO7UQ.js} +3 -3
- package/dist/commands/build/marketplace.js +3 -3
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +63 -163
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/diff.js +27 -632
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +41 -28
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +128 -194
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +58 -126
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +15 -148
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +34 -85
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +23 -17
- package/dist/commands/list.js +4 -4
- package/dist/commands/new/agent.js +23 -97
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +9 -9
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +169 -20
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +18 -24
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +37 -100
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +39 -156
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +49 -99
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +4 -4
- package/dist/components/skill-search/skill-search.js +2 -1
- package/dist/components/wizard/category-grid.test.js +4 -4
- package/dist/components/wizard/domain-selection.js +5 -5
- package/dist/components/wizard/help-modal.js +5 -5
- package/dist/components/wizard/source-grid.test.js +4 -4
- package/dist/components/wizard/stack-selection.js +5 -5
- package/dist/components/wizard/step-agents.js +5 -5
- package/dist/components/wizard/step-agents.test.js +5 -5
- package/dist/components/wizard/step-build.js +5 -5
- package/dist/components/wizard/step-build.test.js +5 -5
- package/dist/components/wizard/step-confirm.test.js +4 -4
- package/dist/components/wizard/step-settings.js +4 -4
- package/dist/components/wizard/step-settings.test.js +7 -7
- package/dist/components/wizard/step-sources.js +5 -5
- package/dist/components/wizard/step-sources.test.js +5 -5
- package/dist/components/wizard/step-stack.js +6 -6
- package/dist/components/wizard/step-stack.test.js +6 -6
- package/dist/components/wizard/wizard-layout.js +6 -6
- package/dist/components/wizard/wizard.js +14 -14
- package/dist/hooks/init.js +21 -16
- package/dist/hooks/init.js.map +1 -1
- package/dist/{loader-GT2A7R7U.js → loader-GSEGPK64.js} +3 -3
- package/dist/{source-loader-TNQW4P47.js → source-loader-OGFTIRIX.js} +4 -4
- package/dist/{source-manager-INRXRFJE.js → source-manager-FMMDDVZA.js} +4 -4
- package/dist/stores/wizard-store.js +4 -4
- package/dist/stores/wizard-store.test.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-AABH2HSE.js +0 -340
- package/dist/chunk-AABH2HSE.js.map +0 -1
- package/dist/chunk-CYPCJ536.js.map +0 -1
- package/dist/chunk-FKXD3EXJ.js.map +0 -1
- package/dist/chunk-FT46LN7K.js.map +0 -1
- package/dist/chunk-TXW257CU.js.map +0 -1
- package/dist/chunk-WJKD6EGK.js.map +0 -1
- /package/dist/{chunk-6VGBO6SZ.js.map → chunk-5M6Q5UQO.js.map} +0 -0
- /package/dist/{chunk-YJ2URWF7.js.map → chunk-B6MYECV6.js.map} +0 -0
- /package/dist/{chunk-G2MINRWX.js.map → chunk-C5IYJ42F.js.map} +0 -0
- /package/dist/{chunk-7UZUDHP7.js.map → chunk-CXWBVBDM.js.map} +0 -0
- /package/dist/{chunk-LTFGEVTM.js.map → chunk-HH3AWXF4.js.map} +0 -0
- /package/dist/{chunk-2XVLQDNI.js.map → chunk-HSLVCKVQ.js.map} +0 -0
- /package/dist/{chunk-TAQGYJIS.js.map → chunk-HZ2IBXVQ.js.map} +0 -0
- /package/dist/{chunk-LN76TJJP.js.map → chunk-HZQOFFKA.js.map} +0 -0
- /package/dist/{chunk-W7LHI54P.js.map → chunk-I44YG6VI.js.map} +0 -0
- /package/dist/{chunk-L7COG2EX.js.map → chunk-LZ7XQ3IU.js.map} +0 -0
- /package/dist/{chunk-LMR7VAP3.js.map → chunk-MMTMXLI4.js.map} +0 -0
- /package/dist/{chunk-YYIWB42G.js.map → chunk-Q4DMIPZB.js.map} +0 -0
- /package/dist/{chunk-YSLDMYWP.js.map → chunk-SGZOFIFF.js.map} +0 -0
- /package/dist/{chunk-WCCWQ56J.js.map → chunk-UNEJKTLP.js.map} +0 -0
- /package/dist/{chunk-ZGD7PLLC.js.map → chunk-ZOWRO7UQ.js.map} +0 -0
- /package/dist/{loader-GT2A7R7U.js.map → loader-GSEGPK64.js.map} +0 -0
- /package/dist/{source-loader-TNQW4P47.js.map → source-loader-OGFTIRIX.js.map} +0 -0
- /package/dist/{source-manager-INRXRFJE.js.map → source-manager-FMMDDVZA.js.map} +0 -0
|
@@ -0,0 +1,1800 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
truncateText
|
|
4
|
+
} from "./chunk-N6A7A4RA.js";
|
|
5
|
+
import {
|
|
6
|
+
getAgentDefinitions,
|
|
7
|
+
recompileAgents
|
|
8
|
+
} from "./chunk-FBZR46GC.js";
|
|
9
|
+
import {
|
|
10
|
+
buildAgentScopeMap,
|
|
11
|
+
buildAndMergeConfig,
|
|
12
|
+
claudePluginInstall,
|
|
13
|
+
claudePluginMarketplaceAdd,
|
|
14
|
+
claudePluginMarketplaceExists,
|
|
15
|
+
claudePluginMarketplaceUpdate,
|
|
16
|
+
claudePluginUninstall,
|
|
17
|
+
compareLocalSkillsWithSource,
|
|
18
|
+
copySkillsToLocalFlattened,
|
|
19
|
+
deriveInstallMode,
|
|
20
|
+
detectGlobalInstallation,
|
|
21
|
+
detectInstallation,
|
|
22
|
+
detectProjectInstallation,
|
|
23
|
+
discoverAllPluginSkills,
|
|
24
|
+
discoverLocalSkills,
|
|
25
|
+
ensureBlankGlobalConfig,
|
|
26
|
+
fetchFromSource,
|
|
27
|
+
fetchMarketplace,
|
|
28
|
+
getInstallationInfo,
|
|
29
|
+
getProjectPluginsDir,
|
|
30
|
+
injectForkedFromMetadata,
|
|
31
|
+
isClaudeCLIAvailable,
|
|
32
|
+
listPluginNames,
|
|
33
|
+
loadProjectConfig,
|
|
34
|
+
loadProjectConfigFromDir,
|
|
35
|
+
loadProjectSourceConfig,
|
|
36
|
+
loadSkillsMatrixFromSource,
|
|
37
|
+
readForkedFromMetadata,
|
|
38
|
+
resolveInstallPaths,
|
|
39
|
+
resolveSource,
|
|
40
|
+
writeScopedConfigs
|
|
41
|
+
} from "./chunk-TMTUTUEV.js";
|
|
42
|
+
import {
|
|
43
|
+
loadAllAgents,
|
|
44
|
+
parseFrontmatter
|
|
45
|
+
} from "./chunk-B6MYECV6.js";
|
|
46
|
+
import {
|
|
47
|
+
typedEntries,
|
|
48
|
+
typedKeys
|
|
49
|
+
} from "./chunk-ANXHMG32.js";
|
|
50
|
+
import {
|
|
51
|
+
copy,
|
|
52
|
+
directoryExists,
|
|
53
|
+
disableBuffering,
|
|
54
|
+
drainBuffer,
|
|
55
|
+
enableBuffering,
|
|
56
|
+
ensureDir,
|
|
57
|
+
fileExists,
|
|
58
|
+
getErrorMessage,
|
|
59
|
+
glob,
|
|
60
|
+
listDirectories,
|
|
61
|
+
readFile,
|
|
62
|
+
remove,
|
|
63
|
+
verbose,
|
|
64
|
+
warn,
|
|
65
|
+
writeFile
|
|
66
|
+
} from "./chunk-NUU3U43A.js";
|
|
67
|
+
import {
|
|
68
|
+
CLAUDE_DIR,
|
|
69
|
+
CLAUDE_SRC_DIR,
|
|
70
|
+
DEFAULT_SKILLS_SUBDIR,
|
|
71
|
+
DIRS,
|
|
72
|
+
GLOBAL_INSTALL_ROOT,
|
|
73
|
+
LOCAL_SKILLS_PATH,
|
|
74
|
+
PROJECT_ROOT,
|
|
75
|
+
STANDARD_FILES
|
|
76
|
+
} from "./chunk-6PGL2XMY.js";
|
|
77
|
+
import {
|
|
78
|
+
init_esm_shims
|
|
79
|
+
} from "./chunk-DHET7RCE.js";
|
|
80
|
+
|
|
81
|
+
// src/cli/lib/operations/detect-both-installations.ts
|
|
82
|
+
init_esm_shims();
|
|
83
|
+
import os from "os";
|
|
84
|
+
async function detectBothInstallations(projectDir) {
|
|
85
|
+
const global = await detectGlobalInstallation();
|
|
86
|
+
const project = projectDir === os.homedir() ? null : await detectProjectInstallation(projectDir);
|
|
87
|
+
return { global, project, hasBoth: !!global && !!project };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/cli/lib/operations/load-source.ts
|
|
91
|
+
init_esm_shims();
|
|
92
|
+
async function loadSource(options) {
|
|
93
|
+
const { sourceFlag, projectDir, forceRefresh, captureStartupMessages } = options;
|
|
94
|
+
if (captureStartupMessages) {
|
|
95
|
+
enableBuffering();
|
|
96
|
+
}
|
|
97
|
+
let sourceResult;
|
|
98
|
+
try {
|
|
99
|
+
sourceResult = await loadSkillsMatrixFromSource({
|
|
100
|
+
sourceFlag,
|
|
101
|
+
projectDir,
|
|
102
|
+
forceRefresh
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (captureStartupMessages) {
|
|
106
|
+
disableBuffering();
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
let startupMessages = [];
|
|
111
|
+
if (captureStartupMessages) {
|
|
112
|
+
startupMessages = drainBuffer();
|
|
113
|
+
disableBuffering();
|
|
114
|
+
}
|
|
115
|
+
return { sourceResult, startupMessages };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/cli/lib/operations/get-dashboard-data.ts
|
|
119
|
+
init_esm_shims();
|
|
120
|
+
async function getDashboardData(projectDir) {
|
|
121
|
+
const [info, loaded] = await Promise.all([getInstallationInfo(), loadProjectConfig(projectDir)]);
|
|
122
|
+
const skillCount = loaded?.config?.skills?.length ?? 0;
|
|
123
|
+
const agentCount = info?.agentCount ?? 0;
|
|
124
|
+
const mode = info?.mode ?? (loaded?.config?.skills ? deriveInstallMode(loaded.config.skills) : "local");
|
|
125
|
+
const source = loaded?.config?.source;
|
|
126
|
+
return { skillCount, agentCount, mode, source };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/cli/lib/operations/detect-project.ts
|
|
130
|
+
init_esm_shims();
|
|
131
|
+
async function detectProject(projectDir) {
|
|
132
|
+
const resolvedDir = projectDir ?? process.cwd();
|
|
133
|
+
const installation = await detectInstallation(resolvedDir);
|
|
134
|
+
if (!installation) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const loaded = await loadProjectConfig(installation.projectDir);
|
|
138
|
+
return {
|
|
139
|
+
installation,
|
|
140
|
+
config: loaded?.config ?? null,
|
|
141
|
+
configPath: loaded?.configPath ?? null
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/cli/lib/operations/load-agent-defs.ts
|
|
146
|
+
init_esm_shims();
|
|
147
|
+
async function loadAgentDefs(agentSource, options) {
|
|
148
|
+
const agentSourcePaths = await getAgentDefinitions(agentSource, options);
|
|
149
|
+
const cliAgents = await loadAllAgents(PROJECT_ROOT);
|
|
150
|
+
const sourceAgents = await loadAllAgents(agentSourcePaths.sourcePath);
|
|
151
|
+
const agents = { ...cliAgents, ...sourceAgents };
|
|
152
|
+
return {
|
|
153
|
+
agents,
|
|
154
|
+
sourcePath: agentSourcePaths.sourcePath,
|
|
155
|
+
agentSourcePaths
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/cli/lib/operations/copy-local-skills.ts
|
|
160
|
+
init_esm_shims();
|
|
161
|
+
async function copyLocalSkills(skills, projectDir, sourceResult) {
|
|
162
|
+
const projectLocalSkills = skills.filter((s) => s.scope !== "global");
|
|
163
|
+
const globalLocalSkills = skills.filter((s) => s.scope === "global");
|
|
164
|
+
const projectPaths = resolveInstallPaths(projectDir, "project");
|
|
165
|
+
const globalPaths = resolveInstallPaths(projectDir, "global");
|
|
166
|
+
let projectCopied = [];
|
|
167
|
+
if (projectLocalSkills.length > 0) {
|
|
168
|
+
await ensureDir(projectPaths.skillsDir);
|
|
169
|
+
projectCopied = await copySkillsToLocalFlattened(
|
|
170
|
+
projectLocalSkills.map((s) => s.id),
|
|
171
|
+
projectPaths.skillsDir,
|
|
172
|
+
sourceResult.matrix,
|
|
173
|
+
sourceResult
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
let globalCopied = [];
|
|
177
|
+
if (globalLocalSkills.length > 0) {
|
|
178
|
+
await ensureDir(globalPaths.skillsDir);
|
|
179
|
+
globalCopied = await copySkillsToLocalFlattened(
|
|
180
|
+
globalLocalSkills.map((s) => s.id),
|
|
181
|
+
globalPaths.skillsDir,
|
|
182
|
+
sourceResult.matrix,
|
|
183
|
+
sourceResult
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
projectCopied,
|
|
188
|
+
globalCopied,
|
|
189
|
+
totalCopied: projectCopied.length + globalCopied.length
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/cli/lib/operations/install-plugin-skills.ts
|
|
194
|
+
init_esm_shims();
|
|
195
|
+
async function installPluginSkills(skills, marketplace, projectDir) {
|
|
196
|
+
const pluginSkills = skills.filter((s) => s.source !== "local");
|
|
197
|
+
const installed = [];
|
|
198
|
+
const failed = [];
|
|
199
|
+
for (const skill of pluginSkills) {
|
|
200
|
+
const pluginRef = `${skill.id}@${marketplace}`;
|
|
201
|
+
const pluginScope = skill.scope === "global" ? "user" : "project";
|
|
202
|
+
try {
|
|
203
|
+
await claudePluginInstall(pluginRef, pluginScope, projectDir);
|
|
204
|
+
installed.push({ id: skill.id, ref: pluginRef });
|
|
205
|
+
} catch (error) {
|
|
206
|
+
failed.push({ id: skill.id, error: getErrorMessage(error) });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return { installed, failed };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/cli/lib/operations/uninstall-plugin-skills.ts
|
|
213
|
+
init_esm_shims();
|
|
214
|
+
async function uninstallPluginSkills(skillIds, oldSkills, projectDir) {
|
|
215
|
+
const uninstalled = [];
|
|
216
|
+
const failed = [];
|
|
217
|
+
for (const skillId of skillIds) {
|
|
218
|
+
const oldSkill = oldSkills.find((s) => s.id === skillId);
|
|
219
|
+
const pluginScope = oldSkill?.scope === "global" ? "user" : "project";
|
|
220
|
+
try {
|
|
221
|
+
await claudePluginUninstall(skillId, pluginScope, projectDir);
|
|
222
|
+
uninstalled.push(skillId);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
failed.push({ id: skillId, error: getErrorMessage(error) });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return { uninstalled, failed };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/cli/lib/operations/collect-scoped-skill-dirs.ts
|
|
231
|
+
init_esm_shims();
|
|
232
|
+
import os2 from "os";
|
|
233
|
+
import path from "path";
|
|
234
|
+
async function collectScopedSkillDirs(projectDir) {
|
|
235
|
+
const homeDir = os2.homedir();
|
|
236
|
+
const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);
|
|
237
|
+
const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);
|
|
238
|
+
const hasProject = await fileExists(projectLocalPath);
|
|
239
|
+
const hasGlobal = projectDir !== homeDir && await fileExists(globalLocalPath);
|
|
240
|
+
const dirs = [];
|
|
241
|
+
if (hasProject) {
|
|
242
|
+
for (const dirName of await listDirectories(projectLocalPath)) {
|
|
243
|
+
dirs.push({ dirName, localSkillsPath: projectLocalPath, scope: "project" });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (hasGlobal) {
|
|
247
|
+
const projectDirNames = new Set(dirs.map((d) => d.dirName));
|
|
248
|
+
for (const dirName of await listDirectories(globalLocalPath)) {
|
|
249
|
+
if (!projectDirNames.has(dirName)) {
|
|
250
|
+
dirs.push({ dirName, localSkillsPath: globalLocalPath, scope: "global" });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return { dirs, hasProject, hasGlobal, projectLocalPath, globalLocalPath };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/cli/lib/operations/compare-skills.ts
|
|
258
|
+
init_esm_shims();
|
|
259
|
+
import os3 from "os";
|
|
260
|
+
function buildSourceSkillsMap(matrix) {
|
|
261
|
+
const sourceSkills = {};
|
|
262
|
+
for (const [skillId, skill] of typedEntries(matrix.skills)) {
|
|
263
|
+
if (!skill) continue;
|
|
264
|
+
if (!skill.local) {
|
|
265
|
+
sourceSkills[skillId] = { path: skill.path };
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return sourceSkills;
|
|
269
|
+
}
|
|
270
|
+
async function compareSkillsWithSource(projectDir, sourcePath, matrix) {
|
|
271
|
+
const sourceSkills = buildSourceSkillsMap(matrix);
|
|
272
|
+
const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);
|
|
273
|
+
const homeDir = os3.homedir();
|
|
274
|
+
const projectResults = hasProject ? await compareLocalSkillsWithSource(projectDir, sourcePath, sourceSkills) : [];
|
|
275
|
+
const globalResults = hasGlobal ? await compareLocalSkillsWithSource(homeDir, sourcePath, sourceSkills) : [];
|
|
276
|
+
const seenIds = new Set(projectResults.map((r) => r.id));
|
|
277
|
+
const merged = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];
|
|
278
|
+
return { projectResults, globalResults, merged };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/cli/lib/operations/ensure-marketplace.ts
|
|
282
|
+
init_esm_shims();
|
|
283
|
+
async function ensureMarketplace(sourceResult) {
|
|
284
|
+
if (!sourceResult.marketplace) {
|
|
285
|
+
try {
|
|
286
|
+
const marketplaceResult = await fetchMarketplace(sourceResult.sourceConfig.source, {});
|
|
287
|
+
sourceResult.marketplace = marketplaceResult.marketplace.name;
|
|
288
|
+
} catch {
|
|
289
|
+
return { marketplace: null, registered: false };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const marketplace = sourceResult.marketplace;
|
|
293
|
+
const exists = await claudePluginMarketplaceExists(marketplace);
|
|
294
|
+
if (!exists) {
|
|
295
|
+
const marketplaceSource = sourceResult.sourceConfig.source.replace(/^github:/, "");
|
|
296
|
+
await claudePluginMarketplaceAdd(marketplaceSource);
|
|
297
|
+
return { marketplace, registered: true };
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
await claudePluginMarketplaceUpdate(marketplace);
|
|
301
|
+
} catch {
|
|
302
|
+
warn("Could not update marketplace \u2014 continuing with cached version");
|
|
303
|
+
}
|
|
304
|
+
return { marketplace, registered: false };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/cli/lib/operations/write-project-config.ts
|
|
308
|
+
init_esm_shims();
|
|
309
|
+
import fs from "fs";
|
|
310
|
+
import os4 from "os";
|
|
311
|
+
import path2 from "path";
|
|
312
|
+
async function writeProjectConfig(options) {
|
|
313
|
+
const { wizardResult, sourceResult, projectDir, sourceFlag } = options;
|
|
314
|
+
const projectPaths = resolveInstallPaths(projectDir, "project");
|
|
315
|
+
await ensureDir(path2.dirname(projectPaths.configPath));
|
|
316
|
+
let agents;
|
|
317
|
+
if (options.agents) {
|
|
318
|
+
agents = options.agents;
|
|
319
|
+
} else {
|
|
320
|
+
const cliAgents = await loadAllAgents(PROJECT_ROOT);
|
|
321
|
+
const sourceAgents = await loadAllAgents(sourceResult.sourcePath);
|
|
322
|
+
agents = { ...cliAgents, ...sourceAgents };
|
|
323
|
+
}
|
|
324
|
+
const mergeResult = await buildAndMergeConfig(wizardResult, sourceResult, projectDir, sourceFlag);
|
|
325
|
+
const finalConfig = mergeResult.config;
|
|
326
|
+
const isProjectContext = fs.realpathSync(projectDir) !== fs.realpathSync(os4.homedir());
|
|
327
|
+
if (isProjectContext) {
|
|
328
|
+
await ensureBlankGlobalConfig();
|
|
329
|
+
}
|
|
330
|
+
await writeScopedConfigs(
|
|
331
|
+
finalConfig,
|
|
332
|
+
sourceResult.matrix,
|
|
333
|
+
agents,
|
|
334
|
+
projectDir,
|
|
335
|
+
projectPaths.configPath,
|
|
336
|
+
isProjectContext
|
|
337
|
+
);
|
|
338
|
+
return {
|
|
339
|
+
config: finalConfig,
|
|
340
|
+
configPath: projectPaths.configPath,
|
|
341
|
+
wasMerged: mergeResult.merged,
|
|
342
|
+
existingConfigPath: mergeResult.existingConfigPath,
|
|
343
|
+
filesWritten: isProjectContext ? 4 : 2
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/cli/lib/operations/compile-agents.ts
|
|
348
|
+
init_esm_shims();
|
|
349
|
+
async function compileAgents(options) {
|
|
350
|
+
let resolvedAgents = options.agents;
|
|
351
|
+
let resolvedAgentScopeMap = options.agentScopeMap;
|
|
352
|
+
if (options.scopeFilter) {
|
|
353
|
+
const loadedConfig = await loadProjectConfigFromDir(options.projectDir);
|
|
354
|
+
if (!resolvedAgentScopeMap && loadedConfig?.config) {
|
|
355
|
+
resolvedAgentScopeMap = buildAgentScopeMap(loadedConfig.config);
|
|
356
|
+
}
|
|
357
|
+
const filteredAgents = loadedConfig?.config?.agents?.filter((a) => a.scope === options.scopeFilter).map((a) => a.name);
|
|
358
|
+
if (resolvedAgents && filteredAgents) {
|
|
359
|
+
const filterSet = new Set(filteredAgents);
|
|
360
|
+
resolvedAgents = resolvedAgents.filter((a) => filterSet.has(a));
|
|
361
|
+
} else if (filteredAgents) {
|
|
362
|
+
resolvedAgents = filteredAgents;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const recompileResult = await recompileAgents({
|
|
366
|
+
pluginDir: options.pluginDir ?? options.projectDir,
|
|
367
|
+
sourcePath: options.sourcePath,
|
|
368
|
+
agents: resolvedAgents,
|
|
369
|
+
skills: options.skills,
|
|
370
|
+
projectDir: options.projectDir,
|
|
371
|
+
outputDir: options.outputDir,
|
|
372
|
+
installMode: options.installMode,
|
|
373
|
+
agentScopeMap: resolvedAgentScopeMap
|
|
374
|
+
});
|
|
375
|
+
return {
|
|
376
|
+
compiled: recompileResult.compiled,
|
|
377
|
+
failed: recompileResult.failed,
|
|
378
|
+
warnings: recompileResult.warnings
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/cli/lib/operations/detect-config-changes.ts
|
|
383
|
+
init_esm_shims();
|
|
384
|
+
function detectConfigChanges(oldConfig, wizardResult, currentSkillIds) {
|
|
385
|
+
const newSkillIds = wizardResult.skills.map((s) => s.id);
|
|
386
|
+
const addedSkills = newSkillIds.filter((id) => !currentSkillIds.includes(id));
|
|
387
|
+
const removedSkills = currentSkillIds.filter((id) => !newSkillIds.includes(id));
|
|
388
|
+
const oldAgentNames = oldConfig?.agents?.map((a) => a.name) ?? [];
|
|
389
|
+
const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);
|
|
390
|
+
const addedAgents = newAgentNames.filter((name) => !oldAgentNames.includes(name));
|
|
391
|
+
const removedAgents = oldAgentNames.filter((name) => !newAgentNames.includes(name));
|
|
392
|
+
const sourceChanges = /* @__PURE__ */ new Map();
|
|
393
|
+
const scopeChanges = /* @__PURE__ */ new Map();
|
|
394
|
+
if (oldConfig?.skills) {
|
|
395
|
+
for (const newSkill of wizardResult.skills) {
|
|
396
|
+
const oldSkill = oldConfig.skills.find((s) => s.id === newSkill.id);
|
|
397
|
+
if (oldSkill && oldSkill.source !== newSkill.source) {
|
|
398
|
+
sourceChanges.set(newSkill.id, {
|
|
399
|
+
from: oldSkill.source,
|
|
400
|
+
to: newSkill.source
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
if (oldSkill && oldSkill.scope !== newSkill.scope) {
|
|
404
|
+
scopeChanges.set(newSkill.id, {
|
|
405
|
+
from: oldSkill.scope,
|
|
406
|
+
to: newSkill.scope
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const agentScopeChanges = /* @__PURE__ */ new Map();
|
|
412
|
+
if (oldConfig?.agents) {
|
|
413
|
+
for (const newAgent of wizardResult.agentConfigs) {
|
|
414
|
+
const oldAgent = oldConfig.agents.find((a) => a.name === newAgent.name);
|
|
415
|
+
if (oldAgent && oldAgent.scope !== newAgent.scope) {
|
|
416
|
+
agentScopeChanges.set(newAgent.name, {
|
|
417
|
+
from: oldAgent.scope,
|
|
418
|
+
to: newAgent.scope
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
addedSkills,
|
|
425
|
+
removedSkills,
|
|
426
|
+
addedAgents,
|
|
427
|
+
removedAgents,
|
|
428
|
+
sourceChanges,
|
|
429
|
+
scopeChanges,
|
|
430
|
+
agentScopeChanges
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// src/cli/lib/operations/update-local-skills.ts
|
|
435
|
+
init_esm_shims();
|
|
436
|
+
import path3 from "path";
|
|
437
|
+
async function updateLocalSkills(options) {
|
|
438
|
+
const { skills, sourceResult, skillBaseDir, onProgress } = options;
|
|
439
|
+
const updated = [];
|
|
440
|
+
const failed = [];
|
|
441
|
+
for (const skill of skills) {
|
|
442
|
+
onProgress?.(skill.id);
|
|
443
|
+
if (!skill.sourcePath || !skill.sourceHash) {
|
|
444
|
+
failed.push({
|
|
445
|
+
id: skill.id,
|
|
446
|
+
success: false,
|
|
447
|
+
newHash: null,
|
|
448
|
+
error: "No source path available"
|
|
449
|
+
});
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
const baseDir = skillBaseDir.get(skill.id) ?? process.cwd();
|
|
453
|
+
const localSkillsPath = path3.join(baseDir, LOCAL_SKILLS_PATH);
|
|
454
|
+
const destPath = path3.join(localSkillsPath, skill.dirName);
|
|
455
|
+
const srcPath = path3.join(sourceResult.sourcePath, "src", skill.sourcePath);
|
|
456
|
+
try {
|
|
457
|
+
await copy(srcPath, destPath);
|
|
458
|
+
await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);
|
|
459
|
+
updated.push({ id: skill.id, success: true, newHash: skill.sourceHash });
|
|
460
|
+
} catch (error) {
|
|
461
|
+
failed.push({ id: skill.id, success: false, newHash: null, error: getErrorMessage(error) });
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
updated,
|
|
466
|
+
failed,
|
|
467
|
+
totalUpdated: updated.length,
|
|
468
|
+
totalFailed: failed.length
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/cli/lib/operations/discover-skills.ts
|
|
473
|
+
init_esm_shims();
|
|
474
|
+
import os5 from "os";
|
|
475
|
+
import path4 from "path";
|
|
476
|
+
async function loadSkillsFromDir(skillsDir, pathPrefix = "") {
|
|
477
|
+
const skills = {};
|
|
478
|
+
if (!await directoryExists(skillsDir)) {
|
|
479
|
+
return skills;
|
|
480
|
+
}
|
|
481
|
+
const skillFiles = await glob("**/SKILL.md", skillsDir);
|
|
482
|
+
for (const skillFile of skillFiles) {
|
|
483
|
+
const skillPath = path4.join(skillsDir, skillFile);
|
|
484
|
+
const skillDir = path4.dirname(skillPath);
|
|
485
|
+
const relativePath = path4.relative(skillsDir, skillDir);
|
|
486
|
+
const skillDirName = path4.basename(skillDir);
|
|
487
|
+
const metadataPath = path4.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
488
|
+
if (!await fileExists(metadataPath)) {
|
|
489
|
+
const displayPath = pathPrefix ? `${pathPrefix}/${relativePath}/` : `${relativePath}/`;
|
|
490
|
+
warn(
|
|
491
|
+
`Skill '${skillDirName}' in '${displayPath}' is missing ${STANDARD_FILES.METADATA_YAML} \u2014 skipped. Add ${STANDARD_FILES.METADATA_YAML} to register it with the CLI.`
|
|
492
|
+
);
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
const content = await readFile(skillPath);
|
|
497
|
+
const frontmatter = parseFrontmatter(content, skillPath);
|
|
498
|
+
if (!frontmatter?.name) {
|
|
499
|
+
warn(`Skipping skill in '${skillDirName}': missing or invalid frontmatter name`);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
const canonicalId = frontmatter.name;
|
|
503
|
+
const skill = {
|
|
504
|
+
id: canonicalId,
|
|
505
|
+
path: pathPrefix ? `${pathPrefix}/${relativePath}/` : `${relativePath}/`,
|
|
506
|
+
description: frontmatter?.description || ""
|
|
507
|
+
};
|
|
508
|
+
skills[canonicalId] = skill;
|
|
509
|
+
verbose(` Loaded skill: ${canonicalId}`);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
verbose(` Failed to load skill: ${skillFile} - ${error}`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return skills;
|
|
515
|
+
}
|
|
516
|
+
async function discoverLocalProjectSkills(projectDir) {
|
|
517
|
+
const localSkillsDir = path4.join(projectDir, LOCAL_SKILLS_PATH);
|
|
518
|
+
return loadSkillsFromDir(localSkillsDir, LOCAL_SKILLS_PATH);
|
|
519
|
+
}
|
|
520
|
+
function mergeSkills(...skillSources) {
|
|
521
|
+
const merged = {};
|
|
522
|
+
for (const source of skillSources) {
|
|
523
|
+
for (const [id, skill] of typedEntries(source)) {
|
|
524
|
+
if (skill) {
|
|
525
|
+
merged[id] = skill;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return merged;
|
|
530
|
+
}
|
|
531
|
+
async function discoverInstalledSkills(projectDir) {
|
|
532
|
+
const isGlobalProject = projectDir === os5.homedir();
|
|
533
|
+
const globalPluginSkills = isGlobalProject ? {} : await discoverAllPluginSkills(os5.homedir());
|
|
534
|
+
const globalPluginSkillCount = typedKeys(globalPluginSkills).length;
|
|
535
|
+
if (globalPluginSkillCount > 0) {
|
|
536
|
+
verbose(` Found ${globalPluginSkillCount} skills from global plugins`);
|
|
537
|
+
}
|
|
538
|
+
const globalLocalSkillsDir = path4.join(GLOBAL_INSTALL_ROOT, LOCAL_SKILLS_PATH);
|
|
539
|
+
const globalLocalSkills = isGlobalProject ? {} : await loadSkillsFromDir(globalLocalSkillsDir, LOCAL_SKILLS_PATH);
|
|
540
|
+
const globalLocalSkillCount = typedKeys(globalLocalSkills).length;
|
|
541
|
+
if (globalLocalSkillCount > 0) {
|
|
542
|
+
verbose(` Found ${globalLocalSkillCount} global local skills from ~/.claude/skills/`);
|
|
543
|
+
}
|
|
544
|
+
const pluginSkills = await discoverAllPluginSkills(projectDir);
|
|
545
|
+
const pluginSkillCount = typedKeys(pluginSkills).length;
|
|
546
|
+
verbose(` Found ${pluginSkillCount} skills from installed plugins`);
|
|
547
|
+
const localSkills = await discoverLocalProjectSkills(projectDir);
|
|
548
|
+
const localSkillCount = typedKeys(localSkills).length;
|
|
549
|
+
verbose(` Found ${localSkillCount} local skills from .claude/skills/`);
|
|
550
|
+
const allSkills = mergeSkills(globalPluginSkills, globalLocalSkills, pluginSkills, localSkills);
|
|
551
|
+
const totalSkillCount = typedKeys(allSkills).length;
|
|
552
|
+
return {
|
|
553
|
+
allSkills,
|
|
554
|
+
totalSkillCount,
|
|
555
|
+
pluginSkillCount: globalPluginSkillCount + pluginSkillCount,
|
|
556
|
+
localSkillCount: globalLocalSkillCount + localSkillCount,
|
|
557
|
+
globalPluginSkillCount,
|
|
558
|
+
globalLocalSkillCount
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// src/cli/lib/operations/find-skill-match.ts
|
|
563
|
+
init_esm_shims();
|
|
564
|
+
function findSkillMatch(skillName, results) {
|
|
565
|
+
const exact = results.find((r) => r.id === skillName);
|
|
566
|
+
if (exact) return { match: exact, similar: [] };
|
|
567
|
+
const partial = results.find((r) => {
|
|
568
|
+
const nameWithoutAuthor = r.id.replace(/\s*\(@\w+\)$/, "").toLowerCase();
|
|
569
|
+
return nameWithoutAuthor === skillName.toLowerCase();
|
|
570
|
+
});
|
|
571
|
+
if (partial) return { match: partial, similar: [] };
|
|
572
|
+
const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());
|
|
573
|
+
if (byDir) return { match: byDir, similar: [] };
|
|
574
|
+
const lowered = skillName.toLowerCase();
|
|
575
|
+
const similar = results.filter((r) => {
|
|
576
|
+
const name = r.id.toLowerCase();
|
|
577
|
+
const dir = r.dirName.toLowerCase();
|
|
578
|
+
return name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(" ")[0]);
|
|
579
|
+
}).map((r) => r.id).slice(0, 3);
|
|
580
|
+
return { match: null, similar };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// node_modules/chalk/source/index.js
|
|
584
|
+
init_esm_shims();
|
|
585
|
+
|
|
586
|
+
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
587
|
+
init_esm_shims();
|
|
588
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
589
|
+
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
590
|
+
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
591
|
+
var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
|
|
592
|
+
var styles = {
|
|
593
|
+
modifier: {
|
|
594
|
+
reset: [0, 0],
|
|
595
|
+
// 21 isn't widely supported and 22 does the same thing
|
|
596
|
+
bold: [1, 22],
|
|
597
|
+
dim: [2, 22],
|
|
598
|
+
italic: [3, 23],
|
|
599
|
+
underline: [4, 24],
|
|
600
|
+
overline: [53, 55],
|
|
601
|
+
inverse: [7, 27],
|
|
602
|
+
hidden: [8, 28],
|
|
603
|
+
strikethrough: [9, 29]
|
|
604
|
+
},
|
|
605
|
+
color: {
|
|
606
|
+
black: [30, 39],
|
|
607
|
+
red: [31, 39],
|
|
608
|
+
green: [32, 39],
|
|
609
|
+
yellow: [33, 39],
|
|
610
|
+
blue: [34, 39],
|
|
611
|
+
magenta: [35, 39],
|
|
612
|
+
cyan: [36, 39],
|
|
613
|
+
white: [37, 39],
|
|
614
|
+
// Bright color
|
|
615
|
+
blackBright: [90, 39],
|
|
616
|
+
gray: [90, 39],
|
|
617
|
+
// Alias of `blackBright`
|
|
618
|
+
grey: [90, 39],
|
|
619
|
+
// Alias of `blackBright`
|
|
620
|
+
redBright: [91, 39],
|
|
621
|
+
greenBright: [92, 39],
|
|
622
|
+
yellowBright: [93, 39],
|
|
623
|
+
blueBright: [94, 39],
|
|
624
|
+
magentaBright: [95, 39],
|
|
625
|
+
cyanBright: [96, 39],
|
|
626
|
+
whiteBright: [97, 39]
|
|
627
|
+
},
|
|
628
|
+
bgColor: {
|
|
629
|
+
bgBlack: [40, 49],
|
|
630
|
+
bgRed: [41, 49],
|
|
631
|
+
bgGreen: [42, 49],
|
|
632
|
+
bgYellow: [43, 49],
|
|
633
|
+
bgBlue: [44, 49],
|
|
634
|
+
bgMagenta: [45, 49],
|
|
635
|
+
bgCyan: [46, 49],
|
|
636
|
+
bgWhite: [47, 49],
|
|
637
|
+
// Bright color
|
|
638
|
+
bgBlackBright: [100, 49],
|
|
639
|
+
bgGray: [100, 49],
|
|
640
|
+
// Alias of `bgBlackBright`
|
|
641
|
+
bgGrey: [100, 49],
|
|
642
|
+
// Alias of `bgBlackBright`
|
|
643
|
+
bgRedBright: [101, 49],
|
|
644
|
+
bgGreenBright: [102, 49],
|
|
645
|
+
bgYellowBright: [103, 49],
|
|
646
|
+
bgBlueBright: [104, 49],
|
|
647
|
+
bgMagentaBright: [105, 49],
|
|
648
|
+
bgCyanBright: [106, 49],
|
|
649
|
+
bgWhiteBright: [107, 49]
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
653
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
654
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
655
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
656
|
+
function assembleStyles() {
|
|
657
|
+
const codes = /* @__PURE__ */ new Map();
|
|
658
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
659
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
660
|
+
styles[styleName] = {
|
|
661
|
+
open: `\x1B[${style[0]}m`,
|
|
662
|
+
close: `\x1B[${style[1]}m`
|
|
663
|
+
};
|
|
664
|
+
group[styleName] = styles[styleName];
|
|
665
|
+
codes.set(style[0], style[1]);
|
|
666
|
+
}
|
|
667
|
+
Object.defineProperty(styles, groupName, {
|
|
668
|
+
value: group,
|
|
669
|
+
enumerable: false
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
Object.defineProperty(styles, "codes", {
|
|
673
|
+
value: codes,
|
|
674
|
+
enumerable: false
|
|
675
|
+
});
|
|
676
|
+
styles.color.close = "\x1B[39m";
|
|
677
|
+
styles.bgColor.close = "\x1B[49m";
|
|
678
|
+
styles.color.ansi = wrapAnsi16();
|
|
679
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
680
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
681
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
682
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
683
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
684
|
+
Object.defineProperties(styles, {
|
|
685
|
+
rgbToAnsi256: {
|
|
686
|
+
value(red, green, blue) {
|
|
687
|
+
if (red === green && green === blue) {
|
|
688
|
+
if (red < 8) {
|
|
689
|
+
return 16;
|
|
690
|
+
}
|
|
691
|
+
if (red > 248) {
|
|
692
|
+
return 231;
|
|
693
|
+
}
|
|
694
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
695
|
+
}
|
|
696
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
697
|
+
},
|
|
698
|
+
enumerable: false
|
|
699
|
+
},
|
|
700
|
+
hexToRgb: {
|
|
701
|
+
value(hex) {
|
|
702
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
703
|
+
if (!matches) {
|
|
704
|
+
return [0, 0, 0];
|
|
705
|
+
}
|
|
706
|
+
let [colorString] = matches;
|
|
707
|
+
if (colorString.length === 3) {
|
|
708
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
709
|
+
}
|
|
710
|
+
const integer = Number.parseInt(colorString, 16);
|
|
711
|
+
return [
|
|
712
|
+
/* eslint-disable no-bitwise */
|
|
713
|
+
integer >> 16 & 255,
|
|
714
|
+
integer >> 8 & 255,
|
|
715
|
+
integer & 255
|
|
716
|
+
/* eslint-enable no-bitwise */
|
|
717
|
+
];
|
|
718
|
+
},
|
|
719
|
+
enumerable: false
|
|
720
|
+
},
|
|
721
|
+
hexToAnsi256: {
|
|
722
|
+
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
723
|
+
enumerable: false
|
|
724
|
+
},
|
|
725
|
+
ansi256ToAnsi: {
|
|
726
|
+
value(code) {
|
|
727
|
+
if (code < 8) {
|
|
728
|
+
return 30 + code;
|
|
729
|
+
}
|
|
730
|
+
if (code < 16) {
|
|
731
|
+
return 90 + (code - 8);
|
|
732
|
+
}
|
|
733
|
+
let red;
|
|
734
|
+
let green;
|
|
735
|
+
let blue;
|
|
736
|
+
if (code >= 232) {
|
|
737
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
738
|
+
green = red;
|
|
739
|
+
blue = red;
|
|
740
|
+
} else {
|
|
741
|
+
code -= 16;
|
|
742
|
+
const remainder = code % 36;
|
|
743
|
+
red = Math.floor(code / 36) / 5;
|
|
744
|
+
green = Math.floor(remainder / 6) / 5;
|
|
745
|
+
blue = remainder % 6 / 5;
|
|
746
|
+
}
|
|
747
|
+
const value = Math.max(red, green, blue) * 2;
|
|
748
|
+
if (value === 0) {
|
|
749
|
+
return 30;
|
|
750
|
+
}
|
|
751
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
752
|
+
if (value === 2) {
|
|
753
|
+
result += 60;
|
|
754
|
+
}
|
|
755
|
+
return result;
|
|
756
|
+
},
|
|
757
|
+
enumerable: false
|
|
758
|
+
},
|
|
759
|
+
rgbToAnsi: {
|
|
760
|
+
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
761
|
+
enumerable: false
|
|
762
|
+
},
|
|
763
|
+
hexToAnsi: {
|
|
764
|
+
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
765
|
+
enumerable: false
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
return styles;
|
|
769
|
+
}
|
|
770
|
+
var ansiStyles = assembleStyles();
|
|
771
|
+
var ansi_styles_default = ansiStyles;
|
|
772
|
+
|
|
773
|
+
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
774
|
+
init_esm_shims();
|
|
775
|
+
import process2 from "process";
|
|
776
|
+
import os6 from "os";
|
|
777
|
+
import tty from "tty";
|
|
778
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
779
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
780
|
+
const position = argv.indexOf(prefix + flag);
|
|
781
|
+
const terminatorPosition = argv.indexOf("--");
|
|
782
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
783
|
+
}
|
|
784
|
+
var { env } = process2;
|
|
785
|
+
var flagForceColor;
|
|
786
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
787
|
+
flagForceColor = 0;
|
|
788
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
789
|
+
flagForceColor = 1;
|
|
790
|
+
}
|
|
791
|
+
function envForceColor() {
|
|
792
|
+
if ("FORCE_COLOR" in env) {
|
|
793
|
+
if (env.FORCE_COLOR === "true") {
|
|
794
|
+
return 1;
|
|
795
|
+
}
|
|
796
|
+
if (env.FORCE_COLOR === "false") {
|
|
797
|
+
return 0;
|
|
798
|
+
}
|
|
799
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function translateLevel(level) {
|
|
803
|
+
if (level === 0) {
|
|
804
|
+
return false;
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
level,
|
|
808
|
+
hasBasic: true,
|
|
809
|
+
has256: level >= 2,
|
|
810
|
+
has16m: level >= 3
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
814
|
+
const noFlagForceColor = envForceColor();
|
|
815
|
+
if (noFlagForceColor !== void 0) {
|
|
816
|
+
flagForceColor = noFlagForceColor;
|
|
817
|
+
}
|
|
818
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
819
|
+
if (forceColor === 0) {
|
|
820
|
+
return 0;
|
|
821
|
+
}
|
|
822
|
+
if (sniffFlags) {
|
|
823
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
824
|
+
return 3;
|
|
825
|
+
}
|
|
826
|
+
if (hasFlag("color=256")) {
|
|
827
|
+
return 2;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
831
|
+
return 1;
|
|
832
|
+
}
|
|
833
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
834
|
+
return 0;
|
|
835
|
+
}
|
|
836
|
+
const min = forceColor || 0;
|
|
837
|
+
if (env.TERM === "dumb") {
|
|
838
|
+
return min;
|
|
839
|
+
}
|
|
840
|
+
if (process2.platform === "win32") {
|
|
841
|
+
const osRelease = os6.release().split(".");
|
|
842
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
843
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
844
|
+
}
|
|
845
|
+
return 1;
|
|
846
|
+
}
|
|
847
|
+
if ("CI" in env) {
|
|
848
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
|
|
849
|
+
return 3;
|
|
850
|
+
}
|
|
851
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
852
|
+
return 1;
|
|
853
|
+
}
|
|
854
|
+
return min;
|
|
855
|
+
}
|
|
856
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
857
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
858
|
+
}
|
|
859
|
+
if (env.COLORTERM === "truecolor") {
|
|
860
|
+
return 3;
|
|
861
|
+
}
|
|
862
|
+
if (env.TERM === "xterm-kitty") {
|
|
863
|
+
return 3;
|
|
864
|
+
}
|
|
865
|
+
if (env.TERM === "xterm-ghostty") {
|
|
866
|
+
return 3;
|
|
867
|
+
}
|
|
868
|
+
if (env.TERM === "wezterm") {
|
|
869
|
+
return 3;
|
|
870
|
+
}
|
|
871
|
+
if ("TERM_PROGRAM" in env) {
|
|
872
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
873
|
+
switch (env.TERM_PROGRAM) {
|
|
874
|
+
case "iTerm.app": {
|
|
875
|
+
return version >= 3 ? 3 : 2;
|
|
876
|
+
}
|
|
877
|
+
case "Apple_Terminal": {
|
|
878
|
+
return 2;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
883
|
+
return 2;
|
|
884
|
+
}
|
|
885
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
886
|
+
return 1;
|
|
887
|
+
}
|
|
888
|
+
if ("COLORTERM" in env) {
|
|
889
|
+
return 1;
|
|
890
|
+
}
|
|
891
|
+
return min;
|
|
892
|
+
}
|
|
893
|
+
function createSupportsColor(stream, options = {}) {
|
|
894
|
+
const level = _supportsColor(stream, {
|
|
895
|
+
streamIsTTY: stream && stream.isTTY,
|
|
896
|
+
...options
|
|
897
|
+
});
|
|
898
|
+
return translateLevel(level);
|
|
899
|
+
}
|
|
900
|
+
var supportsColor = {
|
|
901
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
902
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
903
|
+
};
|
|
904
|
+
var supports_color_default = supportsColor;
|
|
905
|
+
|
|
906
|
+
// node_modules/chalk/source/utilities.js
|
|
907
|
+
init_esm_shims();
|
|
908
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
909
|
+
let index = string.indexOf(substring);
|
|
910
|
+
if (index === -1) {
|
|
911
|
+
return string;
|
|
912
|
+
}
|
|
913
|
+
const substringLength = substring.length;
|
|
914
|
+
let endIndex = 0;
|
|
915
|
+
let returnValue = "";
|
|
916
|
+
do {
|
|
917
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
918
|
+
endIndex = index + substringLength;
|
|
919
|
+
index = string.indexOf(substring, endIndex);
|
|
920
|
+
} while (index !== -1);
|
|
921
|
+
returnValue += string.slice(endIndex);
|
|
922
|
+
return returnValue;
|
|
923
|
+
}
|
|
924
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
925
|
+
let endIndex = 0;
|
|
926
|
+
let returnValue = "";
|
|
927
|
+
do {
|
|
928
|
+
const gotCR = string[index - 1] === "\r";
|
|
929
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
930
|
+
endIndex = index + 1;
|
|
931
|
+
index = string.indexOf("\n", endIndex);
|
|
932
|
+
} while (index !== -1);
|
|
933
|
+
returnValue += string.slice(endIndex);
|
|
934
|
+
return returnValue;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// node_modules/chalk/source/index.js
|
|
938
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
939
|
+
var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
|
|
940
|
+
var STYLER = /* @__PURE__ */ Symbol("STYLER");
|
|
941
|
+
var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
|
|
942
|
+
var levelMapping = [
|
|
943
|
+
"ansi",
|
|
944
|
+
"ansi",
|
|
945
|
+
"ansi256",
|
|
946
|
+
"ansi16m"
|
|
947
|
+
];
|
|
948
|
+
var styles2 = /* @__PURE__ */ Object.create(null);
|
|
949
|
+
var applyOptions = (object, options = {}) => {
|
|
950
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
951
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
952
|
+
}
|
|
953
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
954
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
955
|
+
};
|
|
956
|
+
var chalkFactory = (options) => {
|
|
957
|
+
const chalk2 = (...strings) => strings.join(" ");
|
|
958
|
+
applyOptions(chalk2, options);
|
|
959
|
+
Object.setPrototypeOf(chalk2, createChalk.prototype);
|
|
960
|
+
return chalk2;
|
|
961
|
+
};
|
|
962
|
+
function createChalk(options) {
|
|
963
|
+
return chalkFactory(options);
|
|
964
|
+
}
|
|
965
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
966
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
967
|
+
styles2[styleName] = {
|
|
968
|
+
get() {
|
|
969
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
970
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
971
|
+
return builder;
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
styles2.visible = {
|
|
976
|
+
get() {
|
|
977
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
978
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
979
|
+
return builder;
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
983
|
+
if (model === "rgb") {
|
|
984
|
+
if (level === "ansi16m") {
|
|
985
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
986
|
+
}
|
|
987
|
+
if (level === "ansi256") {
|
|
988
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
989
|
+
}
|
|
990
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
991
|
+
}
|
|
992
|
+
if (model === "hex") {
|
|
993
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
994
|
+
}
|
|
995
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
996
|
+
};
|
|
997
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
998
|
+
for (const model of usedModels) {
|
|
999
|
+
styles2[model] = {
|
|
1000
|
+
get() {
|
|
1001
|
+
const { level } = this;
|
|
1002
|
+
return function(...arguments_) {
|
|
1003
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
1004
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
1009
|
+
styles2[bgModel] = {
|
|
1010
|
+
get() {
|
|
1011
|
+
const { level } = this;
|
|
1012
|
+
return function(...arguments_) {
|
|
1013
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
1014
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
var proto = Object.defineProperties(() => {
|
|
1020
|
+
}, {
|
|
1021
|
+
...styles2,
|
|
1022
|
+
level: {
|
|
1023
|
+
enumerable: true,
|
|
1024
|
+
get() {
|
|
1025
|
+
return this[GENERATOR].level;
|
|
1026
|
+
},
|
|
1027
|
+
set(level) {
|
|
1028
|
+
this[GENERATOR].level = level;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
var createStyler = (open, close, parent) => {
|
|
1033
|
+
let openAll;
|
|
1034
|
+
let closeAll;
|
|
1035
|
+
if (parent === void 0) {
|
|
1036
|
+
openAll = open;
|
|
1037
|
+
closeAll = close;
|
|
1038
|
+
} else {
|
|
1039
|
+
openAll = parent.openAll + open;
|
|
1040
|
+
closeAll = close + parent.closeAll;
|
|
1041
|
+
}
|
|
1042
|
+
return {
|
|
1043
|
+
open,
|
|
1044
|
+
close,
|
|
1045
|
+
openAll,
|
|
1046
|
+
closeAll,
|
|
1047
|
+
parent
|
|
1048
|
+
};
|
|
1049
|
+
};
|
|
1050
|
+
var createBuilder = (self, _styler, _isEmpty) => {
|
|
1051
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
1052
|
+
Object.setPrototypeOf(builder, proto);
|
|
1053
|
+
builder[GENERATOR] = self;
|
|
1054
|
+
builder[STYLER] = _styler;
|
|
1055
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
1056
|
+
return builder;
|
|
1057
|
+
};
|
|
1058
|
+
var applyStyle = (self, string) => {
|
|
1059
|
+
if (self.level <= 0 || !string) {
|
|
1060
|
+
return self[IS_EMPTY] ? "" : string;
|
|
1061
|
+
}
|
|
1062
|
+
let styler = self[STYLER];
|
|
1063
|
+
if (styler === void 0) {
|
|
1064
|
+
return string;
|
|
1065
|
+
}
|
|
1066
|
+
const { openAll, closeAll } = styler;
|
|
1067
|
+
if (string.includes("\x1B")) {
|
|
1068
|
+
while (styler !== void 0) {
|
|
1069
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
1070
|
+
styler = styler.parent;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
const lfIndex = string.indexOf("\n");
|
|
1074
|
+
if (lfIndex !== -1) {
|
|
1075
|
+
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
1076
|
+
}
|
|
1077
|
+
return openAll + string + closeAll;
|
|
1078
|
+
};
|
|
1079
|
+
Object.defineProperties(createChalk.prototype, styles2);
|
|
1080
|
+
var chalk = createChalk();
|
|
1081
|
+
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
1082
|
+
var source_default = chalk;
|
|
1083
|
+
|
|
1084
|
+
// src/cli/lib/operations/generate-skill-diff.ts
|
|
1085
|
+
init_esm_shims();
|
|
1086
|
+
import path5 from "path";
|
|
1087
|
+
import { createTwoFilesPatch } from "diff";
|
|
1088
|
+
async function generateSkillDiff(localSkillsPath, skillDirName, sourcePath, sourceSkills) {
|
|
1089
|
+
const skillDir = path5.join(localSkillsPath, skillDirName);
|
|
1090
|
+
const forkedFrom = await readForkedFromMetadata(skillDir);
|
|
1091
|
+
if (!forkedFrom) {
|
|
1092
|
+
return {
|
|
1093
|
+
skillDirName,
|
|
1094
|
+
forkedFrom: null,
|
|
1095
|
+
hasDiff: false,
|
|
1096
|
+
diffOutput: ""
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
const sourceSkill = sourceSkills[forkedFrom.skillId];
|
|
1100
|
+
if (!sourceSkill) {
|
|
1101
|
+
return {
|
|
1102
|
+
skillDirName,
|
|
1103
|
+
forkedFrom,
|
|
1104
|
+
hasDiff: false,
|
|
1105
|
+
diffOutput: `Source skill '${forkedFrom.skillId}' no longer exists`
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
const sourceSkillMdPath = path5.join(sourcePath, "src", sourceSkill.path, STANDARD_FILES.SKILL_MD);
|
|
1109
|
+
if (!await fileExists(sourceSkillMdPath)) {
|
|
1110
|
+
return {
|
|
1111
|
+
skillDirName,
|
|
1112
|
+
forkedFrom,
|
|
1113
|
+
hasDiff: false,
|
|
1114
|
+
diffOutput: `Source ${STANDARD_FILES.SKILL_MD} not found at ${sourceSkillMdPath}`
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
const sourceContent = await readFile(sourceSkillMdPath);
|
|
1118
|
+
const localSkillMdPath = path5.join(skillDir, STANDARD_FILES.SKILL_MD);
|
|
1119
|
+
if (!await fileExists(localSkillMdPath)) {
|
|
1120
|
+
return {
|
|
1121
|
+
skillDirName,
|
|
1122
|
+
forkedFrom,
|
|
1123
|
+
hasDiff: false,
|
|
1124
|
+
diffOutput: `Local ${STANDARD_FILES.SKILL_MD} not found at ${localSkillMdPath}`
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
const localContent = await readFile(localSkillMdPath);
|
|
1128
|
+
const sourceLabel = `source/${sourceSkill.path}/SKILL.md`;
|
|
1129
|
+
const localLabel = `local/${LOCAL_SKILLS_PATH}/${skillDirName}/SKILL.md`;
|
|
1130
|
+
const diff = createTwoFilesPatch(
|
|
1131
|
+
sourceLabel,
|
|
1132
|
+
localLabel,
|
|
1133
|
+
sourceContent,
|
|
1134
|
+
localContent,
|
|
1135
|
+
"",
|
|
1136
|
+
// No source header
|
|
1137
|
+
""
|
|
1138
|
+
// No local header
|
|
1139
|
+
);
|
|
1140
|
+
const hasDiff = diff.split("\n").some((line) => {
|
|
1141
|
+
return (line.startsWith("+") || line.startsWith("-")) && !line.startsWith("+++") && !line.startsWith("---");
|
|
1142
|
+
});
|
|
1143
|
+
return {
|
|
1144
|
+
skillDirName,
|
|
1145
|
+
forkedFrom,
|
|
1146
|
+
hasDiff,
|
|
1147
|
+
diffOutput: diff
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
function formatColoredDiff(diffText) {
|
|
1151
|
+
return diffText.split("\n").map((line) => {
|
|
1152
|
+
if (line.startsWith("+++") || line.startsWith("---")) {
|
|
1153
|
+
return source_default.bold(line);
|
|
1154
|
+
}
|
|
1155
|
+
if (line.startsWith("+")) {
|
|
1156
|
+
return source_default.green(line);
|
|
1157
|
+
}
|
|
1158
|
+
if (line.startsWith("-")) {
|
|
1159
|
+
return source_default.red(line);
|
|
1160
|
+
}
|
|
1161
|
+
if (line.startsWith("@@")) {
|
|
1162
|
+
return source_default.cyan(line);
|
|
1163
|
+
}
|
|
1164
|
+
return line;
|
|
1165
|
+
}).join("\n");
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// src/cli/lib/operations/resolve-skill-info.ts
|
|
1169
|
+
init_esm_shims();
|
|
1170
|
+
import path6 from "path";
|
|
1171
|
+
var CONTENT_PREVIEW_LINES = 10;
|
|
1172
|
+
var MAX_LINE_LENGTH = 80;
|
|
1173
|
+
var MAX_SUGGESTIONS = 5;
|
|
1174
|
+
function stripFrontmatter(content) {
|
|
1175
|
+
const lines = content.split("\n");
|
|
1176
|
+
let inFrontmatter = false;
|
|
1177
|
+
let frontmatterEndIndex = 0;
|
|
1178
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1179
|
+
const line = lines[i].trim();
|
|
1180
|
+
if (line === "---") {
|
|
1181
|
+
if (!inFrontmatter) {
|
|
1182
|
+
inFrontmatter = true;
|
|
1183
|
+
} else {
|
|
1184
|
+
frontmatterEndIndex = i + 1;
|
|
1185
|
+
break;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
return lines.slice(frontmatterEndIndex).join("\n");
|
|
1190
|
+
}
|
|
1191
|
+
function getPreviewLines(content, maxLines) {
|
|
1192
|
+
const body = stripFrontmatter(content);
|
|
1193
|
+
const lines = body.split("\n");
|
|
1194
|
+
const result = [];
|
|
1195
|
+
for (const line of lines) {
|
|
1196
|
+
if (result.length >= maxLines) break;
|
|
1197
|
+
if (line.trim() || result.length > 0) {
|
|
1198
|
+
result.push(truncateText(line, MAX_LINE_LENGTH));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
return result;
|
|
1202
|
+
}
|
|
1203
|
+
function findSuggestions(skills, query, maxSuggestions) {
|
|
1204
|
+
const lowerQuery = query.toLowerCase();
|
|
1205
|
+
const matches = [];
|
|
1206
|
+
for (const skill of Object.values(skills)) {
|
|
1207
|
+
if (!skill) continue;
|
|
1208
|
+
if (matches.length >= maxSuggestions) break;
|
|
1209
|
+
if (skill.id.toLowerCase().includes(lowerQuery) || skill.displayName.toLowerCase().includes(lowerQuery) || skill.slug.toLowerCase().includes(lowerQuery)) {
|
|
1210
|
+
matches.push(skill.id);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
return matches;
|
|
1214
|
+
}
|
|
1215
|
+
async function resolveSkillInfo(options) {
|
|
1216
|
+
const { query, skills, slugToId, projectDir, sourcePath, isLocal, includePreview } = options;
|
|
1217
|
+
const slugResolvedId = slugToId[query];
|
|
1218
|
+
const skill = skills[query] ?? (slugResolvedId ? skills[slugResolvedId] : void 0);
|
|
1219
|
+
if (!skill) {
|
|
1220
|
+
const suggestions = findSuggestions(skills, query, MAX_SUGGESTIONS);
|
|
1221
|
+
return { resolved: null, suggestions };
|
|
1222
|
+
}
|
|
1223
|
+
const localSkillsResult = await discoverLocalSkills(projectDir);
|
|
1224
|
+
const localSkillIds = localSkillsResult?.skills.map((s) => s.id) || [];
|
|
1225
|
+
const isInstalled = localSkillIds.includes(skill.id);
|
|
1226
|
+
let preview = [];
|
|
1227
|
+
if (includePreview) {
|
|
1228
|
+
let skillMdPath;
|
|
1229
|
+
if (skill.local && skill.localPath) {
|
|
1230
|
+
skillMdPath = path6.join(projectDir, skill.localPath, STANDARD_FILES.SKILL_MD);
|
|
1231
|
+
} else {
|
|
1232
|
+
const sourceDir = isLocal ? sourcePath : path6.dirname(sourcePath);
|
|
1233
|
+
skillMdPath = path6.join(sourceDir, skill.path, STANDARD_FILES.SKILL_MD);
|
|
1234
|
+
}
|
|
1235
|
+
if (await fileExists(skillMdPath)) {
|
|
1236
|
+
const content = await readFile(skillMdPath);
|
|
1237
|
+
preview = getPreviewLines(content, CONTENT_PREVIEW_LINES);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
return {
|
|
1241
|
+
resolved: { skill, isInstalled, preview },
|
|
1242
|
+
suggestions: []
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// src/cli/lib/operations/eject-project.ts
|
|
1247
|
+
init_esm_shims();
|
|
1248
|
+
import path7 from "path";
|
|
1249
|
+
async function ejectAgentPartials(options) {
|
|
1250
|
+
const { outputBase, force, directOutput = false, templatesOnly = false } = options;
|
|
1251
|
+
const sourceDir = templatesOnly ? path7.join(PROJECT_ROOT, DIRS.templates) : path7.join(PROJECT_ROOT, DIRS.agents);
|
|
1252
|
+
if (!await directoryExists(sourceDir)) {
|
|
1253
|
+
return {
|
|
1254
|
+
skipped: true,
|
|
1255
|
+
skipReason: templatesOnly ? "No agent templates found in CLI." : "No agent partials found in CLI.",
|
|
1256
|
+
templatesSkipped: false
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
const destDir = directOutput ? outputBase : templatesOnly ? path7.join(outputBase, path7.basename(DIRS.agents), path7.basename(DIRS.templates)) : path7.join(outputBase, path7.basename(DIRS.agents));
|
|
1260
|
+
const templatesBasename = path7.basename(DIRS.templates);
|
|
1261
|
+
if (await directoryExists(destDir) && !force) {
|
|
1262
|
+
if (templatesOnly) {
|
|
1263
|
+
return {
|
|
1264
|
+
skipped: true,
|
|
1265
|
+
skipReason: `Agent templates already exist at ${destDir}. Use --force to overwrite.`,
|
|
1266
|
+
templatesSkipped: false
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
const hasTemplates = await directoryExists(path7.join(destDir, templatesBasename));
|
|
1270
|
+
if (await hasAgentPartialDirs(destDir) && !hasTemplates) {
|
|
1271
|
+
return {
|
|
1272
|
+
skipped: true,
|
|
1273
|
+
skipReason: `Agent partials already exist at ${destDir}. Use --force to overwrite.`,
|
|
1274
|
+
templatesSkipped: false
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
await ensureDir(destDir);
|
|
1279
|
+
const skipTemplates = !templatesOnly && !force && await directoryExists(path7.join(destDir, templatesBasename));
|
|
1280
|
+
if (skipTemplates) {
|
|
1281
|
+
const sourceEntries = await listDirectories(sourceDir);
|
|
1282
|
+
const nonTemplateEntries = sourceEntries.filter((entry) => entry !== templatesBasename);
|
|
1283
|
+
for (const entry of nonTemplateEntries) {
|
|
1284
|
+
await copy(path7.join(sourceDir, entry), path7.join(destDir, entry));
|
|
1285
|
+
}
|
|
1286
|
+
} else {
|
|
1287
|
+
await copy(sourceDir, destDir);
|
|
1288
|
+
}
|
|
1289
|
+
return {
|
|
1290
|
+
skipped: false,
|
|
1291
|
+
destDir,
|
|
1292
|
+
templatesSkipped: skipTemplates
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
async function ejectSkills(options) {
|
|
1296
|
+
const {
|
|
1297
|
+
projectDir,
|
|
1298
|
+
force,
|
|
1299
|
+
sourceResult,
|
|
1300
|
+
matrix,
|
|
1301
|
+
directOutput = false,
|
|
1302
|
+
customOutputBase
|
|
1303
|
+
} = options;
|
|
1304
|
+
const destDir = directOutput && customOutputBase ? customOutputBase : path7.join(projectDir, LOCAL_SKILLS_PATH);
|
|
1305
|
+
if (await directoryExists(destDir) && !force) {
|
|
1306
|
+
return {
|
|
1307
|
+
skipped: true,
|
|
1308
|
+
skipReason: `Skills already exist at ${destDir}. Use --force to overwrite.`,
|
|
1309
|
+
copiedSkills: []
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
const skillIds = typedKeys(matrix.skills).filter(
|
|
1313
|
+
(skillId) => !matrix.skills[skillId]?.local
|
|
1314
|
+
);
|
|
1315
|
+
if (skillIds.length === 0) {
|
|
1316
|
+
return {
|
|
1317
|
+
skipped: true,
|
|
1318
|
+
skipReason: "No skills found in source to eject.",
|
|
1319
|
+
copiedSkills: []
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
await ensureDir(destDir);
|
|
1323
|
+
const copiedSkills = await copySkillsToLocalFlattened(skillIds, destDir, matrix, sourceResult);
|
|
1324
|
+
const sourceLabel = sourceResult.isLocal ? sourceResult.sourcePath : sourceResult.marketplace || sourceResult.sourceConfig.source;
|
|
1325
|
+
return {
|
|
1326
|
+
skipped: false,
|
|
1327
|
+
copiedSkills,
|
|
1328
|
+
destDir,
|
|
1329
|
+
sourceLabel
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
async function ensureMinimalConfig(options) {
|
|
1333
|
+
const { projectDir, sourceFlag, sourceResult } = options;
|
|
1334
|
+
const tsConfigPath = path7.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_TS);
|
|
1335
|
+
if (await fileExists(tsConfigPath)) {
|
|
1336
|
+
return { configPath: tsConfigPath, created: false };
|
|
1337
|
+
}
|
|
1338
|
+
const projectName = path7.basename(projectDir);
|
|
1339
|
+
const config = {
|
|
1340
|
+
name: projectName
|
|
1341
|
+
};
|
|
1342
|
+
const resolvedConfig = sourceResult?.sourceConfig ?? await resolveSource(sourceFlag, projectDir);
|
|
1343
|
+
if (sourceFlag) {
|
|
1344
|
+
config.source = sourceFlag;
|
|
1345
|
+
} else if (resolvedConfig.source) {
|
|
1346
|
+
config.source = resolvedConfig.source;
|
|
1347
|
+
}
|
|
1348
|
+
if (resolvedConfig.marketplace) {
|
|
1349
|
+
config.marketplace = resolvedConfig.marketplace;
|
|
1350
|
+
}
|
|
1351
|
+
const existingProjectConfig = await loadProjectSourceConfig(projectDir);
|
|
1352
|
+
if (existingProjectConfig?.author) {
|
|
1353
|
+
config.author = existingProjectConfig.author;
|
|
1354
|
+
}
|
|
1355
|
+
if (existingProjectConfig?.agentsSource) {
|
|
1356
|
+
config.agentsSource = existingProjectConfig.agentsSource;
|
|
1357
|
+
}
|
|
1358
|
+
await ensureDir(path7.join(projectDir, CLAUDE_SRC_DIR));
|
|
1359
|
+
const cleaned = JSON.parse(JSON.stringify(config));
|
|
1360
|
+
const body = JSON.stringify(cleaned, null, 2);
|
|
1361
|
+
const content = `export default ${body};
|
|
1362
|
+
`;
|
|
1363
|
+
await writeFile(tsConfigPath, content);
|
|
1364
|
+
return { configPath: tsConfigPath, created: true };
|
|
1365
|
+
}
|
|
1366
|
+
async function hasAgentPartialDirs(agentsDir) {
|
|
1367
|
+
const subdirs = await listDirectories(agentsDir);
|
|
1368
|
+
const templatesBasename = path7.basename(DIRS.templates);
|
|
1369
|
+
return subdirs.some((dir) => dir !== templatesBasename);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// src/cli/lib/operations/uninstall-project.ts
|
|
1373
|
+
init_esm_shims();
|
|
1374
|
+
import path8 from "path";
|
|
1375
|
+
import { readdir } from "fs/promises";
|
|
1376
|
+
function collectConfiguredAgents(config) {
|
|
1377
|
+
if (!config?.agents) return [];
|
|
1378
|
+
return config.agents.map((a) => a.name);
|
|
1379
|
+
}
|
|
1380
|
+
function getCliInstalledPluginKeys(config) {
|
|
1381
|
+
if (!config?.skills) return /* @__PURE__ */ new Set();
|
|
1382
|
+
return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));
|
|
1383
|
+
}
|
|
1384
|
+
async function detectUninstallTarget(projectDir) {
|
|
1385
|
+
const pluginsDir = getProjectPluginsDir(projectDir);
|
|
1386
|
+
const skillsDir = path8.join(projectDir, CLAUDE_DIR, "skills");
|
|
1387
|
+
const agentsDir = path8.join(projectDir, CLAUDE_DIR, "agents");
|
|
1388
|
+
const claudeDir = path8.join(projectDir, CLAUDE_DIR);
|
|
1389
|
+
const claudeSrcDir = path8.join(projectDir, CLAUDE_SRC_DIR);
|
|
1390
|
+
const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(
|
|
1391
|
+
[
|
|
1392
|
+
directoryExists(skillsDir),
|
|
1393
|
+
directoryExists(agentsDir),
|
|
1394
|
+
directoryExists(claudeDir),
|
|
1395
|
+
directoryExists(claudeSrcDir),
|
|
1396
|
+
loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null)
|
|
1397
|
+
]
|
|
1398
|
+
);
|
|
1399
|
+
let pluginNames = [];
|
|
1400
|
+
try {
|
|
1401
|
+
pluginNames = await listPluginNames(projectDir);
|
|
1402
|
+
} catch {
|
|
1403
|
+
}
|
|
1404
|
+
const configuredAgents = collectConfiguredAgents(config);
|
|
1405
|
+
const cliInstalledKeys = getCliInstalledPluginKeys(config);
|
|
1406
|
+
const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));
|
|
1407
|
+
return {
|
|
1408
|
+
hasPlugins: cliPluginNames.length > 0,
|
|
1409
|
+
pluginNames,
|
|
1410
|
+
cliPluginNames,
|
|
1411
|
+
hasLocalSkills,
|
|
1412
|
+
hasLocalAgents,
|
|
1413
|
+
hasClaudeDir,
|
|
1414
|
+
hasClaudeSrcDir,
|
|
1415
|
+
pluginsDir,
|
|
1416
|
+
skillsDir,
|
|
1417
|
+
agentsDir,
|
|
1418
|
+
claudeDir,
|
|
1419
|
+
claudeSrcDir,
|
|
1420
|
+
config,
|
|
1421
|
+
configuredAgents
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
function shouldRemoveSkill(forkedFrom) {
|
|
1425
|
+
return forkedFrom !== null;
|
|
1426
|
+
}
|
|
1427
|
+
async function removeMatchingSkills(target, onRemoved, onSkipped) {
|
|
1428
|
+
if (!target.hasLocalSkills) {
|
|
1429
|
+
return {
|
|
1430
|
+
removedCount: 0,
|
|
1431
|
+
skippedCount: 0,
|
|
1432
|
+
removedNames: [],
|
|
1433
|
+
skippedNames: [],
|
|
1434
|
+
dirCleaned: false
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
const skillDirNames = await listDirectories(target.skillsDir);
|
|
1438
|
+
const removedNames = [];
|
|
1439
|
+
const skippedNames = [];
|
|
1440
|
+
for (const skillDirName of skillDirNames) {
|
|
1441
|
+
const skillDir = path8.join(target.skillsDir, skillDirName);
|
|
1442
|
+
const forkedFrom = await readForkedFromMetadata(skillDir);
|
|
1443
|
+
if (shouldRemoveSkill(forkedFrom)) {
|
|
1444
|
+
await remove(skillDir);
|
|
1445
|
+
removedNames.push(skillDirName);
|
|
1446
|
+
onRemoved?.(skillDirName);
|
|
1447
|
+
} else {
|
|
1448
|
+
skippedNames.push(skillDirName);
|
|
1449
|
+
onSkipped?.(skillDirName);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
let dirCleaned = false;
|
|
1453
|
+
if (skippedNames.length === 0 && await directoryExists(target.skillsDir)) {
|
|
1454
|
+
if (await isDirectoryEmpty(target.skillsDir)) {
|
|
1455
|
+
await remove(target.skillsDir);
|
|
1456
|
+
dirCleaned = true;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
return {
|
|
1460
|
+
removedCount: removedNames.length,
|
|
1461
|
+
skippedCount: skippedNames.length,
|
|
1462
|
+
removedNames,
|
|
1463
|
+
skippedNames,
|
|
1464
|
+
dirCleaned
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
async function removeMatchingAgents(target, onRemoved) {
|
|
1468
|
+
if (!target.hasLocalAgents) {
|
|
1469
|
+
return { removedCount: 0, removedNames: [], dirCleaned: false };
|
|
1470
|
+
}
|
|
1471
|
+
if (target.configuredAgents.length === 0) {
|
|
1472
|
+
return { removedCount: 0, removedNames: [], dirCleaned: false };
|
|
1473
|
+
}
|
|
1474
|
+
const agentFiles = await listAgentFiles(target.agentsDir);
|
|
1475
|
+
const removedNames = [];
|
|
1476
|
+
for (const agentFile of agentFiles) {
|
|
1477
|
+
const agentName = agentFile.replace(/\.md$/, "");
|
|
1478
|
+
if (!target.configuredAgents.includes(agentName)) continue;
|
|
1479
|
+
await remove(path8.join(target.agentsDir, agentFile));
|
|
1480
|
+
removedNames.push(agentName);
|
|
1481
|
+
onRemoved?.(agentName);
|
|
1482
|
+
}
|
|
1483
|
+
let dirCleaned = false;
|
|
1484
|
+
if (await directoryExists(target.agentsDir)) {
|
|
1485
|
+
if (await isDirectoryEmpty(target.agentsDir)) {
|
|
1486
|
+
await remove(target.agentsDir);
|
|
1487
|
+
dirCleaned = true;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
return {
|
|
1491
|
+
removedCount: removedNames.length,
|
|
1492
|
+
removedNames,
|
|
1493
|
+
dirCleaned
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
async function uninstallPlugins(target, projectDir, onUninstalled) {
|
|
1497
|
+
if (!target.hasPlugins) {
|
|
1498
|
+
return { uninstalledNames: [], totalUninstalled: 0 };
|
|
1499
|
+
}
|
|
1500
|
+
const cliAvailable = await isClaudeCLIAvailable();
|
|
1501
|
+
const uninstalledNames = [];
|
|
1502
|
+
for (const pluginName of target.cliPluginNames) {
|
|
1503
|
+
if (cliAvailable) {
|
|
1504
|
+
try {
|
|
1505
|
+
const skillId = pluginName.split("@")[0];
|
|
1506
|
+
const skillConfig = target.config?.skills?.find((s) => s.id === skillId);
|
|
1507
|
+
const pluginScope = skillConfig?.scope === "global" ? "user" : "project";
|
|
1508
|
+
await claudePluginUninstall(pluginName, pluginScope, projectDir);
|
|
1509
|
+
} catch {
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
const pluginPath = path8.join(target.pluginsDir, pluginName);
|
|
1513
|
+
await remove(pluginPath);
|
|
1514
|
+
uninstalledNames.push(pluginName);
|
|
1515
|
+
onUninstalled?.(pluginName);
|
|
1516
|
+
}
|
|
1517
|
+
return {
|
|
1518
|
+
uninstalledNames,
|
|
1519
|
+
totalUninstalled: uninstalledNames.length
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
async function cleanupEmptyDirs(target, removeAll) {
|
|
1523
|
+
let claudeSrcDirRemoved = false;
|
|
1524
|
+
if (removeAll && target.hasClaudeSrcDir) {
|
|
1525
|
+
await remove(target.claudeSrcDir);
|
|
1526
|
+
claudeSrcDirRemoved = true;
|
|
1527
|
+
}
|
|
1528
|
+
let claudeDirRemoved = false;
|
|
1529
|
+
let claudeDirKept = false;
|
|
1530
|
+
if (target.hasClaudeDir && await directoryExists(target.claudeDir)) {
|
|
1531
|
+
if (await isDirectoryEmpty(target.claudeDir)) {
|
|
1532
|
+
await remove(target.claudeDir);
|
|
1533
|
+
claudeDirRemoved = true;
|
|
1534
|
+
} else {
|
|
1535
|
+
claudeDirKept = true;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
return { claudeDirRemoved, claudeSrcDirRemoved, claudeDirKept };
|
|
1539
|
+
}
|
|
1540
|
+
async function isDirectoryEmpty(dirPath) {
|
|
1541
|
+
try {
|
|
1542
|
+
const allEntries = await readdir(dirPath);
|
|
1543
|
+
return allEntries.length === 0;
|
|
1544
|
+
} catch {
|
|
1545
|
+
return true;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
async function listAgentFiles(agentsDir) {
|
|
1549
|
+
try {
|
|
1550
|
+
return (await readdir(agentsDir)).filter((f) => f.endsWith(".md"));
|
|
1551
|
+
} catch {
|
|
1552
|
+
return [];
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
// src/cli/lib/operations/search-skills.ts
|
|
1557
|
+
init_esm_shims();
|
|
1558
|
+
import path9 from "path";
|
|
1559
|
+
async function fetchSkillsFromExternalSource(source, forceRefresh) {
|
|
1560
|
+
try {
|
|
1561
|
+
const result = await fetchFromSource(source.url, { forceRefresh });
|
|
1562
|
+
const skillsDir = path9.join(result.path, DEFAULT_SKILLS_SUBDIR);
|
|
1563
|
+
if (!await fileExists(skillsDir)) {
|
|
1564
|
+
return [];
|
|
1565
|
+
}
|
|
1566
|
+
const skillDirs = await listDirectories(skillsDir);
|
|
1567
|
+
const skills = [];
|
|
1568
|
+
for (const skillDir of skillDirs) {
|
|
1569
|
+
const skillMdPath = path9.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
|
|
1570
|
+
if (!await fileExists(skillMdPath)) continue;
|
|
1571
|
+
const content = await readFile(skillMdPath);
|
|
1572
|
+
const frontmatter = parseFrontmatter(content, skillMdPath);
|
|
1573
|
+
if (!frontmatter) continue;
|
|
1574
|
+
skills.push({
|
|
1575
|
+
id: frontmatter.name,
|
|
1576
|
+
description: frontmatter.description,
|
|
1577
|
+
// Boundary cast: directory name used as slug for third-party source skill
|
|
1578
|
+
slug: skillDir,
|
|
1579
|
+
displayName: skillDir,
|
|
1580
|
+
// Boundary cast: external source skills have no real category; "imported" is a display-only placeholder
|
|
1581
|
+
category: "imported",
|
|
1582
|
+
author: `@${source.name}`,
|
|
1583
|
+
conflictsWith: [],
|
|
1584
|
+
isRecommended: false,
|
|
1585
|
+
requires: [],
|
|
1586
|
+
alternatives: [],
|
|
1587
|
+
discourages: [],
|
|
1588
|
+
compatibleWith: [],
|
|
1589
|
+
sourceName: source.name,
|
|
1590
|
+
sourceUrl: source.url,
|
|
1591
|
+
path: path9.join(skillsDir, skillDir)
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
return skills;
|
|
1595
|
+
} catch {
|
|
1596
|
+
return [];
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
function matchesQuery(skill, query) {
|
|
1600
|
+
const lowerQuery = query.toLowerCase();
|
|
1601
|
+
if (skill.id.toLowerCase().includes(lowerQuery)) return true;
|
|
1602
|
+
if (skill.displayName.toLowerCase().includes(lowerQuery)) return true;
|
|
1603
|
+
if (skill.slug.toLowerCase().includes(lowerQuery)) return true;
|
|
1604
|
+
if (skill.description.toLowerCase().includes(lowerQuery)) return true;
|
|
1605
|
+
if (skill.category.toLowerCase().includes(lowerQuery)) return true;
|
|
1606
|
+
return false;
|
|
1607
|
+
}
|
|
1608
|
+
function matchesCategory(skill, category) {
|
|
1609
|
+
const lowerCategory = category.toLowerCase();
|
|
1610
|
+
return skill.category.toLowerCase().includes(lowerCategory);
|
|
1611
|
+
}
|
|
1612
|
+
function filterSkillsByQuery(skills, options) {
|
|
1613
|
+
let results = skills.filter((skill) => matchesQuery(skill, options.query));
|
|
1614
|
+
if (options.category) {
|
|
1615
|
+
results = results.filter((skill) => matchesCategory(skill, options.category));
|
|
1616
|
+
}
|
|
1617
|
+
return results;
|
|
1618
|
+
}
|
|
1619
|
+
function toSourcedSkill(skill, sourceName, sourceUrl) {
|
|
1620
|
+
return {
|
|
1621
|
+
...skill,
|
|
1622
|
+
sourceName,
|
|
1623
|
+
sourceUrl
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
async function copySearchedSkillsToLocal(skills, projectDir) {
|
|
1627
|
+
const destDir = path9.join(projectDir, LOCAL_SKILLS_PATH);
|
|
1628
|
+
const results = [];
|
|
1629
|
+
for (const skill of skills) {
|
|
1630
|
+
if (skill.path) {
|
|
1631
|
+
const destPath = path9.join(destDir, skill.id);
|
|
1632
|
+
await ensureDir(path9.dirname(destPath));
|
|
1633
|
+
await copy(skill.path, destPath);
|
|
1634
|
+
results.push({ id: skill.id, copied: true });
|
|
1635
|
+
} else {
|
|
1636
|
+
results.push({ id: skill.id, copied: false, reason: "No source path available" });
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
return results;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/cli/lib/operations/scaffold-agent.ts
|
|
1643
|
+
init_esm_shims();
|
|
1644
|
+
import { spawn } from "child_process";
|
|
1645
|
+
import matter from "gray-matter";
|
|
1646
|
+
import path10 from "path";
|
|
1647
|
+
var META_AGENT_NAME = "agent-summoner";
|
|
1648
|
+
function parseCompiledAgent(content) {
|
|
1649
|
+
const { data: frontmatter, content: body } = matter(content);
|
|
1650
|
+
const tools = typeof frontmatter.tools === "string" ? frontmatter.tools.split(",").map((t) => t.trim()) : frontmatter.tools;
|
|
1651
|
+
return {
|
|
1652
|
+
description: frontmatter.description || "Creates new agents",
|
|
1653
|
+
prompt: body.trim(),
|
|
1654
|
+
model: frontmatter.model,
|
|
1655
|
+
tools
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
async function loadMetaAgent(options) {
|
|
1659
|
+
const { projectDir, source, forceRefresh } = options;
|
|
1660
|
+
const compiledFileName = `${META_AGENT_NAME}.md`;
|
|
1661
|
+
const localAgentPath = path10.join(projectDir, CLAUDE_DIR, "agents", compiledFileName);
|
|
1662
|
+
if (await fileExists(localAgentPath)) {
|
|
1663
|
+
return parseCompiledAgent(await readFile(localAgentPath));
|
|
1664
|
+
}
|
|
1665
|
+
try {
|
|
1666
|
+
const agentPaths = await getAgentDefinitions(source, { forceRefresh, projectDir });
|
|
1667
|
+
const remoteAgentPath = path10.join(
|
|
1668
|
+
agentPaths.sourcePath,
|
|
1669
|
+
CLAUDE_DIR,
|
|
1670
|
+
"agents",
|
|
1671
|
+
compiledFileName
|
|
1672
|
+
);
|
|
1673
|
+
if (await fileExists(remoteAgentPath)) {
|
|
1674
|
+
return parseCompiledAgent(await readFile(remoteAgentPath));
|
|
1675
|
+
}
|
|
1676
|
+
} catch {
|
|
1677
|
+
}
|
|
1678
|
+
throw new Error(
|
|
1679
|
+
`Agent '${META_AGENT_NAME}' not found.
|
|
1680
|
+
|
|
1681
|
+
Run 'compile' first to generate agents.`
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
function buildAgentPrompt(agentName, purpose, outputDir) {
|
|
1685
|
+
return `Create a new Claude Code agent named "${agentName}" in the directory "${outputDir}".
|
|
1686
|
+
|
|
1687
|
+
Agent Purpose: ${purpose}
|
|
1688
|
+
|
|
1689
|
+
Requirements:
|
|
1690
|
+
1. Create the agent directory structure at ${outputDir}/${agentName}/
|
|
1691
|
+
2. Create metadata.yaml with appropriate configuration
|
|
1692
|
+
3. Create intro.md with the agent's role and context
|
|
1693
|
+
4. Create workflow.md with the agent's operational process
|
|
1694
|
+
5. Optionally create examples.md if relevant examples would help
|
|
1695
|
+
6. Optionally create critical-requirements.md for important rules
|
|
1696
|
+
7. Include \`custom: true\` in the metadata.yaml configuration
|
|
1697
|
+
|
|
1698
|
+
Follow the existing agent patterns in the codebase. Keep the agent focused and practical.`;
|
|
1699
|
+
}
|
|
1700
|
+
async function invokeMetaAgent(options) {
|
|
1701
|
+
const { agentDef, prompt, nonInteractive } = options;
|
|
1702
|
+
const agentsJson = JSON.stringify({
|
|
1703
|
+
[META_AGENT_NAME]: {
|
|
1704
|
+
description: agentDef.description,
|
|
1705
|
+
prompt: agentDef.prompt,
|
|
1706
|
+
model: agentDef.model,
|
|
1707
|
+
tools: agentDef.tools
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
const args = ["--agents", agentsJson, "--agent", META_AGENT_NAME];
|
|
1711
|
+
if (nonInteractive) {
|
|
1712
|
+
args.push("-p", prompt);
|
|
1713
|
+
} else {
|
|
1714
|
+
args.push("--prompt", prompt);
|
|
1715
|
+
}
|
|
1716
|
+
return new Promise((resolve, reject) => {
|
|
1717
|
+
const child = spawn("claude", args, {
|
|
1718
|
+
stdio: "inherit"
|
|
1719
|
+
});
|
|
1720
|
+
child.on("error", (error) => {
|
|
1721
|
+
reject(new Error(`Failed to spawn claude CLI: ${error.message}`));
|
|
1722
|
+
});
|
|
1723
|
+
child.on("close", (code) => {
|
|
1724
|
+
if (code === 0) {
|
|
1725
|
+
resolve();
|
|
1726
|
+
} else {
|
|
1727
|
+
reject(new Error(`Claude CLI exited with code ${code}`));
|
|
1728
|
+
}
|
|
1729
|
+
});
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
// src/cli/lib/operations/migrate-plugin-scope.ts
|
|
1734
|
+
init_esm_shims();
|
|
1735
|
+
async function migratePluginSkillScopes(scopeChanges, skills, marketplace, projectDir) {
|
|
1736
|
+
const migrated = [];
|
|
1737
|
+
const failed = [];
|
|
1738
|
+
for (const [skillId, change] of scopeChanges) {
|
|
1739
|
+
const skillConfig = skills.find((s) => s.id === skillId);
|
|
1740
|
+
if (!skillConfig || skillConfig.source === "local") {
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
const oldPluginScope = change.from === "global" ? "user" : "project";
|
|
1744
|
+
const newPluginScope = change.to === "global" ? "user" : "project";
|
|
1745
|
+
const pluginRef = `${skillId}@${marketplace}`;
|
|
1746
|
+
try {
|
|
1747
|
+
await claudePluginUninstall(skillId, oldPluginScope, projectDir);
|
|
1748
|
+
await claudePluginInstall(pluginRef, newPluginScope, projectDir);
|
|
1749
|
+
migrated.push(skillId);
|
|
1750
|
+
} catch (error) {
|
|
1751
|
+
failed.push({ id: skillId, error: getErrorMessage(error) });
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
return { migrated, failed };
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// src/cli/lib/operations/index.ts
|
|
1758
|
+
init_esm_shims();
|
|
1759
|
+
|
|
1760
|
+
export {
|
|
1761
|
+
detectBothInstallations,
|
|
1762
|
+
loadSource,
|
|
1763
|
+
getDashboardData,
|
|
1764
|
+
detectProject,
|
|
1765
|
+
loadAgentDefs,
|
|
1766
|
+
copyLocalSkills,
|
|
1767
|
+
installPluginSkills,
|
|
1768
|
+
uninstallPluginSkills,
|
|
1769
|
+
collectScopedSkillDirs,
|
|
1770
|
+
buildSourceSkillsMap,
|
|
1771
|
+
compareSkillsWithSource,
|
|
1772
|
+
ensureMarketplace,
|
|
1773
|
+
writeProjectConfig,
|
|
1774
|
+
compileAgents,
|
|
1775
|
+
detectConfigChanges,
|
|
1776
|
+
updateLocalSkills,
|
|
1777
|
+
discoverInstalledSkills,
|
|
1778
|
+
findSkillMatch,
|
|
1779
|
+
source_default,
|
|
1780
|
+
generateSkillDiff,
|
|
1781
|
+
formatColoredDiff,
|
|
1782
|
+
resolveSkillInfo,
|
|
1783
|
+
ejectAgentPartials,
|
|
1784
|
+
ejectSkills,
|
|
1785
|
+
ensureMinimalConfig,
|
|
1786
|
+
detectUninstallTarget,
|
|
1787
|
+
removeMatchingSkills,
|
|
1788
|
+
removeMatchingAgents,
|
|
1789
|
+
uninstallPlugins,
|
|
1790
|
+
cleanupEmptyDirs,
|
|
1791
|
+
fetchSkillsFromExternalSource,
|
|
1792
|
+
filterSkillsByQuery,
|
|
1793
|
+
toSourcedSkill,
|
|
1794
|
+
copySearchedSkillsToLocal,
|
|
1795
|
+
loadMetaAgent,
|
|
1796
|
+
buildAgentPrompt,
|
|
1797
|
+
invokeMetaAgent,
|
|
1798
|
+
migratePluginSkillScopes
|
|
1799
|
+
};
|
|
1800
|
+
//# sourceMappingURL=chunk-DCVCFBQ7.js.map
|