@convai/web-sdk 0.3.2-beta.0 → 0.3.2-beta.1
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/dist/core/BlendshapeQueue.d.ts +26 -42
- package/dist/core/BlendshapeQueue.d.ts.map +1 -1
- package/dist/core/BlendshapeQueue.js +44 -101
- package/dist/core/BlendshapeQueue.js.map +1 -1
- package/dist/core/ConvaiClient.d.ts +0 -14
- package/dist/core/ConvaiClient.d.ts.map +1 -1
- package/dist/core/ConvaiClient.js +2 -23
- package/dist/core/ConvaiClient.js.map +1 -1
- package/dist/core/MessageHandler.d.ts.map +1 -1
- package/dist/core/MessageHandler.js +1 -2
- package/dist/core/MessageHandler.js.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +6 -11
- package/dist/core/types.d.ts.map +1 -1
- package/dist/lipsync-helpers/createBlendshapeQueue.d.ts +86 -0
- package/dist/lipsync-helpers/createBlendshapeQueue.d.ts.map +1 -0
- package/dist/lipsync-helpers/createBlendshapeQueue.js +126 -0
- package/dist/lipsync-helpers/createBlendshapeQueue.js.map +1 -0
- package/dist/lipsync-helpers/declarativeMapping.d.ts +93 -0
- package/dist/lipsync-helpers/declarativeMapping.d.ts.map +1 -0
- package/dist/lipsync-helpers/declarativeMapping.js +228 -0
- package/dist/lipsync-helpers/declarativeMapping.js.map +1 -0
- package/dist/lipsync-helpers/index.d.ts +9 -4
- package/dist/lipsync-helpers/index.d.ts.map +1 -1
- package/dist/lipsync-helpers/index.js +24 -12
- package/dist/lipsync-helpers/index.js.map +1 -1
- package/dist/lipsync-helpers/mappingTypes.d.ts +64 -0
- package/dist/lipsync-helpers/mappingTypes.d.ts.map +1 -0
- package/dist/lipsync-helpers/mappingTypes.js +28 -0
- package/dist/lipsync-helpers/mappingTypes.js.map +1 -0
- package/dist/lipsync-helpers/presetMappers.d.ts +24 -0
- package/dist/lipsync-helpers/presetMappers.d.ts.map +1 -0
- package/dist/lipsync-helpers/presetMappers.js +38 -0
- package/dist/lipsync-helpers/presetMappers.js.map +1 -0
- package/dist/react/hooks/useConvaiClient.d.ts.map +1 -1
- package/dist/react/hooks/useConvaiClient.js +0 -4
- package/dist/react/hooks/useConvaiClient.js.map +1 -1
- package/dist/vanilla/ConvaiWidget.d.ts +13 -6
- package/dist/vanilla/ConvaiWidget.d.ts.map +1 -1
- package/dist/vanilla/ConvaiWidget.js +107 -70
- package/dist/vanilla/ConvaiWidget.js.map +1 -1
- package/dist/vanilla/types.d.ts +22 -2
- package/dist/vanilla/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/lipsync-helpers/arkitBlendshapeHelpers.d.ts +0 -80
- package/dist/lipsync-helpers/arkitBlendshapeHelpers.d.ts.map +0 -1
- package/dist/lipsync-helpers/arkitBlendshapeHelpers.js +0 -201
- package/dist/lipsync-helpers/arkitBlendshapeHelpers.js.map +0 -1
- package/dist/lipsync-helpers/arkitPhonemeReference.d.ts +0 -155
- package/dist/lipsync-helpers/arkitPhonemeReference.d.ts.map +0 -1
- package/dist/lipsync-helpers/arkitPhonemeReference.js +0 -362
- package/dist/lipsync-helpers/arkitPhonemeReference.js.map +0 -1
- package/dist/lipsync-helpers/neurosyncBlendshapeMapper.d.ts +0 -30
- package/dist/lipsync-helpers/neurosyncBlendshapeMapper.d.ts.map +0 -1
- package/dist/lipsync-helpers/neurosyncBlendshapeMapper.js +0 -315
- package/dist/lipsync-helpers/neurosyncBlendshapeMapper.js.map +0 -1
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { AudioRenderer } from "./AudioRenderer";
|
|
6
6
|
import { aeroTheme, injectGlobalStyles } from "./styles";
|
|
7
7
|
import { Icons } from "./icons";
|
|
8
|
+
import { ConvaiClient } from "../core/ConvaiClient";
|
|
8
9
|
/**
|
|
9
10
|
* Create a Convai chat widget in the specified container
|
|
10
11
|
*
|
|
@@ -12,12 +13,22 @@ import { Icons } from "./icons";
|
|
|
12
13
|
* @param options - Widget configuration options
|
|
13
14
|
* @returns VanillaWidget instance with destroy method
|
|
14
15
|
*
|
|
15
|
-
* @example
|
|
16
|
+
* @example Simple usage with config
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { createConvaiWidget } from '@convai/web-sdk/vanilla';
|
|
19
|
+
*
|
|
20
|
+
* const widget = createConvaiWidget(document.body, {
|
|
21
|
+
* apiKey: 'your-api-key',
|
|
22
|
+
* characterId: 'your-character-id',
|
|
23
|
+
* enableVideo: false
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Advanced usage with client instance
|
|
16
28
|
* ```typescript
|
|
17
29
|
* import { ConvaiClient, createConvaiWidget } from '@convai/web-sdk/vanilla';
|
|
18
30
|
*
|
|
19
|
-
* const client = new ConvaiClient(
|
|
20
|
-
* await client.connect({
|
|
31
|
+
* const client = new ConvaiClient({
|
|
21
32
|
* apiKey: 'your-api-key',
|
|
22
33
|
* characterId: 'your-character-id'
|
|
23
34
|
* });
|
|
@@ -28,13 +39,23 @@ import { Icons } from "./icons";
|
|
|
28
39
|
* showScreenShare: true,
|
|
29
40
|
* defaultVoiceMode: true
|
|
30
41
|
* });
|
|
31
|
-
*
|
|
32
|
-
* // Later, cleanup
|
|
33
|
-
* widget.destroy();
|
|
34
42
|
* ```
|
|
35
43
|
*/
|
|
36
44
|
export function createConvaiWidget(container, options) {
|
|
37
|
-
|
|
45
|
+
// Create client if not provided - guarantee it's defined
|
|
46
|
+
const client = options.convaiClient || (() => {
|
|
47
|
+
if (!options.apiKey || !options.characterId) {
|
|
48
|
+
throw new Error('Either convaiClient or (apiKey + characterId) must be provided');
|
|
49
|
+
}
|
|
50
|
+
return new ConvaiClient({
|
|
51
|
+
apiKey: options.apiKey,
|
|
52
|
+
characterId: options.characterId,
|
|
53
|
+
enableVideo: options.enableVideo ?? false,
|
|
54
|
+
startWithVideoOn: options.startWithVideoOn ?? false,
|
|
55
|
+
enableLipsync: options.enableLipsync ?? false,
|
|
56
|
+
});
|
|
57
|
+
})();
|
|
58
|
+
const { showVideo = true, showScreenShare = true, defaultVoiceMode = true, onConnect, onDisconnect, onMessage } = options;
|
|
38
59
|
// Inject global styles
|
|
39
60
|
injectGlobalStyles();
|
|
40
61
|
// State
|
|
@@ -69,16 +90,16 @@ export function createConvaiWidget(container, options) {
|
|
|
69
90
|
let source = null;
|
|
70
91
|
// Fetch character info - matches React useCharacterInfo hook
|
|
71
92
|
const fetchCharacterInfo = async () => {
|
|
72
|
-
if (!
|
|
93
|
+
if (!client.apiKey || !client.characterId)
|
|
73
94
|
return;
|
|
74
95
|
try {
|
|
75
96
|
const response = await fetch("https://api.convai.com/character/get", {
|
|
76
97
|
method: "POST",
|
|
77
98
|
headers: {
|
|
78
99
|
"Content-Type": "application/json",
|
|
79
|
-
"CONVAI-API-KEY":
|
|
100
|
+
"CONVAI-API-KEY": client.apiKey,
|
|
80
101
|
},
|
|
81
|
-
body: JSON.stringify({ charID:
|
|
102
|
+
body: JSON.stringify({ charID: client.characterId }),
|
|
82
103
|
});
|
|
83
104
|
if (response.ok) {
|
|
84
105
|
const data = await response.json();
|
|
@@ -261,8 +282,8 @@ export function createConvaiWidget(container, options) {
|
|
|
261
282
|
if (!voiceModeOverlay)
|
|
262
283
|
return;
|
|
263
284
|
const bars = voiceModeOverlay.querySelectorAll(".voice-bar");
|
|
264
|
-
const isTalking =
|
|
265
|
-
const isListening = !
|
|
285
|
+
const isTalking = client.state.isSpeaking;
|
|
286
|
+
const isListening = !client.audioControls.isAudioMuted;
|
|
266
287
|
const isAnimating = isListening || isTalking;
|
|
267
288
|
// Update colors based on state
|
|
268
289
|
bars.forEach((bar) => {
|
|
@@ -576,8 +597,8 @@ export function createConvaiWidget(container, options) {
|
|
|
576
597
|
border: none;
|
|
577
598
|
`;
|
|
578
599
|
voiceExitButton.addEventListener("click", async () => {
|
|
579
|
-
|
|
580
|
-
await
|
|
600
|
+
client.sendInterruptMessage();
|
|
601
|
+
await client.audioControls.muteAudio(); // Mute on exit
|
|
581
602
|
isVoiceMode = false;
|
|
582
603
|
updateVoiceMode();
|
|
583
604
|
});
|
|
@@ -647,8 +668,8 @@ export function createConvaiWidget(container, options) {
|
|
|
647
668
|
}
|
|
648
669
|
else {
|
|
649
670
|
// Toggle Voice Mode
|
|
650
|
-
|
|
651
|
-
await
|
|
671
|
+
client.sendInterruptMessage();
|
|
672
|
+
await client.audioControls.unmuteAudio(); // Unmute on enter
|
|
652
673
|
isVoiceMode = true;
|
|
653
674
|
updateVoiceMode();
|
|
654
675
|
}
|
|
@@ -761,8 +782,9 @@ export function createConvaiWidget(container, options) {
|
|
|
761
782
|
resetIcon.style.width = "18px";
|
|
762
783
|
resetIcon.style.height = "18px";
|
|
763
784
|
settingsRow.appendChild(createOption(resetIcon, "Reset", handleReset));
|
|
764
|
-
// Video
|
|
765
|
-
|
|
785
|
+
// Video - only show if connection type is video
|
|
786
|
+
const connectionType = client.connectionType;
|
|
787
|
+
if (connectionType === "video" && showVideo) {
|
|
766
788
|
const videoIcon = isVideoVisible
|
|
767
789
|
? Icons.Video("md")
|
|
768
790
|
: Icons.VideoOff("md");
|
|
@@ -772,9 +794,9 @@ export function createConvaiWidget(container, options) {
|
|
|
772
794
|
videoBtn.id = "convai-settings-video-btn";
|
|
773
795
|
settingsRow.appendChild(videoBtn);
|
|
774
796
|
}
|
|
775
|
-
// Screen Share
|
|
776
|
-
if (
|
|
777
|
-
const isSharing =
|
|
797
|
+
// Screen Share - only show if connection type is video
|
|
798
|
+
if (connectionType === "video" && showScreenShare) {
|
|
799
|
+
const isSharing = client.screenShareControls.isScreenShareActive;
|
|
778
800
|
const shareIcon = isSharing
|
|
779
801
|
? Icons.StopScreenShare("md")
|
|
780
802
|
: Icons.ScreenShare("md");
|
|
@@ -859,7 +881,8 @@ export function createConvaiWidget(container, options) {
|
|
|
859
881
|
resetIcon.style.height = "18px";
|
|
860
882
|
settingsRow.appendChild(createOption(resetIcon, "Reset", handleReset));
|
|
861
883
|
// Video - Always show if showVideo is true and connection type is video
|
|
862
|
-
|
|
884
|
+
const connectionType = client.connectionType;
|
|
885
|
+
if (connectionType === "video" && showVideo) {
|
|
863
886
|
const videoIcon = isVideoVisible
|
|
864
887
|
? Icons.Video("md")
|
|
865
888
|
: Icons.VideoOff("md");
|
|
@@ -870,8 +893,8 @@ export function createConvaiWidget(container, options) {
|
|
|
870
893
|
settingsRow.appendChild(videoBtn);
|
|
871
894
|
}
|
|
872
895
|
// Screen Share - Always show if showScreenShare is true and connection type is video
|
|
873
|
-
if (
|
|
874
|
-
const isSharing =
|
|
896
|
+
if (connectionType === "video" && showScreenShare) {
|
|
897
|
+
const isSharing = client.screenShareControls.isScreenShareActive;
|
|
875
898
|
const shareIcon = isSharing
|
|
876
899
|
? Icons.StopScreenShare("md")
|
|
877
900
|
: Icons.ScreenShare("md");
|
|
@@ -957,7 +980,7 @@ export function createConvaiWidget(container, options) {
|
|
|
957
980
|
`;
|
|
958
981
|
closeButton.addEventListener("click", (e) => {
|
|
959
982
|
e.stopPropagation();
|
|
960
|
-
|
|
983
|
+
client.videoControls.disableVideo();
|
|
961
984
|
});
|
|
962
985
|
closeButton.addEventListener("mouseenter", () => {
|
|
963
986
|
closeButton.style.transform = "scale(1.1)";
|
|
@@ -1077,9 +1100,9 @@ export function createConvaiWidget(container, options) {
|
|
|
1077
1100
|
return;
|
|
1078
1101
|
}
|
|
1079
1102
|
// Connect on first click if not already connected/connecting
|
|
1080
|
-
if (!
|
|
1103
|
+
if (!client.state.isConnected && !client.state.isConnecting) {
|
|
1081
1104
|
try {
|
|
1082
|
-
await
|
|
1105
|
+
await client.connect();
|
|
1083
1106
|
setIsOpen(true);
|
|
1084
1107
|
}
|
|
1085
1108
|
catch (error) {
|
|
@@ -1095,8 +1118,8 @@ export function createConvaiWidget(container, options) {
|
|
|
1095
1118
|
setIsOpen(false);
|
|
1096
1119
|
};
|
|
1097
1120
|
const handleSend = () => {
|
|
1098
|
-
if (inputValue.trim() &&
|
|
1099
|
-
|
|
1121
|
+
if (inputValue.trim() && client.state.isConnected) {
|
|
1122
|
+
client.sendUserTextMessage(inputValue);
|
|
1100
1123
|
inputValue = "";
|
|
1101
1124
|
inputElement.value = "";
|
|
1102
1125
|
updateSendButton();
|
|
@@ -1105,8 +1128,8 @@ export function createConvaiWidget(container, options) {
|
|
|
1105
1128
|
// Microphone toggle removed - only controlled via voice mode now
|
|
1106
1129
|
const handleToggleMute = () => {
|
|
1107
1130
|
isMuted = !isMuted;
|
|
1108
|
-
if (
|
|
1109
|
-
const remoteParticipants = Array.from(
|
|
1131
|
+
if (client.room) {
|
|
1132
|
+
const remoteParticipants = Array.from(client.room.remoteParticipants.values());
|
|
1110
1133
|
remoteParticipants.forEach((participant) => {
|
|
1111
1134
|
participant.audioTrackPublications.forEach((publication) => {
|
|
1112
1135
|
if (publication.track) {
|
|
@@ -1120,8 +1143,8 @@ export function createConvaiWidget(container, options) {
|
|
|
1120
1143
|
const handleReset = async () => {
|
|
1121
1144
|
setIsSettingsOpen(false);
|
|
1122
1145
|
try {
|
|
1123
|
-
await
|
|
1124
|
-
|
|
1146
|
+
await client.disconnect();
|
|
1147
|
+
client.resetSession();
|
|
1125
1148
|
isMuted = false;
|
|
1126
1149
|
isVoiceMode = false;
|
|
1127
1150
|
hasEnteredDefaultVoiceMode = false;
|
|
@@ -1135,7 +1158,7 @@ export function createConvaiWidget(container, options) {
|
|
|
1135
1158
|
};
|
|
1136
1159
|
const handleDisconnect = async () => {
|
|
1137
1160
|
setIsSettingsOpen(false);
|
|
1138
|
-
await
|
|
1161
|
+
await client.disconnect();
|
|
1139
1162
|
isMuted = false;
|
|
1140
1163
|
isVoiceMode = false;
|
|
1141
1164
|
hasEnteredDefaultVoiceMode = false;
|
|
@@ -1144,14 +1167,14 @@ export function createConvaiWidget(container, options) {
|
|
|
1144
1167
|
updateSendButton();
|
|
1145
1168
|
};
|
|
1146
1169
|
const handleToggleVideo = async () => {
|
|
1147
|
-
if (
|
|
1170
|
+
if (client.connectionType !== "video")
|
|
1148
1171
|
return;
|
|
1149
1172
|
try {
|
|
1150
1173
|
if (isVideoVisible) {
|
|
1151
|
-
await
|
|
1174
|
+
await client.videoControls.disableVideo();
|
|
1152
1175
|
}
|
|
1153
1176
|
else {
|
|
1154
|
-
await
|
|
1177
|
+
await client.videoControls.enableVideo();
|
|
1155
1178
|
}
|
|
1156
1179
|
// State will be updated via event listener below
|
|
1157
1180
|
}
|
|
@@ -1161,7 +1184,7 @@ export function createConvaiWidget(container, options) {
|
|
|
1161
1184
|
};
|
|
1162
1185
|
const handleToggleScreenShare = async () => {
|
|
1163
1186
|
try {
|
|
1164
|
-
await
|
|
1187
|
+
await client.screenShareControls.toggleScreenShare();
|
|
1165
1188
|
// State will be updated via event listener above
|
|
1166
1189
|
}
|
|
1167
1190
|
catch (e) {
|
|
@@ -1190,10 +1213,10 @@ export function createConvaiWidget(container, options) {
|
|
|
1190
1213
|
chatContent.style.transform = "scale(1)";
|
|
1191
1214
|
chatContent.style.pointerEvents = "auto";
|
|
1192
1215
|
// Auto-enter voice mode if defaultVoiceMode is true and not already entered
|
|
1193
|
-
if (defaultVoiceMode && !hasEnteredDefaultVoiceMode &&
|
|
1216
|
+
if (defaultVoiceMode && !hasEnteredDefaultVoiceMode && client.state.isConnected) {
|
|
1194
1217
|
setTimeout(async () => {
|
|
1195
1218
|
try {
|
|
1196
|
-
await
|
|
1219
|
+
await client.audioControls.unmuteAudio();
|
|
1197
1220
|
isVoiceMode = true;
|
|
1198
1221
|
hasEnteredDefaultVoiceMode = true;
|
|
1199
1222
|
updateVoiceMode();
|
|
@@ -1246,15 +1269,15 @@ export function createConvaiWidget(container, options) {
|
|
|
1246
1269
|
};
|
|
1247
1270
|
const updateVideoTrack = () => {
|
|
1248
1271
|
if (!floatingVideo ||
|
|
1249
|
-
!
|
|
1250
|
-
!
|
|
1272
|
+
!client.room ||
|
|
1273
|
+
!client.room.localParticipant)
|
|
1251
1274
|
return;
|
|
1252
1275
|
const videoEl = floatingVideo.querySelector("#floating-video-element");
|
|
1253
1276
|
const placeholder = floatingVideo.querySelector("#camera-off-placeholder");
|
|
1254
1277
|
if (!videoEl || !placeholder)
|
|
1255
1278
|
return;
|
|
1256
1279
|
if (isVideoVisible && !isVoiceMode) {
|
|
1257
|
-
const tracks = Array.from(
|
|
1280
|
+
const tracks = Array.from(client.room.localParticipant.videoTrackPublications.values());
|
|
1258
1281
|
const videoPub = tracks.find((t) => t.kind === "video");
|
|
1259
1282
|
if (videoPub && videoPub.track) {
|
|
1260
1283
|
videoPub.track.attach(videoEl);
|
|
@@ -1300,8 +1323,8 @@ export function createConvaiWidget(container, options) {
|
|
|
1300
1323
|
}
|
|
1301
1324
|
else {
|
|
1302
1325
|
// Ensure microphone is muted when not in voice mode
|
|
1303
|
-
if (!
|
|
1304
|
-
await
|
|
1326
|
+
if (!client.audioControls.isAudioMuted) {
|
|
1327
|
+
await client.audioControls.muteAudio();
|
|
1305
1328
|
}
|
|
1306
1329
|
// Hide Overlay
|
|
1307
1330
|
if (voiceModeOverlay)
|
|
@@ -1571,16 +1594,16 @@ export function createConvaiWidget(container, options) {
|
|
|
1571
1594
|
messageListElement.scrollTop = messageListElement.scrollHeight;
|
|
1572
1595
|
};
|
|
1573
1596
|
const getBotStatusColor = () => {
|
|
1574
|
-
if (!
|
|
1597
|
+
if (!client.state.isConnected) {
|
|
1575
1598
|
return { color: "#ef4444", label: "Disconnected" };
|
|
1576
1599
|
}
|
|
1577
|
-
if (
|
|
1600
|
+
if (client.state.isConnecting || !client.isBotReady) {
|
|
1578
1601
|
return { color: "#f59e0b", label: "Connecting" };
|
|
1579
1602
|
}
|
|
1580
1603
|
return { color: "#10b981", label: "Connected" };
|
|
1581
1604
|
};
|
|
1582
1605
|
const formatMessages = () => {
|
|
1583
|
-
const filteredMessages =
|
|
1606
|
+
const filteredMessages = client.chatMessages.filter((msg) => (msg.type === "user-transcription" ||
|
|
1584
1607
|
msg.type === "user-llm-text" ||
|
|
1585
1608
|
msg.type === "bot-llm-text" ||
|
|
1586
1609
|
msg.type === "bot-emotion") &&
|
|
@@ -1600,10 +1623,10 @@ export function createConvaiWidget(container, options) {
|
|
|
1600
1623
|
};
|
|
1601
1624
|
// Setup event listeners for client state changes
|
|
1602
1625
|
const setupClientListeners = () => {
|
|
1603
|
-
|
|
1626
|
+
client.on("stateChange", () => {
|
|
1604
1627
|
updateHeader();
|
|
1605
1628
|
// Update pulse animation based on connecting state
|
|
1606
|
-
if (
|
|
1629
|
+
if (client.state.isConnecting) {
|
|
1607
1630
|
morphingContainer.style.animation =
|
|
1608
1631
|
"convai-pulse 2s ease-in-out infinite";
|
|
1609
1632
|
}
|
|
@@ -1611,21 +1634,21 @@ export function createConvaiWidget(container, options) {
|
|
|
1611
1634
|
morphingContainer.style.animation = "none";
|
|
1612
1635
|
}
|
|
1613
1636
|
// Update speaking animation state
|
|
1614
|
-
if (
|
|
1637
|
+
if (client.state.isSpeaking) {
|
|
1615
1638
|
if (!startTime) {
|
|
1616
1639
|
startTime = Date.now();
|
|
1617
1640
|
}
|
|
1618
1641
|
}
|
|
1619
1642
|
else {
|
|
1620
1643
|
// Reset when not speaking
|
|
1621
|
-
if (startTime && !
|
|
1644
|
+
if (startTime && !client.state.isSpeaking) {
|
|
1622
1645
|
startTime = 0;
|
|
1623
1646
|
currentLevels = Array(40).fill(0.05);
|
|
1624
1647
|
targetLevels = Array(40).fill(0.05);
|
|
1625
1648
|
}
|
|
1626
1649
|
}
|
|
1627
1650
|
// Auto-collapse when disconnected
|
|
1628
|
-
if (!
|
|
1651
|
+
if (!client.state.isConnected && !client.state.isConnecting) {
|
|
1629
1652
|
if (isOpen) {
|
|
1630
1653
|
setIsOpen(false);
|
|
1631
1654
|
}
|
|
@@ -1637,14 +1660,14 @@ export function createConvaiWidget(container, options) {
|
|
|
1637
1660
|
updateVoiceMode();
|
|
1638
1661
|
}
|
|
1639
1662
|
// Auto-enter voice mode on first connection if defaultVoiceMode is true
|
|
1640
|
-
if (
|
|
1663
|
+
if (client.state.isConnected &&
|
|
1641
1664
|
defaultVoiceMode &&
|
|
1642
1665
|
isOpen &&
|
|
1643
1666
|
!hasEnteredDefaultVoiceMode &&
|
|
1644
1667
|
!isVoiceMode) {
|
|
1645
1668
|
setTimeout(async () => {
|
|
1646
1669
|
try {
|
|
1647
|
-
await
|
|
1670
|
+
await client.audioControls.unmuteAudio();
|
|
1648
1671
|
isVoiceMode = true;
|
|
1649
1672
|
hasEnteredDefaultVoiceMode = true;
|
|
1650
1673
|
updateVoiceMode();
|
|
@@ -1657,7 +1680,7 @@ export function createConvaiWidget(container, options) {
|
|
|
1657
1680
|
});
|
|
1658
1681
|
// Audio state changes now only affect voice mode (microphone button removed)
|
|
1659
1682
|
// Video state change listener
|
|
1660
|
-
|
|
1683
|
+
client.videoControls.on("videoStateChange", (videoState) => {
|
|
1661
1684
|
if (videoState.isVideoEnabled !== undefined) {
|
|
1662
1685
|
isVideoVisible = videoState.isVideoEnabled;
|
|
1663
1686
|
updateVoiceMode();
|
|
@@ -1684,7 +1707,7 @@ export function createConvaiWidget(container, options) {
|
|
|
1684
1707
|
}
|
|
1685
1708
|
});
|
|
1686
1709
|
// Screen share state change listener
|
|
1687
|
-
|
|
1710
|
+
client.screenShareControls.on("screenShareStateChange", (screenShareState) => {
|
|
1688
1711
|
if (screenShareState.isScreenShareActive !== undefined) {
|
|
1689
1712
|
const isSharing = screenShareState.isScreenShareActive;
|
|
1690
1713
|
const shareBtn = document.getElementById("convai-settings-share-btn");
|
|
@@ -1710,28 +1733,41 @@ export function createConvaiWidget(container, options) {
|
|
|
1710
1733
|
}
|
|
1711
1734
|
}
|
|
1712
1735
|
});
|
|
1713
|
-
|
|
1736
|
+
client.on("messagesChange", () => {
|
|
1714
1737
|
updateMessageList();
|
|
1738
|
+
// Call onMessage callback if provided
|
|
1739
|
+
if (onMessage && client.chatMessages.length > 0) {
|
|
1740
|
+
const lastMessage = client.chatMessages[client.chatMessages.length - 1];
|
|
1741
|
+
onMessage(lastMessage);
|
|
1742
|
+
}
|
|
1715
1743
|
});
|
|
1716
1744
|
// Bot ready listener - updates UI when bot becomes ready
|
|
1717
|
-
|
|
1745
|
+
client.on("botReady", () => {
|
|
1718
1746
|
updateHeader(); // Update header to show green status
|
|
1719
1747
|
});
|
|
1720
|
-
|
|
1748
|
+
client.on("connect", () => {
|
|
1721
1749
|
// Initialize audio renderer on connection
|
|
1722
|
-
if (
|
|
1723
|
-
audioRenderer = new AudioRenderer(
|
|
1750
|
+
if (client.room && !audioRenderer) {
|
|
1751
|
+
audioRenderer = new AudioRenderer(client.room);
|
|
1724
1752
|
}
|
|
1725
1753
|
// Fetch character info
|
|
1726
1754
|
fetchCharacterInfo();
|
|
1755
|
+
// Call onConnect callback if provided
|
|
1756
|
+
if (onConnect) {
|
|
1757
|
+
onConnect();
|
|
1758
|
+
}
|
|
1727
1759
|
});
|
|
1728
|
-
|
|
1760
|
+
client.on("disconnect", () => {
|
|
1729
1761
|
// Cleanup audio renderer
|
|
1730
1762
|
if (audioRenderer) {
|
|
1731
1763
|
audioRenderer.destroy();
|
|
1732
1764
|
audioRenderer = null;
|
|
1733
1765
|
}
|
|
1734
1766
|
updateMessageList();
|
|
1767
|
+
// Call onDisconnect callback if provided
|
|
1768
|
+
if (onDisconnect) {
|
|
1769
|
+
onDisconnect();
|
|
1770
|
+
}
|
|
1735
1771
|
});
|
|
1736
1772
|
};
|
|
1737
1773
|
// Initialize
|
|
@@ -1744,13 +1780,14 @@ export function createConvaiWidget(container, options) {
|
|
|
1744
1780
|
updateVoiceMode();
|
|
1745
1781
|
}
|
|
1746
1782
|
// If already connected, initialize audio renderer and fetch character info
|
|
1747
|
-
if (
|
|
1748
|
-
audioRenderer = new AudioRenderer(
|
|
1783
|
+
if (client.state.isConnected && client.room) {
|
|
1784
|
+
audioRenderer = new AudioRenderer(client.room);
|
|
1749
1785
|
fetchCharacterInfo();
|
|
1750
1786
|
}
|
|
1751
1787
|
// Return widget instance
|
|
1752
1788
|
const widget = {
|
|
1753
1789
|
element: rootElement,
|
|
1790
|
+
client: client,
|
|
1754
1791
|
destroy: () => {
|
|
1755
1792
|
// Cleanup audio renderer
|
|
1756
1793
|
if (audioRenderer) {
|
|
@@ -1767,11 +1804,11 @@ export function createConvaiWidget(container, options) {
|
|
|
1767
1804
|
floatingVideo.remove();
|
|
1768
1805
|
}
|
|
1769
1806
|
// Unsubscribe from client events
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1807
|
+
client.off("stateChange", () => { });
|
|
1808
|
+
client.off("messagesChange", () => { });
|
|
1809
|
+
client.off("botReady", () => { });
|
|
1810
|
+
client.off("connect", () => { });
|
|
1811
|
+
client.off("disconnect", () => { });
|
|
1775
1812
|
},
|
|
1776
1813
|
};
|
|
1777
1814
|
return widget;
|