Skip to content

Commit ddc7f52

Browse files
committed
provider: Bedrock non-Anthropic message cleanup and xhigh→max
normalizeMessages strips cachePoint and reasoning for amazon-bedrock models without anthropic/mistral ids; placeholder if assistant empty. Map adaptive xhigh reasoning effort to max for Bedrock; test expects max + display summarized for opus 4.7.
1 parent 451650b commit ddc7f52

2 files changed

Lines changed: 46 additions & 3 deletions

File tree

packages/opencode/src/provider/transform.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,49 @@ function normalizeMessages(
214214
})
215215
}
216216

217+
if (
218+
model.api.npm === "@ai-sdk/amazon-bedrock" &&
219+
!model.api.id.includes("anthropic") &&
220+
!model.api.id.includes("mistral")
221+
) {
222+
const keys = ["bedrock", model.providerID]
223+
const strip = (opts: Record<string, unknown> | undefined): Record<string, unknown> | undefined => {
224+
if (!opts) return opts
225+
let out = opts
226+
for (const k of keys) {
227+
const bucket = out[k] as Record<string, unknown> | undefined
228+
if (bucket?.cachePoint) {
229+
const { cachePoint: _, ...rest } = bucket
230+
out = { ...out, [k]: Object.keys(rest).length > 0 ? rest : undefined }
231+
}
232+
}
233+
return out
234+
}
235+
return msgs.map((msg) => {
236+
let content = msg.content
237+
if (msg.role === "assistant" && Array.isArray(content)) {
238+
content = content.filter(
239+
(part) =>
240+
(part as { type: string }).type !== "reasoning" &&
241+
(part as { type: string }).type !== "redacted-reasoning",
242+
) as typeof content
243+
if (content.length === 0)
244+
content = [{ type: "text" as const, text: "..." }] as typeof content
245+
}
246+
if (Array.isArray(content)) {
247+
content = content.map((part) => {
248+
const p = part as { providerOptions?: Record<string, unknown> }
249+
const cleaned = strip(p.providerOptions)
250+
return cleaned !== p.providerOptions ? { ...part, providerOptions: cleaned } : part
251+
}) as typeof content
252+
}
253+
const cleaned = strip(msg.providerOptions as Record<string, unknown> | undefined)
254+
if (content !== msg.content || cleaned !== msg.providerOptions)
255+
return { ...msg, content, providerOptions: cleaned } as typeof msg
256+
return msg
257+
})
258+
}
259+
217260
if (
218261
typeof model.capabilities.interleaved === "object" &&
219262
model.capabilities.interleaved.field &&
@@ -679,7 +722,7 @@ export function variants(model: Provider.Model): Record<string, Record<string, a
679722
{
680723
reasoningConfig: {
681724
type: "adaptive",
682-
maxReasoningEffort: effort,
725+
maxReasoningEffort: effort === "xhigh" ? "max" : effort,
683726
...(model.api.id.includes("opus-4-7") || model.api.id.includes("opus-4.7")
684727
? { display: "summarized" }
685728
: {}),

packages/opencode/test/provider/transform.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3004,7 +3004,7 @@ describe("ProviderTransform.variants", () => {
30043004
})
30053005
})
30063006

3007-
test("anthropic opus 4.7 returns adaptive reasoning options with xhigh", () => {
3007+
test("anthropic opus 4.7 returns adaptive reasoning options with xhigh mapped to max", () => {
30083008
const model = createMockModel({
30093009
id: "bedrock/anthropic-claude-opus-4-7",
30103010
providerID: "bedrock",
@@ -3019,7 +3019,7 @@ describe("ProviderTransform.variants", () => {
30193019
expect(result.xhigh).toEqual({
30203020
reasoningConfig: {
30213021
type: "adaptive",
3022-
maxReasoningEffort: "xhigh",
3022+
maxReasoningEffort: "max",
30233023
display: "summarized",
30243024
},
30253025
})

0 commit comments

Comments
 (0)