You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When calling api.githubcopilot.com/v1/messages with thinking: {type: "enabled", budget_tokens: N}, the upstream returns real thinking blocks with a signature field:
{
"type": "thinking",
"thinking": "I need to calculate 1234 * 5678...\n\n1234 * 5000 = 6,170,000...",
"signature": "EqMPCkgIDRABGAIqQLsu3KN/ovAdOg1a1HQqToWQ..."
}
The signature is the Anthropic equivalent of OpenAI's encrypted_content — it must be echoed back verbatim in subsequent turns for multi-turn reasoning continuity.
On the input side (turn N+1): when client sends prior thinking blocks in the messages array, they are forwarded upstream as-is on the native path.
Tasks
Verify AnthropicThinkingBlock in anthropic-types.ts includes signature?: string. Add if missing.
No additional code needed for the native path — pass-through preserves the field. Document this explicitly with a code comment.
For the translation path (legacy models): add handling for inbound thinking blocks with signature in conversation history — currently they are flattened to text (non-stream-translation.ts:146-154). After this issue, they should be forwarded in a way that OpenAI-format upstream can interpret (or at minimum: not crash). Lower priority since legacy models don't support thinking anyway.
Add thinking to the test for count_tokens — verify the heuristic accounts for thinking tokens in the output budget
Multi-turn test: send turn 1 with thinking enabled → extract thinking block with signature → send turn 2 with the thinking block in messages → verify upstream accepts it without error
Acceptance criteria
Two-turn conversation with thinking enabled returns coherent responses (upstream doesn't reject the echoed signature)
signature field is preserved byte-exact through the proxy (verify with a hash comparison test)
anthropic-types.ts has signature?: string on thinking content blocks
File pointers
Touch: src/routes/messages/anthropic-types.ts (add signature if missing)
Part of #38. Depends on #39, #40.
Background (verified by live test — 2026-05-10)
When calling
api.githubcopilot.com/v1/messageswiththinking: {type: "enabled", budget_tokens: N}, the upstream returns real thinking blocks with asignaturefield:{ "type": "thinking", "thinking": "I need to calculate 1234 * 5678...\n\n1234 * 5000 = 6,170,000...", "signature": "EqMPCkgIDRABGAIqQLsu3KN/ovAdOg1a1HQqToWQ..." }The
signatureis the Anthropic equivalent of OpenAI'sencrypted_content— it must be echoed back verbatim in subsequent turns for multi-turn reasoning continuity.Live test confirmed:
claude-sonnet-4.5+thinking: {budget_tokens: 2000}→ thinking block with signature ✅claude-sonnet-4.6+thinking: {budget_tokens: 2000}→ thinking block with signature ✅claude-sonnet-4.6+thinking+toolstogether → both blocks in response ✅Current state
AnthropicThinkingBlockinanthropic-types.ts— check ifsignaturefield is declared. If not, add it.thinkingblocks in themessagesarray, they are forwarded upstream as-is on the native path.Tasks
AnthropicThinkingBlockinanthropic-types.tsincludessignature?: string. Add if missing.thinkingblocks withsignaturein conversation history — currently they are flattened to text (non-stream-translation.ts:146-154). After this issue, they should be forwarded in a way that OpenAI-format upstream can interpret (or at minimum: not crash). Lower priority since legacy models don't support thinking anyway.thinkingto the test forcount_tokens— verify the heuristic accounts for thinking tokens in the output budgetAcceptance criteria
signaturefield is preserved byte-exact through the proxy (verify with a hash comparison test)anthropic-types.tshassignature?: stringon thinking content blocksFile pointers
src/routes/messages/anthropic-types.ts(addsignatureif missing)create-messages-native.tsfrom feat: create-messages-native.ts — Anthropic pass-through service client #39) handles this automaticallyencrypted_contenton Responses API path — same concept, different API)