Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ee97715
feat(webinar): refactor mercury to support multiple connections
mickelr Aug 11, 2025
08cec92
feat(webinar): refactor llm to support multiple connections
mickelr Aug 12, 2025
76b03e0
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Aug 13, 2025
747972e
feat(webinar): refactor llm to support multiple connections
mickelr Aug 15, 2025
769788a
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Aug 15, 2025
bf5d1cf
feat(webinar): refactor llm to support multiple connections
mickelr Aug 19, 2025
fc1e29d
feat(webinar): refactor llm to support multiple connections
mickelr Aug 19, 2025
4e78451
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 20, 2025
6314d63
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 20, 2025
333f9cc
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 21, 2025
ab6ed81
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 21, 2025
5c7965c
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 21, 2025
e637351
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 21, 2025
de644e1
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Aug 22, 2025
c2c2bdd
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Aug 25, 2025
417e82d
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 25, 2025
3e78f3f
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 25, 2025
6a38330
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 26, 2025
78d117c
feat(webinar): refactor meeting/index to support multiple connections
mickelr Aug 26, 2025
258cbb8
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Sep 2, 2025
cc31bf6
feat(webinar): refactor meeting/index to support multiple connections
mickelr Sep 3, 2025
024907d
feat(webinar): add set default socket func
mickelr Sep 3, 2025
ec9df82
feat(webinar): refactor webinar/index to support multiple connections
mickelr Sep 9, 2025
5aad590
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Sep 9, 2025
78af02d
feat(webinar): refactor webinar/index to support multiple connections
mickelr Sep 9, 2025
22328c4
feat(webinar): refactor webinar/index to support multiple connections
mickelr Sep 10, 2025
92c15a1
feat(webinar): refactor webinar/index to support multiple connections
mickelr Sep 10, 2025
751f4cf
feat(webinar): refactor mercury/llm to support multiple connections
mickelr Sep 11, 2025
7e3ac9f
Merge remote-tracking branch 'origin/next' into feat/mulitpleDataChannel
mickelr Sep 16, 2025
595af00
feat(webinar): refactor mercury/llm to support multiple connections
mickelr Sep 16, 2025
509ceeb
feat(webinar): refactor mercury/llm to support multiple connections
mickelr Sep 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/@webex/internal-plugin-llm/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
// eslint-disable-next-line import/prefer-default-export
export const LLM = 'llm';

export const LLM_DEFAULT_SESSION = 'llm-default-session';
134 changes: 101 additions & 33 deletions packages/@webex/internal-plugin-llm/src/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Mercury from '@webex/internal-plugin-mercury';

import {LLM} from './constants';
import {LLM, LLM_DEFAULT_SESSION} from './constants';
// eslint-disable-next-line no-unused-vars
import {ILLMChannel} from './llm.types';

Expand Down Expand Up @@ -42,90 +42,158 @@ export const config = {
*/
export default class LLMChannel extends (Mercury as any) implements ILLMChannel {
namespace = LLM;

defaultSessionId = LLM_DEFAULT_SESSION;
/**
* If the LLM plugin has been registered and listening
* @instance
* @type {Boolean}
* @public
* Map to store connection-specific data for multiple LLM connections
* @private
* @type {Map<string, {webSocketUrl?: string; binding?: string; locusUrl?: string; datachannelUrl?: string}>}
*/

private webSocketUrl?: string;

private binding?: string;

private locusUrl?: string;

private datachannelUrl?: string;
private connections: Map<
string,
{
webSocketUrl?: string;
binding?: string;
locusUrl?: string;
datachannelUrl?: string;
}
> = new Map();

/**
* Register to the websocket
* @param {string} llmSocketUrl
* @param {string} sessionId - Connection identifier
* @returns {Promise<void>}
*/
private register = (llmSocketUrl: string): Promise<void> =>
private register = (
llmSocketUrl: string,
sessionId: string = LLM_DEFAULT_SESSION
): Promise<void> =>
this.request({
method: 'POST',
url: llmSocketUrl,
body: {deviceUrl: this.webex.internal.device.url},
})
.then((res: {body: {webSocketUrl: string; binding: string}}) => {
this.webSocketUrl = res.body.webSocketUrl;
this.binding = res.body.binding;
// Get or create connection data
const sessionData = this.connections.get(sessionId) || {};
sessionData.webSocketUrl = res.body.webSocketUrl;
sessionData.binding = res.body.binding;
this.connections.set(sessionId, sessionData);
})
.catch((error: any) => {
this.logger.error(`Error connecting to websocket: ${error}`);
this.logger.error(`Error connecting to websocket for ${sessionId}: ${error}`);
throw error;
});

/**
* Register and connect to the websocket
* @param {string} locusUrl
* @param {string} datachannelUrl
* @param {string} sessionId - Connection identifier
* @returns {Promise<void>}
*/
public registerAndConnect = (locusUrl: string, datachannelUrl: string): Promise<void> =>
this.register(datachannelUrl).then(() => {
public registerAndConnect = (
locusUrl: string,
datachannelUrl: string,
sessionId: string = LLM_DEFAULT_SESSION
): Promise<void> =>
this.register(datachannelUrl, sessionId).then(() => {
if (!locusUrl || !datachannelUrl) return undefined;
this.locusUrl = locusUrl;
this.datachannelUrl = datachannelUrl;
this.connect(this.webSocketUrl);

// Get or create connection data
const sessionData = this.connections.get(sessionId) || {};
sessionData.locusUrl = locusUrl;
sessionData.datachannelUrl = datachannelUrl;
this.connections.set(sessionId, sessionData);
console.error(
`registerAndConnect(${sessionId}) --> channel is ${datachannelUrl}! -->websocketurl is ${sessionData.webSocketUrl}`
);

return this.connect(sessionData.webSocketUrl, sessionId);
});

/**
* Tells if LLM socket is connected
* @param {string} sessionId - Connection identifier
* @returns {boolean} connected
*/
public isConnected = (): boolean => this.connected;
public isConnected = (sessionId = LLM_DEFAULT_SESSION): boolean => {
const socket = this.getSocket(sessionId);

return socket ? socket.connected : false;
};

/**
* Tells if LLM socket is binding
* @param {string} sessionId - Connection identifier
* @returns {string} binding
*/
public getBinding = (): string => this.binding;
public getBinding = (sessionId = LLM_DEFAULT_SESSION): string => {
const sessionData = this.connections.get(sessionId);

return sessionData?.binding || '';
};

/**
* Get Locus URL for the connection
* @param {string} sessionId - Connection identifier
* @returns {string} locus Url
*/
public getLocusUrl = (): string => this.locusUrl;
public getLocusUrl = (sessionId = LLM_DEFAULT_SESSION): string => {
const sessionData = this.connections.get(sessionId);

return sessionData?.locusUrl || '';
};

/**
* Get data channel URL for the connection
* @param {string} sessionId - Connection identifier
* @returns {string} data channel Url
*/
public getDatachannelUrl = (): string => this.datachannelUrl;
public getDatachannelUrl = (sessionId = LLM_DEFAULT_SESSION): string => {
const sessionData = this.connections.get(sessionId);

return sessionData?.datachannelUrl || '';
};

/**
* Disconnects websocket connection
* @param {{code: number, reason: string}} options - The disconnect option object with code and reason
* @param {string} sessionId - Connection identifier
* @returns {Promise<void>}
*/
public disconnectLLM = (
options: {code: number; reason: string},
sessionId: string = LLM_DEFAULT_SESSION
): Promise<void> =>
this.disconnect(options, sessionId).then(() => {
// Clean up sessions data
console.error(`disconnectLLM(${sessionId})`);
this.connections.delete(sessionId);
});

/**
* Disconnects all LLM websocket connections
* @param {{code: number, reason: string}} options - The disconnect option object with code and reason
* @returns {Promise<void>}
*/
public disconnectLLM = (options: object): Promise<void> =>
this.disconnect(options).then(() => {
this.locusUrl = undefined;
this.datachannelUrl = undefined;
this.binding = undefined;
this.webSocketUrl = undefined;
public disconnectAllLLM = (options?: {code: number; reason: string}): Promise<void> =>
this.disconnectAll(options).then(() => {
// Clean up all connection data
this.connections.clear();
});

/**
* Get all active LLM connections
* @returns {Map} Map of sessionId to session data
*/
public getAllConnections = (): Map<
string,
{
webSocketUrl?: string;
binding?: string;
locusUrl?: string;
datachannelUrl?: string;
}
> => new Map(this.connections);
}
25 changes: 20 additions & 5 deletions packages/@webex/internal-plugin-llm/src/llm.types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
interface ILLMChannel {
registerAndConnect: (locusUrl: string, datachannelUrl: string) => Promise<void>;
isConnected: () => boolean;
getBinding: () => string;
getLocusUrl: () => string;
disconnectLLM: (options: {code: number; reason: string}) => Promise<void>;
registerAndConnect: (
locusUrl: string,
datachannelUrl: string,
sessionId?: string
) => Promise<void>;
isConnected: (sessionId?: string) => boolean;
getBinding: (sessionId?: string) => string;
getLocusUrl: (sessionId?: string) => string;
getDatachannelUrl: (sessionId?: string) => string;
disconnectLLM: (options: {code: number; reason: string}, sessionId?: string) => Promise<void>;
disconnectAllLLM: (options?: {code: number; reason: string}) => Promise<void>;
getAllConnections: () => Map<
string,
{
webSocketUrl?: string;
binding?: string;
locusUrl?: string;
datachannelUrl?: string;
}
>;
}
// eslint-disable-next-line import/prefer-default-export
export type {ILLMChannel};
Loading
Loading