diff --git a/docs/current-handoff.md b/docs/current-handoff.md index cccea91..a9e4948 100644 --- a/docs/current-handoff.md +++ b/docs/current-handoff.md @@ -98,6 +98,12 @@ - This skipped schema-constrained reconstruction `/api/chat` and used unconstrained `/api/generate`. Response-body disposal now uses Fetch-compatible consumption without changing capability or fallback semantics. - Next boundary: one fresh-process fixed-scenario production observation. +## Reconstruction chat timeout + +- Capability detection/body disposal was fixed at `7070342`. Fresh runtime evidence then proved the real schema-constrained `/api/chat` request was attempted but Confidence Engine aborted it after 60 seconds while Qwen was still generating. +- Fallback `/api/generate` completed but produced structurally invalid reconstruction. The real reconstruction `/api/chat` timeout is now 300 seconds, matching `/api/generate`; fallback, schema, prompt, and reasoning semantics are unchanged. +- Next boundary: one fresh-process fixed-scenario production observation. + ## Current product architecture Three distinct routes, not a single page: diff --git a/lib/llm/provider.js b/lib/llm/provider.js index 4bdb74e..04f3e16 100644 --- a/lib/llm/provider.js +++ b/lib/llm/provider.js @@ -134,7 +134,7 @@ class OllamaLlmProvider { if (chatSupported) { try { const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 60000); + const timeout = setTimeout(() => controller.abort(), 300000); // 5 min for reconstruction apiUsed = "/api/chat"; providerExecution.chatRequestAttempted = true; diff --git a/tests/llm/provider.test.js b/tests/llm/provider.test.js index eb16177..a8fe8a1 100644 --- a/tests/llm/provider.test.js +++ b/tests/llm/provider.test.js @@ -10,6 +10,7 @@ describe("OllamaLlmProvider chat capability detection", () => { ok: true, json: async () => ({ message: { content: "{}" } }), }); + const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout"); vi.stubGlobal("fetch", fetchSpy); process.env.OLLAMA_BASE_URL = "http://ollama.test"; @@ -24,6 +25,7 @@ describe("OllamaLlmProvider chat capability detection", () => { expect(fetchSpy.mock.calls[0][0]).toBe("http://ollama.test/api/chat"); expect(fetchSpy.mock.calls[1][0]).toBe("http://ollama.test/api/chat"); expect(fetchSpy.mock.calls[1][0]).not.toContain("/api/generate"); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 300000); const chatRequest = JSON.parse(fetchSpy.mock.calls[1][1].body); expect(chatRequest).toMatchObject({ model: "configured-model", @@ -46,6 +48,7 @@ describe("OllamaLlmProvider chat capability detection", () => { }, }); } finally { + setTimeoutSpy.mockRestore(); vi.unstubAllGlobals(); if (originalBaseUrl === undefined) delete process.env.OLLAMA_BASE_URL; else process.env.OLLAMA_BASE_URL = originalBaseUrl;