Skip to content

Polish Huddle voice controls - #4694

Open
klopez4212 wants to merge 11 commits into
mainfrom
kennylopez-huddle-stop-speaking
Open

Polish Huddle voice controls#4694
klopez4212 wants to merge 11 commits into
mainfrom
kennylopez-huddle-stop-speaking

Conversation

@klopez4212

Copy link
Copy Markdown
Contributor

Summary

  • add a visible Stop control for interrupting agent speech
  • make push-to-talk available by default while preserving manual mute controls
  • refine agent management, muted audio states, drawer layering, and return navigation
  • suppress duplicate notification sounds for Huddle messages

Why

Huddles could trap users behind long agent speech, hide useful agent controls, and leave temporary Huddle state visible after the call. The drawer also regressed when the terminal substrate began painting behind the rounded app surface.

Validation

  • just desktop-ci
  • focused Huddle Playwright coverage for the drawer, speech interruption, agent picker, and leave navigation

Signed-off-by: kenny lopez <klopez4212@gmail.com>
klopez4212 added a commit that referenced this pull request Aug 4, 2026
@klopez4212

Copy link
Copy Markdown
Contributor Author

🤖 Huddle UI snapshots

Drawer and agent voice controls

The drawer keeps its surface behind the rounded app and exposes agent controls from the avatar.

01-huddle-drawer-agent-menu

Interrupt agent speech

A responding agent replaces its name with a visible Stop control without changing tile height.

02-speaking-stop-control

Add an agent

The picker uses the shared modal styling and starts a stopped agent when selected.

03-add-agent-dialog

@klopez4212
klopez4212 marked this pull request as ready for review August 4, 2026 13:53
@klopez4212
klopez4212 requested a review from a team as a code owner August 4, 2026 13:53

@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: 5d7192503c

ℹ️ 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 thread desktop/src/features/huddle/HuddleContext.tsx

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Requesting changes on Wes's behalf. I found three user-visible correctness issues in the new Huddle controls: the displayed mute action can leave the microphone open after PTT release, a stale Stop click can discard the next agent utterance, and removing an agent can leave that agent's current/queued speech playing. Details and requested regression coverage are inline. I am acting on Wes's behalf and am not approving this PR.

Comment thread desktop/src/features/huddle/HuddleContext.tsx
Comment thread desktop/src-tauri/src/huddle/commands.rs Outdated
Comment thread desktop/src-tauri/src/huddle/commands.rs
Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.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: 53d4e079a1

ℹ️ 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 thread desktop/src-tauri/src/huddle/tts_pipeline_controls.rs Outdated
Comment thread desktop/src/features/huddle/components/AddAgentDialog.tsx Outdated
Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.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: 1015ade24e

ℹ️ 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 thread desktop/src-tauri/src/huddle/tts_speaker_cancellation.rs Outdated
Comment thread desktop/src-tauri/src/huddle/commands.rs Outdated
Comment thread desktop/src/features/huddle/components/AddAgentDialog.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.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: 80258a5066

ℹ️ 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 thread desktop/src/features/huddle/HuddleContext.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.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: 6e9fbbd176

ℹ️ 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 thread desktop/src/features/huddle/components/ParticipantList.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Carl here, commenting on Wes's behalf. Requesting changes at exact head 05c7623b1debc8619fd9d1dcf29677e59bc76d01.

P1 — a stale Stop click can discard the same agent's next queued utterance after the displayed utterance has already drained. active_speaker and tts_active remain set until the worker notices player.empty() during receive-timeout or pre-synthesis cleanup (desktop/src-tauri/src/huddle/tts.rs:557-575, 662-677). During that real drain→cleanup window, the UI still presents Alice's Stop action. Clicking it passes request_active_speaker_cancel's ownership check and advances Alice's generation (desktop/src-tauri/src/huddle/tts_voice_transition.rs:133-157), invalidating Alice text already queued under the prior generation (desktop/src-tauri/src/huddle/tts.rs:603-608) even though the utterance the user intended to stop is over.

The new regression does not cover this ordering because it manually clears active_speaker before issuing the stale click (tts_voice_transition.rs:463-475). Please bind Stop to actual player/utterance liveness under the same synchronization and add a regression where playback is empty but ownership cleanup has not run; Alice's already-queued next utterance must survive.

The earlier mute/PTT, agent-removal, unrelated-speaker, provider-start, and wrong-speaker Stop issues appear fixed.

Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.com>
@klopez4212

Copy link
Copy Markdown
Contributor Author

🤖 Addressed Wes’s P1 in 0aa4cbb. Stop now reads the actual Rodio player under the same player-operation lock used for append and clear, and only advances the selected agent’s generation when playback is still non-empty and that agent still owns it. Added a device-free regression with an empty player, stale Alice ownership, and Alice’s already-queued next utterance; the Stop request is rejected and the queued utterance remains current. All 66 Huddle TTS tests, strict Clippy, 4,177 desktop tests, the native workspace suite, and the full merged-tree pre-push gate pass. Latest main is merged at 241d57f.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I’m commenting on Wes Billman’s behalf as his review agent.

P1 — Do not treat every empty player as a stale Stop click.

request_active_speaker_cancel now rejects Stop whenever player.empty() is true (desktop/src-tauri/src/huddle/tts_voice_transition.rs:178-188). That closes the drain→cleanup case, but empty() is also transiently true when playback has exhausted one synthesized chunk while the worker is still synthesizing a later chunk of the same utterance. tts_active and active_speaker deliberately remain set across that lookahead pipeline (tts.rs:451-524, 722-856), so the UI still presents that speaker as active. If the user clicks Stop during such a synthesis gap, this function returns false without advancing the speaker generation or installing speaker_cancel; the in-flight synthesis then passes the unchanged generation check in append_audio and appends more audio, so the agent resumes speaking after Stop.

The fix needs to distinguish “utterance fully drained with only stale ownership/UI state” from “player temporarily empty while the owned utterance still has synthesis in flight.” Please add a regression for the latter alongside the new drained-playback regression: empty player + active/in-flight Alice utterance must accept Stop and prevent Alice’s later synthesized chunk from appending, while empty player + fully drained Alice state must preserve already-queued next speech.

@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: 241d57ffc4

ℹ️ 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 +881 to +885
if !agent_is_present {
eprintln!(
"buzz-desktop: tts stage=queue status=dropped reason=speaker_removed route_id={route_id}"
);
return Ok(());

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 Avoid dropping relay-verified newly added agents

When an agent is added to the huddle by another participant, the React TTS subscription can authorize that speaker from the relay via get_huddle_agent_pubkeys, but this new native gate still checks only the local hs.agent_pubkeys snapshot, which is refreshed separately by check_pipeline_hotstart on a 15s throttle. In that window, the first responses from the newly added agent are accepted by the frontend and then silently returned here as speaker_removed, so remote agent additions can miss their initial spoken replies until the backend refresh catches up.

Useful? React with 👍 / 👎.

Track synthesis-in-flight separately from player queue liveness so Stop
still cancels an utterance while its player is temporarily empty. Keep
repeat clicks idempotent while cancellation is pending and serialize the
drain boundary with player operations.

Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
@wesbillman
wesbillman enabled auto-merge (squash) August 4, 2026 19:02
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