Skip to content

feat(contact-center): realtime ws implementation#4815

Merged
Kesari3008 merged 16 commits intowebex:nextfrom
Kesari3008:Realtime-WS-Implementation
Mar 27, 2026
Merged

feat(contact-center): realtime ws implementation#4815
Kesari3008 merged 16 commits intowebex:nextfrom
Kesari3008:Realtime-WS-Implementation

Conversation

@Kesari3008
Copy link
Copy Markdown
Contributor

@Kesari3008 Kesari3008 commented Mar 27, 2026

COMPLETES

This pull request addresses

New real time websocket implementation

by making the following changes

New real time websocket implementation

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/c2d427f6-2b17-40ea-8eda-7ffe73e58483?playerMode=vidcast

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

I certified that

  • I have read and followed contributing guidelines
  • I discussed changes with code owners prior to submitting this pull request
  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the documentation accordingly

Make sure to have followed the contributing guidelines before submitting.

@Kesari3008 Kesari3008 requested a review from a team as a code owner March 27, 2026 08:21
@Kesari3008 Kesari3008 added the validated If the pull request is validated for automation. label Mar 27, 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: e029090a01

ℹ️ 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 +610 to +611
if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
this.services.rtdWebSocketManager.close(false, 'Unregistering the RTD websocket');
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 Guard RTD websocket close for non-RTD sessions

deregister() now attempts to close rtdWebSocketManager whenever isSocketClosed is false, but RTD is optional and may never be initialized when aiFeature.realtimeTranscripts.enable is off. In that path, WebSocketManager still has the constructor placeholder (this.websocket = {}), so close() calls this.websocket.close() and throws, causing deregistration to fail for agents who never opened the RTD socket.

Useful? React with 👍 / 👎.

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.

Addressed

Comment on lines +49 to +53
resource: string;
}): Promise<WelcomeResponse> {
const {body: connectionConfig, resource} = options;
try {
await this.register(connectionConfig);
await this.register(connectionConfig, resource);
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 Preserve default subscribe endpoint in websocket init

This refactor makes initWebSocket() depend on a caller-provided resource, but existing registration flow still calls initWebSocket({ body: ... }) for the primary socket in cc.connectWebsocket(). That means the main subscribe request can be issued with resource: undefined in runtime paths without strict TS enforcement, breaking the core websocket registration. Add a SUBSCRIBE_API default here or update all callers to pass a resource.

Useful? React with 👍 / 👎.

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.

Addressed

constructor(options: {webex: WebexSDK; connectionConfig: SubscribeRequest}) {
const {webex, connectionConfig} = options;
this.webSocketManager = new WebSocketManager({webex});
this.rtdWebSocketManager = new WebSocketManager({webex});
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 reconnect wiring for RTD websocket manager

A second websocket manager is created for RTD, but only webSocketManager is wired into ConnectionService (the component that reacts to socketClose and re-initializes subscriptions). As a result, after network drops/keepalive timeouts, RTD can stay disconnected even if the primary websocket recovers, so transcript events silently stop until full re-registration.

Useful? React with 👍 / 👎.

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.

P2 Badge Add reconnect wiring for RTD websocket manager

A second websocket manager is created for RTD, but only webSocketManager is wired into ConnectionService (the component that reacts to socketClose and re-initializes subscriptions). As a result, after network drops/keepalive timeouts, RTD can stay disconnected even if the primary websocket recovers, so transcript events silently stop until full re-registration.

Useful? React with 👍 / 👎.

check this if its valid. if yes lets have note for upcoming PR.

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: 6645108bc1

ℹ️ 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 eventPayload = payload.data || payload.data.data;

task.emit(eventType, eventPayload);
task.emit(payload.data.type, payload.data);
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 top-level type when re-emitting task events

This re-emit path now always uses payload.data.type, even though the same function still accepts task events via payload.data.type || payload.type when deciding whether to process them. For websocket payloads that carry task event names only at the top level (payload.type) and omit data.type, task.emit now fires with an undefined event name, so consumers listening for task lifecycle events will miss those notifications. The previous fallback behavior handled both shapes.

Useful? React with 👍 / 👎.

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.

We have 2 different websocket connections so this will not be a conern

data?: {conversationId?: string};
conversationId?: string;
};
};
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 create a type for this and use it?

const eventPayload = payload.data || payload.data.data;

task.emit(eventType, eventPayload);
task.emit(payload.data.type, payload.data);
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 u re-check this again we were doing below (payload.type is first priority)

const eventType = payload.type || payload.data.type;

Copy link
Copy Markdown
Contributor Author

@Kesari3008 Kesari3008 Mar 27, 2026

Choose a reason for hiding this comment

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

Discussed it. This doesn't need to be addressed as this change was introduced in previous PR istelf

constructor(options: {webex: WebexSDK; connectionConfig: SubscribeRequest}) {
const {webex, connectionConfig} = options;
this.webSocketManager = new WebSocketManager({webex});
this.rtdWebSocketManager = new WebSocketManager({webex});
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.

P2 Badge Add reconnect wiring for RTD websocket manager

A second websocket manager is created for RTD, but only webSocketManager is wired into ConnectionService (the component that reacts to socketClose and re-initializes subscriptions). As a result, after network drops/keepalive timeouts, RTD can stay disconnected even if the primary websocket recovers, so transcript events silently stop until full re-registration.

Useful? React with 👍 / 👎.

check this if its valid. if yes lets have note for upcoming PR.

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.

Had a sit down review with Priya and Ravi on call. Changes look good to me. A couple of things to handle in the future:

  • Condition while connecting the RTD web socket. Right now, it only checks if RTT is enabled
  • The handleRtdWebSocketMessage method might need to change conditionally to call between RTT and other AI features.

These aren't blockers, just notes for future. Approving the PR

@Kesari3008 Kesari3008 enabled auto-merge (squash) March 27, 2026 13:06
@Kesari3008 Kesari3008 merged commit 4997118 into webex:next Mar 27, 2026
11 checks passed
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: 9ee792ab0a

ℹ️ 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 +778 to +783
.catch((error) => {
LoggerProxy.error(`Error during RTD websocket setup: ${error}`, {
module: CC_FILE,
method: METHODS.CONNECT_WEBSOCKET,
});
});
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 Fail registration when RTD websocket setup fails

The RTD websocket initialization error is caught and only logged here, so register() still returns success even when the realtime subscribe/connect path failed. In that failure path (for example, auth/network errors on v1/realtime/subscribe), the SDK keeps the realtime transcript feature enabled but never receives transcript events and has no RTD reconnect wiring, which creates a silent partial-registration state for clients. Consider propagating this failure (or explicitly disabling realtime transcripts and surfacing a status event) instead of swallowing it.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown

🎉 Your changes are now available!
Released in: v3.12.0-next.2
📖 View full changelog →
Packages Updated Version
webex 3.12.0-next.2
@webex/contact-center 3.12.0-next.1

Thank you for your contribution!
🤖 This is an automated message. For questions, please refer to the documentation.

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

Labels

validated If the pull request is validated for automation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants