fix(confidence-engine): preserve successful chat detection

This commit is contained in:
2026-09-05 19:41:01 +01:00
parent cd1c6f4fc5
commit 7070342fb1
3 changed files with 14 additions and 8 deletions
+6
View File
@@ -92,6 +92,12 @@
- Provider execution diagnostics now distinguish chat skipped due capability state, chat attempted and failed before generate fallback, and successful chat without fallback. They are deterministically verified through `/api/cases/start`; endpoint selection and fallback behaviour remain unchanged.
- Next restart point: one observation-only fixed-scenario production call to identify why `/api/generate` is reached.
## Chat capability body disposal
- A fresh-process debugger observation proved capability `/api/chat` returned HTTP 200, then invalid `res.body?.consume()` threw and the catch incorrectly cached `_chatSupported = false`.
- 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.
## Current product architecture
Three distinct routes, not a single page:
+4 -4
View File
@@ -84,13 +84,13 @@ async function detectChatSupport(baseUrl, modelName) {
});
if (res.ok) {
await res.body?.consume();
await res.text();
_chatSupported = true;
} else if (res.status === 405 || res.status === 501) {
await res.body?.consume();
await res.text();
_chatSupported = false;
} else {
await res.body?.consume();
await res.text();
_chatSupported = false;
}
} catch {
@@ -160,7 +160,7 @@ class OllamaLlmProvider {
: JSON.stringify(fullResponseData.message?.content ?? null);
apiUsed = "/api/chat";
} else {
await res.body?.consume();
await res.text();
}
} catch (e) {
if (!e.message.includes("abort")) { /* non-fatal */ }
+4 -4
View File
@@ -5,7 +5,7 @@ describe("OllamaLlmProvider chat capability detection", () => {
it("uses the configured model for the chat probe and keeps the chat path", async () => {
const originalBaseUrl = process.env.OLLAMA_BASE_URL;
const fetchSpy = vi.fn()
.mockResolvedValueOnce({ ok: true, body: { consume: vi.fn() } })
.mockResolvedValueOnce({ ok: true, text: async () => "" })
.mockResolvedValueOnce({
ok: true,
json: async () => ({ message: { content: "{}" } }),
@@ -55,7 +55,7 @@ describe("OllamaLlmProvider chat capability detection", () => {
it("reports chat-skipped generate fallback execution", async () => {
const originalBaseUrl = process.env.OLLAMA_BASE_URL;
const fetchSpy = vi.fn()
.mockResolvedValueOnce({ ok: false, status: 501, body: { consume: vi.fn() } })
.mockResolvedValueOnce({ ok: false, status: 501, text: async () => "" })
.mockResolvedValueOnce({ ok: false, status: 500, text: async () => "failure" });
vi.stubGlobal("fetch", fetchSpy);
process.env.OLLAMA_BASE_URL = "http://ollama.test";
@@ -84,8 +84,8 @@ describe("OllamaLlmProvider chat capability detection", () => {
it("reports chat-attempt-failed generate fallback execution", async () => {
const originalBaseUrl = process.env.OLLAMA_BASE_URL;
const fetchSpy = vi.fn()
.mockResolvedValueOnce({ ok: true, body: { consume: vi.fn() } })
.mockResolvedValueOnce({ ok: false, body: { consume: vi.fn() } })
.mockResolvedValueOnce({ ok: true, text: async () => "" })
.mockResolvedValueOnce({ ok: false, text: async () => "" })
.mockResolvedValueOnce({ ok: false, status: 500, text: async () => "failure" });
vi.stubGlobal("fetch", fetchSpy);
process.env.OLLAMA_BASE_URL = "http://ollama.test";