-
Notifications
You must be signed in to change notification settings - Fork 2.7k
fix(chatcmpl): preserve all LiteLLM thinking-block signatures in converter #1779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…erter Previously only the last signature was preserved when multiple thinking blocks had signatures. Now all signatures are collected and stored with newline delimiters, ensuring proper reconstruction of each thinking block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codex Review: Here are some suggestions.
About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".
"type": "thinking", | ||
"thinking": content_item.get("text", ""), | ||
} | ||
# Add signature if available | ||
if signature: | ||
thinking_block["signature"] = signature | ||
# Add signatures if available | ||
if signatures: | ||
thinking_block["signature"] = signatures.pop(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Preserve signature alignment when some thinking blocks lack signatures
message_to_output_items
now collects only the signatures that are present and stores them as a newline‑joined string, but items_to_messages
reconstructs thinking blocks by popping from that list for every reasoning block in order. If a response contains multiple thinking blocks where some early blocks do not have signatures, this logic shifts the later signatures onto earlier blocks and drops any trailing ones (e.g., blocks [no sig, sigA, sigB]
become [sigA, sigB, none]
). This produces incorrect signature/block pairing and will break downstream verification whenever not all blocks carry a signature. Consider storing signature placeholders (e.g., None
) for blocks without signatures or associating signatures with their block index before reconstruction.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All reasoning blocks should always contain signatures, this is basically a N:1 conversion and 1:N back-conversion. So N should always equal. if signatures
is simply a defensive coding practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this!
Summary
In rare cases, Claude Sonnet 4 with extended thinking emits multiple thinking blocks, each with its own signature. Our converter previously kept only the last signature. This change collects all signatures in order and joins them with
\n
, enabling proper reconstruction/verification of each block.Before
Input: two thinking blocks with signatures → output stored only the last signature.
After
Input: two+ thinking blocks with signatures → output stores all signatures joined by newline (e.g.,
"sig1\nsig2\nsig3"
).Implementation
encrypted_content
Tests
Compatibility / Risk