fix(tools): clear timeout timers and update audit state

This commit is contained in:
William Valentin
2026-02-15 21:44:40 -08:00
parent d93c1c9f8d
commit 4cdad8eee9
4 changed files with 607 additions and 491 deletions
+17 -1
View File
@@ -1,4 +1,4 @@
import { describe, it, expect } from 'vitest';
import { describe, it, expect, vi } from 'vitest';
import { ToolExecutor } from './executor.js';
import { ToolRegistry } from './registry.js';
import { HookEngine } from '../hooks/engine.js';
@@ -98,6 +98,22 @@ describe('ToolExecutor', () => {
expect(result.output).toContain('[truncated]');
});
it('clears timeout timer after fast tool completion', async () => {
vi.useFakeTimers();
try {
const registry = new ToolRegistry();
registry.register(echoTool);
const hooks = new HookEngine({ confirm: [], log: [], silent: [] });
const executor = new ToolExecutor(registry, hooks, { defaultTimeoutMs: 30_000 });
const result = await executor.execute('test.echo', { text: 'hello' });
expect(result.success).toBe(true);
expect(vi.getTimerCount()).toBe(0);
} finally {
vi.useRealTimers();
}
});
it('blocks on confirm hook and resolves when approved', async () => {
const registry = new ToolRegistry();
registry.register(echoTool);
+11 -3
View File
@@ -224,6 +224,7 @@ export class ToolExecutor {
agent_tier: context?.tier,
});
let timeoutHandle: NodeJS.Timeout | undefined;
try {
const result = await Promise.race([
(async () => {
@@ -239,9 +240,12 @@ export class ToolExecutor {
}
return tool.execute(args);
})(),
new Promise<ToolResult>((_, reject) =>
setTimeout(() => reject(new Error(`Tool '${toolName}' timed out after ${this.defaultTimeoutMs}ms`)), this.defaultTimeoutMs),
),
new Promise<ToolResult>((_, reject) => {
timeoutHandle = setTimeout(
() => reject(new Error(`Tool '${toolName}' timed out after ${this.defaultTimeoutMs}ms`)),
this.defaultTimeoutMs,
);
}),
]);
const duration = Date.now() - startTime;
@@ -286,6 +290,10 @@ export class ToolExecutor {
output: '',
error: String(errorRedaction.value),
};
} finally {
if (timeoutHandle) {
clearTimeout(timeoutHandle);
}
}
}