fix: prevent double-prefixing of Bedrock cross-region inference models (#12056)
This commit is contained in:
@@ -239,7 +239,9 @@ export namespace Provider {
|
||||
options: providerOptions,
|
||||
async getModel(sdk: any, modelID: string, options?: Record<string, any>) {
|
||||
// Skip region prefixing if model already has a cross-region inference profile prefix
|
||||
if (modelID.startsWith("global.") || modelID.startsWith("jp.")) {
|
||||
// Models from models.dev may already include prefixes like us., eu., global., etc.
|
||||
const crossRegionPrefixes = ["global.", "us.", "eu.", "jp.", "apac.", "au."]
|
||||
if (crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))) {
|
||||
return sdk.languageModel(modelID)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { test, expect, mock } from "bun:test"
|
||||
import { test, expect, mock, describe } from "bun:test"
|
||||
import path from "path"
|
||||
import { unlink } from "fs/promises"
|
||||
|
||||
@@ -266,3 +266,214 @@ test("Bedrock: autoloads when AWS_WEB_IDENTITY_TOKEN_FILE is present", async ()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
// Tests for cross-region inference profile prefix handling
|
||||
// Models from models.dev may come with prefixes already (e.g., us., eu., global.)
|
||||
// These should NOT be double-prefixed when passed to the SDK
|
||||
|
||||
test("Bedrock: model with us. prefix should not be double-prefixed", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
await Bun.write(
|
||||
path.join(dir, "opencode.json"),
|
||||
JSON.stringify({
|
||||
$schema: "https://opencode.ai/config.json",
|
||||
provider: {
|
||||
"amazon-bedrock": {
|
||||
options: {
|
||||
region: "us-east-1",
|
||||
},
|
||||
models: {
|
||||
"us.anthropic.claude-opus-4-5-20251101-v1:0": {
|
||||
name: "Claude Opus 4.5 (US)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
init: async () => {
|
||||
Env.set("AWS_PROFILE", "default")
|
||||
},
|
||||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["amazon-bedrock"]).toBeDefined()
|
||||
// The model should exist with the us. prefix
|
||||
expect(providers["amazon-bedrock"].models["us.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("Bedrock: model with global. prefix should not be prefixed", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
await Bun.write(
|
||||
path.join(dir, "opencode.json"),
|
||||
JSON.stringify({
|
||||
$schema: "https://opencode.ai/config.json",
|
||||
provider: {
|
||||
"amazon-bedrock": {
|
||||
options: {
|
||||
region: "us-east-1",
|
||||
},
|
||||
models: {
|
||||
"global.anthropic.claude-opus-4-5-20251101-v1:0": {
|
||||
name: "Claude Opus 4.5 (Global)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
init: async () => {
|
||||
Env.set("AWS_PROFILE", "default")
|
||||
},
|
||||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["amazon-bedrock"]).toBeDefined()
|
||||
expect(providers["amazon-bedrock"].models["global.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("Bedrock: model with eu. prefix should not be double-prefixed", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
await Bun.write(
|
||||
path.join(dir, "opencode.json"),
|
||||
JSON.stringify({
|
||||
$schema: "https://opencode.ai/config.json",
|
||||
provider: {
|
||||
"amazon-bedrock": {
|
||||
options: {
|
||||
region: "eu-west-1",
|
||||
},
|
||||
models: {
|
||||
"eu.anthropic.claude-opus-4-5-20251101-v1:0": {
|
||||
name: "Claude Opus 4.5 (EU)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
init: async () => {
|
||||
Env.set("AWS_PROFILE", "default")
|
||||
},
|
||||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["amazon-bedrock"]).toBeDefined()
|
||||
expect(providers["amazon-bedrock"].models["eu.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("Bedrock: model without prefix in US region should get us. prefix added", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
await Bun.write(
|
||||
path.join(dir, "opencode.json"),
|
||||
JSON.stringify({
|
||||
$schema: "https://opencode.ai/config.json",
|
||||
provider: {
|
||||
"amazon-bedrock": {
|
||||
options: {
|
||||
region: "us-east-1",
|
||||
},
|
||||
models: {
|
||||
"anthropic.claude-opus-4-5-20251101-v1:0": {
|
||||
name: "Claude Opus 4.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
init: async () => {
|
||||
Env.set("AWS_PROFILE", "default")
|
||||
},
|
||||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["amazon-bedrock"]).toBeDefined()
|
||||
// Non-prefixed model should still be registered
|
||||
expect(providers["amazon-bedrock"].models["anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
// Direct unit tests for cross-region inference profile prefix handling
|
||||
// These test the prefix detection logic used in getModel
|
||||
|
||||
describe("Bedrock cross-region prefix detection", () => {
|
||||
const crossRegionPrefixes = ["global.", "us.", "eu.", "jp.", "apac.", "au."]
|
||||
|
||||
test("should detect global. prefix", () => {
|
||||
const modelID = "global.anthropic.claude-opus-4-5-20251101-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should detect us. prefix", () => {
|
||||
const modelID = "us.anthropic.claude-opus-4-5-20251101-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should detect eu. prefix", () => {
|
||||
const modelID = "eu.anthropic.claude-opus-4-5-20251101-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should detect jp. prefix", () => {
|
||||
const modelID = "jp.anthropic.claude-sonnet-4-20250514-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should detect apac. prefix", () => {
|
||||
const modelID = "apac.anthropic.claude-sonnet-4-20250514-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should detect au. prefix", () => {
|
||||
const modelID = "au.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(true)
|
||||
})
|
||||
|
||||
test("should NOT detect prefix for non-prefixed model", () => {
|
||||
const modelID = "anthropic.claude-opus-4-5-20251101-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(false)
|
||||
})
|
||||
|
||||
test("should NOT detect prefix for amazon nova models", () => {
|
||||
const modelID = "amazon.nova-pro-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(false)
|
||||
})
|
||||
|
||||
test("should NOT detect prefix for cohere models", () => {
|
||||
const modelID = "cohere.command-r-plus-v1:0"
|
||||
const hasPrefix = crossRegionPrefixes.some((prefix) => modelID.startsWith(prefix))
|
||||
expect(hasPrefix).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user