@webex/internal-plugin-voicea 3.12.0-llmrefactor.7 → 3.12.0-llmrefactor.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"names":["_events","_interopRequireDefault","require","_uuid","_webexCore","_constants","_utils","ownKeys","e","r","t","_Object$keys","_Object$getOwnPropertySymbols","o","filter","_Object$getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","Object","forEach","_defineProperty2","default","_Object$getOwnPropertyDescriptors","_Object$defineProperties","_Object$defineProperty","_callSuper","_getPrototypeOf2","_possibleConstructorReturn2","_isNativeReflectConstruct","_Reflect$construct","constructor","Boolean","prototype","valueOf","call","VoiceaChannel","exports","_EventEmitter","llmChannel","request","_this","_classCallCheck2","_e$headers","seqNum","sequenceNumber","data","relayType","AIBRIDGE_RELAY_TYPES","VOICEA","ANNOUNCEMENT","onCaptionServiceIdUpdate","headers","from","announceStatus","ANNOUNCE_STATUS","JOINED","processAnnouncementMessage","voiceaPayload","TRANSLATION_RESPONSE","processCaptionLanguageResponse","TRANSCRIPTION","processTranscription","SPEAKER_NAME_UPDATE","processSpeakerNameUpdate","MANUAL","CAPTIONER","processManualTranscription","transcriptPayload","sender","data_source","type","TRANSCRIPTION_TYPE","MANUAL_CAPTION_FINAL_RESULT","MANUAL_CAPTION_INTERIM_RESULT","emit","EVENT_TRIGGERS","NEW_MANUAL_CAPTION","isFinal","transcriptId","id","transcripts","source","SPEAKER_NAME_UPDATED","_voiceaPayload$transc","_voiceaPayload$highli","_voiceaPayload$highli2","_voiceaPayload$highli3","_voiceaPayload$highli4","_voiceaPayload$highli5","_voiceaPayload$highli6","_voiceaPayload$highli7","TRANSCRIPT_INTERIM_RESULTS","NEW_CAPTION","transcript_id","TRANSCRIPT_FINAL_RESULT","map","transcript","timestamp","millisToMinutesAndSeconds","end_millis","HIGHLIGHT_CREATED","csis","highlight","highlightId","highlight_id","text","highlightLabel","highlight_label","highlightSource","highlight_source","EVA_THANKS","EVA_COMMAND","isListening","command_response","EVA_WAKE","EVA_CANCEL","LANGUAGE_DETECTED","isInSpokenLanguages","spokenLanguages","includes","language","languageCode","statusCode","CAPTION_LANGUAGE_UPDATE","errorCode","errorMessage","message","_voiceaPayload$transl","_voiceaPayload$transl2","_voiceaPayload$transl3","_voiceaPayload$transl4","_voiceaPayload$ASR$sp","_voiceaPayload$ASR","_voiceaPayload$ASR$sp2","_voiceaPayload$ASR2","voiceaLanguageOptions","captionLanguages","translation","allowed_languages","maxLanguages","max_languages","ASR","spoken_languages","currentSpokenLanguage","VOICEA_ANNOUNCEMENT","isConnected","keepTranscriptionSubscribed","JOINING","socket","getSocket","binding","getBinding","payload","concat","recipients","route","captionServiceId","to","clientPayload","version","eventType","CLIENT_ANNOUNCEMENT","trackingId","config","trackingIdPrefix","uuid","v4","toString","send","languageAssignment","method","url","getLocusUrl","body","transcribe","spokenLanguage","then","SPOKEN_LANGUAGE_UPDATE","isLLMConnected","translationLanguage","TRANSLATION_REQUEST","currentCaptionLanguage","timeStamp","start_millis","captionStatus","TURN_ON_CAPTION_STATUS","SENDING","locusUrl","caption","CAPTIONS_TURNED_ON","areCaptionsEnabled","ENABLED","announce","updateSubchannelSubscriptionsAndSyncCaptionState","subscribe","catch","error","IDLE","Error","isAnnounceProcessed","sendAnnouncement","_ref","_asyncToGenerator2","_regenerator","mark","_callee","wrap","_context","prev","next","abrupt","undefined","requestTurnOnCaptions","stop","_x","activate","transcribing","turnOnCaptions","enable","toggleManualCaptionStatus","TOGGLE_MANUAL_CAPTION_STATUS","manualCaption","meetingId","serviceId","requestLanguage","_callee2","_ref3","_ref3$subscribe","_ref3$unsubscribe","unsubscribe","isDataChannelTokenEnabled","datachannelUrl","_args2","_context2","sent","getDatachannelUrl","datachannelUri","options","keepSubscribed","updateSubchannelSubscriptions","DEFAULT_SPOKEN_LANGUAGE","on","eventProcessor","hasSubscribedToEvents","_inherits2","_createClass2","key","value","deregisterEvents","off","_switchLLMChannel","_callee3","newLLMChannel","captionsWereOn","_context3","switchLLMChannel","_x2","EventEmitter","_default"],"sources":["voicea.ts"],"sourcesContent":["import EventEmitter from 'events';\nimport uuid from 'uuid';\n// @ts-ignore - webex-core types\nimport {config} from '@webex/webex-core';\n\n// @ts-ignore - internal-plugin-llm types\nimport type LLMChannel from '@webex/internal-plugin-llm';\nimport {\n EVENT_TRIGGERS,\n AIBRIDGE_RELAY_TYPES,\n TRANSCRIPTION_TYPE,\n ANNOUNCE_STATUS,\n TURN_ON_CAPTION_STATUS,\n TOGGLE_MANUAL_CAPTION_STATUS,\n DEFAULT_SPOKEN_LANGUAGE,\n} from './constants';\nimport {\n AnnouncementPayload,\n CaptionLanguageResponse,\n SpeakerNameUpdatePayload,\n TranscriptionResponse,\n IVoiceaChannel,\n} from './voicea.types';\nimport {millisToMinutesAndSeconds} from './utils';\n\n/**\n * @description VoiceaChannel — handles voicea/transcription functionality for a single LLM connection.\n * Created via `webex.internal.voicea.createChannel(llmChannel)`. The caller owns the\n * channel and is responsible for its lifecycle.\n * @export\n * @class VoiceaChannel\n */\nexport class VoiceaChannel extends EventEmitter implements IVoiceaChannel {\n private request: (options: {method: string; url: string; body?: object}) => Promise<any>;\n private llmChannel: LLMChannel;\n\n private seqNum: number;\n private areCaptionsEnabled: boolean;\n private hasSubscribedToEvents = false;\n private captionServiceId?: string;\n private announceStatus: string;\n private captionStatus: string;\n\n private keepTranscriptionSubscribed: boolean;\n\n private toggleManualCaptionStatus: string;\n private currentSpokenLanguage?: string;\n private spokenLanguages: string[] = [];\n private currentCaptionLanguage?: string;\n\n /**\n * Creates a VoiceaChannel bound to the given LLMChannel\n * @param {LLMChannel} llmChannel - The LLM channel to use\n * @param {Function} request - The request function for making API calls (typically webex.request bound to webex)\n */\n constructor(\n llmChannel: LLMChannel,\n request: (options: {method: string; url: string; body?: object}) => Promise<any>\n ) {\n super();\n this.llmChannel = llmChannel;\n this.request = request;\n\n this.seqNum = 1;\n this.areCaptionsEnabled = false;\n this.captionServiceId = undefined;\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n this.currentSpokenLanguage = DEFAULT_SPOKEN_LANGUAGE;\n this.currentCaptionLanguage = undefined;\n this.keepTranscriptionSubscribed = false;\n\n // Subscribe to relay events from the LLM channel\n this.llmChannel.on('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = true;\n }\n\n /**\n * Process events from LLM channel\n * @param {Object} e - Event data\n * @returns {void}\n */\n private eventProcessor = (e: any): void => {\n this.seqNum = e.sequenceNumber + 1;\n switch (e.data.relayType) {\n case AIBRIDGE_RELAY_TYPES.VOICEA.ANNOUNCEMENT:\n this.onCaptionServiceIdUpdate(e.headers.from);\n this.announceStatus = ANNOUNCE_STATUS.JOINED;\n this.processAnnouncementMessage(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.TRANSLATION_RESPONSE:\n this.processCaptionLanguageResponse(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.TRANSCRIPTION:\n this.processTranscription(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.SPEAKER_NAME_UPDATE:\n this.processSpeakerNameUpdate(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.MANUAL.TRANSCRIPTION:\n case AIBRIDGE_RELAY_TYPES.MANUAL.CAPTIONER:\n this.processManualTranscription({\n ...e.data.transcriptPayload,\n sender: e.headers?.from,\n data_source: e.data.relayType,\n });\n break;\n default:\n break;\n }\n };\n\n /**\n * Deregister events and clean up\n * @returns {void}\n */\n public deregisterEvents(): void {\n this.areCaptionsEnabled = false;\n this.keepTranscriptionSubscribed = false;\n this.captionServiceId = undefined;\n\n if (this.hasSubscribedToEvents) {\n this.llmChannel.off('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = false;\n }\n\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n this.currentSpokenLanguage = undefined;\n this.currentCaptionLanguage = undefined;\n }\n\n /**\n * Switch to a different LLM channel while preserving caption state.\n * Used when transitioning between main meeting and practice session.\n * - Preserves keepTranscriptionSubscribed and spokenLanguage state\n * - Unsubscribes from old channel, subscribes to new channel\n * - Re-announces and re-enables captions if they were on\n * @param {LLMChannel} newLLMChannel - The new LLM channel to switch to\n * @returns {Promise<void>}\n */\n public async switchLLMChannel(newLLMChannel: LLMChannel): Promise<void> {\n // Save current state\n const captionsWereOn = this.keepTranscriptionSubscribed;\n const spokenLanguage = this.currentSpokenLanguage;\n\n // Unsubscribe from old channel\n if (this.hasSubscribedToEvents && this.llmChannel) {\n this.llmChannel.off('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = false;\n }\n\n // Switch to new channel\n this.llmChannel = newLLMChannel;\n\n // Subscribe to new channel\n this.llmChannel.on('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = true;\n\n // Reset announcement state for new connection\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.captionServiceId = undefined;\n this.areCaptionsEnabled = false;\n\n // Re-announce and re-enable captions if they were on\n if (captionsWereOn) {\n await this.turnOnCaptions(spokenLanguage);\n }\n }\n\n /**\n * Process manual Transcript and send alert\n * @param {TranscriptionResponse} transcriptPayload\n * @returns {void}\n */\n private processManualTranscription = (transcriptPayload: TranscriptionResponse): void => {\n if (\n transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT ||\n transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_INTERIM_RESULT\n ) {\n this.emit(EVENT_TRIGGERS.NEW_MANUAL_CAPTION, {\n isFinal: transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT,\n transcriptId: transcriptPayload.id,\n transcripts: transcriptPayload.transcripts,\n sender: transcriptPayload.sender,\n source: transcriptPayload.data_source,\n });\n }\n };\n\n /**\n * Process speaker name update and send alert\n * @param {SpeakerNameUpdatePayload} voiceaPayload\n * @returns {void}\n */\n private processSpeakerNameUpdate = (voiceaPayload: SpeakerNameUpdatePayload): void => {\n // @ts-ignore\n this.emit(EVENT_TRIGGERS.SPEAKER_NAME_UPDATED, voiceaPayload);\n };\n\n /**\n * Process Transcript and send alert\n * @param {TranscriptionResponse} voiceaPayload\n * @returns {void}\n */\n private processTranscription = (voiceaPayload: TranscriptionResponse): void => {\n switch (voiceaPayload.type) {\n case TRANSCRIPTION_TYPE.TRANSCRIPT_INTERIM_RESULTS:\n this.emit(EVENT_TRIGGERS.NEW_CAPTION, {\n isFinal: false,\n transcriptId: voiceaPayload.transcript_id,\n transcripts: voiceaPayload.transcripts,\n });\n break;\n\n case TRANSCRIPTION_TYPE.TRANSCRIPT_FINAL_RESULT:\n this.emit(EVENT_TRIGGERS.NEW_CAPTION, {\n isFinal: true,\n transcriptId: voiceaPayload.transcript_id,\n transcripts: voiceaPayload.transcripts?.map((transcript) => {\n transcript.timestamp = millisToMinutesAndSeconds(transcript.end_millis);\n\n return transcript;\n }),\n });\n break;\n\n case TRANSCRIPTION_TYPE.HIGHLIGHT_CREATED:\n this.emit(EVENT_TRIGGERS.HIGHLIGHT_CREATED, {\n csis: voiceaPayload.highlight?.csis,\n highlightId: voiceaPayload.highlight?.highlight_id,\n text: voiceaPayload.highlight?.transcript,\n highlightLabel: voiceaPayload.highlight?.highlight_label,\n highlightSource: voiceaPayload.highlight?.highlight_source,\n timestamp: millisToMinutesAndSeconds(voiceaPayload.highlight?.end_millis ?? 0),\n });\n break;\n\n case TRANSCRIPTION_TYPE.EVA_THANKS:\n this.emit(EVENT_TRIGGERS.EVA_COMMAND, {\n isListening: false,\n text: voiceaPayload.command_response,\n });\n break;\n\n case TRANSCRIPTION_TYPE.EVA_WAKE:\n case TRANSCRIPTION_TYPE.EVA_CANCEL:\n this.emit(EVENT_TRIGGERS.EVA_COMMAND, {\n isListening: voiceaPayload.type === TRANSCRIPTION_TYPE.EVA_WAKE,\n });\n break;\n\n case TRANSCRIPTION_TYPE.LANGUAGE_DETECTED: {\n const isInSpokenLanguages = this.spokenLanguages.includes(voiceaPayload.language);\n if (isInSpokenLanguages) {\n this.emit(EVENT_TRIGGERS.LANGUAGE_DETECTED, {\n languageCode: voiceaPayload.language,\n });\n }\n break;\n }\n default:\n break;\n }\n };\n\n /**\n * Processes Caption Language Response\n * @param {CaptionLanguageResponse} voiceaPayload\n * @returns {void}\n */\n private processCaptionLanguageResponse = (voiceaPayload: CaptionLanguageResponse): void => {\n if (voiceaPayload.statusCode === 200) {\n this.emit(EVENT_TRIGGERS.CAPTION_LANGUAGE_UPDATE, {statusCode: 200});\n } else {\n this.emit(EVENT_TRIGGERS.CAPTION_LANGUAGE_UPDATE, {\n statusCode: voiceaPayload.errorCode,\n errorMessage: voiceaPayload.message,\n });\n }\n };\n\n /**\n * processes voicea announcement response and triggers event\n * @param {Object} voiceaPayload\n * @returns {void}\n */\n private processAnnouncementMessage = (voiceaPayload: AnnouncementPayload): void => {\n const voiceaLanguageOptions = {\n captionLanguages: voiceaPayload?.translation?.allowed_languages ?? [],\n maxLanguages: voiceaPayload?.translation?.max_languages ?? 0,\n spokenLanguages: voiceaPayload?.ASR?.spoken_languages ?? [],\n currentSpokenLanguage: this.currentSpokenLanguage,\n };\n\n this.spokenLanguages = voiceaPayload?.ASR?.spoken_languages ?? [];\n this.emit(EVENT_TRIGGERS.VOICEA_ANNOUNCEMENT, voiceaLanguageOptions);\n };\n\n /**\n * Indicates whether the LLM channel is connected.\n * @returns {boolean}\n */\n public isLLMConnected = (): boolean => this.llmChannel.isConnected();\n\n public getKeepTranscriptionSubscribed = (): boolean => this.keepTranscriptionSubscribed;\n\n /**\n * Sends Announcement to add voicea to the meeting\n * @returns {void}\n */\n public sendAnnouncement = (): void => {\n this.announceStatus = ANNOUNCE_STATUS.JOINING;\n const socket = this.llmChannel.getSocket();\n const binding = this.llmChannel.getBinding();\n\n const payload = {\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n // If captionServiceId exists, send it as the 'to' header; otherwise keep headers empty.\n headers: this.captionServiceId ? {to: this.captionServiceId} : {},\n data: {\n clientPayload: {\n version: 'v2',\n },\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.VOICEA.CLIENT_ANNOUNCEMENT,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n };\n socket.send(payload);\n this.seqNum += 1;\n };\n\n /**\n * Set Spoken Language for the meeting\n * @param {string} languageCode\n * @param {\"DEFAULT\" | \"AUTO\" | \"MANUAL\"} languageAssignment\n * @returns {Promise}\n */\n public setSpokenLanguage = (\n languageCode: string,\n languageAssignment?: 'DEFAULT' | 'AUTO' | 'MANUAL'\n ): Promise<void> =>\n this.request({\n method: 'PUT',\n url: `${this.llmChannel.getLocusUrl()}/controls/`,\n body: {\n transcribe: {\n spokenLanguage: languageCode,\n ...(languageAssignment && {languageAssignment}),\n },\n },\n }).then(() => {\n this.emit(EVENT_TRIGGERS.SPOKEN_LANGUAGE_UPDATE, {languageCode});\n });\n\n /**\n * Request Language translation\n * @param {string} languageCode\n * @returns {void}\n */\n public requestLanguage = (languageCode: string): void => {\n if (!this.isLLMConnected()) {\n return;\n }\n\n const socket = this.llmChannel.getSocket();\n const binding = this.llmChannel.getBinding();\n\n socket.send({\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n headers: {\n to: this.captionServiceId,\n },\n data: {\n clientPayload: {\n translationLanguage: languageCode,\n id: uuid.v4(),\n },\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.VOICEA.TRANSLATION_REQUEST,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n this.currentCaptionLanguage = languageCode;\n this.seqNum += 1;\n };\n\n /**\n * Send manual closed captions to voicea service\n * @param {string} text\n * @param {number} timeStamp\n * @param {number[]} csis\n * @param {boolean} isFinal\n * @returns {void}\n */\n public sendManualClosedCaption = (\n text: string,\n timeStamp: number,\n csis: number[],\n isFinal: boolean\n ): void => {\n if (!this.isLLMConnected()) {\n return;\n }\n\n const socket = this.llmChannel.getSocket();\n const binding = this.llmChannel.getBinding();\n\n socket?.send({\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n headers: {},\n data: {\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.MANUAL.CAPTIONER,\n transcriptPayload: {\n type: isFinal\n ? TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT\n : TRANSCRIPTION_TYPE.MANUAL_CAPTION_INTERIM_RESULT,\n id: uuid.v4(),\n transcripts: [\n {\n text,\n start_millis: timeStamp,\n end_millis: timeStamp,\n csis,\n },\n ],\n transcript_id: uuid.v4(),\n },\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n this.seqNum += 1;\n };\n\n /**\n * request turn on Captions\n * @param {string} [languageCode] - Optional Parameter for spoken language code\n * @returns {Promise}\n */\n private requestTurnOnCaptions = (languageCode?: string): undefined | Promise<void> => {\n this.captionStatus = TURN_ON_CAPTION_STATUS.SENDING;\n\n const locusUrl = this.llmChannel.getLocusUrl();\n\n const body = {\n transcribe: {caption: true},\n languageCode,\n };\n\n return this.request({\n method: 'PUT',\n url: `${locusUrl}/controls/`,\n body,\n })\n .then(() => {\n this.emit(EVENT_TRIGGERS.CAPTIONS_TURNED_ON);\n\n this.areCaptionsEnabled = true;\n this.captionStatus = TURN_ON_CAPTION_STATUS.ENABLED;\n this.announce();\n this.updateSubchannelSubscriptionsAndSyncCaptionState({subscribe: ['transcription']}, true);\n })\n .catch((error) => {\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n throw new Error('turn on captions fail');\n });\n };\n\n /**\n * is announce processing\n * @returns {boolean}\n */\n private isAnnounceProcessing = (): boolean =>\n [ANNOUNCE_STATUS.JOINING, ANNOUNCE_STATUS.JOINED].includes(this.announceStatus);\n\n /**\n * is announce processed\n * @returns {boolean}\n */\n private isAnnounceProcessed = (): boolean => this.announceStatus === ANNOUNCE_STATUS.JOINED;\n\n /**\n * announce to voicea data channel\n * @returns {void}\n */\n public announce = (): void => {\n if (this.isAnnounceProcessed()) {\n return;\n }\n if (!this.isLLMConnected()) {\n throw new Error('voicea can not announce before llm connected');\n }\n this.sendAnnouncement();\n };\n\n /**\n * is turn on caption processing\n * @returns {boolean}\n */\n private isCaptionProcessing = (): boolean =>\n [TURN_ON_CAPTION_STATUS.SENDING, TURN_ON_CAPTION_STATUS.ENABLED].includes(this.captionStatus);\n\n /**\n * Turn on Captions\n * @param {string} [spokenLanguage] - Optional Spoken language code\n * @returns {Promise}\n */\n public turnOnCaptions = async (spokenLanguage?: string): Promise<void | undefined> => {\n if (this.captionStatus === TURN_ON_CAPTION_STATUS.SENDING) return undefined;\n\n if (!this.isLLMConnected()) {\n throw new Error('can not turn on captions before llm connected');\n }\n\n return this.requestTurnOnCaptions(spokenLanguage);\n };\n\n /**\n * Toggle transcribing for highlights\n * @param {boolean} activate true means to turn on transcribing and false means to turn off\n * @param {string} spokenLanguage language code for spoken language\n * @returns {Promise}\n */\n public toggleTranscribing = (\n activate: boolean,\n spokenLanguage?: string\n ): undefined | Promise<void> => {\n return this.request({\n method: 'PUT',\n url: `${this.llmChannel.getLocusUrl()}/controls/`,\n body: {\n transcribe: {\n transcribing: activate,\n },\n spokenLanguage,\n },\n }).then((): undefined | Promise<void> => {\n if (activate && !this.areCaptionsEnabled) {\n return this.turnOnCaptions(spokenLanguage);\n }\n\n return undefined;\n });\n };\n\n /**\n * Toggle turn on manual caption\n * @param {boolean} enable true means to turn on manual caption, false means to turn off\n * @returns {Promise}\n */\n public toggleManualCaption = (enable: boolean): undefined | Promise<void> => {\n if (this.toggleManualCaptionStatus === TOGGLE_MANUAL_CAPTION_STATUS.SENDING) return undefined;\n\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.SENDING;\n\n return this.request({\n method: 'PUT',\n url: `${this.llmChannel.getLocusUrl()}/controls/`,\n body: {\n manualCaption: {\n enable,\n },\n },\n })\n .then((): undefined | Promise<void> => {\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n\n return undefined;\n })\n .catch(() => {\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n throw new Error('toggle manual captions fail');\n });\n };\n\n /**\n * In meeting Spoken Language changed event\n * @param {string} languageCode\n * @param {string} meetingId\n * @returns {void}\n */\n public onSpokenLanguageUpdate = (languageCode: string, meetingId: string): void => {\n this.emit(EVENT_TRIGGERS.SPOKEN_LANGUAGE_UPDATE, {languageCode, meetingId});\n this.currentSpokenLanguage = languageCode;\n };\n\n /**\n * In meeting Spoken Language changed event\n * @param {string} serviceId\n * @returns {void}\n */\n public onCaptionServiceIdUpdate = (serviceId: string): void => {\n if (!serviceId) {\n return;\n }\n if (this.captionServiceId !== serviceId) {\n this.captionServiceId = serviceId;\n if (this.currentCaptionLanguage) {\n this.requestLanguage(this.currentCaptionLanguage);\n }\n }\n };\n\n /**\n * get caption status\n * @returns {string}\n */\n public getCaptionStatus = (): string => this.captionStatus;\n\n /**\n * get announce status\n * @returns {string}\n */\n public getAnnounceStatus = (): string => this.announceStatus;\n\n /**\n * update LLM sub‑channel subscriptions.\n *\n * @param {string[]} options.subscribe Sub‑channels to subscribe to.\n * @param {string[]} options.unsubscribe Sub‑channels to unsubscribe from.\n * @returns {Promise}\n */\n public updateSubchannelSubscriptions = async ({\n subscribe = [],\n unsubscribe = [],\n }: {\n subscribe?: string[];\n unsubscribe?: string[];\n } = {}): Promise<void> => {\n if (!this.isLLMConnected()) return;\n\n const isDataChannelTokenEnabled = await this.llmChannel.isDataChannelTokenEnabled();\n if (!isDataChannelTokenEnabled) return;\n\n const socket = this.llmChannel.getSocket();\n const datachannelUrl = this.llmChannel.getDatachannelUrl();\n\n socket.send({\n id: `${this.seqNum}`,\n type: 'subchannelSubscriptionRequest',\n data: {\n datachannelUri: datachannelUrl,\n subscribe,\n unsubscribe,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n\n this.seqNum += 1;\n };\n\n /**\n * Updates transcription subchannel subscriptions and records whether the\n * transcription subscription should be kept (and restored on reconnect).\n *\n * @param {Object} [options] - Subscription options.\n * @param {string[]} [options.subscribe] - Subchannels to subscribe to.\n * @param {string[]} [options.unsubscribe] - Subchannels to unsubscribe from.\n * @param {boolean} [keepSubscribed=false] - Whether the transcription\n * subscription should be kept and restored on reconnect.\n *\n * @returns {Promise<void>}\n */\n public updateSubchannelSubscriptionsAndSyncCaptionState = (\n options: {\n subscribe?: string[];\n unsubscribe?: string[];\n } = {},\n keepSubscribed = false\n ): Promise<void> => {\n this.keepTranscriptionSubscribed = keepSubscribed;\n\n return this.updateSubchannelSubscriptions(options);\n };\n}\n\nexport default VoiceaChannel;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_events","_interopRequireDefault","require","_uuid","_webexCore","_constants","_utils","ownKeys","e","r","t","_Object$keys","_Object$getOwnPropertySymbols","o","filter","_Object$getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","Object","forEach","_defineProperty2","default","_Object$getOwnPropertyDescriptors","_Object$defineProperties","_Object$defineProperty","_callSuper","_getPrototypeOf2","_possibleConstructorReturn2","_isNativeReflectConstruct","_Reflect$construct","constructor","Boolean","prototype","valueOf","call","VoiceaChannel","exports","_EventEmitter","llmChannel","request","_this","_classCallCheck2","_e$headers","seqNum","sequenceNumber","data","relayType","AIBRIDGE_RELAY_TYPES","VOICEA","ANNOUNCEMENT","onCaptionServiceIdUpdate","headers","from","announceStatus","ANNOUNCE_STATUS","JOINED","processAnnouncementMessage","voiceaPayload","TRANSLATION_RESPONSE","processCaptionLanguageResponse","TRANSCRIPTION","processTranscription","SPEAKER_NAME_UPDATE","processSpeakerNameUpdate","MANUAL","CAPTIONER","processManualTranscription","transcriptPayload","sender","data_source","type","TRANSCRIPTION_TYPE","MANUAL_CAPTION_FINAL_RESULT","MANUAL_CAPTION_INTERIM_RESULT","emit","EVENT_TRIGGERS","NEW_MANUAL_CAPTION","isFinal","transcriptId","id","transcripts","source","SPEAKER_NAME_UPDATED","_voiceaPayload$transc","_voiceaPayload$highli","_voiceaPayload$highli2","_voiceaPayload$highli3","_voiceaPayload$highli4","_voiceaPayload$highli5","_voiceaPayload$highli6","_voiceaPayload$highli7","TRANSCRIPT_INTERIM_RESULTS","NEW_CAPTION","transcript_id","TRANSCRIPT_FINAL_RESULT","map","transcript","timestamp","millisToMinutesAndSeconds","end_millis","HIGHLIGHT_CREATED","csis","highlight","highlightId","highlight_id","text","highlightLabel","highlight_label","highlightSource","highlight_source","EVA_THANKS","EVA_COMMAND","isListening","command_response","EVA_WAKE","EVA_CANCEL","LANGUAGE_DETECTED","isInSpokenLanguages","spokenLanguages","includes","language","languageCode","statusCode","CAPTION_LANGUAGE_UPDATE","errorCode","errorMessage","message","_voiceaPayload$transl","_voiceaPayload$transl2","_voiceaPayload$transl3","_voiceaPayload$transl4","_voiceaPayload$ASR$sp","_voiceaPayload$ASR","_voiceaPayload$ASR$sp2","_voiceaPayload$ASR2","voiceaLanguageOptions","captionLanguages","translation","allowed_languages","maxLanguages","max_languages","ASR","spoken_languages","currentSpokenLanguage","VOICEA_ANNOUNCEMENT","_this$llmChannel$isCo","_this$llmChannel","isConnected","keepTranscriptionSubscribed","llm","requireLLMChannel","JOINING","socket","getSocket","binding","getBinding","payload","concat","recipients","route","captionServiceId","to","clientPayload","version","eventType","CLIENT_ANNOUNCEMENT","trackingId","config","trackingIdPrefix","uuid","v4","toString","send","languageAssignment","method","url","getLocusUrl","body","transcribe","spokenLanguage","then","SPOKEN_LANGUAGE_UPDATE","isLLMConnected","translationLanguage","TRANSLATION_REQUEST","currentCaptionLanguage","timeStamp","start_millis","captionStatus","TURN_ON_CAPTION_STATUS","SENDING","locusUrl","caption","CAPTIONS_TURNED_ON","areCaptionsEnabled","ENABLED","announce","updateSubchannelSubscriptionsAndSyncCaptionState","subscribe","catch","error","IDLE","Error","cause","isAnnounceProcessed","sendAnnouncement","_ref","_asyncToGenerator2","_regenerator","mark","_callee","wrap","_context","prev","next","isCaptionProcessing","abrupt","undefined","requestTurnOnCaptions","stop","_x","activate","transcribing","turnOnCaptions","enable","toggleManualCaptionStatus","TOGGLE_MANUAL_CAPTION_STATUS","manualCaption","meetingId","serviceId","requestLanguage","_callee2","_ref3","_ref3$subscribe","_ref3$unsubscribe","unsubscribe","isDataChannelTokenEnabled","datachannelUrl","_args2","_context2","sent","getDatachannelUrl","datachannelUri","options","keepSubscribed","updateSubchannelSubscriptions","DEFAULT_SPOKEN_LANGUAGE","on","eventProcessor","hasSubscribedToEvents","_inherits2","_createClass2","key","value","deregisterEvents","targetLLMChannel","_pendingCaptionRestore","detachPendingOnline","_this$llmChannel2","off","attachPendingOnline","channel","callback","_pendingOnlineListener","once","resetAnnounceState","reconcile","_this2","target","_promise","resolve","switchLLMChannel","newLLMChannel","EventEmitter","_default"],"sources":["voicea.ts"],"sourcesContent":["import EventEmitter from 'events';\nimport uuid from 'uuid';\n// @ts-ignore - webex-core types\nimport {config} from '@webex/webex-core';\n\n// @ts-ignore - internal-plugin-llm types\nimport type LLMChannel from '@webex/internal-plugin-llm';\nimport {\n EVENT_TRIGGERS,\n AIBRIDGE_RELAY_TYPES,\n TRANSCRIPTION_TYPE,\n ANNOUNCE_STATUS,\n TURN_ON_CAPTION_STATUS,\n TOGGLE_MANUAL_CAPTION_STATUS,\n DEFAULT_SPOKEN_LANGUAGE,\n} from './constants';\nimport {\n AnnouncementPayload,\n CaptionLanguageResponse,\n SpeakerNameUpdatePayload,\n TranscriptionResponse,\n IVoiceaChannel,\n} from './voicea.types';\nimport {millisToMinutesAndSeconds} from './utils';\n\n/**\n * @description VoiceaChannel — handles voicea/transcription functionality for a single LLM connection.\n * Created via `webex.internal.voicea.createChannel(llmChannel)`. The caller owns the\n * channel and is responsible for its lifecycle.\n * @export\n * @class VoiceaChannel\n */\nexport class VoiceaChannel extends EventEmitter implements IVoiceaChannel {\n private request: (options: {method: string; url: string; body?: object}) => Promise<any>;\n private llmChannel?: LLMChannel;\n\n private seqNum: number;\n private areCaptionsEnabled: boolean;\n private hasSubscribedToEvents = false;\n private captionServiceId?: string;\n private announceStatus: string;\n private captionStatus: string;\n\n private keepTranscriptionSubscribed: boolean;\n\n private toggleManualCaptionStatus: string;\n private currentSpokenLanguage?: string;\n private spokenLanguages: string[] = [];\n private currentCaptionLanguage?: string;\n\n // Target channel for reconciler pattern - the channel voicea WANTS to be bound to\n private targetLLMChannel?: LLMChannel;\n // Single pending 'online' listener for deferred reconciliation\n private _pendingOnlineListener?: () => void;\n // Tracks whether caption restoration is pending (set on switch, cleared on restore)\n private _pendingCaptionRestore = false;\n\n /**\n * Creates a VoiceaChannel, optionally bound to an LLMChannel.\n * If no llmChannel is provided, call switchLLMChannel() later to attach one.\n * @param {LLMChannel} [llmChannel] - The LLM channel to use (optional)\n * @param {Function} request - The request function for making API calls (typically webex.request bound to webex)\n */\n constructor(\n llmChannel: LLMChannel | undefined,\n request: (options: {method: string; url: string; body?: object}) => Promise<any>\n ) {\n super();\n this.llmChannel = llmChannel;\n this.request = request;\n\n this.seqNum = 1;\n this.areCaptionsEnabled = false;\n this.captionServiceId = undefined;\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n this.currentSpokenLanguage = DEFAULT_SPOKEN_LANGUAGE;\n this.currentCaptionLanguage = undefined;\n this.keepTranscriptionSubscribed = false;\n\n // Subscribe to relay events from the LLM channel if provided\n if (this.llmChannel) {\n this.llmChannel.on('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = true;\n }\n }\n\n /**\n * Returns the LLM channel, throwing if not available.\n * @private\n * @returns {LLMChannel}\n * @throws {Error} If LLM channel is not available\n */\n private requireLLMChannel(): LLMChannel {\n if (!this.llmChannel) {\n throw new Error('VoiceaChannel: LLM channel not available');\n }\n\n return this.llmChannel;\n }\n\n /**\n * Process events from LLM channel\n * @param {Object} e - Event data\n * @returns {void}\n */\n private eventProcessor = (e: any): void => {\n this.seqNum = e.sequenceNumber + 1;\n switch (e.data.relayType) {\n case AIBRIDGE_RELAY_TYPES.VOICEA.ANNOUNCEMENT:\n this.onCaptionServiceIdUpdate(e.headers.from);\n this.announceStatus = ANNOUNCE_STATUS.JOINED;\n this.processAnnouncementMessage(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.TRANSLATION_RESPONSE:\n this.processCaptionLanguageResponse(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.TRANSCRIPTION:\n this.processTranscription(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.VOICEA.SPEAKER_NAME_UPDATE:\n this.processSpeakerNameUpdate(e.data.voiceaPayload);\n break;\n case AIBRIDGE_RELAY_TYPES.MANUAL.TRANSCRIPTION:\n case AIBRIDGE_RELAY_TYPES.MANUAL.CAPTIONER:\n this.processManualTranscription({\n ...e.data.transcriptPayload,\n sender: e.headers?.from,\n data_source: e.data.relayType,\n });\n break;\n default:\n break;\n }\n };\n\n /**\n * Deregister events and clean up\n * @returns {void}\n */\n public deregisterEvents(): void {\n this.areCaptionsEnabled = false;\n this.keepTranscriptionSubscribed = false;\n this.captionServiceId = undefined;\n this.targetLLMChannel = undefined;\n this._pendingCaptionRestore = false;\n\n // Remove any pending online listener\n this.detachPendingOnline();\n\n if (this.hasSubscribedToEvents) {\n this.llmChannel?.off('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = false;\n }\n\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n this.currentSpokenLanguage = undefined;\n this.currentCaptionLanguage = undefined;\n }\n\n /**\n * Attach a pending 'online' listener to a channel for deferred reconciliation.\n * Detaches any existing listener first.\n * @param {LLMChannel} channel - The channel to attach to\n * @param {Function} callback - The callback to run when 'online' fires\n * @private\n * @returns {void}\n */\n private attachPendingOnline(channel: LLMChannel, callback: () => void): void {\n this.detachPendingOnline();\n this._pendingOnlineListener = callback;\n channel.once('online', this._pendingOnlineListener);\n }\n\n /**\n * Detach any pending 'online' listener.\n * @private\n * @returns {void}\n */\n private detachPendingOnline(): void {\n if (this._pendingOnlineListener && this.llmChannel) {\n this.llmChannel.off('online', this._pendingOnlineListener);\n }\n this._pendingOnlineListener = undefined;\n }\n\n /**\n * Reset announcement state for a new connection.\n * @private\n * @returns {void}\n */\n private resetAnnounceState(): void {\n this.announceStatus = ANNOUNCE_STATUS.IDLE;\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n this.captionServiceId = undefined;\n this.areCaptionsEnabled = false;\n }\n\n /**\n * Reconcile voicea binding and caption state to match the desired target.\n * This is idempotent - always re-reads targetLLMChannel and current state.\n * A deferred 'online' callback that fires late self-corrects automatically.\n * @private\n * @returns {Promise<void>}\n */\n private reconcile(): Promise<void> {\n const target = this.targetLLMChannel;\n if (!target) return Promise.resolve();\n\n // 1. Rebind relay-event subscription if actual != desired\n if (this.llmChannel !== target) {\n if (this.hasSubscribedToEvents && this.llmChannel) {\n this.llmChannel.off('event:relay.event', this.eventProcessor);\n }\n this.detachPendingOnline();\n this.llmChannel = target;\n this.llmChannel.on('event:relay.event', this.eventProcessor);\n this.hasSubscribedToEvents = true;\n this.resetAnnounceState();\n // Mark caption restoration as pending if captions were subscribed\n this._pendingCaptionRestore = this.keepTranscriptionSubscribed;\n }\n\n // 2. Restore captions if pending\n if (!this._pendingCaptionRestore) return Promise.resolve();\n\n if (this.isLLMConnected()) {\n // Channel is connected, restore captions immediately\n this._pendingCaptionRestore = false;\n\n return this.turnOnCaptions(this.currentSpokenLanguage)\n .then(() => undefined)\n .catch(() => {\n // Best-effort restoration\n });\n }\n // Channel not yet connected - defer until 'online' then re-reconcile.\n // If target changes meanwhile, reconcile() self-corrects.\n this.attachPendingOnline(target, () => {\n this.reconcile();\n });\n\n return Promise.resolve();\n }\n\n /**\n * Switch to a different LLM channel while preserving caption state.\n * Used when transitioning between main meeting and practice session.\n * This is a thin intent-setter - actual binding happens in reconcile().\n * @param {LLMChannel} newLLMChannel - The new LLM channel to switch to\n * @returns {Promise<void>}\n */\n public switchLLMChannel(newLLMChannel: LLMChannel): Promise<void> {\n this.targetLLMChannel = newLLMChannel;\n\n return this.reconcile();\n }\n\n /**\n * Process manual Transcript and send alert\n * @param {TranscriptionResponse} transcriptPayload\n * @returns {void}\n */\n private processManualTranscription = (transcriptPayload: TranscriptionResponse): void => {\n if (\n transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT ||\n transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_INTERIM_RESULT\n ) {\n this.emit(EVENT_TRIGGERS.NEW_MANUAL_CAPTION, {\n isFinal: transcriptPayload.type === TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT,\n transcriptId: transcriptPayload.id,\n transcripts: transcriptPayload.transcripts,\n sender: transcriptPayload.sender,\n source: transcriptPayload.data_source,\n });\n }\n };\n\n /**\n * Process speaker name update and send alert\n * @param {SpeakerNameUpdatePayload} voiceaPayload\n * @returns {void}\n */\n private processSpeakerNameUpdate = (voiceaPayload: SpeakerNameUpdatePayload): void => {\n // @ts-ignore\n this.emit(EVENT_TRIGGERS.SPEAKER_NAME_UPDATED, voiceaPayload);\n };\n\n /**\n * Process Transcript and send alert\n * @param {TranscriptionResponse} voiceaPayload\n * @returns {void}\n */\n private processTranscription = (voiceaPayload: TranscriptionResponse): void => {\n switch (voiceaPayload.type) {\n case TRANSCRIPTION_TYPE.TRANSCRIPT_INTERIM_RESULTS:\n this.emit(EVENT_TRIGGERS.NEW_CAPTION, {\n isFinal: false,\n transcriptId: voiceaPayload.transcript_id,\n transcripts: voiceaPayload.transcripts,\n });\n break;\n\n case TRANSCRIPTION_TYPE.TRANSCRIPT_FINAL_RESULT:\n this.emit(EVENT_TRIGGERS.NEW_CAPTION, {\n isFinal: true,\n transcriptId: voiceaPayload.transcript_id,\n transcripts: voiceaPayload.transcripts?.map((transcript) => {\n transcript.timestamp = millisToMinutesAndSeconds(transcript.end_millis);\n\n return transcript;\n }),\n });\n break;\n\n case TRANSCRIPTION_TYPE.HIGHLIGHT_CREATED:\n this.emit(EVENT_TRIGGERS.HIGHLIGHT_CREATED, {\n csis: voiceaPayload.highlight?.csis,\n highlightId: voiceaPayload.highlight?.highlight_id,\n text: voiceaPayload.highlight?.transcript,\n highlightLabel: voiceaPayload.highlight?.highlight_label,\n highlightSource: voiceaPayload.highlight?.highlight_source,\n timestamp: millisToMinutesAndSeconds(voiceaPayload.highlight?.end_millis ?? 0),\n });\n break;\n\n case TRANSCRIPTION_TYPE.EVA_THANKS:\n this.emit(EVENT_TRIGGERS.EVA_COMMAND, {\n isListening: false,\n text: voiceaPayload.command_response,\n });\n break;\n\n case TRANSCRIPTION_TYPE.EVA_WAKE:\n case TRANSCRIPTION_TYPE.EVA_CANCEL:\n this.emit(EVENT_TRIGGERS.EVA_COMMAND, {\n isListening: voiceaPayload.type === TRANSCRIPTION_TYPE.EVA_WAKE,\n });\n break;\n\n case TRANSCRIPTION_TYPE.LANGUAGE_DETECTED: {\n const isInSpokenLanguages = this.spokenLanguages.includes(voiceaPayload.language);\n if (isInSpokenLanguages) {\n this.emit(EVENT_TRIGGERS.LANGUAGE_DETECTED, {\n languageCode: voiceaPayload.language,\n });\n }\n break;\n }\n default:\n break;\n }\n };\n\n /**\n * Processes Caption Language Response\n * @param {CaptionLanguageResponse} voiceaPayload\n * @returns {void}\n */\n private processCaptionLanguageResponse = (voiceaPayload: CaptionLanguageResponse): void => {\n if (voiceaPayload.statusCode === 200) {\n this.emit(EVENT_TRIGGERS.CAPTION_LANGUAGE_UPDATE, {statusCode: 200});\n } else {\n this.emit(EVENT_TRIGGERS.CAPTION_LANGUAGE_UPDATE, {\n statusCode: voiceaPayload.errorCode,\n errorMessage: voiceaPayload.message,\n });\n }\n };\n\n /**\n * processes voicea announcement response and triggers event\n * @param {Object} voiceaPayload\n * @returns {void}\n */\n private processAnnouncementMessage = (voiceaPayload: AnnouncementPayload): void => {\n const voiceaLanguageOptions = {\n captionLanguages: voiceaPayload?.translation?.allowed_languages ?? [],\n maxLanguages: voiceaPayload?.translation?.max_languages ?? 0,\n spokenLanguages: voiceaPayload?.ASR?.spoken_languages ?? [],\n currentSpokenLanguage: this.currentSpokenLanguage,\n };\n\n this.spokenLanguages = voiceaPayload?.ASR?.spoken_languages ?? [];\n this.emit(EVENT_TRIGGERS.VOICEA_ANNOUNCEMENT, voiceaLanguageOptions);\n };\n\n /**\n * Indicates whether the LLM channel is connected.\n * @returns {boolean}\n */\n public isLLMConnected = (): boolean => this.llmChannel?.isConnected() ?? false;\n\n public getKeepTranscriptionSubscribed = (): boolean => this.keepTranscriptionSubscribed;\n\n /**\n * Sends Announcement to add voicea to the meeting\n * @returns {void}\n */\n public sendAnnouncement = (): void => {\n const llm = this.requireLLMChannel();\n this.announceStatus = ANNOUNCE_STATUS.JOINING;\n const socket = llm.getSocket();\n const binding = llm.getBinding();\n\n const payload = {\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n // If captionServiceId exists, send it as the 'to' header; otherwise keep headers empty.\n headers: this.captionServiceId ? {to: this.captionServiceId} : {},\n data: {\n clientPayload: {\n version: 'v2',\n },\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.VOICEA.CLIENT_ANNOUNCEMENT,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n };\n socket.send(payload);\n this.seqNum += 1;\n };\n\n /**\n * Set Spoken Language for the meeting\n * @param {string} languageCode\n * @param {\"DEFAULT\" | \"AUTO\" | \"MANUAL\"} languageAssignment\n * @returns {Promise}\n */\n public setSpokenLanguage = (\n languageCode: string,\n languageAssignment?: 'DEFAULT' | 'AUTO' | 'MANUAL'\n ): Promise<void> =>\n this.request({\n method: 'PUT',\n url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,\n body: {\n transcribe: {\n spokenLanguage: languageCode,\n ...(languageAssignment && {languageAssignment}),\n },\n },\n }).then(() => {\n this.emit(EVENT_TRIGGERS.SPOKEN_LANGUAGE_UPDATE, {languageCode});\n });\n\n /**\n * Request Language translation\n * @param {string} languageCode\n * @returns {void}\n */\n public requestLanguage = (languageCode: string): void => {\n if (!this.isLLMConnected()) {\n return;\n }\n\n const llm = this.requireLLMChannel();\n const socket = llm.getSocket();\n const binding = llm.getBinding();\n\n socket.send({\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n headers: {\n to: this.captionServiceId,\n },\n data: {\n clientPayload: {\n translationLanguage: languageCode,\n id: uuid.v4(),\n },\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.VOICEA.TRANSLATION_REQUEST,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n this.currentCaptionLanguage = languageCode;\n this.seqNum += 1;\n };\n\n /**\n * Send manual closed captions to voicea service\n * @param {string} text\n * @param {number} timeStamp\n * @param {number[]} csis\n * @param {boolean} isFinal\n * @returns {void}\n */\n public sendManualClosedCaption = (\n text: string,\n timeStamp: number,\n csis: number[],\n isFinal: boolean\n ): void => {\n if (!this.isLLMConnected()) {\n return;\n }\n\n const llm = this.requireLLMChannel();\n const socket = llm.getSocket();\n const binding = llm.getBinding();\n\n socket?.send({\n id: `${this.seqNum}`,\n type: 'publishRequest',\n recipients: [\n {\n route: binding,\n },\n ],\n headers: {},\n data: {\n eventType: 'relay.event',\n relayType: AIBRIDGE_RELAY_TYPES.MANUAL.CAPTIONER,\n transcriptPayload: {\n type: isFinal\n ? TRANSCRIPTION_TYPE.MANUAL_CAPTION_FINAL_RESULT\n : TRANSCRIPTION_TYPE.MANUAL_CAPTION_INTERIM_RESULT,\n id: uuid.v4(),\n transcripts: [\n {\n text,\n start_millis: timeStamp,\n end_millis: timeStamp,\n csis,\n },\n ],\n transcript_id: uuid.v4(),\n },\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n this.seqNum += 1;\n };\n\n /**\n * request turn on Captions\n * @param {string} [languageCode] - Optional Parameter for spoken language code\n * @returns {Promise}\n */\n private requestTurnOnCaptions = (languageCode?: string): undefined | Promise<void> => {\n this.captionStatus = TURN_ON_CAPTION_STATUS.SENDING;\n\n const locusUrl = this.requireLLMChannel().getLocusUrl();\n\n const body = {\n transcribe: {caption: true},\n languageCode,\n };\n\n return this.request({\n method: 'PUT',\n url: `${locusUrl}/controls/`,\n body,\n })\n .then(() => {\n this.emit(EVENT_TRIGGERS.CAPTIONS_TURNED_ON);\n\n this.areCaptionsEnabled = true;\n this.captionStatus = TURN_ON_CAPTION_STATUS.ENABLED;\n this.announce();\n this.updateSubchannelSubscriptionsAndSyncCaptionState({subscribe: ['transcription']}, true);\n })\n .catch((error) => {\n this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;\n throw new Error('turn on captions fail', {cause: error});\n });\n };\n\n /**\n * is announce processing\n * @returns {boolean}\n */\n private isAnnounceProcessing = (): boolean =>\n [ANNOUNCE_STATUS.JOINING, ANNOUNCE_STATUS.JOINED].includes(this.announceStatus);\n\n /**\n * is announce processed\n * @returns {boolean}\n */\n private isAnnounceProcessed = (): boolean => this.announceStatus === ANNOUNCE_STATUS.JOINED;\n\n /**\n * announce to voicea data channel\n * @returns {void}\n */\n public announce = (): void => {\n if (this.isAnnounceProcessed()) {\n return;\n }\n if (!this.isLLMConnected()) {\n throw new Error('voicea can not announce before llm connected');\n }\n this.sendAnnouncement();\n };\n\n /**\n * is turn on caption processing\n * @returns {boolean}\n */\n private isCaptionProcessing = (): boolean =>\n [TURN_ON_CAPTION_STATUS.SENDING, TURN_ON_CAPTION_STATUS.ENABLED].includes(this.captionStatus);\n\n /**\n * Turn on Captions\n * @param {string} [spokenLanguage] - Optional Spoken language code\n * @returns {Promise}\n */\n public turnOnCaptions = async (spokenLanguage?: string): Promise<void | undefined> => {\n if (this.isCaptionProcessing()) return undefined;\n\n if (!this.isLLMConnected()) {\n throw new Error('can not turn on captions before llm connected');\n }\n\n return this.requestTurnOnCaptions(spokenLanguage);\n };\n\n /**\n * Toggle transcribing for highlights\n * @param {boolean} activate true means to turn on transcribing and false means to turn off\n * @param {string} spokenLanguage language code for spoken language\n * @returns {Promise}\n */\n public toggleTranscribing = (\n activate: boolean,\n spokenLanguage?: string\n ): undefined | Promise<void> => {\n return this.request({\n method: 'PUT',\n url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,\n body: {\n transcribe: {\n transcribing: activate,\n },\n spokenLanguage,\n },\n }).then((): undefined | Promise<void> => {\n if (activate && !this.areCaptionsEnabled) {\n return this.turnOnCaptions(spokenLanguage);\n }\n\n return undefined;\n });\n };\n\n /**\n * Toggle turn on manual caption\n * @param {boolean} enable true means to turn on manual caption, false means to turn off\n * @returns {Promise}\n */\n public toggleManualCaption = (enable: boolean): undefined | Promise<void> => {\n if (this.toggleManualCaptionStatus === TOGGLE_MANUAL_CAPTION_STATUS.SENDING) return undefined;\n\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.SENDING;\n\n return this.request({\n method: 'PUT',\n url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,\n body: {\n manualCaption: {\n enable,\n },\n },\n })\n .then((): undefined | Promise<void> => {\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n\n return undefined;\n })\n .catch(() => {\n this.toggleManualCaptionStatus = TOGGLE_MANUAL_CAPTION_STATUS.IDLE;\n throw new Error('toggle manual captions fail');\n });\n };\n\n /**\n * In meeting Spoken Language changed event\n * @param {string} languageCode\n * @param {string} meetingId\n * @returns {void}\n */\n public onSpokenLanguageUpdate = (languageCode: string, meetingId: string): void => {\n this.emit(EVENT_TRIGGERS.SPOKEN_LANGUAGE_UPDATE, {languageCode, meetingId});\n this.currentSpokenLanguage = languageCode;\n };\n\n /**\n * In meeting Spoken Language changed event\n * @param {string} serviceId\n * @returns {void}\n */\n public onCaptionServiceIdUpdate = (serviceId: string): void => {\n if (!serviceId) {\n return;\n }\n if (this.captionServiceId !== serviceId) {\n this.captionServiceId = serviceId;\n if (this.currentCaptionLanguage) {\n this.requestLanguage(this.currentCaptionLanguage);\n }\n }\n };\n\n /**\n * get caption status\n * @returns {string}\n */\n public getCaptionStatus = (): string => this.captionStatus;\n\n /**\n * get announce status\n * @returns {string}\n */\n public getAnnounceStatus = (): string => this.announceStatus;\n\n /**\n * update LLM sub‑channel subscriptions.\n *\n * @param {string[]} options.subscribe Sub‑channels to subscribe to.\n * @param {string[]} options.unsubscribe Sub‑channels to unsubscribe from.\n * @returns {Promise}\n */\n public updateSubchannelSubscriptions = async ({\n subscribe = [],\n unsubscribe = [],\n }: {\n subscribe?: string[];\n unsubscribe?: string[];\n } = {}): Promise<void> => {\n if (!this.isLLMConnected()) return;\n\n const llm = this.requireLLMChannel();\n const isDataChannelTokenEnabled = await llm.isDataChannelTokenEnabled();\n if (!isDataChannelTokenEnabled) return;\n\n const socket = llm.getSocket();\n const datachannelUrl = llm.getDatachannelUrl();\n\n socket.send({\n id: `${this.seqNum}`,\n type: 'subchannelSubscriptionRequest',\n data: {\n datachannelUri: datachannelUrl,\n subscribe,\n unsubscribe,\n },\n trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,\n });\n\n this.seqNum += 1;\n };\n\n /**\n * Updates transcription subchannel subscriptions and records whether the\n * transcription subscription should be kept (and restored on reconnect).\n *\n * @param {Object} [options] - Subscription options.\n * @param {string[]} [options.subscribe] - Subchannels to subscribe to.\n * @param {string[]} [options.unsubscribe] - Subchannels to unsubscribe from.\n * @param {boolean} [keepSubscribed=false] - Whether the transcription\n * subscription should be kept and restored on reconnect.\n *\n * @returns {Promise<void>}\n */\n public updateSubchannelSubscriptionsAndSyncCaptionState = (\n options: {\n subscribe?: string[];\n unsubscribe?: string[];\n } = {},\n keepSubscribed = false\n ): Promise<void> => {\n this.keepTranscriptionSubscribed = keepSubscribed;\n\n return this.updateSubchannelSubscriptions(options);\n };\n}\n\nexport default VoiceaChannel;\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -49,5 +49,5 @@
49
49
  "test:style": "eslint ./src/**/*.*",
50
50
  "test:unit": "webex-legacy-tools test --unit --runner jest"
51
51
  },
52
- "version": "3.12.0-llmrefactor.7"
52
+ "version": "3.12.0-llmrefactor.8"
53
53
  }
@@ -13,16 +13,16 @@ export class VoiceaPlugin extends WebexPlugin {
13
13
  namespace = VOICEA;
14
14
 
15
15
  /**
16
- * Creates a VoiceaChannel bound to the given LLMChannel.
16
+ * Creates a VoiceaChannel, optionally bound to an LLMChannel.
17
17
  *
18
18
  * Note: VoiceaChannel does not take ownership of the LLMChannel.
19
19
  * The caller retains ownership and is responsible for the LLMChannel's
20
20
  * lifecycle (connection, disconnection, cleanup).
21
21
  *
22
- * @param {LLMChannel} llmChannel - The LLM channel to use for voicea
22
+ * @param {LLMChannel} [llmChannel] - The LLM channel to use for voicea (optional)
23
23
  * @returns {VoiceaChannel} A new VoiceaChannel instance
24
24
  */
25
- public createChannel(llmChannel: LLMChannel): VoiceaChannel {
25
+ public createChannel(llmChannel?: LLMChannel): VoiceaChannel {
26
26
  // @ts-ignore - webex is available on WebexPlugin
27
27
  const channel = new VoiceaChannel(llmChannel, this.webex.request.bind(this.webex));
28
28
 
package/src/voicea.ts CHANGED
@@ -32,7 +32,7 @@ import {millisToMinutesAndSeconds} from './utils';
32
32
  */
33
33
  export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
34
34
  private request: (options: {method: string; url: string; body?: object}) => Promise<any>;
35
- private llmChannel: LLMChannel;
35
+ private llmChannel?: LLMChannel;
36
36
 
37
37
  private seqNum: number;
38
38
  private areCaptionsEnabled: boolean;
@@ -48,13 +48,21 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
48
48
  private spokenLanguages: string[] = [];
49
49
  private currentCaptionLanguage?: string;
50
50
 
51
+ // Target channel for reconciler pattern - the channel voicea WANTS to be bound to
52
+ private targetLLMChannel?: LLMChannel;
53
+ // Single pending 'online' listener for deferred reconciliation
54
+ private _pendingOnlineListener?: () => void;
55
+ // Tracks whether caption restoration is pending (set on switch, cleared on restore)
56
+ private _pendingCaptionRestore = false;
57
+
51
58
  /**
52
- * Creates a VoiceaChannel bound to the given LLMChannel
53
- * @param {LLMChannel} llmChannel - The LLM channel to use
59
+ * Creates a VoiceaChannel, optionally bound to an LLMChannel.
60
+ * If no llmChannel is provided, call switchLLMChannel() later to attach one.
61
+ * @param {LLMChannel} [llmChannel] - The LLM channel to use (optional)
54
62
  * @param {Function} request - The request function for making API calls (typically webex.request bound to webex)
55
63
  */
56
64
  constructor(
57
- llmChannel: LLMChannel,
65
+ llmChannel: LLMChannel | undefined,
58
66
  request: (options: {method: string; url: string; body?: object}) => Promise<any>
59
67
  ) {
60
68
  super();
@@ -71,9 +79,25 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
71
79
  this.currentCaptionLanguage = undefined;
72
80
  this.keepTranscriptionSubscribed = false;
73
81
 
74
- // Subscribe to relay events from the LLM channel
75
- this.llmChannel.on('event:relay.event', this.eventProcessor);
76
- this.hasSubscribedToEvents = true;
82
+ // Subscribe to relay events from the LLM channel if provided
83
+ if (this.llmChannel) {
84
+ this.llmChannel.on('event:relay.event', this.eventProcessor);
85
+ this.hasSubscribedToEvents = true;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Returns the LLM channel, throwing if not available.
91
+ * @private
92
+ * @returns {LLMChannel}
93
+ * @throws {Error} If LLM channel is not available
94
+ */
95
+ private requireLLMChannel(): LLMChannel {
96
+ if (!this.llmChannel) {
97
+ throw new Error('VoiceaChannel: LLM channel not available');
98
+ }
99
+
100
+ return this.llmChannel;
77
101
  }
78
102
 
79
103
  /**
@@ -119,9 +143,14 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
119
143
  this.areCaptionsEnabled = false;
120
144
  this.keepTranscriptionSubscribed = false;
121
145
  this.captionServiceId = undefined;
146
+ this.targetLLMChannel = undefined;
147
+ this._pendingCaptionRestore = false;
148
+
149
+ // Remove any pending online listener
150
+ this.detachPendingOnline();
122
151
 
123
152
  if (this.hasSubscribedToEvents) {
124
- this.llmChannel.off('event:relay.event', this.eventProcessor);
153
+ this.llmChannel?.off('event:relay.event', this.eventProcessor);
125
154
  this.hasSubscribedToEvents = false;
126
155
  }
127
156
 
@@ -133,42 +162,101 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
133
162
  }
134
163
 
135
164
  /**
136
- * Switch to a different LLM channel while preserving caption state.
137
- * Used when transitioning between main meeting and practice session.
138
- * - Preserves keepTranscriptionSubscribed and spokenLanguage state
139
- * - Unsubscribes from old channel, subscribes to new channel
140
- * - Re-announces and re-enables captions if they were on
141
- * @param {LLMChannel} newLLMChannel - The new LLM channel to switch to
142
- * @returns {Promise<void>}
165
+ * Attach a pending 'online' listener to a channel for deferred reconciliation.
166
+ * Detaches any existing listener first.
167
+ * @param {LLMChannel} channel - The channel to attach to
168
+ * @param {Function} callback - The callback to run when 'online' fires
169
+ * @private
170
+ * @returns {void}
143
171
  */
144
- public async switchLLMChannel(newLLMChannel: LLMChannel): Promise<void> {
145
- // Save current state
146
- const captionsWereOn = this.keepTranscriptionSubscribed;
147
- const spokenLanguage = this.currentSpokenLanguage;
172
+ private attachPendingOnline(channel: LLMChannel, callback: () => void): void {
173
+ this.detachPendingOnline();
174
+ this._pendingOnlineListener = callback;
175
+ channel.once('online', this._pendingOnlineListener);
176
+ }
148
177
 
149
- // Unsubscribe from old channel
150
- if (this.hasSubscribedToEvents && this.llmChannel) {
151
- this.llmChannel.off('event:relay.event', this.eventProcessor);
152
- this.hasSubscribedToEvents = false;
178
+ /**
179
+ * Detach any pending 'online' listener.
180
+ * @private
181
+ * @returns {void}
182
+ */
183
+ private detachPendingOnline(): void {
184
+ if (this._pendingOnlineListener && this.llmChannel) {
185
+ this.llmChannel.off('online', this._pendingOnlineListener);
153
186
  }
187
+ this._pendingOnlineListener = undefined;
188
+ }
154
189
 
155
- // Switch to new channel
156
- this.llmChannel = newLLMChannel;
157
-
158
- // Subscribe to new channel
159
- this.llmChannel.on('event:relay.event', this.eventProcessor);
160
- this.hasSubscribedToEvents = true;
161
-
162
- // Reset announcement state for new connection
190
+ /**
191
+ * Reset announcement state for a new connection.
192
+ * @private
193
+ * @returns {void}
194
+ */
195
+ private resetAnnounceState(): void {
163
196
  this.announceStatus = ANNOUNCE_STATUS.IDLE;
164
197
  this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;
165
198
  this.captionServiceId = undefined;
166
199
  this.areCaptionsEnabled = false;
200
+ }
201
+
202
+ /**
203
+ * Reconcile voicea binding and caption state to match the desired target.
204
+ * This is idempotent - always re-reads targetLLMChannel and current state.
205
+ * A deferred 'online' callback that fires late self-corrects automatically.
206
+ * @private
207
+ * @returns {Promise<void>}
208
+ */
209
+ private reconcile(): Promise<void> {
210
+ const target = this.targetLLMChannel;
211
+ if (!target) return Promise.resolve();
212
+
213
+ // 1. Rebind relay-event subscription if actual != desired
214
+ if (this.llmChannel !== target) {
215
+ if (this.hasSubscribedToEvents && this.llmChannel) {
216
+ this.llmChannel.off('event:relay.event', this.eventProcessor);
217
+ }
218
+ this.detachPendingOnline();
219
+ this.llmChannel = target;
220
+ this.llmChannel.on('event:relay.event', this.eventProcessor);
221
+ this.hasSubscribedToEvents = true;
222
+ this.resetAnnounceState();
223
+ // Mark caption restoration as pending if captions were subscribed
224
+ this._pendingCaptionRestore = this.keepTranscriptionSubscribed;
225
+ }
167
226
 
168
- // Re-announce and re-enable captions if they were on
169
- if (captionsWereOn) {
170
- await this.turnOnCaptions(spokenLanguage);
227
+ // 2. Restore captions if pending
228
+ if (!this._pendingCaptionRestore) return Promise.resolve();
229
+
230
+ if (this.isLLMConnected()) {
231
+ // Channel is connected, restore captions immediately
232
+ this._pendingCaptionRestore = false;
233
+
234
+ return this.turnOnCaptions(this.currentSpokenLanguage)
235
+ .then(() => undefined)
236
+ .catch(() => {
237
+ // Best-effort restoration
238
+ });
171
239
  }
240
+ // Channel not yet connected - defer until 'online' then re-reconcile.
241
+ // If target changes meanwhile, reconcile() self-corrects.
242
+ this.attachPendingOnline(target, () => {
243
+ this.reconcile();
244
+ });
245
+
246
+ return Promise.resolve();
247
+ }
248
+
249
+ /**
250
+ * Switch to a different LLM channel while preserving caption state.
251
+ * Used when transitioning between main meeting and practice session.
252
+ * This is a thin intent-setter - actual binding happens in reconcile().
253
+ * @param {LLMChannel} newLLMChannel - The new LLM channel to switch to
254
+ * @returns {Promise<void>}
255
+ */
256
+ public switchLLMChannel(newLLMChannel: LLMChannel): Promise<void> {
257
+ this.targetLLMChannel = newLLMChannel;
258
+
259
+ return this.reconcile();
172
260
  }
173
261
 
174
262
  /**
@@ -304,7 +392,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
304
392
  * Indicates whether the LLM channel is connected.
305
393
  * @returns {boolean}
306
394
  */
307
- public isLLMConnected = (): boolean => this.llmChannel.isConnected();
395
+ public isLLMConnected = (): boolean => this.llmChannel?.isConnected() ?? false;
308
396
 
309
397
  public getKeepTranscriptionSubscribed = (): boolean => this.keepTranscriptionSubscribed;
310
398
 
@@ -313,9 +401,10 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
313
401
  * @returns {void}
314
402
  */
315
403
  public sendAnnouncement = (): void => {
404
+ const llm = this.requireLLMChannel();
316
405
  this.announceStatus = ANNOUNCE_STATUS.JOINING;
317
- const socket = this.llmChannel.getSocket();
318
- const binding = this.llmChannel.getBinding();
406
+ const socket = llm.getSocket();
407
+ const binding = llm.getBinding();
319
408
 
320
409
  const payload = {
321
410
  id: `${this.seqNum}`,
@@ -352,7 +441,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
352
441
  ): Promise<void> =>
353
442
  this.request({
354
443
  method: 'PUT',
355
- url: `${this.llmChannel.getLocusUrl()}/controls/`,
444
+ url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,
356
445
  body: {
357
446
  transcribe: {
358
447
  spokenLanguage: languageCode,
@@ -373,8 +462,9 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
373
462
  return;
374
463
  }
375
464
 
376
- const socket = this.llmChannel.getSocket();
377
- const binding = this.llmChannel.getBinding();
465
+ const llm = this.requireLLMChannel();
466
+ const socket = llm.getSocket();
467
+ const binding = llm.getBinding();
378
468
 
379
469
  socket.send({
380
470
  id: `${this.seqNum}`,
@@ -419,8 +509,9 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
419
509
  return;
420
510
  }
421
511
 
422
- const socket = this.llmChannel.getSocket();
423
- const binding = this.llmChannel.getBinding();
512
+ const llm = this.requireLLMChannel();
513
+ const socket = llm.getSocket();
514
+ const binding = llm.getBinding();
424
515
 
425
516
  socket?.send({
426
517
  id: `${this.seqNum}`,
@@ -463,7 +554,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
463
554
  private requestTurnOnCaptions = (languageCode?: string): undefined | Promise<void> => {
464
555
  this.captionStatus = TURN_ON_CAPTION_STATUS.SENDING;
465
556
 
466
- const locusUrl = this.llmChannel.getLocusUrl();
557
+ const locusUrl = this.requireLLMChannel().getLocusUrl();
467
558
 
468
559
  const body = {
469
560
  transcribe: {caption: true},
@@ -485,7 +576,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
485
576
  })
486
577
  .catch((error) => {
487
578
  this.captionStatus = TURN_ON_CAPTION_STATUS.IDLE;
488
- throw new Error('turn on captions fail');
579
+ throw new Error('turn on captions fail', {cause: error});
489
580
  });
490
581
  };
491
582
 
@@ -529,7 +620,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
529
620
  * @returns {Promise}
530
621
  */
531
622
  public turnOnCaptions = async (spokenLanguage?: string): Promise<void | undefined> => {
532
- if (this.captionStatus === TURN_ON_CAPTION_STATUS.SENDING) return undefined;
623
+ if (this.isCaptionProcessing()) return undefined;
533
624
 
534
625
  if (!this.isLLMConnected()) {
535
626
  throw new Error('can not turn on captions before llm connected');
@@ -550,7 +641,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
550
641
  ): undefined | Promise<void> => {
551
642
  return this.request({
552
643
  method: 'PUT',
553
- url: `${this.llmChannel.getLocusUrl()}/controls/`,
644
+ url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,
554
645
  body: {
555
646
  transcribe: {
556
647
  transcribing: activate,
@@ -578,7 +669,7 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
578
669
 
579
670
  return this.request({
580
671
  method: 'PUT',
581
- url: `${this.llmChannel.getLocusUrl()}/controls/`,
672
+ url: `${this.requireLLMChannel().getLocusUrl()}/controls/`,
582
673
  body: {
583
674
  manualCaption: {
584
675
  enable,
@@ -652,11 +743,12 @@ export class VoiceaChannel extends EventEmitter implements IVoiceaChannel {
652
743
  } = {}): Promise<void> => {
653
744
  if (!this.isLLMConnected()) return;
654
745
 
655
- const isDataChannelTokenEnabled = await this.llmChannel.isDataChannelTokenEnabled();
746
+ const llm = this.requireLLMChannel();
747
+ const isDataChannelTokenEnabled = await llm.isDataChannelTokenEnabled();
656
748
  if (!isDataChannelTokenEnabled) return;
657
749
 
658
- const socket = this.llmChannel.getSocket();
659
- const datachannelUrl = this.llmChannel.getDatachannelUrl();
750
+ const socket = llm.getSocket();
751
+ const datachannelUrl = llm.getDatachannelUrl();
660
752
 
661
753
  socket.send({
662
754
  id: `${this.seqNum}`,
@@ -51,6 +51,18 @@ describe('plugin-voicea', () => {
51
51
  assert.instanceOf(channel, VoiceaChannel);
52
52
  });
53
53
 
54
+ it('creates a new VoiceaChannel instance without llmChannel', () => {
55
+ const channel = plugin.createChannel();
56
+
57
+ assert.instanceOf(channel, VoiceaChannel);
58
+ });
59
+
60
+ it('creates a new VoiceaChannel instance with undefined llmChannel', () => {
61
+ const channel = plugin.createChannel(undefined);
62
+
63
+ assert.instanceOf(channel, VoiceaChannel);
64
+ });
65
+
54
66
  it('creates independent channels for multiple calls', () => {
55
67
  const mockLLMChannel1 = createMockLLMChannel();
56
68
  const mockLLMChannel2 = createMockLLMChannel();