From f1fcdbfa6edc4abc5efc64af6e70ca428f75e8de Mon Sep 17 00:00:00 2001 From: Will Gordon Date: Tue, 28 Jul 2026 10:49:52 -0400 Subject: [PATCH] fix(executors): route current Claude generations through Vertex partner endpoint (#8852) * fix(executors): route current Claude generations through Vertex partner endpoint PARTNER_MODELS pinned three Claude 3.x prefixes (claude-3-5-sonnet, claude-3-opus, claude-3-haiku). Every newer Claude generation on Vertex (claude-sonnet-4-6, claude-haiku-4-5, etc.) fell through to the Google-publisher branch instead, producing an invalid publishers/google/models/claude-... path. Replace the pinned prefixes with a single generic "claude-" prefix: any Claude model on Vertex is always an Anthropic partner model, never a Google one, so this can't go stale again the way pinned version strings did. Fixes #1985 * docs: add changelog fragment for #8852 --- .../8852-vertex-claude-partner-models.md | 1 + open-sse/executors/vertex.ts | 7 +++--- tests/unit/executor-vertex-extended.test.ts | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 changelog.d/fixes/8852-vertex-claude-partner-models.md diff --git a/changelog.d/fixes/8852-vertex-claude-partner-models.md b/changelog.d/fixes/8852-vertex-claude-partner-models.md new file mode 100644 index 0000000000..b5b616fd47 --- /dev/null +++ b/changelog.d/fixes/8852-vertex-claude-partner-models.md @@ -0,0 +1 @@ +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 diff --git a/open-sse/executors/vertex.ts b/open-sse/executors/vertex.ts index 4ca1a1ab05..0344a456d6 100644 --- a/open-sse/executors/vertex.ts +++ b/open-sse/executors/vertex.ts @@ -116,9 +116,10 @@ export async function getAccessToken(sa: ServiceAccount): Promise { } const PARTNER_MODELS = new Set([ - "claude-3-5-sonnet", - "claude-3-opus", - "claude-3-haiku", + // Generic prefix, not pinned to a version: every Claude model on Vertex is an Anthropic + // partner model, never a Google-publisher one. Pinned prefixes (e.g. "claude-3-5-sonnet") + // silently break every time Anthropic ships a new generation — see issue #1985. + "claude-", "deepseek-v3", "deepseek-v3.2", "deepseek-v4", diff --git a/tests/unit/executor-vertex-extended.test.ts b/tests/unit/executor-vertex-extended.test.ts index f7ac599518..b8cbbe5900 100644 --- a/tests/unit/executor-vertex-extended.test.ts +++ b/tests/unit/executor-vertex-extended.test.ts @@ -90,6 +90,28 @@ test("VertexExecutor.buildUrl routes partner and org-prefixed models to the glob ); }); +test("VertexExecutor.buildUrl routes current-generation Claude models to the global partner endpoint (#1985)", () => { + const executor = new VertexExecutor(); + + // These model IDs post-date the old pinned "claude-3-5-sonnet" / "claude-3-opus" / + // "claude-3-haiku" prefixes and were previously misrouted to the Google-publisher path. + const claude4Sonnet = executor.buildUrl("claude-sonnet-4-6", false, 0, { + apiKey: createServiceAccountJson({ projectId: "proj-claude" }), + }); + const claude4Haiku = executor.buildUrl("claude-haiku-4-5@20251001", true, 0, { + apiKey: createServiceAccountJson({ projectId: "proj-claude" }), + }); + + assert.equal( + claude4Sonnet, + "https://aiplatform.googleapis.com/v1/projects/proj-claude/locations/global/endpoints/openapi/chat/completions" + ); + assert.equal( + claude4Haiku, + "https://aiplatform.googleapis.com/v1/projects/proj-claude/locations/global/endpoints/openapi/chat/completions" + ); +}); + test("VertexExecutor.buildHeaders includes Bearer token and SSE Accept only for streaming", () => { const executor = new VertexExecutor(); const streamHeaders = executor.buildHeaders({ accessToken: "ya29.stream" }, true);