feat(labs): add local-OCR text mode for image-blind AI providers

Add an opt-in in-browser OCR path so a user whose provider cannot read
images (ChatGPT-OAuth/Codex, a text-only model) can still scan a lab
report. The capability probe gains a `mode` field: `vision` when the
provider reads the image directly, `text` when local OCR is enabled and
any provider is configured, or null. The extract route grows a text
branch that accepts the in-browser-OCR'd text as JSON and structures it
through the existing schema + review/commit flow; the raw image never
reaches the server in text mode. New `labsLocalOcrEnabled` user column
(migration 0184, default off) gates it, with a dedicated PATCH endpoint.
This commit is contained in:
Marc-André Bombeck committed 2026-06-20 16:50:06 +02:00
1 parent fa37941add
commit 3d039d5220
13 files changed
+634 -77

No files matched your search

@@ -0,0 +1,16 @@
-- v1.18.10 — opt-in local (in-browser) OCR for lab-report scans.
--
-- One additive, defaulted column on `users`. When `true`, a user whose AI
-- provider cannot read images (ChatGPT-OAuth/Codex, a text-only model) can
-- still scan a paper report: the image is OCR'd in the browser via tesseract.js
-- and only the extracted TEXT is forwarded to the text-only provider for
-- structuring. The raw image never leaves the device in this mode.
--
-- Less accurate than a native vision model — the mandatory per-row review
-- screen stays the safety backstop, and the in-app copy sets that expectation.
-- The default `false` backfills every existing row onto the current behaviour
-- (vision-only scan, or no scan affordance), so this is a no-op for anyone who
-- never opts in.
ALTER TABLE "users"
ADD COLUMN "labs_local_ocr_enabled" BOOLEAN NOT NULL DEFAULT false;
+8
View File
@@ -207,6 +207,14 @@ model User {
// diagnosis — purely a user-declared preference that selects which target
// band the user is judged against. Default `false`.
hasDiabetes Boolean @default(false) @map("has_diabetes")
// v1.18.10 — opt-in local (in-browser) OCR for lab-report scans. When `true`,
// a user whose AI provider cannot read images (e.g. ChatGPT-OAuth/Codex, a
// text-only model) can still scan a report: the image is OCR'd in the browser
// via tesseract.js and only the extracted TEXT is sent to the text-only
// provider for structuring. Less accurate than native vision — the mandatory
// review screen remains the safety backstop. Default `false`; vision-capable
// users keep the higher-accuracy native path and never pay the WASM download.
labsLocalOcrEnabled Boolean @default(false) @map("labs_local_ocr_enabled")
// v1.7.0 unit pref — global metric/imperial display preference.
// Canonical storage stays SI; this only selects the display-time
// transform branch (km/h vs mph, km vs mi). Null = default "metric".