@cleocode/caamp 0.4.1 → 0.5.1
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 +32 -10
- package/dist/{chunk-6HQDRJLS.js → chunk-YCSZGZ5W.js} +387 -149
- package/dist/chunk-YCSZGZ5W.js.map +1 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +240 -36
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +307 -3
- package/dist/index.js +19 -1
- package/dist/index.js.map +0 -0
- package/package.json +2 -1
- package/providers/registry.json +0 -49
- package/dist/chunk-6HQDRJLS.js.map +0 -1
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
1
7
|
// src/core/paths/standard.ts
|
|
2
8
|
import { existsSync } from "fs";
|
|
3
9
|
import { homedir } from "os";
|
|
@@ -70,6 +76,33 @@ function getCanonicalSkillsDir() {
|
|
|
70
76
|
function getLockFilePath() {
|
|
71
77
|
return join(getAgentsHome(), ".caamp-lock.json");
|
|
72
78
|
}
|
|
79
|
+
function getAgentsMcpDir(scope = "global", projectDir) {
|
|
80
|
+
if (scope === "global") return join(getAgentsHome(), "mcp");
|
|
81
|
+
return join(projectDir ?? process.cwd(), ".agents", "mcp");
|
|
82
|
+
}
|
|
83
|
+
function getAgentsMcpServersPath(scope = "global", projectDir) {
|
|
84
|
+
return join(getAgentsMcpDir(scope, projectDir), "servers.json");
|
|
85
|
+
}
|
|
86
|
+
function getAgentsInstructFile(scope = "global", projectDir) {
|
|
87
|
+
if (scope === "global") return join(getAgentsHome(), "AGENTS.md");
|
|
88
|
+
return join(projectDir ?? process.cwd(), ".agents", "AGENTS.md");
|
|
89
|
+
}
|
|
90
|
+
function getAgentsConfigPath(scope = "global", projectDir) {
|
|
91
|
+
if (scope === "global") return join(getAgentsHome(), "config.toml");
|
|
92
|
+
return join(projectDir ?? process.cwd(), ".agents", "config.toml");
|
|
93
|
+
}
|
|
94
|
+
function getAgentsWikiDir(scope = "global", projectDir) {
|
|
95
|
+
if (scope === "global") return join(getAgentsHome(), "wiki");
|
|
96
|
+
return join(projectDir ?? process.cwd(), ".agents", "wiki");
|
|
97
|
+
}
|
|
98
|
+
function getAgentsSpecDir(scope = "global", projectDir) {
|
|
99
|
+
if (scope === "global") return join(getAgentsHome(), "spec");
|
|
100
|
+
return join(projectDir ?? process.cwd(), ".agents", "spec");
|
|
101
|
+
}
|
|
102
|
+
function getAgentsLinksDir(scope = "global", projectDir) {
|
|
103
|
+
if (scope === "global") return join(getAgentsHome(), "links");
|
|
104
|
+
return join(projectDir ?? process.cwd(), ".agents", "links");
|
|
105
|
+
}
|
|
73
106
|
function resolveRegistryTemplatePath(template) {
|
|
74
107
|
const locations = getPlatformLocations();
|
|
75
108
|
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());
|
|
@@ -205,16 +238,17 @@ function ensureProviders() {
|
|
|
205
238
|
}
|
|
206
239
|
function getAllProviders() {
|
|
207
240
|
ensureProviders();
|
|
241
|
+
if (!_providers) return [];
|
|
208
242
|
return Array.from(_providers.values());
|
|
209
243
|
}
|
|
210
244
|
function getProvider(idOrAlias) {
|
|
211
245
|
ensureProviders();
|
|
212
|
-
const resolved = _aliasMap
|
|
213
|
-
return _providers
|
|
246
|
+
const resolved = _aliasMap?.get(idOrAlias) ?? idOrAlias;
|
|
247
|
+
return _providers?.get(resolved);
|
|
214
248
|
}
|
|
215
249
|
function resolveAlias(idOrAlias) {
|
|
216
250
|
ensureProviders();
|
|
217
|
-
return _aliasMap
|
|
251
|
+
return _aliasMap?.get(idOrAlias) ?? idOrAlias;
|
|
218
252
|
}
|
|
219
253
|
function getProvidersByPriority(priority) {
|
|
220
254
|
return getAllProviders().filter((p) => p.priority === priority);
|
|
@@ -234,7 +268,7 @@ function getInstructionFiles() {
|
|
|
234
268
|
}
|
|
235
269
|
function getProviderCount() {
|
|
236
270
|
ensureProviders();
|
|
237
|
-
return _providers
|
|
271
|
+
return _providers?.size ?? 0;
|
|
238
272
|
}
|
|
239
273
|
function getRegistryVersion() {
|
|
240
274
|
return loadRegistry().version;
|
|
@@ -411,13 +445,15 @@ function inferName(source, type) {
|
|
|
411
445
|
const url = new URL(source);
|
|
412
446
|
const parts = url.hostname.split(".");
|
|
413
447
|
if (parts.length >= 2) {
|
|
414
|
-
const
|
|
448
|
+
const fallback = parts[0] ?? source;
|
|
449
|
+
const secondLevel = parts[parts.length - 2] ?? fallback;
|
|
450
|
+
const brand = parts.length === 3 ? secondLevel : fallback;
|
|
415
451
|
if (brand !== "www" && brand !== "api" && brand !== "mcp") {
|
|
416
452
|
return brand;
|
|
417
453
|
}
|
|
418
|
-
return
|
|
454
|
+
return secondLevel;
|
|
419
455
|
}
|
|
420
|
-
return parts[0];
|
|
456
|
+
return parts[0] ?? source;
|
|
421
457
|
} catch {
|
|
422
458
|
return source;
|
|
423
459
|
}
|
|
@@ -434,6 +470,11 @@ function inferName(source, type) {
|
|
|
434
470
|
const match = source.match(/\/([^/]+?)(?:\.git)?$/);
|
|
435
471
|
return match?.[1] ?? source;
|
|
436
472
|
}
|
|
473
|
+
if (type === "local") {
|
|
474
|
+
const normalized = source.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
475
|
+
const lastSegment = normalized.split("/").pop();
|
|
476
|
+
return lastSegment ?? source;
|
|
477
|
+
}
|
|
437
478
|
if (type === "command") {
|
|
438
479
|
const parts = source.split(/\s+/);
|
|
439
480
|
const command = parts.find((p) => !p.startsWith("-") && p !== "npx" && p !== "node" && p !== "python" && p !== "python3");
|
|
@@ -444,24 +485,34 @@ function inferName(source, type) {
|
|
|
444
485
|
function parseSource(input) {
|
|
445
486
|
const ghUrlMatch = input.match(GITHUB_URL);
|
|
446
487
|
if (ghUrlMatch) {
|
|
488
|
+
const owner = ghUrlMatch[1];
|
|
489
|
+
const repo = ghUrlMatch[2];
|
|
490
|
+
if (!owner || !repo) {
|
|
491
|
+
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
492
|
+
}
|
|
447
493
|
return {
|
|
448
494
|
type: "github",
|
|
449
495
|
value: input,
|
|
450
|
-
inferredName:
|
|
451
|
-
owner
|
|
452
|
-
repo
|
|
496
|
+
inferredName: repo,
|
|
497
|
+
owner,
|
|
498
|
+
repo,
|
|
453
499
|
ref: ghUrlMatch[3],
|
|
454
500
|
path: ghUrlMatch[4]
|
|
455
501
|
};
|
|
456
502
|
}
|
|
457
503
|
const glUrlMatch = input.match(GITLAB_URL);
|
|
458
504
|
if (glUrlMatch) {
|
|
505
|
+
const owner = glUrlMatch[1];
|
|
506
|
+
const repo = glUrlMatch[2];
|
|
507
|
+
if (!owner || !repo) {
|
|
508
|
+
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
509
|
+
}
|
|
459
510
|
return {
|
|
460
511
|
type: "gitlab",
|
|
461
512
|
value: input,
|
|
462
|
-
inferredName:
|
|
463
|
-
owner
|
|
464
|
-
repo
|
|
513
|
+
inferredName: repo,
|
|
514
|
+
owner,
|
|
515
|
+
repo,
|
|
465
516
|
ref: glUrlMatch[3],
|
|
466
517
|
path: glUrlMatch[4]
|
|
467
518
|
};
|
|
@@ -482,12 +533,17 @@ function parseSource(input) {
|
|
|
482
533
|
}
|
|
483
534
|
const ghShorthand = input.match(GITHUB_SHORTHAND);
|
|
484
535
|
if (ghShorthand && !NPM_SCOPED.test(input)) {
|
|
536
|
+
const owner = ghShorthand[1];
|
|
537
|
+
const repo = ghShorthand[2];
|
|
538
|
+
if (!owner || !repo) {
|
|
539
|
+
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
540
|
+
}
|
|
485
541
|
return {
|
|
486
542
|
type: "github",
|
|
487
|
-
value: `https://github.com/${
|
|
488
|
-
inferredName:
|
|
489
|
-
owner
|
|
490
|
-
repo
|
|
543
|
+
value: `https://github.com/${owner}/${repo}`,
|
|
544
|
+
inferredName: repo,
|
|
545
|
+
owner,
|
|
546
|
+
repo,
|
|
491
547
|
path: ghShorthand[3]
|
|
492
548
|
};
|
|
493
549
|
}
|
|
@@ -524,6 +580,9 @@ import { join as join3 } from "path";
|
|
|
524
580
|
var AGENTS_HOME = getAgentsHome();
|
|
525
581
|
var LOCK_FILE_PATH = getLockFilePath();
|
|
526
582
|
var CANONICAL_SKILLS_DIR = getCanonicalSkillsDir();
|
|
583
|
+
var AGENTS_MCP_DIR = getAgentsMcpDir();
|
|
584
|
+
var AGENTS_MCP_SERVERS_PATH = getAgentsMcpServersPath();
|
|
585
|
+
var AGENTS_CONFIG_PATH = getAgentsConfigPath();
|
|
527
586
|
|
|
528
587
|
// src/core/skills/installer.ts
|
|
529
588
|
async function ensureCanonicalDir() {
|
|
@@ -630,7 +689,7 @@ async function listCanonicalSkills() {
|
|
|
630
689
|
}
|
|
631
690
|
|
|
632
691
|
// src/core/lock-utils.ts
|
|
633
|
-
import { open, readFile
|
|
692
|
+
import { open, readFile, writeFile, mkdir as mkdir2, rm as rm2, rename } from "fs/promises";
|
|
634
693
|
import { existsSync as existsSync4 } from "fs";
|
|
635
694
|
var LOCK_GUARD_PATH = `${LOCK_FILE_PATH}.lock`;
|
|
636
695
|
function sleep(ms) {
|
|
@@ -657,7 +716,7 @@ async function releaseLockGuard() {
|
|
|
657
716
|
}
|
|
658
717
|
async function writeLockFileUnsafe(lock) {
|
|
659
718
|
const tmpPath = `${LOCK_FILE_PATH}.tmp-${process.pid}-${Date.now()}`;
|
|
660
|
-
await
|
|
719
|
+
await writeFile(tmpPath, JSON.stringify(lock, null, 2) + "\n", "utf-8");
|
|
661
720
|
await rename(tmpPath, LOCK_FILE_PATH);
|
|
662
721
|
}
|
|
663
722
|
async function readLockFile() {
|
|
@@ -665,7 +724,7 @@ async function readLockFile() {
|
|
|
665
724
|
if (!existsSync4(LOCK_FILE_PATH)) {
|
|
666
725
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
667
726
|
}
|
|
668
|
-
const content = await
|
|
727
|
+
const content = await readFile(LOCK_FILE_PATH, "utf-8");
|
|
669
728
|
return JSON.parse(content);
|
|
670
729
|
} catch {
|
|
671
730
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
@@ -691,16 +750,16 @@ async function recordSkillInstall(skillName, scopedName, source, sourceType, age
|
|
|
691
750
|
const existing = lock.skills[skillName];
|
|
692
751
|
lock.skills[skillName] = {
|
|
693
752
|
name: skillName,
|
|
694
|
-
scopedName,
|
|
695
|
-
source,
|
|
696
|
-
sourceType,
|
|
697
|
-
version,
|
|
753
|
+
scopedName: existing?.scopedName ?? scopedName,
|
|
754
|
+
source: existing?.source ?? source,
|
|
755
|
+
sourceType: existing?.sourceType ?? sourceType,
|
|
756
|
+
version: version ?? existing?.version,
|
|
698
757
|
installedAt: existing?.installedAt ?? now,
|
|
699
758
|
updatedAt: now,
|
|
700
759
|
agents: [.../* @__PURE__ */ new Set([...existing?.agents ?? [], ...agents])],
|
|
701
760
|
canonicalPath,
|
|
702
|
-
isGlobal,
|
|
703
|
-
projectDir
|
|
761
|
+
isGlobal: existing?.isGlobal ?? isGlobal,
|
|
762
|
+
projectDir: existing?.projectDir ?? projectDir
|
|
704
763
|
};
|
|
705
764
|
});
|
|
706
765
|
}
|
|
@@ -1023,26 +1082,26 @@ var MarketplaceClient = class {
|
|
|
1023
1082
|
};
|
|
1024
1083
|
|
|
1025
1084
|
// src/core/skills/discovery.ts
|
|
1026
|
-
import { readFile as
|
|
1085
|
+
import { readFile as readFile2, readdir } from "fs/promises";
|
|
1027
1086
|
import { existsSync as existsSync5 } from "fs";
|
|
1028
1087
|
import { join as join4 } from "path";
|
|
1029
1088
|
import matter from "gray-matter";
|
|
1030
1089
|
async function parseSkillFile(filePath) {
|
|
1031
1090
|
try {
|
|
1032
|
-
const content = await
|
|
1091
|
+
const content = await readFile2(filePath, "utf-8");
|
|
1033
1092
|
const { data } = matter(content);
|
|
1034
|
-
if (!data
|
|
1093
|
+
if (!data.name || !data.description) {
|
|
1035
1094
|
return null;
|
|
1036
1095
|
}
|
|
1037
|
-
const allowedTools = data["allowed-tools"] ?? data
|
|
1096
|
+
const allowedTools = data["allowed-tools"] ?? data.allowedTools;
|
|
1038
1097
|
return {
|
|
1039
|
-
name: String(data
|
|
1040
|
-
description: String(data
|
|
1041
|
-
license: data
|
|
1042
|
-
compatibility: data
|
|
1043
|
-
metadata: data
|
|
1098
|
+
name: String(data.name),
|
|
1099
|
+
description: String(data.description),
|
|
1100
|
+
license: data.license ? String(data.license) : void 0,
|
|
1101
|
+
compatibility: data.compatibility ? String(data.compatibility) : void 0,
|
|
1102
|
+
metadata: data.metadata,
|
|
1044
1103
|
allowedTools: typeof allowedTools === "string" ? allowedTools.split(/\s+/) : Array.isArray(allowedTools) ? allowedTools.map(String) : void 0,
|
|
1045
|
-
version: data
|
|
1104
|
+
version: data.version ? String(data.version) : void 0
|
|
1046
1105
|
};
|
|
1047
1106
|
} catch {
|
|
1048
1107
|
return null;
|
|
@@ -1089,6 +1148,135 @@ async function discoverSkillsMulti(dirs) {
|
|
|
1089
1148
|
return all;
|
|
1090
1149
|
}
|
|
1091
1150
|
|
|
1151
|
+
// src/core/skills/catalog.ts
|
|
1152
|
+
var catalog_exports = {};
|
|
1153
|
+
__export(catalog_exports, {
|
|
1154
|
+
getCoreSkills: () => getCoreSkills,
|
|
1155
|
+
getDispatchMatrix: () => getDispatchMatrix,
|
|
1156
|
+
getLibraryRoot: () => getLibraryRoot,
|
|
1157
|
+
getManifest: () => getManifest,
|
|
1158
|
+
getProfile: () => getProfile,
|
|
1159
|
+
getProtocolPath: () => getProtocolPath,
|
|
1160
|
+
getSharedResourcePath: () => getSharedResourcePath,
|
|
1161
|
+
getSkill: () => getSkill,
|
|
1162
|
+
getSkillDependencies: () => getSkillDependencies,
|
|
1163
|
+
getSkillDir: () => getSkillDir,
|
|
1164
|
+
getSkillPath: () => getSkillPath,
|
|
1165
|
+
getSkills: () => getSkills,
|
|
1166
|
+
getSkillsByCategory: () => getSkillsByCategory,
|
|
1167
|
+
getVersion: () => getVersion,
|
|
1168
|
+
isCatalogAvailable: () => isCatalogAvailable,
|
|
1169
|
+
listProfiles: () => listProfiles,
|
|
1170
|
+
listProtocols: () => listProtocols,
|
|
1171
|
+
listSharedResources: () => listSharedResources,
|
|
1172
|
+
listSkills: () => listSkills,
|
|
1173
|
+
readProtocol: () => readProtocol,
|
|
1174
|
+
readSharedResource: () => readSharedResource,
|
|
1175
|
+
readSkillContent: () => readSkillContent,
|
|
1176
|
+
resolveDependencyTree: () => resolveDependencyTree,
|
|
1177
|
+
resolveProfile: () => resolveProfile,
|
|
1178
|
+
validateAll: () => validateAll,
|
|
1179
|
+
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
1180
|
+
});
|
|
1181
|
+
import { createRequire } from "module";
|
|
1182
|
+
var require2 = createRequire(import.meta.url);
|
|
1183
|
+
var _ctSkills;
|
|
1184
|
+
function getCtSkills() {
|
|
1185
|
+
if (!_ctSkills) {
|
|
1186
|
+
try {
|
|
1187
|
+
_ctSkills = require2("@cleocode/ct-skills");
|
|
1188
|
+
} catch {
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
"@cleocode/ct-skills is not installed. Run: npm install @cleocode/ct-skills"
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return _ctSkills;
|
|
1195
|
+
}
|
|
1196
|
+
function getSkills() {
|
|
1197
|
+
return getCtSkills().skills;
|
|
1198
|
+
}
|
|
1199
|
+
function getManifest() {
|
|
1200
|
+
return getCtSkills().manifest;
|
|
1201
|
+
}
|
|
1202
|
+
function listSkills() {
|
|
1203
|
+
return getCtSkills().listSkills();
|
|
1204
|
+
}
|
|
1205
|
+
function getSkill(name) {
|
|
1206
|
+
return getCtSkills().getSkill(name);
|
|
1207
|
+
}
|
|
1208
|
+
function getSkillPath(name) {
|
|
1209
|
+
return getCtSkills().getSkillPath(name);
|
|
1210
|
+
}
|
|
1211
|
+
function getSkillDir(name) {
|
|
1212
|
+
return getCtSkills().getSkillDir(name);
|
|
1213
|
+
}
|
|
1214
|
+
function readSkillContent(name) {
|
|
1215
|
+
return getCtSkills().readSkillContent(name);
|
|
1216
|
+
}
|
|
1217
|
+
function getCoreSkills() {
|
|
1218
|
+
return getCtSkills().getCoreSkills();
|
|
1219
|
+
}
|
|
1220
|
+
function getSkillsByCategory(category) {
|
|
1221
|
+
return getCtSkills().getSkillsByCategory(category);
|
|
1222
|
+
}
|
|
1223
|
+
function getSkillDependencies(name) {
|
|
1224
|
+
return getCtSkills().getSkillDependencies(name);
|
|
1225
|
+
}
|
|
1226
|
+
function resolveDependencyTree(names) {
|
|
1227
|
+
return getCtSkills().resolveDependencyTree(names);
|
|
1228
|
+
}
|
|
1229
|
+
function listProfiles() {
|
|
1230
|
+
return getCtSkills().listProfiles();
|
|
1231
|
+
}
|
|
1232
|
+
function getProfile(name) {
|
|
1233
|
+
return getCtSkills().getProfile(name);
|
|
1234
|
+
}
|
|
1235
|
+
function resolveProfile(name) {
|
|
1236
|
+
return getCtSkills().resolveProfile(name);
|
|
1237
|
+
}
|
|
1238
|
+
function listSharedResources() {
|
|
1239
|
+
return getCtSkills().listSharedResources();
|
|
1240
|
+
}
|
|
1241
|
+
function getSharedResourcePath(name) {
|
|
1242
|
+
return getCtSkills().getSharedResourcePath(name);
|
|
1243
|
+
}
|
|
1244
|
+
function readSharedResource(name) {
|
|
1245
|
+
return getCtSkills().readSharedResource(name);
|
|
1246
|
+
}
|
|
1247
|
+
function listProtocols() {
|
|
1248
|
+
return getCtSkills().listProtocols();
|
|
1249
|
+
}
|
|
1250
|
+
function getProtocolPath(name) {
|
|
1251
|
+
return getCtSkills().getProtocolPath(name);
|
|
1252
|
+
}
|
|
1253
|
+
function readProtocol(name) {
|
|
1254
|
+
return getCtSkills().readProtocol(name);
|
|
1255
|
+
}
|
|
1256
|
+
function validateSkillFrontmatter(name) {
|
|
1257
|
+
return getCtSkills().validateSkillFrontmatter(name);
|
|
1258
|
+
}
|
|
1259
|
+
function validateAll() {
|
|
1260
|
+
return getCtSkills().validateAll();
|
|
1261
|
+
}
|
|
1262
|
+
function getDispatchMatrix() {
|
|
1263
|
+
return getCtSkills().getDispatchMatrix();
|
|
1264
|
+
}
|
|
1265
|
+
function getVersion() {
|
|
1266
|
+
return getCtSkills().version;
|
|
1267
|
+
}
|
|
1268
|
+
function getLibraryRoot() {
|
|
1269
|
+
return getCtSkills().libraryRoot;
|
|
1270
|
+
}
|
|
1271
|
+
function isCatalogAvailable() {
|
|
1272
|
+
try {
|
|
1273
|
+
getCtSkills();
|
|
1274
|
+
return true;
|
|
1275
|
+
} catch {
|
|
1276
|
+
return false;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1092
1280
|
// src/core/skills/recommendation.ts
|
|
1093
1281
|
var RECOMMENDATION_ERROR_CODES = {
|
|
1094
1282
|
QUERY_INVALID: "E_SKILLS_QUERY_INVALID",
|
|
@@ -1357,8 +1545,8 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
1357
1545
|
}
|
|
1358
1546
|
|
|
1359
1547
|
// src/core/skills/audit/scanner.ts
|
|
1360
|
-
import { readFile as readFile4 } from "fs/promises";
|
|
1361
1548
|
import { existsSync as existsSync6 } from "fs";
|
|
1549
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
1362
1550
|
|
|
1363
1551
|
// src/core/skills/audit/rules.ts
|
|
1364
1552
|
function rule(id, name, description, severity, category, pattern) {
|
|
@@ -1428,7 +1616,7 @@ var AUDIT_RULES = [
|
|
|
1428
1616
|
"Invisible characters or zero-width spaces",
|
|
1429
1617
|
"medium",
|
|
1430
1618
|
"prompt-injection",
|
|
1431
|
-
/
|
|
1619
|
+
/(?:\u200B|\u200C|\u200D|\u2060|\uFEFF)/
|
|
1432
1620
|
),
|
|
1433
1621
|
// ── Command Injection ───────────────────────────────────────
|
|
1434
1622
|
rule(
|
|
@@ -1740,13 +1928,13 @@ async function scanFile(filePath, rules) {
|
|
|
1740
1928
|
if (!existsSync6(filePath)) {
|
|
1741
1929
|
return { file: filePath, findings: [], score: 100, passed: true };
|
|
1742
1930
|
}
|
|
1743
|
-
const content = await
|
|
1931
|
+
const content = await readFile3(filePath, "utf-8");
|
|
1744
1932
|
const lines = content.split("\n");
|
|
1745
1933
|
const activeRules = rules ?? AUDIT_RULES;
|
|
1746
1934
|
const findings = [];
|
|
1747
1935
|
for (const rule2 of activeRules) {
|
|
1748
1936
|
for (let i = 0; i < lines.length; i++) {
|
|
1749
|
-
const line = lines[i];
|
|
1937
|
+
const line = lines[i] ?? "";
|
|
1750
1938
|
const match = line.match(rule2.pattern);
|
|
1751
1939
|
if (match) {
|
|
1752
1940
|
findings.push({
|
|
@@ -1828,7 +2016,7 @@ function toSarif(results) {
|
|
|
1828
2016
|
}
|
|
1829
2017
|
|
|
1830
2018
|
// src/core/skills/validator.ts
|
|
1831
|
-
import { readFile as
|
|
2019
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
1832
2020
|
import { existsSync as existsSync7 } from "fs";
|
|
1833
2021
|
import matter2 from "gray-matter";
|
|
1834
2022
|
var RESERVED_NAMES = [
|
|
@@ -1857,7 +2045,7 @@ async function validateSkill(filePath) {
|
|
|
1857
2045
|
metadata: null
|
|
1858
2046
|
};
|
|
1859
2047
|
}
|
|
1860
|
-
const content = await
|
|
2048
|
+
const content = await readFile4(filePath, "utf-8");
|
|
1861
2049
|
if (!content.startsWith("---")) {
|
|
1862
2050
|
issues.push({
|
|
1863
2051
|
level: "error",
|
|
@@ -1880,10 +2068,10 @@ async function validateSkill(filePath) {
|
|
|
1880
2068
|
});
|
|
1881
2069
|
return { valid: false, issues, metadata: null };
|
|
1882
2070
|
}
|
|
1883
|
-
if (!data
|
|
2071
|
+
if (!data.name) {
|
|
1884
2072
|
issues.push({ level: "error", field: "name", message: "Missing required field: name" });
|
|
1885
2073
|
} else {
|
|
1886
|
-
const name = String(data
|
|
2074
|
+
const name = String(data.name);
|
|
1887
2075
|
if (name.length > MAX_NAME_LENGTH) {
|
|
1888
2076
|
issues.push({
|
|
1889
2077
|
level: "error",
|
|
@@ -1913,10 +2101,10 @@ async function validateSkill(filePath) {
|
|
|
1913
2101
|
});
|
|
1914
2102
|
}
|
|
1915
2103
|
}
|
|
1916
|
-
if (!data
|
|
2104
|
+
if (!data.description) {
|
|
1917
2105
|
issues.push({ level: "error", field: "description", message: "Missing required field: description" });
|
|
1918
2106
|
} else {
|
|
1919
|
-
const desc = String(data
|
|
2107
|
+
const desc = String(data.description);
|
|
1920
2108
|
if (desc.length > MAX_DESCRIPTION_LENGTH) {
|
|
1921
2109
|
issues.push({
|
|
1922
2110
|
level: "error",
|
|
@@ -1990,17 +2178,17 @@ function getNestedValue(obj, keyPath) {
|
|
|
1990
2178
|
}
|
|
1991
2179
|
async function ensureDir(filePath) {
|
|
1992
2180
|
const { mkdir: mkdir5 } = await import("fs/promises");
|
|
1993
|
-
const { dirname:
|
|
1994
|
-
await mkdir5(
|
|
2181
|
+
const { dirname: dirname5 } = await import("path");
|
|
2182
|
+
await mkdir5(dirname5(filePath), { recursive: true });
|
|
1995
2183
|
}
|
|
1996
2184
|
|
|
1997
2185
|
// src/core/formats/json.ts
|
|
1998
|
-
import { readFile as
|
|
2186
|
+
import { readFile as readFile5, writeFile as writeFile2 } from "fs/promises";
|
|
1999
2187
|
import { existsSync as existsSync8 } from "fs";
|
|
2000
2188
|
import * as jsonc from "jsonc-parser";
|
|
2001
2189
|
async function readJsonConfig(filePath) {
|
|
2002
2190
|
if (!existsSync8(filePath)) return {};
|
|
2003
|
-
const content = await
|
|
2191
|
+
const content = await readFile5(filePath, "utf-8");
|
|
2004
2192
|
if (!content.trim()) return {};
|
|
2005
2193
|
const errors = [];
|
|
2006
2194
|
const result = jsonc.parse(content, errors);
|
|
@@ -2027,7 +2215,7 @@ async function writeJsonConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
2027
2215
|
await ensureDir(filePath);
|
|
2028
2216
|
let content;
|
|
2029
2217
|
if (existsSync8(filePath)) {
|
|
2030
|
-
content = await
|
|
2218
|
+
content = await readFile5(filePath, "utf-8");
|
|
2031
2219
|
if (!content.trim()) {
|
|
2032
2220
|
content = "{}";
|
|
2033
2221
|
}
|
|
@@ -2049,11 +2237,11 @@ async function writeJsonConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
2049
2237
|
if (!content.endsWith("\n")) {
|
|
2050
2238
|
content += "\n";
|
|
2051
2239
|
}
|
|
2052
|
-
await
|
|
2240
|
+
await writeFile2(filePath, content, "utf-8");
|
|
2053
2241
|
}
|
|
2054
2242
|
async function removeJsonConfig(filePath, configKey, serverName) {
|
|
2055
2243
|
if (!existsSync8(filePath)) return false;
|
|
2056
|
-
let content = await
|
|
2244
|
+
let content = await readFile5(filePath, "utf-8");
|
|
2057
2245
|
if (!content.trim()) return false;
|
|
2058
2246
|
const { tabSize, insertSpaces } = detectIndent(content);
|
|
2059
2247
|
const formatOptions = {
|
|
@@ -2069,17 +2257,17 @@ async function removeJsonConfig(filePath, configKey, serverName) {
|
|
|
2069
2257
|
if (!content.endsWith("\n")) {
|
|
2070
2258
|
content += "\n";
|
|
2071
2259
|
}
|
|
2072
|
-
await
|
|
2260
|
+
await writeFile2(filePath, content, "utf-8");
|
|
2073
2261
|
return true;
|
|
2074
2262
|
}
|
|
2075
2263
|
|
|
2076
2264
|
// src/core/formats/yaml.ts
|
|
2077
|
-
import { readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
|
|
2078
2265
|
import { existsSync as existsSync9 } from "fs";
|
|
2266
|
+
import { readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
|
|
2079
2267
|
import yaml from "js-yaml";
|
|
2080
2268
|
async function readYamlConfig(filePath) {
|
|
2081
2269
|
if (!existsSync9(filePath)) return {};
|
|
2082
|
-
const content = await
|
|
2270
|
+
const content = await readFile6(filePath, "utf-8");
|
|
2083
2271
|
if (!content.trim()) return {};
|
|
2084
2272
|
const result = yaml.load(content);
|
|
2085
2273
|
return result ?? {};
|
|
@@ -2089,8 +2277,8 @@ async function writeYamlConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
2089
2277
|
const existing = await readYamlConfig(filePath);
|
|
2090
2278
|
const keyParts = configKey.split(".");
|
|
2091
2279
|
let newEntry = { [serverName]: serverConfig };
|
|
2092
|
-
for (
|
|
2093
|
-
newEntry = { [
|
|
2280
|
+
for (const part of [...keyParts].reverse()) {
|
|
2281
|
+
newEntry = { [part]: newEntry };
|
|
2094
2282
|
}
|
|
2095
2283
|
const merged = deepMerge(existing, newEntry);
|
|
2096
2284
|
const content = yaml.dump(merged, {
|
|
@@ -2099,7 +2287,7 @@ async function writeYamlConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
2099
2287
|
noRefs: true,
|
|
2100
2288
|
sortKeys: false
|
|
2101
2289
|
});
|
|
2102
|
-
await
|
|
2290
|
+
await writeFile3(filePath, content, "utf-8");
|
|
2103
2291
|
}
|
|
2104
2292
|
async function removeYamlConfig(filePath, configKey, serverName) {
|
|
2105
2293
|
if (!existsSync9(filePath)) return false;
|
|
@@ -2119,17 +2307,17 @@ async function removeYamlConfig(filePath, configKey, serverName) {
|
|
|
2119
2307
|
noRefs: true,
|
|
2120
2308
|
sortKeys: false
|
|
2121
2309
|
});
|
|
2122
|
-
await
|
|
2310
|
+
await writeFile3(filePath, content, "utf-8");
|
|
2123
2311
|
return true;
|
|
2124
2312
|
}
|
|
2125
2313
|
|
|
2126
2314
|
// src/core/formats/toml.ts
|
|
2127
|
-
import { readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
|
|
2128
2315
|
import { existsSync as existsSync10 } from "fs";
|
|
2316
|
+
import { readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
|
|
2129
2317
|
import TOML from "@iarna/toml";
|
|
2130
2318
|
async function readTomlConfig(filePath) {
|
|
2131
2319
|
if (!existsSync10(filePath)) return {};
|
|
2132
|
-
const content = await
|
|
2320
|
+
const content = await readFile7(filePath, "utf-8");
|
|
2133
2321
|
if (!content.trim()) return {};
|
|
2134
2322
|
const result = TOML.parse(content);
|
|
2135
2323
|
return result;
|
|
@@ -2139,12 +2327,12 @@ async function writeTomlConfig(filePath, configKey, serverName, serverConfig) {
|
|
|
2139
2327
|
const existing = await readTomlConfig(filePath);
|
|
2140
2328
|
const keyParts = configKey.split(".");
|
|
2141
2329
|
let newEntry = { [serverName]: serverConfig };
|
|
2142
|
-
for (
|
|
2143
|
-
newEntry = { [
|
|
2330
|
+
for (const part of [...keyParts].reverse()) {
|
|
2331
|
+
newEntry = { [part]: newEntry };
|
|
2144
2332
|
}
|
|
2145
2333
|
const merged = deepMerge(existing, newEntry);
|
|
2146
2334
|
const content = TOML.stringify(merged);
|
|
2147
|
-
await
|
|
2335
|
+
await writeFile4(filePath, content, "utf-8");
|
|
2148
2336
|
}
|
|
2149
2337
|
async function removeTomlConfig(filePath, configKey, serverName) {
|
|
2150
2338
|
if (!existsSync10(filePath)) return false;
|
|
@@ -2159,7 +2347,7 @@ async function removeTomlConfig(filePath, configKey, serverName) {
|
|
|
2159
2347
|
if (!(serverName in current)) return false;
|
|
2160
2348
|
delete current[serverName];
|
|
2161
2349
|
const content = TOML.stringify(existing);
|
|
2162
|
-
await
|
|
2350
|
+
await writeFile4(filePath, content, "utf-8");
|
|
2163
2351
|
return true;
|
|
2164
2352
|
}
|
|
2165
2353
|
|
|
@@ -2206,6 +2394,83 @@ async function removeConfig(filePath, format, key, serverName) {
|
|
|
2206
2394
|
}
|
|
2207
2395
|
}
|
|
2208
2396
|
|
|
2397
|
+
// src/core/mcp/reader.ts
|
|
2398
|
+
import { existsSync as existsSync11 } from "fs";
|
|
2399
|
+
function resolveConfigPath(provider, scope, projectDir) {
|
|
2400
|
+
return resolveProviderConfigPath(provider, scope, projectDir ?? process.cwd());
|
|
2401
|
+
}
|
|
2402
|
+
async function listMcpServers(provider, scope, projectDir) {
|
|
2403
|
+
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2404
|
+
debug(`listing MCP servers for ${provider.id} (${scope}) at ${configPath ?? "(none)"}`);
|
|
2405
|
+
if (!configPath || !existsSync11(configPath)) return [];
|
|
2406
|
+
try {
|
|
2407
|
+
const config = await readConfig(configPath, provider.configFormat);
|
|
2408
|
+
const servers = getNestedValue(config, provider.configKey);
|
|
2409
|
+
if (!servers || typeof servers !== "object") return [];
|
|
2410
|
+
const entries = [];
|
|
2411
|
+
for (const [name, cfg] of Object.entries(servers)) {
|
|
2412
|
+
entries.push({
|
|
2413
|
+
name,
|
|
2414
|
+
providerId: provider.id,
|
|
2415
|
+
providerName: provider.toolName,
|
|
2416
|
+
scope,
|
|
2417
|
+
configPath,
|
|
2418
|
+
config: cfg ?? {}
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
2421
|
+
return entries;
|
|
2422
|
+
} catch {
|
|
2423
|
+
return [];
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
async function listAgentsMcpServers(scope, projectDir) {
|
|
2427
|
+
const serversPath = getAgentsMcpServersPath(scope, projectDir);
|
|
2428
|
+
debug(`listing .agents/ MCP servers (${scope}) at ${serversPath}`);
|
|
2429
|
+
if (!existsSync11(serversPath)) return [];
|
|
2430
|
+
try {
|
|
2431
|
+
const config = await readConfig(serversPath, "json");
|
|
2432
|
+
const servers = config["servers"];
|
|
2433
|
+
if (!servers || typeof servers !== "object") return [];
|
|
2434
|
+
const entries = [];
|
|
2435
|
+
for (const [name, cfg] of Object.entries(servers)) {
|
|
2436
|
+
entries.push({
|
|
2437
|
+
name,
|
|
2438
|
+
providerId: ".agents",
|
|
2439
|
+
providerName: ".agents/ standard",
|
|
2440
|
+
scope,
|
|
2441
|
+
configPath: serversPath,
|
|
2442
|
+
config: cfg ?? {}
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2445
|
+
return entries;
|
|
2446
|
+
} catch {
|
|
2447
|
+
return [];
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
async function listAllMcpServers(providers, scope, projectDir) {
|
|
2451
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2452
|
+
const allEntries = [];
|
|
2453
|
+
const agentsServersPath = getAgentsMcpServersPath(scope, projectDir);
|
|
2454
|
+
const agentsEntries = await listAgentsMcpServers(scope, projectDir);
|
|
2455
|
+
if (agentsEntries.length > 0) {
|
|
2456
|
+
allEntries.push(...agentsEntries);
|
|
2457
|
+
seen.add(agentsServersPath);
|
|
2458
|
+
}
|
|
2459
|
+
for (const provider of providers) {
|
|
2460
|
+
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2461
|
+
if (!configPath || seen.has(configPath)) continue;
|
|
2462
|
+
seen.add(configPath);
|
|
2463
|
+
const entries = await listMcpServers(provider, scope, projectDir);
|
|
2464
|
+
allEntries.push(...entries);
|
|
2465
|
+
}
|
|
2466
|
+
return allEntries;
|
|
2467
|
+
}
|
|
2468
|
+
async function removeMcpServer(provider, serverName, scope, projectDir) {
|
|
2469
|
+
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2470
|
+
if (!configPath) return false;
|
|
2471
|
+
return removeConfig(configPath, provider.configFormat, provider.configKey, serverName);
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2209
2474
|
// src/core/mcp/transforms.ts
|
|
2210
2475
|
function transformGoose(serverName, config) {
|
|
2211
2476
|
if (config.url) {
|
|
@@ -2229,7 +2494,7 @@ function transformGoose(serverName, config) {
|
|
|
2229
2494
|
timeout: 300
|
|
2230
2495
|
};
|
|
2231
2496
|
}
|
|
2232
|
-
function transformZed(
|
|
2497
|
+
function transformZed(_serverName, config) {
|
|
2233
2498
|
if (config.url) {
|
|
2234
2499
|
return {
|
|
2235
2500
|
source: "custom",
|
|
@@ -2245,7 +2510,7 @@ function transformZed(serverName, config) {
|
|
|
2245
2510
|
...config.env ? { env: config.env } : {}
|
|
2246
2511
|
};
|
|
2247
2512
|
}
|
|
2248
|
-
function transformOpenCode(
|
|
2513
|
+
function transformOpenCode(_serverName, config) {
|
|
2249
2514
|
if (config.url) {
|
|
2250
2515
|
return {
|
|
2251
2516
|
type: "remote",
|
|
@@ -2262,7 +2527,7 @@ function transformOpenCode(serverName, config) {
|
|
|
2262
2527
|
...config.env ? { environment: config.env } : {}
|
|
2263
2528
|
};
|
|
2264
2529
|
}
|
|
2265
|
-
function transformCodex(
|
|
2530
|
+
function transformCodex(_serverName, config) {
|
|
2266
2531
|
if (config.url) {
|
|
2267
2532
|
return {
|
|
2268
2533
|
type: config.type ?? "http",
|
|
@@ -2276,7 +2541,7 @@ function transformCodex(serverName, config) {
|
|
|
2276
2541
|
...config.env ? { env: config.env } : {}
|
|
2277
2542
|
};
|
|
2278
2543
|
}
|
|
2279
|
-
function transformCursor(
|
|
2544
|
+
function transformCursor(_serverName, config) {
|
|
2280
2545
|
if (config.url) {
|
|
2281
2546
|
return {
|
|
2282
2547
|
url: config.url,
|
|
@@ -2302,53 +2567,6 @@ function getTransform(providerId) {
|
|
|
2302
2567
|
}
|
|
2303
2568
|
}
|
|
2304
2569
|
|
|
2305
|
-
// src/core/mcp/reader.ts
|
|
2306
|
-
import { existsSync as existsSync11 } from "fs";
|
|
2307
|
-
function resolveConfigPath(provider, scope, projectDir) {
|
|
2308
|
-
return resolveProviderConfigPath(provider, scope, projectDir ?? process.cwd());
|
|
2309
|
-
}
|
|
2310
|
-
async function listMcpServers(provider, scope, projectDir) {
|
|
2311
|
-
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2312
|
-
debug(`listing MCP servers for ${provider.id} (${scope}) at ${configPath ?? "(none)"}`);
|
|
2313
|
-
if (!configPath || !existsSync11(configPath)) return [];
|
|
2314
|
-
try {
|
|
2315
|
-
const config = await readConfig(configPath, provider.configFormat);
|
|
2316
|
-
const servers = getNestedValue(config, provider.configKey);
|
|
2317
|
-
if (!servers || typeof servers !== "object") return [];
|
|
2318
|
-
const entries = [];
|
|
2319
|
-
for (const [name, cfg] of Object.entries(servers)) {
|
|
2320
|
-
entries.push({
|
|
2321
|
-
name,
|
|
2322
|
-
providerId: provider.id,
|
|
2323
|
-
providerName: provider.toolName,
|
|
2324
|
-
scope,
|
|
2325
|
-
configPath,
|
|
2326
|
-
config: cfg ?? {}
|
|
2327
|
-
});
|
|
2328
|
-
}
|
|
2329
|
-
return entries;
|
|
2330
|
-
} catch {
|
|
2331
|
-
return [];
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
async function listAllMcpServers(providers, scope, projectDir) {
|
|
2335
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2336
|
-
const allEntries = [];
|
|
2337
|
-
for (const provider of providers) {
|
|
2338
|
-
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2339
|
-
if (!configPath || seen.has(configPath)) continue;
|
|
2340
|
-
seen.add(configPath);
|
|
2341
|
-
const entries = await listMcpServers(provider, scope, projectDir);
|
|
2342
|
-
allEntries.push(...entries);
|
|
2343
|
-
}
|
|
2344
|
-
return allEntries;
|
|
2345
|
-
}
|
|
2346
|
-
async function removeMcpServer(provider, serverName, scope, projectDir) {
|
|
2347
|
-
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
2348
|
-
if (!configPath) return false;
|
|
2349
|
-
return removeConfig(configPath, provider.configFormat, provider.configKey, serverName);
|
|
2350
|
-
}
|
|
2351
|
-
|
|
2352
2570
|
// src/core/mcp/installer.ts
|
|
2353
2571
|
function buildConfig(provider, serverName, config) {
|
|
2354
2572
|
const transform = getTransform(provider.id);
|
|
@@ -2419,9 +2637,10 @@ function buildServerConfig(source, transport, headers) {
|
|
|
2419
2637
|
args: ["-y", source.value]
|
|
2420
2638
|
};
|
|
2421
2639
|
}
|
|
2422
|
-
const parts = source.value.split(/\s+/);
|
|
2640
|
+
const parts = source.value.trim().split(/\s+/);
|
|
2641
|
+
const command = parts[0] ?? source.value;
|
|
2423
2642
|
return {
|
|
2424
|
-
command
|
|
2643
|
+
command,
|
|
2425
2644
|
args: parts.slice(1)
|
|
2426
2645
|
};
|
|
2427
2646
|
}
|
|
@@ -2468,16 +2687,16 @@ async function getLastSelectedAgents() {
|
|
|
2468
2687
|
}
|
|
2469
2688
|
|
|
2470
2689
|
// src/core/instructions/injector.ts
|
|
2471
|
-
import { readFile as
|
|
2690
|
+
import { readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
|
|
2472
2691
|
import { existsSync as existsSync12 } from "fs";
|
|
2473
|
-
import { join as join5, dirname as
|
|
2692
|
+
import { join as join5, dirname as dirname3 } from "path";
|
|
2474
2693
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
2475
2694
|
var MARKER_START = "<!-- CAAMP:START -->";
|
|
2476
2695
|
var MARKER_END = "<!-- CAAMP:END -->";
|
|
2477
2696
|
var MARKER_PATTERN = /<!-- CAAMP:START -->[\s\S]*?<!-- CAAMP:END -->/;
|
|
2478
2697
|
async function checkInjection(filePath, expectedContent) {
|
|
2479
2698
|
if (!existsSync12(filePath)) return "missing";
|
|
2480
|
-
const content = await
|
|
2699
|
+
const content = await readFile8(filePath, "utf-8");
|
|
2481
2700
|
if (!MARKER_PATTERN.test(content)) return "none";
|
|
2482
2701
|
if (expectedContent) {
|
|
2483
2702
|
const blockContent = extractBlock(content);
|
|
@@ -2500,31 +2719,35 @@ ${MARKER_END}`;
|
|
|
2500
2719
|
}
|
|
2501
2720
|
async function inject(filePath, content) {
|
|
2502
2721
|
const block = buildBlock(content);
|
|
2503
|
-
await mkdir3(
|
|
2722
|
+
await mkdir3(dirname3(filePath), { recursive: true });
|
|
2504
2723
|
if (!existsSync12(filePath)) {
|
|
2505
|
-
await
|
|
2724
|
+
await writeFile5(filePath, `${block}
|
|
2725
|
+
`, "utf-8");
|
|
2506
2726
|
return "created";
|
|
2507
2727
|
}
|
|
2508
|
-
const existing = await
|
|
2728
|
+
const existing = await readFile8(filePath, "utf-8");
|
|
2509
2729
|
if (MARKER_PATTERN.test(existing)) {
|
|
2510
2730
|
const updated2 = existing.replace(MARKER_PATTERN, block);
|
|
2511
|
-
await
|
|
2731
|
+
await writeFile5(filePath, updated2, "utf-8");
|
|
2512
2732
|
return "updated";
|
|
2513
2733
|
}
|
|
2514
|
-
const updated = block
|
|
2515
|
-
|
|
2734
|
+
const updated = `${block}
|
|
2735
|
+
|
|
2736
|
+
${existing}`;
|
|
2737
|
+
await writeFile5(filePath, updated, "utf-8");
|
|
2516
2738
|
return "added";
|
|
2517
2739
|
}
|
|
2518
2740
|
async function removeInjection(filePath) {
|
|
2519
2741
|
if (!existsSync12(filePath)) return false;
|
|
2520
|
-
const content = await
|
|
2742
|
+
const content = await readFile8(filePath, "utf-8");
|
|
2521
2743
|
if (!MARKER_PATTERN.test(content)) return false;
|
|
2522
2744
|
const cleaned = content.replace(MARKER_PATTERN, "").replace(/^\n{2,}/, "\n").trim();
|
|
2523
2745
|
if (!cleaned) {
|
|
2524
2746
|
const { rm: rm4 } = await import("fs/promises");
|
|
2525
2747
|
await rm4(filePath);
|
|
2526
2748
|
} else {
|
|
2527
|
-
await
|
|
2749
|
+
await writeFile5(filePath, `${cleaned}
|
|
2750
|
+
`, "utf-8");
|
|
2528
2751
|
}
|
|
2529
2752
|
return true;
|
|
2530
2753
|
}
|
|
@@ -2591,20 +2814,19 @@ import { existsSync as existsSync13, lstatSync as lstatSync2 } from "fs";
|
|
|
2591
2814
|
import {
|
|
2592
2815
|
cp as cp2,
|
|
2593
2816
|
mkdir as mkdir4,
|
|
2594
|
-
readFile as
|
|
2595
|
-
readlink
|
|
2817
|
+
readFile as readFile9,
|
|
2818
|
+
readlink,
|
|
2596
2819
|
rm as rm3,
|
|
2597
2820
|
symlink as symlink2,
|
|
2598
|
-
writeFile as
|
|
2821
|
+
writeFile as writeFile6
|
|
2599
2822
|
} from "fs/promises";
|
|
2600
|
-
import {
|
|
2601
|
-
import { basename
|
|
2823
|
+
import { tmpdir } from "os";
|
|
2824
|
+
import { basename, dirname as dirname4, join as join6 } from "path";
|
|
2602
2825
|
var PRIORITY_ORDER = {
|
|
2603
2826
|
high: 0,
|
|
2604
2827
|
medium: 1,
|
|
2605
2828
|
low: 2
|
|
2606
2829
|
};
|
|
2607
|
-
var CANONICAL_SKILLS_DIR2 = join6(homedir2(), ".agents", "skills");
|
|
2608
2830
|
function selectProvidersByMinimumPriority(providers, minimumPriority = "low") {
|
|
2609
2831
|
const maxRank = PRIORITY_ORDER[minimumPriority];
|
|
2610
2832
|
return [...providers].filter((provider) => PRIORITY_ORDER[provider.priority] <= maxRank).sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);
|
|
@@ -2621,7 +2843,7 @@ async function snapshotConfigs(paths) {
|
|
|
2621
2843
|
snapshots.set(path, null);
|
|
2622
2844
|
continue;
|
|
2623
2845
|
}
|
|
2624
|
-
snapshots.set(path, await
|
|
2846
|
+
snapshots.set(path, await readFile9(path, "utf-8"));
|
|
2625
2847
|
}
|
|
2626
2848
|
return snapshots;
|
|
2627
2849
|
}
|
|
@@ -2631,18 +2853,18 @@ async function restoreConfigSnapshots(snapshots) {
|
|
|
2631
2853
|
await rm3(path, { force: true });
|
|
2632
2854
|
continue;
|
|
2633
2855
|
}
|
|
2634
|
-
await mkdir4(
|
|
2635
|
-
await
|
|
2856
|
+
await mkdir4(dirname4(path), { recursive: true });
|
|
2857
|
+
await writeFile6(path, content, "utf-8");
|
|
2636
2858
|
}
|
|
2637
2859
|
}
|
|
2638
2860
|
async function snapshotSkillState(providerTargets, operation, projectDir, backupRoot) {
|
|
2639
2861
|
const skillName = operation.skillName;
|
|
2640
2862
|
const isGlobal = operation.isGlobal ?? true;
|
|
2641
|
-
const canonicalPath = join6(
|
|
2863
|
+
const canonicalPath = join6(CANONICAL_SKILLS_DIR, skillName);
|
|
2642
2864
|
const canonicalExisted = existsSync13(canonicalPath);
|
|
2643
2865
|
const canonicalBackupPath = join6(backupRoot, "canonical", skillName);
|
|
2644
2866
|
if (canonicalExisted) {
|
|
2645
|
-
await mkdir4(
|
|
2867
|
+
await mkdir4(dirname4(canonicalBackupPath), { recursive: true });
|
|
2646
2868
|
await cp2(canonicalPath, canonicalBackupPath, { recursive: true });
|
|
2647
2869
|
}
|
|
2648
2870
|
const pathSnapshots = [];
|
|
@@ -2657,12 +2879,12 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
2657
2879
|
pathSnapshots.push({
|
|
2658
2880
|
linkPath,
|
|
2659
2881
|
state: "symlink",
|
|
2660
|
-
symlinkTarget: await
|
|
2882
|
+
symlinkTarget: await readlink(linkPath)
|
|
2661
2883
|
});
|
|
2662
2884
|
continue;
|
|
2663
2885
|
}
|
|
2664
|
-
const backupPath = join6(backupRoot, "links", provider.id, `${skillName}-${
|
|
2665
|
-
await mkdir4(
|
|
2886
|
+
const backupPath = join6(backupRoot, "links", provider.id, `${skillName}-${basename(linkPath)}`);
|
|
2887
|
+
await mkdir4(dirname4(backupPath), { recursive: true });
|
|
2666
2888
|
if (stat.isDirectory()) {
|
|
2667
2889
|
await cp2(linkPath, backupPath, { recursive: true });
|
|
2668
2890
|
pathSnapshots.push({ linkPath, state: "directory", backupPath });
|
|
@@ -2685,13 +2907,13 @@ async function restoreSkillSnapshot(snapshot) {
|
|
|
2685
2907
|
await rm3(snapshot.canonicalPath, { recursive: true, force: true });
|
|
2686
2908
|
}
|
|
2687
2909
|
if (snapshot.canonicalExisted && snapshot.canonicalBackupPath && existsSync13(snapshot.canonicalBackupPath)) {
|
|
2688
|
-
await mkdir4(
|
|
2910
|
+
await mkdir4(dirname4(snapshot.canonicalPath), { recursive: true });
|
|
2689
2911
|
await cp2(snapshot.canonicalBackupPath, snapshot.canonicalPath, { recursive: true });
|
|
2690
2912
|
}
|
|
2691
2913
|
for (const pathSnapshot of snapshot.pathSnapshots) {
|
|
2692
2914
|
await rm3(pathSnapshot.linkPath, { recursive: true, force: true });
|
|
2693
2915
|
if (pathSnapshot.state === "missing") continue;
|
|
2694
|
-
await mkdir4(
|
|
2916
|
+
await mkdir4(dirname4(pathSnapshot.linkPath), { recursive: true });
|
|
2695
2917
|
if (pathSnapshot.state === "symlink" && pathSnapshot.symlinkTarget) {
|
|
2696
2918
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
2697
2919
|
await symlink2(pathSnapshot.symlinkTarget, pathSnapshot.linkPath, linkType);
|
|
@@ -2916,7 +3138,7 @@ async function updateInstructionsSingleOperation(providers, content, scope = "pr
|
|
|
2916
3138
|
const expectedPath = scope === "global" ? join6(provider.pathGlobal, provider.instructFile) : join6(projectDir, provider.instructFile);
|
|
2917
3139
|
return expectedPath === filePath;
|
|
2918
3140
|
});
|
|
2919
|
-
const fallback = groupedByFile.get(
|
|
3141
|
+
const fallback = groupedByFile.get(basename(filePath)) ?? [];
|
|
2920
3142
|
const selected = providersForFile.length > 0 ? providersForFile : fallback;
|
|
2921
3143
|
summary.actions.push({
|
|
2922
3144
|
file: filePath,
|
|
@@ -2984,6 +3206,13 @@ export {
|
|
|
2984
3206
|
getProjectAgentsDir,
|
|
2985
3207
|
getCanonicalSkillsDir,
|
|
2986
3208
|
getLockFilePath,
|
|
3209
|
+
getAgentsMcpDir,
|
|
3210
|
+
getAgentsMcpServersPath,
|
|
3211
|
+
getAgentsInstructFile,
|
|
3212
|
+
getAgentsConfigPath,
|
|
3213
|
+
getAgentsWikiDir,
|
|
3214
|
+
getAgentsSpecDir,
|
|
3215
|
+
getAgentsLinksDir,
|
|
2987
3216
|
resolveRegistryTemplatePath,
|
|
2988
3217
|
resolveProviderConfigPath,
|
|
2989
3218
|
resolvePreferredConfigScope,
|
|
@@ -3009,6 +3238,7 @@ export {
|
|
|
3009
3238
|
resetDetectionCache,
|
|
3010
3239
|
parseSource,
|
|
3011
3240
|
isMarketplaceScoped,
|
|
3241
|
+
CANONICAL_SKILLS_DIR,
|
|
3012
3242
|
installSkill,
|
|
3013
3243
|
removeSkill,
|
|
3014
3244
|
listCanonicalSkills,
|
|
@@ -3023,6 +3253,13 @@ export {
|
|
|
3023
3253
|
discoverSkill,
|
|
3024
3254
|
discoverSkills,
|
|
3025
3255
|
discoverSkillsMulti,
|
|
3256
|
+
listSkills,
|
|
3257
|
+
getSkill,
|
|
3258
|
+
getSkillDir,
|
|
3259
|
+
listProfiles,
|
|
3260
|
+
resolveProfile,
|
|
3261
|
+
isCatalogAvailable,
|
|
3262
|
+
catalog_exports,
|
|
3026
3263
|
RECOMMENDATION_ERROR_CODES,
|
|
3027
3264
|
tokenizeCriteriaValue,
|
|
3028
3265
|
validateRecommendationCriteria,
|
|
@@ -3042,11 +3279,12 @@ export {
|
|
|
3042
3279
|
readConfig,
|
|
3043
3280
|
writeConfig,
|
|
3044
3281
|
removeConfig,
|
|
3045
|
-
getTransform,
|
|
3046
3282
|
resolveConfigPath,
|
|
3047
3283
|
listMcpServers,
|
|
3284
|
+
listAgentsMcpServers,
|
|
3048
3285
|
listAllMcpServers,
|
|
3049
3286
|
removeMcpServer,
|
|
3287
|
+
getTransform,
|
|
3050
3288
|
installMcpServer,
|
|
3051
3289
|
installMcpServerToAll,
|
|
3052
3290
|
buildServerConfig,
|
|
@@ -3069,4 +3307,4 @@ export {
|
|
|
3069
3307
|
updateInstructionsSingleOperation,
|
|
3070
3308
|
configureProviderGlobalAndProject
|
|
3071
3309
|
};
|
|
3072
|
-
//# sourceMappingURL=chunk-
|
|
3310
|
+
//# sourceMappingURL=chunk-YCSZGZ5W.js.map
|