fix(bedrock): resolve context limits for every vendor prefix, not just anthropic (#12921)

Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings.

Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
This commit is contained in:
Nguyen Thanh Dat
2026-09-11 04:12:49 +07:00
committed by GitHub
parent e1a1290fde
commit 5df94f8b05
3 changed files with 71 additions and 7 deletions

View File

@@ -0,0 +1 @@
- **fix(bedrock):** model import now resolves context limits for every vendor prefix instead of only `anthropic.*`, so `global.openai.gpt-5.6-*` no longer imports with a null `inputTokenLimit` and gets rejected pre-flight at the 200k default ([#12921](https://github.com/diegosouzapw/OmniRoute/pull/12921)).

View File

@@ -90,13 +90,19 @@ export function getBedrockKnownModelLimits(modelId: string): {
if (!trimmed) return null;
const unqualified = trimmed.includes("/") ? trimmed.slice(trimmed.indexOf("/") + 1) : trimmed;
const withoutProfilePrefix = unqualified.replace(/^(?:eu|us|global)\./i, "");
const withoutProviderPrefix = withoutProfilePrefix.replace(/^anthropic\./i, "");
const spec =
getModelSpec(trimmed) ||
getModelSpec(unqualified) ||
getModelSpec(withoutProfilePrefix) ||
getModelSpec(withoutProviderPrefix);
// A Bedrock id is "<vendor>.<model>" optionally behind a cross-region profile
// prefix: "global.openai.gpt-5.6-sol", "us.anthropic.claude-...". The model
// name itself contains dots ("gpt-5.6-sol"), so peel at most those two leading
// qualifiers and keep the first candidate a spec knows. Peeling only
// "anthropic." left every other vendor (openai, meta, amazon, ...) without a
// context window, and the caller then fell back to a 200k default (#12915).
const segments = unqualified.split(".");
const spec = [trimmed, unqualified, segments.slice(1).join("."), segments.slice(2).join(".")]
.filter((candidate) => candidate.length > 0)
.reduce<ReturnType<typeof getModelSpec>>(
(found, candidate) => found || getModelSpec(candidate),
undefined
);
if (!spec?.contextWindow && !spec?.maxOutputTokens) return null;
return {

View File

@@ -0,0 +1,57 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { discoverBedrockNativeModels } from "../../open-sse/services/bedrock.ts";
// ─── #12915 — every Bedrock vendor prefix must resolve a context window ──────
// Bedrock ids are "<vendor>.<model>", optionally behind a cross-region profile
// prefix ("global.openai.gpt-5.6-sol"). The known-limits lookup used to peel
// only "anthropic.", so imported openai.* models carried no inputTokenLimit and
// the pre-flight context check fell back to a 200k default — rejecting 1M-context
// models locally, before the request ever reached AWS.
function bedrockFetcher(): (url: string, init: RequestInit) => Promise<Response> {
return async (url: string) => {
const body = url.includes("/inference-profiles")
? { inferenceProfileSummaries: [] }
: {
modelSummaries: [
{
modelId: "global.openai.gpt-5.6-sol",
modelName: "GPT-5.6 Sol",
providerName: "OpenAI",
responseStreamingSupported: true,
},
{
modelId: "global.anthropic.claude-opus-4-6-v1",
modelName: "Claude Opus 4.6",
providerName: "Anthropic",
responseStreamingSupported: true,
},
],
};
return new Response(JSON.stringify(body), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
}
describe("Bedrock model discovery (#12915)", () => {
it("carries a context window for openai.* models, not just anthropic.*", async () => {
const { models } = await discoverBedrockNativeModels({
apiKey: "test-key",
providerSpecificData: { region: "eu-west-1" },
fetcher: bedrockFetcher(),
});
const openai = models.find((m) => m.id === "global.openai.gpt-5.6-sol");
const anthropic = models.find((m) => m.id === "global.anthropic.claude-opus-4-6-v1");
// 1_050_000 and 1_000_000 differ, so a lookup that silently answered with the
// anthropic model's limit would not pass either assertion.
assert.equal(openai?.inputTokenLimit, 1_050_000);
assert.equal(openai?.outputTokenLimit, 128_000);
// The anthropic path must keep working unchanged.
assert.equal(anthropic?.inputTokenLimit, 1_000_000);
});
});