fix(consult)L fix mute state in desktop consult#4978
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55ecbeaf0c
ℹ️ 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".
| Boolean(interaction?.media?.[mainCallId]?.participants?.includes(selfAgentId as string)); | ||
| const consultMedia = Object.values(interaction?.media ?? {}).find( | ||
| (media: any) => | ||
| media?.mediaResourceId === taskData?.consultMediaResourceId || media?.mType === 'consult' |
There was a problem hiding this comment.
Select consult leg by ID before fallback media type
The consult leg lookup now uses mediaResourceId === consultMediaResourceId || mType === 'consult' in a single find, which can return the wrong media object when interaction.media contains multiple consult entries (for example, a stale earlier consult plus the current one). In that case, selfInConsultCall is computed from the stale leg and consult.mute is incorrectly hidden on the active consult leg. This regression appears whenever object insertion order places a non-current consult media first, so the lookup should prioritize exact consultMediaResourceId and only fall back to mType when no ID match exists.
Useful? React with 👍 / 👎.
| (media: any) => | ||
| media?.mediaResourceId === taskData?.consultMediaResourceId || media?.mType === 'consult' | ||
| ) as {participants?: string[]} | undefined; | ||
| const selfInConsultCall = |
There was a problem hiding this comment.
Why this guard exists: in desktop consult, the consult media leg can belong to another participant; hiding mute here prevents exposing a control that the current agent cannot safely apply to their own active media stream.
| mute: (() => { | ||
| if (!isWebrtc) return DISABLED; | ||
| if (isWrappingUp) return DISABLED; | ||
| if (currentLeg === 'consult' && !selfInConsultCall) return DISABLED; |
There was a problem hiding this comment.
Behavioral intent: mute is explicitly disabled on consult leg when ownership check fails, avoiding cross-leg mute side effects observed in desktop consult flows.
| expect(uiControls.main.end).toEqual({isVisible: true, isEnabled: false}); | ||
|
|
||
| expect(uiControls.consult.hold).toEqual({isVisible: false, isEnabled: false}); | ||
| expect(uiControls.consult.mute).toEqual({isVisible: false, isEnabled: false}); |
There was a problem hiding this comment.
Regression coverage note: this assertion ensures consult leg does not surface mute when the current agent is not a participant in consult media, matching desktop consult ownership semantics.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0854c84a8b
ℹ️ 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".
| // Interaction terminated during consult (customer left) → WRAPPING_UP | ||
| guard: ({context, event}) => { | ||
| if (context.consultInitiator !== true) return false; | ||
| const taskData = getTaskDataFromEvent(event); | ||
|
|
There was a problem hiding this comment.
Reorder consult-end guards to honor terminated consults
The new CONSULT_END wrap-up branch is placed after the existing consultCallHeld branch, but XState evaluates transition options in order and takes the first passing guard. When an initiator has switched back to the main leg (consultCallHeld === true) and the customer disconnects (interaction.isTerminated === true), the machine will still transition to CONNECTED via the earlier branch, so the new WRAPPING_UP path never runs and wrap-up/cleanup can be skipped for that ended interaction.
Useful? React with 👍 / 👎.
COMPLETES #N/A
This pull request addresses
During desktop consult flows, the UI was showing
muteon the first (main) leg while the actual mute operation could affect a different leg, and the consult leg could expose mute even when the current agent did not control that media leg.by making the following changes
uiControlsComputerto identify whether the current agent is in the consult media leg.muteis hidden for that leg.uiControlsComputertests to lock this behavior for desktop consult scenarios.Change Type
The following scenarios were tested
consult.muteis hidden when the current agent does not own the consult media leg.fastqueue concurrency must be greater than 1), but tests are included in the PR changeset.The GAI Coding Policy And Copyright Annotation Best Practices
I certified that
Make sure to have followed the contributing guidelines before submitting.