@cleocode/caamp 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/dist/{chunk-6T3TJQFF.js → chunk-YWO4I7LI.js} +162 -837
- package/dist/chunk-YWO4I7LI.js.map +1 -0
- package/dist/chunk-ZVRDBY6L.js +756 -0
- package/dist/chunk-ZVRDBY6L.js.map +1 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +20 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +194 -12
- package/dist/index.js +201 -47
- package/dist/index.js.map +1 -1
- package/dist/injector-XGI7NNZA.js +19 -0
- package/dist/injector-XGI7NNZA.js.map +1 -0
- package/package.json +1 -1
- package/providers/registry.json +0 -0
- package/dist/chunk-6T3TJQFF.js.map +0 -1
|
@@ -1,171 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const content = await readFile(filePath, "utf-8");
|
|
18
|
-
if (!MARKER_PATTERN.test(content)) return "none";
|
|
19
|
-
if (expectedContent) {
|
|
20
|
-
const blockContent = extractBlock(content);
|
|
21
|
-
if (blockContent && blockContent.trim() === expectedContent.trim()) {
|
|
22
|
-
return "current";
|
|
23
|
-
}
|
|
24
|
-
return "outdated";
|
|
25
|
-
}
|
|
26
|
-
return "current";
|
|
27
|
-
}
|
|
28
|
-
function extractBlock(content) {
|
|
29
|
-
const match = content.match(MARKER_PATTERN);
|
|
30
|
-
if (!match) return null;
|
|
31
|
-
return match[0].replace(MARKER_START, "").replace(MARKER_END, "").trim();
|
|
32
|
-
}
|
|
33
|
-
function buildBlock(content) {
|
|
34
|
-
return `${MARKER_START}
|
|
35
|
-
${content}
|
|
36
|
-
${MARKER_END}`;
|
|
37
|
-
}
|
|
38
|
-
async function inject(filePath, content) {
|
|
39
|
-
const block = buildBlock(content);
|
|
40
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
41
|
-
if (!existsSync(filePath)) {
|
|
42
|
-
await writeFile(filePath, `${block}
|
|
43
|
-
`, "utf-8");
|
|
44
|
-
return "created";
|
|
45
|
-
}
|
|
46
|
-
const existing = await readFile(filePath, "utf-8");
|
|
47
|
-
if (MARKER_PATTERN.test(existing)) {
|
|
48
|
-
const updated2 = existing.replace(MARKER_PATTERN, block);
|
|
49
|
-
await writeFile(filePath, updated2, "utf-8");
|
|
50
|
-
return "updated";
|
|
51
|
-
}
|
|
52
|
-
const updated = `${block}
|
|
53
|
-
|
|
54
|
-
${existing}`;
|
|
55
|
-
await writeFile(filePath, updated, "utf-8");
|
|
56
|
-
return "added";
|
|
57
|
-
}
|
|
58
|
-
async function removeInjection(filePath) {
|
|
59
|
-
if (!existsSync(filePath)) return false;
|
|
60
|
-
const content = await readFile(filePath, "utf-8");
|
|
61
|
-
if (!MARKER_PATTERN.test(content)) return false;
|
|
62
|
-
const cleaned = content.replace(MARKER_PATTERN, "").replace(/^\n{2,}/, "\n").trim();
|
|
63
|
-
if (!cleaned) {
|
|
64
|
-
const { rm: rm4 } = await import("fs/promises");
|
|
65
|
-
await rm4(filePath);
|
|
66
|
-
} else {
|
|
67
|
-
await writeFile(filePath, `${cleaned}
|
|
68
|
-
`, "utf-8");
|
|
69
|
-
}
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
async function checkAllInjections(providers, projectDir, scope, expectedContent) {
|
|
73
|
-
const results = [];
|
|
74
|
-
const checked = /* @__PURE__ */ new Set();
|
|
75
|
-
for (const provider of providers) {
|
|
76
|
-
const filePath = scope === "global" ? join(provider.pathGlobal, provider.instructFile) : join(projectDir, provider.instructFile);
|
|
77
|
-
if (checked.has(filePath)) continue;
|
|
78
|
-
checked.add(filePath);
|
|
79
|
-
const status = await checkInjection(filePath, expectedContent);
|
|
80
|
-
results.push({
|
|
81
|
-
file: filePath,
|
|
82
|
-
provider: provider.id,
|
|
83
|
-
status,
|
|
84
|
-
fileExists: existsSync(filePath)
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return results;
|
|
88
|
-
}
|
|
89
|
-
async function injectAll(providers, projectDir, scope, content) {
|
|
90
|
-
const results = /* @__PURE__ */ new Map();
|
|
91
|
-
const injected = /* @__PURE__ */ new Set();
|
|
92
|
-
for (const provider of providers) {
|
|
93
|
-
const filePath = scope === "global" ? join(provider.pathGlobal, provider.instructFile) : join(projectDir, provider.instructFile);
|
|
94
|
-
if (injected.has(filePath)) continue;
|
|
95
|
-
injected.add(filePath);
|
|
96
|
-
const action = await inject(filePath, content);
|
|
97
|
-
results.set(filePath, action);
|
|
98
|
-
}
|
|
99
|
-
return results;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/core/instructions/templates.ts
|
|
103
|
-
function buildInjectionContent(template) {
|
|
104
|
-
const lines = [];
|
|
105
|
-
for (const ref of template.references) {
|
|
106
|
-
lines.push(ref);
|
|
107
|
-
}
|
|
108
|
-
if (template.content && template.content.length > 0) {
|
|
109
|
-
if (lines.length > 0) {
|
|
110
|
-
lines.push("");
|
|
111
|
-
}
|
|
112
|
-
lines.push(...template.content);
|
|
113
|
-
}
|
|
114
|
-
return lines.join("\n");
|
|
115
|
-
}
|
|
116
|
-
function parseInjectionContent(content) {
|
|
117
|
-
const references = [];
|
|
118
|
-
const contentLines = [];
|
|
119
|
-
for (const line of content.split("\n")) {
|
|
120
|
-
const trimmed = line.trim();
|
|
121
|
-
if (!trimmed) continue;
|
|
122
|
-
if (trimmed.startsWith("@")) {
|
|
123
|
-
references.push(trimmed);
|
|
124
|
-
} else {
|
|
125
|
-
contentLines.push(line);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
references,
|
|
130
|
-
content: contentLines.length > 0 ? contentLines : void 0
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function generateInjectionContent(options) {
|
|
134
|
-
const lines = [];
|
|
135
|
-
lines.push("## CAAMP Managed Configuration");
|
|
136
|
-
lines.push("");
|
|
137
|
-
lines.push("This section is managed by [CAAMP](https://github.com/caamp/caamp).");
|
|
138
|
-
lines.push("Do not edit between the CAAMP markers manually.");
|
|
139
|
-
if (options?.mcpServerName) {
|
|
140
|
-
lines.push("");
|
|
141
|
-
lines.push(`### MCP Server: ${options.mcpServerName}`);
|
|
142
|
-
lines.push(`Configured via \`caamp mcp install\`.`);
|
|
143
|
-
}
|
|
144
|
-
if (options?.customContent) {
|
|
145
|
-
lines.push("");
|
|
146
|
-
lines.push(options.customContent);
|
|
147
|
-
}
|
|
148
|
-
return lines.join("\n");
|
|
149
|
-
}
|
|
150
|
-
function generateSkillsSection(skillNames) {
|
|
151
|
-
if (skillNames.length === 0) return "";
|
|
152
|
-
const lines = [];
|
|
153
|
-
lines.push("### Installed Skills");
|
|
154
|
-
lines.push("");
|
|
155
|
-
for (const name of skillNames) {
|
|
156
|
-
lines.push(`- \`${name}\` - Available via SKILL.md`);
|
|
157
|
-
}
|
|
158
|
-
return lines.join("\n");
|
|
159
|
-
}
|
|
160
|
-
function groupByInstructFile(providers) {
|
|
161
|
-
const groups = /* @__PURE__ */ new Map();
|
|
162
|
-
for (const provider of providers) {
|
|
163
|
-
const existing = groups.get(provider.instructFile) ?? [];
|
|
164
|
-
existing.push(provider);
|
|
165
|
-
groups.set(provider.instructFile, existing);
|
|
166
|
-
}
|
|
167
|
-
return groups;
|
|
168
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
__export,
|
|
3
|
+
getAgentsConfigPath,
|
|
4
|
+
getAgentsHome,
|
|
5
|
+
getAgentsMcpDir,
|
|
6
|
+
getAgentsMcpServersPath,
|
|
7
|
+
getAllProviders,
|
|
8
|
+
getCanonicalSkillsDir,
|
|
9
|
+
getLockFilePath,
|
|
10
|
+
getPlatformLocations,
|
|
11
|
+
groupByInstructFile,
|
|
12
|
+
injectAll,
|
|
13
|
+
resolveProviderConfigPath,
|
|
14
|
+
resolveProviderProjectPath,
|
|
15
|
+
resolveProviderSkillsDirs
|
|
16
|
+
} from "./chunk-ZVRDBY6L.js";
|
|
169
17
|
|
|
170
18
|
// src/core/formats/utils.ts
|
|
171
19
|
function deepMerge(target, source) {
|
|
@@ -194,9 +42,9 @@ function getNestedValue(obj, keyPath) {
|
|
|
194
42
|
return current;
|
|
195
43
|
}
|
|
196
44
|
async function ensureDir(filePath) {
|
|
197
|
-
const { mkdir:
|
|
198
|
-
const { dirname:
|
|
199
|
-
await
|
|
45
|
+
const { mkdir: mkdir4 } = await import("fs/promises");
|
|
46
|
+
const { dirname: dirname3 } = await import("path");
|
|
47
|
+
await mkdir4(dirname3(filePath), { recursive: true });
|
|
200
48
|
}
|
|
201
49
|
|
|
202
50
|
// src/core/logger.ts
|
|
@@ -226,12 +74,12 @@ function isHuman() {
|
|
|
226
74
|
}
|
|
227
75
|
|
|
228
76
|
// src/core/formats/json.ts
|
|
229
|
-
import { readFile
|
|
230
|
-
import { existsSync
|
|
77
|
+
import { readFile, writeFile } from "fs/promises";
|
|
78
|
+
import { existsSync } from "fs";
|
|
231
79
|
import * as jsonc from "jsonc-parser";
|
|
232
80
|
async function readJsonConfig(filePath) {
|
|
233
|
-
if (!
|
|
234
|
-
const content = await
|
|
81
|
+
if (!existsSync(filePath)) return {};
|
|
82
|
+
const content = await readFile(filePath, "utf-8");
|
|
235
83
|
if (!content.trim()) return {};
|
|
236
84
|
const errors = [];
|
|
237
85
|
const result = jsonc.parse(content, errors);
|
|
@@ -257,8 +105,8 @@ function detectIndent(content) {
|
|
|
257
105
|
async function writeJsonConfig(filePath, configKey, serverName, serverConfig) {
|
|
258
106
|
await ensureDir(filePath);
|
|
259
107
|
let content;
|
|
260
|
-
if (
|
|
261
|
-
content = await
|
|
108
|
+
if (existsSync(filePath)) {
|
|
109
|
+
content = await readFile(filePath, "utf-8");
|
|
262
110
|
if (!content.trim()) {
|
|
263
111
|
content = "{}";
|
|
264
112
|
}
|
|
@@ -280,11 +128,11 @@ async function writeJsonConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
280
128
|
if (!content.endsWith("\n")) {
|
|
281
129
|
content += "\n";
|
|
282
130
|
}
|
|
283
|
-
await
|
|
131
|
+
await writeFile(filePath, content, "utf-8");
|
|
284
132
|
}
|
|
285
133
|
async function removeJsonConfig(filePath, configKey, serverName) {
|
|
286
|
-
if (!
|
|
287
|
-
let content = await
|
|
134
|
+
if (!existsSync(filePath)) return false;
|
|
135
|
+
let content = await readFile(filePath, "utf-8");
|
|
288
136
|
if (!content.trim()) return false;
|
|
289
137
|
const { tabSize, insertSpaces } = detectIndent(content);
|
|
290
138
|
const formatOptions = {
|
|
@@ -300,17 +148,17 @@ async function removeJsonConfig(filePath, configKey, serverName) {
|
|
|
300
148
|
if (!content.endsWith("\n")) {
|
|
301
149
|
content += "\n";
|
|
302
150
|
}
|
|
303
|
-
await
|
|
151
|
+
await writeFile(filePath, content, "utf-8");
|
|
304
152
|
return true;
|
|
305
153
|
}
|
|
306
154
|
|
|
307
155
|
// src/core/formats/yaml.ts
|
|
308
|
-
import { existsSync as
|
|
309
|
-
import { readFile as
|
|
156
|
+
import { existsSync as existsSync2 } from "fs";
|
|
157
|
+
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
310
158
|
import yaml from "js-yaml";
|
|
311
159
|
async function readYamlConfig(filePath) {
|
|
312
|
-
if (!
|
|
313
|
-
const content = await
|
|
160
|
+
if (!existsSync2(filePath)) return {};
|
|
161
|
+
const content = await readFile2(filePath, "utf-8");
|
|
314
162
|
if (!content.trim()) return {};
|
|
315
163
|
const result = yaml.load(content);
|
|
316
164
|
return result ?? {};
|
|
@@ -330,10 +178,10 @@ async function writeYamlConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
330
178
|
noRefs: true,
|
|
331
179
|
sortKeys: false
|
|
332
180
|
});
|
|
333
|
-
await
|
|
181
|
+
await writeFile2(filePath, content, "utf-8");
|
|
334
182
|
}
|
|
335
183
|
async function removeYamlConfig(filePath, configKey, serverName) {
|
|
336
|
-
if (!
|
|
184
|
+
if (!existsSync2(filePath)) return false;
|
|
337
185
|
const existing = await readYamlConfig(filePath);
|
|
338
186
|
const keyParts = configKey.split(".");
|
|
339
187
|
let current = existing;
|
|
@@ -350,17 +198,17 @@ async function removeYamlConfig(filePath, configKey, serverName) {
|
|
|
350
198
|
noRefs: true,
|
|
351
199
|
sortKeys: false
|
|
352
200
|
});
|
|
353
|
-
await
|
|
201
|
+
await writeFile2(filePath, content, "utf-8");
|
|
354
202
|
return true;
|
|
355
203
|
}
|
|
356
204
|
|
|
357
205
|
// src/core/formats/toml.ts
|
|
358
|
-
import { existsSync as
|
|
359
|
-
import { readFile as
|
|
206
|
+
import { existsSync as existsSync3 } from "fs";
|
|
207
|
+
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
360
208
|
import TOML from "@iarna/toml";
|
|
361
209
|
async function readTomlConfig(filePath) {
|
|
362
|
-
if (!
|
|
363
|
-
const content = await
|
|
210
|
+
if (!existsSync3(filePath)) return {};
|
|
211
|
+
const content = await readFile3(filePath, "utf-8");
|
|
364
212
|
if (!content.trim()) return {};
|
|
365
213
|
const result = TOML.parse(content);
|
|
366
214
|
return result;
|
|
@@ -375,10 +223,10 @@ async function writeTomlConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
375
223
|
}
|
|
376
224
|
const merged = deepMerge(existing, newEntry);
|
|
377
225
|
const content = TOML.stringify(merged);
|
|
378
|
-
await
|
|
226
|
+
await writeFile3(filePath, content, "utf-8");
|
|
379
227
|
}
|
|
380
228
|
async function removeTomlConfig(filePath, configKey, serverName) {
|
|
381
|
-
if (!
|
|
229
|
+
if (!existsSync3(filePath)) return false;
|
|
382
230
|
const existing = await readTomlConfig(filePath);
|
|
383
231
|
const keyParts = configKey.split(".");
|
|
384
232
|
let current = existing;
|
|
@@ -390,7 +238,7 @@ async function removeTomlConfig(filePath, configKey, serverName) {
|
|
|
390
238
|
if (!(serverName in current)) return false;
|
|
391
239
|
delete current[serverName];
|
|
392
240
|
const content = TOML.stringify(existing);
|
|
393
|
-
await
|
|
241
|
+
await writeFile3(filePath, content, "utf-8");
|
|
394
242
|
return true;
|
|
395
243
|
}
|
|
396
244
|
|
|
@@ -437,258 +285,15 @@ async function removeConfig(filePath, format, key, serverName) {
|
|
|
437
285
|
}
|
|
438
286
|
}
|
|
439
287
|
|
|
440
|
-
// src/core/platform-paths.ts
|
|
441
|
-
import envPaths from "env-paths";
|
|
442
|
-
import { arch, homedir, hostname, platform, release } from "os";
|
|
443
|
-
import { isAbsolute, join as join2, resolve } from "path";
|
|
444
|
-
var APP_NAME = "agents";
|
|
445
|
-
function resolveAgentsHomeOverride(value) {
|
|
446
|
-
if (value === void 0) return void 0;
|
|
447
|
-
const trimmed = value.trim();
|
|
448
|
-
if (trimmed.length === 0) return void 0;
|
|
449
|
-
if (trimmed === "~") return homedir();
|
|
450
|
-
if (trimmed.startsWith("~/")) return join2(homedir(), trimmed.slice(2));
|
|
451
|
-
if (isAbsolute(trimmed)) return resolve(trimmed);
|
|
452
|
-
return resolve(homedir(), trimmed);
|
|
453
|
-
}
|
|
454
|
-
var _paths = null;
|
|
455
|
-
var _sysInfo = null;
|
|
456
|
-
var _lastAgentsHome = void 0;
|
|
457
|
-
function getPlatformPaths() {
|
|
458
|
-
const currentAgentsHome = process.env["AGENTS_HOME"];
|
|
459
|
-
if (_paths && currentAgentsHome !== _lastAgentsHome) {
|
|
460
|
-
_paths = null;
|
|
461
|
-
_sysInfo = null;
|
|
462
|
-
}
|
|
463
|
-
if (_paths) return _paths;
|
|
464
|
-
const ep = envPaths(APP_NAME, { suffix: "" });
|
|
465
|
-
_lastAgentsHome = currentAgentsHome;
|
|
466
|
-
_paths = {
|
|
467
|
-
data: resolveAgentsHomeOverride(currentAgentsHome) ?? ep.data,
|
|
468
|
-
config: ep.config,
|
|
469
|
-
cache: ep.cache,
|
|
470
|
-
log: ep.log,
|
|
471
|
-
temp: ep.temp
|
|
472
|
-
};
|
|
473
|
-
return _paths;
|
|
474
|
-
}
|
|
475
|
-
function getSystemInfo() {
|
|
476
|
-
if (_sysInfo) return _sysInfo;
|
|
477
|
-
const paths = getPlatformPaths();
|
|
478
|
-
_sysInfo = {
|
|
479
|
-
platform: platform(),
|
|
480
|
-
arch: arch(),
|
|
481
|
-
release: release(),
|
|
482
|
-
hostname: hostname(),
|
|
483
|
-
nodeVersion: process.version,
|
|
484
|
-
paths
|
|
485
|
-
};
|
|
486
|
-
return _sysInfo;
|
|
487
|
-
}
|
|
488
|
-
function _resetPlatformPathsCache() {
|
|
489
|
-
_paths = null;
|
|
490
|
-
_sysInfo = null;
|
|
491
|
-
_lastAgentsHome = void 0;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// src/core/paths/standard.ts
|
|
495
|
-
import { existsSync as existsSync5 } from "fs";
|
|
496
|
-
import { homedir as homedir2 } from "os";
|
|
497
|
-
import { dirname as dirname2, join as join3 } from "path";
|
|
498
|
-
function getPlatformLocations() {
|
|
499
|
-
const home = homedir2();
|
|
500
|
-
const platform2 = process.platform;
|
|
501
|
-
if (platform2 === "win32") {
|
|
502
|
-
const appData = process.env["APPDATA"] ?? join3(home, "AppData", "Roaming");
|
|
503
|
-
return {
|
|
504
|
-
home,
|
|
505
|
-
config: appData,
|
|
506
|
-
vscodeConfig: join3(appData, "Code", "User"),
|
|
507
|
-
zedConfig: join3(appData, "Zed"),
|
|
508
|
-
claudeDesktopConfig: join3(appData, "Claude"),
|
|
509
|
-
applications: []
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
if (platform2 === "darwin") {
|
|
513
|
-
const config2 = process.env["XDG_CONFIG_HOME"] ?? join3(home, ".config");
|
|
514
|
-
return {
|
|
515
|
-
home,
|
|
516
|
-
config: config2,
|
|
517
|
-
vscodeConfig: join3(home, "Library", "Application Support", "Code", "User"),
|
|
518
|
-
zedConfig: join3(home, "Library", "Application Support", "Zed"),
|
|
519
|
-
claudeDesktopConfig: join3(home, "Library", "Application Support", "Claude"),
|
|
520
|
-
applications: ["/Applications", join3(home, "Applications")]
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
const config = process.env["XDG_CONFIG_HOME"] ?? join3(home, ".config");
|
|
524
|
-
return {
|
|
525
|
-
home,
|
|
526
|
-
config,
|
|
527
|
-
vscodeConfig: join3(config, "Code", "User"),
|
|
528
|
-
zedConfig: join3(config, "zed"),
|
|
529
|
-
claudeDesktopConfig: join3(config, "Claude"),
|
|
530
|
-
applications: []
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
function getAgentsHome() {
|
|
534
|
-
return getPlatformPaths().data;
|
|
535
|
-
}
|
|
536
|
-
function getProjectAgentsDir(projectRoot = process.cwd()) {
|
|
537
|
-
return join3(projectRoot, ".agents");
|
|
538
|
-
}
|
|
539
|
-
function resolveProjectPath(relativePath, projectDir = process.cwd()) {
|
|
540
|
-
return join3(projectDir, relativePath);
|
|
541
|
-
}
|
|
542
|
-
function getCanonicalSkillsDir() {
|
|
543
|
-
return join3(getAgentsHome(), "skills");
|
|
544
|
-
}
|
|
545
|
-
function getLockFilePath() {
|
|
546
|
-
return join3(getAgentsHome(), ".caamp-lock.json");
|
|
547
|
-
}
|
|
548
|
-
function getAgentsMcpDir(scope = "global", projectDir) {
|
|
549
|
-
if (scope === "global") return join3(getAgentsHome(), "mcp");
|
|
550
|
-
return join3(projectDir ?? process.cwd(), ".agents", "mcp");
|
|
551
|
-
}
|
|
552
|
-
function getAgentsMcpServersPath(scope = "global", projectDir) {
|
|
553
|
-
return join3(getAgentsMcpDir(scope, projectDir), "servers.json");
|
|
554
|
-
}
|
|
555
|
-
function getAgentsInstructFile(scope = "global", projectDir) {
|
|
556
|
-
if (scope === "global") return join3(getAgentsHome(), "AGENTS.md");
|
|
557
|
-
return join3(projectDir ?? process.cwd(), ".agents", "AGENTS.md");
|
|
558
|
-
}
|
|
559
|
-
function getAgentsConfigPath(scope = "global", projectDir) {
|
|
560
|
-
if (scope === "global") return join3(getAgentsHome(), "config.toml");
|
|
561
|
-
return join3(projectDir ?? process.cwd(), ".agents", "config.toml");
|
|
562
|
-
}
|
|
563
|
-
function getAgentsWikiDir(scope = "global", projectDir) {
|
|
564
|
-
if (scope === "global") return join3(getAgentsHome(), "wiki");
|
|
565
|
-
return join3(projectDir ?? process.cwd(), ".agents", "wiki");
|
|
566
|
-
}
|
|
567
|
-
function getAgentsSpecDir(scope = "global", projectDir) {
|
|
568
|
-
if (scope === "global") return join3(getAgentsHome(), "spec");
|
|
569
|
-
return join3(projectDir ?? process.cwd(), ".agents", "spec");
|
|
570
|
-
}
|
|
571
|
-
function getAgentsLinksDir(scope = "global", projectDir) {
|
|
572
|
-
if (scope === "global") return join3(getAgentsHome(), "links");
|
|
573
|
-
return join3(projectDir ?? process.cwd(), ".agents", "links");
|
|
574
|
-
}
|
|
575
|
-
function resolveRegistryTemplatePath(template) {
|
|
576
|
-
const locations = getPlatformLocations();
|
|
577
|
-
return template.replace(/\$HOME/g, locations.home).replace(/\$CONFIG/g, locations.config).replace(/\$VSCODE_CONFIG/g, locations.vscodeConfig).replace(/\$ZED_CONFIG/g, locations.zedConfig).replace(/\$CLAUDE_DESKTOP_CONFIG/g, locations.claudeDesktopConfig).replace(/\$AGENTS_HOME/g, getAgentsHome());
|
|
578
|
-
}
|
|
579
|
-
function resolveProviderConfigPath(provider, scope, projectDir = process.cwd()) {
|
|
580
|
-
if (scope === "global") {
|
|
581
|
-
return provider.configPathGlobal;
|
|
582
|
-
}
|
|
583
|
-
if (!provider.configPathProject) {
|
|
584
|
-
return null;
|
|
585
|
-
}
|
|
586
|
-
return resolveProjectPath(provider.configPathProject, projectDir);
|
|
587
|
-
}
|
|
588
|
-
function resolvePreferredConfigScope(provider, useGlobalFlag) {
|
|
589
|
-
if (useGlobalFlag) {
|
|
590
|
-
return "global";
|
|
591
|
-
}
|
|
592
|
-
return provider.configPathProject ? "project" : "global";
|
|
593
|
-
}
|
|
594
|
-
function resolveProviderSkillsDir(provider, scope, projectDir = process.cwd()) {
|
|
595
|
-
if (scope === "global") {
|
|
596
|
-
return provider.pathSkills;
|
|
597
|
-
}
|
|
598
|
-
return resolveProjectPath(provider.pathProjectSkills, projectDir);
|
|
599
|
-
}
|
|
600
|
-
function resolveProviderSkillsDirs(provider, scope, projectDir = process.cwd()) {
|
|
601
|
-
const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);
|
|
602
|
-
const precedence = provider.capabilities?.skills?.precedence ?? "vendor-only";
|
|
603
|
-
const resolveAgentsPath = () => {
|
|
604
|
-
if (scope === "global") {
|
|
605
|
-
return provider.capabilities?.skills?.agentsGlobalPath ?? null;
|
|
606
|
-
}
|
|
607
|
-
const projectRelative = provider.capabilities?.skills?.agentsProjectPath ?? null;
|
|
608
|
-
return projectRelative ? join3(projectDir, projectRelative) : null;
|
|
609
|
-
};
|
|
610
|
-
switch (precedence) {
|
|
611
|
-
case "vendor-only":
|
|
612
|
-
return [vendorPath];
|
|
613
|
-
case "agents-canonical": {
|
|
614
|
-
const agentsPath = resolveAgentsPath();
|
|
615
|
-
return agentsPath ? [agentsPath] : [vendorPath];
|
|
616
|
-
}
|
|
617
|
-
case "agents-first": {
|
|
618
|
-
const agentsPath = resolveAgentsPath();
|
|
619
|
-
return agentsPath ? [agentsPath, vendorPath] : [vendorPath];
|
|
620
|
-
}
|
|
621
|
-
case "agents-supported": {
|
|
622
|
-
const agentsPath = resolveAgentsPath();
|
|
623
|
-
return agentsPath ? [vendorPath, agentsPath] : [vendorPath];
|
|
624
|
-
}
|
|
625
|
-
case "vendor-global-agents-project": {
|
|
626
|
-
if (scope === "global") {
|
|
627
|
-
return [vendorPath];
|
|
628
|
-
}
|
|
629
|
-
const agentsPath = resolveAgentsPath();
|
|
630
|
-
return agentsPath ? [agentsPath, vendorPath] : [vendorPath];
|
|
631
|
-
}
|
|
632
|
-
default:
|
|
633
|
-
return [vendorPath];
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
function resolveProviderProjectPath(provider, projectDir = process.cwd()) {
|
|
637
|
-
return resolveProjectPath(provider.pathProject, projectDir);
|
|
638
|
-
}
|
|
639
|
-
function resolveProvidersRegistryPath(startDir) {
|
|
640
|
-
const candidates = [
|
|
641
|
-
join3(startDir, "..", "..", "..", "providers", "registry.json"),
|
|
642
|
-
join3(startDir, "..", "providers", "registry.json")
|
|
643
|
-
];
|
|
644
|
-
for (const candidate of candidates) {
|
|
645
|
-
if (existsSync5(candidate)) {
|
|
646
|
-
return candidate;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
let current = startDir;
|
|
650
|
-
for (let i = 0; i < 8; i += 1) {
|
|
651
|
-
const candidate = join3(current, "providers", "registry.json");
|
|
652
|
-
if (existsSync5(candidate)) {
|
|
653
|
-
return candidate;
|
|
654
|
-
}
|
|
655
|
-
current = dirname2(current);
|
|
656
|
-
}
|
|
657
|
-
throw new Error(`Cannot find providers/registry.json (searched from ${startDir})`);
|
|
658
|
-
}
|
|
659
|
-
function normalizeSkillSubPath(path) {
|
|
660
|
-
if (!path) return void 0;
|
|
661
|
-
const normalized = path.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/SKILL\.md$/i, "").trim();
|
|
662
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
663
|
-
}
|
|
664
|
-
function buildSkillSubPathCandidates(marketplacePath, parsedPath) {
|
|
665
|
-
const candidates = [];
|
|
666
|
-
const base = normalizeSkillSubPath(marketplacePath);
|
|
667
|
-
const parsed = normalizeSkillSubPath(parsedPath);
|
|
668
|
-
if (base) candidates.push(base);
|
|
669
|
-
if (parsed) candidates.push(parsed);
|
|
670
|
-
const knownPrefixes = [".agents", ".claude"];
|
|
671
|
-
for (const value of [base, parsed]) {
|
|
672
|
-
if (!value || !value.startsWith("skills/")) continue;
|
|
673
|
-
for (const prefix of knownPrefixes) {
|
|
674
|
-
candidates.push(`${prefix}/${value}`);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
if (candidates.length === 0) {
|
|
678
|
-
candidates.push(void 0);
|
|
679
|
-
}
|
|
680
|
-
return Array.from(new Set(candidates));
|
|
681
|
-
}
|
|
682
|
-
|
|
683
288
|
// src/core/mcp/reader.ts
|
|
684
|
-
import { existsSync as
|
|
289
|
+
import { existsSync as existsSync4 } from "fs";
|
|
685
290
|
function resolveConfigPath(provider, scope, projectDir) {
|
|
686
291
|
return resolveProviderConfigPath(provider, scope, projectDir ?? process.cwd());
|
|
687
292
|
}
|
|
688
293
|
async function listMcpServers(provider, scope, projectDir) {
|
|
689
294
|
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
690
295
|
debug(`listing MCP servers for ${provider.id} (${scope}) at ${configPath ?? "(none)"}`);
|
|
691
|
-
if (!configPath || !
|
|
296
|
+
if (!configPath || !existsSync4(configPath)) return [];
|
|
692
297
|
try {
|
|
693
298
|
const config = await readConfig(configPath, provider.configFormat);
|
|
694
299
|
const servers = getNestedValue(config, provider.configKey);
|
|
@@ -712,7 +317,7 @@ async function listMcpServers(provider, scope, projectDir) {
|
|
|
712
317
|
async function listAgentsMcpServers(scope, projectDir) {
|
|
713
318
|
const serversPath = getAgentsMcpServersPath(scope, projectDir);
|
|
714
319
|
debug(`listing .agents/ MCP servers (${scope}) at ${serversPath}`);
|
|
715
|
-
if (!
|
|
320
|
+
if (!existsSync4(serversPath)) return [];
|
|
716
321
|
try {
|
|
717
322
|
const config = await readConfig(serversPath, "json");
|
|
718
323
|
const servers = config["servers"];
|
|
@@ -930,240 +535,10 @@ function buildServerConfig(source, transport, headers) {
|
|
|
930
535
|
};
|
|
931
536
|
}
|
|
932
537
|
|
|
933
|
-
// src/core/registry/providers.ts
|
|
934
|
-
import { readFileSync } from "fs";
|
|
935
|
-
import { dirname as dirname3, join as join4 } from "path";
|
|
936
|
-
import { fileURLToPath } from "url";
|
|
937
|
-
var DEFAULT_SKILLS_CAPABILITY = {
|
|
938
|
-
agentsGlobalPath: null,
|
|
939
|
-
agentsProjectPath: null,
|
|
940
|
-
precedence: "vendor-only"
|
|
941
|
-
};
|
|
942
|
-
var DEFAULT_HOOKS_CAPABILITY = {
|
|
943
|
-
supported: [],
|
|
944
|
-
hookConfigPath: null,
|
|
945
|
-
hookFormat: null
|
|
946
|
-
};
|
|
947
|
-
var DEFAULT_SPAWN_CAPABILITY = {
|
|
948
|
-
supportsSubagents: false,
|
|
949
|
-
supportsProgrammaticSpawn: false,
|
|
950
|
-
supportsInterAgentComms: false,
|
|
951
|
-
supportsParallelSpawn: false,
|
|
952
|
-
spawnMechanism: null
|
|
953
|
-
};
|
|
954
|
-
function resolveCapabilities(raw) {
|
|
955
|
-
const skills = raw?.skills ? {
|
|
956
|
-
agentsGlobalPath: raw.skills.agentsGlobalPath ? resolveRegistryTemplatePath(raw.skills.agentsGlobalPath) : null,
|
|
957
|
-
agentsProjectPath: raw.skills.agentsProjectPath,
|
|
958
|
-
precedence: raw.skills.precedence
|
|
959
|
-
} : { ...DEFAULT_SKILLS_CAPABILITY };
|
|
960
|
-
const hooks = raw?.hooks ? {
|
|
961
|
-
supported: raw.hooks.supported,
|
|
962
|
-
hookConfigPath: raw.hooks.hookConfigPath ? resolveRegistryTemplatePath(raw.hooks.hookConfigPath) : null,
|
|
963
|
-
hookFormat: raw.hooks.hookFormat
|
|
964
|
-
} : { ...DEFAULT_HOOKS_CAPABILITY, supported: [] };
|
|
965
|
-
const spawn = raw?.spawn ? {
|
|
966
|
-
supportsSubagents: raw.spawn.supportsSubagents,
|
|
967
|
-
supportsProgrammaticSpawn: raw.spawn.supportsProgrammaticSpawn,
|
|
968
|
-
supportsInterAgentComms: raw.spawn.supportsInterAgentComms,
|
|
969
|
-
supportsParallelSpawn: raw.spawn.supportsParallelSpawn,
|
|
970
|
-
spawnMechanism: raw.spawn.spawnMechanism
|
|
971
|
-
} : { ...DEFAULT_SPAWN_CAPABILITY };
|
|
972
|
-
return { skills, hooks, spawn };
|
|
973
|
-
}
|
|
974
|
-
function findRegistryPath() {
|
|
975
|
-
const thisDir = dirname3(fileURLToPath(import.meta.url));
|
|
976
|
-
return resolveProvidersRegistryPath(thisDir);
|
|
977
|
-
}
|
|
978
|
-
var _registry = null;
|
|
979
|
-
var _providers = null;
|
|
980
|
-
var _aliasMap = null;
|
|
981
|
-
function resolveProvider(raw) {
|
|
982
|
-
return {
|
|
983
|
-
id: raw.id,
|
|
984
|
-
toolName: raw.toolName,
|
|
985
|
-
vendor: raw.vendor,
|
|
986
|
-
agentFlag: raw.agentFlag,
|
|
987
|
-
aliases: raw.aliases,
|
|
988
|
-
pathGlobal: resolveRegistryTemplatePath(raw.pathGlobal),
|
|
989
|
-
pathProject: raw.pathProject,
|
|
990
|
-
instructFile: raw.instructFile,
|
|
991
|
-
configKey: raw.configKey,
|
|
992
|
-
configFormat: raw.configFormat,
|
|
993
|
-
configPathGlobal: resolveRegistryTemplatePath(raw.configPathGlobal),
|
|
994
|
-
configPathProject: raw.configPathProject,
|
|
995
|
-
pathSkills: resolveRegistryTemplatePath(raw.pathSkills),
|
|
996
|
-
pathProjectSkills: raw.pathProjectSkills,
|
|
997
|
-
detection: {
|
|
998
|
-
methods: raw.detection.methods,
|
|
999
|
-
binary: raw.detection.binary,
|
|
1000
|
-
directories: raw.detection.directories?.map(resolveRegistryTemplatePath),
|
|
1001
|
-
appBundle: raw.detection.appBundle,
|
|
1002
|
-
flatpakId: raw.detection.flatpakId
|
|
1003
|
-
},
|
|
1004
|
-
supportedTransports: raw.supportedTransports,
|
|
1005
|
-
supportsHeaders: raw.supportsHeaders,
|
|
1006
|
-
priority: raw.priority,
|
|
1007
|
-
status: raw.status,
|
|
1008
|
-
agentSkillsCompatible: raw.agentSkillsCompatible,
|
|
1009
|
-
capabilities: resolveCapabilities(raw.capabilities)
|
|
1010
|
-
};
|
|
1011
|
-
}
|
|
1012
|
-
function loadRegistry() {
|
|
1013
|
-
if (_registry) return _registry;
|
|
1014
|
-
const registryPath = findRegistryPath();
|
|
1015
|
-
const raw = readFileSync(registryPath, "utf-8");
|
|
1016
|
-
_registry = JSON.parse(raw);
|
|
1017
|
-
return _registry;
|
|
1018
|
-
}
|
|
1019
|
-
function ensureProviders() {
|
|
1020
|
-
if (_providers) return;
|
|
1021
|
-
const registry = loadRegistry();
|
|
1022
|
-
_providers = /* @__PURE__ */ new Map();
|
|
1023
|
-
_aliasMap = /* @__PURE__ */ new Map();
|
|
1024
|
-
for (const [id, raw] of Object.entries(registry.providers)) {
|
|
1025
|
-
const provider = resolveProvider(raw);
|
|
1026
|
-
_providers.set(id, provider);
|
|
1027
|
-
for (const alias of provider.aliases) {
|
|
1028
|
-
_aliasMap.set(alias, id);
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
function getAllProviders() {
|
|
1033
|
-
ensureProviders();
|
|
1034
|
-
if (!_providers) return [];
|
|
1035
|
-
return Array.from(_providers.values());
|
|
1036
|
-
}
|
|
1037
|
-
function getProvider(idOrAlias) {
|
|
1038
|
-
ensureProviders();
|
|
1039
|
-
const resolved = _aliasMap?.get(idOrAlias) ?? idOrAlias;
|
|
1040
|
-
return _providers?.get(resolved);
|
|
1041
|
-
}
|
|
1042
|
-
function resolveAlias(idOrAlias) {
|
|
1043
|
-
ensureProviders();
|
|
1044
|
-
return _aliasMap?.get(idOrAlias) ?? idOrAlias;
|
|
1045
|
-
}
|
|
1046
|
-
function getProvidersByPriority(priority) {
|
|
1047
|
-
return getAllProviders().filter((p) => p.priority === priority);
|
|
1048
|
-
}
|
|
1049
|
-
function getProvidersByStatus(status) {
|
|
1050
|
-
return getAllProviders().filter((p) => p.status === status);
|
|
1051
|
-
}
|
|
1052
|
-
function getProvidersByInstructFile(file) {
|
|
1053
|
-
return getAllProviders().filter((p) => p.instructFile === file);
|
|
1054
|
-
}
|
|
1055
|
-
function getInstructionFiles() {
|
|
1056
|
-
const files = /* @__PURE__ */ new Set();
|
|
1057
|
-
for (const p of getAllProviders()) {
|
|
1058
|
-
files.add(p.instructFile);
|
|
1059
|
-
}
|
|
1060
|
-
return Array.from(files);
|
|
1061
|
-
}
|
|
1062
|
-
function getProviderCount() {
|
|
1063
|
-
ensureProviders();
|
|
1064
|
-
return _providers?.size ?? 0;
|
|
1065
|
-
}
|
|
1066
|
-
function getRegistryVersion() {
|
|
1067
|
-
return loadRegistry().version;
|
|
1068
|
-
}
|
|
1069
|
-
function getProvidersByHookEvent(event) {
|
|
1070
|
-
return getAllProviders().filter((p) => p.capabilities.hooks.supported.includes(event));
|
|
1071
|
-
}
|
|
1072
|
-
function getCommonHookEvents(providerIds) {
|
|
1073
|
-
const providers = providerIds && providerIds.length > 0 ? providerIds.map((id) => getProvider(id)).filter((p) => p !== void 0) : getAllProviders();
|
|
1074
|
-
if (providers.length === 0) return [];
|
|
1075
|
-
const first = providers[0].capabilities.hooks.supported;
|
|
1076
|
-
return first.filter(
|
|
1077
|
-
(event) => providers.every((p) => p.capabilities.hooks.supported.includes(event))
|
|
1078
|
-
);
|
|
1079
|
-
}
|
|
1080
|
-
function providerSupports(provider, dotPath) {
|
|
1081
|
-
const parts = dotPath.split(".");
|
|
1082
|
-
let current = provider.capabilities;
|
|
1083
|
-
for (const part of parts) {
|
|
1084
|
-
if (current == null || typeof current !== "object") return false;
|
|
1085
|
-
current = current[part];
|
|
1086
|
-
}
|
|
1087
|
-
if (typeof current === "boolean") return current;
|
|
1088
|
-
if (Array.isArray(current)) return current.length > 0;
|
|
1089
|
-
return current != null;
|
|
1090
|
-
}
|
|
1091
|
-
function getSpawnCapableProviders() {
|
|
1092
|
-
return getAllProviders().filter((p) => p.capabilities.spawn.supportsSubagents);
|
|
1093
|
-
}
|
|
1094
|
-
function getProvidersBySpawnCapability(flag) {
|
|
1095
|
-
return getAllProviders().filter((p) => p.capabilities.spawn[flag] === true);
|
|
1096
|
-
}
|
|
1097
|
-
function getProvidersBySkillsPrecedence(precedence) {
|
|
1098
|
-
return getAllProviders().filter((p) => p.capabilities.skills.precedence === precedence);
|
|
1099
|
-
}
|
|
1100
|
-
function getEffectiveSkillsPaths(provider, scope, projectDir) {
|
|
1101
|
-
const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);
|
|
1102
|
-
const { precedence, agentsGlobalPath, agentsProjectPath } = provider.capabilities.skills;
|
|
1103
|
-
const resolveAgentsPath = () => {
|
|
1104
|
-
if (scope === "global" && agentsGlobalPath) return agentsGlobalPath;
|
|
1105
|
-
if (scope === "project" && agentsProjectPath && projectDir) {
|
|
1106
|
-
return join4(projectDir, agentsProjectPath);
|
|
1107
|
-
}
|
|
1108
|
-
return null;
|
|
1109
|
-
};
|
|
1110
|
-
const agentsPath = resolveAgentsPath();
|
|
1111
|
-
const scopeLabel = scope === "global" ? "global" : "project";
|
|
1112
|
-
switch (precedence) {
|
|
1113
|
-
case "vendor-only":
|
|
1114
|
-
return [{ path: vendorPath, source: "vendor", scope: scopeLabel }];
|
|
1115
|
-
case "agents-canonical":
|
|
1116
|
-
return agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : [];
|
|
1117
|
-
case "agents-first":
|
|
1118
|
-
return [
|
|
1119
|
-
...agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : [],
|
|
1120
|
-
{ path: vendorPath, source: "vendor", scope: scopeLabel }
|
|
1121
|
-
];
|
|
1122
|
-
case "agents-supported":
|
|
1123
|
-
return [
|
|
1124
|
-
{ path: vendorPath, source: "vendor", scope: scopeLabel },
|
|
1125
|
-
...agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : []
|
|
1126
|
-
];
|
|
1127
|
-
case "vendor-global-agents-project":
|
|
1128
|
-
if (scope === "global") {
|
|
1129
|
-
return [{ path: vendorPath, source: "vendor", scope: "global" }];
|
|
1130
|
-
}
|
|
1131
|
-
return [
|
|
1132
|
-
...agentsPath ? [{ path: agentsPath, source: "agents", scope: "project" }] : [],
|
|
1133
|
-
{ path: vendorPath, source: "vendor", scope: "project" }
|
|
1134
|
-
];
|
|
1135
|
-
default:
|
|
1136
|
-
return [{ path: vendorPath, source: "vendor", scope: scopeLabel }];
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
function buildSkillsMap() {
|
|
1140
|
-
return getAllProviders().map((p) => {
|
|
1141
|
-
const { precedence, agentsGlobalPath, agentsProjectPath } = p.capabilities.skills;
|
|
1142
|
-
const isVendorOnly = precedence === "vendor-only";
|
|
1143
|
-
return {
|
|
1144
|
-
providerId: p.id,
|
|
1145
|
-
toolName: p.toolName,
|
|
1146
|
-
precedence,
|
|
1147
|
-
paths: {
|
|
1148
|
-
global: isVendorOnly ? p.pathSkills : agentsGlobalPath ?? null,
|
|
1149
|
-
project: isVendorOnly ? p.pathProjectSkills : agentsProjectPath ?? null
|
|
1150
|
-
}
|
|
1151
|
-
};
|
|
1152
|
-
});
|
|
1153
|
-
}
|
|
1154
|
-
function getProviderCapabilities(idOrAlias) {
|
|
1155
|
-
return getProvider(idOrAlias)?.capabilities;
|
|
1156
|
-
}
|
|
1157
|
-
function providerSupportsById(idOrAlias, capabilityPath) {
|
|
1158
|
-
const provider = getProvider(idOrAlias);
|
|
1159
|
-
if (!provider) return false;
|
|
1160
|
-
return providerSupports(provider, capabilityPath);
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
538
|
// src/core/registry/detection.ts
|
|
1164
539
|
import { execFileSync } from "child_process";
|
|
1165
|
-
import { existsSync as
|
|
1166
|
-
import { join
|
|
540
|
+
import { existsSync as existsSync5 } from "fs";
|
|
541
|
+
import { join } from "path";
|
|
1167
542
|
var DEFAULT_DETECTION_CACHE_TTL_MS = 3e4;
|
|
1168
543
|
var detectionCache = null;
|
|
1169
544
|
function checkBinary(binary) {
|
|
@@ -1176,12 +551,12 @@ function checkBinary(binary) {
|
|
|
1176
551
|
}
|
|
1177
552
|
}
|
|
1178
553
|
function checkDirectory(dir) {
|
|
1179
|
-
return
|
|
554
|
+
return existsSync5(dir);
|
|
1180
555
|
}
|
|
1181
556
|
function checkAppBundle(appName) {
|
|
1182
557
|
if (process.platform !== "darwin") return false;
|
|
1183
558
|
const applications = getPlatformLocations().applications;
|
|
1184
|
-
return applications.some((base) =>
|
|
559
|
+
return applications.some((base) => existsSync5(join(base, appName)));
|
|
1185
560
|
}
|
|
1186
561
|
function checkFlatpak(flatpakId) {
|
|
1187
562
|
if (process.platform !== "linux") return false;
|
|
@@ -1272,7 +647,7 @@ function setCachedResults(signature, results) {
|
|
|
1272
647
|
}
|
|
1273
648
|
function detectProjectProvider(provider, projectDir) {
|
|
1274
649
|
if (!provider.pathProject) return false;
|
|
1275
|
-
return
|
|
650
|
+
return existsSync5(resolveProviderProjectPath(provider, projectDir));
|
|
1276
651
|
}
|
|
1277
652
|
function detectAllProviders(options = {}) {
|
|
1278
653
|
const providers = getAllProviders() ?? [];
|
|
@@ -1301,15 +676,15 @@ function resetDetectionCache() {
|
|
|
1301
676
|
}
|
|
1302
677
|
|
|
1303
678
|
// src/core/skills/installer.ts
|
|
1304
|
-
import { existsSync as
|
|
1305
|
-
import { cp, mkdir
|
|
1306
|
-
import { join as
|
|
679
|
+
import { existsSync as existsSync6, lstatSync } from "fs";
|
|
680
|
+
import { cp, mkdir, rm, symlink } from "fs/promises";
|
|
681
|
+
import { join as join2 } from "path";
|
|
1307
682
|
async function ensureCanonicalDir() {
|
|
1308
|
-
await
|
|
683
|
+
await mkdir(getCanonicalSkillsDir(), { recursive: true });
|
|
1309
684
|
}
|
|
1310
685
|
async function installToCanonical(sourcePath, skillName) {
|
|
1311
686
|
await ensureCanonicalDir();
|
|
1312
|
-
const targetDir =
|
|
687
|
+
const targetDir = join2(getCanonicalSkillsDir(), skillName);
|
|
1313
688
|
await rm(targetDir, { recursive: true, force: true });
|
|
1314
689
|
try {
|
|
1315
690
|
await cp(sourcePath, targetDir, { recursive: true });
|
|
@@ -1334,9 +709,9 @@ async function linkToAgent(canonicalPath, provider, skillName, isGlobal, project
|
|
|
1334
709
|
for (const targetSkillsDir of targetDirs) {
|
|
1335
710
|
if (!targetSkillsDir) continue;
|
|
1336
711
|
try {
|
|
1337
|
-
await
|
|
1338
|
-
const linkPath =
|
|
1339
|
-
if (
|
|
712
|
+
await mkdir(targetSkillsDir, { recursive: true });
|
|
713
|
+
const linkPath = join2(targetSkillsDir, skillName);
|
|
714
|
+
if (existsSync6(linkPath)) {
|
|
1340
715
|
const stat2 = lstatSync(linkPath);
|
|
1341
716
|
if (stat2.isSymbolicLink()) {
|
|
1342
717
|
await rm(linkPath);
|
|
@@ -1392,8 +767,8 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
1392
767
|
let providerRemoved = false;
|
|
1393
768
|
for (const skillsDir of targetDirs) {
|
|
1394
769
|
if (!skillsDir) continue;
|
|
1395
|
-
const linkPath =
|
|
1396
|
-
if (
|
|
770
|
+
const linkPath = join2(skillsDir, skillName);
|
|
771
|
+
if (existsSync6(linkPath)) {
|
|
1397
772
|
try {
|
|
1398
773
|
await rm(linkPath, { recursive: true });
|
|
1399
774
|
providerRemoved = true;
|
|
@@ -1406,8 +781,8 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
1406
781
|
removed.push(provider.id);
|
|
1407
782
|
}
|
|
1408
783
|
}
|
|
1409
|
-
const canonicalPath =
|
|
1410
|
-
if (
|
|
784
|
+
const canonicalPath = join2(getCanonicalSkillsDir(), skillName);
|
|
785
|
+
if (existsSync6(canonicalPath)) {
|
|
1411
786
|
try {
|
|
1412
787
|
await rm(canonicalPath, { recursive: true });
|
|
1413
788
|
} catch (err) {
|
|
@@ -1417,25 +792,25 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
1417
792
|
return { removed, errors };
|
|
1418
793
|
}
|
|
1419
794
|
async function listCanonicalSkills() {
|
|
1420
|
-
if (!
|
|
795
|
+
if (!existsSync6(getCanonicalSkillsDir())) return [];
|
|
1421
796
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1422
797
|
const entries = await readdir2(getCanonicalSkillsDir(), { withFileTypes: true });
|
|
1423
798
|
return entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name);
|
|
1424
799
|
}
|
|
1425
800
|
|
|
1426
801
|
// src/core/advanced/orchestration.ts
|
|
1427
|
-
import { existsSync as
|
|
802
|
+
import { existsSync as existsSync7, lstatSync as lstatSync2 } from "fs";
|
|
1428
803
|
import {
|
|
1429
804
|
cp as cp2,
|
|
1430
|
-
mkdir as
|
|
1431
|
-
readFile as
|
|
805
|
+
mkdir as mkdir2,
|
|
806
|
+
readFile as readFile4,
|
|
1432
807
|
readlink,
|
|
1433
808
|
rm as rm2,
|
|
1434
809
|
symlink as symlink2,
|
|
1435
|
-
writeFile as
|
|
810
|
+
writeFile as writeFile4
|
|
1436
811
|
} from "fs/promises";
|
|
1437
812
|
import { tmpdir } from "os";
|
|
1438
|
-
import { basename, dirname
|
|
813
|
+
import { basename, dirname, join as join3 } from "path";
|
|
1439
814
|
|
|
1440
815
|
// src/core/paths/agents.ts
|
|
1441
816
|
var AGENTS_HOME = getAgentsHome();
|
|
@@ -1456,18 +831,18 @@ function selectProvidersByMinimumPriority(providers, minimumPriority = "low") {
|
|
|
1456
831
|
return [...providers].filter((provider) => PRIORITY_ORDER[provider.priority] <= maxRank).sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);
|
|
1457
832
|
}
|
|
1458
833
|
function resolveSkillLinkPath(provider, skillName, isGlobal, projectDir) {
|
|
1459
|
-
const skillDir = isGlobal ? provider.pathSkills :
|
|
1460
|
-
return
|
|
834
|
+
const skillDir = isGlobal ? provider.pathSkills : join3(projectDir, provider.pathProjectSkills);
|
|
835
|
+
return join3(skillDir, skillName);
|
|
1461
836
|
}
|
|
1462
837
|
async function snapshotConfigs(paths) {
|
|
1463
838
|
const snapshots = /* @__PURE__ */ new Map();
|
|
1464
839
|
for (const path of paths) {
|
|
1465
840
|
if (!path || snapshots.has(path)) continue;
|
|
1466
|
-
if (!
|
|
841
|
+
if (!existsSync7(path)) {
|
|
1467
842
|
snapshots.set(path, null);
|
|
1468
843
|
continue;
|
|
1469
844
|
}
|
|
1470
|
-
snapshots.set(path, await
|
|
845
|
+
snapshots.set(path, await readFile4(path, "utf-8"));
|
|
1471
846
|
}
|
|
1472
847
|
return snapshots;
|
|
1473
848
|
}
|
|
@@ -1477,24 +852,24 @@ async function restoreConfigSnapshots(snapshots) {
|
|
|
1477
852
|
await rm2(path, { force: true });
|
|
1478
853
|
continue;
|
|
1479
854
|
}
|
|
1480
|
-
await
|
|
1481
|
-
await
|
|
855
|
+
await mkdir2(dirname(path), { recursive: true });
|
|
856
|
+
await writeFile4(path, content, "utf-8");
|
|
1482
857
|
}
|
|
1483
858
|
}
|
|
1484
859
|
async function snapshotSkillState(providerTargets, operation, projectDir, backupRoot) {
|
|
1485
860
|
const skillName = operation.skillName;
|
|
1486
861
|
const isGlobal = operation.isGlobal ?? true;
|
|
1487
|
-
const canonicalPath =
|
|
1488
|
-
const canonicalExisted =
|
|
1489
|
-
const canonicalBackupPath =
|
|
862
|
+
const canonicalPath = join3(CANONICAL_SKILLS_DIR, skillName);
|
|
863
|
+
const canonicalExisted = existsSync7(canonicalPath);
|
|
864
|
+
const canonicalBackupPath = join3(backupRoot, "canonical", skillName);
|
|
1490
865
|
if (canonicalExisted) {
|
|
1491
|
-
await
|
|
866
|
+
await mkdir2(dirname(canonicalBackupPath), { recursive: true });
|
|
1492
867
|
await cp2(canonicalPath, canonicalBackupPath, { recursive: true });
|
|
1493
868
|
}
|
|
1494
869
|
const pathSnapshots = [];
|
|
1495
870
|
for (const provider of providerTargets) {
|
|
1496
871
|
const linkPath = resolveSkillLinkPath(provider, skillName, isGlobal, projectDir);
|
|
1497
|
-
if (!
|
|
872
|
+
if (!existsSync7(linkPath)) {
|
|
1498
873
|
pathSnapshots.push({ linkPath, state: "missing" });
|
|
1499
874
|
continue;
|
|
1500
875
|
}
|
|
@@ -1507,8 +882,8 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
1507
882
|
});
|
|
1508
883
|
continue;
|
|
1509
884
|
}
|
|
1510
|
-
const backupPath =
|
|
1511
|
-
await
|
|
885
|
+
const backupPath = join3(backupRoot, "links", provider.id, `${skillName}-${basename(linkPath)}`);
|
|
886
|
+
await mkdir2(dirname(backupPath), { recursive: true });
|
|
1512
887
|
if (stat2.isDirectory()) {
|
|
1513
888
|
await cp2(linkPath, backupPath, { recursive: true });
|
|
1514
889
|
pathSnapshots.push({ linkPath, state: "directory", backupPath });
|
|
@@ -1527,17 +902,17 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
1527
902
|
};
|
|
1528
903
|
}
|
|
1529
904
|
async function restoreSkillSnapshot(snapshot) {
|
|
1530
|
-
if (
|
|
905
|
+
if (existsSync7(snapshot.canonicalPath)) {
|
|
1531
906
|
await rm2(snapshot.canonicalPath, { recursive: true, force: true });
|
|
1532
907
|
}
|
|
1533
|
-
if (snapshot.canonicalExisted && snapshot.canonicalBackupPath &&
|
|
1534
|
-
await
|
|
908
|
+
if (snapshot.canonicalExisted && snapshot.canonicalBackupPath && existsSync7(snapshot.canonicalBackupPath)) {
|
|
909
|
+
await mkdir2(dirname(snapshot.canonicalPath), { recursive: true });
|
|
1535
910
|
await cp2(snapshot.canonicalBackupPath, snapshot.canonicalPath, { recursive: true });
|
|
1536
911
|
}
|
|
1537
912
|
for (const pathSnapshot of snapshot.pathSnapshots) {
|
|
1538
913
|
await rm2(pathSnapshot.linkPath, { recursive: true, force: true });
|
|
1539
914
|
if (pathSnapshot.state === "missing") continue;
|
|
1540
|
-
await
|
|
915
|
+
await mkdir2(dirname(pathSnapshot.linkPath), { recursive: true });
|
|
1541
916
|
if (pathSnapshot.state === "symlink" && pathSnapshot.symlinkTarget) {
|
|
1542
917
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
1543
918
|
await symlink2(pathSnapshot.symlinkTarget, pathSnapshot.linkPath, linkType);
|
|
@@ -1568,7 +943,7 @@ async function installBatchWithRollback(options) {
|
|
|
1568
943
|
return paths;
|
|
1569
944
|
});
|
|
1570
945
|
const configSnapshots = await snapshotConfigs(configPaths);
|
|
1571
|
-
const backupRoot =
|
|
946
|
+
const backupRoot = join3(
|
|
1572
947
|
tmpdir(),
|
|
1573
948
|
`caamp-skill-backup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
1574
949
|
);
|
|
@@ -1759,7 +1134,7 @@ async function updateInstructionsSingleOperation(providers, content, scope = "pr
|
|
|
1759
1134
|
};
|
|
1760
1135
|
for (const [filePath, action] of actions.entries()) {
|
|
1761
1136
|
const providersForFile = providers.filter((provider) => {
|
|
1762
|
-
const expectedPath = scope === "global" ?
|
|
1137
|
+
const expectedPath = scope === "global" ? join3(provider.pathGlobal, provider.instructFile) : join3(projectDir, provider.instructFile);
|
|
1763
1138
|
return expectedPath === filePath;
|
|
1764
1139
|
});
|
|
1765
1140
|
const fallback = groupedByFile.get(basename(filePath)) ?? [];
|
|
@@ -1826,9 +1201,9 @@ async function configureProviderGlobalAndProject(provider, options) {
|
|
|
1826
1201
|
|
|
1827
1202
|
// src/core/mcp/cleo.ts
|
|
1828
1203
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
1829
|
-
import { existsSync as
|
|
1830
|
-
import { homedir
|
|
1831
|
-
import { isAbsolute
|
|
1204
|
+
import { existsSync as existsSync8 } from "fs";
|
|
1205
|
+
import { homedir } from "os";
|
|
1206
|
+
import { isAbsolute, resolve as resolve2 } from "path";
|
|
1832
1207
|
var CLEO_SERVER_NAMES = {
|
|
1833
1208
|
stable: "cleo",
|
|
1834
1209
|
beta: "cleo-beta",
|
|
@@ -1909,9 +1284,9 @@ function buildCleoProfile(options) {
|
|
|
1909
1284
|
};
|
|
1910
1285
|
}
|
|
1911
1286
|
function expandHome(pathValue) {
|
|
1912
|
-
if (pathValue === "~") return
|
|
1287
|
+
if (pathValue === "~") return homedir();
|
|
1913
1288
|
if (pathValue.startsWith("~/")) {
|
|
1914
|
-
return
|
|
1289
|
+
return resolve2(homedir(), pathValue.slice(2));
|
|
1915
1290
|
}
|
|
1916
1291
|
return pathValue;
|
|
1917
1292
|
}
|
|
@@ -1919,8 +1294,8 @@ function checkCommandReachability(command) {
|
|
|
1919
1294
|
const hasPathSeparator = command.includes("/") || command.includes("\\");
|
|
1920
1295
|
if (hasPathSeparator || command.startsWith("~")) {
|
|
1921
1296
|
const expanded = expandHome(command);
|
|
1922
|
-
const candidate =
|
|
1923
|
-
if (
|
|
1297
|
+
const candidate = isAbsolute(expanded) ? expanded : resolve2(process.cwd(), expanded);
|
|
1298
|
+
if (existsSync8(candidate)) {
|
|
1924
1299
|
return { reachable: true, method: "path", detail: candidate };
|
|
1925
1300
|
}
|
|
1926
1301
|
return { reachable: false, method: "path", detail: candidate };
|
|
@@ -1960,12 +1335,12 @@ function isCleoSource(source) {
|
|
|
1960
1335
|
}
|
|
1961
1336
|
|
|
1962
1337
|
// src/core/lock-utils.ts
|
|
1963
|
-
import { open, readFile as
|
|
1964
|
-
import { existsSync as
|
|
1338
|
+
import { open, readFile as readFile5, writeFile as writeFile5, mkdir as mkdir3, rm as rm3, rename, stat } from "fs/promises";
|
|
1339
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1965
1340
|
var LOCK_GUARD_PATH = `${LOCK_FILE_PATH}.lock`;
|
|
1966
1341
|
var STALE_LOCK_MS = 5e3;
|
|
1967
1342
|
function sleep(ms) {
|
|
1968
|
-
return new Promise((
|
|
1343
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
1969
1344
|
}
|
|
1970
1345
|
async function removeStaleLock() {
|
|
1971
1346
|
try {
|
|
@@ -1979,7 +1354,7 @@ async function removeStaleLock() {
|
|
|
1979
1354
|
return false;
|
|
1980
1355
|
}
|
|
1981
1356
|
async function acquireLockGuard(retries = 40, delayMs = 25) {
|
|
1982
|
-
await
|
|
1357
|
+
await mkdir3(AGENTS_HOME, { recursive: true });
|
|
1983
1358
|
for (let attempt = 0; attempt < retries; attempt += 1) {
|
|
1984
1359
|
try {
|
|
1985
1360
|
const handle = await open(LOCK_GUARD_PATH, "wx");
|
|
@@ -2003,15 +1378,15 @@ async function releaseLockGuard() {
|
|
|
2003
1378
|
}
|
|
2004
1379
|
async function writeLockFileUnsafe(lock) {
|
|
2005
1380
|
const tmpPath = `${LOCK_FILE_PATH}.tmp-${process.pid}-${Date.now()}`;
|
|
2006
|
-
await
|
|
1381
|
+
await writeFile5(tmpPath, JSON.stringify(lock, null, 2) + "\n", "utf-8");
|
|
2007
1382
|
await rename(tmpPath, LOCK_FILE_PATH);
|
|
2008
1383
|
}
|
|
2009
1384
|
async function readLockFile() {
|
|
2010
1385
|
try {
|
|
2011
|
-
if (!
|
|
1386
|
+
if (!existsSync9(LOCK_FILE_PATH)) {
|
|
2012
1387
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
2013
1388
|
}
|
|
2014
|
-
const content = await
|
|
1389
|
+
const content = await readFile5(LOCK_FILE_PATH, "utf-8");
|
|
2015
1390
|
return JSON.parse(content);
|
|
2016
1391
|
} catch {
|
|
2017
1392
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
@@ -2626,8 +2001,8 @@ var MarketplaceClient = class {
|
|
|
2626
2001
|
|
|
2627
2002
|
// src/core/skills/library-loader.ts
|
|
2628
2003
|
import { createRequire } from "module";
|
|
2629
|
-
import { existsSync as
|
|
2630
|
-
import { basename as basename2, dirname as
|
|
2004
|
+
import { existsSync as existsSync10, readdirSync, readFileSync } from "fs";
|
|
2005
|
+
import { basename as basename2, dirname as dirname2, join as join4 } from "path";
|
|
2631
2006
|
var require2 = createRequire(import.meta.url);
|
|
2632
2007
|
function loadLibraryFromModule(root) {
|
|
2633
2008
|
let mod;
|
|
@@ -2675,17 +2050,17 @@ function loadLibraryFromModule(root) {
|
|
|
2675
2050
|
return mod;
|
|
2676
2051
|
}
|
|
2677
2052
|
function buildLibraryFromFiles(root) {
|
|
2678
|
-
const catalogPath =
|
|
2679
|
-
if (!
|
|
2053
|
+
const catalogPath = join4(root, "skills.json");
|
|
2054
|
+
if (!existsSync10(catalogPath)) {
|
|
2680
2055
|
throw new Error(`No skills.json found at ${root}`);
|
|
2681
2056
|
}
|
|
2682
|
-
const catalogData = JSON.parse(
|
|
2057
|
+
const catalogData = JSON.parse(readFileSync(catalogPath, "utf-8"));
|
|
2683
2058
|
const entries = catalogData.skills ?? [];
|
|
2684
2059
|
const version = catalogData.version ?? "0.0.0";
|
|
2685
|
-
const manifestPath =
|
|
2060
|
+
const manifestPath = join4(root, "skills", "manifest.json");
|
|
2686
2061
|
let manifest;
|
|
2687
|
-
if (
|
|
2688
|
-
manifest = JSON.parse(
|
|
2062
|
+
if (existsSync10(manifestPath)) {
|
|
2063
|
+
manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
2689
2064
|
} else {
|
|
2690
2065
|
manifest = {
|
|
2691
2066
|
$schema: "",
|
|
@@ -2694,14 +2069,14 @@ function buildLibraryFromFiles(root) {
|
|
|
2694
2069
|
skills: []
|
|
2695
2070
|
};
|
|
2696
2071
|
}
|
|
2697
|
-
const profilesDir =
|
|
2072
|
+
const profilesDir = join4(root, "profiles");
|
|
2698
2073
|
const profiles = /* @__PURE__ */ new Map();
|
|
2699
|
-
if (
|
|
2074
|
+
if (existsSync10(profilesDir)) {
|
|
2700
2075
|
for (const file of readdirSync(profilesDir)) {
|
|
2701
2076
|
if (!file.endsWith(".json")) continue;
|
|
2702
2077
|
try {
|
|
2703
2078
|
const profile = JSON.parse(
|
|
2704
|
-
|
|
2079
|
+
readFileSync(join4(profilesDir, file), "utf-8")
|
|
2705
2080
|
);
|
|
2706
2081
|
profiles.set(profile.name, profile);
|
|
2707
2082
|
} catch {
|
|
@@ -2715,9 +2090,9 @@ function buildLibraryFromFiles(root) {
|
|
|
2715
2090
|
function getSkillDir2(name) {
|
|
2716
2091
|
const entry = skillMap.get(name);
|
|
2717
2092
|
if (entry) {
|
|
2718
|
-
return
|
|
2093
|
+
return dirname2(join4(root, entry.path));
|
|
2719
2094
|
}
|
|
2720
|
-
return
|
|
2095
|
+
return join4(root, "skills", name);
|
|
2721
2096
|
}
|
|
2722
2097
|
function resolveDeps(names, visited = /* @__PURE__ */ new Set()) {
|
|
2723
2098
|
const result = [];
|
|
@@ -2745,7 +2120,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2745
2120
|
return resolveDeps([...new Set(skills)]);
|
|
2746
2121
|
}
|
|
2747
2122
|
function discoverFiles(dir, ext) {
|
|
2748
|
-
if (!
|
|
2123
|
+
if (!existsSync10(dir)) return [];
|
|
2749
2124
|
return readdirSync(dir).filter((f) => f.endsWith(ext)).map((f) => basename2(f, ext));
|
|
2750
2125
|
}
|
|
2751
2126
|
const library = {
|
|
@@ -2762,17 +2137,17 @@ function buildLibraryFromFiles(root) {
|
|
|
2762
2137
|
getSkillPath(name) {
|
|
2763
2138
|
const entry = skillMap.get(name);
|
|
2764
2139
|
if (entry) {
|
|
2765
|
-
return
|
|
2140
|
+
return join4(root, entry.path);
|
|
2766
2141
|
}
|
|
2767
|
-
return
|
|
2142
|
+
return join4(root, "skills", name, "SKILL.md");
|
|
2768
2143
|
},
|
|
2769
2144
|
getSkillDir: getSkillDir2,
|
|
2770
2145
|
readSkillContent(name) {
|
|
2771
2146
|
const skillPath = library.getSkillPath(name);
|
|
2772
|
-
if (!
|
|
2147
|
+
if (!existsSync10(skillPath)) {
|
|
2773
2148
|
throw new Error(`Skill content not found: ${skillPath}`);
|
|
2774
2149
|
}
|
|
2775
|
-
return
|
|
2150
|
+
return readFileSync(skillPath, "utf-8");
|
|
2776
2151
|
},
|
|
2777
2152
|
getCoreSkills() {
|
|
2778
2153
|
return entries.filter((e) => e.core);
|
|
@@ -2796,32 +2171,32 @@ function buildLibraryFromFiles(root) {
|
|
|
2796
2171
|
return resolveProfileByName(name);
|
|
2797
2172
|
},
|
|
2798
2173
|
listSharedResources() {
|
|
2799
|
-
return discoverFiles(
|
|
2174
|
+
return discoverFiles(join4(root, "skills", "_shared"), ".md");
|
|
2800
2175
|
},
|
|
2801
2176
|
getSharedResourcePath(name) {
|
|
2802
|
-
const resourcePath =
|
|
2803
|
-
return
|
|
2177
|
+
const resourcePath = join4(root, "skills", "_shared", `${name}.md`);
|
|
2178
|
+
return existsSync10(resourcePath) ? resourcePath : void 0;
|
|
2804
2179
|
},
|
|
2805
2180
|
readSharedResource(name) {
|
|
2806
2181
|
const resourcePath = library.getSharedResourcePath(name);
|
|
2807
2182
|
if (!resourcePath) return void 0;
|
|
2808
|
-
return
|
|
2183
|
+
return readFileSync(resourcePath, "utf-8");
|
|
2809
2184
|
},
|
|
2810
2185
|
listProtocols() {
|
|
2811
|
-
const rootProtocols = discoverFiles(
|
|
2186
|
+
const rootProtocols = discoverFiles(join4(root, "protocols"), ".md");
|
|
2812
2187
|
if (rootProtocols.length > 0) return rootProtocols;
|
|
2813
|
-
return discoverFiles(
|
|
2188
|
+
return discoverFiles(join4(root, "skills", "protocols"), ".md");
|
|
2814
2189
|
},
|
|
2815
2190
|
getProtocolPath(name) {
|
|
2816
|
-
const rootPath =
|
|
2817
|
-
if (
|
|
2818
|
-
const skillsPath =
|
|
2819
|
-
return
|
|
2191
|
+
const rootPath = join4(root, "protocols", `${name}.md`);
|
|
2192
|
+
if (existsSync10(rootPath)) return rootPath;
|
|
2193
|
+
const skillsPath = join4(root, "skills", "protocols", `${name}.md`);
|
|
2194
|
+
return existsSync10(skillsPath) ? skillsPath : void 0;
|
|
2820
2195
|
},
|
|
2821
2196
|
readProtocol(name) {
|
|
2822
2197
|
const protocolPath = library.getProtocolPath(name);
|
|
2823
2198
|
if (!protocolPath) return void 0;
|
|
2824
|
-
return
|
|
2199
|
+
return readFileSync(protocolPath, "utf-8");
|
|
2825
2200
|
},
|
|
2826
2201
|
validateSkillFrontmatter(name) {
|
|
2827
2202
|
const entry = skillMap.get(name);
|
|
@@ -2841,8 +2216,8 @@ function buildLibraryFromFiles(root) {
|
|
|
2841
2216
|
if (!entry.version) {
|
|
2842
2217
|
issues.push({ level: "warn", field: "version", message: "Missing version" });
|
|
2843
2218
|
}
|
|
2844
|
-
const skillPath =
|
|
2845
|
-
if (!
|
|
2219
|
+
const skillPath = join4(root, entry.path);
|
|
2220
|
+
if (!existsSync10(skillPath)) {
|
|
2846
2221
|
issues.push({ level: "error", field: "path", message: `SKILL.md not found at ${entry.path}` });
|
|
2847
2222
|
}
|
|
2848
2223
|
return {
|
|
@@ -2897,15 +2272,15 @@ __export(catalog_exports, {
|
|
|
2897
2272
|
validateAll: () => validateAll,
|
|
2898
2273
|
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
2899
2274
|
});
|
|
2900
|
-
import { existsSync as
|
|
2901
|
-
import { join as
|
|
2275
|
+
import { existsSync as existsSync11 } from "fs";
|
|
2276
|
+
import { join as join5 } from "path";
|
|
2902
2277
|
var _library = null;
|
|
2903
2278
|
function registerSkillLibrary(library) {
|
|
2904
2279
|
_library = library;
|
|
2905
2280
|
}
|
|
2906
2281
|
function registerSkillLibraryFromPath(root) {
|
|
2907
|
-
const indexPath =
|
|
2908
|
-
if (
|
|
2282
|
+
const indexPath = join5(root, "index.js");
|
|
2283
|
+
if (existsSync11(indexPath)) {
|
|
2909
2284
|
_library = loadLibraryFromModule(root);
|
|
2910
2285
|
return;
|
|
2911
2286
|
}
|
|
@@ -2916,13 +2291,13 @@ function clearRegisteredLibrary() {
|
|
|
2916
2291
|
}
|
|
2917
2292
|
function discoverLibrary() {
|
|
2918
2293
|
const envPath = process.env["CAAMP_SKILL_LIBRARY"];
|
|
2919
|
-
if (envPath &&
|
|
2294
|
+
if (envPath && existsSync11(envPath)) {
|
|
2920
2295
|
try {
|
|
2921
|
-
const indexPath =
|
|
2922
|
-
if (
|
|
2296
|
+
const indexPath = join5(envPath, "index.js");
|
|
2297
|
+
if (existsSync11(indexPath)) {
|
|
2923
2298
|
return loadLibraryFromModule(envPath);
|
|
2924
2299
|
}
|
|
2925
|
-
if (
|
|
2300
|
+
if (existsSync11(join5(envPath, "skills.json"))) {
|
|
2926
2301
|
return buildLibraryFromFiles(envPath);
|
|
2927
2302
|
}
|
|
2928
2303
|
} catch {
|
|
@@ -3029,13 +2404,13 @@ function getLibraryRoot() {
|
|
|
3029
2404
|
}
|
|
3030
2405
|
|
|
3031
2406
|
// src/core/skills/discovery.ts
|
|
3032
|
-
import { readFile as
|
|
3033
|
-
import { existsSync as
|
|
3034
|
-
import { join as
|
|
2407
|
+
import { readFile as readFile6, readdir } from "fs/promises";
|
|
2408
|
+
import { existsSync as existsSync12 } from "fs";
|
|
2409
|
+
import { join as join6 } from "path";
|
|
3035
2410
|
import matter from "gray-matter";
|
|
3036
2411
|
async function parseSkillFile(filePath) {
|
|
3037
2412
|
try {
|
|
3038
|
-
const content = await
|
|
2413
|
+
const content = await readFile6(filePath, "utf-8");
|
|
3039
2414
|
const { data } = matter(content);
|
|
3040
2415
|
if (!data.name || !data.description) {
|
|
3041
2416
|
return null;
|
|
@@ -3055,8 +2430,8 @@ async function parseSkillFile(filePath) {
|
|
|
3055
2430
|
}
|
|
3056
2431
|
}
|
|
3057
2432
|
async function discoverSkill(skillDir) {
|
|
3058
|
-
const skillFile =
|
|
3059
|
-
if (!
|
|
2433
|
+
const skillFile = join6(skillDir, "SKILL.md");
|
|
2434
|
+
if (!existsSync12(skillFile)) return null;
|
|
3060
2435
|
const metadata = await parseSkillFile(skillFile);
|
|
3061
2436
|
if (!metadata) return null;
|
|
3062
2437
|
return {
|
|
@@ -3067,12 +2442,12 @@ async function discoverSkill(skillDir) {
|
|
|
3067
2442
|
};
|
|
3068
2443
|
}
|
|
3069
2444
|
async function discoverSkills(rootDir) {
|
|
3070
|
-
if (!
|
|
2445
|
+
if (!existsSync12(rootDir)) return [];
|
|
3071
2446
|
const entries = await readdir(rootDir, { withFileTypes: true });
|
|
3072
2447
|
const skills = [];
|
|
3073
2448
|
for (const entry of entries) {
|
|
3074
2449
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
3075
|
-
const skillDir =
|
|
2450
|
+
const skillDir = join6(rootDir, entry.name);
|
|
3076
2451
|
const skill = await discoverSkill(skillDir);
|
|
3077
2452
|
if (skill) {
|
|
3078
2453
|
skills.push(skill);
|
|
@@ -3498,8 +2873,8 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
3498
2873
|
}
|
|
3499
2874
|
|
|
3500
2875
|
// src/core/skills/audit/scanner.ts
|
|
3501
|
-
import { existsSync as
|
|
3502
|
-
import { readFile as
|
|
2876
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2877
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
3503
2878
|
|
|
3504
2879
|
// src/core/skills/audit/rules.ts
|
|
3505
2880
|
function rule(id, name, description, severity, category, pattern) {
|
|
@@ -3878,10 +3253,10 @@ var SEVERITY_WEIGHTS = {
|
|
|
3878
3253
|
info: 0
|
|
3879
3254
|
};
|
|
3880
3255
|
async function scanFile(filePath, rules) {
|
|
3881
|
-
if (!
|
|
3256
|
+
if (!existsSync13(filePath)) {
|
|
3882
3257
|
return { file: filePath, findings: [], score: 100, passed: true };
|
|
3883
3258
|
}
|
|
3884
|
-
const content = await
|
|
3259
|
+
const content = await readFile7(filePath, "utf-8");
|
|
3885
3260
|
const lines = content.split("\n");
|
|
3886
3261
|
const activeRules = rules ?? AUDIT_RULES;
|
|
3887
3262
|
const findings = [];
|
|
@@ -3910,14 +3285,14 @@ async function scanFile(filePath, rules) {
|
|
|
3910
3285
|
}
|
|
3911
3286
|
async function scanDirectory(dirPath) {
|
|
3912
3287
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3913
|
-
const { join:
|
|
3914
|
-
if (!
|
|
3288
|
+
const { join: join7 } = await import("path");
|
|
3289
|
+
if (!existsSync13(dirPath)) return [];
|
|
3915
3290
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
3916
3291
|
const results = [];
|
|
3917
3292
|
for (const entry of entries) {
|
|
3918
3293
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
3919
|
-
const skillFile =
|
|
3920
|
-
if (
|
|
3294
|
+
const skillFile = join7(dirPath, entry.name, "SKILL.md");
|
|
3295
|
+
if (existsSync13(skillFile)) {
|
|
3921
3296
|
results.push(await scanFile(skillFile));
|
|
3922
3297
|
}
|
|
3923
3298
|
}
|
|
@@ -3969,8 +3344,8 @@ function toSarif(results) {
|
|
|
3969
3344
|
}
|
|
3970
3345
|
|
|
3971
3346
|
// src/core/skills/validator.ts
|
|
3972
|
-
import { readFile as
|
|
3973
|
-
import { existsSync as
|
|
3347
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
3348
|
+
import { existsSync as existsSync14 } from "fs";
|
|
3974
3349
|
import matter2 from "gray-matter";
|
|
3975
3350
|
var RESERVED_NAMES = [
|
|
3976
3351
|
"anthropic",
|
|
@@ -3991,14 +3366,14 @@ var WARN_BODY_LINES = 500;
|
|
|
3991
3366
|
var WARN_DESCRIPTION_LENGTH = 50;
|
|
3992
3367
|
async function validateSkill(filePath) {
|
|
3993
3368
|
const issues = [];
|
|
3994
|
-
if (!
|
|
3369
|
+
if (!existsSync14(filePath)) {
|
|
3995
3370
|
return {
|
|
3996
3371
|
valid: false,
|
|
3997
3372
|
issues: [{ level: "error", field: "file", message: "File does not exist" }],
|
|
3998
3373
|
metadata: null
|
|
3999
3374
|
};
|
|
4000
3375
|
}
|
|
4001
|
-
const content = await
|
|
3376
|
+
const content = await readFile8(filePath, "utf-8");
|
|
4002
3377
|
if (!content.startsWith("---")) {
|
|
4003
3378
|
issues.push({
|
|
4004
3379
|
level: "error",
|
|
@@ -4104,16 +3479,6 @@ async function validateSkill(filePath) {
|
|
|
4104
3479
|
}
|
|
4105
3480
|
|
|
4106
3481
|
export {
|
|
4107
|
-
checkInjection,
|
|
4108
|
-
inject,
|
|
4109
|
-
removeInjection,
|
|
4110
|
-
checkAllInjections,
|
|
4111
|
-
injectAll,
|
|
4112
|
-
buildInjectionContent,
|
|
4113
|
-
parseInjectionContent,
|
|
4114
|
-
generateInjectionContent,
|
|
4115
|
-
generateSkillsSection,
|
|
4116
|
-
groupByInstructFile,
|
|
4117
3482
|
deepMerge,
|
|
4118
3483
|
getNestedValue,
|
|
4119
3484
|
ensureDir,
|
|
@@ -4126,27 +3491,6 @@ export {
|
|
|
4126
3491
|
readConfig,
|
|
4127
3492
|
writeConfig,
|
|
4128
3493
|
removeConfig,
|
|
4129
|
-
getPlatformPaths,
|
|
4130
|
-
getSystemInfo,
|
|
4131
|
-
_resetPlatformPathsCache,
|
|
4132
|
-
getPlatformLocations,
|
|
4133
|
-
getAgentsHome,
|
|
4134
|
-
getProjectAgentsDir,
|
|
4135
|
-
getCanonicalSkillsDir,
|
|
4136
|
-
getLockFilePath,
|
|
4137
|
-
getAgentsMcpDir,
|
|
4138
|
-
getAgentsMcpServersPath,
|
|
4139
|
-
getAgentsInstructFile,
|
|
4140
|
-
getAgentsConfigPath,
|
|
4141
|
-
getAgentsWikiDir,
|
|
4142
|
-
getAgentsSpecDir,
|
|
4143
|
-
getAgentsLinksDir,
|
|
4144
|
-
resolveRegistryTemplatePath,
|
|
4145
|
-
resolveProviderConfigPath,
|
|
4146
|
-
resolvePreferredConfigScope,
|
|
4147
|
-
resolveProviderSkillsDir,
|
|
4148
|
-
resolveProviderSkillsDirs,
|
|
4149
|
-
buildSkillSubPathCandidates,
|
|
4150
3494
|
resolveConfigPath,
|
|
4151
3495
|
listMcpServers,
|
|
4152
3496
|
listAgentsMcpServers,
|
|
@@ -4157,25 +3501,6 @@ export {
|
|
|
4157
3501
|
installMcpServerToAll,
|
|
4158
3502
|
buildServerConfig,
|
|
4159
3503
|
CANONICAL_SKILLS_DIR,
|
|
4160
|
-
getAllProviders,
|
|
4161
|
-
getProvider,
|
|
4162
|
-
resolveAlias,
|
|
4163
|
-
getProvidersByPriority,
|
|
4164
|
-
getProvidersByStatus,
|
|
4165
|
-
getProvidersByInstructFile,
|
|
4166
|
-
getInstructionFiles,
|
|
4167
|
-
getProviderCount,
|
|
4168
|
-
getRegistryVersion,
|
|
4169
|
-
getProvidersByHookEvent,
|
|
4170
|
-
getCommonHookEvents,
|
|
4171
|
-
providerSupports,
|
|
4172
|
-
getSpawnCapableProviders,
|
|
4173
|
-
getProvidersBySpawnCapability,
|
|
4174
|
-
getProvidersBySkillsPrecedence,
|
|
4175
|
-
getEffectiveSkillsPaths,
|
|
4176
|
-
buildSkillsMap,
|
|
4177
|
-
getProviderCapabilities,
|
|
4178
|
-
providerSupportsById,
|
|
4179
3504
|
detectProvider,
|
|
4180
3505
|
detectAllProviders,
|
|
4181
3506
|
getInstalledProviders,
|
|
@@ -4245,4 +3570,4 @@ export {
|
|
|
4245
3570
|
toSarif,
|
|
4246
3571
|
validateSkill
|
|
4247
3572
|
};
|
|
4248
|
-
//# sourceMappingURL=chunk-
|
|
3573
|
+
//# sourceMappingURL=chunk-YWO4I7LI.js.map
|