Skip to content

fix(conversations): resolve turn content OmniRoute never sends back to the client - #12447

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.51from
hartmark:fix-conversation-turn-content-resolution
Sep 3, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.51from
hartmark:fix-conversation-turn-content-resolution

Conversation

@hartmark

@hartmark hartmark commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

/dashboard/conversations's turn tree showed many turns as "Tool (empty)"/"Assistant (empty)" for genuine-continuation conversations, even though the actual content clearly existed and was served correctly.

Why This Change Was Made

resolveTurnDisplayContent only ever read a turn node's originating clientRawRequest.body — fine for a full-history-resend conversation (every later request's body eventually contains everything), but a genuine-continuation turn's own request only ever carries the NEW delta. That silently left the model's own generated tool_use/text turns unresolved — their content never appears in any request body, only in a response.

Verified against a real 133-node continuation conversation: request-only resolution left 131/133 nodes unresolved.

Added two more sources, read from the SAME already-loaded artifact (no extra I/O):

  • the call's own clientResponse.output (the model's own generated turn — 131 → 76 unresolved)
  • the call's own providerRequest.body (the server-reconstructed full history actually forwarded upstream for non-Responses-native providers, Chat Completions messages shape) — best-effort, translated text can differ byte-for-byte from what was originally hashed, so this doesn't close 100%, but it does close the "Tool (empty)" case entirely (76 → 21, all 112 tool nodes resolved; the remaining 21 are plain user/assistant text turns old enough to predate both available artifacts — genuinely lost history, not a resolution gap).

User Impact

The conversation tree now renders real content for tool calls and assistant turns in continuation-mode conversations instead of empty placeholders.

Evidence

Verified against a real production conversation (133 turn nodes): before/after unresolved-node counts (131 → 76 → 21) computed by replaying the exact resolution logic against the real stored artifacts.

🤖 Generated with Claude Code

…o the client

resolveTurnDisplayContent only ever read a turn node's originating
clientRawRequest.body -- fine for a full-history-resend conversation
(every later request's body eventually contains everything), but a
genuine-continuation turn's own request only ever carries the NEW delta
(see responsesContinuationStore.ts). That silently rendered the model's own
generated tool_use/text turns as "Tool (empty)"/"Assistant (empty)" in
the /dashboard/conversations tree -- their content never appears in any
request body, only in a response.

Verified against a real 133-node continuation conversation: request-only
resolution left 131/133 nodes unresolved.

Added two more sources, read from the SAME already-loaded artifact (no
extra I/O):
- the call's own clientResponse.output (the model's own generated turn --
  132 -> 76 unresolved)
- the call's own providerRequest.body (the server-reconstructed full
  history actually forwarded upstream for non-Responses-native providers,
  Chat Completions messages shape) -- best-effort, translated text can
  differ byte-for-byte from what was originally hashed, so this doesn't
  close 100% but does close the "Tool (empty)" case entirely (76 -> 21,
  all 112 tool nodes resolved; the remaining 21 are plain user/assistant
  text turns old enough to predate both available artifacts -- genuinely
  lost history, not a resolution gap).
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 2, 2026
… OmniRoute never sends back to the client) into dev/omniroute-dev-combined
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 2, 2026
… OmniRoute never sends back to the client) into dev/omniroute-dev-combined
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 2, 2026
… OmniRoute never sends back to the client) into dev/omniroute-dev-combined
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 2, 2026
… OmniRoute never sends back to the client) into dev/omniroute-dev-combined
…lexity

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw

Copy link
Copy Markdown
Owner

sweep-reds / babysit: No new ESLint warnings is inherited from base-red #12581 — CodeQL ratchet 12 open > baseline 11 (repo-wide Security alerts, not this diff). No unused/@eloqnt findings here, so no ESLint code change.

Own FQG (complexity + open-sse typecheck TS2345) and API Route Typecheck are fixed in bae2cab01f by splitting conversationTurnContent.ts helpers and typing turns as the canonical role union. Did not merge origin/release/v3.8.51.

@diegosouzapw

Copy link
Copy Markdown
Owner

sweep-reds round 6 / babysit: remaining FQG after the typecheck/complexity split bae2cab01f is inherited from base-red #12581 — not this turn-content diff. Did not merge origin/release/v3.8.51.

  • file-size: src/sse/handlers/chat.ts: 2434 > congelado 2424 — this PR does not touch chat.ts (one file: conversationTurnContent.ts).
  • complexity-ratchets: CI merge-base 7802f6ea reported 118 changed files; local three-dot is 1. Listed regressions (attemptLogging.ts, tlsClientBase.ts, tlsClient.ts) are not this PR's file.

STOP on inherited FQG. Own split already landed.

@diegosouzapw
diegosouzapw merged commit 7881e7e into diegosouzapw:release/v3.8.51 Sep 3, 2026
15 of 16 checks passed
@hartmark
hartmark deleted the fix-conversation-turn-content-resolution branch September 3, 2026 18:05
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…o the client (diegosouzapw#12447)

Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51` (já com a leva anterior dentro): os nove boardaram **sem um único conflito**, `typecheck:core` limpo e **80/80** nos 6 arquivos de teste que os PRs trazem.

O crescimento de arquivo próprio da leva foi rebaselinado num registro datado (`_rebaseline_2026_09_03_hartmark_batch`): `combos/page.tsx` 5012→5018 (diegosouzapw#12355, tratar o estado degradado quando o bundling de tiktoken de um provider sem relação falha) e `open-sse/services/combo.ts` 4023→4036 (diegosouzapw#12338, os fixes do universal-handoff). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.

Obrigado, @hartmark.
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