@cleocode/caamp 1.8.1 → 1.9.1

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/cli.js CHANGED
@@ -61,26 +61,35 @@ import {
61
61
  tokenizeCriteriaValue,
62
62
  updateInstructionsSingleOperation,
63
63
  validateSkill
64
- } from "./chunk-LDTYDQGR.js";
64
+ } from "./chunk-ZF4W3K5H.js";
65
65
  import {
66
- buildSkillSubPathCandidates,
67
66
  buildSkillsMap,
68
67
  checkAllInjections,
69
68
  generateInjectionContent,
70
69
  getAllProviders,
71
- getCommonHookEvents,
72
70
  getProvider,
73
71
  getProviderCount,
74
- getProvidersByHookEvent,
75
72
  getProvidersByPriority,
76
73
  getRegistryVersion,
77
74
  groupByInstructFile,
78
75
  injectAll,
79
- providerSupports,
76
+ providerSupports
77
+ } from "./chunk-O7IVK5JY.js";
78
+ import {
79
+ CANONICAL_HOOK_EVENTS,
80
+ buildHookMatrix,
81
+ getCommonEvents,
82
+ getHookMappingsVersion,
83
+ getHookSupport,
84
+ getProviderSummary,
85
+ translateToAll
86
+ } from "./chunk-J7UN457C.js";
87
+ import {
88
+ buildSkillSubPathCandidates,
80
89
  resolvePreferredConfigScope,
81
90
  resolveProviderConfigPath,
82
91
  resolveProviderSkillsDir
83
- } from "./chunk-CPHF5IM4.js";
92
+ } from "./chunk-TI6WOJDG.js";
84
93
 
85
94
  // src/cli.ts
86
95
  import { Command } from "commander";
@@ -94,11 +103,17 @@ import {
94
103
  isRegisteredErrorCode
95
104
  } from "@cleocode/lafs-protocol";
96
105
  var LAFSCommandError = class extends Error {
106
+ /** LAFS error code identifying the failure type. */
97
107
  code;
108
+ /** LAFS error category inferred from the error code. */
98
109
  category;
110
+ /** Whether the operation can be retried after fixing the root cause. */
99
111
  recoverable;
112
+ /** Human-readable suggestion for resolving the error. */
100
113
  suggestion;
114
+ /** Optional delay in milliseconds before retrying, or null. */
101
115
  retryAfterMs;
116
+ /** Optional additional error details payload. */
102
117
  details;
103
118
  constructor(code, message, suggestion, recoverable = true, details) {
104
119
  super(message);
@@ -2936,8 +2951,69 @@ ${provider.toolName}`));
2936
2951
  ${map.length} providers shown`));
2937
2952
  console.log();
2938
2953
  });
2939
- providers.command("hooks").description("Show provider hook event support").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--event <event>", "Filter to providers supporting a specific hook event").option("--common", "Show hook events common to all providers").action(async (opts) => {
2940
- const operation = "providers.hooks";
2954
+ const hooks = providers.command("hooks").description("Show provider hook event support");
2955
+ hooks.command("list", { isDefault: true }).description("Show all providers with their hook support summary").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2956
+ const operation = "providers.hooks.list";
2957
+ const mvi = "standard";
2958
+ let format;
2959
+ try {
2960
+ format = resolveOutputFormat2({
2961
+ jsonFlag: opts.json ?? false,
2962
+ humanFlag: (opts.human ?? false) || isHuman(),
2963
+ projectDefault: "json"
2964
+ }).format;
2965
+ } catch (error) {
2966
+ const message = error instanceof Error ? error.message : String(error);
2967
+ emitJsonError2(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
2968
+ process.exit(1);
2969
+ }
2970
+ const all = getAllProviders();
2971
+ const summaries = all.map((p) => getProviderSummary(p.id)).filter((s) => s !== void 0);
2972
+ if (format === "json") {
2973
+ const envelope = buildEnvelope4(
2974
+ operation,
2975
+ mvi,
2976
+ {
2977
+ mappingsVersion: getHookMappingsVersion(),
2978
+ canonicalEventCount: CANONICAL_HOOK_EVENTS.length,
2979
+ providers: summaries
2980
+ },
2981
+ null
2982
+ );
2983
+ console.log(JSON.stringify(envelope, null, 2));
2984
+ return;
2985
+ }
2986
+ console.log(pc11.bold(`
2987
+ CAMP Hook Support (mappings v${getHookMappingsVersion()})
2988
+ `));
2989
+ console.log(pc11.dim(` ${CANONICAL_HOOK_EVENTS.length} canonical events defined
2990
+ `));
2991
+ console.log(
2992
+ ` ${pc11.bold("Provider".padEnd(22))} ${pc11.bold("System".padEnd(10))} ${pc11.bold("Coverage".padEnd(12))} ${pc11.bold("Supported".padEnd(12))} ${pc11.bold("Provider-Only")}`
2993
+ );
2994
+ console.log(` ${"\u2500".repeat(22)} ${"\u2500".repeat(10)} ${"\u2500".repeat(12)} ${"\u2500".repeat(12)} ${"\u2500".repeat(20)}`);
2995
+ for (const s of summaries) {
2996
+ if (!s) continue;
2997
+ const system = s.hookSystem === "none" ? pc11.dim("none") : s.experimental ? pc11.yellow(s.hookSystem + "*") : pc11.green(s.hookSystem);
2998
+ const coverage = s.coverage > 0 ? (s.coverage >= 75 ? pc11.green : s.coverage >= 40 ? pc11.yellow : pc11.dim)(`${s.coverage}%`) : pc11.dim("0%");
2999
+ const supported = s.supportedCount > 0 ? `${s.supportedCount}/${s.totalCanonical}` : pc11.dim("0");
3000
+ const provOnly = s.providerOnly.length > 0 ? String(s.providerOnly.length) : pc11.dim("-");
3001
+ const provider = getProvider(s.providerId);
3002
+ const name = provider?.toolName ?? s.providerId;
3003
+ console.log(
3004
+ ` ${name.padEnd(22)} ${system.padEnd(20)} ${coverage.padEnd(22)} ${supported.padEnd(22)} ${provOnly}`
3005
+ );
3006
+ }
3007
+ const withHooks = summaries.filter((s) => s && s.supportedCount > 0);
3008
+ console.log(pc11.dim(`
3009
+ ${withHooks.length} providers with hook support, ${summaries.length - withHooks.length} without`));
3010
+ if (summaries.some((s) => s?.experimental)) {
3011
+ console.log(pc11.dim(" * = experimental hook system"));
3012
+ }
3013
+ console.log();
3014
+ });
3015
+ hooks.command("matrix").description("Show cross-provider hook support matrix").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--provider <ids>", "Comma-separated provider IDs to compare").action(async (opts) => {
3016
+ const operation = "providers.hooks.matrix";
2941
3017
  const mvi = "standard";
2942
3018
  let format;
2943
3019
  try {
@@ -2951,102 +3027,144 @@ ${provider.toolName}`));
2951
3027
  emitJsonError2(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
2952
3028
  process.exit(1);
2953
3029
  }
2954
- if (opts.event) {
2955
- const event = opts.event;
2956
- const matching = getProvidersByHookEvent(event);
3030
+ const ids = opts.provider?.split(",").map((s) => s.trim());
3031
+ const matrix = buildHookMatrix(ids);
3032
+ if (format === "json") {
3033
+ const envelope = buildEnvelope4(operation, mvi, { matrix }, null);
3034
+ console.log(JSON.stringify(envelope, null, 2));
3035
+ return;
3036
+ }
3037
+ const providerNames = matrix.providers.map((id) => {
3038
+ const p = getProvider(id);
3039
+ return (p?.toolName ?? id).slice(0, 14);
3040
+ });
3041
+ console.log(pc11.bold("\nHook Support Matrix\n"));
3042
+ const eventCol = "CAAMP Event".padEnd(22);
3043
+ const provCols = providerNames.map((n) => pc11.bold(n.padEnd(16))).join("");
3044
+ console.log(` ${pc11.bold(eventCol)} ${provCols}`);
3045
+ console.log(` ${"\u2500".repeat(22)} ${providerNames.map(() => "\u2500".repeat(16)).join("")}`);
3046
+ for (const event of matrix.events) {
3047
+ const cells = matrix.providers.map((id) => {
3048
+ const m = matrix.matrix[event][id];
3049
+ if (!m?.supported) return pc11.dim("\xB7".padEnd(16));
3050
+ return pc11.green((m.nativeName ?? "?").slice(0, 14).padEnd(16));
3051
+ }).join("");
3052
+ console.log(` ${event.padEnd(22)} ${cells}`);
3053
+ }
3054
+ const commonEvents = getCommonEvents(matrix.providers);
3055
+ console.log(pc11.dim(`
3056
+ Common events: ${commonEvents.length > 0 ? commonEvents.join(", ") : "none"}`));
3057
+ console.log();
3058
+ });
3059
+ hooks.command("translate").description("Translate a hook event name between CAAMP canonical and provider-native").argument("<event>", "Hook event name (canonical or native)").option("--to <provider>", "Target provider ID for canonical\u2192native translation").option("--from <provider>", "Source provider ID for native\u2192canonical translation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (event, opts) => {
3060
+ const operation = "providers.hooks.translate";
3061
+ const mvi = "standard";
3062
+ let format;
3063
+ try {
3064
+ format = resolveOutputFormat2({
3065
+ jsonFlag: opts.json ?? false,
3066
+ humanFlag: (opts.human ?? false) || isHuman(),
3067
+ projectDefault: "json"
3068
+ }).format;
3069
+ } catch (error) {
3070
+ const message = error instanceof Error ? error.message : String(error);
3071
+ emitJsonError2(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
3072
+ process.exit(1);
3073
+ }
3074
+ if (opts.to) {
3075
+ const canonical2 = event;
3076
+ if (!CANONICAL_HOOK_EVENTS.includes(canonical2)) {
3077
+ const msg = `Unknown canonical event: ${event}. Valid: ${CANONICAL_HOOK_EVENTS.join(", ")}`;
3078
+ if (format === "json") {
3079
+ emitJsonError2(operation, mvi, "E_UNKNOWN_EVENT", msg, "VALIDATION");
3080
+ } else {
3081
+ console.error(pc11.red(msg));
3082
+ }
3083
+ process.exit(1);
3084
+ }
3085
+ const result = getHookSupport(canonical2, opts.to);
2957
3086
  if (format === "json") {
2958
- const envelope = buildEnvelope4(
2959
- operation,
2960
- mvi,
2961
- {
2962
- event,
2963
- providers: matching.map((p) => ({
2964
- id: p.id,
2965
- toolName: p.toolName,
2966
- supportedEvents: p.capabilities.hooks.supported
2967
- })),
2968
- count: matching.length
2969
- },
2970
- null
2971
- );
3087
+ const envelope = buildEnvelope4(operation, mvi, {
3088
+ direction: "canonical-to-native",
3089
+ providerId: opts.to,
3090
+ ...result
3091
+ }, null);
2972
3092
  console.log(JSON.stringify(envelope, null, 2));
2973
- return;
2974
- }
2975
- console.log(pc11.bold(`
2976
- Providers supporting ${pc11.green(event)}:
2977
- `));
2978
- if (matching.length === 0) {
2979
- console.log(pc11.dim(" No providers support this event."));
2980
3093
  } else {
2981
- for (const p of matching) {
2982
- console.log(` ${pc11.bold(p.toolName.padEnd(22))} ${pc11.dim(p.id)}`);
3094
+ if (result.supported) {
3095
+ console.log(`
3096
+ ${pc11.green(event)} \u2192 ${pc11.bold(result.native)} (${opts.to})`);
3097
+ if (result.notes) console.log(pc11.dim(` Note: ${result.notes}`));
3098
+ } else {
3099
+ console.log(`
3100
+ ${pc11.red(event)} \u2192 ${pc11.dim("not supported")} (${opts.to})`);
2983
3101
  }
3102
+ console.log();
2984
3103
  }
2985
- console.log();
2986
3104
  return;
2987
3105
  }
2988
- if (opts.common) {
2989
- const common = getCommonHookEvents();
3106
+ if (opts.from) {
3107
+ const { toCanonical } = await import("./hooks-E2XQ7TQG.js");
3108
+ const canonical2 = toCanonical(event, opts.from);
2990
3109
  if (format === "json") {
2991
- const envelope = buildEnvelope4(
2992
- operation,
2993
- mvi,
2994
- {
2995
- commonEvents: common,
2996
- count: common.length
2997
- },
2998
- null
2999
- );
3110
+ const envelope = buildEnvelope4(operation, mvi, {
3111
+ direction: "native-to-canonical",
3112
+ native: event,
3113
+ providerId: opts.from,
3114
+ canonical: canonical2,
3115
+ supported: canonical2 !== null
3116
+ }, null);
3000
3117
  console.log(JSON.stringify(envelope, null, 2));
3001
- return;
3002
- }
3003
- console.log(pc11.bold("\nHook events common to all providers:\n"));
3004
- if (common.length === 0) {
3005
- console.log(pc11.dim(" No events are common to all providers."));
3006
3118
  } else {
3007
- for (const event of common) {
3008
- console.log(` ${pc11.green(event)}`);
3119
+ if (canonical2) {
3120
+ console.log(`
3121
+ ${pc11.bold(event)} (${opts.from}) \u2192 ${pc11.green(canonical2)}`);
3122
+ } else {
3123
+ console.log(`
3124
+ ${pc11.bold(event)} (${opts.from}) \u2192 ${pc11.dim("no canonical mapping (provider-only event)")}`);
3009
3125
  }
3126
+ console.log();
3010
3127
  }
3011
- console.log();
3012
3128
  return;
3013
3129
  }
3014
- const all = getAllProviders();
3015
- const withHooks = all.filter((p) => p.capabilities.hooks.supported.length > 0);
3130
+ const canonical = event;
3131
+ if (!CANONICAL_HOOK_EVENTS.includes(canonical)) {
3132
+ const msg = `Unknown canonical event: ${event}. Use --from <provider> for native names, or valid canonical: ${CANONICAL_HOOK_EVENTS.join(", ")}`;
3133
+ if (format === "json") {
3134
+ emitJsonError2(operation, mvi, "E_UNKNOWN_EVENT", msg, "VALIDATION");
3135
+ } else {
3136
+ console.error(pc11.red(msg));
3137
+ }
3138
+ process.exit(1);
3139
+ }
3140
+ const { getMappedProviderIds } = await import("./hooks-E2XQ7TQG.js");
3141
+ const allIds = getMappedProviderIds();
3142
+ const translations = translateToAll(canonical, allIds);
3016
3143
  if (format === "json") {
3017
- const envelope = buildEnvelope4(
3018
- operation,
3019
- mvi,
3020
- {
3021
- providers: all.map((p) => ({
3022
- id: p.id,
3023
- toolName: p.toolName,
3024
- supportedEvents: p.capabilities.hooks.supported
3025
- })),
3026
- withHooksCount: withHooks.length,
3027
- totalCount: all.length
3028
- },
3029
- null
3030
- );
3144
+ const envelope = buildEnvelope4(operation, mvi, {
3145
+ direction: "canonical-to-all",
3146
+ canonical: event,
3147
+ translations,
3148
+ supportedCount: Object.keys(translations).length,
3149
+ totalProviders: allIds.length
3150
+ }, null);
3031
3151
  console.log(JSON.stringify(envelope, null, 2));
3032
- return;
3033
- }
3034
- console.log(pc11.bold(`
3035
- Provider Hook Support
3036
- `));
3037
- if (withHooks.length === 0) {
3038
- console.log(pc11.dim(" No providers have hook support."));
3039
3152
  } else {
3040
- for (const p of withHooks) {
3041
- console.log(` ${pc11.bold(p.toolName.padEnd(22))} ${pc11.dim(p.capabilities.hooks.supported.join(", "))}`);
3153
+ console.log(pc11.bold(`
3154
+ ${event} across providers:
3155
+ `));
3156
+ for (const id of allIds) {
3157
+ const native = translations[id];
3158
+ const provider = getProvider(id);
3159
+ const name = (provider?.toolName ?? id).padEnd(22);
3160
+ if (native) {
3161
+ console.log(` ${pc11.green("\u2713")} ${name} ${pc11.bold(native)}`);
3162
+ } else {
3163
+ console.log(` ${pc11.dim("\xB7")} ${name} ${pc11.dim("not supported")}`);
3164
+ }
3042
3165
  }
3166
+ console.log();
3043
3167
  }
3044
- const withoutHooks = all.length - withHooks.length;
3045
- if (withoutHooks > 0) {
3046
- console.log(pc11.dim(`
3047
- ${withoutHooks} providers without hook support`));
3048
- }
3049
- console.log();
3050
3168
  });
3051
3169
  providers.command("capabilities").description("Show provider capability matrix").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--filter <path>", "Filter to providers supporting a capability dot-path (e.g. spawn.supportsSubagents)").action(async (opts) => {
3052
3170
  const operation = "providers.capabilities";
@@ -3104,10 +3222,10 @@ Provider Hook Support
3104
3222
  );
3105
3223
  console.log(` ${"\u2500".repeat(22)} ${"\u2500".repeat(20)} ${"\u2500".repeat(8)} ${"\u2500".repeat(20)}`);
3106
3224
  for (const row of matrix) {
3107
- const hooks = row.hooksCount > 0 ? String(row.hooksCount) : "-";
3225
+ const hooks2 = row.hooksCount > 0 ? String(row.hooksCount) : "-";
3108
3226
  const spawn = row.spawnMechanism ?? "-";
3109
3227
  console.log(
3110
- ` ${row.toolName.padEnd(22)} ${row.skillsPrecedence.padEnd(20)} ${hooks.padEnd(8)} ${spawn}`
3228
+ ` ${row.toolName.padEnd(22)} ${row.skillsPrecedence.padEnd(20)} ${hooks2.padEnd(8)} ${spawn}`
3111
3229
  );
3112
3230
  }
3113
3231
  console.log(pc11.dim(`