@mmnto/cli 1.101.1 → 1.102.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.
Files changed (82) hide show
  1. package/dist/commands/doctor.d.ts +36 -6
  2. package/dist/commands/doctor.d.ts.map +1 -1
  3. package/dist/commands/doctor.js +27 -0
  4. package/dist/commands/doctor.js.map +1 -1
  5. package/dist/commands/doctor.test.js +46 -1
  6. package/dist/commands/doctor.test.js.map +1 -1
  7. package/dist/commands/ecl-gc.d.ts.map +1 -1
  8. package/dist/commands/ecl-gc.js +16 -4
  9. package/dist/commands/ecl-gc.js.map +1 -1
  10. package/dist/commands/eject.d.ts +37 -2
  11. package/dist/commands/eject.d.ts.map +1 -1
  12. package/dist/commands/eject.js +79 -9
  13. package/dist/commands/eject.js.map +1 -1
  14. package/dist/commands/eject.test.js +169 -7
  15. package/dist/commands/eject.test.js.map +1 -1
  16. package/dist/commands/gate-install.test.js +22 -1
  17. package/dist/commands/gate-install.test.js.map +1 -1
  18. package/dist/commands/init-detect.js +1 -1
  19. package/dist/commands/init-detect.js.map +1 -1
  20. package/dist/commands/init-detect.test.js +2 -1
  21. package/dist/commands/init-detect.test.js.map +1 -1
  22. package/dist/commands/init-templates.js +8 -8
  23. package/dist/commands/install-hooks.d.ts +16 -0
  24. package/dist/commands/install-hooks.d.ts.map +1 -1
  25. package/dist/commands/install-hooks.js +5 -1
  26. package/dist/commands/install-hooks.js.map +1 -1
  27. package/dist/commands/mail-cli-wiring.test.d.ts +15 -0
  28. package/dist/commands/mail-cli-wiring.test.d.ts.map +1 -0
  29. package/dist/commands/mail-cli-wiring.test.js +106 -0
  30. package/dist/commands/mail-cli-wiring.test.js.map +1 -0
  31. package/dist/commands/mail.d.ts +80 -0
  32. package/dist/commands/mail.d.ts.map +1 -1
  33. package/dist/commands/mail.js +241 -9
  34. package/dist/commands/mail.js.map +1 -1
  35. package/dist/commands/mail.test.js +359 -4
  36. package/dist/commands/mail.test.js.map +1 -1
  37. package/dist/commands/review-fan.d.ts.map +1 -1
  38. package/dist/commands/review-fan.js +32 -8
  39. package/dist/commands/review-fan.js.map +1 -1
  40. package/dist/commands/review-fan.test.js +153 -7
  41. package/dist/commands/review-fan.test.js.map +1 -1
  42. package/dist/commands/shield-generated.d.ts +145 -0
  43. package/dist/commands/shield-generated.d.ts.map +1 -0
  44. package/dist/commands/shield-generated.js +266 -0
  45. package/dist/commands/shield-generated.js.map +1 -0
  46. package/dist/commands/shield-generated.test.d.ts +2 -0
  47. package/dist/commands/shield-generated.test.d.ts.map +1 -0
  48. package/dist/commands/shield-generated.test.js +323 -0
  49. package/dist/commands/shield-generated.test.js.map +1 -0
  50. package/dist/commands/shield.d.ts +27 -5
  51. package/dist/commands/shield.d.ts.map +1 -1
  52. package/dist/commands/shield.js +116 -41
  53. package/dist/commands/shield.js.map +1 -1
  54. package/dist/commands/shield.test.js +92 -2
  55. package/dist/commands/shield.test.js.map +1 -1
  56. package/dist/commands/status.d.ts.map +1 -1
  57. package/dist/commands/status.js +26 -2
  58. package/dist/commands/status.js.map +1 -1
  59. package/dist/commands/status.test.js +55 -1
  60. package/dist/commands/status.test.js.map +1 -1
  61. package/dist/hook/schema.d.ts +2 -2
  62. package/dist/index.js +28 -7
  63. package/dist/index.js.map +1 -1
  64. package/dist/orchestrators/orchestrator.d.ts +86 -1
  65. package/dist/orchestrators/orchestrator.d.ts.map +1 -1
  66. package/dist/orchestrators/orchestrator.js +277 -9
  67. package/dist/orchestrators/orchestrator.js.map +1 -1
  68. package/dist/orchestrators/orchestrator.test.js +240 -4
  69. package/dist/orchestrators/orchestrator.test.js.map +1 -1
  70. package/dist/orchestrators/shell-orchestrator.d.ts +12 -1
  71. package/dist/orchestrators/shell-orchestrator.d.ts.map +1 -1
  72. package/dist/orchestrators/shell-orchestrator.js +256 -49
  73. package/dist/orchestrators/shell-orchestrator.js.map +1 -1
  74. package/dist/orchestrators/shell-orchestrator.test.js +252 -4
  75. package/dist/orchestrators/shell-orchestrator.test.js.map +1 -1
  76. package/dist/utils.d.ts +19 -1
  77. package/dist/utils.d.ts.map +1 -1
  78. package/dist/utils.js +394 -108
  79. package/dist/utils.js.map +1 -1
  80. package/dist/utils.test.js +406 -14
  81. package/dist/utils.test.js.map +1 -1
  82. package/package.json +2 -2
@@ -1,5 +1,227 @@
1
1
  import { TotemConfigError, TotemOrchestratorError } from '@mmnto/totem';
2
2
  import { invokeShellOrchestrator } from './shell-orchestrator.js';
3
+ const INVOKE_RECOVERY_HINT_LIMIT_BYTES = 1024;
4
+ function boundUtf8Text(value, limitBytes) {
5
+ const bytes = Buffer.from(value, 'utf8');
6
+ if (bytes.length <= limitBytes)
7
+ return value;
8
+ return bytes
9
+ .subarray(0, limitBytes)
10
+ .toString('utf8')
11
+ .replace(/\uFFFD$/u, '');
12
+ }
13
+ function defaultInvokeRecoveryHint(kind) {
14
+ switch (kind) {
15
+ case 'auth':
16
+ return 'Check the provider login or API key, then retry the invocation.';
17
+ case 'quota':
18
+ return 'Wait for quota to reset, increase provider quota, or configure an available fallbackModel.';
19
+ case 'model':
20
+ return 'Select a model that is available to the configured provider account.';
21
+ case 'process-spawn':
22
+ return 'Install the configured CLI, verify it is on PATH, and check the shell command.';
23
+ case 'process-exit':
24
+ return 'Inspect the bounded invocation evidence, correct the CLI/provider failure, and retry.';
25
+ case 'timeout':
26
+ return 'Reduce the request workload or fix provider availability, then retry.';
27
+ case 'unknown':
28
+ return 'Inspect the invocation failure artifact and provider status, then retry.';
29
+ }
30
+ }
31
+ function normalizeTotemErrorBody(message) {
32
+ return message.replace(/^(?:\[Totem Error\]\s*)+/u, '');
33
+ }
34
+ /**
35
+ * Stable invocation failure surface consumed by run-artifact persistence and
36
+ * review-fan diagnostics. Process text in `attempts` is bounded but not yet
37
+ * DLP-masked; callers must not persist it directly.
38
+ */
39
+ export class OrchestratorInvokeError extends TotemOrchestratorError {
40
+ code = 'ORCHESTRATOR_UNAVAILABLE';
41
+ kind;
42
+ attempts;
43
+ failureArtifactHash;
44
+ constructor(message, kind, attempts, options) {
45
+ super(normalizeTotemErrorBody(message), boundUtf8Text(options?.recoveryHint ?? defaultInvokeRecoveryHint(kind), INVOKE_RECOVERY_HINT_LIMIT_BYTES), options?.cause);
46
+ this.name = kind === 'quota' ? 'QuotaError' : 'OrchestratorInvokeError';
47
+ this.kind = kind;
48
+ this.attempts = attempts;
49
+ this.failureArtifactHash = options?.failureArtifactHash;
50
+ }
51
+ }
52
+ const ERROR_CAUSE_MAX_DEPTH = 8;
53
+ /** Bounded, cycle-safe traversal for provider metadata wrapped by Totem errors. */
54
+ function errorCauseChain(err) {
55
+ const chain = [];
56
+ const seen = new Set();
57
+ let current = err;
58
+ while (current !== null &&
59
+ (typeof current === 'object' || typeof current === 'function') &&
60
+ chain.length < ERROR_CAUSE_MAX_DEPTH &&
61
+ !seen.has(current)) {
62
+ chain.push(current);
63
+ seen.add(current);
64
+ try {
65
+ current = current['cause'];
66
+ // totem-context: intentional cleanup — a hostile cause getter ends this bounded, cycle-safe traversal at the last readable error; the already-collected evidence remains usable.
67
+ }
68
+ catch {
69
+ break;
70
+ }
71
+ }
72
+ return chain;
73
+ }
74
+ function numericProperty(err, names) {
75
+ for (const item of errorCauseChain(err)) {
76
+ for (const name of names) {
77
+ let value;
78
+ try {
79
+ value = item[name];
80
+ // totem-context: intentional cleanup — provider errors may expose hostile numeric getters; skip an unreadable field while bounded cause traversal continues.
81
+ }
82
+ catch {
83
+ continue;
84
+ }
85
+ if (typeof value === 'number' && Number.isFinite(value))
86
+ return value;
87
+ }
88
+ }
89
+ return undefined;
90
+ }
91
+ function stringProperties(err, names) {
92
+ const values = [];
93
+ for (const item of errorCauseChain(err)) {
94
+ for (const name of names) {
95
+ let value;
96
+ try {
97
+ value = item[name];
98
+ // totem-context: intentional cleanup — provider errors may expose hostile string getters; skip an unreadable field while bounded cause traversal continues.
99
+ }
100
+ catch {
101
+ continue;
102
+ }
103
+ if (typeof value === 'string' && value.length > 0)
104
+ values.push(value);
105
+ }
106
+ }
107
+ return values;
108
+ }
109
+ /**
110
+ * Deterministically classify an invocation failure. Structured process facts
111
+ * and provider status/code win over message heuristics; unmatched failures
112
+ * remain fail-honest as `unknown`.
113
+ */
114
+ export function classifyInvokeFailure(err, context = {}) {
115
+ if (context.timedOut)
116
+ return 'timeout';
117
+ if (context.spawnFailed)
118
+ return 'process-spawn';
119
+ if (!(err instanceof Error)) {
120
+ return context.exitCode !== undefined || context.signal !== undefined
121
+ ? 'process-exit'
122
+ : 'unknown';
123
+ }
124
+ const status = numericProperty(err, ['status', 'statusCode']);
125
+ const normalizedCodes = stringProperties(err, ['code', 'type']).map((value) => value.toLowerCase());
126
+ const hasCode = (predicate) => normalizedCodes.some(predicate);
127
+ const message = err.message.toLowerCase();
128
+ if (hasCode((code) => code === 'etimedout' || code === 'abort_err'))
129
+ return 'timeout';
130
+ if (hasCode((code) => ['enoent', 'eacces', 'enoexec'].includes(code)))
131
+ return 'process-spawn';
132
+ // Structured provider metadata is authoritative. In particular, an auth or
133
+ // model status/code must not be reclassified as quota merely because the
134
+ // provider's prose happens to mention quota or rate limits.
135
+ if (status === 429 ||
136
+ hasCode((code) => code.includes('rate_limit') || code.includes('quota')) ||
137
+ stringProperties(err, ['name']).includes('QuotaError') ||
138
+ stringProperties(err, ['kind']).includes('quota')) {
139
+ return 'quota';
140
+ }
141
+ if (status === 401 ||
142
+ status === 403 ||
143
+ hasCode((code) => code.includes('auth') || code.includes('api_key'))) {
144
+ return 'auth';
145
+ }
146
+ if (hasCode((code) => code.includes('model')))
147
+ return 'model';
148
+ if (message.includes('429') ||
149
+ message.includes('quota') ||
150
+ message.includes('rate limit') ||
151
+ message.includes('too many requests')) {
152
+ return 'quota';
153
+ }
154
+ if (message.includes('unauthorized') ||
155
+ message.includes('forbidden') ||
156
+ message.includes('authentication') ||
157
+ message.includes('invalid api key') ||
158
+ message.includes('no anthropic api key') ||
159
+ message.includes('no gemini api key') ||
160
+ message.includes('no openai api key')) {
161
+ return 'auth';
162
+ }
163
+ if (message.includes('model not found') ||
164
+ message.includes('unknown model') ||
165
+ message.includes('model unavailable') ||
166
+ message.includes('does not exist') ||
167
+ (message.includes('model') && message.includes('not installed'))) {
168
+ return 'model';
169
+ }
170
+ if (context.exitCode !== undefined || context.signal !== undefined)
171
+ return 'process-exit';
172
+ return 'unknown';
173
+ }
174
+ function providerMetadata(err) {
175
+ if (!(err instanceof Error))
176
+ return {};
177
+ const providerStatus = numericProperty(err, ['status', 'statusCode']);
178
+ const providerCodes = stringProperties(err, ['code', 'type']);
179
+ const providerCode = providerCodes.find((code) => code !== 'ORCHESTRATOR_UNAVAILABLE') ?? providerCodes[0];
180
+ return {
181
+ ...(providerStatus !== undefined ? { providerStatus } : {}),
182
+ ...(providerCode !== undefined ? { providerCode } : {}),
183
+ };
184
+ }
185
+ function failedRuntimeAttempt(provider, model, route, durationMs, err, context = {}) {
186
+ const failureKind = classifyInvokeFailure(err, context);
187
+ return {
188
+ sequence: 1,
189
+ route,
190
+ provider,
191
+ model,
192
+ status: 'failed',
193
+ durationMs,
194
+ failureKind,
195
+ ...providerMetadata(err),
196
+ };
197
+ }
198
+ function recoveryHintProperty(err) {
199
+ if (!(err instanceof Error))
200
+ return undefined;
201
+ const recoveryHint = err['recoveryHint'];
202
+ return typeof recoveryHint === 'string' && recoveryHint.length > 0 ? recoveryHint : undefined;
203
+ }
204
+ /**
205
+ * Normalize any provider throw at the invocation boundary. Existing structured
206
+ * errors retain identity; legacy Totem/provider errors remain available as the
207
+ * cause and keep their recovery hint while gaining typed attempt evidence.
208
+ */
209
+ export function toOrchestratorInvokeError(args) {
210
+ if (args.err instanceof OrchestratorInvokeError)
211
+ return args.err;
212
+ const attempt = failedRuntimeAttempt(args.provider, args.model, args.route, args.durationMs, args.err);
213
+ const message = args.err instanceof Error
214
+ ? args.err.message
215
+ : `Invocation failed for '${args.provider}' with a non-Error rejection.`;
216
+ const recoveryHint = recoveryHintProperty(args.err);
217
+ return new OrchestratorInvokeError(message, attempt.failureKind ?? 'unknown', [attempt], {
218
+ cause: args.err,
219
+ ...(recoveryHint !== undefined ? { recoveryHint } : {}),
220
+ });
221
+ }
222
+ function resequenceAttempts(attempts) {
223
+ return attempts.map((attempt, index) => ({ ...attempt, sequence: index + 1 }));
224
+ }
3
225
  // ─── Package manager detection (#236) ───────────────
4
226
  /**
5
227
  * Detect the active package manager from the `npm_config_user_agent` env var
@@ -23,6 +245,10 @@ export function detectPackageManager() {
23
245
  export function isQuotaError(err) {
24
246
  if (!(err instanceof Error))
25
247
  return false;
248
+ if (err.name === 'QuotaError')
249
+ return true;
250
+ if ('kind' in err && err.kind === 'quota')
251
+ return true;
26
252
  if ('status' in err && err.status === 429)
27
253
  return true;
28
254
  const msg = err.message.toLowerCase();
@@ -111,9 +337,9 @@ export function resolveOrchestrator(rawModel, baseProvider, baseInvoke) {
111
337
  }
112
338
  // ─── CLI fallback infrastructure ─────────────────────
113
339
  /** Map provider names to their CLI command templates. {file} and {model} are replaced at runtime. */
114
- const CLI_FALLBACK_COMMANDS = {
340
+ export const CLI_FALLBACK_COMMANDS = {
115
341
  gemini: 'gemini -e none -m {model} < {file}',
116
- anthropic: 'claude -p {file} --model {model}',
342
+ anthropic: 'claude -p --model {model} < {file}',
117
343
  };
118
344
  /** Check if a CLI binary is available on PATH. */
119
345
  async function isCliAvailable(binary) {
@@ -166,19 +392,56 @@ function withCliFallback(provider, sdkInvoker) {
166
392
  if (!binary || !command)
167
393
  return sdkInvoker;
168
394
  return async (opts) => {
395
+ const sdkStartMs = Date.now();
169
396
  try {
170
397
  return await sdkInvoker(opts);
171
398
  }
172
399
  catch (err) {
173
- if (!isFallbackEligible(err))
174
- throw err;
175
- if (!(await isCliAvailable(binary))) {
176
- const msg = err instanceof Error ? err.message : String(err);
177
- throw new TotemOrchestratorError(`CLI fallback for '${provider}' unavailable: '${binary}' not found on PATH. Original error: ${msg}`, `Install the ${provider} CLI or its SDK to use this provider.`, err);
400
+ const sdkAttempt = failedRuntimeAttempt(provider, opts.model, 'sdk', Date.now() - sdkStartMs, err);
401
+ if (!isFallbackEligible(err)) {
402
+ const recoveryHint = recoveryHintProperty(err);
403
+ throw new OrchestratorInvokeError(err instanceof Error ? err.message : `Invocation failed for '${provider}'.`, sdkAttempt.failureKind ?? 'unknown', [sdkAttempt], {
404
+ cause: err,
405
+ ...(recoveryHint !== undefined ? { recoveryHint } : {}),
406
+ });
407
+ }
408
+ const cliProbeStartMs = Date.now();
409
+ const cliAvailable = await isCliAvailable(binary);
410
+ const cliProbeDurationMs = Date.now() - cliProbeStartMs;
411
+ if (!cliAvailable) {
412
+ const cliUnavailable = new Error(`[Totem Error] '${binary}' not found on PATH.`);
413
+ const cliAttempt = failedRuntimeAttempt(provider, opts.model, 'cli-fallback', cliProbeDurationMs, cliUnavailable, { spawnFailed: true });
414
+ throw new OrchestratorInvokeError(`CLI fallback for '${provider}' unavailable: '${binary}' not found on PATH.`, 'process-spawn', resequenceAttempts([sdkAttempt, cliAttempt]), {
415
+ cause: err,
416
+ recoveryHint: `Install the ${provider} CLI or its SDK to use this provider.`,
417
+ });
178
418
  }
179
419
  const { log } = await import('../ui.js');
180
420
  log.warn(opts.tag, `SDK unavailable, falling back to ${binary} CLI...`);
181
- return invokeShellOrchestrator({ ...opts, command });
421
+ try {
422
+ const result = await invokeShellOrchestrator({
423
+ ...opts,
424
+ command,
425
+ provider,
426
+ route: 'cli-fallback',
427
+ });
428
+ return {
429
+ ...result,
430
+ attempts: resequenceAttempts([sdkAttempt, ...(result.attempts ?? [])]),
431
+ };
432
+ }
433
+ catch (fallbackErr) {
434
+ const fallbackAttempts = fallbackErr instanceof OrchestratorInvokeError
435
+ ? fallbackErr.attempts
436
+ : [failedRuntimeAttempt(provider, opts.model, 'cli-fallback', 0, fallbackErr)];
437
+ const attempts = resequenceAttempts([sdkAttempt, ...fallbackAttempts]);
438
+ const kind = fallbackErr instanceof OrchestratorInvokeError
439
+ ? fallbackErr.kind
440
+ : (attempts.at(-1)?.failureKind ?? 'unknown');
441
+ throw new OrchestratorInvokeError(fallbackErr instanceof Error
442
+ ? fallbackErr.message
443
+ : `CLI fallback failed for '${provider}'.`, kind, attempts, { cause: fallbackErr });
444
+ }
182
445
  }
183
446
  };
184
447
  }
@@ -192,7 +455,12 @@ function withCliFallback(provider, sdkInvoker) {
192
455
  export function createOrchestrator(config) {
193
456
  switch (config.provider) {
194
457
  case 'shell':
195
- return (opts) => invokeShellOrchestrator({ ...opts, command: config.command });
458
+ return (opts) => invokeShellOrchestrator({
459
+ ...opts,
460
+ command: config.command,
461
+ provider: 'shell',
462
+ route: 'configured-shell',
463
+ });
196
464
  case 'gemini':
197
465
  return withCliFallback('gemini', async (opts) => {
198
466
  const { invokeGeminiOrchestrator } = await import('./gemini-orchestrator.js');
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrators/orchestrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrators/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,18 @@
1
+ import { EventEmitter } from 'node:events';
1
2
  import { afterEach, describe, expect, it, vi } from 'vitest';
2
- import { createOrchestrator, detectPackageManager, isQuotaError, parseModelString, resolveOrchestrator, } from './orchestrator.js';
3
+ import { TotemOrchestratorError } from '@mmnto/totem';
4
+ import { classifyInvokeFailure, CLI_FALLBACK_COMMANDS, createOrchestrator, detectPackageManager, isQuotaError, OrchestratorInvokeError, parseModelString, resolveOrchestrator, toOrchestratorInvokeError, } from './orchestrator.js';
5
+ const { mockShellInvoke, mockSpawn } = vi.hoisted(() => ({
6
+ mockShellInvoke: vi.fn(),
7
+ mockSpawn: vi.fn(),
8
+ }));
9
+ vi.mock('node:child_process', async (importOriginal) => ({
10
+ ...(await importOriginal()),
11
+ spawn: mockSpawn,
12
+ }));
13
+ vi.mock('./shell-orchestrator.js', () => ({
14
+ invokeShellOrchestrator: mockShellInvoke,
15
+ }));
3
16
  // ─── Mock provider modules ──────────────────────────
4
17
  vi.mock('./gemini-orchestrator.js', () => ({
5
18
  invokeGeminiOrchestrator: vi.fn().mockResolvedValue({
@@ -101,6 +114,10 @@ describe('createOrchestrator', () => {
101
114
  });
102
115
  // ─── CLI fallback ───────────────────────────────────
103
116
  describe('withCliFallback (via createOrchestrator)', () => {
117
+ it('pins Anthropic CLI fallback to prompt bytes on stdin', () => {
118
+ expect(CLI_FALLBACK_COMMANDS['anthropic']).toBe('claude -p --model {model} < {file}');
119
+ expect(CLI_FALLBACK_COMMANDS['anthropic']).not.toMatch(/-p\s+\{file\}/);
120
+ });
104
121
  it('gemini SDK success does not trigger fallback', async () => {
105
122
  const config = { provider: 'gemini' };
106
123
  const invoke = createOrchestrator(config);
@@ -126,13 +143,232 @@ describe('withCliFallback (via createOrchestrator)', () => {
126
143
  });
127
144
  expect(result.content).toBe('anthropic result');
128
145
  });
129
- it('non-fallback-eligible errors are re-thrown', async () => {
146
+ it('preserves the failed SDK attempt before a successful CLI fallback', async () => {
147
+ const { invokeAnthropicOrchestrator } = await import('./anthropic-orchestrator.js');
148
+ vi.mocked(invokeAnthropicOrchestrator).mockRejectedValueOnce(new Error('No Anthropic API key found'));
149
+ const availability = new EventEmitter();
150
+ availability.kill = vi.fn();
151
+ mockSpawn.mockImplementationOnce(() => {
152
+ process.nextTick(() => availability.emit('close', 0));
153
+ return availability;
154
+ });
155
+ mockShellInvoke.mockResolvedValueOnce({
156
+ content: 'fallback result',
157
+ inputTokens: null,
158
+ outputTokens: null,
159
+ durationMs: 20,
160
+ attempts: [
161
+ {
162
+ sequence: 1,
163
+ route: 'cli-fallback',
164
+ provider: 'anthropic',
165
+ model: 'claude-sonnet-5',
166
+ status: 'succeeded',
167
+ durationMs: 20,
168
+ },
169
+ ],
170
+ });
171
+ const invoke = createOrchestrator({ provider: 'anthropic' });
172
+ const result = await invoke({
173
+ prompt: 'test',
174
+ model: 'claude-sonnet-5',
175
+ cwd: '.',
176
+ tag: 'Test',
177
+ totemDir: '.totem',
178
+ });
179
+ expect(mockShellInvoke).toHaveBeenCalledWith(expect.objectContaining({
180
+ command: 'claude -p --model {model} < {file}',
181
+ provider: 'anthropic',
182
+ route: 'cli-fallback',
183
+ }));
184
+ expect(result.attempts).toEqual([
185
+ expect.objectContaining({
186
+ sequence: 1,
187
+ route: 'sdk',
188
+ status: 'failed',
189
+ failureKind: 'auth',
190
+ }),
191
+ expect.objectContaining({
192
+ sequence: 2,
193
+ route: 'cli-fallback',
194
+ status: 'succeeded',
195
+ }),
196
+ ]);
197
+ });
198
+ it('preserves both attempts when the CLI fallback also fails', async () => {
199
+ const { invokeGeminiOrchestrator } = await import('./gemini-orchestrator.js');
200
+ vi.mocked(invokeGeminiOrchestrator).mockRejectedValueOnce(new Error('No Gemini API key found'));
201
+ const availability = new EventEmitter();
202
+ availability.kill = vi.fn();
203
+ mockSpawn.mockImplementationOnce(() => {
204
+ process.nextTick(() => availability.emit('close', 0));
205
+ return availability;
206
+ });
207
+ const fallbackAttempt = {
208
+ sequence: 1,
209
+ route: 'cli-fallback',
210
+ provider: 'gemini',
211
+ model: 'gemini-3-pro',
212
+ status: 'failed',
213
+ durationMs: 30,
214
+ failureKind: 'timeout',
215
+ };
216
+ mockShellInvoke.mockRejectedValueOnce(new OrchestratorInvokeError('fallback timed out', 'timeout', [fallbackAttempt]));
217
+ const invoke = createOrchestrator({ provider: 'gemini' });
218
+ const err = await invoke({
219
+ prompt: 'test',
220
+ model: 'gemini-3-pro',
221
+ cwd: '.',
222
+ tag: 'Test',
223
+ totemDir: '.totem',
224
+ }).catch((cause) => cause);
225
+ expect(err).toBeInstanceOf(OrchestratorInvokeError);
226
+ expect(err).toMatchObject({ kind: 'timeout' });
227
+ expect(err.attempts).toEqual([
228
+ expect.objectContaining({ sequence: 1, route: 'sdk', status: 'failed' }),
229
+ expect.objectContaining({
230
+ sequence: 2,
231
+ route: 'cli-fallback',
232
+ status: 'failed',
233
+ failureKind: 'timeout',
234
+ }),
235
+ ]);
236
+ });
237
+ it('preserves the structured CLI install recovery contract when fallback is unavailable', async () => {
238
+ const { invokeAnthropicOrchestrator } = await import('./anthropic-orchestrator.js');
239
+ vi.mocked(invokeAnthropicOrchestrator).mockRejectedValueOnce(new Error('No Anthropic API key found'));
240
+ let nowMs = 1_000;
241
+ const dateNow = vi.spyOn(Date, 'now').mockImplementation(() => nowMs);
242
+ const availability = new EventEmitter();
243
+ availability.kill = vi.fn();
244
+ mockSpawn.mockImplementationOnce(() => {
245
+ process.nextTick(() => {
246
+ nowMs += 75;
247
+ availability.emit('close', 1);
248
+ });
249
+ return availability;
250
+ });
251
+ const invoke = createOrchestrator({ provider: 'anthropic' });
252
+ const err = await invoke({
253
+ prompt: 'test',
254
+ model: 'claude-sonnet-5',
255
+ cwd: '.',
256
+ tag: 'Test',
257
+ totemDir: '.totem',
258
+ }).catch((cause) => cause);
259
+ dateNow.mockRestore();
260
+ expect(err).toBeInstanceOf(OrchestratorInvokeError);
261
+ expect(err).toMatchObject({
262
+ code: 'ORCHESTRATOR_UNAVAILABLE',
263
+ kind: 'process-spawn',
264
+ recoveryHint: 'Install the anthropic CLI or its SDK to use this provider.',
265
+ attempts: [
266
+ expect.objectContaining({ sequence: 1, route: 'sdk' }),
267
+ expect.objectContaining({ sequence: 2, route: 'cli-fallback', durationMs: 75 }),
268
+ ],
269
+ });
270
+ });
271
+ it('preserves recovery guidance on non-fallback-eligible errors', async () => {
130
272
  // Override the mock to throw a non-eligible error
131
273
  const { invokeGeminiOrchestrator } = await import('./gemini-orchestrator.js');
132
- vi.mocked(invokeGeminiOrchestrator).mockRejectedValueOnce(new Error('Gemini API call failed: model not found'));
274
+ const sdkErr = Object.assign(new Error('Gemini API call failed: model not found'), {
275
+ recoveryHint: 'Select a Gemini model available to this account.',
276
+ });
277
+ vi.mocked(invokeGeminiOrchestrator).mockRejectedValueOnce(sdkErr);
133
278
  const config = { provider: 'gemini' };
134
279
  const invoke = createOrchestrator(config);
135
- await expect(invoke({ prompt: 'test', model: 'bad-model', cwd: '.', tag: 'Test', totemDir: '.totem' })).rejects.toThrow('model not found');
280
+ const rejection = invoke({
281
+ prompt: 'test',
282
+ model: 'bad-model',
283
+ cwd: '.',
284
+ tag: 'Test',
285
+ totemDir: '.totem',
286
+ });
287
+ await expect(rejection).rejects.toThrow('model not found');
288
+ await expect(rejection).rejects.toMatchObject({
289
+ name: 'OrchestratorInvokeError',
290
+ kind: 'model',
291
+ cause: sdkErr,
292
+ recoveryHint: 'Select a Gemini model available to this account.',
293
+ attempts: [
294
+ expect.objectContaining({
295
+ sequence: 1,
296
+ route: 'sdk',
297
+ status: 'failed',
298
+ failureKind: 'model',
299
+ }),
300
+ ],
301
+ });
302
+ });
303
+ });
304
+ describe('classifyInvokeFailure', () => {
305
+ it('uses deterministic timeout and spawn precedence', () => {
306
+ expect(classifyInvokeFailure(new Error('quota exceeded'), { timedOut: true })).toBe('timeout');
307
+ expect(classifyInvokeFailure(new Error('quota exceeded'), { spawnFailed: true })).toBe('process-spawn');
308
+ });
309
+ it('prefers structured provider metadata over generic prose', () => {
310
+ expect(classifyInvokeFailure(Object.assign(new Error('request failed'), { status: 429 }))).toBe('quota');
311
+ expect(classifyInvokeFailure(Object.assign(new Error('request failed'), { status: 401 }))).toBe('auth');
312
+ expect(classifyInvokeFailure(Object.assign(new Error('request failed'), { code: 'model_not_found' }))).toBe('model');
313
+ });
314
+ it('prefers structured auth/model metadata over conflicting quota prose', () => {
315
+ expect(classifyInvokeFailure(Object.assign(new Error('quota exhausted'), { status: 401 }))).toBe('auth');
316
+ expect(classifyInvokeFailure(Object.assign(new Error('rate limit exceeded'), { code: 'model_not_found' }))).toBe('model');
317
+ expect(classifyInvokeFailure(Object.assign(new Error('authentication failed'), { status: 429 }))).toBe('quota');
318
+ });
319
+ it('reads structured provider metadata through wrapped Error causes', () => {
320
+ const providerErr = Object.assign(new Error('provider rejected request'), {
321
+ status: 401,
322
+ code: 'authentication_error',
323
+ });
324
+ const wrapped = new TotemOrchestratorError('outer message mentions quota', 'keep the provider-specific recovery', providerErr);
325
+ expect(classifyInvokeFailure(wrapped)).toBe('auth');
326
+ const normalized = toOrchestratorInvokeError({
327
+ err: wrapped,
328
+ provider: 'openai',
329
+ model: 'gpt-5',
330
+ route: 'sdk',
331
+ durationMs: 12,
332
+ });
333
+ expect(normalized).toBeInstanceOf(TotemOrchestratorError);
334
+ expect(normalized.cause).toBe(wrapped);
335
+ expect(normalized.recoveryHint).toBe('keep the provider-specific recovery');
336
+ expect(normalized.attempts[0]).toMatchObject({
337
+ failureKind: 'auth',
338
+ providerStatus: 401,
339
+ providerCode: 'authentication_error',
340
+ durationMs: 12,
341
+ });
342
+ });
343
+ it('bounds cause traversal and terminates safely on cause cycles', () => {
344
+ const first = new Error('first');
345
+ const second = Object.assign(new Error('second'), { code: 'model_not_found', cause: first });
346
+ Object.assign(first, { cause: second });
347
+ expect(classifyInvokeFailure(first)).toBe('model');
348
+ let beyondDepth = Object.assign(new Error('provider'), { status: 429 });
349
+ for (let index = 0; index < 8; index++) {
350
+ beyondDepth = new Error(`wrapper-${index}`, { cause: beyondDepth });
351
+ }
352
+ expect(classifyInvokeFailure(beyondDepth)).toBe('unknown');
353
+ });
354
+ it('distinguishes process exit and preserves unknown', () => {
355
+ expect(classifyInvokeFailure(new Error('failed'), { exitCode: 2, signal: null })).toBe('process-exit');
356
+ expect(classifyInvokeFailure(new Error('unclassified provider response'))).toBe('unknown');
357
+ });
358
+ it('keeps quota name compatibility on the structured error', () => {
359
+ const err = new OrchestratorInvokeError('provider rejected the request', 'quota', []);
360
+ expect(err).toBeInstanceOf(OrchestratorInvokeError);
361
+ expect(err.name).toBe('QuotaError');
362
+ expect(isQuotaError(err)).toBe(true);
363
+ expect(err.code).toBe('ORCHESTRATOR_UNAVAILABLE');
364
+ expect(err.recoveryHint).toContain('fallbackModel');
365
+ });
366
+ it('normalizes duplicate Totem prefixes and bounds recovery hints', () => {
367
+ const err = new OrchestratorInvokeError('[Totem Error] [Totem Error] failed', 'unknown', [], {
368
+ recoveryHint: 'x'.repeat(2_000),
369
+ });
370
+ expect(err.message).toBe('[Totem Error] failed');
371
+ expect(Buffer.byteLength(err.recoveryHint, 'utf8')).toBeLessThanOrEqual(1_024);
136
372
  });
137
373
  });
138
374
  // ─── detectPackageManager ───────────────────────────