@cleocode/caamp 2026.9.18 → 2026.9.19
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-G3CEXEW2.js → chunk-CHPNPLOK.js} +51 -8
- package/dist/chunk-CHPNPLOK.js.map +1 -0
- package/dist/{chunk-52ZWZXEN.js → chunk-IBHW6GEI.js} +227 -43
- package/dist/chunk-IBHW6GEI.js.map +1 -0
- package/dist/cli.js +86 -19
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +196 -2
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/{injector-X5FN7WMR.js → injector-ZUPRC2HS.js} +4 -2
- package/package.json +7 -7
- package/dist/chunk-52ZWZXEN.js.map +0 -1
- package/dist/chunk-G3CEXEW2.js.map +0 -1
- /package/dist/{injector-X5FN7WMR.js.map → injector-ZUPRC2HS.js.map} +0 -0
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
blockPattern,
|
|
2
3
|
getAllProviders,
|
|
3
4
|
getPrimaryProvider,
|
|
4
5
|
groupByInstructFile,
|
|
6
|
+
inject,
|
|
5
7
|
injectAll,
|
|
6
8
|
normalizeMarkers,
|
|
7
9
|
parseBlocks,
|
|
8
10
|
reconcile,
|
|
11
|
+
resolveGlobalInstructionPath,
|
|
12
|
+
resolveInstructionDelivery,
|
|
9
13
|
withFileLock
|
|
10
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-CHPNPLOK.js";
|
|
11
15
|
import {
|
|
12
16
|
__export,
|
|
13
17
|
getAgentsConfigPath,
|
|
@@ -2428,8 +2432,186 @@ async function removeConfig(filePath, format, key, serverName) {
|
|
|
2428
2432
|
}
|
|
2429
2433
|
}
|
|
2430
2434
|
|
|
2431
|
-
// src/core/
|
|
2435
|
+
// src/core/instructions/global-sync.ts
|
|
2436
|
+
import { createHash } from "crypto";
|
|
2432
2437
|
import { existsSync as existsSync8 } from "fs";
|
|
2438
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
2439
|
+
import { homedir as homedir3 } from "os";
|
|
2440
|
+
import {
|
|
2441
|
+
CAAMP_SOURCE_STAMP_PATTERN_SOURCE,
|
|
2442
|
+
GLOBAL_INSTRUCTION_HUB_REFERENCE
|
|
2443
|
+
} from "@cleocode/contracts/caamp-markers";
|
|
2444
|
+
import { writeFileAtomic as writeFileAtomic2 } from "@cleocode/core/tools/fs.js";
|
|
2445
|
+
var LEGACY_CLEO_BLOCK = /\n?<!-- CLEO:START[^>]*-->[\s\S]*?<!-- CLEO:END -->\n?/g;
|
|
2446
|
+
var DUPLICATE_LINE_MIN_LENGTH = 24;
|
|
2447
|
+
var DUPLICATE_LINE_THRESHOLD = 2;
|
|
2448
|
+
function groupGlobalTargets(providers) {
|
|
2449
|
+
const targets = /* @__PURE__ */ new Map();
|
|
2450
|
+
const skipped = [];
|
|
2451
|
+
for (const provider of providers) {
|
|
2452
|
+
const path = resolveGlobalInstructionPath(provider);
|
|
2453
|
+
if (path === null) {
|
|
2454
|
+
skipped.push(provider.id);
|
|
2455
|
+
continue;
|
|
2456
|
+
}
|
|
2457
|
+
targets.set(path, [...targets.get(path) ?? [], provider.id]);
|
|
2458
|
+
}
|
|
2459
|
+
return { targets, skipped };
|
|
2460
|
+
}
|
|
2461
|
+
async function stripLegacyCleoBlock(path) {
|
|
2462
|
+
if (!existsSync8(path)) return false;
|
|
2463
|
+
return withFileLock(path, async () => {
|
|
2464
|
+
const content = await readFile5(path, "utf8");
|
|
2465
|
+
const stripped = content.replace(LEGACY_CLEO_BLOCK, "");
|
|
2466
|
+
if (stripped === content) return false;
|
|
2467
|
+
await writeFileAtomic2({ path, content: stripped });
|
|
2468
|
+
return true;
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
async function syncGlobalInstructions(options = {}) {
|
|
2472
|
+
const providers = options.providers ?? getInstalledProviders();
|
|
2473
|
+
const { targets, skipped } = groupGlobalTargets(providers);
|
|
2474
|
+
const result = {
|
|
2475
|
+
status: "synced",
|
|
2476
|
+
files: [],
|
|
2477
|
+
findings: [],
|
|
2478
|
+
legacyStripped: [],
|
|
2479
|
+
skippedProviders: skipped
|
|
2480
|
+
};
|
|
2481
|
+
if (targets.size === 0) {
|
|
2482
|
+
result.status = "no-providers";
|
|
2483
|
+
return result;
|
|
2484
|
+
}
|
|
2485
|
+
if (options.dryRun) {
|
|
2486
|
+
result.status = "dry-run";
|
|
2487
|
+
for (const [path, ids] of targets) {
|
|
2488
|
+
result.files.push({ path, providers: ids, action: "planned" });
|
|
2489
|
+
}
|
|
2490
|
+
return result;
|
|
2491
|
+
}
|
|
2492
|
+
const delivery = await resolveInstructionDelivery(
|
|
2493
|
+
options.hubReference ?? GLOBAL_INSTRUCTION_HUB_REFERENCE,
|
|
2494
|
+
options.baseDir ?? homedir3()
|
|
2495
|
+
);
|
|
2496
|
+
const blocking = delivery.findings.filter((finding) => finding.kind !== "duplicate");
|
|
2497
|
+
if (blocking.length > 0) {
|
|
2498
|
+
result.status = "unresolved";
|
|
2499
|
+
result.findings = blocking;
|
|
2500
|
+
return result;
|
|
2501
|
+
}
|
|
2502
|
+
for (const [path, ids] of targets) {
|
|
2503
|
+
const entry = { path, providers: ids, action: "intact" };
|
|
2504
|
+
try {
|
|
2505
|
+
if (await stripLegacyCleoBlock(path)) result.legacyStripped.push(path);
|
|
2506
|
+
entry.action = await inject(path, delivery.content);
|
|
2507
|
+
} catch (err) {
|
|
2508
|
+
entry.action = "failed";
|
|
2509
|
+
entry.error = err instanceof Error ? err.message : String(err);
|
|
2510
|
+
}
|
|
2511
|
+
result.files.push(entry);
|
|
2512
|
+
}
|
|
2513
|
+
return result;
|
|
2514
|
+
}
|
|
2515
|
+
async function snapshotSource(path) {
|
|
2516
|
+
try {
|
|
2517
|
+
const bytes = await readFile5(path);
|
|
2518
|
+
return {
|
|
2519
|
+
digest: createHash("sha256").update(bytes).digest("hex"),
|
|
2520
|
+
lines: bytes.toString("utf8").split("\n")
|
|
2521
|
+
};
|
|
2522
|
+
} catch {
|
|
2523
|
+
return { digest: null, lines: [] };
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
function evidenceLine(line) {
|
|
2527
|
+
const trimmed = line.trim();
|
|
2528
|
+
if (trimmed.length < DUPLICATE_LINE_MIN_LENGTH) return null;
|
|
2529
|
+
if (trimmed.startsWith("@") || trimmed.startsWith("<!--")) return null;
|
|
2530
|
+
if (/^(`{3,}|~{3,}|[-|: ]+)$/.test(trimmed)) return null;
|
|
2531
|
+
return trimmed;
|
|
2532
|
+
}
|
|
2533
|
+
async function checkGlobalInstructionStaleness(options = {}) {
|
|
2534
|
+
const providers = options.providers ?? getInstalledProviders();
|
|
2535
|
+
const { targets } = groupGlobalTargets(providers);
|
|
2536
|
+
const sources = /* @__PURE__ */ new Map();
|
|
2537
|
+
const outsideByFile = /* @__PURE__ */ new Map();
|
|
2538
|
+
const files = [];
|
|
2539
|
+
for (const [path, ids] of targets) {
|
|
2540
|
+
const status = {
|
|
2541
|
+
path,
|
|
2542
|
+
providers: ids,
|
|
2543
|
+
state: "current",
|
|
2544
|
+
staleSources: [],
|
|
2545
|
+
duplicateLines: 0
|
|
2546
|
+
};
|
|
2547
|
+
files.push(status);
|
|
2548
|
+
let content;
|
|
2549
|
+
try {
|
|
2550
|
+
content = await readFile5(path, "utf8");
|
|
2551
|
+
} catch {
|
|
2552
|
+
status.state = "absent";
|
|
2553
|
+
continue;
|
|
2554
|
+
}
|
|
2555
|
+
const blocks = parseBlocks(content);
|
|
2556
|
+
if (blocks.length === 0) {
|
|
2557
|
+
status.state = "no-block";
|
|
2558
|
+
continue;
|
|
2559
|
+
}
|
|
2560
|
+
outsideByFile.set(path, content.replace(blockPattern(), ""));
|
|
2561
|
+
const stamps = blocks.flatMap((block) => [
|
|
2562
|
+
...block.content.matchAll(new RegExp(CAAMP_SOURCE_STAMP_PATTERN_SOURCE, "gm"))
|
|
2563
|
+
]);
|
|
2564
|
+
if (stamps.length === 0) {
|
|
2565
|
+
status.state = "unembedded";
|
|
2566
|
+
continue;
|
|
2567
|
+
}
|
|
2568
|
+
for (const stamp of stamps) {
|
|
2569
|
+
const encoded = stamp[1];
|
|
2570
|
+
const expected = stamp[2];
|
|
2571
|
+
if (!encoded || !expected) continue;
|
|
2572
|
+
let source;
|
|
2573
|
+
try {
|
|
2574
|
+
source = decodeURIComponent(encoded);
|
|
2575
|
+
} catch {
|
|
2576
|
+
source = encoded;
|
|
2577
|
+
}
|
|
2578
|
+
let snapshot = sources.get(source);
|
|
2579
|
+
if (!snapshot) {
|
|
2580
|
+
snapshot = await snapshotSource(source);
|
|
2581
|
+
sources.set(source, snapshot);
|
|
2582
|
+
}
|
|
2583
|
+
if (snapshot.digest !== expected && !status.staleSources.includes(source)) {
|
|
2584
|
+
status.staleSources.push(source);
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
if (status.staleSources.length > 0) status.state = "stale";
|
|
2588
|
+
}
|
|
2589
|
+
const managedLines = /* @__PURE__ */ new Set();
|
|
2590
|
+
for (const snapshot of sources.values()) {
|
|
2591
|
+
for (const line of snapshot.lines) {
|
|
2592
|
+
const evidence = evidenceLine(line);
|
|
2593
|
+
if (evidence !== null) managedLines.add(evidence);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
for (const status of files) {
|
|
2597
|
+
const outside = outsideByFile.get(status.path);
|
|
2598
|
+
if (outside === void 0) continue;
|
|
2599
|
+
let matched = 0;
|
|
2600
|
+
for (const line of outside.split("\n")) {
|
|
2601
|
+
const evidence = evidenceLine(line);
|
|
2602
|
+
if (evidence !== null && managedLines.has(evidence)) matched++;
|
|
2603
|
+
}
|
|
2604
|
+
status.duplicateLines = matched >= DUPLICATE_LINE_THRESHOLD ? matched : 0;
|
|
2605
|
+
}
|
|
2606
|
+
return {
|
|
2607
|
+
files,
|
|
2608
|
+
needsSync: files.filter((file) => file.state === "stale" || file.state === "unembedded").map((file) => file.path),
|
|
2609
|
+
duplicates: files.filter((file) => file.duplicateLines > 0).map((file) => file.path)
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
// src/core/mcp/reader.ts
|
|
2614
|
+
import { existsSync as existsSync9 } from "fs";
|
|
2433
2615
|
import { stat as stat2 } from "fs/promises";
|
|
2434
2616
|
function resolveMcpConfigPath(provider, scope, projectDir) {
|
|
2435
2617
|
if (provider.capabilities.mcp === null) return null;
|
|
@@ -2440,7 +2622,7 @@ async function listMcpServers(provider, scope, projectDir) {
|
|
|
2440
2622
|
if (mcp === null) return [];
|
|
2441
2623
|
const configPath = resolveMcpConfigPath(provider, scope, projectDir);
|
|
2442
2624
|
if (configPath === null) return [];
|
|
2443
|
-
if (!
|
|
2625
|
+
if (!existsSync9(configPath)) {
|
|
2444
2626
|
debug(`mcp.list: ${provider.id} (${scope}) \u2014 config file missing at ${configPath}`);
|
|
2445
2627
|
return [];
|
|
2446
2628
|
}
|
|
@@ -2483,7 +2665,7 @@ async function detectMcpInstallations(scope, projectDir) {
|
|
|
2483
2665
|
if (mcp === null) continue;
|
|
2484
2666
|
const configPath = resolveMcpConfigPath(provider, scope, projectDir);
|
|
2485
2667
|
if (configPath === null) continue;
|
|
2486
|
-
const exists =
|
|
2668
|
+
const exists = existsSync9(configPath);
|
|
2487
2669
|
let serverCount = null;
|
|
2488
2670
|
let lastModified = null;
|
|
2489
2671
|
if (exists) {
|
|
@@ -2546,7 +2728,7 @@ async function installMcpServer(provider, serverName, config, opts) {
|
|
|
2546
2728
|
}
|
|
2547
2729
|
|
|
2548
2730
|
// src/core/mcp/remover.ts
|
|
2549
|
-
import { existsSync as
|
|
2731
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2550
2732
|
async function removeMcpServer(provider, serverName, opts) {
|
|
2551
2733
|
const mcp = provider.capabilities.mcp;
|
|
2552
2734
|
if (mcp === null) {
|
|
@@ -2568,7 +2750,7 @@ async function removeMcpServer(provider, serverName, opts) {
|
|
|
2568
2750
|
reason: "no-config-path"
|
|
2569
2751
|
};
|
|
2570
2752
|
}
|
|
2571
|
-
if (!
|
|
2753
|
+
if (!existsSync10(configPath)) {
|
|
2572
2754
|
return {
|
|
2573
2755
|
providerId: provider.id,
|
|
2574
2756
|
serverName,
|
|
@@ -2761,8 +2943,8 @@ function isMarketplaceScoped(input) {
|
|
|
2761
2943
|
}
|
|
2762
2944
|
|
|
2763
2945
|
// src/core/skills/audit/scanner.ts
|
|
2764
|
-
import { existsSync as
|
|
2765
|
-
import { readFile as
|
|
2946
|
+
import { existsSync as existsSync11 } from "fs";
|
|
2947
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
2766
2948
|
|
|
2767
2949
|
// src/core/skills/audit/rules.ts
|
|
2768
2950
|
function rule(id, name, description, severity, category, pattern) {
|
|
@@ -3134,10 +3316,10 @@ var SEVERITY_WEIGHTS = {
|
|
|
3134
3316
|
info: 0
|
|
3135
3317
|
};
|
|
3136
3318
|
async function scanFile(filePath, rules) {
|
|
3137
|
-
if (!
|
|
3319
|
+
if (!existsSync11(filePath)) {
|
|
3138
3320
|
return { file: filePath, findings: [], score: 100, passed: true };
|
|
3139
3321
|
}
|
|
3140
|
-
const content = await
|
|
3322
|
+
const content = await readFile6(filePath, "utf-8");
|
|
3141
3323
|
const lines = content.split("\n");
|
|
3142
3324
|
const activeRules = rules ?? AUDIT_RULES;
|
|
3143
3325
|
const findings = [];
|
|
@@ -3169,13 +3351,13 @@ async function scanFile(filePath, rules) {
|
|
|
3169
3351
|
async function scanDirectory(dirPath) {
|
|
3170
3352
|
const { readdir: readdir3 } = await import("fs/promises");
|
|
3171
3353
|
const { join: join9 } = await import("path");
|
|
3172
|
-
if (!
|
|
3354
|
+
if (!existsSync11(dirPath)) return [];
|
|
3173
3355
|
const entries = await readdir3(dirPath, { withFileTypes: true });
|
|
3174
3356
|
const results = [];
|
|
3175
3357
|
for (const entry of entries) {
|
|
3176
3358
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
3177
3359
|
const skillFile = join9(dirPath, entry.name, "SKILL.md");
|
|
3178
|
-
if (
|
|
3360
|
+
if (existsSync11(skillFile)) {
|
|
3179
3361
|
results.push(await scanFile(skillFile));
|
|
3180
3362
|
}
|
|
3181
3363
|
}
|
|
@@ -3232,9 +3414,9 @@ import { promisify } from "util";
|
|
|
3232
3414
|
import { simpleGit } from "simple-git";
|
|
3233
3415
|
|
|
3234
3416
|
// src/core/lock-utils.ts
|
|
3235
|
-
import { existsSync as
|
|
3236
|
-
import { readFile as
|
|
3237
|
-
import { writeFileAtomic as
|
|
3417
|
+
import { existsSync as existsSync12 } from "fs";
|
|
3418
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
3419
|
+
import { writeFileAtomic as writeFileAtomic3 } from "@cleocode/core/tools/fs.js";
|
|
3238
3420
|
|
|
3239
3421
|
// src/core/paths/agents.ts
|
|
3240
3422
|
var AGENTS_HOME = getAgentsHome();
|
|
@@ -3245,15 +3427,15 @@ var AGENTS_CONFIG_PATH = getAgentsConfigPath();
|
|
|
3245
3427
|
|
|
3246
3428
|
// src/core/lock-utils.ts
|
|
3247
3429
|
async function writeLockFileUnsafe(lock) {
|
|
3248
|
-
await
|
|
3430
|
+
await writeFileAtomic3({ path: LOCK_FILE_PATH, content: `${JSON.stringify(lock, null, 2)}
|
|
3249
3431
|
` });
|
|
3250
3432
|
}
|
|
3251
3433
|
async function readLockFile() {
|
|
3252
3434
|
try {
|
|
3253
|
-
if (!
|
|
3435
|
+
if (!existsSync12(LOCK_FILE_PATH)) {
|
|
3254
3436
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
3255
3437
|
}
|
|
3256
|
-
const content = await
|
|
3438
|
+
const content = await readFile7(LOCK_FILE_PATH, "utf-8");
|
|
3257
3439
|
return JSON.parse(content);
|
|
3258
3440
|
} catch {
|
|
3259
3441
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
@@ -3978,7 +4160,7 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
3978
4160
|
}
|
|
3979
4161
|
|
|
3980
4162
|
// src/core/skills/library-loader.ts
|
|
3981
|
-
import { existsSync as
|
|
4163
|
+
import { existsSync as existsSync13, readdirSync, readFileSync } from "fs";
|
|
3982
4164
|
import { createRequire } from "module";
|
|
3983
4165
|
import { basename as basename3, dirname as dirname3, join as join6 } from "path";
|
|
3984
4166
|
var require2 = createRequire(import.meta.url);
|
|
@@ -4027,7 +4209,7 @@ function loadLibraryFromModule(root) {
|
|
|
4027
4209
|
}
|
|
4028
4210
|
function buildLibraryFromFiles(root) {
|
|
4029
4211
|
const catalogPath = join6(root, "skills.json");
|
|
4030
|
-
if (!
|
|
4212
|
+
if (!existsSync13(catalogPath)) {
|
|
4031
4213
|
throw new Error(`No skills.json found at ${root}`);
|
|
4032
4214
|
}
|
|
4033
4215
|
const catalogData = JSON.parse(readFileSync(catalogPath, "utf-8"));
|
|
@@ -4035,7 +4217,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4035
4217
|
const version = catalogData.version ?? "0.0.0";
|
|
4036
4218
|
const manifestPath = join6(root, "skills", "manifest.json");
|
|
4037
4219
|
let manifest;
|
|
4038
|
-
if (
|
|
4220
|
+
if (existsSync13(manifestPath)) {
|
|
4039
4221
|
manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
4040
4222
|
} else {
|
|
4041
4223
|
manifest = {
|
|
@@ -4047,7 +4229,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4047
4229
|
}
|
|
4048
4230
|
const profilesDir = join6(root, "profiles");
|
|
4049
4231
|
const profiles = /* @__PURE__ */ new Map();
|
|
4050
|
-
if (
|
|
4232
|
+
if (existsSync13(profilesDir)) {
|
|
4051
4233
|
for (const file of readdirSync(profilesDir)) {
|
|
4052
4234
|
if (!file.endsWith(".json")) continue;
|
|
4053
4235
|
try {
|
|
@@ -4096,7 +4278,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4096
4278
|
return resolveDeps([...new Set(skills)]);
|
|
4097
4279
|
}
|
|
4098
4280
|
function discoverFiles(dir, ext) {
|
|
4099
|
-
if (!
|
|
4281
|
+
if (!existsSync13(dir)) return [];
|
|
4100
4282
|
return readdirSync(dir).filter((f) => f.endsWith(ext)).map((f) => basename3(f, ext));
|
|
4101
4283
|
}
|
|
4102
4284
|
const library = {
|
|
@@ -4120,7 +4302,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4120
4302
|
getSkillDir: getSkillDir2,
|
|
4121
4303
|
readSkillContent(name) {
|
|
4122
4304
|
const skillPath = library.getSkillPath(name);
|
|
4123
|
-
if (!
|
|
4305
|
+
if (!existsSync13(skillPath)) {
|
|
4124
4306
|
throw new Error(`Skill content not found: ${skillPath}`);
|
|
4125
4307
|
}
|
|
4126
4308
|
return readFileSync(skillPath, "utf-8");
|
|
@@ -4151,7 +4333,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4151
4333
|
},
|
|
4152
4334
|
getSharedResourcePath(name) {
|
|
4153
4335
|
const resourcePath = join6(root, "skills", "_shared", `${name}.md`);
|
|
4154
|
-
return
|
|
4336
|
+
return existsSync13(resourcePath) ? resourcePath : void 0;
|
|
4155
4337
|
},
|
|
4156
4338
|
readSharedResource(name) {
|
|
4157
4339
|
const resourcePath = library.getSharedResourcePath(name);
|
|
@@ -4165,9 +4347,9 @@ function buildLibraryFromFiles(root) {
|
|
|
4165
4347
|
},
|
|
4166
4348
|
getProtocolPath(name) {
|
|
4167
4349
|
const rootPath = join6(root, "protocols", `${name}.md`);
|
|
4168
|
-
if (
|
|
4350
|
+
if (existsSync13(rootPath)) return rootPath;
|
|
4169
4351
|
const skillsPath = join6(root, "skills", "protocols", `${name}.md`);
|
|
4170
|
-
return
|
|
4352
|
+
return existsSync13(skillsPath) ? skillsPath : void 0;
|
|
4171
4353
|
},
|
|
4172
4354
|
readProtocol(name) {
|
|
4173
4355
|
const protocolPath = library.getProtocolPath(name);
|
|
@@ -4193,7 +4375,7 @@ function buildLibraryFromFiles(root) {
|
|
|
4193
4375
|
issues.push({ level: "warn", field: "version", message: "Missing version" });
|
|
4194
4376
|
}
|
|
4195
4377
|
const skillPath = join6(root, entry.path);
|
|
4196
|
-
if (!
|
|
4378
|
+
if (!existsSync13(skillPath)) {
|
|
4197
4379
|
issues.push({
|
|
4198
4380
|
level: "error",
|
|
4199
4381
|
field: "path",
|
|
@@ -4252,7 +4434,7 @@ __export(catalog_exports, {
|
|
|
4252
4434
|
validateAll: () => validateAll,
|
|
4253
4435
|
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
4254
4436
|
});
|
|
4255
|
-
import { existsSync as
|
|
4437
|
+
import { existsSync as existsSync14 } from "fs";
|
|
4256
4438
|
import { join as join7 } from "path";
|
|
4257
4439
|
var _library = null;
|
|
4258
4440
|
function registerSkillLibrary(library) {
|
|
@@ -4260,7 +4442,7 @@ function registerSkillLibrary(library) {
|
|
|
4260
4442
|
}
|
|
4261
4443
|
function registerSkillLibraryFromPath(root) {
|
|
4262
4444
|
const indexPath = join7(root, "index.js");
|
|
4263
|
-
if (
|
|
4445
|
+
if (existsSync14(indexPath)) {
|
|
4264
4446
|
_library = loadLibraryFromModule(root);
|
|
4265
4447
|
return;
|
|
4266
4448
|
}
|
|
@@ -4271,13 +4453,13 @@ function clearRegisteredLibrary() {
|
|
|
4271
4453
|
}
|
|
4272
4454
|
function discoverLibrary() {
|
|
4273
4455
|
const envPath = process.env["CAAMP_SKILL_LIBRARY"];
|
|
4274
|
-
if (envPath &&
|
|
4456
|
+
if (envPath && existsSync14(envPath)) {
|
|
4275
4457
|
try {
|
|
4276
4458
|
const indexPath = join7(envPath, "index.js");
|
|
4277
|
-
if (
|
|
4459
|
+
if (existsSync14(indexPath)) {
|
|
4278
4460
|
return loadLibraryFromModule(envPath);
|
|
4279
4461
|
}
|
|
4280
|
-
if (
|
|
4462
|
+
if (existsSync14(join7(envPath, "skills.json"))) {
|
|
4281
4463
|
return buildLibraryFromFiles(envPath);
|
|
4282
4464
|
}
|
|
4283
4465
|
} catch {
|
|
@@ -4384,8 +4566,8 @@ function getLibraryRoot() {
|
|
|
4384
4566
|
}
|
|
4385
4567
|
|
|
4386
4568
|
// src/core/skills/discovery.ts
|
|
4387
|
-
import { existsSync as
|
|
4388
|
-
import { readdir as readdir2, readFile as
|
|
4569
|
+
import { existsSync as existsSync15 } from "fs";
|
|
4570
|
+
import { readdir as readdir2, readFile as readFile8 } from "fs/promises";
|
|
4389
4571
|
import { join as join8 } from "path";
|
|
4390
4572
|
import matter from "gray-matter";
|
|
4391
4573
|
function toJsonCompatibleYamlValue(value) {
|
|
@@ -4408,7 +4590,7 @@ function toJsonCompatibleYamlValue(value) {
|
|
|
4408
4590
|
}
|
|
4409
4591
|
async function parseSkillFile(filePath) {
|
|
4410
4592
|
try {
|
|
4411
|
-
const content = await
|
|
4593
|
+
const content = await readFile8(filePath, "utf-8");
|
|
4412
4594
|
const { data } = matter(content);
|
|
4413
4595
|
if (!data.name || !data.description) {
|
|
4414
4596
|
return null;
|
|
@@ -4434,7 +4616,7 @@ async function parseSkillFile(filePath) {
|
|
|
4434
4616
|
}
|
|
4435
4617
|
async function discoverSkill(skillDir) {
|
|
4436
4618
|
const skillFile = join8(skillDir, "SKILL.md");
|
|
4437
|
-
if (!
|
|
4619
|
+
if (!existsSync15(skillFile)) return null;
|
|
4438
4620
|
const metadata = await parseSkillFile(skillFile);
|
|
4439
4621
|
if (!metadata) return null;
|
|
4440
4622
|
return {
|
|
@@ -4445,7 +4627,7 @@ async function discoverSkill(skillDir) {
|
|
|
4445
4627
|
};
|
|
4446
4628
|
}
|
|
4447
4629
|
async function discoverSkills(rootDir) {
|
|
4448
|
-
if (!
|
|
4630
|
+
if (!existsSync15(rootDir)) return [];
|
|
4449
4631
|
const entries = await readdir2(rootDir, { withFileTypes: true });
|
|
4450
4632
|
const skills = [];
|
|
4451
4633
|
for (const entry of entries) {
|
|
@@ -4474,8 +4656,8 @@ async function discoverSkillsMulti(dirs) {
|
|
|
4474
4656
|
}
|
|
4475
4657
|
|
|
4476
4658
|
// src/core/skills/validator.ts
|
|
4477
|
-
import { existsSync as
|
|
4478
|
-
import { readFile as
|
|
4659
|
+
import { existsSync as existsSync16 } from "fs";
|
|
4660
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
4479
4661
|
import matter2 from "gray-matter";
|
|
4480
4662
|
var RESERVED_NAMES = [
|
|
4481
4663
|
"anthropic",
|
|
@@ -4496,14 +4678,14 @@ var WARN_BODY_LINES = 500;
|
|
|
4496
4678
|
var WARN_DESCRIPTION_LENGTH = 50;
|
|
4497
4679
|
async function validateSkill(filePath) {
|
|
4498
4680
|
const issues = [];
|
|
4499
|
-
if (!
|
|
4681
|
+
if (!existsSync16(filePath)) {
|
|
4500
4682
|
return {
|
|
4501
4683
|
valid: false,
|
|
4502
4684
|
issues: [{ level: "error", field: "file", message: "File does not exist" }],
|
|
4503
4685
|
metadata: null
|
|
4504
4686
|
};
|
|
4505
4687
|
}
|
|
4506
|
-
const content = await
|
|
4688
|
+
const content = await readFile9(filePath, "utf-8");
|
|
4507
4689
|
if (!content.startsWith("---")) {
|
|
4508
4690
|
issues.push({
|
|
4509
4691
|
level: "error",
|
|
@@ -4652,6 +4834,8 @@ export {
|
|
|
4652
4834
|
writeConfig,
|
|
4653
4835
|
removeConfig,
|
|
4654
4836
|
readLockFile,
|
|
4837
|
+
syncGlobalInstructions,
|
|
4838
|
+
checkGlobalInstructionStaleness,
|
|
4655
4839
|
resolveMcpConfigPath,
|
|
4656
4840
|
listMcpServers,
|
|
4657
4841
|
listAllMcpServers,
|
|
@@ -4699,4 +4883,4 @@ export {
|
|
|
4699
4883
|
discoverSkillsMulti,
|
|
4700
4884
|
validateSkill
|
|
4701
4885
|
};
|
|
4702
|
-
//# sourceMappingURL=chunk-
|
|
4886
|
+
//# sourceMappingURL=chunk-IBHW6GEI.js.map
|