Skip to content

fix(voice): preserve speech and model work - #589

Merged
kev (kevchoi) merged 10 commits into
mainfrom
kevchoi/fix-unowned-voice-speech
Nov 10, 2026
Merged

kev (kevchoi) merged 10 commits into
mainfrom
kevchoi/fix-unowned-voice-speech

Conversation

@kevchoi

@kevchoi kev (kevchoi) commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

working with David Elner (@delner) on the last mile portion for cascaded/gpt-realtime traces


LiveKit records generated output in llm_response and played speech in agent_speech. Represent voice model calls as existing llm_analysis work so the thread displays played speech once, while generated messages, tool calls, usage, and timing remain inspectable. No VoiceTurnRole, public schema additions, or UI changes.

Also preserve unowned user_speech intervals as empty standalone turns when the session has no explicit user turns. Keep their IDs and actual intervals without inventing transcripts or replies. Other unowned modeled voice spans are skipped; invalid explicit turn references retain diagnostics. Loaded empty requests remain hidden by the current UI.

When no explicit or inherited turn.id exists, use the nearest structural user_turn or agent_turn ancestor in the same session. The search is bounded. Missing ownership is skipped, and invalid explicit IDs remain nonfatal diagnostics; healthy spans continue rendering. No timestamp or text matching.

The Realtime fixture covers the attached conversation’s greeting, tool exchange, and closing reply in one fixture and regression test. Expected turns live in JSON; the shared runner checks batching, body/header imports, randomized load order, and coverage. The same fixture is also tested with all turn.id fields removed. The orphan-speech and tool fixtures cover separate ownership cases. Implementation reference: Python SDK #1069.

Validation

  • All 105 trajectory tests pass, including the new Realtime regression and existing orphan-speech coverage. Formatting and typed-boundary checks pass.
  • Fresh Playwright captures compare 03f15aa6 with 13a055ea: the supplied trace is unchanged; a copy with only turn.id removed regains assistant speech and model work. Both runs have no browser page errors.
  • Independent review found no blockers or dependencies on fix(voice): show played speech once #591, which is closed.

The hosted app still needs its Lingua pin/build updated. Audio-only bubbles and per-turn playback are outside this change.

Screenshots

Latest change, 03f15aa6 → 13a055ea, with the same app and viewport.

Supplied trace with IDs intact: unchanged.

Original trace before
Open full size

Original trace after
Open full size

Same trace with only turn.id removed, before: assistant speech and model work are missing.

Missing turn IDs before
Open full size

After: structural ownership restores the conversation and model work.

Missing turn IDs after
Open full size

@kevchoi
kev (kevchoi) marked this pull request as ready for review November 10, 2026 17:41
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

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

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T20:44:27.576177Z 13a055e New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6b6277936

ℹ️ 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 (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3bc75676a

ℹ️ 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 (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

@kevchoi

kev (kevchoi) commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

actually, holding off on merging this since I believe the SDK might fix this

@kevchoi kev (kevchoi) changed the title fix(voice): ignore unowned user speech intervals fix(voice): preserve unowned speech intervals Nov 10, 2026
@kevchoi kev (kevchoi) changed the title fix(voice): preserve unowned speech intervals fix(voice): preserve speech and model work Nov 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13a055ea95

ℹ️ 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 (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

Comment on lines +245 to +248
&& (owners[&index].voice_turn.is_some()
|| session_of[index].is_some_and(|session| user_sessions.contains(&session)))
{
plan.ignored.insert(index);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate speech references before skipping them

When a user_speech span has an explicit or inherited turn.id that is unresolved or points to a non-turn, voice_turn.is_some() sends it through this continue before the resolver below can record an import failure. Fresh evidence in this commit is that it adds a preservation path for unowned user_speech and states invalid explicit references retain diagnostics; validate these references before omitting the spans.

AGENTS.md reference: AGENTS.md:L15-L15

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine; skip if we have an invalid turn

@kevchoi
kev (kevchoi) merged commit 9efdbac into main Nov 10, 2026
23 checks passed
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