diff --git a/packages/core/src/plugin/provider/amazon-bedrock.ts b/packages/core/src/plugin/provider/amazon-bedrock.ts index d15ffd4b499..b1b7ecbfddc 100644 --- a/packages/core/src/plugin/provider/amazon-bedrock.ts +++ b/packages/core/src/plugin/provider/amazon-bedrock.ts @@ -18,6 +18,32 @@ const isBedrock = (item: { readonly package: string }) => { return name.startsWith("@ai-sdk/amazon-bedrock") || name.startsWith("@opencode/ai/providers/amazon-bedrock") } +// Bare Bedrock model IDs that AWS rejects unless sent as an inference-profile +// ID (`us.`/`eu.`/`global.`/...). Verified via on-demand foundation-model +// listings across six regions plus live Converse probes, all returning "with +// on-demand throughput isn't supported. Retry ... with an inference profile". +// V1 rewrites these to profiles at request time so they must stay in +// models.dev; V2 sends IDs verbatim, so listing them only produces errors. +// Interim until per-entry source-region metadata lands; region-aware +// filtering will subsume this list then. +export const PROFILE_ONLY_BARE_IDS = [ + "amazon.nova-2-lite-v1:0", + "anthropic.claude-fable-5", + "anthropic.claude-fable-5-1", + "anthropic.claude-haiku-4-5-20251001-v1:0", + "anthropic.claude-opus-4-1-20250805-v1:0", + "anthropic.claude-opus-4-5-20251101-v1:0", + "anthropic.claude-opus-4-6-v1", + "anthropic.claude-opus-4-7", + "anthropic.claude-opus-4-8", + "anthropic.claude-opus-5", + "anthropic.claude-sonnet-4-5-20250929-v1:0", + "anthropic.claude-sonnet-4-6", + "anthropic.claude-sonnet-5", + "deepseek.r1-v1:0", + "mistral.pixtral-large-2502-v1:0", +] + export const AmazonBedrockPlugin = define({ id: "opencode.provider.amazon.bedrock", effect: Effect.fn(function* (ctx) { @@ -53,6 +79,12 @@ export const AmazonBedrockPlugin = define({ } delete provider.settings.endpoint }) + for (const modelID of PROFILE_ONLY_BARE_IDS) { + if (!evt.model.get(item.provider.id, modelID)) continue + evt.model.update(item.provider.id, modelID, (model) => { + model.enabled = false + }) + } } }) }), diff --git a/packages/core/test/plugin/provider-amazon-bedrock.test.ts b/packages/core/test/plugin/provider-amazon-bedrock.test.ts index 44e6a57c4bb..41f4ef57fc4 100644 --- a/packages/core/test/plugin/provider-amazon-bedrock.test.ts +++ b/packages/core/test/plugin/provider-amazon-bedrock.test.ts @@ -4,7 +4,8 @@ import { Catalog } from "@opencode/core/catalog" import { Integration } from "@opencode/core/integration" import { Plugin } from "@opencode/core/plugin" import { PluginHost } from "@opencode/core/plugin/host" -import { AmazonBedrockPlugin } from "@opencode/core/plugin/provider/amazon-bedrock" +import { AmazonBedrockPlugin, PROFILE_ONLY_BARE_IDS } from "@opencode/core/plugin/provider/amazon-bedrock" +import { Model } from "@opencode/core/model" import { Provider } from "@opencode/core/provider" import { testEffect } from "../lib/effect" import { PluginTestLayer } from "./fixture" @@ -222,4 +223,45 @@ describe("AmazonBedrockPlugin", () => { }), ), ) + + it.effect("disables profile-only bare IDs while keeping working IDs", () => + withEnv(noAmbientAWS, () => + Effect.gen(function* () { + const catalog = yield* seedBedrock() + const controls = [ + "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "amazon.nova-micro-v1:0", + "openai.gpt-6-astra", + ] + yield* catalog.transform((catalog) => { + for (const id of [...PROFILE_ONLY_BARE_IDS, ...controls]) { + catalog.model.update(Provider.ID.amazonBedrock, Model.ID.make(id), () => {}) + } + }) + yield* addPlugin() + for (const id of PROFILE_ONLY_BARE_IDS) { + expect(required(yield* catalog.model.get(Provider.ID.amazonBedrock, Model.ID.make(id))).enabled).toBe( + false, + ) + } + for (const id of controls) { + expect(required(yield* catalog.model.get(Provider.ID.amazonBedrock, Model.ID.make(id))).enabled).toBe( + true, + ) + } + }), + ), + ) + + it.effect("does not create catalog entries for absent profile-only IDs", () => + withEnv(noAmbientAWS, () => + Effect.gen(function* () { + const catalog = yield* seedBedrock() + yield* addPlugin() + for (const id of PROFILE_ONLY_BARE_IDS) { + expect(yield* catalog.model.get(Provider.ID.amazonBedrock, Model.ID.make(id))).toBeUndefined() + } + }), + ), + ) })