From c17f2abd7ba1f67fa26be93d937b4ef3eaf4242c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 21 Jun 2026 09:38:58 +0200 Subject: [PATCH] fix(ai): keep gpt-5-codex slugs text-only in the vision gate The codex vision gate accepted any gpt-5 prefix, which included the gpt-5-codex specialist slugs that the surrounding contract documents as text-only. Each lab OCR upload on such a slug burned a doomed image attempt before falling back. Exclude the -codex slugs from the gate so multimodal gpt-5.x slugs still report vision while the codex specialists stay on the text path. --- src/lib/ai/__tests__/vision-capability.test.ts | 3 +++ src/lib/ai/vision-capability.ts | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/ai/__tests__/vision-capability.test.ts b/src/lib/ai/__tests__/vision-capability.test.ts index 7edebe2fb..9a1e03c24 100644 --- a/src/lib/ai/__tests__/vision-capability.test.ts +++ b/src/lib/ai/__tests__/vision-capability.test.ts @@ -69,6 +69,9 @@ describe("supportsVisionForConfig", () => { expect(supportsVisionForConfig("codex", "gpt-4")).toBe(false); expect(supportsVisionForConfig("codex", "gpt-3.5-turbo")).toBe(false); expect(supportsVisionForConfig("codex", null)).toBe(false); + // The `-codex` specialist slugs are text-only despite the gpt-5 prefix. + expect(supportsVisionForConfig("codex", "gpt-5-codex")).toBe(false); + expect(supportsVisionForConfig("codex", "gpt-5.1-codex-mini")).toBe(false); }); it("never reports vision for none", () => { diff --git a/src/lib/ai/vision-capability.ts b/src/lib/ai/vision-capability.ts index 10f0950fd..daf382900 100644 --- a/src/lib/ai/vision-capability.ts +++ b/src/lib/ai/vision-capability.ts @@ -71,7 +71,10 @@ function openaiSupportsVision(model: string): boolean { function codexSupportsVision(model: string): boolean { const m = model.toLowerCase(); return ( - m.startsWith("gpt-5") || // GPT-5.x line is multimodal (text + vision) + // GPT-5.x line is multimodal (text + vision) — but the `-codex` specialist + // slugs (e.g. gpt-5-codex) are text-only, so they must not claim vision or + // every lab-OCR upload burns a doomed image attempt before falling back. + (m.startsWith("gpt-5") && !m.includes("-codex")) || m.startsWith("gpt-4o") || m.startsWith("gpt-4.1") || m.startsWith("gpt-4-turbo") ||