From 269afc66abfd5fdd37ff0eedfe2b749b6050a420 Mon Sep 17 00:00:00 2001 From: "robopipi[bot]" <336283572+robopipi[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:38:06 +0100 Subject: [PATCH] fix(coding-agent): pass thinking level to branch summarization (#11482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `/tree` "Summarize" option ignored the session's thinking level. `AgentSession` already passes `thinkingLevel` into the `generateBranchSummary` options, but `generateBranchSummary` never read it, so the request was built without `reasoning`. For reasoning models on OpenAI Responses and Azure Responses, a missing `reasoning` becomes `effort: thinkingLevelMap.off ?? "none"`. Models that don't accept `"none"` then reject the branch summary with a 400 error: ``` Unsupported value: 'none' is not supported with the 'gpt-6-astra-…' model. ``` This change adds `thinkingLevel` to `GenerateBranchSummaryOptions`. It sets `reasoning` on the request when the model supports reasoning and the level is not `off`, the same rule compaction uses in `createSummarizationOptions`. **Testing** - Added a test to `packages/coding-agent/test/branch-summarization.test.ts` that records the stream options for three cases: a reasoning model at `xhigh`, a reasoning model at `off`, and a non-reasoning model. The expected `reasoning` values are `["xhigh", undefined, undefined]`. Without the fix, the test fails and every case gets `undefined`. With the fix, it passes. - Ran `branch-summarization`, `agent-session-branching`, `branch-summary-extensions` and `compaction-summary-reasoning`: all pass. - `npm run check` passes. - Not tested against a real provider endpoint. Fixes #11444 Requested by @davidbrai Co-authored-by: triagent --- .../core/compaction/branch-summarization.ts | 8 +++++++- .../test/branch-summarization.test.ts | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/src/core/compaction/branch-summarization.ts b/packages/coding-agent/src/core/compaction/branch-summarization.ts index f1db25e14..69bd75133 100644 --- a/packages/coding-agent/src/core/compaction/branch-summarization.ts +++ b/packages/coding-agent/src/core/compaction/branch-summarization.ts @@ -5,7 +5,7 @@ * a summary of the branch being left so context isn't lost. */ -import type { AgentMessage, StreamFn } from "@earendil-works/pi-agent-core"; +import type { AgentMessage, StreamFn, ThinkingLevel } from "@earendil-works/pi-agent-core"; import type { RetryCallbacks, RetryPolicy } from "@earendil-works/pi-ai"; import { contentText, normalizeContext } from "@earendil-works/pi-ai"; import type { Model, SimpleStreamOptions, Usage } from "@earendil-works/pi-ai/compat"; @@ -75,6 +75,8 @@ export interface GenerateBranchSummaryOptions { env?: Record; /** Abort signal for cancellation */ signal: AbortSignal; + /** Thinking level for reasoning-capable models */ + thinkingLevel?: ThinkingLevel; /** Optional custom instructions for summarization */ customInstructions?: string; /** If true, customInstructions replaces the default prompt instead of being appended */ @@ -300,6 +302,7 @@ export async function generateBranchSummary( headers, env, signal, + thinkingLevel, customInstructions, replaceInstructions, reserveTokens = 16384, @@ -348,6 +351,9 @@ export async function generateBranchSummary( // so transient stream drops reuse the configured retry policy. const context = normalizeContext({ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages }); const requestOptions: SimpleStreamOptions = { apiKey, headers, env, signal }; + if (model.reasoning && thinkingLevel && thinkingLevel !== "off") { + requestOptions.reasoning = thinkingLevel; + } const response = await completeSummarization(model, context, requestOptions, streamFn, retry, callbacks); // Check if aborted or errored diff --git a/packages/coding-agent/test/branch-summarization.test.ts b/packages/coding-agent/test/branch-summarization.test.ts index 7018e969f..ade25dbfd 100644 --- a/packages/coding-agent/test/branch-summarization.test.ts +++ b/packages/coding-agent/test/branch-summarization.test.ts @@ -44,6 +44,26 @@ function response(content: AssistantMessage["content"]): AssistantMessage { } describe("branch summarization", () => { + it("passes the thinking level only for reasoning-capable models", async () => { + const seen: Array = []; + const streamFn: StreamFn = (_model, _context, options) => { + seen.push(options?.reasoning); + const stream = createAssistantMessageEventStream(); + queueMicrotask(() => + stream.push({ type: "done", reason: "stop", message: response([{ type: "text", text: "summary" }]) }), + ); + return stream; + }; + const reasoningModel = { ...model, reasoning: true }; + const signal = new AbortController().signal; + + await generateBranchSummary(entries, { model: reasoningModel, signal, streamFn, thinkingLevel: "xhigh" }); + await generateBranchSummary(entries, { model: reasoningModel, signal, streamFn, thinkingLevel: "off" }); + await generateBranchSummary(entries, { model, signal, streamFn, thinkingLevel: "high" }); + + expect(seen).toEqual(["xhigh", undefined, undefined]); + }); + it("does not override tool choice for branch summaries", async () => { let requestOptions: SimpleStreamOptions | undefined; const streamFn: StreamFn = (_model, _context, options) => {