Skip to content

gateway: a Chat turn's thinking is read in every spelling the client … - #1075

Open
TryWorld2026 wants to merge 1 commit into
yetone:mainfrom
TryWorld2026:fix/chat-inbound-reasoning-spellings
Open

TryWorld2026 wants to merge 1 commit into
yetone:mainfrom
TryWorld2026:fix/chat-inbound-reasoning-spellings

Conversation

@TryWorld2026

@TryWorld2026 TryWorld2026 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

gateway: a Chat turn's thinking is read in every spelling the client sends it back in

What is wrong

A client sends the previous assistant turn's thinking back in one of three
spellings: reasoning_content (DeepSeek's, which OpenCode and most clients
send), reasoning (OpenRouter's) or reasoning_details (OpenRouter's
structured one). parseChat read only reasoning_content, so a request
translated to a non-Chat upstream lost the thinking of every turn sent another
way, and the model went on without its own reasoning. A tool-calling session
shows it from its second turn on: the assistant has a thinking block in turn
one, none in turn three.

chattidy's passthrough has read all three since mistralThinking (#494); the
parse layer never got the same reader.

What changed

The assistant branch now reads the thinking through reasoningText,
messageReasoning's own reader, in the order the passthrough keeps it:
reasoning_content, else reasoning, else reasoning_details' text. The
three fields are read as json.RawMessage so one reader handles every
spelling, as the passthrough already does.

A turn sent in a spelling the reader does not know is still carried as before:
reasoningText answers empty and no thinking part is added.

Semantic change (Gateway routing and fallback)

  • Before: an assistant message whose thinking arrived as reasoning or
    reasoning_details produced a Message with no Part{Kind: Thinking}.
  • After: it produces that part, so the IR carries the client's own thinking
    into whichever upstream the request is translated to.
  • Reference: docs/subsystems/gateway-routing.md;
    implementation parseChat in internal/gateway/chat.go.

Verification

  • TestParseChatReadsEveryReasoningSpelling fails without the change for the
    reasoning and reasoning_details spellings — the assistant turn's parts: [{Kind:tool_call ...}], the turn keeps its tool call and its thinking is gone
    — and passes with it. Its reasoning_content subtest passes on the base as
    well: upstream already reads that one, so it is a guard against dropping it
    rather than a reproducer. TestParseChatTakesTheFirstReasoningSpellingSent
    also passes on the base and stays green.
  • go test -tags nogui ./internal/gateway/ for the chat, reasoning and
    thinking tests; go vet -tags nogui ./internal/gateway/...; GOOS=windows,
    GOOS=darwin and GOOS=linux builds.
  • The whole internal/gateway package leaves one failure on this Windows box,
    TestSweepBridgeProjectsTakesOnlyTheBridgesFolders, which needs a symlink
    privilege Windows does not grant here and fails the same way on the untouched
    base. A second, TestPluginStreamStalledClientKeepsOtherRequestsMoving, failed
    in one run of the package and passed in another, and passes under -count=3.

…sends it back in

A client sends the previous assistant turn's thinking back in reasoning_content (DeepSeek's, which OpenCode and most clients send), reasoning (OpenRouter's) or reasoning_details (OpenRouter's structured one). parseChat read only reasoning_content, so a request translated to a non-Chat upstream lost the thinking of every turn sent another way and the model went on without its own reasoning, which a tool-calling session shows from its second turn on. chattidy's passthrough has read all three since mistralThinking (yetone#494); the parse layer never got the same reader.

The assistant branch now reads the thinking through reasoningText, messageReasoning's own reader, in the order the passthrough keeps it: reasoning_content, else reasoning, else reasoning_details' text.

TestParseChatReadsEveryReasoningSpelling (a tool-calling turn per spelling) and TestParseChatTakesTheFirstReasoningSpellingSent fail without the change ("the assistant turn's parts: [{Kind:tool_call ...}]"). go vet -tags nogui ./internal/gateway/..., builds for windows, darwin and linux, and the package's chat/reasoning/thinking tests pass.
@TryWorld2026
TryWorld2026 force-pushed the fix/chat-inbound-reasoning-spellings branch from 12530ea to bb04efa Compare October 7, 2026 00:59

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.

1 participant