import test from "node:test"; import assert from "node:assert/strict"; import { resolveMasterAgentTaskTimeoutMs, runWithTaskTimeout } from "./master-task-timeout.mjs"; test("resolveMasterAgentTaskTimeoutMs prefers short timeout for project understanding sync", () => { const timeoutMs = resolveMasterAgentTaskTimeoutMs( {}, { taskType: "conversation_reply", projectId: "master-agent", projectUnderstandingTargetProjectId: "project-1", }, ); assert.equal(timeoutMs, 8 * 60 * 1000); }); test("resolveMasterAgentTaskTimeoutMs uses thread execution timeout for child thread work", () => { const timeoutMs = resolveMasterAgentTaskTimeoutMs( {}, { taskType: "conversation_reply", projectId: "project-1", }, ); assert.equal(timeoutMs, 30 * 60 * 1000); }); test("resolveMasterAgentTaskTimeoutMs honors config overrides", () => { const timeoutMs = resolveMasterAgentTaskTimeoutMs( { projectUnderstandingTaskTimeoutMs: 1234, masterAgentReplyTimeoutMs: 2345, threadExecutionTaskTimeoutMs: 3456, }, { taskType: "conversation_reply", projectId: "master-agent", projectUnderstandingTargetProjectId: "project-1", }, ); assert.equal(timeoutMs, 1234); }); test("runWithTaskTimeout resolves before timeout when operation finishes", async () => { const result = await runWithTaskTimeout( { timeoutMs: 100, label: "quick-task", }, async () => "ok", ); assert.equal(result, "ok"); }); test("runWithTaskTimeout rejects and invokes timeout cleanup when operation hangs", async () => { let timeoutCleanupCalled = 0; await assert.rejects( runWithTaskTimeout( { timeoutMs: 20, label: "hung-task", onTimeout: async () => { timeoutCleanupCalled += 1; }, }, async () => await new Promise(() => {}), ), /hung-task exceeded timeout after 20ms/, ); assert.equal(timeoutCleanupCalled, 1); });