Skip to content

feat(ccwidgets): merge rtt with next#666

Merged
Kesari3008 merged 13 commits intowebex:nextfrom
Kesari3008:merge-rtt-with-next
Apr 15, 2026
Merged

feat(ccwidgets): merge rtt with next#666
Kesari3008 merged 13 commits intowebex:nextfrom
Kesari3008:merge-rtt-with-next

Conversation

@Kesari3008
Copy link
Copy Markdown
Contributor

@Kesari3008 Kesari3008 commented Apr 1, 2026

COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7783

This pull request addresses

Merging the feature branch created for rtt with next

by making the following changes

Merging the feature branch created for rtt with next

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

https://app.vidcast.io/share/06138e83-f481-4598-81ef-4f72c4ea04c3

Have test conference and consult flows in Agent desktop and in Widgets, behavior is consistent:

Screenshot 2026-04-14 at 4 40 18 PM Screenshot 2026-04-14 at 4 59 28 PM
  • The testing is done with the amplify link

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 - Please Specify
  • 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

Make sure to have followed the contributing guidelines before submitting.

@Kesari3008 Kesari3008 requested a review from a team as a code owner April 1, 2026 13:13
@Kesari3008 Kesari3008 added validated Indicates that the PR is ready for actions run_e2e Add this label to run E2E test for meeting and CC widgets labels Apr 1, 2026
@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-666.d1b38q61t1z947.amplifyapp.com

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: f75a3c08dc

ℹ️ 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".

Comment on lines +192 to +196
return transcriptLines.map((line, index) => {
const payload: RealtimeTranscriptionData = {
messageId: line.messageId,
conversationId: line.conversationId,
role: line.role,
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 Filter realtime transcript lines by current task

useRealtimeTranscript receives currentTaskId but maps every item in realtimeTranscriptLines without task/conversation filtering. Since the store subscribes transcription events on each task, multi-task sessions will show utterances from other interactions in the currently selected task transcript, which can leak cross-call content and corrupt the UI. Filter by the selected task (or store a task identifier on each line) before mapping.

Useful? React with 👍 / 👎.

Comment on lines +31 to +35
aria-selected={activeTab === 'live'}
className={`real-time-transcript__tab ${activeTab === 'live' ? 'real-time-transcript__tab--active' : ''}`.trim()}
onClick={() => onTabChange?.('live')}
data-testid="real-time-transcript:live-tab"
>
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 Add an IVR tab trigger to the transcript tablist

The component models two tabs ('ivr' | 'live') and has separate IVR rendering, but the tablist renders only a Live tab and its handler only emits 'live'. In the default state, users have no in-component way to switch to IVR content, so ivrTranscript is effectively inaccessible unless a parent forces activeTab='ivr' externally.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 5c933ce8eb

ℹ️ 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".

CallControlCAD,
store,
OutdialCall,
RealtimeTranscript,
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 Import RealTimeTranscript using the exported symbol name

@webex/cc-widgets now exports the widget as RealTimeTranscript, but this sample imports RealtimeTranscript (lowercase t in Time). In environments that type-check or validate ESM named imports, this causes a build/runtime failure (RealtimeTranscript is undefined), so the new sample toggle cannot render the transcript widget.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@mkesavan13 mkesavan13 left a comment

Choose a reason for hiding this comment

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

I went back to SDK PR#4794 to realize that the transcripts are being started always based on certain events:

export const TRANSCRIPT_EVENT_MAP = {
  [CC_EVENTS.AGENT_CONTACT_ASSIGNED]: 'START',
  [CC_EVENTS.AGENT_CONSULTING]: 'START',
  [CC_EVENTS.AGENT_CONSULT_CONFERENCED]: 'START',
  [CC_EVENTS.AGENT_WRAPUP]: 'STOP',
  [CC_EVENTS.AGENT_CONSULT_ENDED]: 'STOP',
  [CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE]: 'STOP', 
};

However, what if the developer doesn't want to enable transcript from SDK or in this case, the RTT widget isn't included by the developer?


‼️ Also, let's change the PR title to match semantic-release format

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't it still be "transcripts" because it is not one transcript you get?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

feature says real time transcript and everywhere we are keeping without s so to make it consistent I changed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When you say, "feature says", where is this?

I was trying to find the help doc and the help doc says real time transcripts in plural?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I checked in AgentDesktop Code and contact center announcements for this feature. Let me know if you still want it to be changed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we remove this file change? Looks like they're only quotes and spacing change that's unnecessary

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed

<section className={`real-time-transcript ${className || ''}`.trim()} data-testid="real-time-transcript:root">
<div className="real-time-transcript__content" data-testid="real-time-transcript:live-content">
{sortedEntries.length === 0 ? (
<div className="real-time-transcript__empty">No live transcript available.</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be behind a constant so that we can do i18n later?

Comment on lines +773 to +779
const normalizedRealtimeData = {
...data,
role,
caller,
content: (payload?.content || data.content || '').trim(),
publishTimestamp: Number.isNaN(publishTimestamp) ? Date.now() : publishTimestamp,
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Couldn't we have encapsulated this normalization in the SDK itself so that other SDK users also benefitted from it?

We could have the raw data but also the normalized one?

Or better, we handle this whole merging of transcripts at the SDK itself and just send the new list of transcripts to Widgets?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is to be able to provide control to the consumers. As of now we do not know how each consumer would like to handle these event data so that's why I have kept it in widgets.

@Kesari3008
Copy link
Copy Markdown
Contributor Author

I went back to SDK PR#4794 to realize that the transcripts are being started always based on certain events:

export const TRANSCRIPT_EVENT_MAP = {
  [CC_EVENTS.AGENT_CONTACT_ASSIGNED]: 'START',
  [CC_EVENTS.AGENT_CONSULTING]: 'START',
  [CC_EVENTS.AGENT_CONSULT_CONFERENCED]: 'START',
  [CC_EVENTS.AGENT_WRAPUP]: 'STOP',
  [CC_EVENTS.AGENT_CONSULT_ENDED]: 'STOP',
  [CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE]: 'STOP', 
};

However, what if the developer doesn't want to enable transcript from SDK or in this case, the RTT widget isn't included by the developer?

‼️ Also, let's change the PR title to match semantic-release format

AGENT_CONTACT_ASSIGNED is an event that happens for any incoming call and for consult offer, it is going to be CONSULTING so transcriptions are basically supposed to start for any incoming accepted task. RealTime transcription enablement is actually dependent on if the feature is enabled from control hub setting

@Kesari3008 Kesari3008 changed the title Merge rtt with next feat(ccwidgets): merge rtt with next Apr 13, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: a8fb0ad9e9

ℹ️ 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".

Comment on lines +734 to +735
const transcriptData = payload.data;
if (!transcriptData?.messageId) 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.

P1 Badge Normalize transcription payload before reading messageId

handleRealtimeTranscription assumes the SDK callback shape is always { data: ... } and immediately reads payload.data, so any realtime event emitted as a direct transcript object is treated as missing messageId and ignored. In that environment, the widget never renders live transcript lines even though events are arriving. This mismatch is also reflected by the new test case in this commit that sends a direct payload and expects it to be accepted.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 3898f6db3d

ℹ️ 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".

Comment on lines +750 to +754
const newTranscriptData = {
...transcriptData,
role,
content,
publishTimestamp: normalizedPublishTimestamp,
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 Persist actionEvent when storing transcript updates

handleRealtimeTranscription currently stores only payload.data, so notifDetails.actionEvent is discarded before data reaches useRealTimeTranscript. In sessions where the SDK emits action/tombstone transcript updates, those events never appear in the widget even though RealTimeTranscriptEntry and the component support rendering event rows, resulting in missing live transcript context.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: cc968f31b0

ℹ️ 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".

Comment on lines +467 to +469
const removedTaskId = taskToRemove.data?.interactionId;
if (removedTaskId && this.store.currentTask?.data?.interactionId === removedTaskId) {
this.store.realtimeTranscriptionData = [];
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 Preserve transcripts for remaining active tasks

Clearing this.store.realtimeTranscriptionData when the removed task is the current task wipes transcript history for all tasks, not just the ended one. In multi-task sessions, transcription listeners are registered per task, so another active interaction can already have lines in this shared array; ending the current task will erase those lines and the remaining task transcript appears empty until new chunks arrive. Remove only the ended task's entries (or key storage by task/conversation) instead of resetting the whole array.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/pull-request.yml Outdated
if (taskToRemove) {
const removedTaskId = taskToRemove.data?.interactionId;
if (removedTaskId && this.store.currentTask?.data?.interactionId === removedTaskId) {
this.store.realtimeTranscriptionData = [];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be wrapped in runInAction

Comment thread packages/contact-center/ui-logging/src/metricsLogger.ts
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When you say, "feature says", where is this?

I was trying to find the help doc and the help doc says real time transcripts in plural?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why are we extending outdial call tests as part of this PR?

Copy link
Copy Markdown
Contributor Author

@Kesari3008 Kesari3008 Apr 15, 2026

Choose a reason for hiding this comment

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

These tests were failing in the pipeline and in my local as well, not sure why that was happening because there is no change in outdial code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's strange. What if we take a fresh clone of next branch? Do we see the same error there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes I did pull fresh next branch before adding this and it was still failing for me yesterday. I found it strange too. I can try it again today and if it is not needed, I will remove it

Comment thread packages/contact-center/store/src/storeEventsWrapper.ts
Copy link
Copy Markdown
Contributor

@mkesavan13 mkesavan13 left a comment

Choose a reason for hiding this comment

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

While the outdial flakyness was a mystery, the changes still are good improvements. So approving the PR.

@Kesari3008 Kesari3008 merged commit f566438 into webex:next Apr 15, 2026
7 of 8 checks passed
@github-actions
Copy link
Copy Markdown

🎉 Your changes are now available!
Released in: webex-cc-widgets-v1.28.0-next.35
📖 View full changelog →
Packages Updated Version
@webex/cc-widgets 1.28.0-next.35
@webex/cc-components 1.28.0-next.25
@webex/cc-digital-channels 0.0.0-next.10
@webex/cc-station-login 1.28.0-next.25
@webex/cc-store 1.28.0-next.14
@webex/cc-task 1.28.0-next.28
@webex/cc-ui-logging 1.28.0-next.15
@webex/cc-user-state 1.28.0-next.26
@webex/test-fixtures 0.0.0-next.1
samples-cc-react-app 0.0.0-next.1
samples-cc-wc-app 0.0.0-next.1

Thank you for your contribution!
🤖 This is an automated message. For queries, please contact support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run_e2e Add this label to run E2E test for meeting and CC widgets validated Indicates that the PR is ready for actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants