@cleocode/caamp 2026.5.84 → 2026.5.87
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-QSJSM57K.js → chunk-WXL7RPS4.js} +435 -47
- package/dist/chunk-WXL7RPS4.js.map +1 -0
- package/dist/cli.js +173 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +333 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-QSJSM57K.js.map +0 -1
|
@@ -3182,13 +3182,13 @@ async function scanFile(filePath, rules) {
|
|
|
3182
3182
|
}
|
|
3183
3183
|
async function scanDirectory(dirPath) {
|
|
3184
3184
|
const { readdir: readdir4 } = await import("fs/promises");
|
|
3185
|
-
const { join:
|
|
3185
|
+
const { join: join11 } = await import("path");
|
|
3186
3186
|
if (!existsSync10(dirPath)) return [];
|
|
3187
3187
|
const entries = await readdir4(dirPath, { withFileTypes: true });
|
|
3188
3188
|
const results = [];
|
|
3189
3189
|
for (const entry of entries) {
|
|
3190
3190
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
3191
|
-
const skillFile =
|
|
3191
|
+
const skillFile = join11(dirPath, entry.name, "SKILL.md");
|
|
3192
3192
|
if (existsSync10(skillFile)) {
|
|
3193
3193
|
results.push(await scanFile(skillFile));
|
|
3194
3194
|
}
|
|
@@ -3554,6 +3554,10 @@ var ErrorCodes = {
|
|
|
3554
3554
|
INVALID_FORMAT: "E_INVALID_FORMAT",
|
|
3555
3555
|
// Operation errors
|
|
3556
3556
|
INSTALL_FAILED: "E_INSTALL_FAILED",
|
|
3557
|
+
// Skills federation gates (T9564 — Sphere B)
|
|
3558
|
+
SKILL_TRUST_GATE_BLOCKED: "E_SKILL_TRUST_GATE_BLOCKED",
|
|
3559
|
+
FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED: "E_FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED",
|
|
3560
|
+
FEDERATION_CHECKSUM_MISMATCH: "E_FEDERATION_CHECKSUM_MISMATCH",
|
|
3557
3561
|
REMOVE_FAILED: "E_REMOVE_FAILED",
|
|
3558
3562
|
UPDATE_FAILED: "E_UPDATE_FAILED",
|
|
3559
3563
|
VALIDATION_FAILED: "E_VALIDATION_FAILED",
|
|
@@ -3820,6 +3824,384 @@ function registerDoctorBridge(parent) {
|
|
|
3820
3824
|
);
|
|
3821
3825
|
}
|
|
3822
3826
|
|
|
3827
|
+
// src/commands/skills/doctor-adopt.ts
|
|
3828
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
3829
|
+
import {
|
|
3830
|
+
cpSync,
|
|
3831
|
+
existsSync as existsSync13,
|
|
3832
|
+
lstatSync as lstatSync4,
|
|
3833
|
+
mkdirSync,
|
|
3834
|
+
readdirSync as readdirSync2,
|
|
3835
|
+
realpathSync as realpathSync2,
|
|
3836
|
+
renameSync,
|
|
3837
|
+
rmSync,
|
|
3838
|
+
statSync,
|
|
3839
|
+
writeFileSync
|
|
3840
|
+
} from "fs";
|
|
3841
|
+
import { homedir as homedir4 } from "os";
|
|
3842
|
+
import { join as join7 } from "path";
|
|
3843
|
+
import { createInterface } from "readline/promises";
|
|
3844
|
+
import pc2 from "picocolors";
|
|
3845
|
+
function cleoSkillsRoot() {
|
|
3846
|
+
return join7(homedir4(), ".cleo", "skills");
|
|
3847
|
+
}
|
|
3848
|
+
function legacyAgentsSkillsRoot() {
|
|
3849
|
+
return join7(homedir4(), ".local", "share", "agents", "skills");
|
|
3850
|
+
}
|
|
3851
|
+
function homeAgentsSkillsRoot() {
|
|
3852
|
+
return join7(homedir4(), ".agents", "skills");
|
|
3853
|
+
}
|
|
3854
|
+
function archiveRoot() {
|
|
3855
|
+
return join7(cleoSkillsRoot(), ".archive");
|
|
3856
|
+
}
|
|
3857
|
+
function auditLogRoot() {
|
|
3858
|
+
return join7(cleoSkillsRoot(), ".audit-log");
|
|
3859
|
+
}
|
|
3860
|
+
function listCandidates(root) {
|
|
3861
|
+
if (!existsSync13(root)) return [];
|
|
3862
|
+
let entries;
|
|
3863
|
+
try {
|
|
3864
|
+
entries = readdirSync2(root);
|
|
3865
|
+
} catch {
|
|
3866
|
+
return [];
|
|
3867
|
+
}
|
|
3868
|
+
const out = [];
|
|
3869
|
+
for (const name of entries) {
|
|
3870
|
+
if (name.startsWith(".")) continue;
|
|
3871
|
+
const full = join7(root, name);
|
|
3872
|
+
let isDirLike = false;
|
|
3873
|
+
try {
|
|
3874
|
+
const stat4 = lstatSync4(full);
|
|
3875
|
+
if (stat4.isDirectory()) {
|
|
3876
|
+
isDirLike = true;
|
|
3877
|
+
} else if (stat4.isSymbolicLink()) {
|
|
3878
|
+
try {
|
|
3879
|
+
const real = statSync(full);
|
|
3880
|
+
isDirLike = real.isDirectory();
|
|
3881
|
+
} catch {
|
|
3882
|
+
isDirLike = false;
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
} catch {
|
|
3886
|
+
isDirLike = false;
|
|
3887
|
+
}
|
|
3888
|
+
if (isDirLike) {
|
|
3889
|
+
out.push({ name, path: full });
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
return out;
|
|
3893
|
+
}
|
|
3894
|
+
function approxDirSize(dir) {
|
|
3895
|
+
let total = 0;
|
|
3896
|
+
try {
|
|
3897
|
+
const entries = readdirSync2(dir);
|
|
3898
|
+
for (const entry of entries) {
|
|
3899
|
+
try {
|
|
3900
|
+
const stat4 = statSync(join7(dir, entry));
|
|
3901
|
+
if (stat4.isFile()) total += stat4.size;
|
|
3902
|
+
} catch {
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
} catch {
|
|
3906
|
+
return 0;
|
|
3907
|
+
}
|
|
3908
|
+
return total;
|
|
3909
|
+
}
|
|
3910
|
+
function discoverOrphans(registeredNames) {
|
|
3911
|
+
const cleoRoot = cleoSkillsRoot();
|
|
3912
|
+
const legacyRoot = legacyAgentsSkillsRoot();
|
|
3913
|
+
const homeRoot = homeAgentsSkillsRoot();
|
|
3914
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3915
|
+
const visit = (root, via, filter) => {
|
|
3916
|
+
for (const candidate of listCandidates(root)) {
|
|
3917
|
+
if (seen.has(candidate.name)) continue;
|
|
3918
|
+
if (registeredNames.has(candidate.name)) continue;
|
|
3919
|
+
if (filter && !filter(candidate.path)) continue;
|
|
3920
|
+
seen.set(candidate.name, {
|
|
3921
|
+
name: candidate.name,
|
|
3922
|
+
path: candidate.path,
|
|
3923
|
+
discoveredVia: via,
|
|
3924
|
+
hasSkillMd: existsSync13(join7(candidate.path, "SKILL.md")),
|
|
3925
|
+
sizeBytes: approxDirSize(candidate.path)
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3928
|
+
};
|
|
3929
|
+
visit(cleoRoot, "cleo");
|
|
3930
|
+
visit(legacyRoot, "legacy-agents");
|
|
3931
|
+
visit(homeRoot, "home-agents", (path2) => {
|
|
3932
|
+
try {
|
|
3933
|
+
const real = realpathSync2(path2);
|
|
3934
|
+
return !real.startsWith(`${cleoRoot}/`);
|
|
3935
|
+
} catch {
|
|
3936
|
+
return true;
|
|
3937
|
+
}
|
|
3938
|
+
});
|
|
3939
|
+
return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
3940
|
+
}
|
|
3941
|
+
function canonicalAdoptRefusal() {
|
|
3942
|
+
return {
|
|
3943
|
+
code: "E_CANONICAL_ADOPT_REFUSED",
|
|
3944
|
+
message: "Canonical adoption is refused on user machines. Canonical skills are owned by the CLEO core team and ONLY the owner-CI workflow may write them (architecture-v3 \xA76 invariant).",
|
|
3945
|
+
remediation: "To contribute this skill to canonical: clone https://github.com/kryptobaseddev/cleo, place the skill under packages/skills/skills/<name>/, and open a PR. Local user-machine canonical writes are blocked by design."
|
|
3946
|
+
};
|
|
3947
|
+
}
|
|
3948
|
+
function buildAdoptedRow(orphan, now) {
|
|
3949
|
+
return {
|
|
3950
|
+
name: orphan.name,
|
|
3951
|
+
installPath: orphan.path,
|
|
3952
|
+
installedAt: now,
|
|
3953
|
+
sourceType: "user",
|
|
3954
|
+
lifecycleState: "active"
|
|
3955
|
+
};
|
|
3956
|
+
}
|
|
3957
|
+
function archiveAndDelete(orphan, now) {
|
|
3958
|
+
const tsToken = now.replace(/[:.]/g, "-");
|
|
3959
|
+
const archiveDir = join7(archiveRoot(), `${orphan.name}-${tsToken}`);
|
|
3960
|
+
mkdirSync(archiveRoot(), { recursive: true });
|
|
3961
|
+
cpSync(orphan.path, archiveDir, { recursive: true, dereference: false });
|
|
3962
|
+
rmSync(orphan.path, { recursive: true, force: true });
|
|
3963
|
+
return archiveDir;
|
|
3964
|
+
}
|
|
3965
|
+
async function applyDecision(orphan, decision, now, recordRow) {
|
|
3966
|
+
const base = {
|
|
3967
|
+
orphan,
|
|
3968
|
+
decidedAt: now
|
|
3969
|
+
};
|
|
3970
|
+
if (decision === "canonical-adopt") {
|
|
3971
|
+
return {
|
|
3972
|
+
...base,
|
|
3973
|
+
decision,
|
|
3974
|
+
applied: false,
|
|
3975
|
+
refusal: canonicalAdoptRefusal(),
|
|
3976
|
+
archivedTo: null
|
|
3977
|
+
};
|
|
3978
|
+
}
|
|
3979
|
+
if (decision === "skip") {
|
|
3980
|
+
return { ...base, decision, applied: true, refusal: null, archivedTo: null };
|
|
3981
|
+
}
|
|
3982
|
+
if (decision === "user-adopt") {
|
|
3983
|
+
try {
|
|
3984
|
+
await recordRow(buildAdoptedRow(orphan, now));
|
|
3985
|
+
return { ...base, decision, applied: true, refusal: null, archivedTo: null };
|
|
3986
|
+
} catch (err) {
|
|
3987
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3988
|
+
return {
|
|
3989
|
+
...base,
|
|
3990
|
+
decision,
|
|
3991
|
+
applied: false,
|
|
3992
|
+
refusal: {
|
|
3993
|
+
code: "E_CANONICAL_ADOPT_REFUSED",
|
|
3994
|
+
message: `user-adopt failed: ${message}`,
|
|
3995
|
+
remediation: "Initialise the registry with `cleo skills list` then re-run."
|
|
3996
|
+
},
|
|
3997
|
+
archivedTo: null
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
try {
|
|
4002
|
+
const archived = archiveAndDelete(orphan, now);
|
|
4003
|
+
return { ...base, decision, applied: true, refusal: null, archivedTo: archived };
|
|
4004
|
+
} catch (err) {
|
|
4005
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4006
|
+
return {
|
|
4007
|
+
...base,
|
|
4008
|
+
decision,
|
|
4009
|
+
applied: false,
|
|
4010
|
+
refusal: {
|
|
4011
|
+
code: "E_CANONICAL_ADOPT_REFUSED",
|
|
4012
|
+
message: `delete failed: ${message}`,
|
|
4013
|
+
remediation: "Inspect filesystem permissions and rerun with --non-interactive to verify."
|
|
4014
|
+
},
|
|
4015
|
+
archivedTo: null
|
|
4016
|
+
};
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
function writeAuditLog(result) {
|
|
4020
|
+
const dir = auditLogRoot();
|
|
4021
|
+
mkdirSync(dir, { recursive: true });
|
|
4022
|
+
const tsToken = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4023
|
+
const path2 = join7(dir, `adopt-${tsToken}.json`);
|
|
4024
|
+
const tmp = `${path2}.tmp`;
|
|
4025
|
+
const payload = {
|
|
4026
|
+
runId: randomUUID2(),
|
|
4027
|
+
writtenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4028
|
+
...result
|
|
4029
|
+
};
|
|
4030
|
+
writeFileSync(tmp, `${JSON.stringify(payload, null, 2)}
|
|
4031
|
+
`, "utf8");
|
|
4032
|
+
renameSync(tmp, path2);
|
|
4033
|
+
return path2;
|
|
4034
|
+
}
|
|
4035
|
+
async function promptDecision(rl, orphan) {
|
|
4036
|
+
const kb = Math.round(orphan.sizeBytes / 1024);
|
|
4037
|
+
process.stderr.write(
|
|
4038
|
+
`
|
|
4039
|
+
${pc2.bold(orphan.name)}
|
|
4040
|
+
path: ${orphan.path}
|
|
4041
|
+
via: ${orphan.discoveredVia}
|
|
4042
|
+
size: ~${kb} KiB
|
|
4043
|
+
SKILL.md: ${orphan.hasSkillMd ? "yes" : "no"}
|
|
4044
|
+
`
|
|
4045
|
+
);
|
|
4046
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
4047
|
+
const answer = (await rl.question(" [c]anonical-adopt | [u]ser-adopt | [d]elete | [s]kip: ")).trim().toLowerCase();
|
|
4048
|
+
if (answer === "c" || answer === "canonical" || answer === "canonical-adopt") {
|
|
4049
|
+
return "canonical-adopt";
|
|
4050
|
+
}
|
|
4051
|
+
if (answer === "u" || answer === "user" || answer === "user-adopt") {
|
|
4052
|
+
return "user-adopt";
|
|
4053
|
+
}
|
|
4054
|
+
if (answer === "d" || answer === "delete") return "delete";
|
|
4055
|
+
if (answer === "s" || answer === "skip" || answer === "") return "skip";
|
|
4056
|
+
process.stderr.write(` ${pc2.yellow("unrecognised input \u2014 try one of c/u/d/s")}
|
|
4057
|
+
`);
|
|
4058
|
+
}
|
|
4059
|
+
return "skip";
|
|
4060
|
+
}
|
|
4061
|
+
async function runDoctorAdopt(options) {
|
|
4062
|
+
const discover = options.discoverFn ?? discoverOrphans;
|
|
4063
|
+
const registeredNames = await options.loadRegisteredNames();
|
|
4064
|
+
const orphans = discover(registeredNames);
|
|
4065
|
+
const results = [];
|
|
4066
|
+
const mode = options.nonInteractive ? "non-interactive" : options.autoUserAdopt ? "auto-user-adopt" : "interactive";
|
|
4067
|
+
if (orphans.length === 0) {
|
|
4068
|
+
const empty = {
|
|
4069
|
+
totalOrphans: 0,
|
|
4070
|
+
results: [],
|
|
4071
|
+
auditLogPath: "",
|
|
4072
|
+
mode
|
|
4073
|
+
};
|
|
4074
|
+
if (!options.skipAuditLog) empty.auditLogPath = writeAuditLog(empty);
|
|
4075
|
+
return empty;
|
|
4076
|
+
}
|
|
4077
|
+
if (mode === "non-interactive") {
|
|
4078
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4079
|
+
for (const orphan of orphans) {
|
|
4080
|
+
results.push({
|
|
4081
|
+
orphan,
|
|
4082
|
+
decision: "skip",
|
|
4083
|
+
applied: true,
|
|
4084
|
+
refusal: null,
|
|
4085
|
+
archivedTo: null,
|
|
4086
|
+
decidedAt: now
|
|
4087
|
+
});
|
|
4088
|
+
}
|
|
4089
|
+
} else if (mode === "auto-user-adopt") {
|
|
4090
|
+
for (const orphan of orphans) {
|
|
4091
|
+
results.push(
|
|
4092
|
+
await applyDecision(orphan, "user-adopt", (/* @__PURE__ */ new Date()).toISOString(), options.recordRow)
|
|
4093
|
+
);
|
|
4094
|
+
}
|
|
4095
|
+
} else {
|
|
4096
|
+
const promptFn = options.prompt ?? (async (orphan) => {
|
|
4097
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
4098
|
+
try {
|
|
4099
|
+
return await promptDecision(rl, orphan);
|
|
4100
|
+
} finally {
|
|
4101
|
+
rl.close();
|
|
4102
|
+
}
|
|
4103
|
+
});
|
|
4104
|
+
for (const orphan of orphans) {
|
|
4105
|
+
const decision = await promptFn(orphan);
|
|
4106
|
+
results.push(
|
|
4107
|
+
await applyDecision(orphan, decision, (/* @__PURE__ */ new Date()).toISOString(), options.recordRow)
|
|
4108
|
+
);
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
const result = {
|
|
4112
|
+
totalOrphans: orphans.length,
|
|
4113
|
+
results,
|
|
4114
|
+
auditLogPath: "",
|
|
4115
|
+
mode
|
|
4116
|
+
};
|
|
4117
|
+
if (!options.skipAuditLog) result.auditLogPath = writeAuditLog(result);
|
|
4118
|
+
return result;
|
|
4119
|
+
}
|
|
4120
|
+
var caampStandaloneAdapters = {
|
|
4121
|
+
loadRegisteredNames: () => /* @__PURE__ */ new Set(),
|
|
4122
|
+
recordRow: () => {
|
|
4123
|
+
throw new Error(
|
|
4124
|
+
"caamp standalone CLI cannot write to skills.db. Use `cleo skills doctor adopt-orphans` instead."
|
|
4125
|
+
);
|
|
4126
|
+
}
|
|
4127
|
+
};
|
|
4128
|
+
function registerSkillsDoctorAdopt(parent, adapters = caampStandaloneAdapters) {
|
|
4129
|
+
const existing = parent.commands.find((c) => c.name() === "doctor");
|
|
4130
|
+
const doctor = existing ?? parent.command("doctor").description("Diagnostics + repair for the skill system");
|
|
4131
|
+
doctor.command("adopt-orphans").description(
|
|
4132
|
+
"Interactive audit of on-disk skill dirs not tracked in skills.db (canonical/user/delete/skip)"
|
|
4133
|
+
).option("--json", "Output as LAFS JSON envelope (default)").option("--human", "Output a colorised human-readable summary").option("--non-interactive", "List orphans + exit without action").option("--auto-user-adopt", "Bulk-mark all orphans as source_type=user without prompting").action(
|
|
4134
|
+
async (opts) => {
|
|
4135
|
+
const operation = "skills.doctor.adopt-orphans";
|
|
4136
|
+
const mvi = "standard";
|
|
4137
|
+
let format;
|
|
4138
|
+
try {
|
|
4139
|
+
format = resolveFormat({
|
|
4140
|
+
jsonFlag: opts.json ?? false,
|
|
4141
|
+
humanFlag: opts.human ?? false,
|
|
4142
|
+
projectDefault: "json"
|
|
4143
|
+
});
|
|
4144
|
+
} catch (error) {
|
|
4145
|
+
handleFormatError(error, operation, mvi, opts.json);
|
|
4146
|
+
}
|
|
4147
|
+
try {
|
|
4148
|
+
const result = await runDoctorAdopt({
|
|
4149
|
+
nonInteractive: opts.nonInteractive ?? false,
|
|
4150
|
+
autoUserAdopt: opts.autoUserAdopt ?? false,
|
|
4151
|
+
loadRegisteredNames: adapters.loadRegisteredNames,
|
|
4152
|
+
recordRow: adapters.recordRow
|
|
4153
|
+
});
|
|
4154
|
+
if (format === "json") {
|
|
4155
|
+
outputSuccess(operation, mvi, result);
|
|
4156
|
+
return;
|
|
4157
|
+
}
|
|
4158
|
+
const ok = result.results.filter((r) => r.applied);
|
|
4159
|
+
const blocked = result.results.filter((r) => !r.applied);
|
|
4160
|
+
console.log(pc2.bold(`
|
|
4161
|
+
skills doctor adopt-orphans (${result.mode})
|
|
4162
|
+
`));
|
|
4163
|
+
console.log(
|
|
4164
|
+
` ${pc2.bold("Discovered")}: ${result.totalOrphans} orphan${result.totalOrphans === 1 ? "" : "s"}`
|
|
4165
|
+
);
|
|
4166
|
+
for (const r of result.results) {
|
|
4167
|
+
const icon = r.decision === "skip" ? pc2.dim("\xB7") : r.applied ? pc2.green("\u2713") : pc2.red("\u2717");
|
|
4168
|
+
const verb = r.applied ? r.decision : `${r.decision} (refused)`;
|
|
4169
|
+
console.log(` ${icon} ${r.orphan.name.padEnd(32)} ${pc2.dim(verb)}`);
|
|
4170
|
+
if (r.refusal) {
|
|
4171
|
+
console.log(` ${pc2.yellow(r.refusal.message)}`);
|
|
4172
|
+
console.log(` ${pc2.dim(r.refusal.remediation)}`);
|
|
4173
|
+
}
|
|
4174
|
+
if (r.archivedTo) {
|
|
4175
|
+
console.log(` ${pc2.dim(`archived \u2192 ${r.archivedTo}`)}`);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
console.log(
|
|
4179
|
+
`
|
|
4180
|
+
${pc2.bold("Summary")}: ${pc2.green(`${ok.length} applied`)}, ${pc2.red(`${blocked.length} blocked`)}`
|
|
4181
|
+
);
|
|
4182
|
+
if (result.auditLogPath) {
|
|
4183
|
+
console.log(` ${pc2.dim(`audit log \u2192 ${result.auditLogPath}`)}`);
|
|
4184
|
+
}
|
|
4185
|
+
console.log();
|
|
4186
|
+
} catch (error) {
|
|
4187
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4188
|
+
if (format === "json") {
|
|
4189
|
+
emitJsonError(
|
|
4190
|
+
operation,
|
|
4191
|
+
mvi,
|
|
4192
|
+
ErrorCodes.INTERNAL_ERROR,
|
|
4193
|
+
message,
|
|
4194
|
+
ErrorCategories.INTERNAL
|
|
4195
|
+
);
|
|
4196
|
+
} else {
|
|
4197
|
+
console.error(pc2.red(`Error: ${message}`));
|
|
4198
|
+
}
|
|
4199
|
+
process.exit(1);
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
);
|
|
4203
|
+
}
|
|
4204
|
+
|
|
3823
4205
|
// src/core/network/fetch.ts
|
|
3824
4206
|
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
3825
4207
|
var NetworkError = class extends Error {
|
|
@@ -4396,9 +4778,9 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
4396
4778
|
}
|
|
4397
4779
|
|
|
4398
4780
|
// src/core/skills/library-loader.ts
|
|
4399
|
-
import { existsSync as
|
|
4781
|
+
import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync } from "fs";
|
|
4400
4782
|
import { createRequire } from "module";
|
|
4401
|
-
import { basename as basename3, dirname as dirname4, join as
|
|
4783
|
+
import { basename as basename3, dirname as dirname4, join as join8 } from "path";
|
|
4402
4784
|
var require2 = createRequire(import.meta.url);
|
|
4403
4785
|
function loadLibraryFromModule(root) {
|
|
4404
4786
|
let mod;
|
|
@@ -4444,16 +4826,16 @@ function loadLibraryFromModule(root) {
|
|
|
4444
4826
|
return mod;
|
|
4445
4827
|
}
|
|
4446
4828
|
function buildLibraryFromFiles(root) {
|
|
4447
|
-
const catalogPath =
|
|
4448
|
-
if (!
|
|
4829
|
+
const catalogPath = join8(root, "skills.json");
|
|
4830
|
+
if (!existsSync14(catalogPath)) {
|
|
4449
4831
|
throw new Error(`No skills.json found at ${root}`);
|
|
4450
4832
|
}
|
|
4451
4833
|
const catalogData = JSON.parse(readFileSync(catalogPath, "utf-8"));
|
|
4452
4834
|
const entries = catalogData.skills ?? [];
|
|
4453
4835
|
const version = catalogData.version ?? "0.0.0";
|
|
4454
|
-
const manifestPath =
|
|
4836
|
+
const manifestPath = join8(root, "skills", "manifest.json");
|
|
4455
4837
|
let manifest;
|
|
4456
|
-
if (
|
|
4838
|
+
if (existsSync14(manifestPath)) {
|
|
4457
4839
|
manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
4458
4840
|
} else {
|
|
4459
4841
|
manifest = {
|
|
@@ -4463,14 +4845,14 @@ function buildLibraryFromFiles(root) {
|
|
|
4463
4845
|
skills: []
|
|
4464
4846
|
};
|
|
4465
4847
|
}
|
|
4466
|
-
const profilesDir =
|
|
4848
|
+
const profilesDir = join8(root, "profiles");
|
|
4467
4849
|
const profiles = /* @__PURE__ */ new Map();
|
|
4468
|
-
if (
|
|
4469
|
-
for (const file of
|
|
4850
|
+
if (existsSync14(profilesDir)) {
|
|
4851
|
+
for (const file of readdirSync3(profilesDir)) {
|
|
4470
4852
|
if (!file.endsWith(".json")) continue;
|
|
4471
4853
|
try {
|
|
4472
4854
|
const profile = JSON.parse(
|
|
4473
|
-
readFileSync(
|
|
4855
|
+
readFileSync(join8(profilesDir, file), "utf-8")
|
|
4474
4856
|
);
|
|
4475
4857
|
profiles.set(profile.name, profile);
|
|
4476
4858
|
} catch {
|
|
@@ -4484,9 +4866,9 @@ function buildLibraryFromFiles(root) {
|
|
|
4484
4866
|
function getSkillDir2(name) {
|
|
4485
4867
|
const entry = skillMap.get(name);
|
|
4486
4868
|
if (entry) {
|
|
4487
|
-
return dirname4(
|
|
4869
|
+
return dirname4(join8(root, entry.path));
|
|
4488
4870
|
}
|
|
4489
|
-
return
|
|
4871
|
+
return join8(root, "skills", name);
|
|
4490
4872
|
}
|
|
4491
4873
|
function resolveDeps(names, visited = /* @__PURE__ */ new Set()) {
|
|
4492
4874
|
const result = [];
|
|
@@ -4514,8 +4896,8 @@ function buildLibraryFromFiles(root) {
|
|
|
4514
4896
|
return resolveDeps([...new Set(skills)]);
|
|
4515
4897
|
}
|
|
4516
4898
|
function discoverFiles(dir, ext) {
|
|
4517
|
-
if (!
|
|
4518
|
-
return
|
|
4899
|
+
if (!existsSync14(dir)) return [];
|
|
4900
|
+
return readdirSync3(dir).filter((f) => f.endsWith(ext)).map((f) => basename3(f, ext));
|
|
4519
4901
|
}
|
|
4520
4902
|
const library = {
|
|
4521
4903
|
version,
|
|
@@ -4531,14 +4913,14 @@ function buildLibraryFromFiles(root) {
|
|
|
4531
4913
|
getSkillPath(name) {
|
|
4532
4914
|
const entry = skillMap.get(name);
|
|
4533
4915
|
if (entry) {
|
|
4534
|
-
return
|
|
4916
|
+
return join8(root, entry.path);
|
|
4535
4917
|
}
|
|
4536
|
-
return
|
|
4918
|
+
return join8(root, "skills", name, "SKILL.md");
|
|
4537
4919
|
},
|
|
4538
4920
|
getSkillDir: getSkillDir2,
|
|
4539
4921
|
readSkillContent(name) {
|
|
4540
4922
|
const skillPath = library.getSkillPath(name);
|
|
4541
|
-
if (!
|
|
4923
|
+
if (!existsSync14(skillPath)) {
|
|
4542
4924
|
throw new Error(`Skill content not found: ${skillPath}`);
|
|
4543
4925
|
}
|
|
4544
4926
|
return readFileSync(skillPath, "utf-8");
|
|
@@ -4565,11 +4947,11 @@ function buildLibraryFromFiles(root) {
|
|
|
4565
4947
|
return resolveProfileByName(name);
|
|
4566
4948
|
},
|
|
4567
4949
|
listSharedResources() {
|
|
4568
|
-
return discoverFiles(
|
|
4950
|
+
return discoverFiles(join8(root, "skills", "_shared"), ".md");
|
|
4569
4951
|
},
|
|
4570
4952
|
getSharedResourcePath(name) {
|
|
4571
|
-
const resourcePath =
|
|
4572
|
-
return
|
|
4953
|
+
const resourcePath = join8(root, "skills", "_shared", `${name}.md`);
|
|
4954
|
+
return existsSync14(resourcePath) ? resourcePath : void 0;
|
|
4573
4955
|
},
|
|
4574
4956
|
readSharedResource(name) {
|
|
4575
4957
|
const resourcePath = library.getSharedResourcePath(name);
|
|
@@ -4577,15 +4959,15 @@ function buildLibraryFromFiles(root) {
|
|
|
4577
4959
|
return readFileSync(resourcePath, "utf-8");
|
|
4578
4960
|
},
|
|
4579
4961
|
listProtocols() {
|
|
4580
|
-
const rootProtocols = discoverFiles(
|
|
4962
|
+
const rootProtocols = discoverFiles(join8(root, "protocols"), ".md");
|
|
4581
4963
|
if (rootProtocols.length > 0) return rootProtocols;
|
|
4582
|
-
return discoverFiles(
|
|
4964
|
+
return discoverFiles(join8(root, "skills", "protocols"), ".md");
|
|
4583
4965
|
},
|
|
4584
4966
|
getProtocolPath(name) {
|
|
4585
|
-
const rootPath =
|
|
4586
|
-
if (
|
|
4587
|
-
const skillsPath =
|
|
4588
|
-
return
|
|
4967
|
+
const rootPath = join8(root, "protocols", `${name}.md`);
|
|
4968
|
+
if (existsSync14(rootPath)) return rootPath;
|
|
4969
|
+
const skillsPath = join8(root, "skills", "protocols", `${name}.md`);
|
|
4970
|
+
return existsSync14(skillsPath) ? skillsPath : void 0;
|
|
4589
4971
|
},
|
|
4590
4972
|
readProtocol(name) {
|
|
4591
4973
|
const protocolPath = library.getProtocolPath(name);
|
|
@@ -4610,8 +4992,8 @@ function buildLibraryFromFiles(root) {
|
|
|
4610
4992
|
if (!entry.version) {
|
|
4611
4993
|
issues.push({ level: "warn", field: "version", message: "Missing version" });
|
|
4612
4994
|
}
|
|
4613
|
-
const skillPath =
|
|
4614
|
-
if (!
|
|
4995
|
+
const skillPath = join8(root, entry.path);
|
|
4996
|
+
if (!existsSync14(skillPath)) {
|
|
4615
4997
|
issues.push({
|
|
4616
4998
|
level: "error",
|
|
4617
4999
|
field: "path",
|
|
@@ -4670,15 +5052,15 @@ __export(catalog_exports, {
|
|
|
4670
5052
|
validateAll: () => validateAll,
|
|
4671
5053
|
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
4672
5054
|
});
|
|
4673
|
-
import { existsSync as
|
|
4674
|
-
import { join as
|
|
5055
|
+
import { existsSync as existsSync15 } from "fs";
|
|
5056
|
+
import { join as join9 } from "path";
|
|
4675
5057
|
var _library = null;
|
|
4676
5058
|
function registerSkillLibrary(library) {
|
|
4677
5059
|
_library = library;
|
|
4678
5060
|
}
|
|
4679
5061
|
function registerSkillLibraryFromPath(root) {
|
|
4680
|
-
const indexPath =
|
|
4681
|
-
if (
|
|
5062
|
+
const indexPath = join9(root, "index.js");
|
|
5063
|
+
if (existsSync15(indexPath)) {
|
|
4682
5064
|
_library = loadLibraryFromModule(root);
|
|
4683
5065
|
return;
|
|
4684
5066
|
}
|
|
@@ -4689,13 +5071,13 @@ function clearRegisteredLibrary() {
|
|
|
4689
5071
|
}
|
|
4690
5072
|
function discoverLibrary() {
|
|
4691
5073
|
const envPath = process.env["CAAMP_SKILL_LIBRARY"];
|
|
4692
|
-
if (envPath &&
|
|
5074
|
+
if (envPath && existsSync15(envPath)) {
|
|
4693
5075
|
try {
|
|
4694
|
-
const indexPath =
|
|
4695
|
-
if (
|
|
5076
|
+
const indexPath = join9(envPath, "index.js");
|
|
5077
|
+
if (existsSync15(indexPath)) {
|
|
4696
5078
|
return loadLibraryFromModule(envPath);
|
|
4697
5079
|
}
|
|
4698
|
-
if (
|
|
5080
|
+
if (existsSync15(join9(envPath, "skills.json"))) {
|
|
4699
5081
|
return buildLibraryFromFiles(envPath);
|
|
4700
5082
|
}
|
|
4701
5083
|
} catch {
|
|
@@ -4802,9 +5184,9 @@ function getLibraryRoot() {
|
|
|
4802
5184
|
}
|
|
4803
5185
|
|
|
4804
5186
|
// src/core/skills/discovery.ts
|
|
4805
|
-
import { existsSync as
|
|
5187
|
+
import { existsSync as existsSync16 } from "fs";
|
|
4806
5188
|
import { readdir as readdir3, readFile as readFile7 } from "fs/promises";
|
|
4807
|
-
import { join as
|
|
5189
|
+
import { join as join10 } from "path";
|
|
4808
5190
|
import matter from "gray-matter";
|
|
4809
5191
|
async function parseSkillFile(filePath) {
|
|
4810
5192
|
try {
|
|
@@ -4828,8 +5210,8 @@ async function parseSkillFile(filePath) {
|
|
|
4828
5210
|
}
|
|
4829
5211
|
}
|
|
4830
5212
|
async function discoverSkill(skillDir) {
|
|
4831
|
-
const skillFile =
|
|
4832
|
-
if (!
|
|
5213
|
+
const skillFile = join10(skillDir, "SKILL.md");
|
|
5214
|
+
if (!existsSync16(skillFile)) return null;
|
|
4833
5215
|
const metadata = await parseSkillFile(skillFile);
|
|
4834
5216
|
if (!metadata) return null;
|
|
4835
5217
|
return {
|
|
@@ -4840,12 +5222,12 @@ async function discoverSkill(skillDir) {
|
|
|
4840
5222
|
};
|
|
4841
5223
|
}
|
|
4842
5224
|
async function discoverSkills(rootDir) {
|
|
4843
|
-
if (!
|
|
5225
|
+
if (!existsSync16(rootDir)) return [];
|
|
4844
5226
|
const entries = await readdir3(rootDir, { withFileTypes: true });
|
|
4845
5227
|
const skills = [];
|
|
4846
5228
|
for (const entry of entries) {
|
|
4847
5229
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
4848
|
-
const skillDir =
|
|
5230
|
+
const skillDir = join10(rootDir, entry.name);
|
|
4849
5231
|
const skill = await discoverSkill(skillDir);
|
|
4850
5232
|
if (skill) {
|
|
4851
5233
|
skills.push(skill);
|
|
@@ -4869,7 +5251,7 @@ async function discoverSkillsMulti(dirs) {
|
|
|
4869
5251
|
}
|
|
4870
5252
|
|
|
4871
5253
|
// src/core/skills/validator.ts
|
|
4872
|
-
import { existsSync as
|
|
5254
|
+
import { existsSync as existsSync17 } from "fs";
|
|
4873
5255
|
import { readFile as readFile8 } from "fs/promises";
|
|
4874
5256
|
import matter2 from "gray-matter";
|
|
4875
5257
|
var RESERVED_NAMES = [
|
|
@@ -4891,7 +5273,7 @@ var WARN_BODY_LINES = 500;
|
|
|
4891
5273
|
var WARN_DESCRIPTION_LENGTH = 50;
|
|
4892
5274
|
async function validateSkill(filePath) {
|
|
4893
5275
|
const issues = [];
|
|
4894
|
-
if (!
|
|
5276
|
+
if (!existsSync17(filePath)) {
|
|
4895
5277
|
return {
|
|
4896
5278
|
valid: false,
|
|
4897
5279
|
issues: [{ level: "error", field: "file", message: "File does not exist" }],
|
|
@@ -5079,6 +5461,12 @@ export {
|
|
|
5079
5461
|
buildBackupTimestamp,
|
|
5080
5462
|
runDoctorBridge,
|
|
5081
5463
|
registerDoctorBridge,
|
|
5464
|
+
discoverOrphans,
|
|
5465
|
+
applyDecision,
|
|
5466
|
+
writeAuditLog,
|
|
5467
|
+
runDoctorAdopt,
|
|
5468
|
+
caampStandaloneAdapters,
|
|
5469
|
+
registerSkillsDoctorAdopt,
|
|
5082
5470
|
MarketplaceClient,
|
|
5083
5471
|
RECOMMENDATION_ERROR_CODES,
|
|
5084
5472
|
tokenizeCriteriaValue,
|
|
@@ -5107,4 +5495,4 @@ export {
|
|
|
5107
5495
|
discoverSkillsMulti,
|
|
5108
5496
|
validateSkill
|
|
5109
5497
|
};
|
|
5110
|
-
//# sourceMappingURL=chunk-
|
|
5498
|
+
//# sourceMappingURL=chunk-WXL7RPS4.js.map
|