@cleocode/caamp 1.4.0 → 1.5.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/dist/{chunk-QZOOTKAJ.js → chunk-G7UPJOYG.js} +264 -121
- package/dist/chunk-G7UPJOYG.js.map +1 -0
- package/dist/cli.js +166 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +5 -1
- package/package.json +1 -1
- package/dist/chunk-QZOOTKAJ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
readConfig,
|
|
51
51
|
readLockFile,
|
|
52
52
|
recommendSkills,
|
|
53
|
+
reconcileCleoLock,
|
|
53
54
|
recordMcpInstall,
|
|
54
55
|
recordSkillInstall,
|
|
55
56
|
removeMcpFromLock,
|
|
@@ -73,7 +74,7 @@ import {
|
|
|
73
74
|
tokenizeCriteriaValue,
|
|
74
75
|
updateInstructionsSingleOperation,
|
|
75
76
|
validateSkill
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-G7UPJOYG.js";
|
|
77
78
|
|
|
78
79
|
// src/cli.ts
|
|
79
80
|
import { Command } from "commander";
|
|
@@ -1173,6 +1174,69 @@ async function checkLockFile() {
|
|
|
1173
1174
|
}
|
|
1174
1175
|
return { name: "Lock File", checks };
|
|
1175
1176
|
}
|
|
1177
|
+
async function checkMcpLockEntries() {
|
|
1178
|
+
const checks = [];
|
|
1179
|
+
try {
|
|
1180
|
+
const lock = await readLockFile();
|
|
1181
|
+
const lockNames = Object.keys(lock.mcpServers);
|
|
1182
|
+
checks.push({ label: `${lockNames.length} MCP server entries in lock`, status: "pass" });
|
|
1183
|
+
const results = detectAllProviders();
|
|
1184
|
+
const installed = results.filter((r) => r.installed);
|
|
1185
|
+
const liveCleoNames = /* @__PURE__ */ new Set();
|
|
1186
|
+
let untrackedCount = 0;
|
|
1187
|
+
for (const scope of ["project", "global"]) {
|
|
1188
|
+
for (const r of installed) {
|
|
1189
|
+
try {
|
|
1190
|
+
const entries = await listMcpServers(r.provider, scope);
|
|
1191
|
+
for (const entry of entries) {
|
|
1192
|
+
const channel = resolveChannelFromServerName(entry.name);
|
|
1193
|
+
if (!channel) continue;
|
|
1194
|
+
liveCleoNames.add(entry.name);
|
|
1195
|
+
if (!lock.mcpServers[entry.name]) {
|
|
1196
|
+
untrackedCount++;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
} catch {
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
if (untrackedCount === 0) {
|
|
1204
|
+
checks.push({ label: "All CLEO servers tracked in lock", status: "pass" });
|
|
1205
|
+
} else {
|
|
1206
|
+
checks.push({
|
|
1207
|
+
label: `${untrackedCount} untracked CLEO server${untrackedCount !== 1 ? "s" : ""} (in config, not in lock)`,
|
|
1208
|
+
status: "warn",
|
|
1209
|
+
detail: "Run `caamp cleo repair` to backfill lock entries"
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
let orphanedCount = 0;
|
|
1213
|
+
const orphanedNames = [];
|
|
1214
|
+
for (const serverName of lockNames) {
|
|
1215
|
+
const channel = resolveChannelFromServerName(serverName);
|
|
1216
|
+
if (!channel) continue;
|
|
1217
|
+
if (!liveCleoNames.has(serverName)) {
|
|
1218
|
+
orphanedCount++;
|
|
1219
|
+
orphanedNames.push(serverName);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
if (orphanedCount === 0) {
|
|
1223
|
+
checks.push({ label: "No orphaned CLEO lock entries", status: "pass" });
|
|
1224
|
+
} else {
|
|
1225
|
+
checks.push({
|
|
1226
|
+
label: `${orphanedCount} orphaned CLEO lock entr${orphanedCount !== 1 ? "ies" : "y"} (in lock, not in any config)`,
|
|
1227
|
+
status: "warn",
|
|
1228
|
+
detail: orphanedNames.join(", ") + " \u2014 Run `caamp cleo repair --prune` to clean up"
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
} catch (err) {
|
|
1232
|
+
checks.push({
|
|
1233
|
+
label: "Failed to check MCP lock entries",
|
|
1234
|
+
status: "fail",
|
|
1235
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
return { name: "MCP Lock", checks };
|
|
1239
|
+
}
|
|
1176
1240
|
async function checkConfigFiles() {
|
|
1177
1241
|
const checks = [];
|
|
1178
1242
|
const results = detectAllProviders();
|
|
@@ -1241,6 +1305,7 @@ function registerDoctorCommand(program2) {
|
|
|
1241
1305
|
sections.push(checkInstalledProviders());
|
|
1242
1306
|
sections.push(checkSkillSymlinks());
|
|
1243
1307
|
sections.push(await checkLockFile());
|
|
1308
|
+
sections.push(await checkMcpLockEntries());
|
|
1244
1309
|
sections.push(await checkConfigFiles());
|
|
1245
1310
|
let passed = 0;
|
|
1246
1311
|
let warnings = 0;
|
|
@@ -1260,6 +1325,7 @@ function registerDoctorCommand(program2) {
|
|
|
1260
1325
|
const detectionResults = detectAllProviders();
|
|
1261
1326
|
const installedProviders = detectionResults.filter((r) => r.installed);
|
|
1262
1327
|
const { canonicalCount, brokenCount, staleCount } = countSkillIssues();
|
|
1328
|
+
const { tracked: mcpTracked, untracked: mcpUntracked, orphaned: mcpOrphaned } = countMcpLockIssues(sections);
|
|
1263
1329
|
const result = {
|
|
1264
1330
|
environment: {
|
|
1265
1331
|
node: getNodeVersion(),
|
|
@@ -1281,6 +1347,11 @@ function registerDoctorCommand(program2) {
|
|
|
1281
1347
|
brokenLinks: brokenCount,
|
|
1282
1348
|
staleLinks: staleCount
|
|
1283
1349
|
},
|
|
1350
|
+
mcpServers: {
|
|
1351
|
+
tracked: mcpTracked,
|
|
1352
|
+
untracked: mcpUntracked,
|
|
1353
|
+
orphaned: mcpOrphaned
|
|
1354
|
+
},
|
|
1284
1355
|
checks: sections.flatMap(
|
|
1285
1356
|
(s) => s.checks.map((c) => ({
|
|
1286
1357
|
label: `${s.name}: ${c.label}`,
|
|
@@ -1377,6 +1448,26 @@ function countSkillIssues() {
|
|
|
1377
1448
|
}
|
|
1378
1449
|
return { canonicalCount, brokenCount, staleCount };
|
|
1379
1450
|
}
|
|
1451
|
+
function countMcpLockIssues(sections) {
|
|
1452
|
+
const mcpSection = sections.find((s) => s.name === "MCP Lock");
|
|
1453
|
+
if (!mcpSection) return { tracked: 0, untracked: 0, orphaned: 0 };
|
|
1454
|
+
let tracked = 0;
|
|
1455
|
+
let untracked = 0;
|
|
1456
|
+
let orphaned = 0;
|
|
1457
|
+
for (const check of mcpSection.checks) {
|
|
1458
|
+
const countMatch = check.label.match(/^(\d+)/);
|
|
1459
|
+
if (!countMatch?.[1]) continue;
|
|
1460
|
+
const count = Number.parseInt(countMatch[1], 10);
|
|
1461
|
+
if (check.label.includes("MCP server entries in lock")) {
|
|
1462
|
+
tracked = count;
|
|
1463
|
+
} else if (check.label.includes("untracked")) {
|
|
1464
|
+
untracked = count;
|
|
1465
|
+
} else if (check.label.includes("orphaned")) {
|
|
1466
|
+
orphaned = count;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return { tracked, untracked, orphaned };
|
|
1470
|
+
}
|
|
1380
1471
|
|
|
1381
1472
|
// src/commands/instructions/inject.ts
|
|
1382
1473
|
import pc3 from "picocolors";
|
|
@@ -2066,14 +2157,14 @@ async function executeCleoShow(opts, operation) {
|
|
|
2066
2157
|
const header = [
|
|
2067
2158
|
"Channel".padEnd(10),
|
|
2068
2159
|
"Version".padEnd(10),
|
|
2069
|
-
"Provider".padEnd(
|
|
2160
|
+
"Provider".padEnd(22),
|
|
2070
2161
|
"Scope".padEnd(9),
|
|
2071
2162
|
"Command".padEnd(33),
|
|
2072
2163
|
"Status".padEnd(10),
|
|
2073
2164
|
"Installed".padEnd(12)
|
|
2074
2165
|
].join("");
|
|
2075
2166
|
console.log(` ${pc6.dim(header)}`);
|
|
2076
|
-
console.log(` ${pc6.dim("-".repeat(
|
|
2167
|
+
console.log(` ${pc6.dim("-".repeat(106))}`);
|
|
2077
2168
|
for (const entry of entries) {
|
|
2078
2169
|
const commandStr = entry.command ? `${entry.command} ${entry.args.join(" ")}`.slice(0, 31).padEnd(33) : pc6.dim("-").padEnd(33);
|
|
2079
2170
|
const versionStr = (entry.version ?? "-").padEnd(10);
|
|
@@ -2087,7 +2178,7 @@ async function executeCleoShow(opts, operation) {
|
|
|
2087
2178
|
statusStr = pc6.red("broken".padEnd(10));
|
|
2088
2179
|
}
|
|
2089
2180
|
console.log(
|
|
2090
|
-
` ${entry.channel.padEnd(10)}${versionStr}${entry.providerName.padEnd(
|
|
2181
|
+
` ${entry.channel.padEnd(10)}${versionStr}${entry.providerName.padEnd(22)}${entry.scope.padEnd(9)}${commandStr}${statusStr}${installedStr}`
|
|
2091
2182
|
);
|
|
2092
2183
|
}
|
|
2093
2184
|
console.log();
|
|
@@ -2121,6 +2212,71 @@ async function executeCleoShow(opts, operation) {
|
|
|
2121
2212
|
);
|
|
2122
2213
|
}
|
|
2123
2214
|
}
|
|
2215
|
+
async function executeCleoRepair(opts, operation) {
|
|
2216
|
+
const mvi = "standard";
|
|
2217
|
+
let format;
|
|
2218
|
+
try {
|
|
2219
|
+
format = resolveFormat({
|
|
2220
|
+
jsonFlag: opts.json ?? false,
|
|
2221
|
+
humanFlag: (opts.human ?? false) || isHuman(),
|
|
2222
|
+
projectDefault: "json"
|
|
2223
|
+
});
|
|
2224
|
+
} catch (error) {
|
|
2225
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2226
|
+
emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
|
|
2227
|
+
process.exit(1);
|
|
2228
|
+
}
|
|
2229
|
+
const providerIds = opts.provider.length > 0 ? opts.provider : void 0;
|
|
2230
|
+
const result = await reconcileCleoLock({
|
|
2231
|
+
providerIds,
|
|
2232
|
+
all: opts.all,
|
|
2233
|
+
global: opts.global,
|
|
2234
|
+
project: opts.project,
|
|
2235
|
+
prune: opts.prune,
|
|
2236
|
+
dryRun: opts.dryRun
|
|
2237
|
+
});
|
|
2238
|
+
if (format === "human") {
|
|
2239
|
+
const prefix = opts.dryRun ? "CLEO Lock Repair (dry run)" : "CLEO Lock Repair";
|
|
2240
|
+
console.log(pc6.bold(prefix));
|
|
2241
|
+
console.log();
|
|
2242
|
+
if (result.backfilled.length > 0) {
|
|
2243
|
+
for (const entry of result.backfilled) {
|
|
2244
|
+
const agents = entry.agents.join(", ");
|
|
2245
|
+
const versionStr = entry.version ? `(${entry.version})` : "";
|
|
2246
|
+
console.log(
|
|
2247
|
+
` ${pc6.green("+")} ${entry.serverName.padEnd(12)}${entry.channel.padEnd(10)}${agents.padEnd(22)}${entry.scope.padEnd(10)}${entry.source} ${pc6.dim(versionStr)}`
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
if (result.pruned.length > 0) {
|
|
2252
|
+
for (const name of result.pruned) {
|
|
2253
|
+
console.log(` ${pc6.red("-")} ${name} (removed from lock)`);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
if (result.backfilled.length === 0 && result.pruned.length === 0) {
|
|
2257
|
+
console.log(pc6.dim(" No changes needed. All CLEO entries are tracked."));
|
|
2258
|
+
}
|
|
2259
|
+
console.log();
|
|
2260
|
+
console.log(
|
|
2261
|
+
` ${result.backfilled.length} backfilled | ${result.pruned.length} pruned | ${result.alreadyTracked} already tracked`
|
|
2262
|
+
);
|
|
2263
|
+
if (result.errors.length > 0) {
|
|
2264
|
+
console.log();
|
|
2265
|
+
for (const err of result.errors) {
|
|
2266
|
+
console.log(` ${pc6.red("!")} ${err.message}`);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if (format === "json") {
|
|
2271
|
+
outputSuccess(operation, mvi, {
|
|
2272
|
+
backfilled: result.backfilled,
|
|
2273
|
+
pruned: result.pruned,
|
|
2274
|
+
alreadyTracked: result.alreadyTracked,
|
|
2275
|
+
dryRun: opts.dryRun ?? false,
|
|
2276
|
+
errors: result.errors
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2124
2280
|
function buildInstallOptions(command) {
|
|
2125
2281
|
return command.requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--version <tag>", "Tag/version for stable or beta").option("--command <command>", "Dev channel command").option("--arg <arg>", "Dev command arg (repeatable)", collect, []).option("--env <kv>", "Environment assignment KEY=value (repeatable)", collect, []).option("--cleo-dir <path>", "CLEO_DIR override for dev channel").option("--dry-run", "Preview without writing").option("-y, --yes", "Skip confirmation").option("--interactive", "Guided interactive setup").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format");
|
|
2126
2282
|
}
|
|
@@ -2142,6 +2298,9 @@ function registerMcpCleoCommands(parent) {
|
|
|
2142
2298
|
cleo.command("show").description("Show installed CLEO MCP channel profiles").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Inspect all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
|
|
2143
2299
|
await executeCleoShow(opts, "mcp.cleo.show");
|
|
2144
2300
|
});
|
|
2301
|
+
cleo.command("repair").description("Repair lock file by backfilling untracked CLEO entries").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Scan all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--prune", "Remove orphaned lock entries not in any config").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
|
|
2302
|
+
await executeCleoRepair(opts, "mcp.cleo.repair");
|
|
2303
|
+
});
|
|
2145
2304
|
}
|
|
2146
2305
|
function registerMcpCleoCompatibilityCommands(parent) {
|
|
2147
2306
|
parent.command("update").description("Update channel-managed MCP profile").argument("<name>", "Managed MCP profile name (cleo)").requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--version <tag>", "Tag/version for stable or beta").option("--command <command>", "Dev channel command").option("--arg <arg>", "Dev command arg (repeatable)", collect, []).option("--env <kv>", "Environment assignment KEY=value (repeatable)", collect, []).option("--cleo-dir <path>", "CLEO_DIR override for dev channel").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (name, opts) => {
|
|
@@ -2206,6 +2365,9 @@ function registerCleoCommands(program2) {
|
|
|
2206
2365
|
cleo.command("show").description("Show installed CLEO channel profiles").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Inspect all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
|
|
2207
2366
|
await executeCleoShow(opts, "cleo.show");
|
|
2208
2367
|
});
|
|
2368
|
+
cleo.command("repair").description("Repair lock file by backfilling untracked CLEO entries").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Scan all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--prune", "Remove orphaned lock entries not in any config").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
|
|
2369
|
+
await executeCleoRepair(opts, "cleo.repair");
|
|
2370
|
+
});
|
|
2209
2371
|
}
|
|
2210
2372
|
|
|
2211
2373
|
// src/commands/mcp/detect.ts
|