Skip to content

feat(contact-center): wxcc-6026 wxapp answer, mute sync, dtmf keypad - #734

Open
akulakum wants to merge 2 commits into
webex:nextfrom
akulakum:feature/WXCC-6026-wxapp-answer-WIDGETS
Open

feat(contact-center): wxcc-6026 wxapp answer, mute sync, dtmf keypad#734
akulakum wants to merge 2 commits into
webex:nextfrom
akulakum:feature/WXCC-6026-wxapp-answer-WIDGETS

Conversation

@akulakum

@akulakum akulakum commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

COMPLETES WXCC-6026

This pull request addresses

Third-party CRM embeds need Answer on Webex: agents working in Contact Center widgets should accept, decline, mute, and send DTMF from the embed while Webex App (thick client) handles telephony on the same machine and user.

This widgets PR wires the UI and store layer to the new SDK wxApp telephony APIs. Widgets do not call usersub or Mercury directly — that is SDK-owned.

by making the following changes

@webex/cc-task

  • Route wxApp offer Accept/Decline to acceptOnWebex() / rejectOnWebex() instead of standard task accept/decline.
  • Add wxapp-task.utils.ts — shared helpers (isWxAppEngagedCall, toggleMuteForTask, accept/decline routing).
  • CallControl: engaged wxApp mute via toggleMuteOnWebex({ muted }) with explicit UI intent (fixes Mercury desync); DTMF via transmitDtmfOnWebex().
  • IncomingTask: resolve live task from store.taskList so Accept stays enabled when uiControls update.
  • Unit tests for helper, wxApp utils, IncomingTask, CallControl, CallControlCAD.
  • Update task-spec.md (spec-currency).

@webex/cc-store

  • Listen for SDK TASK_WXAPP_MUTE_STATE_UPDATED per task; handleWxAppMuteStateUpdatedsetIsMuted() when task is currentTask.
  • Detach wxApp mute listener in handleTaskRemove (prevent duplicate/stale listeners).
  • Unit tests for wxApp mute sync wiring.
  • Update store-spec.md (spec-currency).

@webex/cc-components

  • Add in-call DTMF keypad component for wxApp engaged calls.
  • CallControl visibility/utils for wxApp offer/engaged states.
  • Snapshot and unit test updates.

Sample app (widgets-samples/cc/samples-cc-react-app)

  • Remove pre-init Enable Answer on Webex from SDK Toggles.
  • Add post-login Webex Calling (WxCC) fieldset gated on store.isAgentLoggedIn.
  • Toggle calls store.cc.setManageWebexCallingInWxcc() (usersub publish in SDK).

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

  • The testing is done with the amplify link

Automated (unit):

  • @webex/cc-task — wxApp accept/decline routing, toggleMuteForTask, CallControl mute/DTMF, IncomingTask live task resolution
  • @webex/cc-storeTASK_WXAPP_MUTE_STATE_UPDATED listener attach/detach, handleWxAppMuteStateUpdated
  • @webex/cc-components — CallControl snapshots and utils

Manual (end-to-end, with SDK #5167):

  • Extension station login → enable Webex Calling (WxCC) in sample app
  • Inbound wxApp offer → Accept / Decline from embed
  • Engaged call → mute/unmute embed ↔ Webex App (bidirectional sync)
  • DTMF keypad digits during engaged wxApp call
  • Toggle OFF / logout → SDK publishes usersub false (toast suppression cleared)

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Cursor
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

Checklist before merging

  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the testing document
  • I have tested the functionality with amplify link

Merge order: Merge SDK PR #5167 first (or bump @webex/contact-center in store before release). Widgets depend on SDK wxApp methods, TASK_WXAPP_MUTE_STATE_UPDATED, and setManageWebexCallingInWxcc().

Make sure to have followed the contributing guidelines before submitting.

@akulakum
akulakum requested a review from a team as a code owner August 13, 2026 07:42

@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: 5158542d05

ℹ️ 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 +999 to +1002
if (taskId && !this.wxAppMuteStateListeners[taskId]) {
const wxAppMuteListener = (payload: {muted: boolean}) => this.handleWxAppMuteStateUpdated(payload, task);
this.wxAppMuteStateListeners[taskId] = wxAppMuteListener;
task.on(TASK_EVENTS.TASK_WXAPP_MUTE_STATE_UPDATED, wxAppMuteListener);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Rebind the mute listener when the SDK replaces a task

When TASK_HYDRATE or TASK_MERGED supplies a replacement task object with the same interaction ID, registerTaskEventListeners is called again, but this ID-only guard skips attaching the mute listener to the replacement. Subsequent TASK_WXAPP_MUTE_STATE_UPDATED events emitted by the new task therefore never update store.isMuted, and removal also tries to detach the callback from the wrong task object. Track both the task and listener and detach/rebind when the task identity changes, as the adjacent real-time-assist listener does.

Useful? React with 👍 / 👎.


handleTaskEnd = () => {
this.setIsDeclineButtonEnabled(false);
this.setIsMuted(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.

P1 Badge Reset mute only when the current task ends

In a multi-task session, every task is registered with the same handleTaskEnd callback, so ending a background or digital task while the current wxApp call is muted unconditionally resets the global mute state. The UI then shows the active call as unmuted, and the next toggle derives muted: true instead of unmuting it. Pass the ending task identity into the handler or defer the reset to the existing current-task-aware removal path.

Useful? React with 👍 / 👎.

| 'toggleHold'
| 'toggleRecording'
| 'toggleMute'
| 'sendDtmf'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep the new DTMF callback backward-compatible

Any external consumer that directly renders the published CallControlComponent or CallControlCADComponent now fails type checking unless it supplies sendDtmf, even for calls where the keypad is never visible, because CallControlComponentProps is exported and the newly picked field is required. Make this callback optional with a safe default, or treat and document the change as a breaking major-version contract update.

Useful? React with 👍 / 👎.

Comment on lines +36 to +37
if (isWxAppCallingOffer(task) && typeof wxTask.acceptOnWebex === 'function') {
return wxTask.acceptOnWebex();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route the new wxApp operations through the store

For wxApp accept, reject, mute, and DTMF paths, this widget-package utility directly invokes newly duck-typed SDK task methods, moving SDK compatibility and dispatch outside the repository's sole SDK boundary. Expose these operations and their types from @webex/cc-store instead so SDK upgrades remain isolated to the store rather than coupling @webex/cc-task to the SDK.

AGENTS.md reference: AGENTS.md:L61-L62

Useful? React with 👍 / 👎.

@@ -0,0 +1,37 @@
import React from 'react';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the cc-components spec for the keypad surface

This change adds a new cc-components keypad and changes the exported CallControl prop surface, but only the task and store module specs were updated; packages/contact-center/cc-components/ai-docs/cc-components-spec.md remains unchanged. Update the owning module spec and public-contract documentation in this change so consumers and validators do not retain the old CallControl contract.

AGENTS.md reference: AGENTS.md:L68-L68

Useful? React with 👍 / 👎.

@aws-amplify-us-east-2

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-734.d1b38q61t1z947.amplifyapp.com

@akulakum akulakum added the validated Indicates that the PR is ready for actions label Aug 13, 2026
@github-actions github-actions Bot removed the validated Indicates that the PR is ready for actions label Aug 13, 2026

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

ℹ️ 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 +36 to +39
if (isWxAppCallingOffer(task) && typeof wxTask.acceptOnWebex === 'function') {
return wxTask.acceptOnWebex();
}
return task.accept();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bump the SDK before routing wxApp calls

When this commit is installed as-is, packages/contact-center/store/package.json remains pinned to @webex/contact-center 3.12.0-next.96 even though these methods and the new mute event come from the required companion SDK change. Because this helper duck-types the missing surface, wxApp offers silently fall through to the legacy accept()/decline() paths, mute falls through to toggleMute(), and DTMF becomes a no-op rather than exposing the incompatible dependency. Update the pinned SDK and lockfile to a release containing the new APIs before enabling these routes.

AGENTS.md reference: AGENTS.md:L56-L57

Useful? React with 👍 / 👎.

Comment on lines +877 to +880
if (!getKeypadControl(controls)?.isVisible) {
logger.warn('Keypad control not available', {module: 'useCallControl', method: 'sendDtmf'});
return;
}

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 Honor the keypad enabled state before sending tones

If the SDK updates keypad controls to {isVisible: true, isEnabled: false} while its popover is already open, the trigger becomes disabled but the rendered digit buttons remain clickable. This guard checks only isVisible, so those clicks still call transmitDtmfForTask() despite the SDK explicitly disabling DTMF; check isEnabled here and/or disable the individual keys.

Useful? React with 👍 / 👎.

| `ai-docs/_archive/.../task/ai-docs/widgets/TaskList/AGENTS.md` + `ARCHITECTURE.md` | architecture / overview / API | reconciled | Task selection / accept / decline flow → Sequence Diagram(s). |
| `packages/contact-center/ai-docs/migration/*.md` (7 files) | architecture (planned refactor) | reference-only | Describes a planned SDK `task.uiControls` migration that is NOT in current code. Used only to mark conflicts; current behavior documented as-is. |
| `packages/contact-center/task/src/` | source of truth | migrated | All requirements, flows, state, and error tables derive from real code here. |
| `packages/contact-center/ai-docs/features/thick-client-answer/intake.md` | feature intake (WXCC-6026) | reference-only (implemented) | wxApp Answer/Decline/Mute + Mercury mute sync — see § Feature: Accept on Webex thick client |

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 Commit the canonical intake before linking it

The newly declared canonical intake resolves to packages/contact-center/ai-docs/features/thick-client-answer/intake.md, but a repository-wide filename and WXCC-6026 search finds no such file or generated equivalent. Consequently the task and store specs both direct maintainers and validators to nonexistent feature evidence; add the intake in this change or retain the existing source-of-truth entry instead.

AGENTS.md reference: AGENTS.md:L68-L68

Useful? React with 👍 / 👎.

@akulakum akulakum added the validated Indicates that the PR is ready for actions label Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

validated Indicates that the PR is ready for actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant