@cleocode/caamp 2026.5.82 → 2026.5.84
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-OCI4RYI5.js → chunk-H5YXR2DC.js} +31 -2
- package/dist/chunk-H5YXR2DC.js.map +1 -0
- package/dist/{chunk-OPUPNLUJ.js → chunk-PGETUTYZ.js} +2 -2
- package/dist/{chunk-SV33CE5X.js → chunk-QKC2JRSG.js} +2 -2
- package/dist/{chunk-4W35AEYA.js → chunk-QSJSM57K.js} +477 -75
- package/dist/chunk-QSJSM57K.js.map +1 -0
- package/dist/cli.js +442 -245
- package/dist/cli.js.map +1 -1
- package/dist/{hooks-5EXBKPII.js → hooks-ZN3C4WCK.js} +3 -3
- package/dist/index.d.ts +399 -10
- package/dist/index.js +17 -5
- package/dist/index.js.map +1 -1
- package/dist/{injector-F4EHB3CZ.js → injector-QPOIJVOR.js} +3 -3
- package/package.json +5 -5
- package/dist/chunk-4W35AEYA.js.map +0 -1
- package/dist/chunk-OCI4RYI5.js.map +0 -1
- /package/dist/{chunk-OPUPNLUJ.js.map → chunk-PGETUTYZ.js.map} +0 -0
- /package/dist/{chunk-SV33CE5X.js.map → chunk-QKC2JRSG.js.map} +0 -0
- /package/dist/{hooks-5EXBKPII.js.map → hooks-ZN3C4WCK.js.map} +0 -0
- /package/dist/{injector-F4EHB3CZ.js.map → injector-QPOIJVOR.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
getPrimaryProvider,
|
|
4
4
|
groupByInstructFile,
|
|
5
5
|
injectAll
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PGETUTYZ.js";
|
|
7
7
|
import {
|
|
8
8
|
__export,
|
|
9
9
|
getAgentsConfigPath,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
resolveProviderConfigPath,
|
|
17
17
|
resolveProviderProjectPath,
|
|
18
18
|
resolveProviderSkillsDirs
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-H5YXR2DC.js";
|
|
20
20
|
|
|
21
21
|
// src/core/logger.ts
|
|
22
22
|
var verboseMode = false;
|
|
@@ -247,10 +247,28 @@ async function linkToAgent(canonicalPath, provider, skillName, isGlobal, project
|
|
|
247
247
|
error: errors.join("; ") || `Provider ${provider.id} has no skills directory`
|
|
248
248
|
};
|
|
249
249
|
}
|
|
250
|
-
|
|
250
|
+
function inferSkillSourceType(sourceUrl) {
|
|
251
|
+
if (!sourceUrl) return "user";
|
|
252
|
+
if (sourceUrl.startsWith("library:")) return "canonical";
|
|
253
|
+
if (sourceUrl.startsWith("@") || sourceUrl.includes("github.com") || sourceUrl.includes("gitlab.com") || sourceUrl.includes("://")) {
|
|
254
|
+
return "community";
|
|
255
|
+
}
|
|
256
|
+
return "user";
|
|
257
|
+
}
|
|
258
|
+
async function installSkill(sourcePath, skillName, providers, isGlobal, projectDir, options) {
|
|
251
259
|
const errors = [];
|
|
252
260
|
const linkedAgents = [];
|
|
253
261
|
const canonicalPath = await installToCanonical(sourcePath, skillName);
|
|
262
|
+
if (options?.recordRow) {
|
|
263
|
+
const resolvedSourceUrl = options.sourceUrl ?? sourcePath;
|
|
264
|
+
const resolvedSourceType = options.sourceType ?? inferSkillSourceType(resolvedSourceUrl);
|
|
265
|
+
await options.recordRow({
|
|
266
|
+
name: skillName,
|
|
267
|
+
installPath: canonicalPath,
|
|
268
|
+
sourceUrl: resolvedSourceUrl,
|
|
269
|
+
sourceType: resolvedSourceType
|
|
270
|
+
});
|
|
271
|
+
}
|
|
254
272
|
for (const provider of providers) {
|
|
255
273
|
const result = await linkToAgent(canonicalPath, provider, skillName, isGlobal, projectDir);
|
|
256
274
|
if (result.success) {
|
|
@@ -302,8 +320,8 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
302
320
|
}
|
|
303
321
|
async function listCanonicalSkills() {
|
|
304
322
|
if (!existsSync2(getCanonicalSkillsDir())) return [];
|
|
305
|
-
const { readdir:
|
|
306
|
-
const entries = await
|
|
323
|
+
const { readdir: readdir4 } = await import("fs/promises");
|
|
324
|
+
const entries = await readdir4(getCanonicalSkillsDir(), { withFileTypes: true });
|
|
307
325
|
return entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name);
|
|
308
326
|
}
|
|
309
327
|
|
|
@@ -1088,7 +1106,7 @@ ${MARKER_END}`;
|
|
|
1088
1106
|
task.signal.addEventListener("abort", onAbort, { once: true });
|
|
1089
1107
|
}
|
|
1090
1108
|
}
|
|
1091
|
-
const exitPromise = new Promise((
|
|
1109
|
+
const exitPromise = new Promise((resolve2) => {
|
|
1092
1110
|
child.on("close", (exitCode, signal) => {
|
|
1093
1111
|
flushStdoutBuffer(true);
|
|
1094
1112
|
flushStderrBuffer(true);
|
|
@@ -1110,7 +1128,7 @@ ${MARKER_END}`;
|
|
|
1110
1128
|
};
|
|
1111
1129
|
Promise.allSettled(pendingWrites).then(() => {
|
|
1112
1130
|
safeOnStream({ kind: "exit", subagentId, payload: result2 });
|
|
1113
|
-
|
|
1131
|
+
resolve2(result2);
|
|
1114
1132
|
});
|
|
1115
1133
|
});
|
|
1116
1134
|
child.on("error", () => {
|
|
@@ -1839,11 +1857,11 @@ async function terminateSubagent(child, graceMs) {
|
|
|
1839
1857
|
}
|
|
1840
1858
|
const pollInterval = Math.min(25, Math.max(1, graceMs));
|
|
1841
1859
|
const deadline = Date.now() + graceMs;
|
|
1842
|
-
await new Promise((
|
|
1860
|
+
await new Promise((resolve2) => {
|
|
1843
1861
|
const timer = setInterval(() => {
|
|
1844
1862
|
if (child.exitCode !== null || child.signalCode !== null) {
|
|
1845
1863
|
clearInterval(timer);
|
|
1846
|
-
|
|
1864
|
+
resolve2();
|
|
1847
1865
|
return;
|
|
1848
1866
|
}
|
|
1849
1867
|
if (Date.now() >= deadline) {
|
|
@@ -1852,12 +1870,12 @@ async function terminateSubagent(child, graceMs) {
|
|
|
1852
1870
|
child.kill("SIGKILL");
|
|
1853
1871
|
} catch {
|
|
1854
1872
|
}
|
|
1855
|
-
|
|
1873
|
+
resolve2();
|
|
1856
1874
|
}
|
|
1857
1875
|
}, pollInterval);
|
|
1858
1876
|
child.once("close", () => {
|
|
1859
1877
|
clearInterval(timer);
|
|
1860
|
-
|
|
1878
|
+
resolve2();
|
|
1861
1879
|
});
|
|
1862
1880
|
});
|
|
1863
1881
|
}
|
|
@@ -2207,9 +2225,9 @@ function getNestedValue(obj, keyPath) {
|
|
|
2207
2225
|
return current;
|
|
2208
2226
|
}
|
|
2209
2227
|
async function ensureDir(filePath) {
|
|
2210
|
-
const { mkdir:
|
|
2211
|
-
const { dirname:
|
|
2212
|
-
await
|
|
2228
|
+
const { mkdir: mkdir6 } = await import("fs/promises");
|
|
2229
|
+
const { dirname: dirname5 } = await import("path");
|
|
2230
|
+
await mkdir6(dirname5(filePath), { recursive: true });
|
|
2213
2231
|
}
|
|
2214
2232
|
|
|
2215
2233
|
// src/core/formats/json.ts
|
|
@@ -2654,11 +2672,11 @@ function parseSource(input) {
|
|
|
2654
2672
|
if (ghUrlMatch) {
|
|
2655
2673
|
const owner = ghUrlMatch[1];
|
|
2656
2674
|
const repo = ghUrlMatch[2];
|
|
2657
|
-
const
|
|
2675
|
+
const path2 = ghUrlMatch[4];
|
|
2658
2676
|
if (!owner || !repo) {
|
|
2659
2677
|
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
2660
2678
|
}
|
|
2661
|
-
const inferredName =
|
|
2679
|
+
const inferredName = path2 ? path2.split("/").pop() ?? repo : repo;
|
|
2662
2680
|
return {
|
|
2663
2681
|
type: "github",
|
|
2664
2682
|
value: input,
|
|
@@ -2666,18 +2684,18 @@ function parseSource(input) {
|
|
|
2666
2684
|
owner,
|
|
2667
2685
|
repo,
|
|
2668
2686
|
ref: ghUrlMatch[3],
|
|
2669
|
-
path
|
|
2687
|
+
path: path2
|
|
2670
2688
|
};
|
|
2671
2689
|
}
|
|
2672
2690
|
const glUrlMatch = input.match(GITLAB_URL);
|
|
2673
2691
|
if (glUrlMatch) {
|
|
2674
2692
|
const owner = glUrlMatch[1];
|
|
2675
2693
|
const repo = glUrlMatch[2];
|
|
2676
|
-
const
|
|
2694
|
+
const path2 = glUrlMatch[4];
|
|
2677
2695
|
if (!owner || !repo) {
|
|
2678
2696
|
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
2679
2697
|
}
|
|
2680
|
-
const inferredName =
|
|
2698
|
+
const inferredName = path2 ? path2.split("/").pop() ?? repo : repo;
|
|
2681
2699
|
return {
|
|
2682
2700
|
type: "gitlab",
|
|
2683
2701
|
value: input,
|
|
@@ -2685,7 +2703,7 @@ function parseSource(input) {
|
|
|
2685
2703
|
owner,
|
|
2686
2704
|
repo,
|
|
2687
2705
|
ref: glUrlMatch[3],
|
|
2688
|
-
path
|
|
2706
|
+
path: path2
|
|
2689
2707
|
};
|
|
2690
2708
|
}
|
|
2691
2709
|
if (HTTP_URL.test(input)) {
|
|
@@ -2706,18 +2724,18 @@ function parseSource(input) {
|
|
|
2706
2724
|
if (ghShorthand && !NPM_SCOPED.test(input)) {
|
|
2707
2725
|
const owner = ghShorthand[1];
|
|
2708
2726
|
const repo = ghShorthand[2];
|
|
2709
|
-
const
|
|
2727
|
+
const path2 = ghShorthand[3];
|
|
2710
2728
|
if (!owner || !repo) {
|
|
2711
2729
|
return { type: "command", value: input, inferredName: inferName(input, "command") };
|
|
2712
2730
|
}
|
|
2713
|
-
const inferredName =
|
|
2731
|
+
const inferredName = path2 ? path2.split("/").pop() ?? repo : repo;
|
|
2714
2732
|
return {
|
|
2715
2733
|
type: "github",
|
|
2716
2734
|
value: `https://github.com/${owner}/${repo}`,
|
|
2717
2735
|
inferredName,
|
|
2718
2736
|
owner,
|
|
2719
2737
|
repo,
|
|
2720
|
-
path
|
|
2738
|
+
path: path2
|
|
2721
2739
|
};
|
|
2722
2740
|
}
|
|
2723
2741
|
const libraryMatch = input.match(LIBRARY_SKILL);
|
|
@@ -3163,14 +3181,14 @@ async function scanFile(filePath, rules) {
|
|
|
3163
3181
|
return { file: filePath, findings, score, passed };
|
|
3164
3182
|
}
|
|
3165
3183
|
async function scanDirectory(dirPath) {
|
|
3166
|
-
const { readdir:
|
|
3167
|
-
const { join:
|
|
3184
|
+
const { readdir: readdir4 } = await import("fs/promises");
|
|
3185
|
+
const { join: join10 } = await import("path");
|
|
3168
3186
|
if (!existsSync10(dirPath)) return [];
|
|
3169
|
-
const entries = await
|
|
3187
|
+
const entries = await readdir4(dirPath, { withFileTypes: true });
|
|
3170
3188
|
const results = [];
|
|
3171
3189
|
for (const entry of entries) {
|
|
3172
3190
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
3173
|
-
const skillFile =
|
|
3191
|
+
const skillFile = join10(dirPath, entry.name, "SKILL.md");
|
|
3174
3192
|
if (existsSync10(skillFile)) {
|
|
3175
3193
|
results.push(await scanFile(skillFile));
|
|
3176
3194
|
}
|
|
@@ -3233,7 +3251,7 @@ import { mkdir as mkdir4, open as open2, readFile as readFile6, rename as rename
|
|
|
3233
3251
|
var LOCK_GUARD_PATH = `${LOCK_FILE_PATH}.lock`;
|
|
3234
3252
|
var STALE_LOCK_MS = 5e3;
|
|
3235
3253
|
function sleep(ms) {
|
|
3236
|
-
return new Promise((
|
|
3254
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3237
3255
|
}
|
|
3238
3256
|
async function removeStaleLock() {
|
|
3239
3257
|
try {
|
|
@@ -3431,6 +3449,377 @@ async function checkAllSkillUpdates() {
|
|
|
3431
3449
|
return results;
|
|
3432
3450
|
}
|
|
3433
3451
|
|
|
3452
|
+
// src/commands/skills/doctor-bridge.ts
|
|
3453
|
+
import { existsSync as existsSync12, lstatSync as lstatSync3, readdirSync, readlinkSync, realpathSync } from "fs";
|
|
3454
|
+
import { cp as cp4, mkdir as mkdir5, readdir as readdir2, rm as rm5, symlink as symlink3, unlink } from "fs/promises";
|
|
3455
|
+
import { homedir as homedir3 } from "os";
|
|
3456
|
+
import * as path from "path";
|
|
3457
|
+
import pc from "picocolors";
|
|
3458
|
+
|
|
3459
|
+
// src/core/lafs.ts
|
|
3460
|
+
import { randomUUID } from "crypto";
|
|
3461
|
+
import { resolveOutputFormat } from "@cleocode/lafs";
|
|
3462
|
+
function resolveFormat(options) {
|
|
3463
|
+
return resolveOutputFormat({
|
|
3464
|
+
jsonFlag: options.jsonFlag ?? false,
|
|
3465
|
+
humanFlag: (options.humanFlag ?? false) || isHuman(),
|
|
3466
|
+
projectDefault: options.projectDefault ?? "json"
|
|
3467
|
+
}).format;
|
|
3468
|
+
}
|
|
3469
|
+
function buildEnvelope(operation, mvi, result, error, page = null, sessionId, warnings) {
|
|
3470
|
+
return {
|
|
3471
|
+
$schema: "https://lafs.dev/schemas/v1/envelope.schema.json",
|
|
3472
|
+
_meta: {
|
|
3473
|
+
specVersion: "1.0.0",
|
|
3474
|
+
schemaVersion: "1.0.0",
|
|
3475
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3476
|
+
operation,
|
|
3477
|
+
requestId: randomUUID(),
|
|
3478
|
+
transport: "cli",
|
|
3479
|
+
strict: true,
|
|
3480
|
+
mvi,
|
|
3481
|
+
contextVersion: 0,
|
|
3482
|
+
...sessionId && { sessionId },
|
|
3483
|
+
...warnings && warnings.length > 0 && { warnings }
|
|
3484
|
+
},
|
|
3485
|
+
success: error === null,
|
|
3486
|
+
result,
|
|
3487
|
+
error,
|
|
3488
|
+
page
|
|
3489
|
+
};
|
|
3490
|
+
}
|
|
3491
|
+
function emitError(operation, mvi, code, message, category, details = {}, exitCode = 1) {
|
|
3492
|
+
const envelope = buildEnvelope(operation, mvi, null, {
|
|
3493
|
+
code,
|
|
3494
|
+
message,
|
|
3495
|
+
category,
|
|
3496
|
+
retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
|
|
3497
|
+
retryAfterMs: null,
|
|
3498
|
+
details
|
|
3499
|
+
});
|
|
3500
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
3501
|
+
process.exit(exitCode);
|
|
3502
|
+
}
|
|
3503
|
+
function emitJsonError(operation, mvi, code, message, category, details = {}) {
|
|
3504
|
+
const envelope = buildEnvelope(operation, mvi, null, {
|
|
3505
|
+
code,
|
|
3506
|
+
message,
|
|
3507
|
+
category,
|
|
3508
|
+
retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
|
|
3509
|
+
retryAfterMs: null,
|
|
3510
|
+
details
|
|
3511
|
+
});
|
|
3512
|
+
console.error(JSON.stringify(envelope, null, 2));
|
|
3513
|
+
}
|
|
3514
|
+
function outputSuccess(operation, mvi, result, page, sessionId, warnings) {
|
|
3515
|
+
const envelope = buildEnvelope(operation, mvi, result, null, page ?? null, sessionId, warnings);
|
|
3516
|
+
if (isQuiet() && !envelope.error) {
|
|
3517
|
+
return;
|
|
3518
|
+
}
|
|
3519
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
3520
|
+
}
|
|
3521
|
+
function handleFormatError(error, operation, mvi, jsonFlag) {
|
|
3522
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3523
|
+
if (jsonFlag) {
|
|
3524
|
+
emitJsonError(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
|
|
3525
|
+
} else {
|
|
3526
|
+
console.error(message);
|
|
3527
|
+
}
|
|
3528
|
+
process.exit(1);
|
|
3529
|
+
}
|
|
3530
|
+
var ErrorCategories = {
|
|
3531
|
+
VALIDATION: "VALIDATION",
|
|
3532
|
+
AUTH: "AUTH",
|
|
3533
|
+
PERMISSION: "PERMISSION",
|
|
3534
|
+
NOT_FOUND: "NOT_FOUND",
|
|
3535
|
+
CONFLICT: "CONFLICT",
|
|
3536
|
+
RATE_LIMIT: "RATE_LIMIT",
|
|
3537
|
+
TRANSIENT: "TRANSIENT",
|
|
3538
|
+
INTERNAL: "INTERNAL",
|
|
3539
|
+
CONTRACT: "CONTRACT",
|
|
3540
|
+
MIGRATION: "MIGRATION"
|
|
3541
|
+
};
|
|
3542
|
+
var ErrorCodes = {
|
|
3543
|
+
// Format errors
|
|
3544
|
+
FORMAT_CONFLICT: "E_FORMAT_CONFLICT",
|
|
3545
|
+
INVALID_JSON: "E_INVALID_JSON",
|
|
3546
|
+
// Not found errors
|
|
3547
|
+
SKILL_NOT_FOUND: "E_SKILL_NOT_FOUND",
|
|
3548
|
+
PROVIDER_NOT_FOUND: "E_PROVIDER_NOT_FOUND",
|
|
3549
|
+
MCP_SERVER_NOT_FOUND: "E_MCP_SERVER_NOT_FOUND",
|
|
3550
|
+
FILE_NOT_FOUND: "E_FILE_NOT_FOUND",
|
|
3551
|
+
// Validation errors
|
|
3552
|
+
INVALID_INPUT: "E_INVALID_INPUT",
|
|
3553
|
+
INVALID_CONSTRAINT: "E_INVALID_CONSTRAINT",
|
|
3554
|
+
INVALID_FORMAT: "E_INVALID_FORMAT",
|
|
3555
|
+
// Operation errors
|
|
3556
|
+
INSTALL_FAILED: "E_INSTALL_FAILED",
|
|
3557
|
+
REMOVE_FAILED: "E_REMOVE_FAILED",
|
|
3558
|
+
UPDATE_FAILED: "E_UPDATE_FAILED",
|
|
3559
|
+
VALIDATION_FAILED: "E_VALIDATION_FAILED",
|
|
3560
|
+
AUDIT_FAILED: "E_AUDIT_FAILED",
|
|
3561
|
+
// System errors
|
|
3562
|
+
NETWORK_ERROR: "E_NETWORK_ERROR",
|
|
3563
|
+
FILE_SYSTEM_ERROR: "E_FILE_SYSTEM_ERROR",
|
|
3564
|
+
PERMISSION_DENIED: "E_PERMISSION_DENIED",
|
|
3565
|
+
INTERNAL_ERROR: "E_INTERNAL_ERROR"
|
|
3566
|
+
};
|
|
3567
|
+
|
|
3568
|
+
// src/commands/skills/doctor-bridge.ts
|
|
3569
|
+
var AgentsSkillsRealDirError = class extends Error {
|
|
3570
|
+
/** LAFS error code surfaced by the CLI. */
|
|
3571
|
+
code = "E_AGENTS_SKILLS_REAL_DIR";
|
|
3572
|
+
/** Resolved path of the offending real directory. */
|
|
3573
|
+
agentsSkillsPath;
|
|
3574
|
+
/** Number of immediate entries in the offending directory. */
|
|
3575
|
+
entryCount;
|
|
3576
|
+
/**
|
|
3577
|
+
* Construct an `AgentsSkillsRealDirError`.
|
|
3578
|
+
*
|
|
3579
|
+
* @param agentsSkillsPath - Path to the real `~/.agents/skills` directory.
|
|
3580
|
+
* @param entryCount - Number of entries inside the directory.
|
|
3581
|
+
*/
|
|
3582
|
+
constructor(agentsSkillsPath, entryCount) {
|
|
3583
|
+
super(
|
|
3584
|
+
`Refusing to replace real directory at ${agentsSkillsPath} (${entryCount} entries). Pass --force to back up and bridge.`
|
|
3585
|
+
);
|
|
3586
|
+
this.name = "AgentsSkillsRealDirError";
|
|
3587
|
+
this.agentsSkillsPath = agentsSkillsPath;
|
|
3588
|
+
this.entryCount = entryCount;
|
|
3589
|
+
}
|
|
3590
|
+
};
|
|
3591
|
+
function buildBackupTimestamp() {
|
|
3592
|
+
const d = /* @__PURE__ */ new Date();
|
|
3593
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
3594
|
+
return `${d.getUTCFullYear()}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}-${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}`;
|
|
3595
|
+
}
|
|
3596
|
+
function resolveBridgePaths(homeRoot) {
|
|
3597
|
+
return {
|
|
3598
|
+
skillsRoot: path.join(homeRoot, ".cleo", "skills"),
|
|
3599
|
+
bridgeTarget: path.join(homeRoot, ".claude", "skills", "agents-shared"),
|
|
3600
|
+
bridgePath: path.join(homeRoot, ".agents", "skills"),
|
|
3601
|
+
backupsRoot: path.join(homeRoot, ".cleo", "backups"),
|
|
3602
|
+
claudeSkillsRoot: path.join(homeRoot, ".claude", "skills")
|
|
3603
|
+
};
|
|
3604
|
+
}
|
|
3605
|
+
function listSkillDirs(skillsRoot) {
|
|
3606
|
+
if (!existsSync12(skillsRoot)) return [];
|
|
3607
|
+
const entries = readdirSync(skillsRoot, { withFileTypes: true });
|
|
3608
|
+
return entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name).filter((n) => !n.startsWith(".")).sort();
|
|
3609
|
+
}
|
|
3610
|
+
function symlinkPointsAt(linkPath, target) {
|
|
3611
|
+
try {
|
|
3612
|
+
const stat4 = lstatSync3(linkPath);
|
|
3613
|
+
if (!stat4.isSymbolicLink()) return false;
|
|
3614
|
+
const current = readlinkSync(linkPath);
|
|
3615
|
+
const resolved = path.isAbsolute(current) ? current : path.resolve(path.dirname(linkPath), current);
|
|
3616
|
+
return path.resolve(resolved) === path.resolve(target);
|
|
3617
|
+
} catch {
|
|
3618
|
+
return false;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
async function ensureSymlink(linkPath, target, dryRun) {
|
|
3622
|
+
if (dryRun) return;
|
|
3623
|
+
await mkdir5(path.dirname(linkPath), { recursive: true });
|
|
3624
|
+
if (existsSync12(linkPath)) {
|
|
3625
|
+
try {
|
|
3626
|
+
await unlink(linkPath);
|
|
3627
|
+
} catch {
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
await symlink3(target, linkPath, "dir");
|
|
3631
|
+
}
|
|
3632
|
+
async function countEntries(dir) {
|
|
3633
|
+
try {
|
|
3634
|
+
const entries = await readdir2(dir);
|
|
3635
|
+
return entries.length;
|
|
3636
|
+
} catch {
|
|
3637
|
+
return 0;
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
async function runDoctorBridge(options = {}) {
|
|
3641
|
+
const homeRoot = options.homeDir ?? homedir3();
|
|
3642
|
+
const force = options.force ?? false;
|
|
3643
|
+
const dryRun = options.dryRun ?? false;
|
|
3644
|
+
const { skillsRoot, bridgeTarget, bridgePath, backupsRoot, claudeSkillsRoot } = resolveBridgePaths(homeRoot);
|
|
3645
|
+
if (!dryRun) {
|
|
3646
|
+
await mkdir5(bridgeTarget, { recursive: true });
|
|
3647
|
+
}
|
|
3648
|
+
const skillNames = listSkillDirs(skillsRoot);
|
|
3649
|
+
const created = [];
|
|
3650
|
+
for (const name of skillNames) {
|
|
3651
|
+
const linkPath = path.join(bridgeTarget, name);
|
|
3652
|
+
const target = path.join(skillsRoot, name);
|
|
3653
|
+
if (symlinkPointsAt(linkPath, target)) continue;
|
|
3654
|
+
await ensureSymlink(linkPath, target, dryRun);
|
|
3655
|
+
created.push({ name, linkPath, target });
|
|
3656
|
+
}
|
|
3657
|
+
const removed = [];
|
|
3658
|
+
if (existsSync12(claudeSkillsRoot)) {
|
|
3659
|
+
const entries = readdirSync(claudeSkillsRoot, { withFileTypes: true });
|
|
3660
|
+
for (const entry of entries) {
|
|
3661
|
+
if (entry.name === "agents-shared") continue;
|
|
3662
|
+
const entryPath = path.join(claudeSkillsRoot, entry.name);
|
|
3663
|
+
let stat4;
|
|
3664
|
+
try {
|
|
3665
|
+
stat4 = lstatSync3(entryPath);
|
|
3666
|
+
} catch {
|
|
3667
|
+
continue;
|
|
3668
|
+
}
|
|
3669
|
+
if (!stat4.isSymbolicLink()) continue;
|
|
3670
|
+
let resolvedTarget = null;
|
|
3671
|
+
try {
|
|
3672
|
+
const raw = readlinkSync(entryPath);
|
|
3673
|
+
resolvedTarget = path.isAbsolute(raw) ? raw : path.resolve(path.dirname(entryPath), raw);
|
|
3674
|
+
} catch {
|
|
3675
|
+
resolvedTarget = null;
|
|
3676
|
+
}
|
|
3677
|
+
if (resolvedTarget !== null) {
|
|
3678
|
+
const realResolved = (() => {
|
|
3679
|
+
try {
|
|
3680
|
+
return realpathSync(resolvedTarget);
|
|
3681
|
+
} catch {
|
|
3682
|
+
return resolvedTarget;
|
|
3683
|
+
}
|
|
3684
|
+
})();
|
|
3685
|
+
if (realResolved === bridgeTarget || realResolved.startsWith(`${bridgeTarget}${path.sep}`)) {
|
|
3686
|
+
continue;
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
if (!dryRun) {
|
|
3690
|
+
await unlink(entryPath);
|
|
3691
|
+
}
|
|
3692
|
+
removed.push({ linkPath: entryPath, previousTarget: resolvedTarget });
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
let backupPath = null;
|
|
3696
|
+
const bridgeAlreadyCorrect = symlinkPointsAt(bridgePath, bridgeTarget);
|
|
3697
|
+
let bridgeSymlinkActive = bridgeAlreadyCorrect;
|
|
3698
|
+
if (!bridgeAlreadyCorrect) {
|
|
3699
|
+
if (existsSync12(bridgePath)) {
|
|
3700
|
+
const lstat = lstatSync3(bridgePath);
|
|
3701
|
+
if (lstat.isSymbolicLink()) {
|
|
3702
|
+
if (!dryRun) await unlink(bridgePath);
|
|
3703
|
+
} else if (lstat.isDirectory()) {
|
|
3704
|
+
const entryCount = await countEntries(bridgePath);
|
|
3705
|
+
if (entryCount > 0 && !force) {
|
|
3706
|
+
throw new AgentsSkillsRealDirError(bridgePath, entryCount);
|
|
3707
|
+
}
|
|
3708
|
+
if (entryCount > 0) {
|
|
3709
|
+
backupPath = path.join(backupsRoot, `agents-skills-pre-bridge-${buildBackupTimestamp()}`);
|
|
3710
|
+
if (!dryRun) {
|
|
3711
|
+
await mkdir5(backupsRoot, { recursive: true });
|
|
3712
|
+
await cp4(bridgePath, backupPath, { recursive: true, dereference: false });
|
|
3713
|
+
await rm5(bridgePath, { recursive: true, force: true });
|
|
3714
|
+
}
|
|
3715
|
+
} else if (!dryRun) {
|
|
3716
|
+
await rm5(bridgePath, { recursive: true, force: true });
|
|
3717
|
+
}
|
|
3718
|
+
} else if (!dryRun) {
|
|
3719
|
+
await unlink(bridgePath);
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
if (!dryRun) {
|
|
3723
|
+
await mkdir5(path.dirname(bridgePath), { recursive: true });
|
|
3724
|
+
await symlink3(bridgeTarget, bridgePath, "dir");
|
|
3725
|
+
bridgeSymlinkActive = true;
|
|
3726
|
+
}
|
|
3727
|
+
}
|
|
3728
|
+
return {
|
|
3729
|
+
bridgeCreated: !bridgeAlreadyCorrect,
|
|
3730
|
+
bridgeSymlinkActive,
|
|
3731
|
+
perSkillSymlinksCreated: created,
|
|
3732
|
+
perSkillSymlinksRemoved: removed,
|
|
3733
|
+
backupPath,
|
|
3734
|
+
dryRun,
|
|
3735
|
+
skillsRoot,
|
|
3736
|
+
bridgeTarget,
|
|
3737
|
+
bridgePath
|
|
3738
|
+
};
|
|
3739
|
+
}
|
|
3740
|
+
function printHumanSummary(result) {
|
|
3741
|
+
if (result.dryRun) {
|
|
3742
|
+
console.log(pc.dim("(dry-run \u2014 no disk state mutated)"));
|
|
3743
|
+
}
|
|
3744
|
+
if (!result.bridgeCreated && result.perSkillSymlinksCreated.length === 0) {
|
|
3745
|
+
console.log(pc.green("Bridge already correct \u2014 nothing to do."));
|
|
3746
|
+
} else {
|
|
3747
|
+
console.log(pc.green("Bridge configured."));
|
|
3748
|
+
}
|
|
3749
|
+
console.log(` ${pc.dim("bridge:")} ${result.bridgePath} -> ${result.bridgeTarget}`);
|
|
3750
|
+
console.log(
|
|
3751
|
+
` ${pc.dim("per-skill symlinks created:")} ${result.perSkillSymlinksCreated.length}`
|
|
3752
|
+
);
|
|
3753
|
+
console.log(
|
|
3754
|
+
` ${pc.dim("per-skill symlinks removed:")} ${result.perSkillSymlinksRemoved.length}`
|
|
3755
|
+
);
|
|
3756
|
+
if (result.backupPath) {
|
|
3757
|
+
console.log(` ${pc.yellow("backup:")} ${result.backupPath}`);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
function registerDoctorBridge(parent) {
|
|
3761
|
+
parent.command("bridge").description("Create the single ~/.agents/skills bridge symlink and rip per-skill symlinks").option("--force", "Back up and replace a real ~/.agents/skills directory if present").option("--dry-run", "Print planned actions without mutating disk state").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
|
|
3762
|
+
async (opts) => {
|
|
3763
|
+
const operation = "skills.doctor.bridge";
|
|
3764
|
+
const mvi = "standard";
|
|
3765
|
+
let format;
|
|
3766
|
+
try {
|
|
3767
|
+
format = resolveFormat({
|
|
3768
|
+
jsonFlag: opts.json ?? false,
|
|
3769
|
+
humanFlag: opts.human ?? false,
|
|
3770
|
+
projectDefault: "json"
|
|
3771
|
+
});
|
|
3772
|
+
} catch (error) {
|
|
3773
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3774
|
+
emitJsonError(
|
|
3775
|
+
operation,
|
|
3776
|
+
mvi,
|
|
3777
|
+
ErrorCodes.FORMAT_CONFLICT,
|
|
3778
|
+
message,
|
|
3779
|
+
ErrorCategories.VALIDATION
|
|
3780
|
+
);
|
|
3781
|
+
process.exit(1);
|
|
3782
|
+
}
|
|
3783
|
+
try {
|
|
3784
|
+
const result = await runDoctorBridge({
|
|
3785
|
+
force: opts.force ?? false,
|
|
3786
|
+
dryRun: opts.dryRun ?? false
|
|
3787
|
+
});
|
|
3788
|
+
if (format === "json") {
|
|
3789
|
+
outputSuccess(operation, mvi, result);
|
|
3790
|
+
} else {
|
|
3791
|
+
printHumanSummary(result);
|
|
3792
|
+
}
|
|
3793
|
+
} catch (error) {
|
|
3794
|
+
if (error instanceof AgentsSkillsRealDirError) {
|
|
3795
|
+
if (format === "json") {
|
|
3796
|
+
emitJsonError(operation, mvi, error.code, error.message, ErrorCategories.CONFLICT, {
|
|
3797
|
+
agentsSkillsPath: error.agentsSkillsPath,
|
|
3798
|
+
entryCount: error.entryCount
|
|
3799
|
+
});
|
|
3800
|
+
} else {
|
|
3801
|
+
console.error(pc.red(error.message));
|
|
3802
|
+
}
|
|
3803
|
+
process.exit(1);
|
|
3804
|
+
}
|
|
3805
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3806
|
+
if (format === "json") {
|
|
3807
|
+
emitJsonError(
|
|
3808
|
+
operation,
|
|
3809
|
+
mvi,
|
|
3810
|
+
ErrorCodes.INTERNAL_ERROR,
|
|
3811
|
+
message,
|
|
3812
|
+
ErrorCategories.INTERNAL
|
|
3813
|
+
);
|
|
3814
|
+
} else {
|
|
3815
|
+
console.error(pc.red(message));
|
|
3816
|
+
}
|
|
3817
|
+
process.exit(1);
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
);
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3434
3823
|
// src/core/network/fetch.ts
|
|
3435
3824
|
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
3436
3825
|
var NetworkError = class extends Error {
|
|
@@ -4007,9 +4396,9 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
4007
4396
|
}
|
|
4008
4397
|
|
|
4009
4398
|
// src/core/skills/library-loader.ts
|
|
4010
|
-
import { existsSync as
|
|
4399
|
+
import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync } from "fs";
|
|
4011
4400
|
import { createRequire } from "module";
|
|
4012
|
-
import { basename as basename3, dirname as
|
|
4401
|
+
import { basename as basename3, dirname as dirname4, join as join7 } from "path";
|
|
4013
4402
|
var require2 = createRequire(import.meta.url);
|
|
4014
4403
|
function loadLibraryFromModule(root) {
|
|
4015
4404
|
let mod;
|
|
@@ -4055,16 +4444,16 @@ function loadLibraryFromModule(root) {
|
|
|
4055
4444
|
return mod;
|
|
4056
4445
|
}
|
|
4057
4446
|
function buildLibraryFromFiles(root) {
|
|
4058
|
-
const catalogPath =
|
|
4059
|
-
if (!
|
|
4447
|
+
const catalogPath = join7(root, "skills.json");
|
|
4448
|
+
if (!existsSync13(catalogPath)) {
|
|
4060
4449
|
throw new Error(`No skills.json found at ${root}`);
|
|
4061
4450
|
}
|
|
4062
4451
|
const catalogData = JSON.parse(readFileSync(catalogPath, "utf-8"));
|
|
4063
4452
|
const entries = catalogData.skills ?? [];
|
|
4064
4453
|
const version = catalogData.version ?? "0.0.0";
|
|
4065
|
-
const manifestPath =
|
|
4454
|
+
const manifestPath = join7(root, "skills", "manifest.json");
|
|
4066
4455
|
let manifest;
|
|
4067
|
-
if (
|
|
4456
|
+
if (existsSync13(manifestPath)) {
|
|
4068
4457
|
manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
4069
4458
|
} else {
|
|
4070
4459
|
manifest = {
|
|
@@ -4074,14 +4463,14 @@ function buildLibraryFromFiles(root) {
|
|
|
4074
4463
|
skills: []
|
|
4075
4464
|
};
|
|
4076
4465
|
}
|
|
4077
|
-
const profilesDir =
|
|
4466
|
+
const profilesDir = join7(root, "profiles");
|
|
4078
4467
|
const profiles = /* @__PURE__ */ new Map();
|
|
4079
|
-
if (
|
|
4080
|
-
for (const file of
|
|
4468
|
+
if (existsSync13(profilesDir)) {
|
|
4469
|
+
for (const file of readdirSync2(profilesDir)) {
|
|
4081
4470
|
if (!file.endsWith(".json")) continue;
|
|
4082
4471
|
try {
|
|
4083
4472
|
const profile = JSON.parse(
|
|
4084
|
-
readFileSync(
|
|
4473
|
+
readFileSync(join7(profilesDir, file), "utf-8")
|
|
4085
4474
|
);
|
|
4086
4475
|
profiles.set(profile.name, profile);
|
|
4087
4476
|
} catch {
|
|
@@ -4095,9 +4484,9 @@ function buildLibraryFromFiles(root) {
|
|
|
4095
4484
|
function getSkillDir2(name) {
|
|
4096
4485
|
const entry = skillMap.get(name);
|
|
4097
4486
|
if (entry) {
|
|
4098
|
-
return
|
|
4487
|
+
return dirname4(join7(root, entry.path));
|
|
4099
4488
|
}
|
|
4100
|
-
return
|
|
4489
|
+
return join7(root, "skills", name);
|
|
4101
4490
|
}
|
|
4102
4491
|
function resolveDeps(names, visited = /* @__PURE__ */ new Set()) {
|
|
4103
4492
|
const result = [];
|
|
@@ -4125,8 +4514,8 @@ function buildLibraryFromFiles(root) {
|
|
|
4125
4514
|
return resolveDeps([...new Set(skills)]);
|
|
4126
4515
|
}
|
|
4127
4516
|
function discoverFiles(dir, ext) {
|
|
4128
|
-
if (!
|
|
4129
|
-
return
|
|
4517
|
+
if (!existsSync13(dir)) return [];
|
|
4518
|
+
return readdirSync2(dir).filter((f) => f.endsWith(ext)).map((f) => basename3(f, ext));
|
|
4130
4519
|
}
|
|
4131
4520
|
const library = {
|
|
4132
4521
|
version,
|
|
@@ -4142,14 +4531,14 @@ function buildLibraryFromFiles(root) {
|
|
|
4142
4531
|
getSkillPath(name) {
|
|
4143
4532
|
const entry = skillMap.get(name);
|
|
4144
4533
|
if (entry) {
|
|
4145
|
-
return
|
|
4534
|
+
return join7(root, entry.path);
|
|
4146
4535
|
}
|
|
4147
|
-
return
|
|
4536
|
+
return join7(root, "skills", name, "SKILL.md");
|
|
4148
4537
|
},
|
|
4149
4538
|
getSkillDir: getSkillDir2,
|
|
4150
4539
|
readSkillContent(name) {
|
|
4151
4540
|
const skillPath = library.getSkillPath(name);
|
|
4152
|
-
if (!
|
|
4541
|
+
if (!existsSync13(skillPath)) {
|
|
4153
4542
|
throw new Error(`Skill content not found: ${skillPath}`);
|
|
4154
4543
|
}
|
|
4155
4544
|
return readFileSync(skillPath, "utf-8");
|
|
@@ -4176,11 +4565,11 @@ function buildLibraryFromFiles(root) {
|
|
|
4176
4565
|
return resolveProfileByName(name);
|
|
4177
4566
|
},
|
|
4178
4567
|
listSharedResources() {
|
|
4179
|
-
return discoverFiles(
|
|
4568
|
+
return discoverFiles(join7(root, "skills", "_shared"), ".md");
|
|
4180
4569
|
},
|
|
4181
4570
|
getSharedResourcePath(name) {
|
|
4182
|
-
const resourcePath =
|
|
4183
|
-
return
|
|
4571
|
+
const resourcePath = join7(root, "skills", "_shared", `${name}.md`);
|
|
4572
|
+
return existsSync13(resourcePath) ? resourcePath : void 0;
|
|
4184
4573
|
},
|
|
4185
4574
|
readSharedResource(name) {
|
|
4186
4575
|
const resourcePath = library.getSharedResourcePath(name);
|
|
@@ -4188,15 +4577,15 @@ function buildLibraryFromFiles(root) {
|
|
|
4188
4577
|
return readFileSync(resourcePath, "utf-8");
|
|
4189
4578
|
},
|
|
4190
4579
|
listProtocols() {
|
|
4191
|
-
const rootProtocols = discoverFiles(
|
|
4580
|
+
const rootProtocols = discoverFiles(join7(root, "protocols"), ".md");
|
|
4192
4581
|
if (rootProtocols.length > 0) return rootProtocols;
|
|
4193
|
-
return discoverFiles(
|
|
4582
|
+
return discoverFiles(join7(root, "skills", "protocols"), ".md");
|
|
4194
4583
|
},
|
|
4195
4584
|
getProtocolPath(name) {
|
|
4196
|
-
const rootPath =
|
|
4197
|
-
if (
|
|
4198
|
-
const skillsPath =
|
|
4199
|
-
return
|
|
4585
|
+
const rootPath = join7(root, "protocols", `${name}.md`);
|
|
4586
|
+
if (existsSync13(rootPath)) return rootPath;
|
|
4587
|
+
const skillsPath = join7(root, "skills", "protocols", `${name}.md`);
|
|
4588
|
+
return existsSync13(skillsPath) ? skillsPath : void 0;
|
|
4200
4589
|
},
|
|
4201
4590
|
readProtocol(name) {
|
|
4202
4591
|
const protocolPath = library.getProtocolPath(name);
|
|
@@ -4221,8 +4610,8 @@ function buildLibraryFromFiles(root) {
|
|
|
4221
4610
|
if (!entry.version) {
|
|
4222
4611
|
issues.push({ level: "warn", field: "version", message: "Missing version" });
|
|
4223
4612
|
}
|
|
4224
|
-
const skillPath =
|
|
4225
|
-
if (!
|
|
4613
|
+
const skillPath = join7(root, entry.path);
|
|
4614
|
+
if (!existsSync13(skillPath)) {
|
|
4226
4615
|
issues.push({
|
|
4227
4616
|
level: "error",
|
|
4228
4617
|
field: "path",
|
|
@@ -4281,15 +4670,15 @@ __export(catalog_exports, {
|
|
|
4281
4670
|
validateAll: () => validateAll,
|
|
4282
4671
|
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
4283
4672
|
});
|
|
4284
|
-
import { existsSync as
|
|
4285
|
-
import { join as
|
|
4673
|
+
import { existsSync as existsSync14 } from "fs";
|
|
4674
|
+
import { join as join8 } from "path";
|
|
4286
4675
|
var _library = null;
|
|
4287
4676
|
function registerSkillLibrary(library) {
|
|
4288
4677
|
_library = library;
|
|
4289
4678
|
}
|
|
4290
4679
|
function registerSkillLibraryFromPath(root) {
|
|
4291
|
-
const indexPath =
|
|
4292
|
-
if (
|
|
4680
|
+
const indexPath = join8(root, "index.js");
|
|
4681
|
+
if (existsSync14(indexPath)) {
|
|
4293
4682
|
_library = loadLibraryFromModule(root);
|
|
4294
4683
|
return;
|
|
4295
4684
|
}
|
|
@@ -4300,13 +4689,13 @@ function clearRegisteredLibrary() {
|
|
|
4300
4689
|
}
|
|
4301
4690
|
function discoverLibrary() {
|
|
4302
4691
|
const envPath = process.env["CAAMP_SKILL_LIBRARY"];
|
|
4303
|
-
if (envPath &&
|
|
4692
|
+
if (envPath && existsSync14(envPath)) {
|
|
4304
4693
|
try {
|
|
4305
|
-
const indexPath =
|
|
4306
|
-
if (
|
|
4694
|
+
const indexPath = join8(envPath, "index.js");
|
|
4695
|
+
if (existsSync14(indexPath)) {
|
|
4307
4696
|
return loadLibraryFromModule(envPath);
|
|
4308
4697
|
}
|
|
4309
|
-
if (
|
|
4698
|
+
if (existsSync14(join8(envPath, "skills.json"))) {
|
|
4310
4699
|
return buildLibraryFromFiles(envPath);
|
|
4311
4700
|
}
|
|
4312
4701
|
} catch {
|
|
@@ -4413,9 +4802,9 @@ function getLibraryRoot() {
|
|
|
4413
4802
|
}
|
|
4414
4803
|
|
|
4415
4804
|
// src/core/skills/discovery.ts
|
|
4416
|
-
import { existsSync as
|
|
4417
|
-
import { readdir as
|
|
4418
|
-
import { join as
|
|
4805
|
+
import { existsSync as existsSync15 } from "fs";
|
|
4806
|
+
import { readdir as readdir3, readFile as readFile7 } from "fs/promises";
|
|
4807
|
+
import { join as join9 } from "path";
|
|
4419
4808
|
import matter from "gray-matter";
|
|
4420
4809
|
async function parseSkillFile(filePath) {
|
|
4421
4810
|
try {
|
|
@@ -4439,8 +4828,8 @@ async function parseSkillFile(filePath) {
|
|
|
4439
4828
|
}
|
|
4440
4829
|
}
|
|
4441
4830
|
async function discoverSkill(skillDir) {
|
|
4442
|
-
const skillFile =
|
|
4443
|
-
if (!
|
|
4831
|
+
const skillFile = join9(skillDir, "SKILL.md");
|
|
4832
|
+
if (!existsSync15(skillFile)) return null;
|
|
4444
4833
|
const metadata = await parseSkillFile(skillFile);
|
|
4445
4834
|
if (!metadata) return null;
|
|
4446
4835
|
return {
|
|
@@ -4451,12 +4840,12 @@ async function discoverSkill(skillDir) {
|
|
|
4451
4840
|
};
|
|
4452
4841
|
}
|
|
4453
4842
|
async function discoverSkills(rootDir) {
|
|
4454
|
-
if (!
|
|
4455
|
-
const entries = await
|
|
4843
|
+
if (!existsSync15(rootDir)) return [];
|
|
4844
|
+
const entries = await readdir3(rootDir, { withFileTypes: true });
|
|
4456
4845
|
const skills = [];
|
|
4457
4846
|
for (const entry of entries) {
|
|
4458
4847
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
4459
|
-
const skillDir =
|
|
4848
|
+
const skillDir = join9(rootDir, entry.name);
|
|
4460
4849
|
const skill = await discoverSkill(skillDir);
|
|
4461
4850
|
if (skill) {
|
|
4462
4851
|
skills.push(skill);
|
|
@@ -4480,7 +4869,7 @@ async function discoverSkillsMulti(dirs) {
|
|
|
4480
4869
|
}
|
|
4481
4870
|
|
|
4482
4871
|
// src/core/skills/validator.ts
|
|
4483
|
-
import { existsSync as
|
|
4872
|
+
import { existsSync as existsSync16 } from "fs";
|
|
4484
4873
|
import { readFile as readFile8 } from "fs/promises";
|
|
4485
4874
|
import matter2 from "gray-matter";
|
|
4486
4875
|
var RESERVED_NAMES = [
|
|
@@ -4502,7 +4891,7 @@ var WARN_BODY_LINES = 500;
|
|
|
4502
4891
|
var WARN_DESCRIPTION_LENGTH = 50;
|
|
4503
4892
|
async function validateSkill(filePath) {
|
|
4504
4893
|
const issues = [];
|
|
4505
|
-
if (!
|
|
4894
|
+
if (!existsSync16(filePath)) {
|
|
4506
4895
|
return {
|
|
4507
4896
|
valid: false,
|
|
4508
4897
|
issues: [{ level: "error", field: "file", message: "File does not exist" }],
|
|
@@ -4631,6 +5020,7 @@ export {
|
|
|
4631
5020
|
getInstalledProviders,
|
|
4632
5021
|
detectProjectProviders,
|
|
4633
5022
|
resetDetectionCache,
|
|
5023
|
+
inferSkillSourceType,
|
|
4634
5024
|
installSkill,
|
|
4635
5025
|
removeSkill,
|
|
4636
5026
|
listCanonicalSkills,
|
|
@@ -4657,6 +5047,14 @@ export {
|
|
|
4657
5047
|
readConfig,
|
|
4658
5048
|
writeConfig,
|
|
4659
5049
|
removeConfig,
|
|
5050
|
+
resolveFormat,
|
|
5051
|
+
buildEnvelope,
|
|
5052
|
+
emitError,
|
|
5053
|
+
emitJsonError,
|
|
5054
|
+
outputSuccess,
|
|
5055
|
+
handleFormatError,
|
|
5056
|
+
ErrorCategories,
|
|
5057
|
+
ErrorCodes,
|
|
4660
5058
|
readLockFile,
|
|
4661
5059
|
resolveMcpConfigPath,
|
|
4662
5060
|
listMcpServers,
|
|
@@ -4677,6 +5075,10 @@ export {
|
|
|
4677
5075
|
getTrackedSkills,
|
|
4678
5076
|
checkSkillUpdate,
|
|
4679
5077
|
checkAllSkillUpdates,
|
|
5078
|
+
AgentsSkillsRealDirError,
|
|
5079
|
+
buildBackupTimestamp,
|
|
5080
|
+
runDoctorBridge,
|
|
5081
|
+
registerDoctorBridge,
|
|
4680
5082
|
MarketplaceClient,
|
|
4681
5083
|
RECOMMENDATION_ERROR_CODES,
|
|
4682
5084
|
tokenizeCriteriaValue,
|
|
@@ -4705,4 +5107,4 @@ export {
|
|
|
4705
5107
|
discoverSkillsMulti,
|
|
4706
5108
|
validateSkill
|
|
4707
5109
|
};
|
|
4708
|
-
//# sourceMappingURL=chunk-
|
|
5110
|
+
//# sourceMappingURL=chunk-QSJSM57K.js.map
|