@cleocode/caamp 1.5.2 → 1.6.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/README.md CHANGED
@@ -65,6 +65,31 @@ const installed = getInstalledProviders();
65
65
  const servers = await listAllMcpServers(installed, "global");
66
66
  ```
67
67
 
68
+ ### Querying Provider Capabilities
69
+
70
+ ```typescript
71
+ import {
72
+ getProviderCapabilities,
73
+ getSpawnCapableProviders,
74
+ getProvidersByHookEvent,
75
+ buildSkillsMap,
76
+ } from "@cleocode/caamp";
77
+
78
+ // Get capabilities for a specific provider
79
+ const caps = getProviderCapabilities("claude-code");
80
+ console.log(caps?.spawn.supportsSubagents); // true
81
+ console.log(caps?.hooks.supported); // ["onSessionStart", ...]
82
+
83
+ // Find all providers that support spawning subagents
84
+ const spawnCapable = getSpawnCapableProviders();
85
+
86
+ // Find providers supporting a specific hook event
87
+ const hookProviders = getProvidersByHookEvent("onToolComplete");
88
+
89
+ // Get full skills precedence map
90
+ const skillsMap = buildSkillsMap();
91
+ ```
92
+
68
93
  See [API Reference](https://codluv.gitbook.io/caamp/api-and-reference/api-reference) for full programmatic API documentation.
69
94
 
70
95
  ## CLI Commands
@@ -561,6 +561,42 @@ function resolveProviderSkillsDir(provider, scope, projectDir = process.cwd()) {
561
561
  }
562
562
  return resolveProjectPath(provider.pathProjectSkills, projectDir);
563
563
  }
564
+ function resolveProviderSkillsDirs(provider, scope, projectDir = process.cwd()) {
565
+ const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);
566
+ const precedence = provider.capabilities?.skills?.precedence ?? "vendor-only";
567
+ const resolveAgentsPath = () => {
568
+ if (scope === "global") {
569
+ return provider.capabilities?.skills?.agentsGlobalPath ?? null;
570
+ }
571
+ const projectRelative = provider.capabilities?.skills?.agentsProjectPath ?? null;
572
+ return projectRelative ? join2(projectDir, projectRelative) : null;
573
+ };
574
+ switch (precedence) {
575
+ case "vendor-only":
576
+ return [vendorPath];
577
+ case "agents-canonical": {
578
+ const agentsPath = resolveAgentsPath();
579
+ return agentsPath ? [agentsPath] : [vendorPath];
580
+ }
581
+ case "agents-first": {
582
+ const agentsPath = resolveAgentsPath();
583
+ return agentsPath ? [agentsPath, vendorPath] : [vendorPath];
584
+ }
585
+ case "agents-supported": {
586
+ const agentsPath = resolveAgentsPath();
587
+ return agentsPath ? [vendorPath, agentsPath] : [vendorPath];
588
+ }
589
+ case "vendor-global-agents-project": {
590
+ if (scope === "global") {
591
+ return [vendorPath];
592
+ }
593
+ const agentsPath = resolveAgentsPath();
594
+ return agentsPath ? [agentsPath, vendorPath] : [vendorPath];
595
+ }
596
+ default:
597
+ return [vendorPath];
598
+ }
599
+ }
564
600
  function resolveProviderProjectPath(provider, projectDir = process.cwd()) {
565
601
  return resolveProjectPath(provider.pathProject, projectDir);
566
602
  }
@@ -860,8 +896,45 @@ function buildServerConfig(source, transport, headers) {
860
896
 
861
897
  // src/core/registry/providers.ts
862
898
  import { readFileSync } from "fs";
863
- import { dirname as dirname3 } from "path";
899
+ import { dirname as dirname3, join as join3 } from "path";
864
900
  import { fileURLToPath } from "url";
901
+ var DEFAULT_SKILLS_CAPABILITY = {
902
+ agentsGlobalPath: null,
903
+ agentsProjectPath: null,
904
+ precedence: "vendor-only"
905
+ };
906
+ var DEFAULT_HOOKS_CAPABILITY = {
907
+ supported: [],
908
+ hookConfigPath: null,
909
+ hookFormat: null
910
+ };
911
+ var DEFAULT_SPAWN_CAPABILITY = {
912
+ supportsSubagents: false,
913
+ supportsProgrammaticSpawn: false,
914
+ supportsInterAgentComms: false,
915
+ supportsParallelSpawn: false,
916
+ spawnMechanism: null
917
+ };
918
+ function resolveCapabilities(raw) {
919
+ const skills = raw?.skills ? {
920
+ agentsGlobalPath: raw.skills.agentsGlobalPath ? resolveRegistryTemplatePath(raw.skills.agentsGlobalPath) : null,
921
+ agentsProjectPath: raw.skills.agentsProjectPath,
922
+ precedence: raw.skills.precedence
923
+ } : { ...DEFAULT_SKILLS_CAPABILITY };
924
+ const hooks = raw?.hooks ? {
925
+ supported: raw.hooks.supported,
926
+ hookConfigPath: raw.hooks.hookConfigPath ? resolveRegistryTemplatePath(raw.hooks.hookConfigPath) : null,
927
+ hookFormat: raw.hooks.hookFormat
928
+ } : { ...DEFAULT_HOOKS_CAPABILITY, supported: [] };
929
+ const spawn = raw?.spawn ? {
930
+ supportsSubagents: raw.spawn.supportsSubagents,
931
+ supportsProgrammaticSpawn: raw.spawn.supportsProgrammaticSpawn,
932
+ supportsInterAgentComms: raw.spawn.supportsInterAgentComms,
933
+ supportsParallelSpawn: raw.spawn.supportsParallelSpawn,
934
+ spawnMechanism: raw.spawn.spawnMechanism
935
+ } : { ...DEFAULT_SPAWN_CAPABILITY };
936
+ return { skills, hooks, spawn };
937
+ }
865
938
  function findRegistryPath() {
866
939
  const thisDir = dirname3(fileURLToPath(import.meta.url));
867
940
  return resolveProvidersRegistryPath(thisDir);
@@ -896,7 +969,8 @@ function resolveProvider(raw) {
896
969
  supportsHeaders: raw.supportsHeaders,
897
970
  priority: raw.priority,
898
971
  status: raw.status,
899
- agentSkillsCompatible: raw.agentSkillsCompatible
972
+ agentSkillsCompatible: raw.agentSkillsCompatible,
973
+ capabilities: resolveCapabilities(raw.capabilities)
900
974
  };
901
975
  }
902
976
  function loadRegistry() {
@@ -956,11 +1030,104 @@ function getProviderCount() {
956
1030
  function getRegistryVersion() {
957
1031
  return loadRegistry().version;
958
1032
  }
1033
+ function getProvidersByHookEvent(event) {
1034
+ return getAllProviders().filter((p) => p.capabilities.hooks.supported.includes(event));
1035
+ }
1036
+ function getCommonHookEvents(providerIds) {
1037
+ const providers = providerIds && providerIds.length > 0 ? providerIds.map((id) => getProvider(id)).filter((p) => p !== void 0) : getAllProviders();
1038
+ if (providers.length === 0) return [];
1039
+ const first = providers[0].capabilities.hooks.supported;
1040
+ return first.filter(
1041
+ (event) => providers.every((p) => p.capabilities.hooks.supported.includes(event))
1042
+ );
1043
+ }
1044
+ function providerSupports(provider, dotPath) {
1045
+ const parts = dotPath.split(".");
1046
+ let current = provider.capabilities;
1047
+ for (const part of parts) {
1048
+ if (current == null || typeof current !== "object") return false;
1049
+ current = current[part];
1050
+ }
1051
+ if (typeof current === "boolean") return current;
1052
+ if (Array.isArray(current)) return current.length > 0;
1053
+ return current != null;
1054
+ }
1055
+ function getSpawnCapableProviders() {
1056
+ return getAllProviders().filter((p) => p.capabilities.spawn.supportsSubagents);
1057
+ }
1058
+ function getProvidersBySpawnCapability(flag) {
1059
+ return getAllProviders().filter((p) => p.capabilities.spawn[flag] === true);
1060
+ }
1061
+ function getProvidersBySkillsPrecedence(precedence) {
1062
+ return getAllProviders().filter((p) => p.capabilities.skills.precedence === precedence);
1063
+ }
1064
+ function getEffectiveSkillsPaths(provider, scope, projectDir) {
1065
+ const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);
1066
+ const { precedence, agentsGlobalPath, agentsProjectPath } = provider.capabilities.skills;
1067
+ const resolveAgentsPath = () => {
1068
+ if (scope === "global" && agentsGlobalPath) return agentsGlobalPath;
1069
+ if (scope === "project" && agentsProjectPath && projectDir) {
1070
+ return join3(projectDir, agentsProjectPath);
1071
+ }
1072
+ return null;
1073
+ };
1074
+ const agentsPath = resolveAgentsPath();
1075
+ const scopeLabel = scope === "global" ? "global" : "project";
1076
+ switch (precedence) {
1077
+ case "vendor-only":
1078
+ return [{ path: vendorPath, source: "vendor", scope: scopeLabel }];
1079
+ case "agents-canonical":
1080
+ return agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : [];
1081
+ case "agents-first":
1082
+ return [
1083
+ ...agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : [],
1084
+ { path: vendorPath, source: "vendor", scope: scopeLabel }
1085
+ ];
1086
+ case "agents-supported":
1087
+ return [
1088
+ { path: vendorPath, source: "vendor", scope: scopeLabel },
1089
+ ...agentsPath ? [{ path: agentsPath, source: "agents", scope: scopeLabel }] : []
1090
+ ];
1091
+ case "vendor-global-agents-project":
1092
+ if (scope === "global") {
1093
+ return [{ path: vendorPath, source: "vendor", scope: "global" }];
1094
+ }
1095
+ return [
1096
+ ...agentsPath ? [{ path: agentsPath, source: "agents", scope: "project" }] : [],
1097
+ { path: vendorPath, source: "vendor", scope: "project" }
1098
+ ];
1099
+ default:
1100
+ return [{ path: vendorPath, source: "vendor", scope: scopeLabel }];
1101
+ }
1102
+ }
1103
+ function buildSkillsMap() {
1104
+ return getAllProviders().map((p) => {
1105
+ const { precedence, agentsGlobalPath, agentsProjectPath } = p.capabilities.skills;
1106
+ const isVendorOnly = precedence === "vendor-only";
1107
+ return {
1108
+ providerId: p.id,
1109
+ toolName: p.toolName,
1110
+ precedence,
1111
+ paths: {
1112
+ global: isVendorOnly ? p.pathSkills : agentsGlobalPath ?? null,
1113
+ project: isVendorOnly ? p.pathProjectSkills : agentsProjectPath ?? null
1114
+ }
1115
+ };
1116
+ });
1117
+ }
1118
+ function getProviderCapabilities(idOrAlias) {
1119
+ return getProvider(idOrAlias)?.capabilities;
1120
+ }
1121
+ function providerSupportsById(idOrAlias, capabilityPath) {
1122
+ const provider = getProvider(idOrAlias);
1123
+ if (!provider) return false;
1124
+ return providerSupports(provider, capabilityPath);
1125
+ }
959
1126
 
960
1127
  // src/core/registry/detection.ts
961
1128
  import { execFileSync } from "child_process";
962
1129
  import { existsSync as existsSync7 } from "fs";
963
- import { join as join3 } from "path";
1130
+ import { join as join4 } from "path";
964
1131
  var DEFAULT_DETECTION_CACHE_TTL_MS = 3e4;
965
1132
  var detectionCache = null;
966
1133
  function checkBinary(binary) {
@@ -978,7 +1145,7 @@ function checkDirectory(dir) {
978
1145
  function checkAppBundle(appName) {
979
1146
  if (process.platform !== "darwin") return false;
980
1147
  const applications = getPlatformLocations().applications;
981
- return applications.some((base) => existsSync7(join3(base, appName)));
1148
+ return applications.some((base) => existsSync7(join4(base, appName)));
982
1149
  }
983
1150
  function checkFlatpak(flatpakId) {
984
1151
  if (process.platform !== "linux") return false;
@@ -1100,13 +1267,13 @@ function resetDetectionCache() {
1100
1267
  // src/core/skills/installer.ts
1101
1268
  import { existsSync as existsSync8, lstatSync } from "fs";
1102
1269
  import { cp, mkdir as mkdir2, rm, symlink } from "fs/promises";
1103
- import { join as join4 } from "path";
1270
+ import { join as join5 } from "path";
1104
1271
  async function ensureCanonicalDir() {
1105
1272
  await mkdir2(getCanonicalSkillsDir(), { recursive: true });
1106
1273
  }
1107
1274
  async function installToCanonical(sourcePath, skillName) {
1108
1275
  await ensureCanonicalDir();
1109
- const targetDir = join4(getCanonicalSkillsDir(), skillName);
1276
+ const targetDir = join5(getCanonicalSkillsDir(), skillName);
1110
1277
  await rm(targetDir, { recursive: true, force: true });
1111
1278
  try {
1112
1279
  await cp(sourcePath, targetDir, { recursive: true });
@@ -1121,38 +1288,44 @@ async function installToCanonical(sourcePath, skillName) {
1121
1288
  return targetDir;
1122
1289
  }
1123
1290
  async function linkToAgent(canonicalPath, provider, skillName, isGlobal, projectDir) {
1124
- const targetSkillsDir = resolveProviderSkillsDir(
1125
- provider,
1126
- isGlobal ? "global" : "project",
1127
- projectDir
1128
- );
1129
- if (!targetSkillsDir) {
1291
+ const scope = isGlobal ? "global" : "project";
1292
+ const targetDirs = resolveProviderSkillsDirs(provider, scope, projectDir);
1293
+ if (targetDirs.length === 0) {
1130
1294
  return { success: false, error: `Provider ${provider.id} has no skills directory` };
1131
1295
  }
1132
- try {
1133
- await mkdir2(targetSkillsDir, { recursive: true });
1134
- const linkPath = join4(targetSkillsDir, skillName);
1135
- if (existsSync8(linkPath)) {
1136
- const stat2 = lstatSync(linkPath);
1137
- if (stat2.isSymbolicLink()) {
1138
- await rm(linkPath);
1139
- } else {
1140
- await rm(linkPath, { recursive: true });
1141
- }
1142
- }
1143
- const symlinkType = process.platform === "win32" ? "junction" : "dir";
1296
+ const errors = [];
1297
+ let anySuccess = false;
1298
+ for (const targetSkillsDir of targetDirs) {
1299
+ if (!targetSkillsDir) continue;
1144
1300
  try {
1145
- await symlink(canonicalPath, linkPath, symlinkType);
1146
- } catch {
1147
- await cp(canonicalPath, linkPath, { recursive: true });
1301
+ await mkdir2(targetSkillsDir, { recursive: true });
1302
+ const linkPath = join5(targetSkillsDir, skillName);
1303
+ if (existsSync8(linkPath)) {
1304
+ const stat2 = lstatSync(linkPath);
1305
+ if (stat2.isSymbolicLink()) {
1306
+ await rm(linkPath);
1307
+ } else {
1308
+ await rm(linkPath, { recursive: true });
1309
+ }
1310
+ }
1311
+ const symlinkType = process.platform === "win32" ? "junction" : "dir";
1312
+ try {
1313
+ await symlink(canonicalPath, linkPath, symlinkType);
1314
+ } catch {
1315
+ await cp(canonicalPath, linkPath, { recursive: true });
1316
+ }
1317
+ anySuccess = true;
1318
+ } catch (err) {
1319
+ errors.push(err instanceof Error ? err.message : String(err));
1148
1320
  }
1321
+ }
1322
+ if (anySuccess) {
1149
1323
  return { success: true };
1150
- } catch (err) {
1151
- return {
1152
- success: false,
1153
- error: err instanceof Error ? err.message : String(err)
1154
- };
1155
1324
  }
1325
+ return {
1326
+ success: false,
1327
+ error: errors.join("; ") || `Provider ${provider.id} has no skills directory`
1328
+ };
1156
1329
  }
1157
1330
  async function installSkill(sourcePath, skillName, providers, isGlobal, projectDir) {
1158
1331
  const errors = [];
@@ -1178,23 +1351,26 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
1178
1351
  const removed = [];
1179
1352
  const errors = [];
1180
1353
  for (const provider of providers) {
1181
- const skillsDir = resolveProviderSkillsDir(
1182
- provider,
1183
- isGlobal ? "global" : "project",
1184
- projectDir
1185
- );
1186
- if (!skillsDir) continue;
1187
- const linkPath = join4(skillsDir, skillName);
1188
- if (existsSync8(linkPath)) {
1189
- try {
1190
- await rm(linkPath, { recursive: true });
1191
- removed.push(provider.id);
1192
- } catch (err) {
1193
- errors.push(`${provider.id}: ${err instanceof Error ? err.message : String(err)}`);
1354
+ const scope = isGlobal ? "global" : "project";
1355
+ const targetDirs = resolveProviderSkillsDirs(provider, scope, projectDir);
1356
+ let providerRemoved = false;
1357
+ for (const skillsDir of targetDirs) {
1358
+ if (!skillsDir) continue;
1359
+ const linkPath = join5(skillsDir, skillName);
1360
+ if (existsSync8(linkPath)) {
1361
+ try {
1362
+ await rm(linkPath, { recursive: true });
1363
+ providerRemoved = true;
1364
+ } catch (err) {
1365
+ errors.push(`${provider.id}: ${err instanceof Error ? err.message : String(err)}`);
1366
+ }
1194
1367
  }
1195
1368
  }
1369
+ if (providerRemoved) {
1370
+ removed.push(provider.id);
1371
+ }
1196
1372
  }
1197
- const canonicalPath = join4(getCanonicalSkillsDir(), skillName);
1373
+ const canonicalPath = join5(getCanonicalSkillsDir(), skillName);
1198
1374
  if (existsSync8(canonicalPath)) {
1199
1375
  try {
1200
1376
  await rm(canonicalPath, { recursive: true });
@@ -1223,7 +1399,7 @@ import {
1223
1399
  writeFile as writeFile5
1224
1400
  } from "fs/promises";
1225
1401
  import { tmpdir } from "os";
1226
- import { basename, dirname as dirname4, join as join5 } from "path";
1402
+ import { basename, dirname as dirname4, join as join6 } from "path";
1227
1403
 
1228
1404
  // src/core/paths/agents.ts
1229
1405
  var AGENTS_HOME = getAgentsHome();
@@ -1244,8 +1420,8 @@ function selectProvidersByMinimumPriority(providers, minimumPriority = "low") {
1244
1420
  return [...providers].filter((provider) => PRIORITY_ORDER[provider.priority] <= maxRank).sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);
1245
1421
  }
1246
1422
  function resolveSkillLinkPath(provider, skillName, isGlobal, projectDir) {
1247
- const skillDir = isGlobal ? provider.pathSkills : join5(projectDir, provider.pathProjectSkills);
1248
- return join5(skillDir, skillName);
1423
+ const skillDir = isGlobal ? provider.pathSkills : join6(projectDir, provider.pathProjectSkills);
1424
+ return join6(skillDir, skillName);
1249
1425
  }
1250
1426
  async function snapshotConfigs(paths) {
1251
1427
  const snapshots = /* @__PURE__ */ new Map();
@@ -1272,9 +1448,9 @@ async function restoreConfigSnapshots(snapshots) {
1272
1448
  async function snapshotSkillState(providerTargets, operation, projectDir, backupRoot) {
1273
1449
  const skillName = operation.skillName;
1274
1450
  const isGlobal = operation.isGlobal ?? true;
1275
- const canonicalPath = join5(CANONICAL_SKILLS_DIR, skillName);
1451
+ const canonicalPath = join6(CANONICAL_SKILLS_DIR, skillName);
1276
1452
  const canonicalExisted = existsSync9(canonicalPath);
1277
- const canonicalBackupPath = join5(backupRoot, "canonical", skillName);
1453
+ const canonicalBackupPath = join6(backupRoot, "canonical", skillName);
1278
1454
  if (canonicalExisted) {
1279
1455
  await mkdir3(dirname4(canonicalBackupPath), { recursive: true });
1280
1456
  await cp2(canonicalPath, canonicalBackupPath, { recursive: true });
@@ -1295,7 +1471,7 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
1295
1471
  });
1296
1472
  continue;
1297
1473
  }
1298
- const backupPath = join5(backupRoot, "links", provider.id, `${skillName}-${basename(linkPath)}`);
1474
+ const backupPath = join6(backupRoot, "links", provider.id, `${skillName}-${basename(linkPath)}`);
1299
1475
  await mkdir3(dirname4(backupPath), { recursive: true });
1300
1476
  if (stat2.isDirectory()) {
1301
1477
  await cp2(linkPath, backupPath, { recursive: true });
@@ -1356,7 +1532,7 @@ async function installBatchWithRollback(options) {
1356
1532
  return paths;
1357
1533
  });
1358
1534
  const configSnapshots = await snapshotConfigs(configPaths);
1359
- const backupRoot = join5(
1535
+ const backupRoot = join6(
1360
1536
  tmpdir(),
1361
1537
  `caamp-skill-backup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
1362
1538
  );
@@ -1547,7 +1723,7 @@ async function updateInstructionsSingleOperation(providers, content, scope = "pr
1547
1723
  };
1548
1724
  for (const [filePath, action] of actions.entries()) {
1549
1725
  const providersForFile = providers.filter((provider) => {
1550
- const expectedPath = scope === "global" ? join5(provider.pathGlobal, provider.instructFile) : join5(projectDir, provider.instructFile);
1726
+ const expectedPath = scope === "global" ? join6(provider.pathGlobal, provider.instructFile) : join6(projectDir, provider.instructFile);
1551
1727
  return expectedPath === filePath;
1552
1728
  });
1553
1729
  const fallback = groupedByFile.get(basename(filePath)) ?? [];
@@ -2415,7 +2591,7 @@ var MarketplaceClient = class {
2415
2591
  // src/core/skills/library-loader.ts
2416
2592
  import { createRequire } from "module";
2417
2593
  import { existsSync as existsSync12, readdirSync, readFileSync as readFileSync2 } from "fs";
2418
- import { basename as basename2, dirname as dirname5, join as join6 } from "path";
2594
+ import { basename as basename2, dirname as dirname5, join as join7 } from "path";
2419
2595
  var require2 = createRequire(import.meta.url);
2420
2596
  function loadLibraryFromModule(root) {
2421
2597
  let mod;
@@ -2463,14 +2639,14 @@ function loadLibraryFromModule(root) {
2463
2639
  return mod;
2464
2640
  }
2465
2641
  function buildLibraryFromFiles(root) {
2466
- const catalogPath = join6(root, "skills.json");
2642
+ const catalogPath = join7(root, "skills.json");
2467
2643
  if (!existsSync12(catalogPath)) {
2468
2644
  throw new Error(`No skills.json found at ${root}`);
2469
2645
  }
2470
2646
  const catalogData = JSON.parse(readFileSync2(catalogPath, "utf-8"));
2471
2647
  const entries = catalogData.skills ?? [];
2472
2648
  const version = catalogData.version ?? "0.0.0";
2473
- const manifestPath = join6(root, "skills", "manifest.json");
2649
+ const manifestPath = join7(root, "skills", "manifest.json");
2474
2650
  let manifest;
2475
2651
  if (existsSync12(manifestPath)) {
2476
2652
  manifest = JSON.parse(readFileSync2(manifestPath, "utf-8"));
@@ -2482,14 +2658,14 @@ function buildLibraryFromFiles(root) {
2482
2658
  skills: []
2483
2659
  };
2484
2660
  }
2485
- const profilesDir = join6(root, "profiles");
2661
+ const profilesDir = join7(root, "profiles");
2486
2662
  const profiles = /* @__PURE__ */ new Map();
2487
2663
  if (existsSync12(profilesDir)) {
2488
2664
  for (const file of readdirSync(profilesDir)) {
2489
2665
  if (!file.endsWith(".json")) continue;
2490
2666
  try {
2491
2667
  const profile = JSON.parse(
2492
- readFileSync2(join6(profilesDir, file), "utf-8")
2668
+ readFileSync2(join7(profilesDir, file), "utf-8")
2493
2669
  );
2494
2670
  profiles.set(profile.name, profile);
2495
2671
  } catch {
@@ -2503,9 +2679,9 @@ function buildLibraryFromFiles(root) {
2503
2679
  function getSkillDir2(name) {
2504
2680
  const entry = skillMap.get(name);
2505
2681
  if (entry) {
2506
- return dirname5(join6(root, entry.path));
2682
+ return dirname5(join7(root, entry.path));
2507
2683
  }
2508
- return join6(root, "skills", name);
2684
+ return join7(root, "skills", name);
2509
2685
  }
2510
2686
  function resolveDeps(names, visited = /* @__PURE__ */ new Set()) {
2511
2687
  const result = [];
@@ -2550,9 +2726,9 @@ function buildLibraryFromFiles(root) {
2550
2726
  getSkillPath(name) {
2551
2727
  const entry = skillMap.get(name);
2552
2728
  if (entry) {
2553
- return join6(root, entry.path);
2729
+ return join7(root, entry.path);
2554
2730
  }
2555
- return join6(root, "skills", name, "SKILL.md");
2731
+ return join7(root, "skills", name, "SKILL.md");
2556
2732
  },
2557
2733
  getSkillDir: getSkillDir2,
2558
2734
  readSkillContent(name) {
@@ -2584,10 +2760,10 @@ function buildLibraryFromFiles(root) {
2584
2760
  return resolveProfileByName(name);
2585
2761
  },
2586
2762
  listSharedResources() {
2587
- return discoverFiles(join6(root, "skills", "_shared"), ".md");
2763
+ return discoverFiles(join7(root, "skills", "_shared"), ".md");
2588
2764
  },
2589
2765
  getSharedResourcePath(name) {
2590
- const resourcePath = join6(root, "skills", "_shared", `${name}.md`);
2766
+ const resourcePath = join7(root, "skills", "_shared", `${name}.md`);
2591
2767
  return existsSync12(resourcePath) ? resourcePath : void 0;
2592
2768
  },
2593
2769
  readSharedResource(name) {
@@ -2596,14 +2772,14 @@ function buildLibraryFromFiles(root) {
2596
2772
  return readFileSync2(resourcePath, "utf-8");
2597
2773
  },
2598
2774
  listProtocols() {
2599
- const rootProtocols = discoverFiles(join6(root, "protocols"), ".md");
2775
+ const rootProtocols = discoverFiles(join7(root, "protocols"), ".md");
2600
2776
  if (rootProtocols.length > 0) return rootProtocols;
2601
- return discoverFiles(join6(root, "skills", "protocols"), ".md");
2777
+ return discoverFiles(join7(root, "skills", "protocols"), ".md");
2602
2778
  },
2603
2779
  getProtocolPath(name) {
2604
- const rootPath = join6(root, "protocols", `${name}.md`);
2780
+ const rootPath = join7(root, "protocols", `${name}.md`);
2605
2781
  if (existsSync12(rootPath)) return rootPath;
2606
- const skillsPath = join6(root, "skills", "protocols", `${name}.md`);
2782
+ const skillsPath = join7(root, "skills", "protocols", `${name}.md`);
2607
2783
  return existsSync12(skillsPath) ? skillsPath : void 0;
2608
2784
  },
2609
2785
  readProtocol(name) {
@@ -2629,7 +2805,7 @@ function buildLibraryFromFiles(root) {
2629
2805
  if (!entry.version) {
2630
2806
  issues.push({ level: "warn", field: "version", message: "Missing version" });
2631
2807
  }
2632
- const skillPath = join6(root, entry.path);
2808
+ const skillPath = join7(root, entry.path);
2633
2809
  if (!existsSync12(skillPath)) {
2634
2810
  issues.push({ level: "error", field: "path", message: `SKILL.md not found at ${entry.path}` });
2635
2811
  }
@@ -2686,13 +2862,13 @@ __export(catalog_exports, {
2686
2862
  validateSkillFrontmatter: () => validateSkillFrontmatter
2687
2863
  });
2688
2864
  import { existsSync as existsSync13 } from "fs";
2689
- import { join as join7 } from "path";
2865
+ import { join as join8 } from "path";
2690
2866
  var _library = null;
2691
2867
  function registerSkillLibrary(library) {
2692
2868
  _library = library;
2693
2869
  }
2694
2870
  function registerSkillLibraryFromPath(root) {
2695
- const indexPath = join7(root, "index.js");
2871
+ const indexPath = join8(root, "index.js");
2696
2872
  if (existsSync13(indexPath)) {
2697
2873
  _library = loadLibraryFromModule(root);
2698
2874
  return;
@@ -2706,11 +2882,11 @@ function discoverLibrary() {
2706
2882
  const envPath = process.env["CAAMP_SKILL_LIBRARY"];
2707
2883
  if (envPath && existsSync13(envPath)) {
2708
2884
  try {
2709
- const indexPath = join7(envPath, "index.js");
2885
+ const indexPath = join8(envPath, "index.js");
2710
2886
  if (existsSync13(indexPath)) {
2711
2887
  return loadLibraryFromModule(envPath);
2712
2888
  }
2713
- if (existsSync13(join7(envPath, "skills.json"))) {
2889
+ if (existsSync13(join8(envPath, "skills.json"))) {
2714
2890
  return buildLibraryFromFiles(envPath);
2715
2891
  }
2716
2892
  } catch {
@@ -2819,7 +2995,7 @@ function getLibraryRoot() {
2819
2995
  // src/core/skills/discovery.ts
2820
2996
  import { readFile as readFile7, readdir } from "fs/promises";
2821
2997
  import { existsSync as existsSync14 } from "fs";
2822
- import { join as join8 } from "path";
2998
+ import { join as join9 } from "path";
2823
2999
  import matter from "gray-matter";
2824
3000
  async function parseSkillFile(filePath) {
2825
3001
  try {
@@ -2843,7 +3019,7 @@ async function parseSkillFile(filePath) {
2843
3019
  }
2844
3020
  }
2845
3021
  async function discoverSkill(skillDir) {
2846
- const skillFile = join8(skillDir, "SKILL.md");
3022
+ const skillFile = join9(skillDir, "SKILL.md");
2847
3023
  if (!existsSync14(skillFile)) return null;
2848
3024
  const metadata = await parseSkillFile(skillFile);
2849
3025
  if (!metadata) return null;
@@ -2860,7 +3036,7 @@ async function discoverSkills(rootDir) {
2860
3036
  const skills = [];
2861
3037
  for (const entry of entries) {
2862
3038
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
2863
- const skillDir = join8(rootDir, entry.name);
3039
+ const skillDir = join9(rootDir, entry.name);
2864
3040
  const skill = await discoverSkill(skillDir);
2865
3041
  if (skill) {
2866
3042
  skills.push(skill);
@@ -3698,13 +3874,13 @@ async function scanFile(filePath, rules) {
3698
3874
  }
3699
3875
  async function scanDirectory(dirPath) {
3700
3876
  const { readdir: readdir2 } = await import("fs/promises");
3701
- const { join: join9 } = await import("path");
3877
+ const { join: join10 } = await import("path");
3702
3878
  if (!existsSync15(dirPath)) return [];
3703
3879
  const entries = await readdir2(dirPath, { withFileTypes: true });
3704
3880
  const results = [];
3705
3881
  for (const entry of entries) {
3706
3882
  if (entry.isDirectory() || entry.isSymbolicLink()) {
3707
- const skillFile = join9(dirPath, entry.name, "SKILL.md");
3883
+ const skillFile = join10(dirPath, entry.name, "SKILL.md");
3708
3884
  if (existsSync15(skillFile)) {
3709
3885
  results.push(await scanFile(skillFile));
3710
3886
  }
@@ -3930,6 +4106,7 @@ export {
3930
4106
  resolveProviderConfigPath,
3931
4107
  resolvePreferredConfigScope,
3932
4108
  resolveProviderSkillsDir,
4109
+ resolveProviderSkillsDirs,
3933
4110
  buildSkillSubPathCandidates,
3934
4111
  resolveConfigPath,
3935
4112
  listMcpServers,
@@ -3950,6 +4127,16 @@ export {
3950
4127
  getInstructionFiles,
3951
4128
  getProviderCount,
3952
4129
  getRegistryVersion,
4130
+ getProvidersByHookEvent,
4131
+ getCommonHookEvents,
4132
+ providerSupports,
4133
+ getSpawnCapableProviders,
4134
+ getProvidersBySpawnCapability,
4135
+ getProvidersBySkillsPrecedence,
4136
+ getEffectiveSkillsPaths,
4137
+ buildSkillsMap,
4138
+ getProviderCapabilities,
4139
+ providerSupportsById,
3953
4140
  detectProvider,
3954
4141
  detectAllProviders,
3955
4142
  getInstalledProviders,
@@ -4019,4 +4206,4 @@ export {
4019
4206
  toSarif,
4020
4207
  validateSkill
4021
4208
  };
4022
- //# sourceMappingURL=chunk-ZEXRZTQX.js.map
4209
+ //# sourceMappingURL=chunk-N5E7BZM2.js.map