Repository navigation
Conversation
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
This pull request is automatically being deployed by Amplify Hosting (learn more). |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f601f221f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- Guard voice snapshot initialization when cc is undefined or getVoiceConnectionState is not yet exposed - Preserve forced Idle state transition during wellness-code lookup - Synchronize recovery dialog to open only after Idle state transition successfully resolves - Anchor select overlays in user-state-select-wrapper independently of alert message heights
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e066d4db9b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const defaultIdleCode = idleCodes.find((idleCode) => idleCode.isDefault); | ||
| if (defaultIdleCode && currentStateRef.current !== defaultIdleCode.id) { | ||
| pendingVoiceLossDialogRef.current = true; | ||
| setAgentStatus(defaultIdleCode.id); |
There was a problem hiding this comment.
Read the live wellness-lookup flag before forcing Idle
When a wellness-enabled session starts loadWellbeingBreakIdleCode() during the two-second loss window (for example, AGENT_RELOGIN_SUCCESS calls it in storeEventsWrapper.ts:2368-2372), this timeout still invokes the setAgentStatus closure from the earlier READY→UNAVAILABLE render. The fresh fix routes the forced change through setAgentStatus, but because the voice-loss effect neither reads a ref for nor is recreated from wellnessIdleCodeLookupPending, that closure sees the old false value and does not populate pendingUserSelectionRef; the current-state effect then advances prevStateRef while lookup is pending, so lookup completion never calls cc.setAgentState and the recovery dialog never opens. Record the forced transition using the latest lookup state.
Useful? React with 👍 / 👎.
| } else { | ||
| setVoiceConnectionLossDialogOpen(true); |
There was a problem hiding this comment.
Avoid claiming Idle when no default code exists
If registration returns no idle code with isDefault: true (a shape already represented by test-fixtures/src/fixtures.ts:48), defaultIdleCode is undefined and this else opens the recovery modal without ever calling setAgentStatus; the user is therefore told that their availability changed to Idle while both the store and backend remain unchanged. The new success-gating covers rejected setAgentState calls, but not this no-default path, so distinguish it from the already-in-default case and avoid the false dialog copy.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
If there is no default idle code when the timeout expires, neither branch opens the recovery dialog. The selector remains disabled, but the agent has no way to access the Reconnect action. If the idle codes arrive later, the effect reruns with the previous voice status already UNAVAILABLE, so it does not restart the loss flow. Could we show recovery guidance without claiming that the agent changed to Idle, and handle a default code becoming available after the timeout?
There was a problem hiding this comment.
Fixed in a9f8d21 — When no default idle code exists at timeout, the recovery dialog now still opens with neutral recovery copy ("You're no longer connected to Desktop. Check your internet connection, then try reconnecting.") so the agent retains access to the Reconnect action without false Idle claims. If idleCodes arrives with a default code after the timeout has elapsed, the hook automatically requests the transition and updates the copy to reflect Idle once settled.
mkesavan13
left a comment
There was a problem hiding this comment.
I'll review the rest of the changes during the day. Wanted to send out a quick review
| buildDropdownItems, | ||
| } from './user-state.utils'; | ||
| import {withMetrics} from '@webex/cc-ui-logging'; | ||
| import {VOICE_CONNECTION_STATUS, VoiceLineStatus} from '@webex/cc-store'; |
There was a problem hiding this comment.
I see no evidence of VOICE_CONNECTION_STATUS or VoiceLineStatus being available in the entire cc-store codebase.
Search link for next branch:
Search link for cmullenx:chrmulle/webrtcErrors branch:
Did we miss checking in the entire store folder?
akulakum
left a comment
There was a problem hiding this comment.
Local Agent Desktop parity review feedback.
| <Button | ||
| slot="footer-button-primary" | ||
| type="button" | ||
| disabled={!onVoiceReconnect} |
There was a problem hiding this comment.
When the host does not pass onVoiceReconnect, this button is disabled. Existing UserState embeds therefore show a Reconnect action the user cannot use; the sample’s regular UserState instance also omits this callback. Agent Desktop wires the action to registerWebCalling. Please provide a host integration example that supplies a real retry callback, or clearly document that reconnect requires host wiring before describing this as full parity.
|
@cmullenx, could you please address the outstanding Codex review comments? The findings are valid, especially the Wellness Break timeout and lookup edge cases, and the case where the dialog says the agent changed to Idle when no default idle code exists. Thanks. |
…(CAI-8629) - Only open recovery dialog when default idle code exists and transition settles (or was already in default idle) - Suppress opening recovery dialog with false Idle claim when profile has no default idle code - Wire onVoiceReconnect on sample UserState embed and document host retry contract in user-state spec
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6899699ea8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…ate default codes (CAI-8629) - Bind recovery dialog specifically to the settled forced Idle request to prevent concurrent in-flight updates from falsely opening the modal - Show recovery dialog with non-Idle copy when no default idle code exists so Reconnect action remains accessible - Transition to default idle code if default code arrives after voice-loss timeout has elapsed - Omit onVoiceReconnect from regular sample embed while preserving interactive preview
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a9f8d21827
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (defaultIdleCode && currentStateRef.current !== defaultIdleCode.id) { | ||
| forcedVoiceLossIdleCodeRef.current = defaultIdleCode.id; | ||
| setAgentStatus(defaultIdleCode.id); |
There was a problem hiding this comment.
Prevent rejected forced-Idle requests from retrying on every render
Once the two-second loss timeout fires—for example, when CSP blocks the Blob worker—a rejected forced-Idle request rolls currentState back but leaves hasVoiceLossTimeoutElapsedRef set. StoreWrapper.idleCodes returns a fresh filtered array on every read (storeEventsWrapper.ts:177-180), so the rollback render re-enters this branch and immediately initiates another state-change request. Persistent rejection therefore creates an unbounded request/rollback loop without another connection event or user retry. Limit this latch to waiting for an initially missing default code and consume it once the forced transition is issued.
Useful? React with 👍 / 👎.
| .catch((error) => { | ||
| if (forcedVoiceLossIdleCodeRef.current === currentState) { | ||
| forcedVoiceLossIdleCodeRef.current = null; | ||
| setVoiceConnectionLossDialogOpen(false); |
There was a problem hiding this comment.
Keep reconnect accessible when the forced Idle update fails
If the forced Idle request rejects while voice remains unavailable, a host-provided onVoiceReconnect becomes inaccessible through the widget: this suppresses the dialog, and UserStateComponent renders its only Reconnect button inside that dialog. The selector remains disabled, while the warning and state-change error provide no retry action, so continued state-update failures also prevent the agent from requesting voice recovery. The component already supports truthful non-Idle dialog copy; keep that recovery UI, or an equivalent reconnect control, available independently of availability-update success.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d75561ffcb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| forcedVoiceLossIdleCodeRef.current = defaultIdleCode.id; | ||
| setAgentStatus(defaultIdleCode.id); |
There was a problem hiding this comment.
Persist forced Idle transitions out of WellbeingBreak
If this timeout expires during WellbeingBreak with wellness lookup already complete—for example, in a host that blocks Blob workers—externallyManagedStateRef is still true. This store update changes isCurrentStateExternallyManaged to false, but the current-state effect's isCurrentStateExternallyManaged || externallyManagedStateRef.current branch consumes the transition as an SDK restoration, advancing prevStateRef without calling cc.setAgentState. The dropdown therefore moves to the default Idle code while the backend remains on the wellness code, and the success continuation that opens the recovery dialog never runs. Distinguish explicit forced voice-loss requests from SDK restoration so this transition is persisted rather than suppressed.
Useful? React with 👍 / 👎.
…low (CAI-8629) - Read live wellnessIdleCodeLookupPendingRef before forcing Idle to prevent stale timeout closures from skipping pending state registration - Persist forced Idle transitions out of WellbeingBreak rather than suppressing them as SDK wellness restorations - Stabilize voice loss timeout against displayedIdleCodes and idleCodes array reference changes - Prevent rejected forced-Idle requests from retrying on every render - Keep recovery dialog accessible when forced Idle update fails
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c018359746
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (defaultIdleCode && currentStateRef.current !== defaultIdleCode.id) { | ||
| hasForcedIdleAttemptedRef.current = true; | ||
| forcedVoiceLossIdleCodeRef.current = defaultIdleCode.id; | ||
| setAgentStatus(defaultIdleCode.id); |
There was a problem hiding this comment.
Persist forced Idle when it matches the last confirmed state
If an agent starts in the default Idle code, selects Available, and that request remains pending beyond the two-second voice-loss timeout, this write returns currentState to prevStateRef.current. The current-state effect therefore skips updateAgentState, so no compensating Idle request is sent and no recovery-dialog continuation is installed. If the original Available request subsequently succeeds, the agent can remain Available while voice is unavailable. Queue the forced transition behind the in-flight change, or explicitly persist it even when its target matches the last confirmed state.
Useful? React with 👍 / 👎.
| > | ||
| Simulate voice loss (2 seconds) | ||
| </Button> | ||
| <UserStateComponent |
There was a problem hiding this comment.
Isolate the readiness preview from live-widget selectors
When User State is enabled in the React sample, this mounts a second state control alongside the live <UserState>, duplicating the state-select and elapsed-time test IDs. playwright.config.ts:13-16 serves this app, while playwright/tests/user-state-test.spec.ts:41 and playwright/Utils/userStateUtils.ts:57-62 use unscoped single-element locators, which now encounter strict-mode violations; changeUserState also catches the ambiguity and silently skips the requested change. Make the preview opt-in or introduce instance-specific selectors and scope the affected helpers to the live widget.
Useful? React with 👍 / 👎.
| ) { | ||
| hasVoiceLossTimeoutElapsedRef.current = false; | ||
| hasForcedIdleAttemptedRef.current = false; | ||
| forcedVoiceLossIdleCodeRef.current = null; |
There was a problem hiding this comment.
Preserve deferred forced-Idle intent across voice recovery
When an already-known WellbeingBreak session starts another wellness-code lookup, such as during relogin, the loss timeout can select default Idle while persistence waits for that lookup. If voice becomes READY before lookup finishes, this reset clears the marker required by the new isForcedVoiceLossTransition bypass. Lookup completion then takes the externally managed restoration branch because externallyManagedStateRef is still true, advances prevStateRef, and never calls cc.setAgentState, leaving default Idle in the store while the backend retains the wellness code. Preserve the deferred marker until persistence is processed, or revert the optimistic state if recovery cancels it.
Useful? React with 👍 / 👎.
COMPLETES # https://jira-eng-sjc12.cisco.com/jira/browse/CAI-8629
This pull request addresses
showing the user an error message when mobius connection drops and preventing user state changes to achieve parity with agent desktop
by making the following changes
Vidcast: https://app.vidcast.io/share/40b94562-07d1-4abc-aa12-c382443df773
< DESCRIBE YOUR CHANGES >
Change Type
The following scenarios were tested
< ENUMERATE TESTS PERFORMED, WHETHER MANUAL OR AUTOMATED >
The GAI Coding Policy And Copyright Annotation Best Practices
Checklist before merging
Make sure to have followed the contributing guidelines before submitting.