Skip to content

Commit be18455

Browse files
committed
fix: address Bedrock PR feedback
1 parent d40b8c8 commit be18455

2 files changed

Lines changed: 75 additions & 18 deletions

File tree

src/api/providers/__tests__/bedrock.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import type { Anthropic } from "@anthropic-ai/sdk"
4747

4848
// Get access to the mocked functions
4949
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand)
50+
const mockConverseCommand = vi.mocked(ConverseCommand)
5051
const mockBedrockRuntimeClient = vi.mocked(BedrockRuntimeClient)
5152

5253
describe("AwsBedrockHandler", () => {
@@ -894,6 +895,35 @@ describe("AwsBedrockHandler", () => {
894895
expect(commandArg.inferenceConfig.temperature).toBeUndefined()
895896
})
896897

898+
it("should map xhigh reasoning effort to max for Claude Opus 4.7 adaptive thinking", async () => {
899+
const handler = new AwsBedrockHandler({
900+
apiModelId: "anthropic.claude-opus-4-7",
901+
awsAccessKey: "test",
902+
awsSecretKey: "test",
903+
awsRegion: "us-east-1",
904+
enableReasoningEffort: true,
905+
reasoningEffort: "xhigh",
906+
})
907+
908+
const messages: Anthropic.Messages.MessageParam[] = [
909+
{
910+
role: "user",
911+
content: "Test message",
912+
},
913+
]
914+
915+
const generator = handler.createMessage("", messages)
916+
await generator.next()
917+
918+
expect(mockConverseStreamCommand).toHaveBeenCalled()
919+
const commandArg = mockConverseStreamCommand.mock.calls[0][0] as any
920+
921+
expect(commandArg.additionalModelRequestFields.thinking).toEqual({
922+
type: "adaptive",
923+
effort: "max",
924+
})
925+
})
926+
897927
it("should use global inference for Claude Opus 4.7 when enabled", () => {
898928
const handler = new AwsBedrockHandler({
899929
apiModelId: "anthropic.claude-opus-4-7",
@@ -1392,4 +1422,22 @@ describe("AwsBedrockHandler", () => {
13921422
expect(hasCachePoint).toBe(false)
13931423
})
13941424
})
1425+
1426+
describe("completePrompt", () => {
1427+
it("should omit temperature for Claude Opus 4.7", async () => {
1428+
const handler = new AwsBedrockHandler({
1429+
apiModelId: "anthropic.claude-opus-4-7",
1430+
awsAccessKey: "test",
1431+
awsSecretKey: "test",
1432+
awsRegion: "us-east-1",
1433+
modelTemperature: 0.4,
1434+
})
1435+
1436+
await handler.completePrompt("Test prompt")
1437+
1438+
expect(mockConverseCommand).toHaveBeenCalled()
1439+
const commandArg = mockConverseCommand.mock.calls[0][0] as any
1440+
expect(commandArg.inferenceConfig.temperature).toBeUndefined()
1441+
})
1442+
})
13951443
})

src/api/providers/bedrock.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,30 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
291291
this.client = new BedrockRuntimeClient(clientConfig)
292292
}
293293

294+
private getAdaptiveThinkingEffort(): "low" | "medium" | "high" | "max" | undefined {
295+
switch (this.options.reasoningEffort) {
296+
case "low":
297+
case "medium":
298+
case "high":
299+
return this.options.reasoningEffort
300+
case "xhigh":
301+
return "max"
302+
default:
303+
return undefined
304+
}
305+
}
306+
307+
private getInferenceConfig(modelConfig: {
308+
info: ModelInfo
309+
maxTokens?: number
310+
temperature?: number
311+
}): BedrockInferenceConfig {
312+
return {
313+
maxTokens: modelConfig.maxTokens || (modelConfig.info.maxTokens as number),
314+
temperature: modelConfig.temperature,
315+
}
316+
}
317+
294318
// Helper to guess model info from custom modelId string if not in bedrockModels
295319
private guessModelInfoFromId(modelId: string): Partial<ModelInfo> {
296320
// Define a mapping for model ID patterns and their configurations
@@ -399,16 +423,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
399423

400424
if ((isThinkingExplicitlyEnabled || isThinkingEnabledBySettings) && modelConfig.info.supportsReasoningBudget) {
401425
thinkingEnabled = true
402-
const adaptiveThinkingEffort = (() => {
403-
switch (this.options.reasoningEffort) {
404-
case "low":
405-
case "medium":
406-
case "high":
407-
return this.options.reasoningEffort
408-
default:
409-
return undefined
410-
}
411-
})()
426+
const adaptiveThinkingEffort = this.getAdaptiveThinkingEffort()
412427
additionalModelRequestFields = usesAdaptiveThinking
413428
? {
414429
thinking: {
@@ -429,10 +444,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
429444
})
430445
}
431446

432-
const inferenceConfig: BedrockInferenceConfig = {
433-
maxTokens: modelConfig.maxTokens || (modelConfig.info.maxTokens as number),
434-
temperature: modelConfig.temperature,
435-
}
447+
const inferenceConfig = this.getInferenceConfig(modelConfig)
436448

437449
// Check if 1M context is enabled for supported Claude 4 models
438450
const is1MContextEnabled =
@@ -767,10 +779,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
767779
modelConfig.reasoning &&
768780
modelConfig.reasoningBudget
769781

770-
const inferenceConfig: BedrockInferenceConfig = {
771-
maxTokens: modelConfig.maxTokens || (modelConfig.info.maxTokens as number),
772-
temperature: modelConfig.temperature ?? (this.options.modelTemperature as number),
773-
}
782+
const inferenceConfig = this.getInferenceConfig(modelConfig)
774783

775784
// For completePrompt, use a unique conversation ID based on the prompt
776785
const conversationId = `prompt_${prompt.substring(0, 20)}`

0 commit comments

Comments
 (0)