@convai/web-sdk 1.8.0-beta.2 → 1.8.0-beta.4
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.
- package/README.md +30 -0
- package/dist/core/AudioManager.d.ts +3 -3
- package/dist/core/AudioManager.js +1 -1
- package/dist/core/ConnectionStateHandler.d.ts +1 -1
- package/dist/core/ConvaiClient.d.ts +6 -5
- package/dist/core/ConvaiClient.d.ts.map +1 -1
- package/dist/core/ConvaiClient.js +126 -43
- package/dist/core/ConvaiClient.js.map +1 -1
- package/dist/core/MemoryManager.d.ts +1 -1
- package/dist/core/MessageHandler.d.ts +4 -3
- package/dist/core/MessageHandler.d.ts.map +1 -1
- package/dist/core/MessageHandler.js +28 -11
- package/dist/core/MessageHandler.js.map +1 -1
- package/dist/core/SSESession.d.ts +44 -0
- package/dist/core/SSESession.d.ts.map +1 -0
- package/dist/core/SSESession.js +200 -0
- package/dist/core/SSESession.js.map +1 -0
- package/dist/core/ScreenShareManager.d.ts +2 -2
- package/dist/core/ScreenShareManager.js +2 -2
- package/dist/core/VideoManager.d.ts +2 -2
- package/dist/core/VideoManager.js +3 -3
- package/dist/core/connectRequest.d.ts +3 -1
- package/dist/core/connectRequest.d.ts.map +1 -1
- package/dist/core/connectRequest.js +27 -0
- package/dist/core/connectRequest.js.map +1 -1
- package/dist/core/contextUpdateRequest.d.ts +1 -1
- package/dist/core/index.d.ts +12 -12
- package/dist/core/index.js +10 -10
- package/dist/core/logicalTurn.d.ts +5 -0
- package/dist/core/logicalTurn.d.ts.map +1 -0
- package/dist/core/logicalTurn.js +10 -0
- package/dist/core/logicalTurn.js.map +1 -0
- package/dist/core/types.d.ts +14 -5
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/videoSourceState.d.ts +1 -1
- package/dist/core/visionRequest.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lipsync-helpers/createBlendshapeQueue.d.ts +2 -2
- package/dist/lipsync-helpers/createBlendshapeQueue.js +2 -2
- package/dist/lipsync-helpers/declarativeMapping.d.ts +1 -1
- package/dist/lipsync-helpers/declarativeMapping.js +2 -2
- package/dist/lipsync-helpers/index.d.ts +12 -12
- package/dist/lipsync-helpers/index.js +9 -9
- package/dist/lipsync-helpers/mhaLimitDrivers.js +2 -2
- package/dist/lipsync-helpers/naturalness/processor.d.ts +1 -1
- package/dist/lipsync-helpers/naturalness/processor.js +1 -1
- package/dist/lipsync-helpers/naturalness/profiles/mha.d.ts +1 -1
- package/dist/lipsync-helpers/naturalness/profiles/mha.js +1 -1
- package/dist/lipsync-helpers/presetMappers.d.ts +1 -1
- package/dist/react/components/ConvaiWidget.d.ts +1 -1
- package/dist/react/components/ConvaiWidget.js +4 -4
- package/dist/react/components/index.d.ts +1 -1
- package/dist/react/components/index.js +1 -1
- package/dist/react/components/rtc-widget/components/AudioSettingsPanel.d.ts +1 -1
- package/dist/react/components/rtc-widget/components/ConviMessage.js +3 -3
- package/dist/react/components/rtc-widget/components/FloatingVideo.js +3 -3
- package/dist/react/components/rtc-widget/components/MessageBubble.js +1 -1
- package/dist/react/components/rtc-widget/components/MessageList.d.ts +1 -1
- package/dist/react/components/rtc-widget/components/MessageList.js +4 -4
- package/dist/react/components/rtc-widget/components/UserMessage.js +3 -3
- package/dist/react/components/rtc-widget/components/conviComponents/ConviButton.js +4 -4
- package/dist/react/components/rtc-widget/components/conviComponents/ConviFooter.js +3 -3
- package/dist/react/components/rtc-widget/components/conviComponents/ConviHeader.js +4 -4
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js +3 -3
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.js +3 -3
- package/dist/react/components/rtc-widget/components/conviComponents/index.d.ts +5 -5
- package/dist/react/components/rtc-widget/components/conviComponents/index.js +5 -5
- package/dist/react/components/rtc-widget/components/index.d.ts +8 -8
- package/dist/react/components/rtc-widget/components/index.js +9 -9
- package/dist/react/components/rtc-widget/index.d.ts +5 -5
- package/dist/react/components/rtc-widget/index.js +3 -3
- package/dist/react/components/rtc-widget/styles/icons.d.ts +1 -1
- package/dist/react/components/rtc-widget/styles/icons.js +1 -1
- package/dist/react/components/rtc-widget/styles/index.d.ts +5 -5
- package/dist/react/components/rtc-widget/styles/index.js +4 -4
- package/dist/react/components/rtc-widget/styles/styledComponents.js +1 -1
- package/dist/react/hooks/index.d.ts +3 -3
- package/dist/react/hooks/index.js +3 -3
- package/dist/react/hooks/useCharacterInfo.js +1 -1
- package/dist/react/hooks/useConvaiClient.d.ts +1 -1
- package/dist/react/hooks/useConvaiClient.js +1 -1
- package/dist/react/index.d.ts +6 -6
- package/dist/react/index.js +6 -6
- package/dist/vanilla/AudioRenderer.js +1 -1
- package/dist/vanilla/ConvaiWidget.d.ts +1 -1
- package/dist/vanilla/ConvaiWidget.js +4 -4
- package/dist/vanilla/WebSocketSession.d.ts +1 -1
- package/dist/vanilla/WebSocketSession.js +1 -1
- package/dist/vanilla/index.d.ts +5 -5
- package/dist/vanilla/index.js +4 -4
- package/dist/vanilla/types.d.ts +1 -1
- package/dist/vanilla/websocket.d.ts +1 -1
- package/dist/vanilla/websocket.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RoomEvent } from "livekit-client";
|
|
2
|
-
import { EventEmitter } from "./EventEmitter";
|
|
3
|
-
import { BlendshapeQueue, } from "./BlendshapeQueue";
|
|
2
|
+
import { EventEmitter } from "./EventEmitter.js";
|
|
3
|
+
import { BlendshapeQueue, } from "./BlendshapeQueue.js";
|
|
4
4
|
/**
|
|
5
5
|
* Handles incoming messages from Convai
|
|
6
6
|
* Processes various message types from the AI assistant and updates chat history
|
|
@@ -10,6 +10,7 @@ export class MessageHandler extends EventEmitter {
|
|
|
10
10
|
super();
|
|
11
11
|
this.room = null;
|
|
12
12
|
this.chatMessages = [];
|
|
13
|
+
this.activeBotLlmMessageId = null;
|
|
13
14
|
this.userTranscription = "";
|
|
14
15
|
this.logRtviMessages = true;
|
|
15
16
|
this.isBotResponding = false;
|
|
@@ -162,6 +163,7 @@ export class MessageHandler extends EventEmitter {
|
|
|
162
163
|
timestamp: timestamp,
|
|
163
164
|
isStreaming: true,
|
|
164
165
|
};
|
|
166
|
+
this.activeBotLlmMessageId = messageId;
|
|
165
167
|
this.chatMessages.push(streamingMessage);
|
|
166
168
|
this.emit("messagesChange", this.chatMessages);
|
|
167
169
|
break;
|
|
@@ -188,10 +190,15 @@ export class MessageHandler extends EventEmitter {
|
|
|
188
190
|
break;
|
|
189
191
|
this.seenBotOutputSegments.add(segmentId);
|
|
190
192
|
}
|
|
193
|
+
const activeBotLlmMessage = this.activeBotLlmMessageId
|
|
194
|
+
? this.chatMessages.find((message) => message.id === this.activeBotLlmMessageId)
|
|
195
|
+
: undefined;
|
|
191
196
|
const lastMsg = this.chatMessages[this.chatMessages.length - 1];
|
|
192
197
|
// When the reply is rendered by the LLM text stream
|
|
193
198
|
// (bot-llm-text), the TTS echo adds nothing — never mix
|
|
194
199
|
// bot-output into an LLM bubble (streaming or complete).
|
|
200
|
+
if (activeBotLlmMessage?.type === "bot-llm-text")
|
|
201
|
+
break;
|
|
195
202
|
if (lastMsg?.type === "bot-llm-text")
|
|
196
203
|
break;
|
|
197
204
|
if (lastMsg?.type === "bot-output" &&
|
|
@@ -221,11 +228,16 @@ export class MessageHandler extends EventEmitter {
|
|
|
221
228
|
if (messageData.data?.text) {
|
|
222
229
|
const newChunk = messageData.data.text;
|
|
223
230
|
// Update the streaming message in chat
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
231
|
+
const activeIndex = this.activeBotLlmMessageId
|
|
232
|
+
? this.chatMessages.findIndex((message) => message.id === this.activeBotLlmMessageId &&
|
|
233
|
+
message.type === "bot-llm-text" &&
|
|
234
|
+
message.isStreaming)
|
|
235
|
+
: -1;
|
|
236
|
+
if (activeIndex >= 0) {
|
|
237
|
+
const activeMessage = this.chatMessages[activeIndex];
|
|
238
|
+
this.chatMessages[activeIndex] = {
|
|
239
|
+
...activeMessage,
|
|
240
|
+
content: activeMessage.content + newChunk,
|
|
229
241
|
};
|
|
230
242
|
}
|
|
231
243
|
else {
|
|
@@ -237,6 +249,7 @@ export class MessageHandler extends EventEmitter {
|
|
|
237
249
|
timestamp: new Date().toISOString(),
|
|
238
250
|
isStreaming: true,
|
|
239
251
|
};
|
|
252
|
+
this.activeBotLlmMessageId = streamingMsg.id;
|
|
240
253
|
this.chatMessages.push(streamingMsg);
|
|
241
254
|
}
|
|
242
255
|
this.emit("messagesChange", this.chatMessages);
|
|
@@ -244,10 +257,13 @@ export class MessageHandler extends EventEmitter {
|
|
|
244
257
|
break;
|
|
245
258
|
// Bot LLM Stopped - Complete streaming response
|
|
246
259
|
case "bot-llm-stopped":
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
260
|
+
const activeIndex = this.activeBotLlmMessageId
|
|
261
|
+
? this.chatMessages.findIndex((message) => message.id === this.activeBotLlmMessageId)
|
|
262
|
+
: -1;
|
|
263
|
+
if (activeIndex >= 0 && this.chatMessages[activeIndex].isStreaming) {
|
|
264
|
+
const activeMessage = this.chatMessages[activeIndex];
|
|
265
|
+
this.chatMessages[activeIndex] = {
|
|
266
|
+
...activeMessage,
|
|
251
267
|
isStreaming: false,
|
|
252
268
|
};
|
|
253
269
|
}
|
|
@@ -599,6 +615,7 @@ export class MessageHandler extends EventEmitter {
|
|
|
599
615
|
*/
|
|
600
616
|
reset() {
|
|
601
617
|
this.chatMessages = [];
|
|
618
|
+
this.activeBotLlmMessageId = null;
|
|
602
619
|
this.userTranscription = "";
|
|
603
620
|
this.isBotResponding = false;
|
|
604
621
|
this.isSpeaking = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../src/core/MessageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { Room, RoomEvent } from \"livekit-client\";\nimport { ChatMessage, ConvaiAction, InteractionCreated, ServerResponse } from \"./types\";\nimport { EventEmitter } from \"./EventEmitter\";\nimport {\n BlendshapeQueue,\n type BlendshapeChunkMetadata,\n} from \"./BlendshapeQueue\";\n\ntype LifecycleOwnerPayload = {\n response_id?: string;\n neurosync_turn_id?: number;\n turn_id?: number;\n epoch?: number;\n};\n\n/**\n * Handles incoming messages from Convai\n * Processes various message types from the AI assistant and updates chat history\n */\nexport class MessageHandler extends EventEmitter {\n private room: Room | null = null;\n private chatMessages: ChatMessage[] = [];\n private userTranscription: string = \"\";\n private logRtviMessages: boolean = true;\n private isBotResponding: boolean = false;\n private isSpeaking: boolean = false;\n private isListening: boolean = false;\n private totalBlendshapesReceived: number = 0;\n private blendshapeQueue: BlendshapeQueue;\n private _currentEmotion: { emotion: string; scale?: number } | null = null;\n // bot-output segments already added to the chat. The server re-sends the\n // same segment (full text) as TTS progress advances (spoken_status\n // in-progress → completed); only the first sighting may touch the chat.\n private seenBotOutputSegments = new Set<number | string>();\n\n // Fix 4: store a single bound reference so setupListeners/cleanupListeners use the\n // exact same function object. Previously .bind(this) in each call created a new\n // reference every time, making room.off() a no-op and leaking listeners on reconnect.\n private readonly _boundHandleDataReceived: (\n payload: Uint8Array,\n participant: unknown,\n ) => void;\n\n constructor(room?: Room) {\n super();\n this._boundHandleDataReceived = this.handleDataReceived.bind(this);\n this.blendshapeQueue = new BlendshapeQueue();\n if (room) {\n this.setRoom(room);\n }\n }\n\n /**\n * Get the blendshape queue instance\n */\n getBlendshapeQueue(): BlendshapeQueue {\n return this.blendshapeQueue;\n }\n\n /**\n * Enable or disable console logging for decoded incoming RTVI messages.\n */\n setRtviMessageLogging(enabled: boolean): void {\n this.logRtviMessages = enabled;\n }\n\n /**\n * Get current chat messages\n */\n getChatMessages(): ChatMessage[] {\n return this.chatMessages;\n }\n\n /**\n * Get current user transcription\n */\n getUserTranscription(): string {\n return this.userTranscription;\n }\n\n /**\n * Get bot responding state\n */\n getIsBotResponding(): boolean {\n return this.isBotResponding;\n }\n\n /**\n * Get speaking state\n */\n getIsSpeaking(): boolean {\n return this.isSpeaking;\n }\n\n /**\n * Get current bot emotion (updated from bot-emotion messages)\n */\n getEmotion(): { emotion: string; scale?: number } | null {\n return this._currentEmotion;\n }\n\n /**\n * Get whether the user is currently speaking (bot is in \"listening\" state).\n * True from user-started-speaking until user-stopped-speaking.\n */\n getIsListening(): boolean {\n return this.isListening;\n }\n\n /**\n * Local interruption path used by the client before the server cancel/terminal\n * arrives. Keep MessageHandler state and BlendshapeQueue state in sync so the\n * next bot-started-speaking can activate cleanly.\n */\n interruptLipsyncPlayback(): void {\n const wasSpeaking = this.isSpeaking;\n this.isSpeaking = false;\n this.blendshapeQueue.interrupt();\n if (wasSpeaking) {\n this.emit(\"speakingChange\", false);\n }\n }\n\n /**\n * Set the LiveKit room instance\n */\n setRoom(room: Room): void {\n // Clean up previous room listeners\n if (this.room) {\n this.cleanupListeners();\n }\n\n this.room = room;\n this.setupListeners();\n }\n\n /**\n * Setup message listeners\n */\n private setupListeners(): void {\n if (!this.room) return;\n\n this.room.on(RoomEvent.DataReceived, this._boundHandleDataReceived);\n }\n\n /**\n * Clean up message listeners\n */\n private cleanupListeners(): void {\n if (!this.room) return;\n\n this.room.off(RoomEvent.DataReceived, this._boundHandleDataReceived);\n }\n\n /**\n * Handle incoming data message\n */\n private handleDataReceived(\n payload: Uint8Array,\n _participant: unknown,\n _transport: \"livekit\" | \"websocket\" = \"livekit\",\n ): void {\n let messageString = \"\";\n let parsed = false;\n\n try {\n // Decode bytes to string\n const decoder = new TextDecoder();\n messageString = decoder.decode(payload);\n\n // Parse JSON\n const messageData = JSON.parse(messageString);\n parsed = true;\n\n // Extract and categorize messages for chat display\n const timestamp = new Date().toISOString();\n const messageId = `${messageData.type}-${Date.now()}-${Math.random()}`;\n\n // Handle different message types\n switch (messageData.type) {\n // User text messages - Skip these, only allow user-transcription\n case \"user_text_message\":\n case \"user-llm-text\":\n case \"text-input\":\n case \"user-input\":\n case \"text-message\":\n case \"chat-message\":\n case \"input-text\":\n case \"message\":\n // Skip user text messages - only allow user-transcription\n break;\n\n // Bot Ready - Bot is ready, connection should be true\n case \"bot-ready\":\n this.emit(\"botReady\");\n break;\n\n // Bot LLM Started - Begin streaming response\n case \"bot-llm-started\":\n this.isBotResponding = true;\n this.emit(\"botRespondingChange\", true);\n this.seenBotOutputSegments.clear();\n\n // Add initial streaming message to chat\n const streamingMessage: ChatMessage = {\n id: messageId,\n type: \"bot-llm-text\",\n content: \"\",\n timestamp: timestamp,\n isStreaming: true,\n };\n this.chatMessages.push(streamingMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // Bot Output - Aggregated output stream (sentence/word-level, replaces bot-transcript)\n // Payload: { text, spoken, aggregated_by, segment_id, spoken_status,\n // spoken_progress }. The same segment_id is re-sent with the FULL\n // segment text on every TTS progress tick (spoken_status\n // \"in-progress\" → \"completed\"), so appending per event repeats the\n // sentence once per tick.\n case \"bot-output\":\n if (messageData.data?.text) {\n const newText = messageData.data.text;\n const segmentId = messageData.data.segment_id as\n | number\n | string\n | undefined;\n this.emit(\"botOutput\", {\n text: newText,\n spoken: messageData.data.spoken ?? false,\n aggregatedBy: messageData.data.aggregated_by ?? \"sentence\",\n segmentId,\n spokenStatus: messageData.data.spoken_status,\n });\n\n // Progress re-send of a segment already in the chat — skip.\n if (segmentId !== undefined) {\n if (this.seenBotOutputSegments.has(segmentId)) break;\n this.seenBotOutputSegments.add(segmentId);\n }\n\n const lastMsg = this.chatMessages[this.chatMessages.length - 1];\n // When the reply is rendered by the LLM text stream\n // (bot-llm-text), the TTS echo adds nothing — never mix\n // bot-output into an LLM bubble (streaming or complete).\n if (lastMsg?.type === \"bot-llm-text\") break;\n if (\n lastMsg?.type === \"bot-output\" &&\n lastMsg.content.includes(newText)\n ) {\n break;\n }\n if (lastMsg?.type === \"bot-output\" && lastMsg.isStreaming) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastMsg,\n content: lastMsg.content + newText,\n };\n } else {\n this.chatMessages.push({\n id: `bot-output-${Date.now()}-${Math.random()}`,\n type: \"bot-output\",\n content: newText,\n timestamp: new Date().toISOString(),\n isStreaming: true,\n });\n }\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Bot LLM Text Messages - Streaming chunks\n case \"bot-llm-text\":\n if (messageData.data?.text) {\n const newChunk = messageData.data.text;\n\n // Update the streaming message in chat\n const lastMessage = this.chatMessages[this.chatMessages.length - 1];\n if (lastMessage && lastMessage.isStreaming) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastMessage,\n content: lastMessage.content + newChunk,\n };\n } else {\n // If no streaming message exists yet, create one\n const streamingMsg: ChatMessage = {\n id: `${messageData.type}-${Date.now()}-${Math.random()}`,\n type: \"bot-llm-text\",\n content: newChunk,\n timestamp: new Date().toISOString(),\n isStreaming: true,\n };\n this.chatMessages.push(streamingMsg);\n }\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Bot LLM Stopped - Complete streaming response\n case \"bot-llm-stopped\":\n const lastBotMsg = this.chatMessages[this.chatMessages.length - 1];\n if (lastBotMsg && lastBotMsg.isStreaming) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastBotMsg,\n isStreaming: false,\n };\n }\n\n // Clear streaming state\n this.isBotResponding = false;\n this.emit(\"botRespondingChange\", false);\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // User Transcription Messages\n case \"user-transcription\":\n if (messageData.data?.text) {\n const messageContent = messageData.data.text;\n\n if (messageData.data?.final) {\n // Final transcription - accumulate in single bubble until bot responds\n const lastUserMsg =\n this.chatMessages[this.chatMessages.length - 1];\n\n // Check if last message is an accumulating user message (isStreaming=true)\n if (\n lastUserMsg &&\n lastUserMsg.type === \"user-transcription\" &&\n lastUserMsg.isStreaming === true\n ) {\n // Accumulate: append new content to existing message with space\n const accumulatedContent =\n lastUserMsg.content.trim() + \" \" + messageContent.trim();\n\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastUserMsg,\n content: accumulatedContent,\n timestamp: timestamp,\n };\n } else {\n // Start new accumulating message (isStreaming=true means \"still accumulating\")\n const userMessage: ChatMessage = {\n id: messageId,\n type: \"user-transcription\",\n content: messageContent,\n timestamp: timestamp,\n isStreaming: true,\n };\n this.chatMessages.push(userMessage);\n }\n this.emit(\"messagesChange\", this.chatMessages);\n\n // Clear live transcription when final\n this.userTranscription = \"\";\n this.emit(\"userTranscriptionChange\", \"\");\n } else {\n // Non-final transcription - show in input field\n this.userTranscription = messageContent;\n this.emit(\"userTranscriptionChange\", messageContent);\n }\n }\n break;\n\n // Bot Emotion Messages — LiveKit path: arrives as an RTVI message frame (messageData.data)\n case \"bot-emotion\":\n if (messageData.data?.emotion) {\n this._currentEmotion = {\n emotion: messageData.data.emotion,\n scale: messageData.data.scale,\n };\n console.log(\"[SDK bot-emotion]\", messageData.data);\n this.emit(\"emotionChange\", this._currentEmotion);\n const emotionMessage: ChatMessage = {\n id: messageId,\n type: \"bot-emotion\",\n content: `${messageData.data.emotion} (scale: ${messageData.data.scale || 1})`,\n timestamp,\n };\n this.chatMessages.push(emotionMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n // Bot TTS Text - Words as spoken by TTS (word-by-word for socket-based TTS)\n case \"bot-tts-text\":\n if (messageData.data?.text) {\n this.emit(\"botTtsText\", { text: messageData.data.text });\n }\n break;\n\n // Bot TTS lifecycle (more granular than bot-started/stopped-speaking)\n case \"bot-tts-started\":\n this.emit(\"botTtsStarted\");\n break;\n\n case \"bot-tts-stopped\":\n this.emit(\"botTtsStopped\");\n break;\n\n // Server-side muting indicators\n case \"user-mute-started\":\n this.emit(\"userMuteStarted\");\n break;\n\n case \"user-mute-stopped\":\n this.emit(\"userMuteStopped\");\n break;\n\n case \"user-started-speaking\":\n this.isListening = true;\n this.emit(\"listeningChange\", true);\n break;\n\n case \"user-stopped-speaking\":\n this.isListening = false;\n this.emit(\"listeningChange\", false);\n break;\n\n // Bot Started Speaking (priority over listening: state becomes speaking)\n case \"bot-started-speaking\": {\n const owner = this.lifecycleOwner(messageData.data);\n if (this.blendshapeQueue.isStaleOwner(owner)) {\n break;\n }\n const allowed = this.blendshapeQueue.startBotSpeaking();\n if (allowed) {\n this.isSpeaking = true;\n this.totalBlendshapesReceived = 0;\n this.emit(\"speakingChange\", true);\n }\n break;\n }\n\n // Bot Stopped Speaking\n case \"bot-stopped-speaking\":\n if (this.blendshapeQueue.isStaleOwner(this.lifecycleOwner(messageData.data))) {\n break;\n }\n if (this.isSpeaking) {\n this.isSpeaking = false;\n this.blendshapeQueue.stopBotSpeaking();\n this.emit(\"speakingChange\", false);\n }\n break;\n\n // Action Response Messages (LiveKit/WebRTC path)\n case \"action-response\":\n this._handleActionResponse(messageData.data?.actions ?? [], messageId, timestamp);\n break;\n\n case \"metrics\":\n if (messageData.data) {\n this.emit(\"metrics\", messageData.data);\n }\n break;\n // Behavior Tree Response Messages\n case \"behavior-tree-response\":\n if (messageData.data?.narrative_section_id) {\n const behaviorMessage: ChatMessage = {\n id: messageId,\n type: \"behavior-tree\",\n content: `Narrative Section: ${messageData.data.narrative_section_id}`,\n timestamp,\n };\n this.chatMessages.push(behaviorMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Server Message - Contains various data types like blendshapes\n case \"server-message\":\n if (messageData.data) {\n const serverData = messageData.data;\n\n switch (serverData.type) {\n case \"final-user-transcription\":\n if (serverData.text) {\n const finalText = serverData.text;\n const lastUserMsg =\n this.chatMessages[this.chatMessages.length - 1];\n if (\n lastUserMsg &&\n lastUserMsg.type === \"user-transcription\" &&\n lastUserMsg.isStreaming === true\n ) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastUserMsg,\n content: finalText,\n timestamp,\n isStreaming: false,\n };\n } else {\n this.chatMessages.push({\n id: `${serverData.type}-${Date.now()}-${Math.random()}`,\n type: \"user-transcription\",\n content: finalText,\n timestamp,\n isStreaming: false,\n });\n }\n this.emit(\"messagesChange\", this.chatMessages);\n this.userTranscription = \"\";\n this.emit(\"userTranscriptionChange\", \"\");\n }\n break;\n\n // WebSocket path: arrives inside a bot-text data message as serverData (not messageData.data)\n case \"bot-emotion\":\n if (serverData.emotion) {\n this._currentEmotion = {\n emotion: serverData.emotion,\n scale: serverData.scale,\n };\n console.log(\"[SDK bot-emotion (ws)]\", serverData);\n this.emit(\"emotionChange\", this._currentEmotion);\n }\n break;\n\n case \"blendshape-turn-stats\":\n if (this.blendshapeQueue.isStaleOwner(this.lifecycleOwner(serverData))) {\n break;\n }\n this.blendshapeQueue.endConversation(\n serverData.stats,\n this.lifecycleOwner(serverData),\n );\n this.emit(\"blendshapeStatsReceived\", serverData);\n break;\n\n case \"chunked-neurosync-blendshapes\":\n if (serverData.blendshapes) {\n const owner = this.lifecycleOwner(serverData);\n if (this.blendshapeQueue.isRetiredOwner(owner)) {\n break;\n }\n // If the queue is idle (no active conversation, bot not yet speaking),\n // start a conversation so early chunks from an initial bot greeting\n // are accepted rather than silently dropped.\n if (\n !this.blendshapeQueue.isConversationActive() &&\n !this.isSpeaking\n ) {\n this.blendshapeQueue.startConversation();\n }\n this.blendshapeQueue.addChunk(\n serverData.blendshapes,\n owner,\n );\n if (\n this.blendshapeQueue.consumeOwnerReplacementStoppedSpeaking() &&\n this.isSpeaking\n ) {\n this.isSpeaking = false;\n this.emit(\"speakingChange\", false);\n }\n this.totalBlendshapesReceived +=\n serverData.blendshapes.length;\n this.emit(\"blendshapes\", serverData);\n }\n break;\n\n case \"neurosync-blendshapes-cancel\": {\n const cancelledActive = this.blendshapeQueue.cancelOwner(\n this.lifecycleOwner(serverData),\n );\n if (cancelledActive && this.isSpeaking) {\n this.isSpeaking = false;\n this.emit(\"speakingChange\", false);\n }\n this.emit(\"blendshapeCancel\", serverData);\n break;\n }\n\n case \"user-idle-warning\": {\n const remainingSeconds: number | null =\n serverData.remaining_seconds ??\n serverData.remainingSeconds ??\n null;\n this.emit(\"idleWarning\", { remainingSeconds });\n this.chatMessages.push({\n id: `user-idle-warning-${Date.now()}-${Math.random()}`,\n type: \"idle-warning\",\n content:\n remainingSeconds !== null ? String(remainingSeconds) : \"\",\n timestamp,\n });\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n }\n\n case \"llm-no-response\":\n this.emit(\"llmNoResponse\");\n this.chatMessages.push({\n id: `llm-no-response-${Date.now()}-${Math.random()}`,\n type: \"llm-no-response\",\n content: \"\",\n timestamp,\n });\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // Action Response (WebSocket/RTVI path — wrapped in server-message)\n case \"action-response\":\n this._handleActionResponse(serverData.actions ?? [], messageId, timestamp);\n break;\n\n // Server acknowledgment — arrives wrapped in server-message envelope\n case \"server-response\": {\n // client-ready is an internal RTVI handshake; server echoes an\n // \"Unknown message type\" error for it which is expected and harmless.\n if (serverData.event_type === \"client-ready\") break;\n const serverResponse: ServerResponse = {\n event_type: serverData.event_type ?? \"unknown\",\n status: serverData.status ?? \"error\",\n message: serverData.message ?? null,\n extras: serverData.extras ?? null,\n };\n this.emit(\"serverResponse\", serverResponse);\n break;\n }\n\n // interaction-created: session IDs for analytics/tracking\n case \"interaction-created\": {\n const interactionCreated: InteractionCreated = {\n interactionId: serverData.interaction_id,\n characterSessionId: serverData.character_session_id,\n };\n this.emit(\"interactionCreated\", interactionCreated);\n break;\n }\n }\n }\n break;\n\n // Fallback: server-response at top level (not currently observed but kept for safety)\n case \"server-response\": {\n if (messageData.event_type === \"client-ready\") break;\n const serverResponse: ServerResponse = {\n event_type: messageData.event_type ?? \"unknown\",\n status: messageData.status ?? \"error\",\n message: messageData.message ?? null,\n extras: messageData.extras ?? null,\n };\n this.emit(\"serverResponse\", serverResponse);\n break;\n }\n\n // Silently ignore other message types\n case \"moderation-response\":\n case \"trigger-message\":\n case \"update-template-keys\":\n case \"update-dynamic-info\":\n case \"interrupt-bot\":\n break;\n }\n } catch (error) {\n // Silently handle parse errors\n }\n }\n\n private _handleActionResponse(\n actions: ConvaiAction[],\n messageId: string,\n timestamp: string,\n ): void {\n this.emit(\"actionResponse\", { actions });\n const label = actions.length === 0\n ? \"No action\"\n : actions.map((a) => (a.target ? `${a.name} → ${a.target}` : a.name)).join(\", \");\n const actionMessage: ChatMessage = {\n id: messageId,\n type: \"action\",\n content: label,\n timestamp,\n };\n this.chatMessages.push(actionMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n\n private lifecycleOwner(\n data: LifecycleOwnerPayload | undefined,\n ): BlendshapeChunkMetadata {\n if (!data) {\n return {};\n }\n\n return {\n responseId: data.response_id,\n neurosyncTurnId: data.neurosync_turn_id ?? data.turn_id,\n epoch: data.epoch,\n fps: this.numberOrUndefined((data as { fps?: number }).fps),\n startFrameIndex: this.numberOrUndefined(\n (data as { start_frame_index?: number }).start_frame_index,\n ),\n };\n }\n\n private numberOrUndefined(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n }\n\n /**\n * Public entry point for WebSocket transport to inject messages into the same pipeline.\n */\n handleDataReceivedPublic(payload: Uint8Array): void {\n this.handleDataReceived(payload, null, \"websocket\");\n }\n\n /**\n * Reset message state\n */\n reset(): void {\n this.chatMessages = [];\n this.userTranscription = \"\";\n this.isBotResponding = false;\n this.isSpeaking = false;\n this.isListening = false;\n this.totalBlendshapesReceived = 0;\n this._currentEmotion = null;\n this.blendshapeQueue.reset();\n this.emit(\"messagesChange\", this.chatMessages);\n this.emit(\"userTranscriptionChange\", \"\");\n this.emit(\"botRespondingChange\", false);\n this.emit(\"speakingChange\", false);\n this.emit(\"listeningChange\", false);\n this.emit(\"emotionChange\", null);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../src/core/MessageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { Room, RoomEvent } from \"livekit-client\";\nimport { ChatMessage, ConvaiAction, InteractionCreated, ServerResponse } from \"./types\";\nimport { EventEmitter } from \"./EventEmitter\";\nimport {\n BlendshapeQueue,\n type BlendshapeChunkMetadata,\n} from \"./BlendshapeQueue\";\n\ntype LifecycleOwnerPayload = {\n response_id?: string;\n neurosync_turn_id?: number;\n turn_id?: number;\n epoch?: number;\n};\n\n/**\n * Handles incoming messages from Convai\n * Processes various message types from the AI assistant and updates chat history\n */\nexport class MessageHandler extends EventEmitter {\n private room: Room | null = null;\n private chatMessages: ChatMessage[] = [];\n private activeBotLlmMessageId: string | null = null;\n private userTranscription: string = \"\";\n private logRtviMessages: boolean = true;\n private isBotResponding: boolean = false;\n private isSpeaking: boolean = false;\n private isListening: boolean = false;\n private totalBlendshapesReceived: number = 0;\n private blendshapeQueue: BlendshapeQueue;\n private _currentEmotion: { emotion: string; scale?: number } | null = null;\n // bot-output segments already added to the chat. The server re-sends the\n // same segment (full text) as TTS progress advances (spoken_status\n // in-progress → completed); only the first sighting may touch the chat.\n private seenBotOutputSegments = new Set<number | string>();\n\n // Fix 4: store a single bound reference so setupListeners/cleanupListeners use the\n // exact same function object. Previously .bind(this) in each call created a new\n // reference every time, making room.off() a no-op and leaking listeners on reconnect.\n private readonly _boundHandleDataReceived: (\n payload: Uint8Array,\n participant: unknown,\n ) => void;\n\n constructor(room?: Room) {\n super();\n this._boundHandleDataReceived = this.handleDataReceived.bind(this);\n this.blendshapeQueue = new BlendshapeQueue();\n if (room) {\n this.setRoom(room);\n }\n }\n\n /**\n * Get the blendshape queue instance\n */\n getBlendshapeQueue(): BlendshapeQueue {\n return this.blendshapeQueue;\n }\n\n /**\n * Enable or disable console logging for decoded incoming RTVI messages.\n */\n setRtviMessageLogging(enabled: boolean): void {\n this.logRtviMessages = enabled;\n }\n\n /**\n * Get current chat messages\n */\n getChatMessages(): ChatMessage[] {\n return this.chatMessages;\n }\n\n /**\n * Get current user transcription\n */\n getUserTranscription(): string {\n return this.userTranscription;\n }\n\n /**\n * Get bot responding state\n */\n getIsBotResponding(): boolean {\n return this.isBotResponding;\n }\n\n /**\n * Get speaking state\n */\n getIsSpeaking(): boolean {\n return this.isSpeaking;\n }\n\n /**\n * Get current bot emotion (updated from bot-emotion messages)\n */\n getEmotion(): { emotion: string; scale?: number } | null {\n return this._currentEmotion;\n }\n\n /**\n * Get whether the user is currently speaking (bot is in \"listening\" state).\n * True from user-started-speaking until user-stopped-speaking.\n */\n getIsListening(): boolean {\n return this.isListening;\n }\n\n /**\n * Local interruption path used by the client before the server cancel/terminal\n * arrives. Keep MessageHandler state and BlendshapeQueue state in sync so the\n * next bot-started-speaking can activate cleanly.\n */\n interruptLipsyncPlayback(): void {\n const wasSpeaking = this.isSpeaking;\n this.isSpeaking = false;\n this.blendshapeQueue.interrupt();\n if (wasSpeaking) {\n this.emit(\"speakingChange\", false);\n }\n }\n\n /**\n * Set the LiveKit room instance\n */\n setRoom(room: Room): void {\n // Clean up previous room listeners\n if (this.room) {\n this.cleanupListeners();\n }\n\n this.room = room;\n this.setupListeners();\n }\n\n /**\n * Setup message listeners\n */\n private setupListeners(): void {\n if (!this.room) return;\n\n this.room.on(RoomEvent.DataReceived, this._boundHandleDataReceived);\n }\n\n /**\n * Clean up message listeners\n */\n private cleanupListeners(): void {\n if (!this.room) return;\n\n this.room.off(RoomEvent.DataReceived, this._boundHandleDataReceived);\n }\n\n /**\n * Handle incoming data message\n */\n private handleDataReceived(\n payload: Uint8Array,\n _participant: unknown,\n _transport: \"livekit\" | \"websocket\" = \"livekit\",\n ): void {\n let messageString = \"\";\n let parsed = false;\n\n try {\n // Decode bytes to string\n const decoder = new TextDecoder();\n messageString = decoder.decode(payload);\n\n // Parse JSON\n const messageData = JSON.parse(messageString);\n parsed = true;\n\n // Extract and categorize messages for chat display\n const timestamp = new Date().toISOString();\n const messageId = `${messageData.type}-${Date.now()}-${Math.random()}`;\n\n // Handle different message types\n switch (messageData.type) {\n // User text messages - Skip these, only allow user-transcription\n case \"user_text_message\":\n case \"user-llm-text\":\n case \"text-input\":\n case \"user-input\":\n case \"text-message\":\n case \"chat-message\":\n case \"input-text\":\n case \"message\":\n // Skip user text messages - only allow user-transcription\n break;\n\n // Bot Ready - Bot is ready, connection should be true\n case \"bot-ready\":\n this.emit(\"botReady\");\n break;\n\n // Bot LLM Started - Begin streaming response\n case \"bot-llm-started\":\n this.isBotResponding = true;\n this.emit(\"botRespondingChange\", true);\n this.seenBotOutputSegments.clear();\n\n // Add initial streaming message to chat\n const streamingMessage: ChatMessage = {\n id: messageId,\n type: \"bot-llm-text\",\n content: \"\",\n timestamp: timestamp,\n isStreaming: true,\n };\n this.activeBotLlmMessageId = messageId;\n this.chatMessages.push(streamingMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // Bot Output - Aggregated output stream (sentence/word-level, replaces bot-transcript)\n // Payload: { text, spoken, aggregated_by, segment_id, spoken_status,\n // spoken_progress }. The same segment_id is re-sent with the FULL\n // segment text on every TTS progress tick (spoken_status\n // \"in-progress\" → \"completed\"), so appending per event repeats the\n // sentence once per tick.\n case \"bot-output\":\n if (messageData.data?.text) {\n const newText = messageData.data.text;\n const segmentId = messageData.data.segment_id as\n | number\n | string\n | undefined;\n this.emit(\"botOutput\", {\n text: newText,\n spoken: messageData.data.spoken ?? false,\n aggregatedBy: messageData.data.aggregated_by ?? \"sentence\",\n segmentId,\n spokenStatus: messageData.data.spoken_status,\n });\n\n // Progress re-send of a segment already in the chat — skip.\n if (segmentId !== undefined) {\n if (this.seenBotOutputSegments.has(segmentId)) break;\n this.seenBotOutputSegments.add(segmentId);\n }\n\n const activeBotLlmMessage = this.activeBotLlmMessageId\n ? this.chatMessages.find(\n (message) => message.id === this.activeBotLlmMessageId,\n )\n : undefined;\n const lastMsg = this.chatMessages[this.chatMessages.length - 1];\n // When the reply is rendered by the LLM text stream\n // (bot-llm-text), the TTS echo adds nothing — never mix\n // bot-output into an LLM bubble (streaming or complete).\n if (activeBotLlmMessage?.type === \"bot-llm-text\") break;\n if (lastMsg?.type === \"bot-llm-text\") break;\n if (\n lastMsg?.type === \"bot-output\" &&\n lastMsg.content.includes(newText)\n ) {\n break;\n }\n if (lastMsg?.type === \"bot-output\" && lastMsg.isStreaming) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastMsg,\n content: lastMsg.content + newText,\n };\n } else {\n this.chatMessages.push({\n id: `bot-output-${Date.now()}-${Math.random()}`,\n type: \"bot-output\",\n content: newText,\n timestamp: new Date().toISOString(),\n isStreaming: true,\n });\n }\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Bot LLM Text Messages - Streaming chunks\n case \"bot-llm-text\":\n if (messageData.data?.text) {\n const newChunk = messageData.data.text;\n\n // Update the streaming message in chat\n const activeIndex = this.activeBotLlmMessageId\n ? this.chatMessages.findIndex(\n (message) =>\n message.id === this.activeBotLlmMessageId &&\n message.type === \"bot-llm-text\" &&\n message.isStreaming,\n )\n : -1;\n if (activeIndex >= 0) {\n const activeMessage = this.chatMessages[activeIndex];\n this.chatMessages[activeIndex] = {\n ...activeMessage,\n content: activeMessage.content + newChunk,\n };\n } else {\n // If no streaming message exists yet, create one\n const streamingMsg: ChatMessage = {\n id: `${messageData.type}-${Date.now()}-${Math.random()}`,\n type: \"bot-llm-text\",\n content: newChunk,\n timestamp: new Date().toISOString(),\n isStreaming: true,\n };\n this.activeBotLlmMessageId = streamingMsg.id;\n this.chatMessages.push(streamingMsg);\n }\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Bot LLM Stopped - Complete streaming response\n case \"bot-llm-stopped\":\n const activeIndex = this.activeBotLlmMessageId\n ? this.chatMessages.findIndex(\n (message) => message.id === this.activeBotLlmMessageId,\n )\n : -1;\n if (activeIndex >= 0 && this.chatMessages[activeIndex].isStreaming) {\n const activeMessage = this.chatMessages[activeIndex];\n this.chatMessages[activeIndex] = {\n ...activeMessage,\n isStreaming: false,\n };\n }\n\n // Clear streaming state\n this.isBotResponding = false;\n this.emit(\"botRespondingChange\", false);\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // User Transcription Messages\n case \"user-transcription\":\n if (messageData.data?.text) {\n const messageContent = messageData.data.text;\n\n if (messageData.data?.final) {\n // Final transcription - accumulate in single bubble until bot responds\n const lastUserMsg =\n this.chatMessages[this.chatMessages.length - 1];\n\n // Check if last message is an accumulating user message (isStreaming=true)\n if (\n lastUserMsg &&\n lastUserMsg.type === \"user-transcription\" &&\n lastUserMsg.isStreaming === true\n ) {\n // Accumulate: append new content to existing message with space\n const accumulatedContent =\n lastUserMsg.content.trim() + \" \" + messageContent.trim();\n\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastUserMsg,\n content: accumulatedContent,\n timestamp: timestamp,\n };\n } else {\n // Start new accumulating message (isStreaming=true means \"still accumulating\")\n const userMessage: ChatMessage = {\n id: messageId,\n type: \"user-transcription\",\n content: messageContent,\n timestamp: timestamp,\n isStreaming: true,\n };\n this.chatMessages.push(userMessage);\n }\n this.emit(\"messagesChange\", this.chatMessages);\n\n // Clear live transcription when final\n this.userTranscription = \"\";\n this.emit(\"userTranscriptionChange\", \"\");\n } else {\n // Non-final transcription - show in input field\n this.userTranscription = messageContent;\n this.emit(\"userTranscriptionChange\", messageContent);\n }\n }\n break;\n\n // Bot Emotion Messages — LiveKit path: arrives as an RTVI message frame (messageData.data)\n case \"bot-emotion\":\n if (messageData.data?.emotion) {\n this._currentEmotion = {\n emotion: messageData.data.emotion,\n scale: messageData.data.scale,\n };\n console.log(\"[SDK bot-emotion]\", messageData.data);\n this.emit(\"emotionChange\", this._currentEmotion);\n const emotionMessage: ChatMessage = {\n id: messageId,\n type: \"bot-emotion\",\n content: `${messageData.data.emotion} (scale: ${messageData.data.scale || 1})`,\n timestamp,\n };\n this.chatMessages.push(emotionMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n // Bot TTS Text - Words as spoken by TTS (word-by-word for socket-based TTS)\n case \"bot-tts-text\":\n if (messageData.data?.text) {\n this.emit(\"botTtsText\", { text: messageData.data.text });\n }\n break;\n\n // Bot TTS lifecycle (more granular than bot-started/stopped-speaking)\n case \"bot-tts-started\":\n this.emit(\"botTtsStarted\");\n break;\n\n case \"bot-tts-stopped\":\n this.emit(\"botTtsStopped\");\n break;\n\n // Server-side muting indicators\n case \"user-mute-started\":\n this.emit(\"userMuteStarted\");\n break;\n\n case \"user-mute-stopped\":\n this.emit(\"userMuteStopped\");\n break;\n\n case \"user-started-speaking\":\n this.isListening = true;\n this.emit(\"listeningChange\", true);\n break;\n\n case \"user-stopped-speaking\":\n this.isListening = false;\n this.emit(\"listeningChange\", false);\n break;\n\n // Bot Started Speaking (priority over listening: state becomes speaking)\n case \"bot-started-speaking\": {\n const owner = this.lifecycleOwner(messageData.data);\n if (this.blendshapeQueue.isStaleOwner(owner)) {\n break;\n }\n const allowed = this.blendshapeQueue.startBotSpeaking();\n if (allowed) {\n this.isSpeaking = true;\n this.totalBlendshapesReceived = 0;\n this.emit(\"speakingChange\", true);\n }\n break;\n }\n\n // Bot Stopped Speaking\n case \"bot-stopped-speaking\":\n if (this.blendshapeQueue.isStaleOwner(this.lifecycleOwner(messageData.data))) {\n break;\n }\n if (this.isSpeaking) {\n this.isSpeaking = false;\n this.blendshapeQueue.stopBotSpeaking();\n this.emit(\"speakingChange\", false);\n }\n break;\n\n // Action Response Messages (LiveKit/WebRTC path)\n case \"action-response\":\n this._handleActionResponse(messageData.data?.actions ?? [], messageId, timestamp);\n break;\n\n case \"metrics\":\n if (messageData.data) {\n this.emit(\"metrics\", messageData.data);\n }\n break;\n // Behavior Tree Response Messages\n case \"behavior-tree-response\":\n if (messageData.data?.narrative_section_id) {\n const behaviorMessage: ChatMessage = {\n id: messageId,\n type: \"behavior-tree\",\n content: `Narrative Section: ${messageData.data.narrative_section_id}`,\n timestamp,\n };\n this.chatMessages.push(behaviorMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n break;\n\n // Server Message - Contains various data types like blendshapes\n case \"server-message\":\n if (messageData.data) {\n const serverData = messageData.data;\n\n switch (serverData.type) {\n case \"final-user-transcription\":\n if (serverData.text) {\n const finalText = serverData.text;\n const lastUserMsg =\n this.chatMessages[this.chatMessages.length - 1];\n if (\n lastUserMsg &&\n lastUserMsg.type === \"user-transcription\" &&\n lastUserMsg.isStreaming === true\n ) {\n this.chatMessages[this.chatMessages.length - 1] = {\n ...lastUserMsg,\n content: finalText,\n timestamp,\n isStreaming: false,\n };\n } else {\n this.chatMessages.push({\n id: `${serverData.type}-${Date.now()}-${Math.random()}`,\n type: \"user-transcription\",\n content: finalText,\n timestamp,\n isStreaming: false,\n });\n }\n this.emit(\"messagesChange\", this.chatMessages);\n this.userTranscription = \"\";\n this.emit(\"userTranscriptionChange\", \"\");\n }\n break;\n\n // WebSocket path: arrives inside a bot-text data message as serverData (not messageData.data)\n case \"bot-emotion\":\n if (serverData.emotion) {\n this._currentEmotion = {\n emotion: serverData.emotion,\n scale: serverData.scale,\n };\n console.log(\"[SDK bot-emotion (ws)]\", serverData);\n this.emit(\"emotionChange\", this._currentEmotion);\n }\n break;\n\n case \"blendshape-turn-stats\":\n if (this.blendshapeQueue.isStaleOwner(this.lifecycleOwner(serverData))) {\n break;\n }\n this.blendshapeQueue.endConversation(\n serverData.stats,\n this.lifecycleOwner(serverData),\n );\n this.emit(\"blendshapeStatsReceived\", serverData);\n break;\n\n case \"chunked-neurosync-blendshapes\":\n if (serverData.blendshapes) {\n const owner = this.lifecycleOwner(serverData);\n if (this.blendshapeQueue.isRetiredOwner(owner)) {\n break;\n }\n // If the queue is idle (no active conversation, bot not yet speaking),\n // start a conversation so early chunks from an initial bot greeting\n // are accepted rather than silently dropped.\n if (\n !this.blendshapeQueue.isConversationActive() &&\n !this.isSpeaking\n ) {\n this.blendshapeQueue.startConversation();\n }\n this.blendshapeQueue.addChunk(\n serverData.blendshapes,\n owner,\n );\n if (\n this.blendshapeQueue.consumeOwnerReplacementStoppedSpeaking() &&\n this.isSpeaking\n ) {\n this.isSpeaking = false;\n this.emit(\"speakingChange\", false);\n }\n this.totalBlendshapesReceived +=\n serverData.blendshapes.length;\n this.emit(\"blendshapes\", serverData);\n }\n break;\n\n case \"neurosync-blendshapes-cancel\": {\n const cancelledActive = this.blendshapeQueue.cancelOwner(\n this.lifecycleOwner(serverData),\n );\n if (cancelledActive && this.isSpeaking) {\n this.isSpeaking = false;\n this.emit(\"speakingChange\", false);\n }\n this.emit(\"blendshapeCancel\", serverData);\n break;\n }\n\n case \"user-idle-warning\": {\n const remainingSeconds: number | null =\n serverData.remaining_seconds ??\n serverData.remainingSeconds ??\n null;\n this.emit(\"idleWarning\", { remainingSeconds });\n this.chatMessages.push({\n id: `user-idle-warning-${Date.now()}-${Math.random()}`,\n type: \"idle-warning\",\n content:\n remainingSeconds !== null ? String(remainingSeconds) : \"\",\n timestamp,\n });\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n }\n\n case \"llm-no-response\":\n this.emit(\"llmNoResponse\");\n this.chatMessages.push({\n id: `llm-no-response-${Date.now()}-${Math.random()}`,\n type: \"llm-no-response\",\n content: \"\",\n timestamp,\n });\n this.emit(\"messagesChange\", this.chatMessages);\n break;\n\n // Action Response (WebSocket/RTVI path — wrapped in server-message)\n case \"action-response\":\n this._handleActionResponse(serverData.actions ?? [], messageId, timestamp);\n break;\n\n // Server acknowledgment — arrives wrapped in server-message envelope\n case \"server-response\": {\n // client-ready is an internal RTVI handshake; server echoes an\n // \"Unknown message type\" error for it which is expected and harmless.\n if (serverData.event_type === \"client-ready\") break;\n const serverResponse: ServerResponse = {\n event_type: serverData.event_type ?? \"unknown\",\n status: serverData.status ?? \"error\",\n message: serverData.message ?? null,\n extras: serverData.extras ?? null,\n };\n this.emit(\"serverResponse\", serverResponse);\n break;\n }\n\n // interaction-created: session IDs for analytics/tracking\n case \"interaction-created\": {\n const interactionCreated: InteractionCreated = {\n interactionId: serverData.interaction_id,\n characterSessionId: serverData.character_session_id,\n };\n this.emit(\"interactionCreated\", interactionCreated);\n break;\n }\n }\n }\n break;\n\n // Fallback: server-response at top level (not currently observed but kept for safety)\n case \"server-response\": {\n if (messageData.event_type === \"client-ready\") break;\n const serverResponse: ServerResponse = {\n event_type: messageData.event_type ?? \"unknown\",\n status: messageData.status ?? \"error\",\n message: messageData.message ?? null,\n extras: messageData.extras ?? null,\n };\n this.emit(\"serverResponse\", serverResponse);\n break;\n }\n\n // Silently ignore other message types\n case \"moderation-response\":\n case \"trigger-message\":\n case \"update-template-keys\":\n case \"update-dynamic-info\":\n case \"interrupt-bot\":\n break;\n }\n } catch (error) {\n // Silently handle parse errors\n }\n }\n\n private _handleActionResponse(\n actions: ConvaiAction[],\n messageId: string,\n timestamp: string,\n ): void {\n this.emit(\"actionResponse\", { actions });\n const label = actions.length === 0\n ? \"No action\"\n : actions.map((a) => (a.target ? `${a.name} → ${a.target}` : a.name)).join(\", \");\n const actionMessage: ChatMessage = {\n id: messageId,\n type: \"action\",\n content: label,\n timestamp,\n };\n this.chatMessages.push(actionMessage);\n this.emit(\"messagesChange\", this.chatMessages);\n }\n\n private lifecycleOwner(\n data: LifecycleOwnerPayload | undefined,\n ): BlendshapeChunkMetadata {\n if (!data) {\n return {};\n }\n\n return {\n responseId: data.response_id,\n neurosyncTurnId: data.neurosync_turn_id ?? data.turn_id,\n epoch: data.epoch,\n fps: this.numberOrUndefined((data as { fps?: number }).fps),\n startFrameIndex: this.numberOrUndefined(\n (data as { start_frame_index?: number }).start_frame_index,\n ),\n };\n }\n\n private numberOrUndefined(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n }\n\n /**\n * Public entry point for WebSocket transport to inject messages into the same pipeline.\n */\n handleDataReceivedPublic(payload: Uint8Array): void {\n this.handleDataReceived(payload, null, \"websocket\");\n }\n\n /**\n * Reset message state\n */\n reset(): void {\n this.chatMessages = [];\n this.activeBotLlmMessageId = null;\n this.userTranscription = \"\";\n this.isBotResponding = false;\n this.isSpeaking = false;\n this.isListening = false;\n this.totalBlendshapesReceived = 0;\n this._currentEmotion = null;\n this.blendshapeQueue.reset();\n this.emit(\"messagesChange\", this.chatMessages);\n this.emit(\"userTranscriptionChange\", \"\");\n this.emit(\"botRespondingChange\", false);\n this.emit(\"speakingChange\", false);\n this.emit(\"listeningChange\", false);\n this.emit(\"emotionChange\", null);\n }\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ConvaiConfig } from "./types.js";
|
|
2
|
+
export interface SSESessionOptions {
|
|
3
|
+
interactionApiUrl: string;
|
|
4
|
+
authorization: string;
|
|
5
|
+
characterId: string;
|
|
6
|
+
getCharacterSessionId: () => string | null;
|
|
7
|
+
onCharacterSessionId: (characterSessionId: string) => void;
|
|
8
|
+
endUserId?: string;
|
|
9
|
+
endUserMetadata?: Record<string, unknown>;
|
|
10
|
+
takeStateOfMind: () => string | null;
|
|
11
|
+
enableEmotion?: ConvaiConfig["enableEmotion"];
|
|
12
|
+
emotionConfig?: ConvaiConfig["emotionConfig"];
|
|
13
|
+
actionConfig?: ConvaiConfig["actionConfig"];
|
|
14
|
+
debug?: boolean;
|
|
15
|
+
onMessage: (payload: Uint8Array) => void;
|
|
16
|
+
onError: (error: unknown) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface SSEMessage {
|
|
19
|
+
type: string;
|
|
20
|
+
data: unknown;
|
|
21
|
+
id?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Text-only interaction transport. One POST/SSE stream is used per message. */
|
|
24
|
+
export declare class SSESession {
|
|
25
|
+
private readonly options;
|
|
26
|
+
private static readonly BOT_LLM_TEXT_FLUSH_MS;
|
|
27
|
+
private connected;
|
|
28
|
+
private abortController;
|
|
29
|
+
private queue;
|
|
30
|
+
private pendingBotLlmText;
|
|
31
|
+
private botLlmTextFlushTimer;
|
|
32
|
+
constructor(options: SSESessionOptions);
|
|
33
|
+
get isConnected(): boolean;
|
|
34
|
+
connect(): void;
|
|
35
|
+
sendMessage(type: string, data: unknown, id?: string): void;
|
|
36
|
+
sendMessages(messages: SSEMessage[]): void;
|
|
37
|
+
disconnect(): Promise<void>;
|
|
38
|
+
private sendInteraction;
|
|
39
|
+
private readEvents;
|
|
40
|
+
private queueBotLlmText;
|
|
41
|
+
private flushBotLlmText;
|
|
42
|
+
private clearPendingBotLlmText;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=SSESession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SSESession.d.ts","sourceRoot":"","sources":["../../src/core/SSESession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM5C,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC3C,oBAAoB,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC9C,aAAa,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,gFAAgF;AAChF,qBAAa,UAAU;IAQT,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAM;IACnD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,oBAAoB,CAA8C;gBAE7C,OAAO,EAAE,iBAAiB;IAEvD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,IAAI,IAAI;IAIf,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAI3D,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAYpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAQnB,eAAe;YA4Df,UAAU;IAqExB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,sBAAsB;CAO/B"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { buildActionConnectConfig, buildEmotionConnectConfig, } from "./connectRequest.js";
|
|
2
|
+
/** Text-only interaction transport. One POST/SSE stream is used per message. */
|
|
3
|
+
export class SSESession {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.options = options;
|
|
6
|
+
this.connected = false;
|
|
7
|
+
this.abortController = null;
|
|
8
|
+
this.queue = Promise.resolve();
|
|
9
|
+
this.pendingBotLlmText = "";
|
|
10
|
+
this.botLlmTextFlushTimer = null;
|
|
11
|
+
}
|
|
12
|
+
get isConnected() {
|
|
13
|
+
return this.connected;
|
|
14
|
+
}
|
|
15
|
+
connect() {
|
|
16
|
+
this.connected = true;
|
|
17
|
+
}
|
|
18
|
+
sendMessage(type, data, id) {
|
|
19
|
+
this.sendMessages([{ type, data, ...(id !== undefined ? { id } : {}) }]);
|
|
20
|
+
}
|
|
21
|
+
sendMessages(messages) {
|
|
22
|
+
if (messages.length === 0)
|
|
23
|
+
return;
|
|
24
|
+
this.queue = this.queue
|
|
25
|
+
.then(() => {
|
|
26
|
+
if (!this.connected)
|
|
27
|
+
return;
|
|
28
|
+
return this.sendInteraction(messages, this.options.takeStateOfMind());
|
|
29
|
+
})
|
|
30
|
+
.catch((error) => {
|
|
31
|
+
if (!isAbortError(error))
|
|
32
|
+
this.options.onError(error);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async disconnect() {
|
|
36
|
+
this.connected = false;
|
|
37
|
+
this.abortController?.abort();
|
|
38
|
+
await this.queue;
|
|
39
|
+
this.clearPendingBotLlmText();
|
|
40
|
+
this.abortController = null;
|
|
41
|
+
}
|
|
42
|
+
async sendInteraction(messages, stateOfMind) {
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
this.abortController = controller;
|
|
45
|
+
try {
|
|
46
|
+
const characterSessionId = this.options.getCharacterSessionId();
|
|
47
|
+
const response = await fetch(this.options.interactionApiUrl, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${this.options.authorization}`,
|
|
51
|
+
Accept: "text/event-stream",
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
},
|
|
54
|
+
body: JSON.stringify({
|
|
55
|
+
character_id: this.options.characterId,
|
|
56
|
+
...(stateOfMind ? { state_of_mind: stateOfMind } : {}),
|
|
57
|
+
...(characterSessionId && characterSessionId !== "-1"
|
|
58
|
+
? { character_session_id: characterSessionId }
|
|
59
|
+
: {}),
|
|
60
|
+
...(this.options.endUserId
|
|
61
|
+
? { end_user_id: this.options.endUserId }
|
|
62
|
+
: {}),
|
|
63
|
+
...(this.options.endUserMetadata
|
|
64
|
+
? { end_user_metadata: this.options.endUserMetadata }
|
|
65
|
+
: {}),
|
|
66
|
+
...(buildEmotionConnectConfig(this.options) && {
|
|
67
|
+
emotion_config: buildEmotionConnectConfig(this.options),
|
|
68
|
+
}),
|
|
69
|
+
...(buildActionConnectConfig(this.options) && {
|
|
70
|
+
action_config: buildActionConnectConfig(this.options),
|
|
71
|
+
}),
|
|
72
|
+
...(this.options.debug !== undefined
|
|
73
|
+
? { debug: this.options.debug }
|
|
74
|
+
: {}),
|
|
75
|
+
messages: messages.map(({ type, data, id }) => ({
|
|
76
|
+
label: "rtvi-ai",
|
|
77
|
+
type,
|
|
78
|
+
...(id !== undefined ? { id } : {}),
|
|
79
|
+
data,
|
|
80
|
+
})),
|
|
81
|
+
}),
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
});
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
const text = await response.text();
|
|
86
|
+
throw new Error(`Interaction API HTTP ${response.status}${text ? `: ${text}` : ""}`);
|
|
87
|
+
}
|
|
88
|
+
if (!response.body)
|
|
89
|
+
throw new Error("Interaction API returned no SSE body");
|
|
90
|
+
await this.readEvents(response.body, controller.signal);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
if (this.abortController === controller)
|
|
94
|
+
this.abortController = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async readEvents(body, signal) {
|
|
98
|
+
const reader = body.getReader();
|
|
99
|
+
const decoder = new TextDecoder();
|
|
100
|
+
let buffer = "";
|
|
101
|
+
let eventType = "message";
|
|
102
|
+
let eventData = [];
|
|
103
|
+
const dispatch = () => {
|
|
104
|
+
if (eventData.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const dataText = eventData.join("\n");
|
|
107
|
+
let data = dataText;
|
|
108
|
+
try {
|
|
109
|
+
data = JSON.parse(dataText);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// SSE data is JSON for the interaction API; preserve malformed data for diagnostics.
|
|
113
|
+
}
|
|
114
|
+
if (eventType === "bot-llm-text" &&
|
|
115
|
+
typeof data === "object" &&
|
|
116
|
+
data !== null &&
|
|
117
|
+
typeof data.text === "string") {
|
|
118
|
+
this.queueBotLlmText(data.text);
|
|
119
|
+
eventType = "message";
|
|
120
|
+
eventData = [];
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.flushBotLlmText();
|
|
124
|
+
if (eventType === "session" || eventType === "done") {
|
|
125
|
+
const sessionId = data
|
|
126
|
+
?.character_session_id;
|
|
127
|
+
if (typeof sessionId === "string")
|
|
128
|
+
this.options.onCharacterSessionId(sessionId);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
if (eventType === "error")
|
|
132
|
+
this.options.onError(data);
|
|
133
|
+
this.options.onMessage(new TextEncoder().encode(JSON.stringify({ type: eventType, data })));
|
|
134
|
+
}
|
|
135
|
+
eventType = "message";
|
|
136
|
+
eventData = [];
|
|
137
|
+
};
|
|
138
|
+
while (!signal.aborted) {
|
|
139
|
+
const { done, value } = await reader.read();
|
|
140
|
+
buffer += decoder.decode(value, { stream: !done });
|
|
141
|
+
const lines = buffer.split(/\r?\n/);
|
|
142
|
+
buffer = lines.pop() ?? "";
|
|
143
|
+
for (const line of lines) {
|
|
144
|
+
if (!line)
|
|
145
|
+
dispatch();
|
|
146
|
+
else if (line.startsWith("event:"))
|
|
147
|
+
eventType = line.slice(6).trim();
|
|
148
|
+
else if (line.startsWith("data:")) {
|
|
149
|
+
eventData.push(line.slice(5).trimStart());
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (done) {
|
|
153
|
+
if (buffer) {
|
|
154
|
+
if (buffer.startsWith("event:"))
|
|
155
|
+
eventType = buffer.slice(6).trim();
|
|
156
|
+
else if (buffer.startsWith("data:"))
|
|
157
|
+
eventData.push(buffer.slice(5).trimStart());
|
|
158
|
+
}
|
|
159
|
+
dispatch();
|
|
160
|
+
this.flushBotLlmText();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
queueBotLlmText(text) {
|
|
166
|
+
this.pendingBotLlmText += text;
|
|
167
|
+
if (this.botLlmTextFlushTimer !== null)
|
|
168
|
+
return;
|
|
169
|
+
this.botLlmTextFlushTimer = setTimeout(() => {
|
|
170
|
+
this.botLlmTextFlushTimer = null;
|
|
171
|
+
this.flushBotLlmText();
|
|
172
|
+
}, SSESession.BOT_LLM_TEXT_FLUSH_MS);
|
|
173
|
+
}
|
|
174
|
+
flushBotLlmText() {
|
|
175
|
+
if (this.botLlmTextFlushTimer !== null) {
|
|
176
|
+
clearTimeout(this.botLlmTextFlushTimer);
|
|
177
|
+
this.botLlmTextFlushTimer = null;
|
|
178
|
+
}
|
|
179
|
+
if (!this.pendingBotLlmText)
|
|
180
|
+
return;
|
|
181
|
+
const text = this.pendingBotLlmText;
|
|
182
|
+
this.pendingBotLlmText = "";
|
|
183
|
+
this.options.onMessage(new TextEncoder().encode(JSON.stringify({ type: "bot-llm-text", data: { text } })));
|
|
184
|
+
}
|
|
185
|
+
clearPendingBotLlmText() {
|
|
186
|
+
if (this.botLlmTextFlushTimer !== null) {
|
|
187
|
+
clearTimeout(this.botLlmTextFlushTimer);
|
|
188
|
+
this.botLlmTextFlushTimer = null;
|
|
189
|
+
}
|
|
190
|
+
this.pendingBotLlmText = "";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
SSESession.BOT_LLM_TEXT_FLUSH_MS = 16;
|
|
194
|
+
function isAbortError(error) {
|
|
195
|
+
return (typeof error === "object" &&
|
|
196
|
+
error !== null &&
|
|
197
|
+
"name" in error &&
|
|
198
|
+
error.name === "AbortError");
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=SSESession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SSESession.js","sourceRoot":"","sources":["../../src/core/SSESession.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConvaiConfig } from \"./types\";\nimport {\n buildActionConnectConfig,\n buildEmotionConnectConfig,\n} from \"./connectRequest\";\n\nexport interface SSESessionOptions {\n interactionApiUrl: string;\n authorization: string;\n characterId: string;\n getCharacterSessionId: () => string | null;\n onCharacterSessionId: (characterSessionId: string) => void;\n endUserId?: string;\n endUserMetadata?: Record<string, unknown>;\n takeStateOfMind: () => string | null;\n enableEmotion?: ConvaiConfig[\"enableEmotion\"];\n emotionConfig?: ConvaiConfig[\"emotionConfig\"];\n actionConfig?: ConvaiConfig[\"actionConfig\"];\n debug?: boolean;\n onMessage: (payload: Uint8Array) => void;\n onError: (error: unknown) => void;\n}\n\nexport interface SSEMessage {\n type: string;\n data: unknown;\n id?: string;\n}\n\n/** Text-only interaction transport. One POST/SSE stream is used per message. */\nexport class SSESession {\n private static readonly BOT_LLM_TEXT_FLUSH_MS = 16;\n private connected = false;\n private abortController: AbortController | null = null;\n private queue: Promise<void> = Promise.resolve();\n private pendingBotLlmText = \"\";\n private botLlmTextFlushTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly options: SSESessionOptions) {}\n\n get isConnected(): boolean {\n return this.connected;\n }\n\n connect(): void {\n this.connected = true;\n }\n\n sendMessage(type: string, data: unknown, id?: string): void {\n this.sendMessages([{ type, data, ...(id !== undefined ? { id } : {}) }]);\n }\n\n sendMessages(messages: SSEMessage[]): void {\n if (messages.length === 0) return;\n this.queue = this.queue\n .then(() => {\n if (!this.connected) return;\n return this.sendInteraction(messages, this.options.takeStateOfMind());\n })\n .catch((error: unknown) => {\n if (!isAbortError(error)) this.options.onError(error);\n });\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n this.abortController?.abort();\n await this.queue;\n this.clearPendingBotLlmText();\n this.abortController = null;\n }\n\n private async sendInteraction(\n messages: SSEMessage[],\n stateOfMind: string | null,\n ): Promise<void> {\n const controller = new AbortController();\n this.abortController = controller;\n try {\n const characterSessionId = this.options.getCharacterSessionId();\n const response = await fetch(this.options.interactionApiUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.options.authorization}`,\n Accept: \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n character_id: this.options.characterId,\n ...(stateOfMind ? { state_of_mind: stateOfMind } : {}),\n ...(characterSessionId && characterSessionId !== \"-1\"\n ? { character_session_id: characterSessionId }\n : {}),\n ...(this.options.endUserId\n ? { end_user_id: this.options.endUserId }\n : {}),\n ...(this.options.endUserMetadata\n ? { end_user_metadata: this.options.endUserMetadata }\n : {}),\n ...(buildEmotionConnectConfig(this.options) && {\n emotion_config: buildEmotionConnectConfig(this.options),\n }),\n ...(buildActionConnectConfig(this.options) && {\n action_config: buildActionConnectConfig(this.options),\n }),\n ...(this.options.debug !== undefined\n ? { debug: this.options.debug }\n : {}),\n messages: messages.map(({ type, data, id }) => ({\n label: \"rtvi-ai\",\n type,\n ...(id !== undefined ? { id } : {}),\n data,\n })),\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Interaction API HTTP ${response.status}${text ? `: ${text}` : \"\"}`,\n );\n }\n if (!response.body) throw new Error(\"Interaction API returned no SSE body\");\n\n await this.readEvents(response.body, controller.signal);\n } finally {\n if (this.abortController === controller) this.abortController = null;\n }\n }\n\n private async readEvents(\n body: ReadableStream<Uint8Array>,\n signal: AbortSignal,\n ): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let eventType = \"message\";\n let eventData: string[] = [];\n\n const dispatch = () => {\n if (eventData.length === 0) return;\n const dataText = eventData.join(\"\\n\");\n let data: unknown = dataText;\n try {\n data = JSON.parse(dataText);\n } catch {\n // SSE data is JSON for the interaction API; preserve malformed data for diagnostics.\n }\n if (\n eventType === \"bot-llm-text\" &&\n typeof data === \"object\" &&\n data !== null &&\n typeof (data as { text?: unknown }).text === \"string\"\n ) {\n this.queueBotLlmText((data as { text: string }).text);\n eventType = \"message\";\n eventData = [];\n return;\n }\n this.flushBotLlmText();\n if (eventType === \"session\" || eventType === \"done\") {\n const sessionId = (data as { character_session_id?: unknown })\n ?.character_session_id;\n if (typeof sessionId === \"string\") this.options.onCharacterSessionId(sessionId);\n } else {\n if (eventType === \"error\") this.options.onError(data);\n this.options.onMessage(\n new TextEncoder().encode(JSON.stringify({ type: eventType, data })),\n );\n }\n eventType = \"message\";\n eventData = [];\n };\n\n while (!signal.aborted) {\n const { done, value } = await reader.read();\n buffer += decoder.decode(value, { stream: !done });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n if (!line) dispatch();\n else if (line.startsWith(\"event:\")) eventType = line.slice(6).trim();\n else if (line.startsWith(\"data:\")) {\n eventData.push(line.slice(5).trimStart());\n }\n }\n if (done) {\n if (buffer) {\n if (buffer.startsWith(\"event:\")) eventType = buffer.slice(6).trim();\n else if (buffer.startsWith(\"data:\")) eventData.push(buffer.slice(5).trimStart());\n }\n dispatch();\n this.flushBotLlmText();\n return;\n }\n }\n }\n\n private queueBotLlmText(text: string): void {\n this.pendingBotLlmText += text;\n if (this.botLlmTextFlushTimer !== null) return;\n this.botLlmTextFlushTimer = setTimeout(() => {\n this.botLlmTextFlushTimer = null;\n this.flushBotLlmText();\n }, SSESession.BOT_LLM_TEXT_FLUSH_MS);\n }\n\n private flushBotLlmText(): void {\n if (this.botLlmTextFlushTimer !== null) {\n clearTimeout(this.botLlmTextFlushTimer);\n this.botLlmTextFlushTimer = null;\n }\n if (!this.pendingBotLlmText) return;\n const text = this.pendingBotLlmText;\n this.pendingBotLlmText = \"\";\n this.options.onMessage(\n new TextEncoder().encode(\n JSON.stringify({ type: \"bot-llm-text\", data: { text } }),\n ),\n );\n }\n\n private clearPendingBotLlmText(): void {\n if (this.botLlmTextFlushTimer !== null) {\n clearTimeout(this.botLlmTextFlushTimer);\n this.botLlmTextFlushTimer = null;\n }\n this.pendingBotLlmText = \"\";\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n error.name === \"AbortError\"\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Room } from "livekit-client";
|
|
2
|
-
import { ScreenShareControls } from "./types";
|
|
3
|
-
import { EventEmitter } from "./EventEmitter";
|
|
2
|
+
import { ScreenShareControls } from "./types.js";
|
|
3
|
+
import { EventEmitter } from "./EventEmitter.js";
|
|
4
4
|
/**
|
|
5
5
|
* Manages screen sharing controls for LiveKit room
|
|
6
6
|
* Provides methods to enable/disable screen sharing, manage screen share state,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { logger } from "../utils/logger";
|
|
2
|
-
import { EventEmitter } from "./EventEmitter";
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
import { EventEmitter } from "./EventEmitter.js";
|
|
3
3
|
/**
|
|
4
4
|
* Manages screen sharing controls for LiveKit room
|
|
5
5
|
* Provides methods to enable/disable screen sharing, manage screen share state,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Room } from "livekit-client";
|
|
2
|
-
import { PublishCanvasOptions, PublishVideoTrackOptions, VideoControls, VisionSourceHandle, VisionSourceState } from "./types";
|
|
3
|
-
import { EventEmitter } from "./EventEmitter";
|
|
2
|
+
import { PublishCanvasOptions, PublishVideoTrackOptions, VideoControls, VisionSourceHandle, VisionSourceState } from "./types.js";
|
|
3
|
+
import { EventEmitter } from "./EventEmitter.js";
|
|
4
4
|
type WebSocketVisionMessageType = "vision-frame" | "vision-source-state";
|
|
5
5
|
type WebSocketVisionMessageSender = (type: WebSocketVisionMessageType, data: Record<string, unknown>) => void;
|
|
6
6
|
/**
|