Skip to content

Unify reasoning request conversion across protocols - #46

Merged
maiphucgiang merged 1 commit into
devfrom
fix/shared-reasoning-compat
Sep 26, 2026
Merged

maiphucgiang merged 1 commit into
devfrom
fix/shared-reasoning-compat

Conversation

@maiphucgiang

@maiphucgiang maiphucgiang commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Changes

  • Centralize readable thinking extraction, reasoning-control mapping and account-owned effort defaults in app/reasoning.py, shared by Chat, Messages, Responses and routing/capability checks.
  • Map Messages thinking / output_config.effort and preserve Responses effort extensions supported by the selected model. Resolve implicit effort from the selected account again after failover, while retaining explicit controls and existing capability, binding and free-tier checks.
  • Preserve readable reasoning history as reasoning_content, including thinking-only turns and tool continuations. Keep Responses reasoning, text and calls together even when realtime output starts with a tool call; never inject reasoning into ordinary answer text.
  • Reject opaque/redacted reasoning before routing, omit signatures, and document the limits of summaries, adaptive thinking and token-budget compatibility in concise English/Chinese client and advanced references.

Verification

  • All 64 backend regression scripts pass using the CI entry point; the focused protocol/runtime suite passes 212 tests.
  • Add 16 regression tests covering all three response modes, history round trips, assistant-item ordering, malformed/opaque inputs, account-specific defaults, failover, strict binding and free-tier boundaries.
  • vp build succeeds. Served WebUI assets match the rebuilt files; git diff --check and version consistency pass. Focused Ruff checks have no new findings relative to the base.
  • Replace the original local tmux service on port 8787 with this code, preserving its realtime/desensitization settings, API key and management configuration. Nine zero-multiplier live requests pass across Chat, Messages and Responses JSON/SSE plus history follow-ups; two opaque-history cases return 400 locally. Each inference checks the current model multiplier first.
  • An additional native local instance verifies compatible streaming and account-default effort selection with real upstream transport. Previous application code and a control-database snapshot are retained for rollback.

Fixes #43

Summary by Sourcery

Standardize reasoning conversion and validation across supported protocols while preserving compatible history and routing behavior.

New Features:

  • Unify reasoning-control mapping and readable reasoning extraction across Chat, Messages, and Responses protocols.
  • Preserve readable reasoning history with assistant content and tool continuations while keeping it separate from visible answer text.
  • Support account-specific implicit reasoning defaults, including re-resolution after failover and model-specific effort extensions.

Bug Fixes:

  • Reject malformed, opaque, redacted, or encrypted-only reasoning before routing without forwarding signatures or sensitive content.
  • Preserve Responses assistant-turn ordering when reasoning, text, and tool calls arrive in varying or realtime orders.

Enhancements:

  • Centralize reasoning capability checks, effort resolution, and protocol compatibility validation in shared reasoning utilities.

Documentation:

  • Document reasoning-control mappings, account defaults, history behavior, opaque reasoning limits, adaptive-thinking limitations, and token-budget compatibility in English and Chinese references.

Tests:

  • Add comprehensive regression coverage for protocol mappings, history round trips, tool continuations, malformed inputs, account defaults, failover, capability checks, binding, free-tier boundaries, and request-size limits.

@sourcery-ai

sourcery-ai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

This PR introduces a shared reasoning normalization layer used by all request protocols and routing, preserving readable reasoning as separate assistant history while consistently mapping controls and account-specific defaults, including after failover. It adds documentation and comprehensive regression coverage for conversion, streaming, capability, validation, and routing edge cases.

Sequence diagram for protocol reasoning conversion and account defaults

sequenceDiagram
    participant Client
    participant Protocol as Protocol adapter
    participant Reasoning as app.reasoning
    participant Router
    participant Account
    participant Upstream

    Client->>Protocol: Submit request
    Protocol->>Reasoning: map_reasoning_controls(body, chat, protocol)
    Reasoning-->>Protocol: Explicit reasoning_effort or implicit control
    Protocol->>Router: Validate and route canonical request
    Router->>Account: Select account and model
    Account-->>Router: Account reasoning metadata
    Router->>Reasoning: resolve_reasoning_effort(effort, mode, model)
    Reasoning-->>Router: Account-compatible effort
    Router->>Upstream: Send normalized reasoning_effort
    Upstream-->>Client: Response or stream
Loading

Flow diagram for preserving readable reasoning history

flowchart TD
    Input[Protocol history item]
    Extract[extract_reasoning_text]
    Reject{Opaque or encrypted reasoning?}
    Preserve[Append to assistant reasoning_content]
    Content[Keep answer text and tool calls separate]
    Convert[Forward normalized assistant history]

    Input --> Extract
    Extract --> Reject
    Reject -- Yes --> Error[Return HTTP 400 before routing]
    Reject -- No --> Preserve
    Input --> Content
    Preserve --> Convert
    Content --> Convert
Loading

File-Level Changes

Change Details Files
Centralize reasoning parsing, control mapping, and model/account default resolution across protocols and routing.
  • Added shared validation and readable-reasoning extraction, rejecting opaque or malformed inputs before routing.
  • Mapped Messages and Responses controls to canonical reasoning effort with explicit-control precedence and account-specific defaults.
  • Recomputed implicit effort after failover and reused the resolved value for capability checks and upstream requests.
app/reasoning.py
app/adapters/anthropic_adapter.py
app/adapters/chat_input.py
app/adapters/responses_adapter.py
app/model_capabilities.py
converter.py
Preserve readable reasoning as structured assistant history without leaking it into visible answer content.
  • Stored thinking and Responses reasoning in reasoning_content, including thinking-only turns and tool continuations.
  • Grouped Responses reasoning, text, and function calls into the correct assistant turn across item ordering and realtime tool-first output.
  • Omitted signatures and kept encrypted or redacted reasoning out of converted requests.
app/adapters/anthropic_adapter.py
app/adapters/chat_input.py
app/adapters/responses_adapter.py
tests/test_reasoning_requests.py
Document the unified reasoning compatibility behavior and its protocol limitations.
  • Documented effort mappings, account-owned defaults, failover behavior, budget validation, adaptive-thinking limitations, and summary/encryption handling in English and Chinese references.
  • Updated client guidance for reasoning history and pre-routing validation errors.
docs/advanced.md
docs/advanced.zh-CN.md
docs/clients.md
docs/clients.zh-CN.md
Add broad regression coverage for protocol conversion, runtime behavior, routing, and boundaries.
  • Covered Chat, Messages, and Responses in compatible and realtime modes, including history round trips, tool continuations, item ordering, and output separation.
  • Validated malformed or opaque inputs fail before upstream calls, explicit-control precedence, model extensions, account defaults, failover recomputation, capability checks, strict binding, free-tier behavior, and request-size limits.
tests/test_reasoning_requests.py

Assessment against linked issues

Issue Objective Addressed Explanation
#43 Preserve historical Anthropic thinking blocks when converting assistant messages to the upstream Chat format, including thinking-only turns and tool continuations, without exposing reasoning as ordinary answer text. ✅
#43 Forward Anthropic reasoning controls, including thinking and output_config.effort, as an appropriate upstream reasoning_effort value while preserving validation, capability checks, and account-specific defaults. ✅
#43 Ensure reasoning history and controls are handled consistently across protocols, including rejecting opaque or malformed reasoning and documenting the compatibility limitations. ✅

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-26T14:15:06.703374Z 98f6ddf PR opened
🔒 Security Review ✅ Completed 2026-09-26T14:17:32.427801Z 98f6ddf PR opened
ℹ️ 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
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@sourcery-ai sourcery-ai Bot 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@maiphucgiang
maiphucgiang changed the base branch from main to dev September 26, 2026 14:50
@maiphucgiang
maiphucgiang merged commit 9590bba into dev Sep 26, 2026
8 of 10 checks passed
@maiphucgiang
maiphucgiang deleted the fix/shared-reasoning-compat branch September 26, 2026 16:10
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.

Anthropic path drops historical thinking blocks and never forwards the thinking parameter

1 participant