Skip to content

feat(ocr): Vertex AI DeepSeek-OCR provider - #10395

Closed
diegosouzapw wants to merge 7 commits into
feat/ocr-multi-providerfrom
feat/ocr-vertex-deepseek
Closed

diegosouzapw wants to merge 7 commits into
feat/ocr-multi-providerfrom
feat/ocr-vertex-deepseek

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Summary

Closes the backlog issue #10282 opened alongside PR-A: Vertex AI DeepSeek-OCR as the third /v1/ocr provider, using the transformation layer introduced in #10283 (pattern migrated from litellm's llms/vertex_ai/ocr/deepseek_transformation.py).

⚠️ STACKED on #10283 (feat/ocr-multi-provider) — it needs the OcrTransformation interface and the generic handler dispatch. After #10283 merges, retarget to release/v3.8.50 (gh pr edit --base release/v3.8.50, then verify with --json baseRefName).

  • VERTEX_DEEPSEEK_TRANSFORMATION + the vertex-deepseek-ocr registry entry, mapping the upstream response onto the canonical Mistral OCRResponse shape like the other providers.
  • Auth/endpoint resolution for Vertex (project + location + OAuth access token) reuses the repo's existing Vertex credential path rather than introducing a new OAuth flow — this was the blocker recorded in feat(ocr): Vertex AI DeepSeek-OCR provider #10282.
  • The helpers live in open-sse/handlers/ocr.ts, not in the route: src/app/** may not import open-sse/executors/* directly (EXECUTOR_IMPORT_RESTRICTION eslint boundary).

Validation

  • tests/unit/ocr-*.test.ts — 46/46, including 16 new cases (6 transformation + 10 route/auth-resolution).
  • typecheck:core exit 0 · eslint/prettier clean on touched files.

Not validated live: no GCP test project was available, so the real deepseek-ai/deepseek-ocr-maas response was never exercised end-to-end. Per Hard Rule #18 this shipped through the TDD path (new integration, not a bug repro), but a live smoke test is worth doing before anyone relies on it in production.

Closes #10282

backryun and others added 7 commits August 14, 2026 10:06
Adds VERTEX_DEEPSEEK_TRANSFORMATION (request/response mapping for the
Vertex AI DeepSeek OCR MaaS endpoint) and registers the
"vertex-deepseek-ocr" provider in OCR_PROVIDERS, modeled on litellm's
VertexAIDeepSeekOCRConfig. buildRequest treats the resolved baseUrl as
the complete Vertex endpoint URL (project/location resolved upstream),
matching the existing Mistral passthrough pattern.
Adds resolveVertexOcrAccessToken (mints a Vertex OAuth access token from
a Service Account JSON apiKey, reusing open-sse/executors/vertex.ts's
existing JWT-bearer exchange — no new OAuth flow) and
resolveVertexOcrBaseUrl (derives the project/location "openapi/chat/
completions" endpoint from providerSpecificData or the Service Account
JSON's project_id). Both live in open-sse/handlers/ocr.ts, not the
src/app/api/v1/ocr route, since routes may not import executor
implementations directly (EXECUTOR_IMPORT_RESTRICTION in
eslint.config.mjs) — the route re-exports/consumes them across that
boundary. handleOcr now prefers credentials.accessToken over apiKey so
the minted token (not the raw Service Account JSON) is sent upstream.
Adds the vertex-deepseek-ocr row to the /v1/ocr provider table and a
short section on its Vertex AI auth/endpoint resolution, and lists the
new provider/model id in openapi.yaml alongside mistral and
azure-document-intelligence.
Adds `i-have-adhd` as the 5th entry in OUTPUT_STYLE_CATALOG — a port of the
github.com/ayghri/i-have-adhd skill (MIT), following the same integration shape as
ponytail. Action-first output shaping: the next action leads, multi-step work is
numbered, no preamble/recap/closers — which also trims output tokens.

lite/full/ultra levels in en + pt-BR, each ending in SHARED_BOUNDARIES so code, paths,
commands, errors and URLs stay verbatim. The agent-harness-specific upstream rules
(restate plan state, time estimates) are reworded as conditionals so they hold for plain
chat clients too.

Per the D-A1 registry contract, one catalog entry is the whole change: the injector, the
settings panel, the Zod schema and the telemetry all enumerate the catalog, so no other
production file moves. Dedicated test mirrors ponytail-catalog.test.ts (7 tests).
…ovider-scoped error rules (#10335)

agentrouter.org signals temporary quota exhaustion with HTTP 403/400 and a Chinese body (用户额度不足) instead of 429, so clients like Claude Code treat it as permanent and abort, and the fallback engine classified it as a generic apikey AUTH_ERROR.

New registry open-sse/config/upstreamStatusRestatement.ts restates those statuses to 429 with a synthetic Retry-After at a single hook in chatCore's providerFailure block (after parseUpstreamError), so classification, combo aggregation and the client response all see a retryable error. 无权访问模型 (permanently no model access) is veto-listed and never restated.

agentrouter classification rules are registered in providerErrorRules.ts and reach the real checkFallbackError path through resolveRuleMatchBody() with an exclusive FULL_TEXT_RULE_PROVIDERS allowlist — every other provider keeps its previous behavior byte-for-byte.

Known limitations tracked in #10334: the rules' scope field is informational (persistence applies per-model lockout for agentrouter), the 403-only model-access rule has no production path yet, and errors embedded in 200 SSE streams are not restated.

Refs #10334
@diegosouzapw
diegosouzapw deleted the branch feat/ocr-multi-provider August 14, 2026 16:47
@diegosouzapw

Copy link
Copy Markdown
Collaborator Author

Superseded by #10398 — same three commits, cherry-picked onto the merged #10283 and targeting release/v3.8.50. This one was auto-closed by GitHub when #10283 merged with --delete-branch, which removed the base branch it was stacked on.

@diegosouzapw
diegosouzapw deleted the feat/ocr-vertex-deepseek branch August 14, 2026 18:19
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