Skip to content

fix(responses): route raw reasoning through the expandable summary channel (lands #2007) - #2016

Merged
lidge-jun merged 5 commits into
devfrom
codex/land-2007
Aug 18, 2026
Merged

fix(responses): route raw reasoning through the expandable summary channel (lands #2007)#2016
lidge-jun merged 5 commits into
devfrom
codex/land-2007

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

Lands contributor PR #2007 (AlinJiang) on current dev: content-channel raw reasoning is normalized through the expandable summary channel on the bounded-JSON path, matching the SSE rewrite. The one-hunk conflict against today's backfillResponsesFieldsJson (#1941) is composed: repair → model rewrite → field backfill → summary rewrite.

Verification

  • bridge + reasoning-summary-rewrite + passthrough + field-backfill suites: 84/0
  • tsc --noEmit clean

Checklist

  • Original PR's regression tests included
  • Typecheck green
  • No GUI change (no screenshot required)

AlinJiang and others added 5 commits August 18, 2026 02:06
…annel

Codex renders the expandable reasoning trace from the Responses reasoning
item summary[] channel only. Chat-completions providers (DeepSeek-style)
deliver thinking as raw reasoning_content, which the bridge and the native
Responses passthrough both shaped as summary:[] + content:[reasoning_text],
so routed turns showed the timer with nothing to expand (issue #45).

Route reasoning_raw_delta through the same summary path as thinking_delta
in the streaming and buffered bridges, and add a payload rewrite for the
native-Responses passthrough (DeepSeek /responses) that converts
reasoning_text.delta/done and reasoning item content into the summary
channel. Internal replay-cache handoff and hideThinkingSummary suppression
are preserved.

Tests: bridge summary-channel shape + hide parity, rewrite unit tests,
replay-cache regressions all pass; tsc clean.
…model gate

CodeRabbit follow-ups:
- Apply the summary-channel rewrite to the bounded-JSON passthrough path too
  (plain JSON answers and forced JSON-to-SSE reframing both build from
  clientJson), handling both the SSE completed-event shape and the bare
  response document shape DeepSeek returns for stream:false.
- Return the original reasoning item untouched when it carries no
  reasoning_text content, so summary-channel items are never cleared.
- Normalize both sides of the preserveReasoningContentModels match so
  mixed-case configured ids still gate the rewrite.
…writes

CodeRabbit follow-up: when the client asked for hidden thinking
(no reasoning.summary in the request), the passthrough summary-channel
rewrite must not surface upstream reasoning as visible summary output.
Gate both the SSE payload rewrite and the bounded-JSON rewrite on
parsed.options.hideThinkingSummary !== true, and cover the four
hidden/visible x SSE/JSON combinations with handleResponses integration
tests.
# Conflicts:
#	src/server/responses/core.ts
@lidge-jun
lidge-jun merged commit 891c828 into dev Aug 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 18, 2026
lidge-jun added a commit that referenced this pull request Aug 19, 2026
…d persist visibility (#2078)

* docs(devlog): #2064 RCA — fixed on dev by #2016, version-ancestry proven

* fix(replay): scope durable thought signatures per credential and bound persist visibility

The durable thought-signature store keyed entries by thread + destination +
model but not by credential, so account A's Gemini signatures could replay
under account B on the same destination (#1926 gap 1). Keys now carry a
salted-HMAC credential identity (installation-local salt persisted beside the
store, full 256-bit output — never an unsalted digest of key material) derived
from the persisted OAuth account-slot id, the API key, or the Codex account
handle; a scope that cannot produce one fails closed instead of sharing a
durable slot. STORE_VERSION 3 -> 4 drops old rows on load (not upgradable —
no credential info was recorded).

Gap 2: terminal frames could become externally visible before the queued
signature persist settled. All async terminal paths (completed, truncation
and adapter-EOF incompletes, failed) and both buffered JSON returns now await
a bounded (250ms) durability barrier; the sync stall-timeout kill path keeps
the pre-existing best-effort behavior, documented in place.

Closes #1926

* fix(replay): wire durable lookup at adapter serialization; trust only pool account handles; harden salt perms

Security-review fold-back: (1) the parser's durable lookup ran before the
credential scope was bound, so the store was write-only at runtime — the
google adapter now falls back to the durable store at serialization time,
when the scope identity exists (regression-pinned); (2) the codex-forward
durable handle no longer accepts the client-supplied chatgpt-account-id
header (trusted pool context only; direct-forward fails closed); (3) the
salt file re-asserts 0600 on every load.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants