Skip to content

[Bug]: ChatGPT app (iOS) in Remote Mode renders the routed model raw chain of thought #6122

Closed

Description

@robin-bially

Client or integration

Other (ChatGPT app for iOS, Codex "Remote Mode", pointed at a Codex host that routes through OpenCodex)

Area

Streaming

Summary

A routed provider's chain of thought reaches clients on the raw reasoning content channel, and the ChatGPT app for iOS renders that channel inline in the transcript while it streams. The desktop Codex app shows only the thinking animation for the same stream, so the visible difference is how each client renders response.reasoning_text.*.

Observed with opencode-go/deepseek-v4.1-flash (adapter openai-chat). OpenCodex emits that model's reasoning as response.reasoning_text.delta plus a reasoning item of the shape {"type":"reasoning","summary":[],"content":[{"type":"reasoning_text","text":"..."}]}, and emits no response.reasoning_summary_text.* frames for this route. A client that renders the raw content channel therefore shows the chain of thought, while a client that renders authored summaries shows nothing. Raw reasoning is never relabelled as a provider-authored summary (by design), and hideThinkingSummary is the only switch that hides it — it hides authored summaries at the same time. showThinkingSummary moves in the opposite direction.

Expected: an operator can keep one provider's raw chain of thought off the client wire while provider-authored summaries stay visible (for example for native OpenAI models, which author real summaries).

Reproduction

  1. Route a model whose endpoint returns thinking as reasoning_content (here opencode-go/deepseek-v4.1-flash, adapter openai-chat).

  2. Stream a Responses request with a validated effort and reasoning.summary omitted or "auto":

    curl -N -X POST http://127.0.0.1:10100/v1/responses -H 'content-type: application/json' -d '{"model":"opencode-go/deepseek-v4.1-flash","input":"Reply with exactly: pong","stream":true,"max_output_tokens":64,"reasoning":{"effort":"low","summary":"auto"}}'

  3. Observe that only response.reasoning_text.delta frames carry the thinking (4 in the capture below) and that no response.reasoning_summary_text.* frame appears at all; the finished item carries summary: [] with the text on the content channel.

  4. Open the same Codex thread from the ChatGPT app for iOS in Remote Mode: the chain of thought is rendered inline (screenshot below). The desktop app shows only the thinking animation for the same thread.

  5. Note the only way to suppress it today: reasoning.summary: "none" (or omitting the summary without a validated active effort), which also suppresses any authored summary.

Version

2.68.0

Operating system

Host: macOS 27.0 (arm64). Viewer: ChatGPT app for iOS in Remote Mode.

Provider and model

opencode-go / deepseek-v4.1-flash (adapter openai-chat)

Logs or error output

Probe from step 2 (summary "auto"):

4  response.reasoning_text.delta
0  response.reasoning_summary_text.delta
response.output_item.done item: {"type":"reasoning","summary":[],"content":[{"type":"reasoning_text","text":"We need answer exactly \"pong\"..."}]}

Same probe with summary: "none":

0  response.reasoning_text.delta
response.output_item.done item: {"type":"reasoning","summary":[],"encrypted_content":"ocxr1:..."}

Screenshots and supporting files

ChatGPT app for iOS in Remote Mode, showing the routed model's chain of thought rendered as text in the transcript while it is generated:

ChatGPT app in Remote Mode rendering the routed model's raw chain of thought

Redacted configuration

Redacted provider row. Nothing in it can keep the raw channel off the client wire today:

{
  "providers": {
    "opencode-go": {
      "adapter": "openai-chat",
      "baseUrl": "https://opencode.ai/zen/go/v1",
      "apiKey": "<redacted>"
    }
  }
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. coderabbitai commented on Sep 27, 2026

    @coderabbitai
    Contributor
    ⚠️ Possible Duplicate Issue(s)

    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. added
    bugSomething isn't working
    streamingSSE, WebSocket, terminal stream frames
    on Sep 27, 2026
  3. robin-bially commented on Sep 27, 2026

    @robin-bially
    ContributorAuthor

    Related: #2064 reported the same symptom (Codex Remote on iOS painting private thinking) and was closed as fixed-on-`dev` via #2016 (`56752d7c5`, "route raw reasoning through the expandable summary channel").

    That remedy was the raw-to-summary relabel: raw reasoning was rewritten into `summary_text`, which the client rendered like any authored summary. It was intentionally reverted on 2026-09-12 by `533d57828` ("separate raw reasoning from provider summaries"), which deleted `src/server/responses-reasoning-summary-rewrite.ts` and moved raw reasoning to the content channel it belongs to: `reasoning_raw_delta` now streams as `response.reasoning_text.delta` and finishes as `{"type":"reasoning","summary":[],"content":[{"type":"reasoning_text","text":"…"}]}`.

    So this is not the old escape path returning; it is the deliberate provenance split. Raw reasoning is neither an authored summary nor relabelled as one, and the display decision sits with the client — the desktop app renders the thinking band only, the ChatGPT app in Remote Mode renders the content channel inline. What is missing is the operator-side choice: `hideThinkingSummary` hides raw and authored reasoning together, and `showThinkingSummary` only moves the other way.

    A PR that adds a provider option suppressing just the raw channel (`hideRawReasoning`), keeping authored summaries visible and the hidden text in the `ocxr1` replay envelope, will reference this issue.

  4. lidge-jun commented on Sep 27, 2026

    @lidge-jun
    Owner

    Release train 4 triage: this is held for the next train. The report is clear, and #6123 proposes a per-provider hideRawReasoning switch for it. Both arrived after this train's review window closed. That PR changes what reaches the client wire for reasoning, so it gets a full review of the config surface, docs, and streaming coverage in the next train, not a late merge into this release.

  5. lidge-jun commented on Sep 28, 2026

    @lidge-jun
    Owner

    Fixed on dev by #6170 (a1fb174): a provider can set hideRawReasoning: true so a routed model's raw chain of thought is not rendered by clients such as the iOS app in Remote Mode, while provider-written summaries still stream. It is off by default. It ships in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstreamingSSE, WebSocket, terminal stream frames

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions