@convai/web-sdk 0.1.0 → 0.1.1-beta.0
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 +277 -185
- package/dist/components/ConvaiWidget.d.ts.map +1 -1
- package/dist/components/ConvaiWidget.js +13 -0
- package/dist/components/ConvaiWidget.js.map +1 -1
- package/dist/components/rtc-widget/components/AudioSettingsPanel.js +1 -1
- package/dist/components/rtc-widget/components/AudioSettingsPanel.js.map +1 -1
- package/dist/components/rtc-widget/styles/styledComponents.d.ts.map +1 -1
- package/dist/components/rtc-widget/styles/styledComponents.js +72 -51
- package/dist/components/rtc-widget/styles/styledComponents.js.map +1 -1
- package/dist/core/AudioManager.d.ts +75 -0
- package/dist/core/AudioManager.d.ts.map +1 -0
- package/dist/core/AudioManager.js +219 -0
- package/dist/core/AudioManager.js.map +1 -0
- package/dist/core/ConvaiClient.d.ts +122 -0
- package/dist/core/ConvaiClient.d.ts.map +1 -0
- package/dist/core/ConvaiClient.js +509 -0
- package/dist/core/ConvaiClient.js.map +1 -0
- package/dist/core/EventEmitter.d.ts +38 -0
- package/dist/core/EventEmitter.d.ts.map +1 -0
- package/dist/core/EventEmitter.js +68 -0
- package/dist/core/EventEmitter.js.map +1 -0
- package/dist/core/MessageHandler.d.ts +52 -0
- package/dist/core/MessageHandler.d.ts.map +1 -0
- package/dist/core/MessageHandler.js +281 -0
- package/dist/core/MessageHandler.js.map +1 -0
- package/dist/core/ScreenShareManager.d.ts +57 -0
- package/dist/core/ScreenShareManager.d.ts.map +1 -0
- package/dist/core/ScreenShareManager.js +206 -0
- package/dist/core/ScreenShareManager.js.map +1 -0
- package/dist/core/VideoManager.d.ts +69 -0
- package/dist/core/VideoManager.d.ts.map +1 -0
- package/dist/core/VideoManager.js +207 -0
- package/dist/core/VideoManager.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +311 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/hooks/useConvaiClient.d.ts.map +1 -1
- package/dist/hooks/useConvaiClient.js +16 -0
- package/dist/hooks/useConvaiClient.js.map +1 -1
- package/dist/hooks/useMessageHandler.d.ts.map +1 -1
- package/dist/hooks/useMessageHandler.js +39 -14
- package/dist/hooks/useMessageHandler.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -10
- package/dist/index.js.map +1 -1
- package/dist/react/components/ConvaiWidget.d.ts +59 -0
- package/dist/react/components/ConvaiWidget.d.ts.map +1 -0
- package/dist/react/components/ConvaiWidget.js +421 -0
- package/dist/react/components/ConvaiWidget.js.map +1 -0
- package/dist/react/components/index.d.ts +3 -0
- package/dist/react/components/index.d.ts.map +1 -0
- package/dist/react/components/index.js +5 -0
- package/dist/react/components/index.js.map +1 -0
- package/dist/react/components/rtc-widget/components/AudioSettingsPanel.d.ts +10 -0
- package/dist/react/components/rtc-widget/components/AudioSettingsPanel.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/AudioSettingsPanel.js +316 -0
- package/dist/react/components/rtc-widget/components/AudioSettingsPanel.js.map +1 -0
- package/dist/react/components/rtc-widget/components/ConviMessage.d.ts +10 -0
- package/dist/react/components/rtc-widget/components/ConviMessage.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/ConviMessage.js +14 -0
- package/dist/react/components/rtc-widget/components/ConviMessage.js.map +1 -0
- package/dist/react/components/rtc-widget/components/FloatingVideo.d.ts +9 -0
- package/dist/react/components/rtc-widget/components/FloatingVideo.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/FloatingVideo.js +122 -0
- package/dist/react/components/rtc-widget/components/FloatingVideo.js.map +1 -0
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts +7 -0
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js +68 -0
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js.map +1 -0
- package/dist/react/components/rtc-widget/components/MessageBubble.d.ts +10 -0
- package/dist/react/components/rtc-widget/components/MessageBubble.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/MessageBubble.js +23 -0
- package/dist/react/components/rtc-widget/components/MessageBubble.js.map +1 -0
- package/dist/react/components/rtc-widget/components/MessageList.d.ts +11 -0
- package/dist/react/components/rtc-widget/components/MessageList.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/MessageList.js +89 -0
- package/dist/react/components/rtc-widget/components/MessageList.js.map +1 -0
- package/dist/react/components/rtc-widget/components/UserMessage.d.ts +9 -0
- package/dist/react/components/rtc-widget/components/UserMessage.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/UserMessage.js +15 -0
- package/dist/react/components/rtc-widget/components/UserMessage.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviButton.d.ts +6 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviButton.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviButton.js +15 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviButton.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviFooter.d.ts +25 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviFooter.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviFooter.js +172 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviFooter.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviHeader.d.ts +17 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviHeader.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviHeader.js +66 -0
- package/dist/react/components/rtc-widget/components/conviComponents/ConviHeader.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts +12 -0
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js +68 -0
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.d.ts +8 -0
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.js +199 -0
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.js.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/index.d.ts +6 -0
- package/dist/react/components/rtc-widget/components/conviComponents/index.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/conviComponents/index.js +6 -0
- package/dist/react/components/rtc-widget/components/conviComponents/index.js.map +1 -0
- package/dist/react/components/rtc-widget/components/index.d.ts +8 -0
- package/dist/react/components/rtc-widget/components/index.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/components/index.js +13 -0
- package/dist/react/components/rtc-widget/components/index.js.map +1 -0
- package/dist/react/components/rtc-widget/index.d.ts +6 -0
- package/dist/react/components/rtc-widget/index.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/index.js +9 -0
- package/dist/react/components/rtc-widget/index.js.map +1 -0
- package/dist/react/components/rtc-widget/styles/framerConfig.d.ts +116 -0
- package/dist/react/components/rtc-widget/styles/framerConfig.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/styles/framerConfig.js +73 -0
- package/dist/react/components/rtc-widget/styles/framerConfig.js.map +1 -0
- package/dist/react/components/rtc-widget/styles/icons.d.ts +28 -0
- package/dist/react/components/rtc-widget/styles/icons.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/styles/icons.js +257 -0
- package/dist/react/components/rtc-widget/styles/icons.js.map +1 -0
- package/dist/react/components/rtc-widget/styles/index.d.ts +6 -0
- package/dist/react/components/rtc-widget/styles/index.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/styles/index.js +9 -0
- package/dist/react/components/rtc-widget/styles/index.js.map +1 -0
- package/dist/react/components/rtc-widget/styles/styledComponents.d.ts +90 -0
- package/dist/react/components/rtc-widget/styles/styledComponents.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/styles/styledComponents.js +661 -0
- package/dist/react/components/rtc-widget/styles/styledComponents.js.map +1 -0
- package/dist/react/components/rtc-widget/styles/theme.d.ts +188 -0
- package/dist/react/components/rtc-widget/styles/theme.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/styles/theme.js +290 -0
- package/dist/react/components/rtc-widget/styles/theme.js.map +1 -0
- package/dist/react/components/rtc-widget/types/index.d.ts +60 -0
- package/dist/react/components/rtc-widget/types/index.d.ts.map +1 -0
- package/dist/react/components/rtc-widget/types/index.js +2 -0
- package/dist/react/components/rtc-widget/types/index.js.map +1 -0
- package/dist/react/hooks/index.d.ts +4 -0
- package/dist/react/hooks/index.d.ts.map +1 -0
- package/dist/react/hooks/index.js +6 -0
- package/dist/react/hooks/index.js.map +1 -0
- package/dist/react/hooks/useCharacterInfo.d.ts +17 -0
- package/dist/react/hooks/useCharacterInfo.d.ts.map +1 -0
- package/dist/react/hooks/useCharacterInfo.js +60 -0
- package/dist/react/hooks/useCharacterInfo.js.map +1 -0
- package/dist/react/hooks/useConvaiClient.d.ts +32 -0
- package/dist/react/hooks/useConvaiClient.d.ts.map +1 -0
- package/dist/react/hooks/useConvaiClient.js +140 -0
- package/dist/react/hooks/useConvaiClient.js.map +1 -0
- package/dist/react/hooks/useLocalCameraTrack.d.ts +22 -0
- package/dist/react/hooks/useLocalCameraTrack.d.ts.map +1 -0
- package/dist/react/hooks/useLocalCameraTrack.js +34 -0
- package/dist/react/hooks/useLocalCameraTrack.js.map +1 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +15 -0
- package/dist/react/index.js.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/speakerManagement.d.ts +22 -0
- package/dist/utils/speakerManagement.d.ts.map +1 -0
- package/dist/utils/speakerManagement.js +71 -0
- package/dist/utils/speakerManagement.js.map +1 -0
- package/dist/vanilla/index.d.ts +3 -0
- package/dist/vanilla/index.d.ts.map +1 -0
- package/dist/vanilla/index.js +5 -0
- package/dist/vanilla/index.js.map +1 -0
- package/package.json +22 -5
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Room } from "livekit-client";
|
|
2
|
+
import { ChatMessage } from "./types";
|
|
3
|
+
import { EventEmitter } from "./EventEmitter";
|
|
4
|
+
/**
|
|
5
|
+
* Handles incoming messages from Convai
|
|
6
|
+
* Processes various message types from the AI assistant and updates chat history
|
|
7
|
+
*/
|
|
8
|
+
export declare class MessageHandler extends EventEmitter {
|
|
9
|
+
private room;
|
|
10
|
+
private chatMessages;
|
|
11
|
+
private userTranscription;
|
|
12
|
+
private isBotResponding;
|
|
13
|
+
private isSpeaking;
|
|
14
|
+
constructor(room?: Room);
|
|
15
|
+
/**
|
|
16
|
+
* Get current chat messages
|
|
17
|
+
*/
|
|
18
|
+
getChatMessages(): ChatMessage[];
|
|
19
|
+
/**
|
|
20
|
+
* Get current user transcription
|
|
21
|
+
*/
|
|
22
|
+
getUserTranscription(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get bot responding state
|
|
25
|
+
*/
|
|
26
|
+
getIsBotResponding(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Get speaking state
|
|
29
|
+
*/
|
|
30
|
+
getIsSpeaking(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Set the LiveKit room instance
|
|
33
|
+
*/
|
|
34
|
+
setRoom(room: Room): void;
|
|
35
|
+
/**
|
|
36
|
+
* Setup message listeners
|
|
37
|
+
*/
|
|
38
|
+
private setupListeners;
|
|
39
|
+
/**
|
|
40
|
+
* Clean up message listeners
|
|
41
|
+
*/
|
|
42
|
+
private cleanupListeners;
|
|
43
|
+
/**
|
|
44
|
+
* Handle incoming data message
|
|
45
|
+
*/
|
|
46
|
+
private handleDataReceived;
|
|
47
|
+
/**
|
|
48
|
+
* Reset message state
|
|
49
|
+
*/
|
|
50
|
+
reset(): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=MessageHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/core/MessageHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAa,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;GAGG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,UAAU,CAAkB;gBAExB,IAAI,CAAC,EAAE,IAAI;IAOvB;;OAEG;IACH,eAAe,IAAI,WAAW,EAAE;IAIhC;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAI9B;;OAEG;IACH,kBAAkB,IAAI,OAAO;IAI7B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAUzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoN1B;;OAEG;IACH,KAAK,IAAI,IAAI;CAUd"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { RoomEvent } from "livekit-client";
|
|
2
|
+
import { logger } from "../utils/logger";
|
|
3
|
+
import { EventEmitter } from "./EventEmitter";
|
|
4
|
+
/**
|
|
5
|
+
* Handles incoming messages from Convai
|
|
6
|
+
* Processes various message types from the AI assistant and updates chat history
|
|
7
|
+
*/
|
|
8
|
+
export class MessageHandler extends EventEmitter {
|
|
9
|
+
constructor(room) {
|
|
10
|
+
super();
|
|
11
|
+
this.room = null;
|
|
12
|
+
this.chatMessages = [];
|
|
13
|
+
this.userTranscription = "";
|
|
14
|
+
this.isBotResponding = false;
|
|
15
|
+
this.isSpeaking = false;
|
|
16
|
+
if (room) {
|
|
17
|
+
this.setRoom(room);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get current chat messages
|
|
22
|
+
*/
|
|
23
|
+
getChatMessages() {
|
|
24
|
+
return this.chatMessages;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get current user transcription
|
|
28
|
+
*/
|
|
29
|
+
getUserTranscription() {
|
|
30
|
+
return this.userTranscription;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get bot responding state
|
|
34
|
+
*/
|
|
35
|
+
getIsBotResponding() {
|
|
36
|
+
return this.isBotResponding;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get speaking state
|
|
40
|
+
*/
|
|
41
|
+
getIsSpeaking() {
|
|
42
|
+
return this.isSpeaking;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Set the LiveKit room instance
|
|
46
|
+
*/
|
|
47
|
+
setRoom(room) {
|
|
48
|
+
// Clean up previous room listeners
|
|
49
|
+
if (this.room) {
|
|
50
|
+
this.cleanupListeners();
|
|
51
|
+
}
|
|
52
|
+
this.room = room;
|
|
53
|
+
this.setupListeners();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Setup message listeners
|
|
57
|
+
*/
|
|
58
|
+
setupListeners() {
|
|
59
|
+
if (!this.room)
|
|
60
|
+
return;
|
|
61
|
+
this.room.on(RoomEvent.DataReceived, this.handleDataReceived.bind(this));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clean up message listeners
|
|
65
|
+
*/
|
|
66
|
+
cleanupListeners() {
|
|
67
|
+
if (!this.room)
|
|
68
|
+
return;
|
|
69
|
+
this.room.off(RoomEvent.DataReceived, this.handleDataReceived.bind(this));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Handle incoming data message
|
|
73
|
+
*/
|
|
74
|
+
handleDataReceived(payload, participant) {
|
|
75
|
+
try {
|
|
76
|
+
// Decode bytes to string
|
|
77
|
+
const decoder = new TextDecoder();
|
|
78
|
+
const messageString = decoder.decode(payload);
|
|
79
|
+
// Parse JSON
|
|
80
|
+
const messageData = JSON.parse(messageString);
|
|
81
|
+
// Extract and categorize messages for chat display
|
|
82
|
+
const timestamp = new Date().toISOString();
|
|
83
|
+
const messageId = `${messageData.type}-${Date.now()}-${Math.random()}`;
|
|
84
|
+
// Handle different message types
|
|
85
|
+
switch (messageData.type) {
|
|
86
|
+
// User text messages - Skip these, only allow user-transcription
|
|
87
|
+
case "user_text_message":
|
|
88
|
+
case "user-llm-text":
|
|
89
|
+
case "text-input":
|
|
90
|
+
case "user-input":
|
|
91
|
+
case "text-message":
|
|
92
|
+
case "chat-message":
|
|
93
|
+
case "input-text":
|
|
94
|
+
case "message":
|
|
95
|
+
// Skip user text messages - only allow user-transcription
|
|
96
|
+
break;
|
|
97
|
+
// Bot Ready - Bot is ready, connection should be true
|
|
98
|
+
case "bot-ready":
|
|
99
|
+
this.emit('botReady');
|
|
100
|
+
break;
|
|
101
|
+
// Bot LLM Started - Begin streaming response
|
|
102
|
+
case "bot-llm-started":
|
|
103
|
+
this.isBotResponding = true;
|
|
104
|
+
this.emit('botRespondingChange', true);
|
|
105
|
+
// Mark any accumulated user message as final before starting bot response
|
|
106
|
+
const lastMsg = this.chatMessages[this.chatMessages.length - 1];
|
|
107
|
+
if (lastMsg && lastMsg.type === "user-transcription" && lastMsg.isFinal) {
|
|
108
|
+
this.chatMessages[this.chatMessages.length - 1] = {
|
|
109
|
+
...lastMsg,
|
|
110
|
+
isFinal: false
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// Add initial streaming message to chat
|
|
114
|
+
const streamingMessage = {
|
|
115
|
+
id: messageId,
|
|
116
|
+
type: "bot-llm-text",
|
|
117
|
+
content: "",
|
|
118
|
+
timestamp: timestamp,
|
|
119
|
+
isFinal: true,
|
|
120
|
+
};
|
|
121
|
+
this.chatMessages.push(streamingMessage);
|
|
122
|
+
this.emit('messagesChange', this.chatMessages);
|
|
123
|
+
break;
|
|
124
|
+
// Bot LLM Text Messages - Streaming chunks
|
|
125
|
+
case "bot-llm-text":
|
|
126
|
+
if (messageData.data?.text) {
|
|
127
|
+
const newChunk = messageData.data.text;
|
|
128
|
+
// Update the streaming message in chat
|
|
129
|
+
const lastMessage = this.chatMessages[this.chatMessages.length - 1];
|
|
130
|
+
if (lastMessage && lastMessage.isFinal) {
|
|
131
|
+
this.chatMessages[this.chatMessages.length - 1] = {
|
|
132
|
+
...lastMessage,
|
|
133
|
+
content: lastMessage.content + newChunk
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// If no streaming message exists yet, create one
|
|
138
|
+
const streamingMsg = {
|
|
139
|
+
id: `${messageData.type}-${Date.now()}-${Math.random()}`,
|
|
140
|
+
type: "bot-llm-text",
|
|
141
|
+
content: newChunk,
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
isFinal: true,
|
|
144
|
+
};
|
|
145
|
+
this.chatMessages.push(streamingMsg);
|
|
146
|
+
}
|
|
147
|
+
this.emit('messagesChange', this.chatMessages);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
// Bot LLM Stopped - Complete streaming response
|
|
151
|
+
case "bot-llm-stopped":
|
|
152
|
+
const lastBotMsg = this.chatMessages[this.chatMessages.length - 1];
|
|
153
|
+
if (lastBotMsg && lastBotMsg.isFinal) {
|
|
154
|
+
this.chatMessages[this.chatMessages.length - 1] = {
|
|
155
|
+
...lastBotMsg,
|
|
156
|
+
isFinal: false
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// Clear streaming state
|
|
160
|
+
this.isBotResponding = false;
|
|
161
|
+
this.emit('botRespondingChange', false);
|
|
162
|
+
this.emit('messagesChange', this.chatMessages);
|
|
163
|
+
break;
|
|
164
|
+
// User Transcription Messages
|
|
165
|
+
case "user-transcription":
|
|
166
|
+
if (messageData.data?.text) {
|
|
167
|
+
const messageContent = messageData.data.text;
|
|
168
|
+
if (messageData.data?.final) {
|
|
169
|
+
// Final transcription - accumulate in single bubble until bot responds
|
|
170
|
+
const lastUserMsg = this.chatMessages[this.chatMessages.length - 1];
|
|
171
|
+
// Check if last message is an accumulating user message (isFinal=true)
|
|
172
|
+
if (lastUserMsg &&
|
|
173
|
+
lastUserMsg.type === "user-transcription" &&
|
|
174
|
+
lastUserMsg.isFinal === true) {
|
|
175
|
+
// Accumulate: append new content to existing message with space
|
|
176
|
+
const accumulatedContent = lastUserMsg.content.trim() + " " + messageContent.trim();
|
|
177
|
+
this.chatMessages[this.chatMessages.length - 1] = {
|
|
178
|
+
...lastUserMsg,
|
|
179
|
+
content: accumulatedContent,
|
|
180
|
+
timestamp: timestamp
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Start new accumulating message (isFinal=true means "still accumulating")
|
|
185
|
+
const userMessage = {
|
|
186
|
+
id: messageId,
|
|
187
|
+
type: "user-transcription",
|
|
188
|
+
content: messageContent,
|
|
189
|
+
timestamp: timestamp,
|
|
190
|
+
isFinal: true,
|
|
191
|
+
};
|
|
192
|
+
this.chatMessages.push(userMessage);
|
|
193
|
+
}
|
|
194
|
+
this.emit('messagesChange', this.chatMessages);
|
|
195
|
+
// Clear live transcription when final
|
|
196
|
+
this.userTranscription = '';
|
|
197
|
+
this.emit('userTranscriptionChange', '');
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Non-final transcription - show in input field
|
|
201
|
+
this.userTranscription = messageContent;
|
|
202
|
+
this.emit('userTranscriptionChange', messageContent);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
// Bot Emotion Messages
|
|
207
|
+
case "bot-emotion":
|
|
208
|
+
if (messageData.data?.emotion) {
|
|
209
|
+
const emotionMessage = {
|
|
210
|
+
id: messageId,
|
|
211
|
+
type: "bot-emotion",
|
|
212
|
+
content: `${messageData.data.emotion} (scale: ${messageData.data.scale || 1})`,
|
|
213
|
+
timestamp,
|
|
214
|
+
};
|
|
215
|
+
this.chatMessages.push(emotionMessage);
|
|
216
|
+
this.emit('messagesChange', this.chatMessages);
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
// Bot Started Speaking
|
|
220
|
+
case "bot-started-speaking":
|
|
221
|
+
this.isSpeaking = true;
|
|
222
|
+
this.emit('speakingChange', true);
|
|
223
|
+
break;
|
|
224
|
+
// Bot Stopped Speaking
|
|
225
|
+
case "bot-stopped-speaking":
|
|
226
|
+
this.isSpeaking = false;
|
|
227
|
+
this.emit('speakingChange', false);
|
|
228
|
+
break;
|
|
229
|
+
// Action Response Messages
|
|
230
|
+
case "action-response":
|
|
231
|
+
if (messageData.data?.actions) {
|
|
232
|
+
const actionMessage = {
|
|
233
|
+
id: messageId,
|
|
234
|
+
type: "action",
|
|
235
|
+
content: `Actions: ${messageData.data.actions.join(", ")}`,
|
|
236
|
+
timestamp,
|
|
237
|
+
};
|
|
238
|
+
this.chatMessages.push(actionMessage);
|
|
239
|
+
this.emit('messagesChange', this.chatMessages);
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
// Behavior Tree Response Messages
|
|
243
|
+
case "behavior-tree-response":
|
|
244
|
+
if (messageData.data?.narrative_section_id) {
|
|
245
|
+
const behaviorMessage = {
|
|
246
|
+
id: messageId,
|
|
247
|
+
type: "behavior-tree",
|
|
248
|
+
content: `Narrative Section: ${messageData.data.narrative_section_id}`,
|
|
249
|
+
timestamp,
|
|
250
|
+
};
|
|
251
|
+
this.chatMessages.push(behaviorMessage);
|
|
252
|
+
this.emit('messagesChange', this.chatMessages);
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
// Silently ignore other message types
|
|
256
|
+
case "moderation-response":
|
|
257
|
+
case "trigger-message":
|
|
258
|
+
case "update-template-keys":
|
|
259
|
+
case "update-dynamic-info":
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
logger.error("Failed to parse data message:", error);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Reset message state
|
|
269
|
+
*/
|
|
270
|
+
reset() {
|
|
271
|
+
this.chatMessages = [];
|
|
272
|
+
this.userTranscription = "";
|
|
273
|
+
this.isBotResponding = false;
|
|
274
|
+
this.isSpeaking = false;
|
|
275
|
+
this.emit('messagesChange', this.chatMessages);
|
|
276
|
+
this.emit('userTranscriptionChange', '');
|
|
277
|
+
this.emit('botRespondingChange', false);
|
|
278
|
+
this.emit('speakingChange', false);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=MessageHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../src/core/MessageHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Room } from "livekit-client";
|
|
2
|
+
import { ScreenShareControls } from "./types";
|
|
3
|
+
import { EventEmitter } from "./EventEmitter";
|
|
4
|
+
/**
|
|
5
|
+
* Manages screen sharing controls for LiveKit room
|
|
6
|
+
* Provides methods to enable/disable screen sharing, manage screen share state,
|
|
7
|
+
* and handle screen sharing with audio support.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ScreenShareManager extends EventEmitter implements ScreenShareControls {
|
|
10
|
+
private room;
|
|
11
|
+
private _isScreenShareEnabled;
|
|
12
|
+
private _isScreenShareActive;
|
|
13
|
+
constructor(room?: Room);
|
|
14
|
+
get isScreenShareEnabled(): boolean;
|
|
15
|
+
get isScreenShareActive(): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Set the LiveKit room instance
|
|
18
|
+
*/
|
|
19
|
+
setRoom(room: Room): void;
|
|
20
|
+
/**
|
|
21
|
+
* Setup event listeners for room
|
|
22
|
+
*/
|
|
23
|
+
private setupListeners;
|
|
24
|
+
/**
|
|
25
|
+
* Clean up event listeners
|
|
26
|
+
*/
|
|
27
|
+
private cleanupListeners;
|
|
28
|
+
/**
|
|
29
|
+
* Update screen share state from room
|
|
30
|
+
*/
|
|
31
|
+
private updateState;
|
|
32
|
+
/**
|
|
33
|
+
* Enable screen share
|
|
34
|
+
*/
|
|
35
|
+
enableScreenShare(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Disable screen share
|
|
38
|
+
*/
|
|
39
|
+
disableScreenShare(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Toggle screen share
|
|
42
|
+
*/
|
|
43
|
+
toggleScreenShare(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Enable screen share with audio
|
|
46
|
+
*/
|
|
47
|
+
enableScreenShareWithAudio(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Get screen share tracks
|
|
50
|
+
*/
|
|
51
|
+
getScreenShareTracks(): Promise<any[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Reset state on disconnect
|
|
54
|
+
*/
|
|
55
|
+
reset(): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=ScreenShareManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScreenShareManager.d.ts","sourceRoot":"","sources":["../../src/core/ScreenShareManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,YAAa,YAAW,mBAAmB;IACjF,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,oBAAoB,CAAkB;gBAElC,IAAI,CAAC,EAAE,IAAI;IAOvB,IAAI,oBAAoB,IAAI,OAAO,CAElC;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAczB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuCtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBxC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAczC;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxC;;OAEG;IACG,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BjD;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAuB5C;;OAEG;IACH,KAAK,IAAI,IAAI;CAQd"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { logger } from "../utils/logger";
|
|
2
|
+
import { EventEmitter } from "./EventEmitter";
|
|
3
|
+
/**
|
|
4
|
+
* Manages screen sharing controls for LiveKit room
|
|
5
|
+
* Provides methods to enable/disable screen sharing, manage screen share state,
|
|
6
|
+
* and handle screen sharing with audio support.
|
|
7
|
+
*/
|
|
8
|
+
export class ScreenShareManager extends EventEmitter {
|
|
9
|
+
constructor(room) {
|
|
10
|
+
super();
|
|
11
|
+
this.room = null;
|
|
12
|
+
this._isScreenShareEnabled = false;
|
|
13
|
+
this._isScreenShareActive = false;
|
|
14
|
+
if (room) {
|
|
15
|
+
this.setRoom(room);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
get isScreenShareEnabled() {
|
|
19
|
+
return this._isScreenShareEnabled;
|
|
20
|
+
}
|
|
21
|
+
get isScreenShareActive() {
|
|
22
|
+
return this._isScreenShareActive;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Set the LiveKit room instance
|
|
26
|
+
*/
|
|
27
|
+
setRoom(room) {
|
|
28
|
+
// Clean up previous room listeners
|
|
29
|
+
if (this.room) {
|
|
30
|
+
this.cleanupListeners();
|
|
31
|
+
}
|
|
32
|
+
this.room = room;
|
|
33
|
+
if (room && room.state !== 'disconnected') {
|
|
34
|
+
this.setupListeners();
|
|
35
|
+
this.updateState();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Setup event listeners for room
|
|
40
|
+
*/
|
|
41
|
+
setupListeners() {
|
|
42
|
+
if (!this.room)
|
|
43
|
+
return;
|
|
44
|
+
const localParticipant = this.room.localParticipant;
|
|
45
|
+
const handleTrackPublished = (track) => {
|
|
46
|
+
if (track.source === 'screen_share') {
|
|
47
|
+
this._isScreenShareActive = true;
|
|
48
|
+
this.emit('screenShareStateChange', { isScreenShareActive: true });
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const handleTrackUnpublished = (track) => {
|
|
52
|
+
if (track.source === 'screen_share') {
|
|
53
|
+
this._isScreenShareActive = false;
|
|
54
|
+
this.emit('screenShareStateChange', { isScreenShareActive: false });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const handleTrackMuted = (track) => {
|
|
58
|
+
if (track.source === 'screen_share') {
|
|
59
|
+
this._isScreenShareActive = false;
|
|
60
|
+
this.emit('screenShareStateChange', { isScreenShareActive: false });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const handleTrackUnmuted = (track) => {
|
|
64
|
+
if (track.source === 'screen_share') {
|
|
65
|
+
this._isScreenShareActive = true;
|
|
66
|
+
this.emit('screenShareStateChange', { isScreenShareActive: true });
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
localParticipant.on('trackPublished', handleTrackPublished);
|
|
70
|
+
localParticipant.on('trackUnpublished', handleTrackUnpublished);
|
|
71
|
+
localParticipant.on('trackMuted', handleTrackMuted);
|
|
72
|
+
localParticipant.on('trackUnmuted', handleTrackUnmuted);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Clean up event listeners
|
|
76
|
+
*/
|
|
77
|
+
cleanupListeners() {
|
|
78
|
+
if (!this.room)
|
|
79
|
+
return;
|
|
80
|
+
// LiveKit handles cleanup automatically when participant is removed
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Update screen share state from room
|
|
84
|
+
*/
|
|
85
|
+
updateState() {
|
|
86
|
+
if (!this.room || this.room.state === 'disconnected') {
|
|
87
|
+
this._isScreenShareEnabled = false;
|
|
88
|
+
this._isScreenShareActive = false;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const localParticipant = this.room.localParticipant;
|
|
92
|
+
this._isScreenShareEnabled = localParticipant.isScreenShareEnabled;
|
|
93
|
+
this._isScreenShareActive = localParticipant.isScreenShareEnabled;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Enable screen share
|
|
97
|
+
*/
|
|
98
|
+
async enableScreenShare() {
|
|
99
|
+
if (!this.room) {
|
|
100
|
+
throw new Error('Room not initialized');
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
// Use setScreenShareEnabled with options to include current tab
|
|
104
|
+
await this.room.localParticipant.setScreenShareEnabled(true, {
|
|
105
|
+
// @ts-ignore - selfBrowserSurface is a valid Chrome option but may not be in types
|
|
106
|
+
selfBrowserSurface: "include",
|
|
107
|
+
surfaceSwitching: "include",
|
|
108
|
+
systemAudio: "include",
|
|
109
|
+
});
|
|
110
|
+
this._isScreenShareEnabled = true;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
logger.error("Failed to enable screen share:", error);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Disable screen share
|
|
119
|
+
*/
|
|
120
|
+
async disableScreenShare() {
|
|
121
|
+
if (!this.room) {
|
|
122
|
+
throw new Error('Room not initialized');
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
await this.room.localParticipant.setScreenShareEnabled(false);
|
|
126
|
+
this._isScreenShareEnabled = false;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger.error("Failed to disable screen share:", error);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Toggle screen share
|
|
135
|
+
*/
|
|
136
|
+
async toggleScreenShare() {
|
|
137
|
+
if (this._isScreenShareEnabled) {
|
|
138
|
+
await this.disableScreenShare();
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
await this.enableScreenShare();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Enable screen share with audio
|
|
146
|
+
*/
|
|
147
|
+
async enableScreenShareWithAudio() {
|
|
148
|
+
if (!this.room) {
|
|
149
|
+
throw new Error('Room not initialized');
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
// Create screen tracks with audio enabled and include current tab
|
|
153
|
+
const tracks = await this.room.localParticipant.createScreenTracks({
|
|
154
|
+
audio: true,
|
|
155
|
+
// @ts-ignore - selfBrowserSurface is a valid Chrome option but may not be in types
|
|
156
|
+
selfBrowserSurface: "include",
|
|
157
|
+
surfaceSwitching: "include",
|
|
158
|
+
systemAudio: "include",
|
|
159
|
+
});
|
|
160
|
+
// Publish each track
|
|
161
|
+
tracks.forEach((track) => {
|
|
162
|
+
this.room.localParticipant.publishTrack(track);
|
|
163
|
+
});
|
|
164
|
+
this._isScreenShareEnabled = true;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
logger.error("Failed to enable screen share with audio:", error);
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get screen share tracks
|
|
173
|
+
*/
|
|
174
|
+
async getScreenShareTracks() {
|
|
175
|
+
if (!this.room) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const localParticipant = this.room.localParticipant;
|
|
180
|
+
const screenShareTracks = [];
|
|
181
|
+
// Get all published tracks
|
|
182
|
+
localParticipant.trackPublications.forEach((publication) => {
|
|
183
|
+
if (publication.source === 'screen_share' && publication.track) {
|
|
184
|
+
screenShareTracks.push(publication.track);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
return screenShareTracks;
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
logger.error("Failed to get screen share tracks:", error);
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Reset state on disconnect
|
|
196
|
+
*/
|
|
197
|
+
reset() {
|
|
198
|
+
this._isScreenShareEnabled = false;
|
|
199
|
+
this._isScreenShareActive = false;
|
|
200
|
+
this.emit('screenShareStateChange', {
|
|
201
|
+
isScreenShareEnabled: false,
|
|
202
|
+
isScreenShareActive: false
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=ScreenShareManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScreenShareManager.js","sourceRoot":"","sources":["../../src/core/ScreenShareManager.ts"],"names":[],"mappings":"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"}
|