diff --git a/.changeset/orange-eels-unite.md b/.changeset/orange-eels-unite.md new file mode 100644 index 0000000000..e0eab5d394 --- /dev/null +++ b/.changeset/orange-eels-unite.md @@ -0,0 +1,5 @@ +--- +"claude-dev": patch +--- + +Fix AWS Bedrock Profiles. When configuring the AnthropicBedrock Client you must pass AWS credentials in a specific way, otherwise the client will default to reading credentials from the default AWS profile. diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts index 448190291d..04de4af2b2 100644 --- a/src/api/providers/bedrock.ts +++ b/src/api/providers/bedrock.ts @@ -8,35 +8,50 @@ import { fromIni } from "@aws-sdk/credential-providers" // https://docs.anthropic.com/en/api/claude-on-amazon-bedrock export class AwsBedrockHandler implements ApiHandler { private options: ApiHandlerOptions - private client: AnthropicBedrock + private client: AnthropicBedrock | any + private initializationPromise: Promise constructor(options: ApiHandlerOptions) { this.options = options + this.initializationPromise = this.initializeClient() + } - const clientConfig: any = { + private async initializeClient() { + let clientConfig: any = { awsRegion: this.options.awsRegion || "us-east-1", } - - if (this.options.awsUseProfile) { - // Use profile-based credentials if enabled - if (this.options.awsProfile) { - clientConfig.credentials = fromIni({ - profile: this.options.awsProfile, - }) - } else { - // Use default profile if no specific profile is set - clientConfig.credentials = fromIni() - } - } else if (this.options.awsAccessKey && this.options.awsSecretKey) { - // Use direct credentials if provided - clientConfig.awsAccessKey = this.options.awsAccessKey - clientConfig.awsSecretKey = this.options.awsSecretKey - if (this.options.awsSessionToken) { - clientConfig.awsSessionToken = this.options.awsSessionToken + try { + if (this.options.awsUseProfile) { + // Use profile-based credentials if enabled + // Use named profile, defaulting to 'default' if not specified + var credentials: any + if (this.options.awsProfile) { + credentials = await fromIni({ + profile: this.options.awsProfile, + ignoreCache: true, + })() + } else { + credentials = await fromIni({ + ignoreCache: true, + })() + } + clientConfig.awsAccessKey = credentials.accessKeyId + clientConfig.awsSecretKey = credentials.secretAccessKey + clientConfig.awsSessionToken = credentials.sessionToken + } else if (this.options.awsAccessKey && this.options.awsSecretKey) { + // Use direct credentials if provided + clientConfig.awsAccessKey = this.options.awsAccessKey + clientConfig.awsSecretKey = this.options.awsSecretKey + if (this.options.awsSessionToken) { + clientConfig.awsSessionToken = this.options.awsSessionToken + } } + } catch (error) { + console.error("Failed to initialize Bedrock client:", error) + throw error + } finally { + this.client = new AnthropicBedrock(clientConfig) } - - this.client = new AnthropicBedrock(clientConfig) } async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {