Skip to content

VS Code extension hides reasoning summaries even when app-server emits them #30793

Description

@ODtian

Summary

The VS Code Codex extension does not render reasoning summaries for normal turns, even when model_reasoning_summary = "detailed" is configured and the bundled codex.exe app-server produces and returns non-empty reasoning summaries.

In the affected setup, the TUI can show reasoning summaries, and the app-server/session data contains them, but the VS Code webview only shows a generic Thinking / 正在思考 state unless the shipped webview bundle is patched locally.

Environment

  • Product: VS Code extension, openai.chatgpt
  • Extension version: 26.623.70822
  • Extension package: openai.chatgpt-26.623.70822-win32-x64
  • Platform: Windows x64
  • Bundled app-server: bin/windows-x86_64/codex.exe app-server
  • Model used for repro: gpt-5.5, reasoning effort shown in UI as xhigh / 超高
  • Relevant config:
model_reasoning_summary = "detailed"
model_reasoning_effort = "xhigh"

What happens

  1. Start a new Codex conversation in the VS Code extension.
  2. Ask a prompt that requires reasoning but no tools, for example a combinatorics / candy-counting problem.
  3. The UI shows only a generic thinking row (Thinking / 正在思考) and does not show the streamed reasoning summary text.
  4. The same turn/session data contains non-empty reasoning summaries when inspected through the app-server/session files.

Expected behavior

If the configured/effective reasoning summary mode is detailed, and the app-server emits reasoning summary items, the VS Code extension should render them in the conversation UI.

For a normal no-tool turn, a sequence like this should be visible:

userMessage
reasoning summary
agentMessage

The reasoning item should not require an exploration/tool group to be displayed.

Evidence: app-server/config path is working

The app-server side appears to be producing the correct data.

Observed in local debugging:

  • config/read returns model_reasoning_summary = "detailed".
  • App-server logs for test turns show effective reasoning summary as detailed, e.g. summary: Some(Detailed).
  • The session JSONL contains multiple agent_reasoning summaries for the turn.
  • thread/read with turns included returns reasoning items with non-empty summary arrays.

Example local test sessions used for debugging:

019f19aa-abb3-7850-9613-d56347389199
019f19b2-f719-7a73-9342-5634a0a07c14

The second session contained 14 reasoning summary sections in the session JSONL / thread/read data, but the unpatched VS Code UI still did not show them.

Static analysis of the shipped VS Code webview bundle

I inspected the installed extension bundle under:

.vscode/extensions/openai.chatgpt-26.623.70822-win32-x64/webview/assets/

The shipped webview appears to have multiple issues in the reasoning-summary path.

1. turn/start can default summary to none

The minified request-building code contains a fallback equivalent to:

summary = explicitSummary ?? threadSummary ?? configSummary ?? "none";

Because turn/start.summary is an override field, sending summary: "none" is not the same as omitting the field. It can explicitly disable summaries and override ~/.codex/config.toml.

Based on the public protocol source, summary is documented as an override:

/// Override the reasoning summary for this turn and subsequent turns.
pub summary: Option<ReasoningSummary>,

So the client should omit summary unless the user explicitly selects a summary override.

Suggested behavior:

const summaryOverride = explicitUserSummarySelection;

if (summaryOverride !== undefined) {
  params.summary = summaryOverride;
}

Do not turn undefined into "none".

2. Standalone reasoning items are dropped by render grouping

The shipped grouping logic in split-items-into-render-groups-*.js appears equivalent to:

if (item.type === "reasoning") {
  if (currentExplorationGroup) {
    currentExplorationGroup.push(item);
  }
  continue;
}

For no-tool/no-exploration turns, currentExplorationGroup is absent, so the reasoning item is skipped entirely.

A local patch that fixes display is equivalent to:

if (item.type === "reasoning") {
  if (currentExplorationGroup) {
    currentExplorationGroup.push(item);
  } else {
    groups.push({ kind: "item", item });
  }
  continue;
}

After this patch, no-tool reasoning summaries start appearing.

3. The main conversation item renderer maps reasoning to null

The shipped local conversation item renderer appears to have a branch equivalent to:

case "reasoning":
  return null;

A local patch equivalent to the following makes the reasoning row render:

case "reasoning":
  return (
    <ReasoningItem
      item={item}
      conversationId={conversationId}
      cwd={cwd}
      hideCodeBlocks={hideCodeBlocks}
    />
  );

4. Reasoning title handling can drop information

The existing reasoning renderer seems to strip the leading bold/heading title from the reasoning body. That is okay only if the title is rendered elsewhere. In the current UI path, this can hide the first summary title.

A simple safe behavior is to render the full markdown summary body as provided. A better UI would render each summary section as a structured section, but that likely needs access to the original summary array before it is joined into one string.

5. Collapse behavior should depend on expanded state after completion

When forcing reasoning visible locally, it is easy to accidentally make the disclosure button ineffective. The completed-state visibility should depend on the expanded state, roughly:

const bodyVisible = isStreaming ? Boolean(streamingContent) : expanded;

not simply:

const bodyVisible = Boolean(content);

Why this looks frontend-specific

The app-server protocol and data model already include reasoning items:

  • reasoning items contain { id, summary, content }.
  • item/reasoning/summaryTextDelta streams readable reasoning summaries.
  • item/reasoning/summaryPartAdded marks boundaries between summary sections.

The data is present in session storage and via thread/read; the VS Code webview path is where it gets overridden/dropped/not rendered.

Local workaround that confirmed the diagnosis

Patching the installed webview bundle locally made summaries appear. The effective local workaround was:

  1. Do not let the frontend fall back to summary: "none".
  2. Do not drop standalone reasoning items in the render grouping function.
  3. Render reasoning items in the main conversation item renderer instead of returning null.
  4. Preserve the full markdown body for reasoning summaries.
  5. Keep completed reasoning default-expanded but controlled by the disclosure/expanded state.

This made the same test sessions display the summary text in VS Code.

Suggested fix

In the VS Code extension frontend/webview source:

  1. Treat turn/start.summary as an override only. Omit it unless the user explicitly selected a summary mode.
  2. In render grouping, emit standalone reasoning items as normal renderable items when no exploration/tool group is active.
  3. Add a normal reasoning case to the main conversation item renderer.
  4. Preserve titles, either by keeping the full markdown body or by rendering structured summary sections.
  5. Ensure the collapse/disclosure button controls completed reasoning body visibility.

Related note

I could not find the VS Code webview frontend source in the public openai/codex repository, so I am filing this as an issue rather than a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    app-serverIssues involving app server protocol or interfacesbugSomething isn't workingextensionIssues related to the VS Code extension

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions