Skip to content

fix(prompt): preserve Anthropic thinking block boundaries - #2262

Open
kyboi wants to merge 2 commits into
JetBrains:developfrom
Kreoh:contribute/anthropic-signature-followup
Open

kyboi wants to merge 2 commits into
JetBrains:developfrom
Kreoh:contribute/anthropic-signature-followup

Conversation

@kyboi

@kyboi kyboi commented Sep 29, 2026 •

Copy link
Copy Markdown

Includes Lubaoshuai's original commit from #2241, preserving their authorship, followed by my separate supplement commit, 45f7a14b0805bf313de10a6fedbf312dc904fafd.

Maintainers can choose any of these paths:

Consecutive Anthropic thinking blocks currently fail because normal content_block_stop events have no delta, leaving the previous block buffered. This supplement preserves block boundaries and adds streaming-to-follow-up-request regression coverage, including signature-only thinking before tool results. It also preserves the existing public reasoning-delta method's compatibility.

The underlying signature and block-boundary handling is already included and working in production applications through Kroog. This is a focused adaptation of that implementation, with separate local validation of the upstream patch. Relevant Kroog source: 0587101f0 and 4f955e207.

Anthropic documents multiple initial thinking blocks and preserving them unchanged in tool-use loops.

Validation: 54 Anthropic JVM tests passed; 198 prompt-model JVM tests passed, with three existing skips. Both JVM JAR builds and module ktlint checks passed. The consecutive-block regression fails on unchanged #2241. Compiled JVM inspection confirms that the original emitReasoningDelta and default-call descriptors are preserved. No live-provider or non-JVM tests were run. The internal stream DTO compatibility changes already present in #2241 remain unchanged.

Refs #1959. Related earlier approach: #2010.

Lubaoshuai and others added 2 commits September 14, 2026 00:59
Anthropic streams a thinking block's signature as its own
content_block_delta event (delta.type = signature_delta). The streaming
client had no signature field on AnthropicStreamDelta and no branch for
that delta type, so the signature was dropped with an unknown-delta
warning and the settled StreamFrame.ReasoningComplete carried
encrypted = null. Any follow-up request containing that reasoning
message then failed with 'Encrypted signature is required for reasoning
messages but was null' (JetBrains#1959).

- AnthropicStreamDelta gains a signature field and
  AnthropicStreamDeltaContentType gains SIGNATURE_DELTA
- AnthropicLLMClient routes signature_delta into the pending reasoning
  frame and forwards a non-empty initial signature from
  content_block_start
- StreamFrameFlowBuilder carries the encrypted signature on
  PendingReasoning so tryEmitPendingReasoning() and the emitEnd() flush
  emit ReasoningComplete.encrypted; signature-only updates do not emit
  an empty ReasoningDelta frame and the new parameter is optional, so
  existing callers keep their exact behavior

Signed-off-by: Lubaoshuai <128781758+Lubaoshuai@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants