fix(bedrock): check model.name for prompt caching and adaptive thinking (#3527)
supportsPromptCaching, supportsAdaptiveThinking, supportsThinkingSignature, and the Claude detection in streamSimpleBedrock/buildAdditionalModelRequestFields all check model.id for Claude model name patterns. Application inference profile ARNs are opaque and do not contain the model name, so these checks silently fail. Fix by also checking model.name (user-controlled via models.json or registerProvider) as a fallback in all affected functions. Added a shared isAnthropicClaudeModel helper for the common Claude detection pattern. Fixes #2925 Co-authored-by: Your Name <you@example.com>
This commit is contained in:
@@ -105,3 +105,67 @@ describe("Bedrock thinking payload", () => {
|
||||
expect(payload.additionalModelRequestFields?.anthropic_beta).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Application inference profile support", () => {
|
||||
it("uses adaptive thinking when model.name contains the model name but ARN does not", async () => {
|
||||
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
||||
const model: Model<"bedrock-converse-stream"> = {
|
||||
...baseModel,
|
||||
id: "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/my-profile",
|
||||
name: "Claude Opus 4.6",
|
||||
};
|
||||
|
||||
const payload = await capturePayload(model);
|
||||
|
||||
expect(payload.additionalModelRequestFields?.thinking).toEqual({ type: "adaptive", display: "summarized" });
|
||||
expect(payload.additionalModelRequestFields?.output_config).toEqual({ effort: "high" });
|
||||
});
|
||||
|
||||
it("injects cache points when model.name identifies a supported Claude model", async () => {
|
||||
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
||||
const model: Model<"bedrock-converse-stream"> = {
|
||||
...baseModel,
|
||||
id: "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/my-profile",
|
||||
name: "Claude Sonnet 4.6",
|
||||
};
|
||||
|
||||
let capturedPayload: any;
|
||||
const s = streamBedrock(model, {
|
||||
systemPrompt: "You are helpful.",
|
||||
messages: [{ role: "user", content: "Hello", timestamp: Date.now() }],
|
||||
}, {
|
||||
signal: AbortSignal.abort(),
|
||||
onPayload: (payload) => {
|
||||
capturedPayload = payload;
|
||||
return payload;
|
||||
},
|
||||
});
|
||||
|
||||
for await (const event of s) {
|
||||
if (event.type === "error") break;
|
||||
}
|
||||
|
||||
// System prompt should have a cache point
|
||||
expect(capturedPayload.system).toHaveLength(2);
|
||||
expect(capturedPayload.system[1]).toHaveProperty("cachePoint");
|
||||
|
||||
// Last user message should have a cache point
|
||||
const lastMsg = capturedPayload.messages[capturedPayload.messages.length - 1];
|
||||
const lastContent = lastMsg.content[lastMsg.content.length - 1];
|
||||
expect(lastContent).toHaveProperty("cachePoint");
|
||||
});
|
||||
|
||||
it("falls back to fixed-budget thinking for non-adaptive Claude via model.name", async () => {
|
||||
const baseModel = getModel("amazon-bedrock", "us.anthropic.claude-sonnet-4-5-20250929-v1:0");
|
||||
const model: Model<"bedrock-converse-stream"> = {
|
||||
...baseModel,
|
||||
id: "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/my-profile",
|
||||
name: "Claude Sonnet 4.5",
|
||||
};
|
||||
|
||||
const payload = await capturePayload(model);
|
||||
|
||||
expect(payload.additionalModelRequestFields?.thinking).toMatchObject({ type: "enabled", budget_tokens: expect.any(Number) });
|
||||
expect(payload.additionalModelRequestFields?.anthropic_beta).toEqual(["interleaved-thinking-2025-05-14"]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user