From 7d93af9d09751a21355a57e3080264c699df5c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 2 Sep 2026 10:32:50 +0200 Subject: [PATCH] fix(ai): recognise Claude 5 and Fable models as vision-capable The Anthropic vision check listed the Claude 3 and 4 families by prefix, so a key pinned to claude-sonnet-5, claude-opus-5 or a Fable model was told the provider cannot read images, and lab and document OCR refused the upload even though the model handles image and PDF blocks. Replace the per-release prefix list with a rule: any claude-- slug from the 4 family upward, plus every claude-fable-* model, counts as vision-capable. Claude 3 handling is unchanged. The Settings preset list gains claude-sonnet-5 and claude-opus-5 alongside the existing entries. --- CHANGELOG.md | 6 +++++ src/components/settings/ai/shared.ts | 2 ++ .../ai/__tests__/vision-capability.test.ts | 13 ++++++++++ src/lib/ai/vision-capability.ts | 24 ++++++++++++------- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8564e9de..ae5511ba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ plain instruction to reply with a single JSON object and nothing else, and the reply is narrowed to the object body on the way out, so a fenced or prefixed answer still parses. Reported independently by @sweidinger. +- **Lab and document OCR no longer refuse a current Claude model.** The + vision check knew the Claude 3 and 4 families by name, so a key pinned to + `claude-sonnet-5`, `claude-opus-5` or a Fable model was told the provider + cannot read images even though it can. Any Claude tier from the 4 family + upward, and every Fable model, now counts as vision-capable. The model + preset list in Settings also offers `claude-sonnet-5` and `claude-opus-5`. ## [1.38.1] — 2026-09-01 diff --git a/src/components/settings/ai/shared.ts b/src/components/settings/ai/shared.ts index 70dea2ac3..2b33eea1f 100644 --- a/src/components/settings/ai/shared.ts +++ b/src/components/settings/ai/shared.ts @@ -101,6 +101,8 @@ export const OPENAI_MODEL_PRESETS = [ export const ANTHROPIC_MODEL_PRESETS = [ "claude-sonnet-4-6", "claude-opus-4-7", + "claude-sonnet-5", + "claude-opus-5", "claude-haiku-4-5", "claude-3-5-sonnet-latest", ] as const; diff --git a/src/lib/ai/__tests__/vision-capability.test.ts b/src/lib/ai/__tests__/vision-capability.test.ts index 775d8c385..1eb2c47e1 100644 --- a/src/lib/ai/__tests__/vision-capability.test.ts +++ b/src/lib/ai/__tests__/vision-capability.test.ts @@ -21,6 +21,19 @@ describe("supportsVisionForConfig", () => { } }); + it("accepts current Claude 5-generation and Fable pins for anthropic", () => { + for (const model of [ + "claude-sonnet-5", + "claude-opus-5", + "claude-haiku-4-5", + "claude-fable-5", + "claude-fable-5-1", + "claude-opus-4-8", + ]) { + expect(supportsVisionForConfig("anthropic", model)).toBe(true); + } + }); + it("rejects legacy / text-only anthropic models", () => { expect(supportsVisionForConfig("anthropic", "claude-2.1")).toBe(false); expect(supportsVisionForConfig("anthropic", "claude-instant-1")).toBe( diff --git a/src/lib/ai/vision-capability.ts b/src/lib/ai/vision-capability.ts index ce7c55468..2a2eacae5 100644 --- a/src/lib/ai/vision-capability.ts +++ b/src/lib/ai/vision-capability.ts @@ -15,27 +15,33 @@ /** * Anthropic vision models. The Messages API `image` + `document` blocks are - * accepted by the whole Claude 3 family (3 / 3.5 / 3.7) and the Claude 4 - * family. An older `claude-2*` / `claude-instant*` pin is text-only. + * accepted by the whole Claude 3 family (3 / 3.5 / 3.7) and by every family + * from Claude 4 upward, Fable included. An older `claude-2*` / + * `claude-instant*` pin is text-only. * * The bare `claude-3-opus` / `claude-3-sonnet` / `claude-3-haiku` prefixes are * listed explicitly: a self-hoster pinned to e.g. `claude-3-opus-20240229` - * reads images, but the `claude-3-5` prefix does not match it. + * reads images, but the `claude-3-5` prefix does not match it. From Claude 4 + * on the slug is `claude--[-]`, so a rule on the major + * version covers `claude-sonnet-4-6`, `claude-opus-5`, `claude-haiku-4-5` and + * whatever ships next without this list growing per release. */ function anthropicSupportsVision(model: string): boolean { const m = model.toLowerCase(); - return ( + if ( m.startsWith("claude-3-opus") || m.startsWith("claude-3-sonnet") || m.startsWith("claude-3-haiku") || m.startsWith("claude-3-5") || m.startsWith("claude-3.5") || m.startsWith("claude-3-7") || - m.startsWith("claude-3.7") || - m.startsWith("claude-sonnet-4") || - m.startsWith("claude-opus-4") || - m.startsWith("claude-haiku-4") - ); + m.startsWith("claude-3.7") + ) { + return true; + } + if (m.startsWith("claude-fable-")) return true; + const tiered = m.match(/^claude-(?:sonnet|opus|haiku)-(\d+)/); + return tiered !== null && Number(tiered[1]) >= 4; } /**