From d4b8cdb3184fee4ee6e9c7dc87587fbf815defcb Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Fri, 5 Jun 2026 13:01:33 -0500 Subject: [PATCH] fix(opencode): honor Bedrock Mantle config --- packages/opencode/src/provider/provider.ts | 15 +++++++++++-- .../test/provider/amazon-bedrock.test.ts | 22 ++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 2142f843404c..85a582e47d5c 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -295,6 +295,7 @@ function custom(dep: CustomDep): Record { const profile = configProfile ?? envProfile const awsAccessKeyId = env["AWS_ACCESS_KEY_ID"] + const configApiKey = providerConfig?.options?.apiKey // TODO: Using process.env directly because Env.set only updates a process.env shallow copy, // until the scope of the Env API is clarified (test only or runtime?) @@ -314,7 +315,14 @@ function custom(dep: CustomDep): Record { process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI || process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI, ) - if (!profile && !awsAccessKeyId && !awsBearerToken && !awsWebIdentityTokenFile && !containerCreds) + if ( + !profile && + !awsAccessKeyId && + !awsBearerToken && + !configApiKey && + !awsWebIdentityTokenFile && + !containerCreds + ) return { autoload: false } const { fromNodeProviderChain } = yield* Effect.promise(() => import("@aws-sdk/credential-providers")) @@ -325,7 +333,7 @@ function custom(dep: CustomDep): Record { // Only use credential chain if no bearer token exists // Bearer token takes precedence over credential chain (profiles, access keys, IAM roles, web identity tokens) - if (!awsBearerToken) { + if (!awsBearerToken && !configApiKey) { // Build credential provider options (only pass profile if specified) const credentialProviderOptions = profile ? { profile } : {} @@ -341,6 +349,9 @@ function custom(dep: CustomDep): Record { return { autoload: true, options: providerOptions, + vars(options: Record) { + return { AWS_REGION: options.region ?? defaultRegion } + }, async getModel(sdk: any, modelID: string, options?: Record, model?: Model) { if (model?.api.npm === "@ai-sdk/amazon-bedrock/mantle") return selectBedrockMantleLanguageModel(sdk, modelID) diff --git a/packages/opencode/test/provider/amazon-bedrock.test.ts b/packages/opencode/test/provider/amazon-bedrock.test.ts index 7cbdb1e1ccb9..d1cc510cd1ad 100644 --- a/packages/opencode/test/provider/amazon-bedrock.test.ts +++ b/packages/opencode/test/provider/amazon-bedrock.test.ts @@ -43,11 +43,6 @@ const mantleModelConfig = { }, } -const mantleOpenAIModelConfig = { - ...mantleModelConfig, - provider: { npm: "@ai-sdk/amazon-bedrock/mantle", api: "https://bedrock-mantle.us-east-2.api.aws/openai/v1" }, -} - const withAuthJson = (contents: string) => Effect.acquireRelease( Effect.promise(async () => { @@ -113,7 +108,10 @@ it.instance( "Bedrock Mantle: GPT-5.5 uses Responses API and OpenAI base path", () => Effect.gen(function* () { - yield* set("AWS_BEARER_TOKEN_BEDROCK", "test-bearer-token") + yield* set("AWS_REGION", "") + yield* set("AWS_PROFILE", "") + yield* set("AWS_ACCESS_KEY_ID", "") + yield* set("AWS_BEARER_TOKEN_BEDROCK", "") const model = yield* Provider.use.getModel(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")) const language = yield* Provider.use.getLanguage(model) expect((language as { provider: string }).provider).toBe("bedrock-mantle.responses") @@ -129,8 +127,16 @@ it.instance( config: { provider: { "amazon-bedrock": { - options: { region: "us-east-2" }, - models: { "openai.gpt-5.5": mantleOpenAIModelConfig }, + options: { region: "us-east-2", apiKey: "test-bearer-token" }, + models: { + "openai.gpt-5.5": { + ...mantleModelConfig, + provider: { + npm: "@ai-sdk/amazon-bedrock/mantle", + api: "https://bedrock-mantle.${AWS_REGION}.api.aws/openai/v1", + }, + }, + }, }, }, },