feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(codex): add provider-native voice mode - #8324

Closed
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice
Closed

feat(codex): add provider-native voice mode#8324
PengLx wants to merge 8 commits into
pingdotgg:mainfrom
PengLx:feat/codex-native-voice

Conversation

@PengLx

@PengLxPengLx commented Aug 26, 2026

Copy link
Copy Markdown

What Changed

  • add a microphone control to persisted Codex threads in the web and desktop clients
  • negotiate Codex app-server realtime v3 sessions through typed T3 RPCs
  • send only SDP through T3 while microphone and response audio travel directly over WebRTC
  • clean up voice sessions on stop, route/provider changes, peer failure, and provider shutdown
  • document browser security, provider, mobile, and remote-connection behavior

Why

Codex now exposes provider-native realtime voice, but T3 Code had no way to start it from the current thread. This adds the smallest provider-bound path: the existing Codex process owns the realtime session, T3 routes signaling, and clients own ephemeral media. Raw audio is neither proxied through the T3 WebSocket nor persisted by T3.

This is distinct from global prompt dictation in #5213: voice here is a live two-way Codex session attached to the current thread. Signed macOS builds also need the microphone entitlement tracked in #5321; this PR intentionally does not duplicate that contributor's separate platform change.

UI Changes

Before — persisted Codex thread composer

Before: Codex thread composer without a voice control

After — idle microphone action

After: Codex thread composer with the microphone action beside Send

Rendered live control — connection, mute, and end controls

Rendered live Codex voice control showing connection status, mute, and end controls

The control has no animation or timing behavior. The live-state screenshot renders the real composer component without capturing microphone audio.

Surface Decisions

  • Web: supported; remote pages require HTTPS for browser microphone access
  • Desktop: supported through the web renderer; signed macOS microphone access depends on fix(desktop): allow microphone access #5321
  • Mobile: native iOS and Android controls are intentionally not included in this focused PR
  • Providers: Codex implements the optional adapter capability; Claude, Cursor, Grok, and OpenCode remain unsupported
  • Connections: local, relay, and tunnel signaling use the existing environment RPC path; media remains direct WebRTC client-to-OpenAI

Verification

  • vp test run on 6 focused files: 141 tests passed
  • targeted typecheck for contracts, client-runtime, server, and web
  • targeted lint and formatting checks for changed files
  • isolated real-client UI pass for idle, rendered-live-control, narrow-layout, and denied-permission states; no microphone audio was captured

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • No animation or timing behavior requires a video; the live interaction state is shown above

Built with Codex (gpt-5.6-sol) in the Codex harness through T3 Code.

Note

Add provider-native voice mode to Codex

  • Adds startRealtimeVoice and stopRealtimeVoice to CodexSessionRuntime to manage WebRTC SDP negotiation with Codex via JSON-RPC, including concurrent-start protection, timeouts, and error handling.
  • Introduces useCodexRealtimeVoice hook and ComposerVoiceControl UI component to manage microphone access, ICE gathering, and connection state for server-backed Codex threads.
  • Adds WebSocket RPC endpoints provider.realtimeVoice.start and provider.realtimeVoice.stop to ws.ts with AuthOrchestrationOperateScope required.
  • Risk: CodexSessionRuntime now defaults realtimeVoiceNegotiationTimeoutMs to 20000ms and realtimeVoiceStopTimeoutMs to 3000ms; failure to meet these time bounds will result in timeout errors.

Macroscope summarized 5ff77a9.


Note

Medium Risk
Introduces a new authenticated RPC path and substantial Codex runtime concurrency/cleanup logic around realtime negotiation; audio bypasses T3 but mis-handled stop/start races could leave stale sessions or block retries.

Overview
Adds live Codex voice for web/desktop: the composer gets a microphone control that runs a WebRTC session (mic + oai-events data channel) while only SDP goes through new provider.realtimeVoice.start / stop RPCs with orchestration operate scope.

On the server, Codex-only optional adapter hooks route through ProviderService (session recovery on start, no-op stop when inactive). CodexSessionRuntime negotiates Codex realtime v3 (thread/realtime/start / stop) with guarded concurrent starts, answer/stop timeouts, notification handling, and cleanup on stop, interrupt, or runtime close.

The web useCodexRealtimeVoice hook owns peer connection, ICE gathering, mute, and autoplay recovery; ComposerVoiceControl is wired from ChatComposer for Codex threads (version ≥ 0.145.0). Contracts bound SDP size; docs note direct client↔OpenAI audio and no native mobile UI yet.

Reviewed by Cursor Bugbot for commit 5ff77a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitaiBot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0445dd4-1a9b-4276-a16e-06a31d8aa447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency issue found in apps/web/src/components/chat/ComposerVoiceControl.tsx: the call-site text colors never reach the lucide icons because Button's ghost variant pins --control-icon-color, so the error/destructive tones (including the red microphone documented in docs/user/providers-codex.md) render as muted foreground. See inline comments.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadpackages/contracts/src/provider.ts Outdated
Comment threadpackages/client-runtime/src/state/threadCommands.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new Codex realtime voice service surface (contracts, ProviderService, CodexAdapter, CodexSessionRuntime, ws handlers, client atoms) against the Effect service conventions. Imports, service wiring, dependency acquisition, and the new ProviderRealtimeVoiceError (multi-value operation discriminator with a message derived from structural attributes) all look consistent. Two error-modeling findings below.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new composer voice control and its call site. The icon-color indirection flagged on the previous run is now fixed ([--control-icon-color:currentColor] is applied on all three buttons). Two remaining findings below: a control that renders enabled but is inert on draft routes, and a status dot bypassing the semantic color token.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ComposerVoiceControl.tsx Outdated
Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
@macroscopeapp

macroscopeappBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial live voice workflow across browser microphone/WebRTC handling, new authenticated RPCs, provider routing, and Codex session lifecycle coordination. It also changes an authentication package and handles sensitive microphone/audio flows, so the production blast radius warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Aug 26, 2026
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac1563e. Configure here.

Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment threadapps/server/src/provider/Layers/CodexSessionRuntime.ts Outdated
Comment threadapps/web/src/hooks/useCodexRealtimeVoice.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new realtime-voice RPC boundary discards the underlying failure instead of preserving it as cause. Everything else in the changed Effect service scope (namespace subpath imports, Schema.TaggedErrorClass failures with structured attributes and attribute-derived messages, the requireSession + mapCodexRuntimeError pass-through pattern in CodexAdapter, and dependency acquisition in makeCodexSessionRuntime / makeProviderService) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/ws.ts

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the live voice control can be unmounted while the session is still streaming. See the inline comment.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new composer voice placement logic. The earlier icon-color, bg-success token, and route-gate items from previous runs look addressed.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes (ComposerVoiceControl, its ChatComposer mount points, and useCodexRealtimeVoice). Icon-color indirection, the bg-success token, the render gate, and the duplicate live-control case from earlier rounds all look resolved. One layout nit remains on the new fallback row.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

We are not adding provider-native voice mode. The provider protocol and client support cost is too high for this path in the current product set.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@PengLx@t3dotgg@Yscoshaow