fix(cc): migrate widgets to SDK state-machine-driven uiControls#668
fix(cc): migrate widgets to SDK state-machine-driven uiControls#668akulakum wants to merge 30 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2227d693dc
ℹ️ 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".
| if (lastWrapupAuxCodeIdRef.current) { | ||
| const wrapUpReason = store.wrapupCodes.find((code) => code.id === lastWrapupAuxCodeIdRef.current)?.name; | ||
| if (onWrapUp) { |
There was a problem hiding this comment.
Restore onWrapUp callback for SDK-driven wrapups
wrapupCallCallback now emits onWrapUp only when lastWrapupAuxCodeIdRef.current is present, but that ref is only set in wrapupCall(). As a result, wrapups triggered outside this path (for example auto-wrapup or other SDK-driven/task-synced wrapup events) will fire TASK_WRAPPEDUP but never notify consumers via onWrapUp, which breaks callback-based integrations such as analytics or workflow hooks.
Useful? React with 👍 / 👎.
| </div> | ||
| </> | ||
| )} | ||
| {!controls?.wrapup?.isVisible && isInteractionOnHold(currentTask) && ( |
There was a problem hiding this comment.
Keep consult-state gating for the CAD hold indicator
The hold badge now depends only on isInteractionOnHold(currentTask), which becomes true when either the main leg or consult leg is held. During consult/conference flows one leg is often intentionally held while the agent is active on the other, so this change can incorrectly show an ON HOLD status. The previous logic gated this by consult-state flags, and removing that gating regresses status accuracy.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c63805a45b
ℹ️ 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".
| store.lastConsultDestination ?? { | ||
| to: currentTask.data.destAgentId, | ||
| destinationType: 'agent' as DestinationType, | ||
| } |
There was a problem hiding this comment.
Preserve consult destination for consult transfer
consultTransfer() now falls back to currentTask.transfer({ to: currentTask.data.destAgentId, destinationType: 'agent' }) when store.lastConsultDestination is missing. That store field is only set in consultCall(), so hydrated/multi-session consults (or any flow where the consult was not initiated in this hook) can lose the original destination type. In those cases, queue/EP consult transfers can be sent as agent transfers with an incorrect or empty destination, causing transfer failure or routing to the wrong target.
Useful? React with 👍 / 👎.
| // Derive consultCallHeld from controls: switchToConsult.isVisible means consult call is held | ||
| const consultCallHeld = controls.switchToConsult?.isVisible ?? false; |
There was a problem hiding this comment.
Derive consult hold timer from actual hold state
This computes consultCallHeld from controls.switchToConsult.isVisible, which is a UI visibility signal rather than the consult leg's hold state. If the button is hidden for reasons other than hold status, the timer logic will mislabel a held consult as active consulting and use the wrong timestamp. The timer should be driven by task/media hold state, not button visibility.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24267feeb5
ℹ️ 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".
| this.setState({reset: true}); | ||
| // Ensure agent state is set to Available (auxCodeId '0') when no tasks remain | ||
| // The backend should send AGENT_STATE_CHANGE, but in test environments it may not | ||
| this.setCurrentState('0'); |
There was a problem hiding this comment.
Remove forced Available state on empty task list
Setting currentState to '0' inside refreshTaskList() introduces a side effect beyond UI cleanup: when UserState is mounted, its useEffect reacts to currentState changes and calls cc.setAgentState(...), so ending the last task can unexpectedly push the agent to Available even if the backend intended a different post-call state. This regression was introduced by the new unconditional this.setCurrentState('0') and can cause incorrect agent-state transitions in production flows.
Useful? React with 👍 / 👎.
| isTelephony, | ||
| logger | ||
| ); | ||
| const isConsulting = (controls?.consult?.endConsult?.isVisible || controls?.main?.endConsult?.isVisible) ?? false; |
There was a problem hiding this comment.
Derive consult mode without relying on end-consult visibility
Using endConsult.isVisible as the consult-state detector is not reliable: consult can be active while end-consult is hidden (for example when end-consult is disabled by configuration), so this check can treat an active consult as non-consulting. In that case consult-specific filtering is skipped here, and the same predicate also hides the CAD consult panel, leaving incorrect controls during an ongoing consult session.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 40a5f9f957
ℹ️ 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".
| return buttons; | ||
| } | ||
|
|
||
| return buttons.filter((button) => !['hold', 'consult', 'transfer', 'record'].includes(button.id)); |
There was a problem hiding this comment.
Stop filtering recording control during consult
filterButtonsForConsultation now always removes the record button whenever a consult is active, which bypasses the SDK-provided controls.main.recording visibility/enablement and prevents agents from pausing/resuming recording during consult flows where recording is still allowed. This is a regression from the prior behavior (which only filtered hold/consult) and can break recording-control workflows in consult scenarios.
Useful? React with 👍 / 👎.
| disabled: !(mainCtrl?.transfer?.isEnabled ?? false), | ||
| isVisible: | ||
| (mainCtrl?.transfer?.isVisible ?? false) && | ||
| ((controls?.consult?.endConsult?.isVisible || controls?.main?.endConsult?.isVisible) ?? false) && |
There was a problem hiding this comment.
Use conference transfer control when invoking transferConference
The transferConsult button is gated only by mainCtrl.transfer (isEnabled/isVisible), but the action handler can switch to currentTask.transferConference() in conference flows. When SDK state exposes conference-transfer availability separately from regular transfer, this mapping can hide or disable the button even though conference transfer is the intended action, leaving no way to trigger that path from the UI.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5373115817
ℹ️ 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".
| // in the consulting section UI. Without this filter, switching to | ||
| // main call during a consult would incorrectly show the hold indicator | ||
| // because the consult media has isHold: true. | ||
| return Object.values(interaction.media).some((media) => media.mType === 'mainCall' && media.isHold); |
There was a problem hiding this comment.
Preserve hold detection for non-mainCall media legs
isInteractionOnHold now hard-codes mType === 'mainCall', which means held tasks whose main leg uses another media type value (for example hydrated/legacy task payloads) are treated as not held. useCallControl and useHoldTimer both depend on this helper for initial state, so those sessions can render the wrong hold icon/timer until a new hold event arrives (and may never self-correct after reload).
Useful? React with 👍 / 👎.
| holdParticipants: !allowParticipantsToInteract, | ||
| }; | ||
|
|
||
| store.setLastConsultDestination({to: consultDestination, destinationType}); |
There was a problem hiding this comment.
Clear stale consult destination after consult failures
consultCall writes store.lastConsultDestination before currentTask.consult() succeeds, but the error path does not clear it. Later, consultTransfer() prefers store.lastConsultDestination, so a failed consult attempt can leak stale destination data into a subsequent transfer and send it to the wrong target. Store this only on success (or reset it in catch) to avoid cross-attempt routing errors.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 205e6b3398
ℹ️ 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".
| if (!controls?.main?.mute?.isVisible) { | ||
| logger.warn('Mute control not available', {module: 'useCallControl', method: 'toggleMute'}); | ||
| return; |
There was a problem hiding this comment.
Allow consult mute when only consult mute control is visible
The new guard in toggleMute only allows execution when controls.main.mute.isVisible is true, but the consult panel renders its mute button from controls.consult.mute and calls this same handler. In consult scenarios where the SDK hides main-leg mute while showing consult-leg mute, the mute button is visible but every click returns early here, so agents cannot mute/unmute during an active consult.
Useful? React with 👍 / 👎.
…vel hold state during hydration
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3108e59094
ℹ️ 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".
| setConsultTimerLabel(consultTimerData.label); | ||
| setConsultTimerTimestamp(consultTimerData.timestamp); | ||
| } | ||
| }, [currentTask, controls, agentId, consultMediaIsHold, consultMediaId, participantConsultState]); |
There was a problem hiding this comment.
Include hold timestamp in consult timer dependencies
calculateConsultTimerData() marks consult-on-hold only when the consult media has a positive holdTimestamp, but this effect re-runs only on consultMediaIsHold, consultMediaId, and consult state changes. In the common delayed-update path where isHold is already true and the backend fills holdTimestamp in a follow-up update, none of these dependencies change, so the label/timestamp can stay stuck in non-hold state. Add a derived consult hold timestamp primitive to this dependency list so the timer refreshes when that timestamp arrives.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 03ef286ccd
ℹ️ 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".
| store.setTaskCallback(TASK_EVENTS.TASK_RESUME, resumeCallback, interactionId); | ||
| store.setTaskCallback(TASK_EVENTS.TASK_END, endCallCallback, interactionId); | ||
| store.setTaskCallback(TASK_EVENTS.AGENT_WRAPPEDUP, wrapupCallCallback, interactionId); | ||
| store.setTaskCallback(TASK_EVENTS.TASK_WRAPUP, endCallCallback, interactionId); // Also call onEnd when entering wrapup |
There was a problem hiding this comment.
Avoid firing onEnd again on task wrap-up event
Registering endCallCallback for both TASK_END and TASK_WRAPUP causes duplicate onEnd callbacks in normal wrap-up flows, because the SDK emits task:end when the interaction ends and then task:wrapup when wrap-up starts. Any consumer side effects tied to onEnd (navigation, analytics, cleanup) will run twice for the same task.
Useful? React with 👍 / 👎.
|
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: 3c5e16f813
ℹ️ 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".
| const wrapupCall = (wrapUpReason: string, auxCodeId: string) => { | ||
| try { | ||
| // Store auxCodeId for use in wrapupCallCallback | ||
| lastWrapupAuxCodeIdRef.current = auxCodeId; |
There was a problem hiding this comment.
Reset cached wrapup code between wrapup attempts
lastWrapupAuxCodeIdRef is written before currentTask.wrapup() succeeds and is never cleared, so a failed wrapup or a later SDK-driven wrapup on another task can reuse a stale aux code and emit onWrapUp with the wrong reason. This is new behavior from the ref-based callback path and can misattribute analytics/workflow hooks across tasks unless the cached value is cleared on failure and after callback consumption.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c6e8ae7f1
ℹ️ 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".
| if (p.pType === 'Agent') { | ||
| recoveredTo = pid; | ||
| recoveredDestinationType = 'agent' as DestinationType; |
There was a problem hiding this comment.
Use participant.id when recovering consult transfer target
In the consult-transfer recovery path, the agent destination is rebuilt with recoveredTo = pid, but pid is the participant map key, not necessarily the agent identifier expected by transfer({ to, destinationType: 'agent' }). This same block already treats p.id as the agent ID (p.id === myAgentId), so after refresh/hydration the recovered transfer can be sent to the wrong identifier and fail or route incorrectly.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2723c49b4
ℹ️ 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".
| }); | ||
| } | ||
|
|
||
| export function findHoldTimestamp(interaction: Interaction, mType = 'mainCall'): number | null { |
There was a problem hiding this comment.
Migrate task-util tests before deleting exports
This file now only exports findHoldTimestamp, but the task package tests still import and spy on the removed getControlsVisibility helper (packages/contact-center/task/tests/utils/task-util.ts and packages/contact-center/task/tests/helper.ts). Since @webex/cc-task's test:unit script runs tsc --project tsconfig.test.json before Jest, the package no longer type-checks; either migrate/remove those tests with this deletion or keep a compatibility export until the test migration lands.
Useful? React with 👍 / 👎.
| VVA, | ||
| } from './constants'; | ||
| import {ConsultStatus, ITask, MEDIA_TYPE_TELEPHONY_LOWER, Participant} from './store.types'; | ||
| import {EXCLUDED_PARTICIPANT_TYPES, MEDIA_TYPE_CONSULT, RELATIONSHIP_TYPE_CONSULT} from './constants'; |
There was a problem hiding this comment.
Migrate store utility tests before removing exports
Removing the conference/status helpers leaves packages/contact-center/store/tests/task-utils.ts importing removed symbols such as getIsConferenceInProgress and getConferenceParticipantsCount. The store package also type-checks tests before running Jest, so @webex/cc-store's test:unit is blocked until those tests are updated/deleted or these exports are kept temporarily.
Useful? React with 👍 / 👎.
a2723c4 to
b372732
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b37273226b
ℹ️ 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".
| featureFlags: store.featureFlags, | ||
| deviceType: store.deviceType, |
There was a problem hiding this comment.
Remove deleted props from new useCallControl test cases
The newly added conference-hold test blocks still pass featureFlags and deviceType into useCallControl, but this commit removed both keys from useCallControlProps (task/src/task.types.ts). Because @webex/cc-task runs tsc --project tsconfig.test.json before Jest, these object-literal excess properties cause test type-check failure and block test:unit even if runtime behavior is correct.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b37273226b
ℹ️ 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".
| TASK_POST_CALL_ACTIVITY = 'task:postCallActivity', | ||
| TASK_OUTDIAL_FAILED = 'task:outdialFailed', | ||
| } // TODO: remove this once cc sdk exports this enum | ||
| // TASK_EVENTS is now imported from @webex/contact-center SDK |
There was a problem hiding this comment.
Preserve legacy TASK_EVENTS aliases during event-name migration
Replacing the local TASK_EVENTS enum with the SDK export removes the compatibility layer for legacy members (for example AGENT_WRAPPEDUP, AGENT_CONSULT_CREATED, CONTACT_RECORDING_PAUSED) while the repo still contains tests and call-site expectations using those names (e.g. packages/contact-center/task/tests/helper.ts and packages/contact-center/store/tests/storeEventsWrapper.ts). This makes the migration non-atomic: either type-checking or unit assertions will break until every consumer is updated in the same change. Keep temporary aliases (old key -> new key) in @webex/cc-store until downstream usage is migrated.
Useful? React with 👍 / 👎.
…dgets into TASK_REFACTOR_IMPLEMENTATION
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aadf97adfa
ℹ️ 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".
| const WebIncomingTask = r2wc(IncomingTaskComponent, { | ||
| props: { | ||
| incomingTask: 'json', | ||
| isBrowser: 'boolean', | ||
| accept: 'function', | ||
| reject: 'function', | ||
| }, |
There was a problem hiding this comment.
Keep isBrowser prop exposed on WC task components
Removing isBrowser from the r2wc prop maps for component-cc-incoming-task and component-cc-task-list breaks browser-vs-phone behavior for consumers that use @webex/cc-components/wc directly: those components can no longer receive the device context that extractIncomingTaskData / extractTaskListItemData still use to choose labels and button-state messaging. In browser flows where accept is visible but temporarily disabled (for example auto-answer/outdial transitions), this now defaults to non-browser handling and can show incorrect "Ringing..."/state text.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 330ae3f938
ℹ️ 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".
| } | ||
| } | ||
| isConferenceInProgress={controlVisibility.isConferenceInProgress} | ||
| isConferenceInProgress={controls?.main?.exitConference?.isVisible ?? false} |
There was a problem hiding this comment.
Derive conference state from task, not exit button visibility
Pass a real conference-state signal into the consult/transfer popover instead of controls.main.exitConference.isVisible. In conference consult flows, SDK control visibility can hide exitConference while conference transfer is still active (or app config disables that button), so this expression becomes false even though the task is in conference. That suppresses the popover’s "Allow participants to continue interacting" checkbox and forces consult payloads down the default hold-participants path, changing transfer behavior for conference scenarios.
Useful? React with 👍 / 👎.
…o TASK_REFACTOR_IMPLEMENTATION
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30dd7f9e73
ℹ️ 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".
| export const extractTaskListItemData = ( | ||
| task: ITask, | ||
| isBrowser: boolean, | ||
| agentId: string, | ||
| logger?: ILogger | ||
| logger?: ILogger, | ||
| isDeclineButtonEnabled?: boolean, | ||
| isBrowser?: boolean |
There was a problem hiding this comment.
Update TaskList util callers for new agentId parameter
Changing extractTaskListItemData to (task, agentId, ...) without migrating existing call sites breaks the cc-components test compile step: the TaskList utility tests still pass a boolean in argument 2 (e.g. extractTaskListItemData(mockTask, true, ...)), which is now typed as agentId: string. Since @webex/cc-components runs tsc --project tsconfig.test.json before Jest, this introduces immediate type-check failures and blocks test:unit.
Useful? React with 👍 / 👎.
| export const extractIncomingTaskData = ( | ||
| incomingTask: ITask, | ||
| isBrowser: boolean, | ||
| logger?, | ||
| isDeclineButtonEnabled?: boolean | ||
| acceptControl?: {isVisible: boolean; isEnabled: boolean}, | ||
| declineControl?: {isVisible: boolean; isEnabled: boolean}, | ||
| isDeclineButtonEnabled?: boolean, | ||
| isBrowser?: boolean |
There was a problem hiding this comment.
Preserve positional isBrowser arg in incoming-task extractor
The signature change in extractIncomingTaskData moved isBrowser from the 2nd parameter to the 6th, but existing callers in cc-components/tests/components/task/IncomingTask/incoming-task.utils.tsx still pass true/false as arg 2. Those calls now feed a boolean into logger and leave isBrowser undefined, so browser-vs-extension label/disable logic is evaluated on the wrong branch and incoming-task unit tests fail at runtime.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 966be45ef0
ℹ️ 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".
| if (this.currentTask) { | ||
| this.store.logger.info('CC-Widgets: handleMultiLoginCloseSession(): skipping alert due to active task', { | ||
| module: 'storeEventsWrapper.ts', | ||
| method: 'handleMultiLoginCloseSession', | ||
| }); | ||
| return; |
There was a problem hiding this comment.
Queue multi-login alert when task is active
Do not return here without persisting the event: when AgentMultiLoginCloseSession arrives during an active task, this branch drops the signal entirely, and setShowMultipleLoginAlert(true) is never called later after the task ends. Because this handler is the only place that flips that flag, affected agents can miss the forced-session-close warning in exactly the scenario where the modal is being suppressed.
Useful? React with 👍 / 👎.
| switchToMainCall, | ||
| logger | ||
| logger, | ||
| conferenceEnabled |
There was a problem hiding this comment.
conferenceEnabled is this not part of controls?
There was a problem hiding this comment.
Good question. conferenceEnabled is intentionally separate from controls.
controls.consult.mergeToConference comes from the SDK and tells us when merge is valid for the current task state. conferenceEnabled is an app-level override from the consumer (App.tsx / web component prop) to hide conference UI entirely, even if the SDK would show it.
| // Use the LATEST consult media, not the first. After transfer → re-consult | ||
| // the backend keeps the old consult media (with stale isHold=true) alongside | ||
| // the new one. Array.find() would return the old stale entry. | ||
| let consultMedia = findLatestConsultMedia(interaction); |
There was a problem hiding this comment.
this also should be from controls right?
There was a problem hiding this comment.
We considered using controls here, but for consult hold we deliberately derive state from task media, not uiControls.
activeLeg, switch, etc. have different lifecycle timing and caused false “Consult on hold” labels (e.g. during CONSULT_INITIATING). The wrap-up timer uses controls because that maps cleanly; consult hold does not.
We also use findLatestConsultMedia() because after transfer → re-consult the backend can keep stale consult media with isHold=true; taking the first media entry gives the wrong timer.
|
|
||
| logger.info('Consult transfer initiated', {module: 'useCallControl', method: 'consultTransfer'}); | ||
| await currentTask.consultTransfer(); | ||
| await currentTask.transfer(destination); |
There was a problem hiding this comment.
we should not pass any argument and the destination should be done from sdk itself
There was a problem hiding this comment.
Checked the SDK: task.transfer() requires { to, destinationType } — there is no no-arg overload. The old consultTransfer() is deprecated; voice tasks use transfer(payload)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f95af6e0fe
ℹ️ 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".
|
|
||
| logger.info('Consult transfer initiated', {module: 'useCallControl', method: 'consultTransfer'}); | ||
| await currentTask.consultTransfer(); | ||
| await currentTask.transfer(destination); |
There was a problem hiding this comment.
Use consultTransfer for consult handoff
In the non-conference consult path this now invokes currentTask.transfer(destination), which is the blind-transfer API, not the consult-transfer API. During an active consult this can execute the wrong transfer flow (or fail depending on backend routing rules), because consult handoff semantics are handled by consultTransfer(...) in the SDK. This regression affects agents who initiate consults and then press Transfer in normal (non-conference) consult sessions.
Useful? React with 👍 / 👎.
COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7779
This pull request addresses
The CC Widgets currently compute button visibility and enablement on the widget side using a complex combination of deviceType, featureFlags, conferenceEnabled, task state flags, and ~22 visibility functions in getControlsVisibility(). This approach duplicates logic that the SDK now handles internally through its state-machine-driven task.uiControls — a property on the ITask object where each of the 17 controls has { isVisible: boolean, isEnabled: boolean } computed from TaskState and TaskContext. This PR migrates all task widgets to consume task.uiControls as the single source of truth, eliminating widget-side control computation and aligning with the SDK's new architecture.
by making the following changes
Core migration — SDK uiControls as single source of truth:
Props removed (SDK handles internally):
Props restored (application-level overrides, not feature flags):
Hold state handling:
Transfer button mapping fix:
Type and Web Component updates:
Migration documentation:
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.