Skip to content

fix: strip reasoning toggles from upstream requests (thinking variant exhausted max_tokens) - #5

Merged
dengyie merged 1 commit into
mainfrom
fix/strip-reasoning-triggers
Oct 4, 2026
Merged

dengyie merged 1 commit into
mainfrom
fix/strip-reasoning-triggers

Conversation

@dengyie

@dengyie dengyie commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Root cause (production forensics, 2026-10-04)

Raw upstream frame capture of a failing request:

frame kinds: {'reasoning_only': 1024, 'empty': 2}
content field: []  — never populated
finish_reason: length

Requests carrying reasoning_effort route the CNB gateway to a thinking variant whose reasoning phase is counted against max_tokens. On hard prompts reasoning consumes the entire budget before any answer text is produced, so the stream ends with finish_reason=length and content=[] — the answer is never generated. Reproduced deterministically at both 2048 and 8192 max_tokens (hard prompt), and confirmed the fix condition: without reasoning_effort the same prompt returns a normal content-only answer.

The OpenAI passthrough path forwarded client reasoning_effort verbatim ({ ...payload, stream: true }), which is how real clients (CPA panel / cpa-cnb) hit this every time. The Anthropic /v1/messages adapter was unaffected by construction (it never emits thinking params) — the same "no thinking outbound" policy this PR now applies to both paths.

Fix

Single choke point in forward() (covers OpenAI passthrough + Anthropic adapter): strip reasoning_effort, reasoning, enable_thinking, thinking from the outbound body. Table-driven so new gateway thinking toggles are a one-line addition.

Response side intentionally unchanged: if the thinking variant is ever hit, reasoning_content → thinking block conversion and finish_reason=length → max_tokens stop-reason mapping remain faithful (lock-in tests added; no fabricated answer text).

Tests

  • RED→GREEN: outbound-strip assertions via a body-capturing mock upstream (failed before the fix, caught reasoning_effort: 'medium' leaking through)
  • Anthropic adapter: thinking request params (thinking/reasoning_effort/reasoning/enable_thinking) never leak outbound
  • Lock-in: reasoning_content → thinking block ordering before text block; degenerate reasoning-only truncated stream yields a single thinking block closed with stop_reason: max_tokens, no fabricated text
  • Full suite: 61/61 passing

…requests

Production forensics (2026-10-04 frame capture): requests carrying
reasoning_effort route the CNB gateway to its thinking variant, which
counts the reasoning phase against max_tokens — once reasoning exhausts
the budget the stream ends with finish_reason=length, content empty
(1024 frames, all reasoning_only), and the answer is never generated.

The upstream offers no correct knob to configure, so the gateway now
strips reasoning_effort / reasoning / enable_thinking / thinking at the
single outbound choke point in forward() (covers both the OpenAI
passthrough path and the Anthropic /v1/messages adapter), the same
policy the adapter already applies by dropping thinking blocks.

Tests: outbound-strip assertions against a body-capturing mock upstream,
thinking-param non-leakage through the Anthropic adapter, and lock-in
tests for the reasoning→thinking block ordering plus the degenerate
reasoning-only-truncated stream shape.
Copilot AI lite review requested due to automatic review settings October 4, 2026 17:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@dengyie
dengyie merged commit 557e760 into main Oct 4, 2026
2 checks passed
@dengyie
dengyie deleted the fix/strip-reasoning-triggers branch October 4, 2026 23:16
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