Skip to content

feat(ocr): multi-provider /v1/ocr with transformation layer (Azure Document Intelligence) - #10283

Merged
diegosouzapw merged 10 commits into
release/v3.8.50from
feat/ocr-multi-provider
Aug 14, 2026
Merged

diegosouzapw merged 10 commits into
release/v3.8.50from
feat/ocr-multi-provider

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Summary

PR-A of the OCR/image-to-text migration series (plan: _tasks/superpowers/plans/2026-08-13-ocr-image-to-text-migration.md, mirrors research over _references/_sistemas_proxys — litellm's BaseOCRConfig pattern).

Generalizes the existing Mistral-only /v1/ocr into a multi-provider endpoint:

  • Transformation layer in open-sse/config/ocrRegistry.ts: OcrTransformation { buildRequest, parseResponse, pollUrl? } with MISTRAL_PASSTHROUGH as the default (Mistral response shape stays the canonical /v1/ocr contract).
  • Azure Document Intelligence (azure-document-intelligence/prebuilt-read): documentModels/prebuilt-read:analyze?api-version=2024-11-30&outputContentFormat=markdown, Ocp-Apim-Subscription-Key auth, async analyze+poll via Operation-Location (30 × 1s cap; non-ok poll → fail-fast 502; exhaustion → 504). Endpoint comes from the connection's providerSpecificData.baseUrl via the new pure resolveOcrCredentials() helper in the route.
  • HR#12 hardening (pre-existing violation fixed in passing): the handler's 500 no longer interpolates err.message; the sibling assert in tests/unit/ocr-route.test.ts ("returns a sanitized 500") was aligned to prove the internal detail no longer leaks — its title already described the new behavior.
  • Docs: API_REFERENCE.md /v1/ocr section (both providers + poll flow) and openapi.yaml description.
  • Backlog: Vertex AI DeepSeek-OCR → feat(ocr): Vertex AI DeepSeek-OCR provider #10282 (GCP SA auth is its own project).

Validation (TDD, DI-only — no network in tests)

  • 30/30 across ocr-registry-transformations (5), ocr-handler-dispatch (6, incl. poll-401 fail-fast with call-count proof and 30-attempt 504), ocr-route-contract (5, incl. resolveOcrCredentials malformed-input safety), ocr-route (14).
  • typecheck:core exit 0 · prettier/eslint clean on touched files · check:docs-all exit 0.
  • Mistral path stays byte-compatible (1 POST, body passthrough) — covered by dedicated test.

⚠️ base-red inherited: #9985 (ESLint errors from #10240/#9448 — unrelated to this diff)

Refs #10282

The test's own title ("returns a sanitized 500") describes the new
behavior mandated by HR#12 (never leak err.message in a response body).
The old regex asserted the pre-sanitization leak (`OCR request failed:
socket closed`) as expected output, which contradicted its own title
and the sanitization this task intentionally introduced in
open-sse/handlers/ocr.ts. Scoped to this single assertion only.
pollOcrOperation now checks pollRes.ok and returns a sanitized 502
immediately (logging the upstream status via console.error) instead of
looping until the 30-attempt cap and surfacing a misleading timeout for
what was actually an auth/upstream error during polling.
- Route: map the connection's providerSpecificData.baseUrl onto
  credentials.baseUrl (resolveOcrCredentials) so azure-document-intelligence
  connections resolve their endpoint the same way every other custom-endpoint
  provider does (src/lib/providers/validation/*); previously handleOcr only
  saw a baseUrl when a caller set it directly, so the DB-backed Azure
  connection endpoint was never forwarded.
- v1OcrSchema.model is already a free-form string, no schema change needed.
- Docs: add the /v1/ocr provider table + example + Azure poll-flow note to
  API_REFERENCE.md, and describe the provider/model prefix + async poll
  behavior in openapi.yaml.
- Test: tests/unit/ocr-route-contract.test.ts covers getAllOcrModels/
  parseOcrModel for both providers and resolveOcrCredentials's mapping.
@diegosouzapw
diegosouzapw merged commit c62ace5 into release/v3.8.50 Aug 14, 2026
22 checks passed
@diegosouzapw
diegosouzapw deleted the feat/ocr-multi-provider branch August 14, 2026 16:47
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
…cument Intelligence) (cheaper-inference#10283)

* feat(ocr): transformation layer on ocrRegistry (Mistral shape canonical)

* feat(ocr): Azure Document Intelligence provider (prebuilt-read, analyze+poll)

* feat(ocr): generic dispatch with per-provider transformation and DI poll loop

* test(ocr): align sanitized-500 assert with HR#12 error sanitization

The test's own title ("returns a sanitized 500") describes the new
behavior mandated by HR#12 (never leak err.message in a response body).
The old regex asserted the pre-sanitization leak (`OCR request failed:
socket closed`) as expected output, which contradicted its own title
and the sanitization this task intentionally introduced in
open-sse/handlers/ocr.ts. Scoped to this single assertion only.

* fix(ocr): fail fast on non-ok poll responses instead of misleading 504

pollOcrOperation now checks pollRes.ok and returns a sanitized 502
immediately (logging the upstream status via console.error) instead of
looping until the 30-attempt cap and surfacing a misleading timeout for
what was actually an auth/upstream error during polling.

* feat(ocr): route/docs for multi-provider /v1/ocr

- Route: map the connection's providerSpecificData.baseUrl onto
  credentials.baseUrl (resolveOcrCredentials) so azure-document-intelligence
  connections resolve their endpoint the same way every other custom-endpoint
  provider does (src/lib/providers/validation/*); previously handleOcr only
  saw a baseUrl when a caller set it directly, so the DB-backed Azure
  connection endpoint was never forwarded.
- v1OcrSchema.model is already a free-form string, no schema change needed.
- Docs: add the /v1/ocr provider table + example + Azure poll-flow note to
  API_REFERENCE.md, and describe the provider/model prefix + async poll
  behavior in openapi.yaml.
- Test: tests/unit/ocr-route-contract.test.ts covers getAllOcrModels/
  parseOcrModel for both providers and resolveOcrCredentials's mapping.

* chore(quality): rebaseline deadExports for the OCR/image-to-text series

* docs(skills): regenerate omni-inference skill for the multi-provider /v1/ocr

The generated agent skill mirrors docs/reference/API_REFERENCE.md; updating the
/v1/ocr section left it stale and tripped the merge-integrity gate.

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…cument Intelligence) (cheaper-inference#10283)

* feat(ocr): transformation layer on ocrRegistry (Mistral shape canonical)

* feat(ocr): Azure Document Intelligence provider (prebuilt-read, analyze+poll)

* feat(ocr): generic dispatch with per-provider transformation and DI poll loop

* test(ocr): align sanitized-500 assert with HR#12 error sanitization

The test's own title ("returns a sanitized 500") describes the new
behavior mandated by HR#12 (never leak err.message in a response body).
The old regex asserted the pre-sanitization leak (`OCR request failed:
socket closed`) as expected output, which contradicted its own title
and the sanitization this task intentionally introduced in
open-sse/handlers/ocr.ts. Scoped to this single assertion only.

* fix(ocr): fail fast on non-ok poll responses instead of misleading 504

pollOcrOperation now checks pollRes.ok and returns a sanitized 502
immediately (logging the upstream status via console.error) instead of
looping until the 30-attempt cap and surfacing a misleading timeout for
what was actually an auth/upstream error during polling.

* feat(ocr): route/docs for multi-provider /v1/ocr

- Route: map the connection's providerSpecificData.baseUrl onto
  credentials.baseUrl (resolveOcrCredentials) so azure-document-intelligence
  connections resolve their endpoint the same way every other custom-endpoint
  provider does (src/lib/providers/validation/*); previously handleOcr only
  saw a baseUrl when a caller set it directly, so the DB-backed Azure
  connection endpoint was never forwarded.
- v1OcrSchema.model is already a free-form string, no schema change needed.
- Docs: add the /v1/ocr provider table + example + Azure poll-flow note to
  API_REFERENCE.md, and describe the provider/model prefix + async poll
  behavior in openapi.yaml.
- Test: tests/unit/ocr-route-contract.test.ts covers getAllOcrModels/
  parseOcrModel for both providers and resolveOcrCredentials's mapping.

* chore(quality): rebaseline deadExports for the OCR/image-to-text series

* docs(skills): regenerate omni-inference skill for the multi-provider /v1/ocr

The generated agent skill mirrors docs/reference/API_REFERENCE.md; updating the
/v1/ocr section left it stale and tripped the merge-integrity gate.

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants