Skip to content

refactor(desktop): realtime hub as default voice path + revert pill UI#8002

Open
vendz wants to merge 16 commits into
BasedHardware:mainfrom
vendz:desktop-realtime-hub-default
Open

refactor(desktop): realtime hub as default voice path + revert pill UI#8002
vendz wants to merge 16 commits into
BasedHardware:mainfrom
vendz:desktop-realtime-hub-default

Conversation

@vendz

@vendz vendz commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What

Follow-up cleanup to the merged realtime-hub PR (#7957): make the realtime voice hub the default voice path and revert the floating-bar pill redesign.

Changes

  • Always-on hub, no toggle — removed the realtimeHubEnabled opt-in. Every PTT turn routes through the hub whenever it can connect (BYOK key, or a server-minted ephemeral token for managed users); otherwise it falls back to the legacy STT cascade.
  • Single provider source — removed the duplicate Realtime Hub provider picker from the floating-bar settings; the hub now follows the existing Advanced → Voice Model picker.
  • OpenAI is the default Voice Model (GPT Realtime 2); users can switch to Gemini or Auto.
  • Reverted the floating-bar pill redesign to the pre-redesign look (flat sliver / red pulsing mic, collapse on release). Deleted VoiceActivityIndicator. Kept the agent voice-reply mic button (independent).
  • Dead-code cleanup (/simplify): dropped the orphaned audio level-tap from StreamingPCMPlayer, consolidated the hub's BYOK readiness into canConnect, removed unused RealtimeHubProvider.subtitle/CaseIterable and the empty AVSpeech delegate.

Net: +116 / −665 across 12 files.

Verification

  • Debug build clean; 13/13 desktop unit tests pass.
  • Live-verified full hub turns against a local backend for both providers: OpenAI ("The capital of France is Paris", 110 KB spoken audio) and Gemini (88 KB) — STT + reply + audio, no player errors.
  • A clean release build should be run before merge (signature changes), as usual.

Deploy note

Managed (non-BYOK) Gemini users need GEMINI_API_KEY set on the Rust desktop-backend (same as OPENAI_API_KEY); otherwise selecting Gemini falls back to STT.

🤖 Generated with Claude Code

vendz and others added 9 commits June 17, 2026 18:03
…r from Voice Model

RealtimeHubSettings no longer stores an enable flag or its own provider; the
hub is the default voice path and its provider follows the existing Advanced
'Voice Model' picker (RealtimeOmniSettings). Drops the now-unused subtitle and
CaseIterable conformance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… BYOK predicate

isActive/ensureWarm/reconnect no longer gate on the removed isEnabled toggle.
isActive now consults RealtimeHubSettings.canConnect (single source). Removes
the floating-bar pill flag writes (isVoiceThinking/Speaking/voiceLevel) and the
orphaned AVSpeech delegate; native-audio playback is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… picker

The hub is always-on and follows the existing Voice Model picker, so the
duplicate enable+provider cards are removed. Default Voice Model set to OpenAI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Users can still switch to Gemini or Auto in Advanced settings; this default
also drives the realtime hub provider.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ctivity observer

Keeps the QueryTracer wiring, router-skip/screenshot heuristics, and recordVoiceTurn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mixer RMS tap + pending-buffer tracking only fed the reverted speaking
waveform; playback (enqueue/stop/engine-restart/config-rebuild) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dev-only)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pill entry

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 17, 2026 22:08

Copilot AI 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.

Pull request overview

This PR follows up on the prior “realtime-as-hub” work by making the Realtime Hub the default push-to-talk voice path (with fallback to the legacy STT cascade when the hub can’t connect), and reverting the floating bar voice UI back to the pre-redesign visual/behavior.

Changes:

  • Default the “Voice Model” setting to GPT Realtime 2 and route hub provider selection through that single picker (removing hub enable/provider UI).
  • Revert floating bar voice UI (delete VoiceActivityIndicator, remove thinking/speaking state plumbing, collapse on PTT release).
  • Simplify audio playback plumbing by removing the output-level tap and “playing” edge callbacks from StreamingPCMPlayer.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
desktop/macos/Desktop/Sources/RealtimeOmni/RealtimeOmniSettings.swift Default provider now GPT Realtime 2 via UserDefaults registration.
desktop/macos/Desktop/Sources/MainWindow/Pages/SettingsPage.swift Removes hub toggle/provider settings; defaults Voice Model picker to GPT Realtime 2.
desktop/macos/Desktop/Sources/FloatingControlBar/VoiceActivityIndicator.swift Deletes the pill redesign indicator implementation.
desktop/macos/Desktop/Sources/FloatingControlBar/StreamingPCMPlayer.swift Removes level tap + playback state callbacks; simplifies buffer scheduling/stop.
desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubSettings.swift Makes hub provider derived from RealtimeOmniSettings (no separate picker).
desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubSession.swift Updates session documentation to reflect BYOK vs ephemeral token auth.
desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubController.swift Removes enable-gating; simplifies UI state handling for hub turns.
desktop/macos/Desktop/Sources/FloatingControlBar/PushToTalkManager.swift Collapses bar on hub commit; reintroduces imperative resize control.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarWindow.swift Removes voice-activity observer; relies on listening state + explicit resizes.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarView.swift Reverts to thin idle bar + listening UI with pulsing mic.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarState.swift Removes thinking/speaking/level state and derived isVoiceActive/voiceActivity.
desktop/macos/CHANGELOG.json Updates unreleased note to reflect the new (default) voice hub behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to 66
private init() {}

/// The hub provider follows the user's "Voice Model" choice in Advanced settings —
/// there is no separate hub picker. The two map 1:1 (same underlying models), and
/// `.auto` is already resolved to a concrete provider by `effectiveProvider`.
var provider: RealtimeHubProvider {
get {
let raw = UserDefaults.standard.string(forKey: providerKey)
return raw.flatMap(RealtimeHubProvider.init(rawValue:)) ?? .openai
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: providerKey)
NotificationCenter.default.post(name: .realtimeHubSettingsDidChange, object: nil)
switch RealtimeOmniSettings.shared.effectiveProvider {
case .gptRealtime2: return .openai
case .geminiFlashLive, .auto: return .gemini
}
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26c445b7c2

ℹ️ About Codex in GitHub

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

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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

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

Comment on lines +62 to +64
switch RealtimeOmniSettings.shared.effectiveProvider {
case .gptRealtime2: return .openai
case .geminiFlashLive, .auto: return .gemini

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Rewarm the hub when Voice Model changes

With the hub provider now derived from RealtimeOmniSettings.shared.effectiveProvider, changing Advanced → Voice Model no longer notifies the hub: the picker only mutates @AppStorage/refreshes Auto, while RealtimeHubController.setup still observes only .realtimeHubSettingsDidChange. For managed non-BYOK users this leaves the old warm session in place; after switching providers, isActive becomes false because sessionProvider no longer matches and canConnect is false, so every PTT turn falls back to the legacy cascade until something else restarts/rewarms the hub. Please post/observe the realtime omni settings change and reconnect the hub when this provider source changes.

Useful? React with 👍 / 👎.

Comment on lines +1054 to +1055
} else if !barState.isVoiceListening && wasListening {
FloatingControlBarManager.shared.resizeForPTT(expanded: false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve notification geometry when PTT collapses

If a proactive notification is visible while the user is holding PTT, releasing PTT takes this collapse branch and resizes the panel to the tiny PTT sliver even though currentNotification is still set. The notification presenter allows this state, and the previous reactive collapse guarded currentNotification == nil, so this regression leaves the notification mounted but clipped until it times out/dismisses. Skip the PTT collapse, or resize back to the notification dimensions, when barState.currentNotification is non-nil.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes the Realtime Voice Hub the unconditional default voice path (removing the opt-in toggle), reverts the floating-bar pill UI to the pre-redesign look, and removes the supporting state machinery (VoiceActivityIndicator, isVoiceThinking/isVoiceSpeaking/voiceLevel, the Combine-based resize observer, and the StreamingPCMPlayer level tap).

  • Always-on hub: RealtimeHubSettings.isEnabled is removed; the hub activates for any user who can authenticate (BYOK key or managed ephemeral token), falling back to the legacy STT cascade otherwise.
  • Provider consolidation: the separate hub provider picker is deleted; RealtimeHubSettings.provider is now computed from RealtimeOmniSettings.effectiveProvider, and the default Voice Model moves from .auto to .gptRealtime2.
  • UI revert: VoiceActivityIndicator is replaced with a simple red circle + mic icon; the bar collapses on PTT release rather than staying open through the reply.

Confidence Score: 3/5

Two issues in the controller need fixing before the always-on hub ships cleanly to all users.

The notification wiring between RealtimeOmniSettings and RealtimeHubController is broken: changing the Voice Model in settings has no runtime effect for BYOK users because the hub listens for a notification that is now never posted. Separately, if the hub session errors while the user is still holding PTT, the bar is left expanded because exitVoiceUI() clears the listening flag without triggering a resize, and the imperative resize path in updateBarState() then sees no transition to act on. Both are in the hot path of the feature this PR is promoting to default-on.

RealtimeHubController.swift (notification registration and exitVoiceUI resize gap) and RealtimeHubSettings.swift (the notification name that is now dead).

Important Files Changed

Filename Overview
desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubController.swift Removes opt-in toggle, AVSpeech delegate, and speaking/thinking state flags. Two issues: settingsChanged() observes a notification never posted (provider switch silently no-ops for BYOK users), and exitVoiceUI() can leave the bar expanded on session error during PTT hold.
desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubSettings.swift Collapses isEnabled + separate provider store into a computed provider derived from RealtimeOmniSettings. realtimeHubSettingsDidChange is kept but never posted — root cause of the controller reconnect issue.
desktop/macos/Desktop/Sources/FloatingControlBar/PushToTalkManager.swift Switches from reactive Combine-observer-driven resize to imperative updateBarState() calls. Correct for normal PTT-release path; edge case when exitVoiceUI() pre-clears isVoiceListening before updateBarState() runs.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarWindow.swift Removes 54-line reactive voice-activity observer. Adds resizeForPTT manager delegate. Idempotent size-check removed; expand now always animated.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarState.swift Removes VoiceActivity enum and isVoiceThinking/isVoiceSpeaking/voiceLevel properties. Straightforward cleanup.
desktop/macos/Desktop/Sources/FloatingControlBar/FloatingControlBarView.swift Reverts voice indicator to red circle + mic icon. UI-only, no logic concerns.
desktop/macos/Desktop/Sources/FloatingControlBar/StreamingPCMPlayer.swift Removes audio-level tap and buffer-tracking machinery. Clean enqueue-and-forget player.
desktop/macos/Desktop/Sources/FloatingControlBar/VoiceActivityIndicator.swift Deleted — 199-line SwiftUI indicator removed as part of UI revert.
desktop/macos/Desktop/Sources/MainWindow/Pages/SettingsPage.swift Removes hub toggle/provider cards. Changes realtimeOmniProvider default from .auto to .gptRealtime2.
desktop/macos/Desktop/Sources/RealtimeOmni/RealtimeOmniSettings.swift Default provider changed from .auto to .gptRealtime2. Consistent with PR intent.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant PTTManager as PushToTalkManager
    participant HubCtrl as RealtimeHubController
    participant HubSettings as RealtimeHubSettings
    participant OmniSettings as RealtimeOmniSettings
    participant Session as RealtimeHubSession
    participant Bar as FloatingBarWindow

    User->>PTTManager: PTT press
    PTTManager->>HubCtrl: isActive?
    HubCtrl->>HubSettings: canConnect (BYOK key?)
    HubSettings->>OmniSettings: effectiveProvider
    OmniSettings-->>HubSettings: .gptRealtime2 or .geminiFlashLive
    HubCtrl-->>PTTManager: "true (BYOK) or session!=nil (managed)"
    PTTManager->>HubCtrl: beginTurn()
    PTTManager->>Bar: updateBarState() resizeForPTT expanded true
    User->>PTTManager: PTT release
    PTTManager->>HubCtrl: commitTurn()
    PTTManager->>Bar: updateBarState() resizeForPTT expanded false
    Session-->>HubCtrl: hubDidReceiveAudio pcm24k
    HubCtrl->>HubCtrl: pcmPlayer.enqueue
    Session-->>HubCtrl: hubDidFinishTurn
    HubCtrl->>Bar: exitVoiceUI isVoiceListening already false
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant PTTManager as PushToTalkManager
    participant HubCtrl as RealtimeHubController
    participant HubSettings as RealtimeHubSettings
    participant OmniSettings as RealtimeOmniSettings
    participant Session as RealtimeHubSession
    participant Bar as FloatingBarWindow

    User->>PTTManager: PTT press
    PTTManager->>HubCtrl: isActive?
    HubCtrl->>HubSettings: canConnect (BYOK key?)
    HubSettings->>OmniSettings: effectiveProvider
    OmniSettings-->>HubSettings: .gptRealtime2 or .geminiFlashLive
    HubCtrl-->>PTTManager: "true (BYOK) or session!=nil (managed)"
    PTTManager->>HubCtrl: beginTurn()
    PTTManager->>Bar: updateBarState() resizeForPTT expanded true
    User->>PTTManager: PTT release
    PTTManager->>HubCtrl: commitTurn()
    PTTManager->>Bar: updateBarState() resizeForPTT expanded false
    Session-->>HubCtrl: hubDidReceiveAudio pcm24k
    HubCtrl->>HubCtrl: pcmPlayer.enqueue
    Session-->>HubCtrl: hubDidFinishTurn
    HubCtrl->>Bar: exitVoiceUI isVoiceListening already false
Loading

Comments Outside Diff (2)

  1. desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubController.swift, line 82-97 (link)

    P1 Hub never reconnects when Voice Model changes at runtime

    settingsChanged() is registered for .realtimeHubSettingsDidChange, but nothing in the new code ever posts that notification. The old setters on RealtimeHubSettings.isEnabled and RealtimeHubSettings.provider (which posted it) have been removed, along with the SettingsPage .onChange handlers. The provider is now derived from RealtimeOmniSettings.effectiveProvider, whose setter posts .realtimeOmniSettingsDidChange — a completely different notification name.

    If a user switches from GPT Realtime 2 → Gemini Live in Advanced → Voice Model, settingsChanged() is never invoked: sessionProvider stays .openai, and BYOK users continue routing turns to the OpenAI session until the app restarts or the socket drops.

    Fix: add .realtimeOmniSettingsDidChange to the addObserver call in setup(), or have RealtimeOmniSettings.selectedProvider.set also post .realtimeHubSettingsDidChange.

  2. desktop/macos/Desktop/Sources/FloatingControlBar/RealtimeHubController.swift, line 372-410 (link)

    P1 Bar can get stuck expanded if the hub session errors while PTT is held

    When hubDidError() fires, exitVoiceUI() sets barState.isVoiceListening = false — but the old reactive Combine observer that used to watch this flag and trigger a collapse has been removed. If the error arrives while the user is still holding PTT, barState.isVoiceListening is already false by the time the user releases. When updateBarState() then runs, it captures wasListening = false (cleared by exitVoiceUI), sees no transition, and skips the resizeForPTT(expanded: false) call. The bar stays expanded until the user hovers or triggers another resize.

    Fix: call FloatingControlBarManager.shared.resizeForPTT(expanded: false) directly inside exitVoiceUI() when barState.isVoiceListening was true at entry.

Reviews (1): Last reviewed commit: "chore(desktop): changelog — hub as defau..." | Re-trigger Greptile

Comment on lines 658 to +666
}
}

/// Resize window for PTT state (expanded when listening, compact circle when idle).
/// Expand snaps (animated:false) so the indicator + text never flash cramped while the
/// window grows; collapse animates for a smooth shrink back to the resting sliver.
func resizeForPTTState(expanded: Bool, animated: Bool = true) {
/// Resize window for PTT state (expanded when listening, compact circle when idle)
func resizeForPTTState(expanded: Bool) {
let size = expanded
? NSSize(width: FloatingControlBarWindow.expandedWidth, height: FloatingControlBarWindow.expandedBarSize.height)
: FloatingControlBarWindow.minBarSize
// Idempotent: skip when already at the target size (avoids a no-op resize).
if abs(frame.width - size.width) < 1, abs(frame.height - size.height) < 1 { return }
resizeAnchored(to: size, makeResizable: false, animated: animated)
resizeAnchored(to: size, makeResizable: false, animated: true)

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.

P2 Expand is now always animated — no-snap on PTT start

The old signature was resizeForPTTState(expanded: Bool, animated: Bool = true) and applyVoiceExpansion called it with animated: false on expand, so the window snapped open before content rendered. The new signature always passes animated: true. Given the simpler reverted UI this is likely imperceptible, but the deliberate snap-on-expand choice is now gone without a substitute.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

vendz and others added 3 commits June 17, 2026 18:42
…turn hub exit

- Observe .realtimeOmniSettingsDidChange (the live 'voice model changed' signal)
  instead of the dead .realtimeHubSettingsDidChange, so switching the Voice Model
  re-warms the hub on the newly selected provider for BYOK users.
- exitVoiceUI() now collapses the bar when it clears isVoiceListening (mid-turn
  error / silent-tap cancel) — the transition-based updateBarState() would otherwise
  see no change and leave the bar expanded. Guarded against conversation/response/
  notification/hover/onboarding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nothing posts it after the hub toggle was removed; the controller now listens to
.realtimeOmniSettingsDidChange instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The picker writes @AppStorage directly (bypassing the setter), so post the change
ourselves — this re-warms the realtime hub on the newly selected provider.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1793120ba1

ℹ️ About Codex in GitHub

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

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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

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

let provider = RealtimeHubSettings.shared.provider
if APIKeyService.byokKey(provider.byokProvider) != nil { return true }
return session != nil && sessionProvider == provider
if RealtimeHubSettings.shared.canConnect { return true }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fall back after BYOK hub auth failures

Now that the hub no longer has an opt-in toggle, treating any stored BYOK value as active means users with a stale/revoked OpenAI or Gemini key never fall back to the legacy omni/STT path. After the hub socket fails authentication, isActive still returns true solely because the key exists, so every PTT press enters hub mode and attempts the failing realtime session instead of using the cascade that managed-token failures get.

Useful? React with 👍 / 👎.

vendz and others added 4 commits June 17, 2026 19:12
… cascade fallback)

isActive returned true whenever a BYOK key existed, so a stale/revoked OpenAI or
Gemini key kept entering hub mode on every PTT and lost the turn to a failing
realtime session (while managed-token failures already fell back).

Now isActive requires a live, authenticated session for the selected provider
(new hubConnected flag, set on the post-auth connect, cleared on teardown). A
key/token that can't connect never routes a turn to the hub — PTT transparently
uses the legacy cascade, so a broken hub never costs the user a turn. The hub
re-warms in the background and resumes taking turns the moment it connects (also
covers provider switches and idle-close reconnect windows). Reconnect churn is
still capped via a named maxReconnectStrikes constant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add get_memories, search_memories, search_conversations, get_conversations,
create_action_item and update_action_item to the floating-bar voice agent so it
answers "who am I / what do you know about me" and "most recent conversation"
instead of refusing. Reads are synchronous and spoken; the system prompt no
longer claims it can't see personal data and routes recency vs semantic vs
spawn_agent. Tool dicts are static `let` (built once, not per reconnect).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the new HubTool cases in hubDidRequestTool to the existing APIClient.tool*
endpoints (capped for voice: top 3/5, no transcripts). Reads/writes share one
runToolAndSpeak helper (Task / do-catch / empty-fallback / log / sendToolResult)
and a small arg() accessor; get_tasks output carries [id:…] so update_action_item
can target a task.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the harness tool-result switch exhaustive for the six new HubTool cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants