From acbf8eca0634c6579277d4404c3d5e8663b17d76 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 16 Apr 2026 22:12:06 +0200 Subject: [PATCH] feat(ai): add thinkingDisplay option for Anthropic and Bedrock Claude Exposes the new ThinkingConfig.display field on Anthropic and Bedrock Claude providers. Defaults to 'summarized' so Claude Opus 4.7 and Mythos Preview keep returning thinking text despite Anthropic's silent default change to 'omitted'. Set to 'omitted' explicitly to skip thinking streaming for faster time-to-first-text-token. --- packages/ai/CHANGELOG.md | 5 +++++ packages/ai/src/index.ts | 4 ++-- packages/ai/src/providers/amazon-bedrock.ts | 19 +++++++++++++++++- packages/ai/src/providers/anthropic.ts | 22 +++++++++++++++++++-- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 86b9ebaa..241b7792 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -5,6 +5,11 @@ ### Added - Added `onResponse` to `StreamOptions` so callers can inspect provider HTTP status and headers after each response arrives and before the response stream is consumed ([#3128](https://github.com/badlogic/pi-mono/issues/3128)) +- Added `thinkingDisplay` (`"summarized" | "omitted"`) to `AnthropicOptions` and `BedrockOptions`, wiring it through to the Anthropic/Bedrock `thinking` config. Defaults to `"summarized"` so Claude Opus 4.7 and Mythos Preview keep returning thinking text; set it to `"omitted"` to skip thinking streaming for faster time-to-first-text-token. + +### Changed + +- Bumped `@anthropic-ai/sdk` to `0.90.0` so `ThinkingConfigAdaptive.display` and `ThinkingConfigEnabled.display` are typed by the SDK. ## [0.67.5] - 2026-04-16 diff --git a/packages/ai/src/index.ts b/packages/ai/src/index.ts index 1c885a85..6a1ee2c0 100644 --- a/packages/ai/src/index.ts +++ b/packages/ai/src/index.ts @@ -4,8 +4,8 @@ export { Type } from "@sinclair/typebox"; export * from "./api-registry.js"; export * from "./env-api-keys.js"; export * from "./models.js"; -export type { BedrockOptions } from "./providers/amazon-bedrock.js"; -export type { AnthropicOptions } from "./providers/anthropic.js"; +export type { BedrockOptions, BedrockThinkingDisplay } from "./providers/amazon-bedrock.js"; +export type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from "./providers/anthropic.js"; export type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-responses.js"; export * from "./providers/faux.js"; export type { GoogleOptions } from "./providers/google.js"; diff --git a/packages/ai/src/providers/amazon-bedrock.ts b/packages/ai/src/providers/amazon-bedrock.ts index f72356b5..4b2e61f6 100644 --- a/packages/ai/src/providers/amazon-bedrock.ts +++ b/packages/ai/src/providers/amazon-bedrock.ts @@ -46,6 +46,8 @@ import { sanitizeSurrogates } from "../utils/sanitize-unicode.js"; import { adjustMaxTokensForThinking, buildBaseOptions, clampReasoning } from "./simple-options.js"; import { transformMessages } from "./transform-messages.js"; +export type BedrockThinkingDisplay = "summarized" | "omitted"; + export interface BedrockOptions extends StreamOptions { region?: string; profile?: string; @@ -56,6 +58,17 @@ export interface BedrockOptions extends StreamOptions { thinkingBudgets?: ThinkingBudgets; /* Only supported by Claude 4.x models, see https://docs.aws.amazon.com/bedrock/latest/userguide/claude-messages-extended-thinking.html#claude-messages-extended-thinking-tool-use-interleaved */ interleavedThinking?: boolean; + /** + * Controls how Claude's thinking content is returned in responses. + * - "summarized": Thinking blocks contain summarized thinking text (default here). + * - "omitted": Thinking content is redacted but the signature still travels back + * for multi-turn continuity, reducing time-to-first-text-token. + * + * Note: Anthropic's API default for Claude Opus 4.7 and Mythos Preview is + * "omitted". We default to "summarized" here to keep behavior consistent with + * older Claude 4 models. Only applies to Claude models on Bedrock. + */ + thinkingDisplay?: BedrockThinkingDisplay; /** Key-value pairs attached to the inference request for cost allocation tagging. * Keys: max 64 chars, no `aws:` prefix. Values: max 256 chars. Max 50 pairs. * Tags appear in AWS Cost Explorer split cost allocation data. @@ -759,9 +772,12 @@ function buildAdditionalModelRequestFields( } if (model.id.includes("anthropic.claude") || model.id.includes("anthropic/claude")) { + // Default to "summarized" so Opus 4.7 and Mythos Preview behave like + // older Claude 4 models (whose API default is also "summarized"). + const display: BedrockThinkingDisplay = options.thinkingDisplay ?? "summarized"; const result: Record = supportsAdaptiveThinking(model.id) ? { - thinking: { type: "adaptive" }, + thinking: { type: "adaptive", display }, output_config: { effort: mapThinkingLevelToEffort(options.reasoning, model.id) }, } : (() => { @@ -781,6 +797,7 @@ function buildAdditionalModelRequestFields( thinking: { type: "enabled", budget_tokens: budget, + display, }, }; })(); diff --git a/packages/ai/src/providers/anthropic.ts b/packages/ai/src/providers/anthropic.ts index 861bab8a..47686327 100644 --- a/packages/ai/src/providers/anthropic.ts +++ b/packages/ai/src/providers/anthropic.ts @@ -156,6 +156,8 @@ function convertContentBlocks(content: (TextContent | ImageContent)[]): export type AnthropicEffort = "low" | "medium" | "high" | "xhigh" | "max"; +export type AnthropicThinkingDisplay = "summarized" | "omitted"; + export interface AnthropicOptions extends StreamOptions { /** * Enable extended thinking. @@ -179,6 +181,18 @@ export interface AnthropicOptions extends StreamOptions { * Ignored for older models. */ effort?: AnthropicEffort; + /** + * Controls how thinking content is returned in API responses. + * - "summarized": Thinking blocks contain summarized thinking text (default here). + * - "omitted": Thinking blocks return an empty thinking field; the encrypted + * signature still travels back for multi-turn continuity. Use for faster + * time-to-first-text-token when your UI does not surface thinking. + * + * Note: Anthropic's API default for Claude Opus 4.7 and Claude Mythos Preview + * is "omitted". We default to "summarized" here to keep behavior consistent + * with older Claude 4 models. Set this explicitly to "omitted" to opt in. + */ + thinkingDisplay?: AnthropicThinkingDisplay; interleavedThinking?: boolean; toolChoice?: "auto" | "any" | "none" | { type: "tool"; name: string }; /** @@ -678,11 +692,14 @@ function buildParams( // budget-based (older models), or explicitly disabled. if (model.reasoning) { if (options?.thinkingEnabled) { + // Default to "summarized" so Opus 4.7 and Mythos Preview behave like + // older Claude 4 models (whose API default is also "summarized"). + const display: AnthropicThinkingDisplay = options.thinkingDisplay ?? "summarized"; if (supportsAdaptiveThinking(model.id)) { // Adaptive thinking: Claude decides when and how much to think. - // The Anthropic SDK types can lag newly supported effort values such as "xhigh". - params.thinking = { type: "adaptive" }; + params.thinking = { type: "adaptive", display }; if (options.effort) { + // The Anthropic SDK types can lag newly supported effort values such as "xhigh". params.output_config = options.effort === "xhigh" ? ({ effort: options.effort } as unknown as NonNullable< @@ -695,6 +712,7 @@ function buildParams( params.thinking = { type: "enabled", budget_tokens: options.thinkingBudgetTokens || 1024, + display, }; } } else if (options?.thinkingEnabled === false) {