__tests__/operator-error.test.js
Rama main · réplica de lectura del repositorio original.
import { it, expect, vi } from 'vitest';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { OperatorRun } from '../src/operator/harness.js';
import { Registry } from '../src/operator/registry.js';
it.each([
[new Error('quota exhausted'), 'quota exhausted'],
['every model key is out of allowance (0 of 3 usable)', 'every model key is out of allowance (0 of 3 usable)'],
[{ error: 'quota exhausted' }, 'quota exhausted'],
[null, 'Model request failed'],
])('preserves a rejected model request in the journal: %s', async (failure, expected) => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'op-error-'));
vi.useFakeTimers();
try {
const run = new OperatorRun({
goal: 'generate the video', systemPrompt: 'test', registry: new Registry(), persistDir: dir,
chat: async () => { throw failure; },
});
const done = run.run();
await vi.runAllTimersAsync();
await done;
expect(run.status).toBe('error');
expect(run.error).toBe(expected);
expect(run.finalLine).toContain(expected);
expect(JSON.parse(fs.readFileSync(path.join(dir, run.id + '.json'), 'utf8')).error).toBe(expected);
} finally { vi.useRealTimers(); fs.rmSync(dir, { recursive: true, force: true }); }
});
it('clears a transient provider error after the model recovers', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'op-recover-'));
vi.useFakeTimers();
try {
let attempts = 0;
const run = new OperatorRun({
goal: 'generate the video', systemPrompt: 'test', registry: new Registry(), persistDir: dir,
chat: async () => {
if (attempts++ === 0) throw 'temporary provider failure';
return { content: '', toolCalls: [{ name: 'finish', args: { status: 'done', summary: 'verified' } }] };
},
});
const done = run.run();
await vi.runAllTimersAsync();
await done;
expect(run.status).toBe('done');
expect(run.error).toBeNull();
} finally { vi.useRealTimers(); fs.rmSync(dir, { recursive: true, force: true }); }
});