diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts index 55df305dc00e40a3b10690c5657545651446d290..8b8eabe8fc9df6796761b51dcde21608d47a3c31 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts @@ -2809,14 +2809,10 @@ describe("ClaudeAdapterV2 background wake turns", () => { ), ); - it.effect.each([ - { model: "claude-opus-5-5", expected: "assistant_message" }, - { model: "claude-fable-5-1", expected: "assistant_message" }, - { model: "claude-opus-5", expected: "reasoning" }, - { model: "claude-sonnet-4-6", expected: "reasoning" }, - ] as const)( - "shows $model thinking right before a tool call as $expected", - ({ model, expected }) => + // Summarized thinking can't tell a progress update from reasoning, so both stay Thoughts. + it.effect.each(["claude-opus-5-5", "claude-fable-5-1", "claude-opus-5", "claude-sonnet-4-6"])( + "keeps %s thinking right before a tool call as reasoning", + (model) => Effect.gen(function* () { const harness = yield* makeWakeHarness; yield* harness.runtime.startTurn( @@ -2867,7 +2863,7 @@ describe("ClaudeAdapterV2 background wake turns", () => { [...latest.values()].map((item) => [item.type, item.text]), [ ["reasoning", "Planning the check"], - [expected, "Found it: the memory file is the cause."], + ["reasoning", "Found it: the memory file is the cause."], ], ); }).pipe( diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts index 880652b95f10ca824ebac422455d8b7776b4b932..7aff6b96eb5d7ac4bc79cf6529b31f97565db136 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts @@ -1165,15 +1165,6 @@ function textFromClaudeContent(content: SDKAssistantMessage["message"]["content" return content.flatMap((part) => (part.type === "text" ? [part.text] : [])).join(""); } -// Claude 5.1 and later return the text written ahead of a tool call as a -// thinking block, at most one per call, instead of a text block. -function claudeWritesUpdatesAsThinking(model: string): boolean { - const match = /claude-[a-z]+-(\d+)(?:-(\d{1,2}))?(?!\d)/u.exec(model); - if (match === null) return false; - const major = Number(match[1]); - return major > 5 || (major === 5 && Number(match[2] ?? 0) >= 1); -} - // In SDK mode Claude reports `/goal` only through the transcript (its // `active_goal` event is remote-only): synthetic command output names the // goal, and each unmet evaluator check returns as Stop hook feedback. @@ -2915,12 +2906,6 @@ interface ActiveClaudeTurnContext { readonly nextBlockIndex: Map; readonly snapshotBlockIndex: Map; readonly snapshots: Set; - // The latest snapshot block, when it was non-empty thinking. - lastThinking: { - readonly messageId: string; - readonly itemId: string; - readonly text: string; - } | null; readonly blocks: Map< string, { readonly startedAt: DateTime.Utc; readonly ordinal: number; text: string } @@ -6862,23 +6847,7 @@ export const makeClaudeAdapterV2 = Effect.fn("makeClaudeAdapterV2")(function* ( // The SDK emits one assistant snapshot per completed content block. // Count thinking blocks separately so snapshots share the streamed ID. for (const block of message.message.content) { - if (block.type !== "thinking") { - const update = context.reasoning.lastThinking; - context.reasoning.lastThinking = null; - if ( - block.type === "tool_use" && - update?.messageId === message.message.id && - claudeWritesUpdatesAsThinking(message.message.model) - ) { - // Same item ID, so the update replaces the Thought in place. - yield* emitAssistantTextArtifacts({ - context, - nativeItemId: update.itemId, - text: update.text, - }); - } - continue; - } + if (block.type !== "thinking") continue; const index = context.reasoning.snapshotBlockIndex.get(message.message.id) ?? 0; context.reasoning.snapshotBlockIndex.set(message.message.id, index + 1); const itemId = `${message.message.id}:thinking:${index}`; @@ -6890,9 +6859,6 @@ export const makeClaudeAdapterV2 = Effect.fn("makeClaudeAdapterV2")(function* ( ...(finalText ? { finalText } : {}), emitEmpty: false, }); - context.reasoning.lastThinking = finalText - ? { messageId: message.message.id, itemId, text: finalText } - : null; } } @@ -8587,7 +8553,6 @@ export const makeClaudeAdapterV2 = Effect.fn("makeClaudeAdapterV2")(function* ( streamBlocks: new Map(), nextBlockIndex: new Map(), snapshotBlockIndex: new Map(), - lastThinking: null, snapshots: new Set(), blocks: new Map(), },