@unith-ai/core-client 1.3.0 → 1.5.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 +46 -259
- package/dist/index.d.ts +7 -9
- package/dist/index.d.ts.map +1 -0
- package/dist/lib.js +2 -0
- package/dist/lib.js.map +1 -0
- package/dist/lib.module.js +1 -1
- package/dist/lib.module.js.map +1 -1
- package/dist/lib.umd.js +1 -1
- package/dist/lib.umd.js.map +1 -1
- package/dist/modules/audio.d.ts +1 -0
- package/dist/modules/audio.d.ts.map +1 -0
- package/dist/modules/av.d.ts +1 -0
- package/dist/modules/av.d.ts.map +1 -0
- package/dist/modules/connection.d.ts +1 -0
- package/dist/modules/connection.d.ts.map +1 -0
- package/dist/modules/environment.d.ts +1 -0
- package/dist/modules/environment.d.ts.map +1 -0
- package/dist/modules/event.d.ts +1 -0
- package/dist/modules/event.d.ts.map +1 -0
- package/dist/modules/idle-video.d.ts +1 -0
- package/dist/modules/idle-video.d.ts.map +1 -0
- package/dist/modules/monitor.d.ts +1 -0
- package/dist/modules/monitor.d.ts.map +1 -0
- package/dist/modules/sync.d.ts +1 -0
- package/dist/modules/sync.d.ts.map +1 -0
- package/dist/modules/user.d.ts +1 -0
- package/dist/modules/user.d.ts.map +1 -0
- package/dist/modules/video.d.ts +1 -0
- package/dist/modules/video.d.ts.map +1 -0
- package/dist/modules/vp8.d.ts +1 -0
- package/dist/modules/vp8.d.ts.map +1 -0
- package/dist/types/Conversation.d.ts +11 -16
- package/dist/types/Conversation.d.ts.map +1 -0
- package/dist/types/User.d.ts +7 -0
- package/dist/types/User.d.ts.map +1 -0
- package/dist/types/audio.d.ts +17 -0
- package/dist/types/audio.d.ts.map +1 -0
- package/dist/types/chat.d.ts +29 -0
- package/dist/types/chat.d.ts.map +1 -0
- package/dist/types/connection.d.ts +2 -4
- package/dist/types/connection.d.ts.map +1 -0
- package/dist/types/environment.d.ts +1 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/event.d.ts +8 -1
- package/dist/types/event.d.ts.map +1 -0
- package/dist/types/idle-video.d.ts +8 -0
- package/dist/types/idle-video.d.ts.map +1 -0
- package/dist/types/sync.d.ts +24 -0
- package/dist/types/sync.d.ts.map +1 -0
- package/dist/types/vp8.d.ts +1 -0
- package/dist/types/vp8.d.ts.map +1 -0
- package/dist/utils/audio.d.ts +1 -0
- package/dist/utils/audio.d.ts.map +1 -0
- package/dist/utils/microphone.d.ts +8 -0
- package/dist/utils/microphone.d.ts.map +1 -0
- package/dist/utils/storage.d.ts +1 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/sync.d.ts +1 -0
- package/dist/utils/sync.d.ts.map +1 -0
- package/dist/utils/worklet-loader.d.ts +1 -0
- package/dist/utils/worklet-loader.d.ts.map +1 -0
- package/package.json +19 -8
- package/dist/lib.cjs +0 -2
- package/dist/lib.cjs.map +0 -1
- package/dist/lib.modern.js +0 -2
- package/dist/lib.modern.js.map +0 -1
- package/eslint.config.cjs +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Unith Core Client Typescript SDK
|
|
2
2
|
|
|
3
|
-
An SDK library for building complex digital human experiences using javascript/typescript.
|
|
3
|
+
An SDK library for building complex digital human experiences using javascript/typescript that run on [Unith AI](https://www.unith.ai/).
|
|
4
|
+
|
|
5
|
+
## Prerequisite
|
|
6
|
+
|
|
7
|
+
Before proceeding with using this library, you're expected to have an account on [Unith AI](https://www.unith.ai/), create a digital human and take note of your API key. You can create an account [here](https://app.unith.ai/) in minutes!
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
Install the package in your project through package manager.
|
|
12
|
+
|
|
8
13
|
```shell
|
|
9
14
|
npm install @unith-ai/core-client
|
|
10
15
|
# or
|
|
@@ -20,33 +25,25 @@ This library is designed for use in plain JavaScript applications or to serve as
|
|
|
20
25
|
### Initialize Digital Human
|
|
21
26
|
|
|
22
27
|
First, initialize the Conversation instance:
|
|
28
|
+
|
|
23
29
|
```js
|
|
24
30
|
const conversation = await Conversation.startDigitalHuman(options);
|
|
25
31
|
```
|
|
26
32
|
|
|
27
|
-
This will establish a WebSocket connection and initialize the digital human
|
|
33
|
+
This will establish a WebSocket connection and initialize the digital human with realtime audio & video streaming capabilities.
|
|
28
34
|
|
|
29
35
|
#### Session Configuration
|
|
30
36
|
|
|
31
37
|
The options passed to `startDigitalHuman` specify how the session is established:
|
|
38
|
+
|
|
32
39
|
```js
|
|
33
40
|
const conversation = await Conversation.startDigitalHuman({
|
|
34
41
|
orgId: "your-org-id",
|
|
35
42
|
headId: "your-head-id",
|
|
36
|
-
username: "anonymous",
|
|
37
|
-
password: "Password1",
|
|
38
|
-
environment: "production", // or "development"
|
|
39
43
|
element: document.getElementById("video-container"), // HTML element for video output
|
|
40
44
|
apiKey: "your-api-key",
|
|
41
|
-
mode: "default",
|
|
42
|
-
frameRate: 30,
|
|
43
|
-
streamType: "jpg", // or "vp8"
|
|
44
|
-
quality: "high",
|
|
45
|
-
crop: false,
|
|
46
|
-
showIdle: false,
|
|
47
|
-
language: "en",
|
|
48
45
|
allowWakeLock: true,
|
|
49
|
-
|
|
46
|
+
...callbacks,
|
|
50
47
|
});
|
|
51
48
|
```
|
|
52
49
|
|
|
@@ -54,106 +51,52 @@ const conversation = await Conversation.startDigitalHuman({
|
|
|
54
51
|
|
|
55
52
|
- **orgId** - Your organization ID
|
|
56
53
|
- **headId** - The digital human head ID to use
|
|
54
|
+
- **apiKey** - API key for authentication (default: "")
|
|
57
55
|
- **element** - HTML element where the video will be rendered
|
|
58
|
-
- **username** - Authentication username (default: "anonymous")
|
|
59
|
-
- **password** - Authentication password (default: "Password1")
|
|
60
56
|
|
|
61
57
|
#### Optional Parameters
|
|
62
58
|
|
|
63
|
-
- **environment** - API environment ("production" or "development", default: "production")
|
|
64
|
-
- **apiKey** - API key for authentication (default: "")
|
|
65
59
|
- **mode** - Conversation mode (default: "default")
|
|
66
|
-
- **frameRate** - Video frame rate (default: 30)
|
|
67
|
-
- **streamType** - Video stream format ("jpg" or "vp8", default: "jpg")
|
|
68
|
-
- **quality** - Video quality ("high", "medium", or "low", default: "high")
|
|
69
|
-
- **crop** - Whether to crop the video (default: false)
|
|
70
|
-
- **showIdle** - Whether to show idle video when not speaking (default: false)
|
|
71
60
|
- **language** - Language code for the conversation (default: browser language)
|
|
72
61
|
- **allowWakeLock** - Prevent screen from sleeping during conversation (default: true)
|
|
73
|
-
- **fadeTransitionsType** - Video transition type (default: VideoTransitionType.NONE)
|
|
74
62
|
|
|
75
|
-
####
|
|
63
|
+
#### Callbacks
|
|
76
64
|
|
|
77
65
|
Register callbacks to handle various events:
|
|
78
|
-
```js
|
|
79
|
-
const conversation = await Conversation.startDigitalHuman({
|
|
80
|
-
// ... required options
|
|
81
|
-
onConnect: ({ userId, headInfo, microphoneAccess }) => {
|
|
82
|
-
console.log("Connected:", userId);
|
|
83
|
-
},
|
|
84
|
-
onDisconnect: (details) => {
|
|
85
|
-
console.log("Disconnected:", details.reason);
|
|
86
|
-
},
|
|
87
|
-
onStatusChange: ({ status }) => {
|
|
88
|
-
console.log("Status changed:", status); // "connecting", "connected", "disconnecting", "disconnected"
|
|
89
|
-
},
|
|
90
|
-
onText: (event) => {
|
|
91
|
-
console.log("User message:", event.text);
|
|
92
|
-
},
|
|
93
|
-
onResponse: (event) => {
|
|
94
|
-
console.log("AI response:", event.text);
|
|
95
|
-
},
|
|
96
|
-
onJoin: (event) => {
|
|
97
|
-
console.log("Joined conversation:", event);
|
|
98
|
-
},
|
|
99
|
-
onStreaming: (event) => {
|
|
100
|
-
console.log("Streaming event:", event.type); // "audio_frame", "video_frame", "metadata", "cache", "error"
|
|
101
|
-
},
|
|
102
|
-
onMuteStatusChange: ({ isMuted }) => {
|
|
103
|
-
console.log("Mute status:", isMuted);
|
|
104
|
-
},
|
|
105
|
-
onSpeakingStart: () => {
|
|
106
|
-
console.log("Digital human started speaking");
|
|
107
|
-
},
|
|
108
|
-
onSpeakingEnd: () => {
|
|
109
|
-
console.log("Digital human stopped speaking");
|
|
110
|
-
},
|
|
111
|
-
onStoppingEnd: () => {
|
|
112
|
-
console.log("Response stopped");
|
|
113
|
-
},
|
|
114
|
-
onTimeout: () => {
|
|
115
|
-
console.log("Session timed out");
|
|
116
|
-
},
|
|
117
|
-
onTimeoutWarning: () => {
|
|
118
|
-
console.log("Session will timeout soon");
|
|
119
|
-
},
|
|
120
|
-
onKeepSession: ({ granted }) => {
|
|
121
|
-
console.log("Keep session request:", granted);
|
|
122
|
-
},
|
|
123
|
-
onError: ({ message, endConversation, type }) => {
|
|
124
|
-
console.error("Error:", message);
|
|
125
|
-
// type: "toast" or "modal"
|
|
126
|
-
// endConversation: true if session should be restarted
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
#### Event Types
|
|
132
66
|
|
|
133
|
-
- **onConnect** - Called when the WebSocket connection is established
|
|
134
|
-
- **
|
|
135
|
-
- **
|
|
136
|
-
- **
|
|
137
|
-
- **
|
|
138
|
-
- **
|
|
139
|
-
- **
|
|
67
|
+
- **onConnect ({userId, headInfo, microphoneAccess})** - Called when the WebSocket connection is established
|
|
68
|
+
- **userId** `Boolean` Unique Identifier for the users session.
|
|
69
|
+
- **headInfo** `ConnectHeadType` Object with data about the digital human.
|
|
70
|
+
- **name** `String` Digital human head name
|
|
71
|
+
- **phrases** `String[]` Array with phrases set during digital human creation.
|
|
72
|
+
- **language** `String` Language code setup during digital human creation.
|
|
73
|
+
- **avatar** `String` Static image url for digital human.
|
|
74
|
+
- **microphoneAccess** `Boolean` True if microphone access was granted, False otherwise.
|
|
75
|
+
- **onDisconnect ()** - Called when the connection is closed
|
|
76
|
+
- **onStatusChange ({status})** - Called when connection status changes
|
|
77
|
+
- **status** `"connecting" | "connected" | "disconnecting" | "disconnected"` Shows current websocket connection status.
|
|
78
|
+
- **onMessage ({ timestamp, speaker, text, visible })** - Called when websocket receives a message or sends a response.
|
|
79
|
+
- **timestamp** `Date` Timestamp when message was received/sent
|
|
80
|
+
- **sender** `"user" | "ai"` Shows who the message came from.
|
|
81
|
+
- **text** `String` Message text
|
|
82
|
+
- **visible** `Boolean` Flag that you can use to control visibility of message. Sometimes, message comes before the video response starts playing. In such cases, this is usually `false`. Listen the `onSpeakingStart` event to change visibility when the video response starts playing.
|
|
140
83
|
- **onMuteStatusChange** - Called when mute status changes
|
|
141
84
|
- **onSpeakingStart** - Called when the digital human starts speaking
|
|
142
85
|
- **onSpeakingEnd** - Called when the digital human finishes speaking
|
|
143
86
|
- **onStoppingEnd** - Called when a response is manually stopped
|
|
144
87
|
- **onTimeout** - Called when the session times out due to inactivity
|
|
145
|
-
- **onTimeoutWarning** - Called before the session times out
|
|
88
|
+
- **onTimeoutWarning** - Called before the session times out. This event warns you that the customers session is going to end in a bit. You can call the `keepSession` method to extend the customers session.
|
|
146
89
|
- **onKeepSession** - Called when a keep-alive request is processed
|
|
147
90
|
- **onError** - Called when an error occurs
|
|
148
91
|
|
|
149
92
|
### Getting Background Video
|
|
150
93
|
|
|
151
94
|
Retrieve the idle background video URL for use in welcome screens or widget mode:
|
|
95
|
+
|
|
152
96
|
```js
|
|
153
97
|
const videoUrl = await Conversation.getBackgroundVideo({
|
|
154
98
|
orgId: "your-org-id",
|
|
155
99
|
headId: "your-head-id",
|
|
156
|
-
environment: "production",
|
|
157
100
|
});
|
|
158
101
|
```
|
|
159
102
|
|
|
@@ -161,7 +104,8 @@ const videoUrl = await Conversation.getBackgroundVideo({
|
|
|
161
104
|
|
|
162
105
|
#### startSession()
|
|
163
106
|
|
|
164
|
-
Start the conversation session and begin audio playback:
|
|
107
|
+
Start the conversation session and begin audio & video playback:
|
|
108
|
+
|
|
165
109
|
```js
|
|
166
110
|
await conversation.startSession();
|
|
167
111
|
```
|
|
@@ -171,40 +115,23 @@ This method should be called after user interaction to ensure audio context is p
|
|
|
171
115
|
#### sendMessage(message)
|
|
172
116
|
|
|
173
117
|
Send a text message to the digital human:
|
|
118
|
+
|
|
174
119
|
```js
|
|
175
|
-
conversation.sendMessage(
|
|
176
|
-
id: 1,
|
|
177
|
-
timestamp: new Date().toISOString(),
|
|
178
|
-
speaker: "user",
|
|
179
|
-
text: "Hello, how are you?",
|
|
180
|
-
isSent: false,
|
|
181
|
-
user_id: "user-123",
|
|
182
|
-
username: "John Doe",
|
|
183
|
-
event: EventType.TEXT,
|
|
184
|
-
visible: true,
|
|
185
|
-
});
|
|
120
|
+
conversation.sendMessage("Hello, how are you?");
|
|
186
121
|
```
|
|
187
122
|
|
|
188
|
-
#### keepSession(
|
|
123
|
+
#### keepSession()
|
|
124
|
+
|
|
125
|
+
Sends keep-alive event to prevent session timeout:
|
|
189
126
|
|
|
190
|
-
Send a keep-alive message to prevent session timeout:
|
|
191
127
|
```js
|
|
192
|
-
conversation.keepSession(
|
|
193
|
-
id: 1,
|
|
194
|
-
timestamp: new Date().toISOString(),
|
|
195
|
-
speaker: "user",
|
|
196
|
-
text: "",
|
|
197
|
-
isSent: false,
|
|
198
|
-
user_id: "user-123",
|
|
199
|
-
username: "John Doe",
|
|
200
|
-
event: EventType.KEEP_SESSION,
|
|
201
|
-
visible: true,
|
|
202
|
-
});
|
|
128
|
+
conversation.keepSession();
|
|
203
129
|
```
|
|
204
130
|
|
|
205
131
|
#### stopCurrentResponse()
|
|
206
132
|
|
|
207
133
|
Stop the current response from the digital human:
|
|
134
|
+
|
|
208
135
|
```js
|
|
209
136
|
conversation.stopCurrentResponse();
|
|
210
137
|
```
|
|
@@ -214,6 +141,7 @@ This clears both audio and video queues and returns the digital human to idle st
|
|
|
214
141
|
#### toggleMuteStatus()
|
|
215
142
|
|
|
216
143
|
Toggle the mute status of the audio output:
|
|
144
|
+
|
|
217
145
|
```js
|
|
218
146
|
const volume = await conversation.toggleMuteStatus();
|
|
219
147
|
console.log("New volume:", volume); // 0 for muted, 1 for unmuted
|
|
@@ -222,6 +150,7 @@ console.log("New volume:", volume); // 0 for muted, 1 for unmuted
|
|
|
222
150
|
#### getUserId()
|
|
223
151
|
|
|
224
152
|
Get the current user's ID:
|
|
153
|
+
|
|
225
154
|
```js
|
|
226
155
|
const userId = conversation.getUserId();
|
|
227
156
|
```
|
|
@@ -229,76 +158,30 @@ const userId = conversation.getUserId();
|
|
|
229
158
|
#### endSession()
|
|
230
159
|
|
|
231
160
|
End the conversation session and clean up resources:
|
|
161
|
+
|
|
232
162
|
```js
|
|
233
163
|
await conversation.endSession();
|
|
234
164
|
```
|
|
235
165
|
|
|
236
166
|
This closes the WebSocket connection, releases the wake lock, and destroys audio/video outputs.
|
|
237
167
|
|
|
238
|
-
#### initializeMicrophone()
|
|
239
|
-
|
|
240
|
-
Initialize microphone for speech recognition (ASR):
|
|
241
|
-
```js
|
|
242
|
-
const asrToken = await conversation.initializeMicrophone(
|
|
243
|
-
(result) => {
|
|
244
|
-
console.log("Speech result:", result);
|
|
245
|
-
},
|
|
246
|
-
(error) => {
|
|
247
|
-
console.error("Microphone error:", error);
|
|
248
|
-
},
|
|
249
|
-
(status) => {
|
|
250
|
-
console.log("Microphone status:", status);
|
|
251
|
-
}
|
|
252
|
-
);
|
|
253
|
-
```
|
|
254
|
-
|
|
255
168
|
### Message Structure
|
|
256
169
|
|
|
257
170
|
Messages sent to and from the digital human follow this structure:
|
|
171
|
+
|
|
258
172
|
```typescript
|
|
259
173
|
interface Message {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
speaker: "user" | "backend";
|
|
174
|
+
timestamp: Date;
|
|
175
|
+
sender: SpeakerType;
|
|
263
176
|
text: string;
|
|
264
|
-
isSent: boolean;
|
|
265
|
-
user_id: string;
|
|
266
|
-
username: string;
|
|
267
|
-
event: EventType.TEXT | EventType.KEEP_SESSION;
|
|
268
177
|
visible: boolean;
|
|
269
|
-
session_id?: string; // Auto-generated
|
|
270
178
|
}
|
|
271
179
|
```
|
|
272
180
|
|
|
273
|
-
### Event Types
|
|
274
|
-
|
|
275
|
-
The SDK defines the following event types:
|
|
276
|
-
```typescript
|
|
277
|
-
enum EventType {
|
|
278
|
-
TEXT = "text",
|
|
279
|
-
RESPONSE = "response",
|
|
280
|
-
JOIN = "join",
|
|
281
|
-
STREAMING = "streaming",
|
|
282
|
-
BINARY = "binary",
|
|
283
|
-
TIMEOUT_WARNING = "timeout_warning",
|
|
284
|
-
TIME_OUT = "timeout",
|
|
285
|
-
KEEP_SESSION = "keep_session",
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### Streaming Event Types
|
|
290
|
-
|
|
291
|
-
Streaming events can have the following types:
|
|
292
|
-
|
|
293
|
-
- **audio_frame** - Audio data for playback
|
|
294
|
-
- **video_frame** - Video frame data
|
|
295
|
-
- **metadata** - Stream control metadata (start/end)
|
|
296
|
-
- **cache** - Cached video response
|
|
297
|
-
- **error** - Streaming error occurred
|
|
298
|
-
|
|
299
181
|
### Error Handling
|
|
300
182
|
|
|
301
183
|
Always handle errors appropriately:
|
|
184
|
+
|
|
302
185
|
```js
|
|
303
186
|
try {
|
|
304
187
|
const conversation = await Conversation.startDigitalHuman({
|
|
@@ -324,106 +207,10 @@ try {
|
|
|
324
207
|
}
|
|
325
208
|
```
|
|
326
209
|
|
|
327
|
-
### Common Error Types
|
|
328
|
-
|
|
329
|
-
The SDK handles several error scenarios:
|
|
330
|
-
|
|
331
|
-
- **resource_exhausted** - Server at capacity
|
|
332
|
-
- **deadline_exceeded** - Request timeout
|
|
333
|
-
- **inactivity_timeout** - Session inactive for too long
|
|
334
|
-
- **connection** - WebSocket connection failed
|
|
335
|
-
|
|
336
|
-
## Framework Integration Examples
|
|
337
|
-
|
|
338
|
-
### React/Preact Example
|
|
339
|
-
```jsx
|
|
340
|
-
import { useEffect, useRef, useState } from "react";
|
|
341
|
-
import { Conversation, EventType } from "@unith-ai/core-client";
|
|
342
|
-
|
|
343
|
-
function DigitalHuman() {
|
|
344
|
-
const videoRef = useRef(null);
|
|
345
|
-
const conversationRef = useRef(null);
|
|
346
|
-
const [status, setStatus] = useState("disconnected");
|
|
347
|
-
const [messages, setMessages] = useState([]);
|
|
348
|
-
|
|
349
|
-
useEffect(() => {
|
|
350
|
-
const startConversation = async () => {
|
|
351
|
-
try {
|
|
352
|
-
const conversation = await Conversation.startDigitalHuman({
|
|
353
|
-
orgId: "your-org-id",
|
|
354
|
-
headId: "your-head-id",
|
|
355
|
-
element: videoRef.current,
|
|
356
|
-
onStatusChange: ({ status }) => setStatus(status),
|
|
357
|
-
onText: (event) => {
|
|
358
|
-
setMessages((prev) => [...prev, event]);
|
|
359
|
-
},
|
|
360
|
-
onResponse: (event) => {
|
|
361
|
-
setMessages((prev) => [...prev, event]);
|
|
362
|
-
},
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
conversationRef.current = conversation;
|
|
366
|
-
await conversation.startSession();
|
|
367
|
-
} catch (error) {
|
|
368
|
-
console.error("Failed to start:", error);
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
startConversation();
|
|
373
|
-
|
|
374
|
-
return () => {
|
|
375
|
-
conversationRef.current?.endSession();
|
|
376
|
-
};
|
|
377
|
-
}, []);
|
|
378
|
-
|
|
379
|
-
const sendMessage = async (text) => {
|
|
380
|
-
if (!conversationRef.current) return;
|
|
381
|
-
|
|
382
|
-
await conversationRef.current.sendMessage({
|
|
383
|
-
id: messages.length,
|
|
384
|
-
timestamp: new Date().toISOString(),
|
|
385
|
-
speaker: "user",
|
|
386
|
-
text,
|
|
387
|
-
isSent: false,
|
|
388
|
-
user_id: conversationRef.current.getUserId(),
|
|
389
|
-
username: "User",
|
|
390
|
-
event: EventType.TEXT,
|
|
391
|
-
visible: true,
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
return (
|
|
396
|
-
<div>
|
|
397
|
-
<div ref={videoRef} style={{ width: "100%", height: "600px" }} />
|
|
398
|
-
<div>Status: {status}</div>
|
|
399
|
-
<button onClick={() => sendMessage("Hello!")}>Send Message</button>
|
|
400
|
-
</div>
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
```
|
|
404
|
-
|
|
405
210
|
## TypeScript Support
|
|
406
211
|
|
|
407
212
|
Full TypeScript types are included:
|
|
408
|
-
```typescript
|
|
409
|
-
import {
|
|
410
|
-
Conversation,
|
|
411
|
-
EventType,
|
|
412
|
-
Status,
|
|
413
|
-
HeadType,
|
|
414
|
-
VideoTransitionType,
|
|
415
|
-
type ConversationOptions,
|
|
416
|
-
type Message,
|
|
417
|
-
type IncomingSocketEvent,
|
|
418
|
-
} from "@unith-ai/core-client";
|
|
419
|
-
```
|
|
420
213
|
|
|
421
214
|
## Development
|
|
422
215
|
|
|
423
216
|
Please refer to the README.md file in the root of this repository.
|
|
424
|
-
|
|
425
|
-
## Contributing
|
|
426
|
-
|
|
427
|
-
Please create an issue first to discuss proposed changes. Any contributions are welcome!
|
|
428
|
-
|
|
429
|
-
Remember, if merged, your code will be used as part of a MIT licensed project. By submitting a Pull Request, you are giving your consent for your code to be integrated into this library.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,8 @@ import { IdleVideo } from "./modules/idle-video";
|
|
|
5
5
|
import { SyncController } from "./modules/sync";
|
|
6
6
|
import { User } from "./modules/user";
|
|
7
7
|
import { VideoOutput } from "./modules/video";
|
|
8
|
-
import { ResultType, STATUS_TYPES } from "./types/audio";
|
|
9
8
|
import type { ConversationOptions, ConversationEvents, DigitalHumanOptions, HeadOptions, VideoHtmlElement } from "./types/Conversation";
|
|
10
9
|
import { Environment } from "./types/environment";
|
|
11
|
-
import { Message } from "./types/event";
|
|
12
10
|
import { HeadType } from "./types/User";
|
|
13
11
|
export * from "./types/event";
|
|
14
12
|
export * from "./types/Conversation";
|
|
@@ -32,6 +30,7 @@ export declare class Conversation {
|
|
|
32
30
|
private status;
|
|
33
31
|
protected volume: number;
|
|
34
32
|
private sessionStarted;
|
|
33
|
+
private messageCounter;
|
|
35
34
|
syncController: SyncController;
|
|
36
35
|
avController: AVController;
|
|
37
36
|
private monitor;
|
|
@@ -52,15 +51,13 @@ export declare class Conversation {
|
|
|
52
51
|
static getBackgroundVideo(options: {
|
|
53
52
|
orgId: string;
|
|
54
53
|
headId: string;
|
|
55
|
-
environment
|
|
54
|
+
environment?: Environment;
|
|
56
55
|
}): Promise<string>;
|
|
57
56
|
constructor(options: Options, microphoneAccess: boolean, connection: Connection, idleVideo: IdleVideo, wakeLock: WakeLockSentinel | null, user: User, audioOutput: AudioOutput, videoOutput: VideoOutput, headInfo: HeadType);
|
|
58
57
|
private startLatencyMonitoring;
|
|
59
58
|
private handleIOSSilentMode;
|
|
60
59
|
private onOutputWorkletMessage;
|
|
61
|
-
private
|
|
62
|
-
private handleTextEvent;
|
|
63
|
-
private handleResponseEvent;
|
|
60
|
+
private handleMessage;
|
|
64
61
|
private handleStreamError;
|
|
65
62
|
private handleStreamingEvent;
|
|
66
63
|
private handleVideoFrame;
|
|
@@ -81,11 +78,12 @@ export declare class Conversation {
|
|
|
81
78
|
stopCurrentResponse(): void;
|
|
82
79
|
toggleMuteStatus(): Promise<number>;
|
|
83
80
|
startSession(): Promise<Connection>;
|
|
84
|
-
initializeMicrophone(
|
|
81
|
+
initializeMicrophone(): Promise<{
|
|
85
82
|
token: string | null | undefined;
|
|
86
83
|
region: string | null | undefined;
|
|
87
84
|
}>;
|
|
88
85
|
endSession(): Promise<void>;
|
|
89
|
-
sendMessage(
|
|
90
|
-
keepSession(
|
|
86
|
+
sendMessage(text: string): void;
|
|
87
|
+
keepSession(): void;
|
|
91
88
|
}
|
|
89
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAElB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAEjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAiBlD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,MAAM,MAAM,OAAO,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAC3E,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAC5C,gBAAgB,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,qBAAa,YAAY;IAsLd,OAAO,EAAE,OAAO;IAChB,gBAAgB,EAAE,OAAO;IACzB,UAAU,EAAE,UAAU;IACtB,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IACjC,IAAI,EAAE,IAAI;IACV,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,WAAW;IACxB,QAAQ,EAAE,QAAQ;IA7L3B,OAAO,CAAC,MAAM,CAAwB;IACtC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,cAAc,CAAK;IAEpB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAClC,OAAO,CAAC,OAAO,CAA+B;IAE9C,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,mBAAmB,CAGlB;IAET,OAAO,CAAC,MAAM,CAAC,cAAc;IAsB7B;;;;OAIG;WACiB,iBAAiB,CACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,YAAY,CAAC;IAkHxB;;;;OAIG;WACiB,kBAAkB,CAAC,OAAO,EAAE;QAC9C,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,WAAW,CAAC;KAC3B;gBAaQ,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ;IA4B3B,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,sBAAsB,CAE5B;IAEF,OAAO,CAAC,aAAa,CASnB;IAEF,OAAO,CAAC,iBAAiB,CA2DvB;IAEF,OAAO,CAAC,oBAAoB,CA6D1B;IAEF,OAAO,CAAC,gBAAgB,CAYtB;IAEF,OAAO,CAAC,gBAAgB,CAStB;IAEF,OAAO,CAAC,gBAAgB,CA0BtB;IAEF,OAAO,CAAC,SAAS,CAuEf;IAEF,OAAO,CAAC,qBAAqB,CAQ3B;IAEK,SAAS;YAIF,gBAAgB;IAG9B,OAAO,CAAC,YAAY;IAQpB;;;;;;OAMG;IACI,mBAAmB;IAYb,gBAAgB;IAShB,YAAY;IAkBZ,oBAAoB;;;;IAI1B,UAAU;IAIV,WAAW,CAAC,IAAI,EAAE,MAAM;IAuBxB,WAAW;CAsBnB"}
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=Array(t);n<t;n++)i[n]=e[n];return i}function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var i in n)({}).hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e},t.apply(null,arguments)}function n(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}var i,r,o=new Map,s=(i="audio-concat-processor",r='\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = [];\n this.cursor = 0;\n this.currentBuffer = null;\n this.currentBufferTimestamp = null;\n this.currentBufferStartSample = 0;\n this.wasInterrupted = false;\n this.playing = false;\n this.finished = false;\n\n this.playbackRate = 1.0;\n this.adjustUntilSample = null;\n this.sampleCounter = 0;\n this.format = { sampleRate: 48000 };\n\n // Time synchronization properties\n this.playbackStartTime = null;\n this.totalSamplesPlayed = 0;\n \n // Drift correction parameters\n this.maxCorrectionRate = 0.1; // Maximum 10% speed adjustment\n this.correctionSmoothness = 0.95; // How smoothly to apply corrections (0-1)\n this.targetPlaybackRate = 1.0;\n\n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.format = data.format;\n break;\n\n case "buffer":\n this.wasInterrupted = false;\n \n const bufferData = this.format.encoding === "ulaw"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer);\n \n // Store buffer with its timestamp\n this.buffers.push({\n buffer: bufferData,\n timestamp: data.timestamp_ms\n });\n break;\n \n case "startPlayback":\n this.playing = true;\n this.playbackStartTime = currentTime;\n this.totalSamplesPlayed = 0;\n this.sampleCounter = 0;\n break;\n \n case "stopPlayback":\n this.playing = false;\n this.finished = true;\n \n // Discard all queued buffers\n this.buffers = [];\n \n // Clear current buffer and reset cursor\n this.currentBuffer = null;\n this.currentBufferTimestamp = null;\n this.cursor = 0;\n \n // Reset playback rate adjustments\n this.playbackRate = 1.0;\n this.adjustUntilSample = null;\n this.targetPlaybackRate = 1.0;\n \n // Notify that playback has stopped\n this.port.postMessage({ \n type: "process", \n finished: true,\n stopped: true\n });\n break;\n\n case "adjustPlaybackRate":\n this.playbackRate = data.rate;\n this.adjustUntilSample = this.sampleCounter + Math.floor(this.format.sampleRate * data.duration);\n break;\n \n case "reset":\n this.playing = false;\n this.finished = false;\n this.currentBuffer = null;\n this.currentBufferTimestamp = null;\n this.currentBufferStartSample = 0;\n this.cursor = 0;\n this.buffers = [];\n this.playbackStartTime = null;\n this.totalSamplesPlayed = 0;\n this.targetPlaybackRate = 1.0;\n break;\n\n case "interrupt":\n this.wasInterrupted = true;\n break;\n\n case "clearInterrupted":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n this.currentBufferTimestamp = null;\n }\n break;\n }\n };\n }\n\n // Calculate the expected timestamp based on samples played\n getExpectedTimestamp() {\n if (!this.playbackStartTime) return 0;\n \n // Convert samples to milliseconds\n const samplesPlayedMs = (this.totalSamplesPlayed / this.format.sampleRate) * 1000;\n return samplesPlayedMs;\n }\n\n // Calculate the actual timestamp of current playback position\n getCurrentActualTimestamp() {\n if (!this.currentBufferTimestamp) return 0;\n \n // Current position within the buffer in samples\n const samplesIntoBuffer = Math.floor(this.cursor);\n \n // Convert buffer position to milliseconds (assuming buffer covers specific time duration)\n // Each buffer typically represents a fixed time duration\n const bufferDurationMs = (this.currentBuffer.length / this.format.sampleRate) * 1000;\n const progressThroughBuffer = samplesIntoBuffer / this.currentBuffer.length;\n \n return this.currentBufferTimestamp + (progressThroughBuffer * bufferDurationMs);\n }\n\n // Calculate timing drift and adjust playback rate accordingly\n calculateDriftCorrection() {\n if (!this.currentBufferTimestamp || !this.playbackStartTime) {\n return 1.0;\n }\n\n const expectedTimestamp = this.getExpectedTimestamp();\n const actualTimestamp = this.getCurrentActualTimestamp();\n \n // Calculate drift in milliseconds\n const drift = actualTimestamp - expectedTimestamp;\n \n // Convert drift to a playback rate adjustment\n // Positive drift means we\'re ahead - slow down\n // Negative drift means we\'re behind - speed up\n let correctionFactor = 1.0;\n \n if (Math.abs(drift) > 10) { // Only correct if drift > 10ms\n // Calculate correction rate based on drift\n // More drift = more correction, but capped at maxCorrectionRate\n const driftRatio = Math.min(Math.abs(drift) / 1000, this.maxCorrectionRate);\n \n if (drift > 0) {\n // We\'re ahead, slow down\n correctionFactor = 1.0 - driftRatio;\n } else {\n // We\'re behind, speed up\n correctionFactor = 1.0 + driftRatio;\n }\n \n // Apply smoothing to avoid jarring rate changes\n this.targetPlaybackRate = this.targetPlaybackRate * this.correctionSmoothness + \n correctionFactor * (1 - this.correctionSmoothness);\n } else {\n // Gradually return to normal speed when drift is small\n this.targetPlaybackRate = this.targetPlaybackRate * this.correctionSmoothness + \n 1.0 * (1 - this.correctionSmoothness);\n }\n\n return this.targetPlaybackRate;\n }\n\n process(_, outputs, parameters) {\n const output = outputs[0][0];\n\n if (!this.playing) {\n output.fill(0);\n return true;\n }\n\n let finished = false;\n\n for (let i = 0; i < output.length; i++) {\n // If no buffer is ready, get the next one\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n \n const bufferData = this.buffers.shift();\n this.currentBuffer = bufferData.buffer;\n this.currentBufferTimestamp = bufferData.timestamp;\n this.currentBufferStartSample = this.totalSamplesPlayed;\n this.cursor = 0;\n }\n\n // Calculate drift correction for timing synchronization\n const driftCorrectedRate = this.calculateDriftCorrection();\n \n // Apply manual playback rate adjustments if active\n let finalPlaybackRate = driftCorrectedRate;\n if (this.adjustUntilSample !== null && this.sampleCounter < this.adjustUntilSample) {\n finalPlaybackRate *= this.playbackRate;\n } else if (this.adjustUntilSample !== null) {\n this.playbackRate = 1.0;\n this.adjustUntilSample = null;\n }\n\n const idx = Math.floor(this.cursor);\n const nextIdx = Math.min(idx + 1, this.currentBuffer.length - 1);\n\n let s1 = this.currentBuffer[idx];\n let s2 = this.currentBuffer[nextIdx];\n if (this.format.encoding === "ulaw") {\n s1 = decodeSample(s1);\n s2 = decodeSample(s2);\n }\n\n const frac = this.cursor - idx;\n const interpolated = s1 * (1 - frac) + s2 * frac;\n output[i] = interpolated / 32768;\n\n this.cursor += finalPlaybackRate;\n this.sampleCounter++;\n this.totalSamplesPlayed++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n this.currentBufferTimestamp = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ \n type: "process", \n finished,\n // Optional: send timing info for debugging\n timing: {\n expectedTimestamp: this.getExpectedTimestamp(),\n actualTimestamp: this.getCurrentActualTimestamp(),\n playbackRate: this.targetPlaybackRate\n }\n });\n }\n\n return true;\n }\n}\nregisterProcessor("audio-concat-processor", AudioConcatProcessor);\n',function(e){try{var t,s=function(s){return t?s:n(function(){var t="data:application/javascript;base64,"+btoa(r);return Promise.resolve(e.addModule(t)).then(function(){o.set(i,t)})},function(){throw new Error("Failed to load the "+i+" worklet module. Make sure the browser supports AudioWorklets.")})},a=o.get(i);if(a)return Promise.resolve(e.addModule(a));var u=new Blob([r],{type:"application/javascript"}),c=URL.createObjectURL(u),d=n(function(){return Promise.resolve(e.addModule(c)).then(function(){o.set(i,c),t=1})},function(){URL.revokeObjectURL(c)});return Promise.resolve(d&&d.then?d.then(s):s(d))}catch(e){return Promise.reject(e)}});function a(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}var u,c,d=/*#__PURE__*/function(){function e(e,t,n,i){this.context=void 0,this.analyser=void 0,this.gain=void 0,this.worklet=void 0,this._isMuted=!1,this.context=e,this.analyser=t,this.gain=n,this.worklet=i}e.createAudioOutput=function(t){var n=t.sampleRate,i=t.format;try{var r=null;return Promise.resolve(a(function(){var t=(r=new AudioContext({sampleRate:n})).createAnalyser(),o=r.createGain();return o.connect(t),t.connect(r.destination),Promise.resolve(s(r.audioWorklet)).then(function(){var n=new AudioWorkletNode(r,"audio-concat-processor");n.port.postMessage({type:"setFormat",format:i}),n.connect(o);var s=new e(r,t,o,n);return Promise.resolve(s.ensureIOSCompatibility()).then(function(){return s})})},function(e){var t;throw null==(t=r)||t.close(),e}))}catch(e){return Promise.reject(e)}};var t=e.prototype;return t.ensureIOSCompatibility=function(){try{var e=this;if(/iPad|iPhone|iPod/.test(navigator.userAgent)){var t=e.context.createBuffer(1,1,e.context.sampleRate),n=e.context.createBufferSource();n.buffer=t,n.connect(e.context.destination),n.start()}return Promise.resolve()}catch(e){return Promise.reject(e)}},t.getOutputDevice=function(){try{var e=this;return Promise.resolve(a(function(){var t=e.context.sinkId||"";return Promise.resolve(navigator.mediaDevices.enumerateDevices()).then(function(e){var n=e.filter(function(e){return"audiooutput"===e.kind});return""===t?n.find(function(e){return"default"===e.deviceId})||n[0]||null:n.find(function(e){return e.deviceId===t})||null})},function(e){return console.error("Error getting output device:",e),null}))}catch(e){return Promise.reject(e)}},t.getAvailableOutputDevices=function(){try{return Promise.resolve(a(function(){return Promise.resolve(navigator.mediaDevices.enumerateDevices()).then(function(e){return e.filter(function(e){return"audiooutput"===e.kind})})},function(e){return console.error("Error enumerating devices:",e),[]}))}catch(e){return Promise.reject(e)}},t.mute=function(){this.gain.gain.value=0,this._isMuted=!0},t.unmute=function(){this.gain.gain.value=1,this._isMuted=!1},t.toggleMute=function(){return this._isMuted?this.unmute():this.mute(),this._isMuted},t.close=function(){try{return Promise.resolve(this.context.close()).then(function(){})}catch(e){return Promise.reject(e)}},e}(),l=/*#__PURE__*/function(){function e(e,t,n){var i=this;this.syncController=void 0,this.audioOutput=void 0,this.videoOutput=void 0,this.initialized=!1,this.isPlaying=!1,this.isPlayingAudio=!1,this.isPlayingVideo=!1,this.isStoppingAV=!1,this.handleAudioWorkletMessage=function(e){"process"===e.type&&(i.isPlayingAudio=!1,i.isPlayingVideo||(i.isPlaying=!1),i.audioOutput.worklet.port.postMessage({type:"reset"}))},this.syncController=e,this.audioOutput=t,this.videoOutput=n,this.videoOutput.setEventCallbacks({onIdleVideoShown:function(){},onIdleVideoHidden:function(){i.isPlayingVideo=!1,i.isPlayingAudio||(i.isPlaying=!1),i.videoOutput.stopBufferMonitoring()}})}var t=e.prototype;return t.updatePlayingState=function(e){this.isPlaying=e,this.isPlayingAudio=e,this.isPlayingVideo=e},t.toggleStoppingVideo=function(e){this.isStoppingAV=e},t.startPlayback=function(e){void 0===e&&(e=!1);try{var t=this;return t.isPlaying?Promise.resolve():(e&&(t.initialized=e),Promise.resolve(t.audioOutput.context.resume()).then(function(){t.updatePlayingState(!0),t.videoOutput.startStreaming(e),t.audioOutput.worklet.port.postMessage({type:"startPlayback"})}))}catch(e){return Promise.reject(e)}},t.playAudioVideo=function(){try{var e=this;if(!e.initialized)return Promise.resolve();if(e.isPlaying||e.isStoppingAV)return Promise.resolve();var t=e.videoOutput.getBufferLength();return e.startPlayback(!0),t>=6&&e.startPlayback(),Promise.resolve()}catch(e){return Promise.reject(e)}},e}();function h(e){return e.event===exports.EventType.JOIN}function f(e){return e.event===exports.EventType.TEXT}function m(e){return e.event===exports.EventType.RESPONSE}function p(e){return e.event===exports.EventType.STREAMING}function v(e){return e.event===exports.EventType.STREAMING&&e.type===exports.StreamingEventType.ERROR}function g(e){return e.event===exports.EventType.BINARY}function y(e){return e.type===exports.EventType.PONG}function P(e){return e.event===exports.EventType.TIMEOUT_WARNING}function S(e){return e.event===exports.EventType.TIME_OUT}function I(e){return e.event===exports.EventType.KEEP_SESSION}function w(e){switch(e){case"production":default:return"https://chat-api.unith.ai";case"staging":return"https://chat-api.stg.unith.live";case"development":return"https://chat-development-origin.api.unith.live"}}function E(e){return!!e.event}exports.EventType=void 0,(u=exports.EventType||(exports.EventType={})).TEXT="text",u.CONVERSATION_END="conversation_end",u.JOIN="join",u.ERROR="error",u.TIME_OUT="timeout",u.UNITH_NLP_EXCEPTION="unith_nlp_exception",u.ANALYTICS="analytics-userFeedback",u.CHOICE="choice",u.TIMEOUT_WARNING="timeout_warning",u.KEEP_SESSION="keep_session",u.RESPONSE="response",u.STREAMING="streaming",u.PING="ping",u.PONG="pong",u.BINARY="binary",exports.StreamingEventType=void 0,(c=exports.StreamingEventType||(exports.StreamingEventType={})).VIDEO_FRAME="video_frame",c.AUDIO_FRAME="audio_frame",c.METADATA="metadata",c.ERROR="error",c.CACHE="cache";var T=/*#__PURE__*/function(){function e(e,t){var n=this;this.socket=void 0,this.userId=void 0,this.queue=[],this.disconnectionDetails=null,this.onDisconnectCallback=null,this.onMessageCallback=null,this.onPingPongCallback=null,this.socket=e,this.userId=t,this.socket.addEventListener("error",function(e){n.disconnect({reason:"error",message:"The connection was closed due to a websocket error.",context:e})}),this.socket.addEventListener("close",function(e){n.disconnect({reason:"error",message:e.reason||"The connection was closed by the server.",context:e})}),this.socket.addEventListener("message",function(e){try{var t;if(y(t=e.data instanceof Blob||e.data instanceof ArrayBuffer?{event:exports.EventType.BINARY,user_id:"",username:"",data:e.data}:JSON.parse(e.data))){if(!n.onPingPongCallback)return;return void n.onPingPongCallback(t)}if(!E(t))return;n.onMessageCallback?n.onMessageCallback(t):n.queue.push(t)}catch(e){}})}e.create=function(t){try{var n=null,i=function(e){switch(e){case"production":default:return"wss://stream-api.unith.ai/stream-hub";case"staging":return"wss://stream-api.stg.unith.live/stream-hub";case"development":return"wss://stream-api.dev.unith.live/stream-hub"}}(t.environment);return Promise.resolve(function(r,o){try{var s=(n=new WebSocket(i+"/"+t.orgId+"/"+t.headId),Promise.resolve(new Promise(function(e,i){n.addEventListener("open",function(){n.send(JSON.stringify({token:t.token,api_key:t.apiKey,text_only:!0,format:"vp8",quality:"standard",crop:!1}))},{once:!0}),n.addEventListener("close",i),n.addEventListener("error",i),n.addEventListener("message",function(n){var r=JSON.parse(n.data);E(r)&&(h(r)?r.granted&&(null==t.onJoin||t.onJoin(),e(r.user_id)):v(r)&&i({type:"connection",message:"We are currently at full capacity. Please try again later."}))},{once:!0})})).then(function(t){return new e(n,t)}))}catch(e){return o(e)}return s&&s.then?s.then(void 0,o):s}(0,function(e){var t;throw null==(t=n)||t.close(),e}))}catch(e){return Promise.reject(e)}};var t=e.prototype;return t.disconnect=function(e){var t;this.disconnectionDetails||(this.disconnectionDetails=e,null==(t=this.onDisconnectCallback)||t.call(this,e))},t.close=function(){this.socket.close()},t.sendMessage=function(e){this.socket.send(JSON.stringify(e))},t.sendPingEvent=function(e){this.onPingPongCallback?this.socket.send(JSON.stringify(e)):console.warn("Ping event sent without a callback set.")},t.onPingPong=function(e){this.onPingPongCallback=e},t.onMessage=function(e){this.onMessageCallback=e;var t=this.queue;this.queue=[],t.length>0&&queueMicrotask(function(){t.forEach(e)})},t.onDisconnect=function(e){this.onDisconnectCallback=e;var t=this.disconnectionDetails;t&&queueMicrotask(function(){e(t)})},e}(),V=/*#__PURE__*/function(){function e(e,t){this.idleVideoSource=void 0,this.videoId=void 0,this.idleVideoSource=e,this.videoId=t}return e.getIdleVideo=function(t,n,i){try{return Promise.resolve(e.getIdleVideoId(t,n,i)).then(function(r){return Promise.resolve(fetch(t+"/api/v1/idle/"+n+"/"+i+"/"+r)).then(function(t){return t.status>=200&&t.status<=299?Promise.resolve(t.json()).then(function(t){if(t)return new e(t,r);throw new Error("No idle video found for the specified orgId and headId.")}):Promise.resolve(t.text()).then(function(e){var n=new Error("An error occurred retrieving idle video: "+t.status+" "+t.statusText+". Response: "+e);throw n.name="IdleVideoError",n})})})}catch(e){return Promise.reject(e)}},e.prototype.getAvatarSrc=function(e,t,n){try{return Promise.resolve(fetch(e+"/api/v1/avatar/"+t+"/"+n+"/"+this.videoId)).then(function(e){return e.status>=200&&e.status<=299?Promise.resolve(e.json()).then(function(e){if(e)return e;throw new Error("No avatar image found for the specified orgId and headId.")}):Promise.resolve(e.text()).then(function(t){var n=new Error("An error occurred retrieving avatar: "+e.status+" "+e.statusText+". Response: "+t);throw n.name="AvatarError",n})})}catch(e){return Promise.reject(e)}},e.getIdleVideoId=function(e,t,n){try{return Promise.resolve(fetch(e+"/api/v1/videos/"+t+"/"+n)).then(function(e){return e.status>=200&&e.status<=299?Promise.resolve(e.json()).then(function(e){if(e.length>0)return e[0].id;throw new Error("No idle video found for the specified orgId and headId.")}):Promise.resolve(e.text()).then(function(t){var n=new Error("An error occurred retrieving idle video: "+e.status+" "+e.statusText+". Response: "+t);throw n.name="IdleVideoError",n})})}catch(e){return Promise.reject(e)}},e}(),k=/*#__PURE__*/function(){function e(e,t){this.connection=void 0,this.intervalId=null,this.pingInterval=void 0,this.timeout=void 0,this.lastPingTimestamp="0",this.history=[],this.maxHistory=void 0,this.onUpdate=void 0,this.connection=e,this.pingInterval=(null==t?void 0:t.pingInterval)||4e3,this.timeout=(null==t?void 0:t.timeout)||2e3,this.maxHistory=(null==t?void 0:t.maxHistory)||3,this.onUpdate=null==t?void 0:t.onUpdate,this.handleMessage=this.handleMessage.bind(this),this.connection.onPingPong(this.handleMessage)}var t=e.prototype;return t.start=function(){var e=this;this.intervalId||(this.intervalId=setInterval(function(){e.sendPing()},this.pingInterval))},t.stop=function(){clearInterval(this.intervalId),this.intervalId=null},t.destroy=function(){this.stop()},t.sendPing=function(){var e=performance.now().toString();this.lastPingTimestamp=e;var t={event:exports.EventType.PING,timestamp:this.lastPingTimestamp,id:"0"};this.connection.sendPingEvent(t)},t.handleMessage=function(e){try{if(e.timestamp===this.lastPingTimestamp){var t=performance.now()-parseFloat(e.timestamp);this.recordLatency(t)}}catch(e){console.log("logging irrelevant message")}},t.recordLatency=function(e){this.history.push(e),this.history.length>this.maxHistory&&this.history.shift();var t=this.history.reduce(function(e,t){return e+t},0)/this.history.length,n=this.classifyLatency(t);this.onUpdate&&this.onUpdate({rtt:e,average:t,status:n})},t.classifyLatency=function(e){return e<100?"good":e<250?"moderate":"poor"},e}(),b=/*#__PURE__*/function(){function e(e){this.config=void 0,this.driftHistory=[],this.correctionInProgress=!1,this.lastAudioTiming=null,this.lastVideoTiming=null,this.config=e}var t=e.prototype;return t.updateAudioTime=function(e){this.lastAudioTiming={timestamp:performance.now(),relativeTime:e}},t.updateVideoTime=function(e){this.lastVideoTiming={timestamp:performance.now(),relativeTime:e}},t.resetTiming=function(){this.lastAudioTiming=null,this.lastVideoTiming=null},t.checkSync=function(){try{var e=this;if(e.correctionInProgress)return console.warn("Sync correction already in progress"),Promise.resolve();if(!e.lastAudioTiming||!e.lastVideoTiming)return console.warn("Insufficient timing data for sync check"),Promise.resolve();var t=Math.abs(e.lastAudioTiming.relativeTime-e.lastVideoTiming.relativeTime);return e.recordDrift(t),t>e.config.tolerance?console.log("Drift detected: "+t+"ms"):console.log("No significant drift detected"),Promise.resolve()}catch(e){return Promise.reject(e)}},t.recordDrift=function(e){this.driftHistory.push({timestamp:Date.now(),drift:e,audioTime:this.lastAudioTiming.relativeTime,videoTime:this.lastVideoTiming.relativeTime}),this.driftHistory.length>this.config.historyLength&&this.driftHistory.shift()},e}(),C=window.localStorage,x=window.location.origin+window.location.pathname,A=function(e,t,n){if(void 0!==C)return C.getItem("chat:"+x+":"+t+":"+n+":"+e)},O=function(e,t,n,i){void 0===C||C.setItem("chat:"+x+":"+n+":"+i+":"+e,t)};function R(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}var D,_,M=/*#__PURE__*/function(){function e(e,t,n,i,r,o,s,a){this.id=void 0,this.username=void 0,this.password=void 0,this.orgId=void 0,this.headId=void 0,this.apiBase=void 0,this.EXPIRATION_OFFSET=9e5,this.accessToken="",this.tokenType="",this.sessionId=0,this.id=n,this.username=i,this.password=r,this.orgId=o,this.headId=s,this.apiBase=a,this.accessToken=e,this.tokenType=t;var u=A("session_id",o,s);u&&(this.sessionId=parseInt(u),this.sessionId+=1),O("session_id",this.sessionId.toString(),o,s)}e.loginUser=function(t,n,i,r,o){try{var s=new FormData;return s.append("username",t),s.append("password",n),Promise.resolve(R(function(){return Promise.resolve(fetch(i+"/token",{method:"POST",body:s})).then(function(s){return s.status>=200&&s.status<=299?Promise.resolve(s.json()).then(function(s){return new e(s.access_token,s.token_type,s.user_id,t,n,r,o,i)}):Promise.resolve(s.text()).then(function(e){var t=new Error("An error occurred: "+s.status+" "+s.statusText+". Response: "+e);throw t.response={status:s.status,status_code:s.status,data:JSON.parse(e)},t})})},function(e){var t,n;if(null!=e&&null!=(t=e.response)&&null!=(t=t.data)&&t.detail)throw new Error(null==e||null==(n=e.response)||null==(n=n.data)?void 0:n.detail);throw new Error(JSON.stringify(e))}))}catch(e){return Promise.reject(e)}};var t=e.prototype;return t.getHeadDetails=function(e){try{var t=this,n=t.apiBase+"/api/v1/head/"+t.orgId+"/"+t.headId+"/"+e;return Promise.resolve(R(function(){return Promise.resolve(fetch(n)).then(function(e){return e.status>=200&&e.status<=299?Promise.resolve(e.json()):Promise.resolve(e.text()).then(function(t){var n=new Error("An error occurred: "+e.status+" "+e.statusText+". Response: "+t);throw n.response={status:e.status,status_code:e.status,data:JSON.parse(t)},n})})},function(e){var t,n;if(null!=e&&null!=(t=e.response)&&null!=(t=t.data)&&t.detail)throw new Error(null==e||null==(n=e.response)||null==(n=n.data)?void 0:n.detail);throw new Error(JSON.stringify(e))}))}catch(e){return Promise.reject(e)}},t.getAuthToken=function(e,t){try{var n,i=this.apiBase+"/token",r=new FormData;r.append("username",e),r.append("password",t);var o=R(function(){return Promise.resolve(fetch(i,{method:"POST",body:r})).then(function(e){return Promise.resolve(e.json()).then(function(e){n=e})})},function(e){var t,n;if(null!=e&&null!=(t=e.response)&&null!=(t=t.data)&&t.detail)throw new Error(null==e||null==(n=e.response)||null==(n=n.data)?void 0:n.detail);throw new Error(JSON.stringify(e))});return Promise.resolve(o&&o.then?o.then(function(e){return n}):n)}catch(e){return Promise.reject(e)}},t.getApiAsrToken=function(e){try{var t,n,i=function(e){return{token:t,region:n}},r=this.apiBase+"/api/v1/asr_token",o=R(function(){return Promise.resolve(fetch(r,{headers:{Authorization:"Bearer "+e}})).then(function(e){return Promise.resolve(e.json()).then(function(e){t=e.token,n=e.region})})},function(e){var t,n;if(null!=e&&null!=(t=e.response)&&null!=(t=t.data)&&t.detail)throw new Error(null==e||null==(n=e.response)||null==(n=n.data)?void 0:n.detail);throw new Error(JSON.stringify(e))});return Promise.resolve(o&&o.then?o.then(i):i())}catch(e){return Promise.reject(e)}},t.getAccessToken=function(){try{var e=function(e){var o=JSON.parse(window.atob(n.split(".")[1]));return t.username=o.username,{access_token:n,user_id:i,session_id:r}},t=this,n=A("access_token",t.orgId,t.headId),i=A("user_id",t.orgId,t.headId),r=parseInt(A("session_id",t.orgId,t.headId)||"")||0,o=!0;if("undefined"!==n&&n&&i&&"number"==typeof r){var s=1e3*JSON.parse(window.atob(n.split(".")[1])).exp,a=(new Date).getTime()+t.EXPIRATION_OFFSET;o=a>s}var u=function(){if(o)return Promise.resolve(t.getAuthToken(t.username,t.password)).then(function(e){if(!e)throw new Error("Could not renew authentication token");i=e.user_id,r++,O("access_token",n=e.access_token,t.orgId,t.headId),O("user_id",i,t.orgId,t.headId),O("session_id",r.toString(),t.orgId,t.headId)})}();return Promise.resolve(u&&u.then?u.then(e):e())}catch(e){return Promise.reject(e)}},t.getAsrToken=function(){try{var e=this,t=A("asr_token",e.orgId,e.headId),n=A("region",e.orgId,e.headId);return Promise.resolve(e.getAccessToken()).then(function(i){var r,o=i.access_token;function s(e){return r?e:{token:t,region:n}}var a=!0;if(t&&n){var u=1e3*JSON.parse(window.atob(t.split(".")[1])).exp,c=(new Date).getTime()+e.EXPIRATION_OFFSET;a=c>u}var d=function(){if(a)return Promise.resolve(e.getApiAsrToken(o)).then(function(i){if(!i)return r=1,{token:"",region:""};n=i.region,O("asr_token",t=i.token,e.orgId,e.headId),O("asr_region",n,e.orgId,e.headId)})}();return d&&d.then?d.then(s):s(d)})}catch(e){return Promise.reject(e)}},e}();function B(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}!function(e){e.INITIALIZING="initializing",e.READY="ready",e.PLAYING="playing",e.PAUSED="paused",e.INTERRUPTED="interrupted",e.DESTROYED="destroyed"}(D||(D={})),exports.VideoTransitionType=void 0,(_=exports.VideoTransitionType||(exports.VideoTransitionType={})).NONE="none",_.CROSSFADE="crossfade",_.FADEIN="fadein",_.FADEOUT="fadeout";var F=/*#__PURE__*/function(){function n(e,n,i,r){var o=this;this.canvas=void 0,this.ctx=void 0,this.container=void 0,this.config=void 0,this.resizeObserver=null,this.decoder=null,this.state=D.INITIALIZING,this.isProcessingFrame=!1,this.isStreaming=!1,this.startTime=0,this.frameBuffer=[],this.currentSequenceId=0,this.animationFrameId=null,this.renderLoop=!1,this.fpsCounter={count:0,lastTime:0},this.handleContextLoss=function(){},this.handleContextRestore=function(){},this.handleResize=function(){var e=o.container.getBoundingClientRect(),t=e.width,n=e.height;o.canvas.width=t,o.canvas.height=n,o.canvas.style.width=t+"px",o.canvas.style.height=n+"px",o.ctx.imageSmoothingEnabled=!0},this.canvas=e,this.ctx=n,this.container=i,this.config=t({maxBufferSize:1e3,enableAdaptiveQuality:!1},r),this.setupContextLossHandling(),this.setupResizeHandling(),this.initializeDecoder()}n.create=function(e,t){try{var i;if(!("VideoDecoder"in window))throw new Error("WebCodecs VideoDecoder API is not supported in this browser");var r=document.createElement("canvas");r.width=t.width,r.height=t.height,r.style.position="absolute",r.style.top="0",r.style.left="0",r.style.backgroundColor=(null==(i=t.backgroundColor)?void 0:i.toString())||"#000000",r.style.maxWidth="100%",r.style.height="100%",r.style.zIndex="0",r.style.pointerEvents="none",r.style.objectFit="cover",r.style.imageRendering="pixelated";var o=r.getContext("2d",{alpha:!1,desynchronized:!0});if(!o)throw new Error("Failed to get 2D canvas context");return o.imageSmoothingEnabled=!0,e.appendChild(r),Promise.resolve(new n(r,o,e,t))}catch(e){return Promise.reject(e)}};var i=n.prototype;return i.initializeDecoder=function(){try{var e=this;return Promise.resolve(B(function(){return new VideoDecoder({output:function(){},error:function(){}}).close(),e.decoder=new VideoDecoder({output:function(t){e.renderVideoFrame(t)},error:function(e){console.error("VP8 Decoder error:",e.message)}}),Promise.resolve(e.decoder.configure({codec:"vp8",codedWidth:e.config.width,codedHeight:e.config.height})).then(function(){})},function(e){throw new Error("Failed to initialize VP8 decoder: "+e.message)}))}catch(e){return Promise.reject(e)}},i.setupResizeHandling=function(){var t=this;this.resizeObserver=new ResizeObserver(function(n){for(var i,r=function(t){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=function(t,n){if(t){if("string"==typeof t)return e(t,n);var i={}.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?e(t,n):void 0}}(t))){n&&(t=n);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(n);!(i=r()).done;)i.value.target===t.container&&t.handleResize()}),this.resizeObserver.observe(this.container),window.addEventListener("resize",this.handleResize)},i.getBufferLength=function(){return this.frameBuffer.length},i.getStreamingStatus=function(){return this.isStreaming},i.addFrame=function(e,t,n){void 0===n&&(n=!1);try{var i=this;if(i.state===D.DESTROYED)throw new Error("Cannot add frame to destroyed video output");var r={data:e,timestamp:t,isKeyframe:n,sequenceId:i.currentSequenceId++,size:e.byteLength};if(i.frameBuffer.length>=(i.config.maxBufferSize||1e3))if(i.config.enableAdaptiveQuality){if(!n)return Promise.resolve();var o=i.frameBuffer.findIndex(function(e){return!e.isKeyframe});-1!==o?i.frameBuffer.splice(o,1):i.frameBuffer.shift()}else i.frameBuffer.shift();return i.frameBuffer.push(r),Promise.resolve()}catch(e){return Promise.reject(e)}},i.toggleStream=function(e){try{return this.isStreaming=e,Promise.resolve()}catch(e){return Promise.reject(e)}},i.clearFrame=function(){if(this.state===D.DESTROYED)throw new Error("Cannot clear frame from destroyed video output");if(this.renderLoop=!1,this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.frameBuffer=[],this.isProcessingFrame=!1,this.currentSequenceId=0,this.startTime=0,this.fpsCounter={count:0,lastTime:0},this.decoder&&"configured"===this.decoder.state)try{this.decoder.flush()}catch(e){console.warn("Error flushing decoder:",e)}this.clearCanvas(),this.state=D.READY},i.interrupt=function(e){var t=this;if(void 0===e&&(e=!1),this.state!==D.DESTROYED){if(this.state=D.INTERRUPTED,this.frameBuffer=[],this.isProcessingFrame=!1,this.decoder&&"configured"===this.decoder.state)try{this.decoder.flush()}catch(e){console.warn("Error flushing decoder:",e)}e?this.fadeOutCanvas().then(function(){t.clearCanvas()}):this.clearCanvas()}},i.destroy=function(){this.state!==D.DESTROYED&&(this.state=D.DESTROYED,this.renderLoop=!1,this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.decoder&&(this.decoder.close(),this.decoder=null),this.frameBuffer=[],this.canvas.removeEventListener("webglcontextlost",this.handleContextLoss),this.canvas.removeEventListener("webglcontextrestored",this.handleContextRestore),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas),this.isProcessingFrame=!1)},i.getState=function(){return this.state},i.startRenderingStreamingVideo=function(e){e&&(this.state=D.READY,this.renderLoop=!0,this.startTime=performance.now(),this.render())},i.render=function(){var e,t=this;if(this.renderLoop&&this.state!==D.DESTROYED){var n=(null==(e=this.frameBuffer[0])?void 0:e.timestamp)||0;this.frameBuffer.length>0&&0===this.frameBuffer[0].sequenceId&&(this.startTime=performance.now());var i=performance.now()-this.startTime;i>=n&&this.frameBuffer.length>0&&!this.isProcessingFrame&&this.processNextFrame(i,i-n),this.animationFrameId=requestAnimationFrame(function(){return t.render()})}},i.processNextFrame=function(e,t){try{var n=this;if(n.isProcessingFrame||0===n.frameBuffer.length||!n.decoder)return Promise.resolve();if("configured"!==n.decoder.state)return Promise.resolve();n.isProcessingFrame=!0;var i=n.frameBuffer.shift(),r=function(e,t){try{var r=B(function(){return Promise.resolve(n.decodeVP8Frame(i)).then(function(){})},function(e){console.error("Frame processing failed:",e)})}catch(e){return t(!0,e)}return r&&r.then?r.then(t.bind(null,!1),t.bind(null,!0)):t(!1,r)}(0,function(e,t){if(n.isProcessingFrame=!1,e)throw t;return t});return Promise.resolve(r&&r.then?r.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},i.decodeVP8Frame=function(e){try{try{var t=new EncodedVideoChunk({type:e.isKeyframe?"key":"delta",timestamp:1e3*e.timestamp,data:e.data});this.decoder.decode(t)}catch(e){throw new Error("VP8 decode failed: "+e.message)}return Promise.resolve()}catch(e){return Promise.reject(e)}},i.renderVideoFrame=function(e){try{this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);var t,n,i,r,o=e.displayWidth/e.displayHeight;o>this.canvas.width/this.canvas.height?(i=(this.canvas.width-(t=(n=this.canvas.height)*o))/2,r=0):(i=0,r=(this.canvas.height-(n=(t=this.canvas.width)/o))/2),this.ctx.drawImage(e,i,r,t,n),e.close()}catch(e){console.error("Error rendering video frame:",e)}},i.clearCanvas=function(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)},i.fadeOutCanvas=function(){try{var e=this;return Promise.resolve(new Promise(function(t){var n=1,i=function(){e.canvas.style.opacity=(n-=.05).toString(),n<=0?(e.canvas.style.opacity="1",t()):requestAnimationFrame(i)};i()}))}catch(e){return Promise.reject(e)}},i.setupContextLossHandling=function(){var e=this;this.handleContextLoss=function(t){t.preventDefault(),console.warn("Canvas context lost"),e.state=D.PAUSED},this.handleContextRestore=function(){e.state===D.PAUSED&&(e.state=D.PLAYING)},this.canvas.addEventListener("webglcontextlost",this.handleContextLoss),this.canvas.addEventListener("webglcontextrestored",this.handleContextRestore)},n}();function N(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}var j=/*#__PURE__*/function(){function e(e,t,n,i){this.videoOutput=void 0,this.container=void 0,this.idleVideo=null,this.cachedVideo=null,this.idleVideoConfig=null,this.videoTransitionConfig=null,this.CROSSFADE_DURATION=500,this.isTransitioning=!1,this.isShowingIdleVideo=!0,this.bufferCheckAnimationId=null,this.lastBufferCheckTime=0,this.sessionStarted=!1,this.isShowingCachedVideo=!1,this.onIdleVideoShown=void 0,this.onIdleVideoHidden=void 0,this.onSpeakingStartCallback=null,this.onSpeakingEndCallback=null,this.videoOutput=e,this.container=t,this.videoTransitionConfig=n}e.createVideoOutput=function(t,n){try{return Promise.resolve(F.create(t,n)).then(function(i){var r=new e(i,t,n.transition,n.effects);return Promise.resolve(r.setupIdleVideo(n.idleVideo,n)).then(function(){return Promise.resolve(r.setupCachedVideo(n)).then(function(){return r})})})}catch(e){return Promise.reject(e)}};var t=e.prototype;return t.setupIdleVideo=function(e,t){try{var n=this;n.idleVideoConfig=e,n.idleVideo=document.createElement("video"),n.idleVideo.src=e.src,n.idleVideo.width=t.width,n.idleVideo.height=t.height,n.idleVideo.style.position="absolute",n.idleVideo.style.top="0",n.idleVideo.style.left="0",n.idleVideo.style.width="100%",n.idleVideo.style.height="100%",n.idleVideo.style.objectFit="cover",n.idleVideo.style.maxWidth="100%",n.idleVideo.style.backgroundColor=t.backgroundColor||"#000000",n.idleVideo.style.zIndex="1",n.idleVideo.style.pointerEvents="none",n.idleVideo.style.opacity="1",n.idleVideo.muted=!0,n.idleVideo.loop=!0,n.idleVideo.controls=!1,n.idleVideo.playsInline=!0,n.idleVideo.preload="auto","static"===getComputedStyle(n.container).position&&(n.container.style.position="relative"),n.container.appendChild(n.idleVideo);var i=N(function(){return Promise.resolve(n.idleVideo.load()).then(function(){return Promise.resolve(n.idleVideo.play()).then(function(){})})},function(e){console.error("Failed to load idle video:",e)});return Promise.resolve(i&&i.then?i.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},t.setupCachedVideo=function(e){try{var t=this;return t.cachedVideo=document.createElement("video"),t.cachedVideo.src="",t.cachedVideo.width=e.width,t.cachedVideo.height=e.height,t.cachedVideo.style.position="absolute",t.cachedVideo.style.top="0",t.cachedVideo.style.left="0",t.cachedVideo.style.width="100%",t.cachedVideo.style.height="100%",t.cachedVideo.style.objectFit="cover",t.cachedVideo.style.maxWidth="100%",t.cachedVideo.style.zIndex="2",t.cachedVideo.style.pointerEvents="none",t.cachedVideo.style.opacity="0",t.cachedVideo.style.transition="opacity "+t.CROSSFADE_DURATION+"ms ease-in-out",t.cachedVideo.controls=!1,t.cachedVideo.playsInline=!0,t.cachedVideo.preload="auto",t.container.appendChild(t.cachedVideo),Promise.resolve()}catch(e){return Promise.reject(e)}},t.onSpeakingStart=function(e){this.onSpeakingStartCallback=e},t.onSpeakingEnd=function(e){this.onSpeakingEndCallback=e},t.startStreaming=function(e){void 0===e&&(e=!1),this.sessionStarted=!0,this.startBufferMonitoring(),this.videoOutput.startRenderingStreamingVideo(e)},t.stopBufferMonitoring=function(){this.bufferCheckAnimationId&&(cancelAnimationFrame(this.bufferCheckAnimationId),this.bufferCheckAnimationId=null),this.lastBufferCheckTime=0,this.sessionStarted=!1},t.getBufferLength=function(){return this.videoOutput.getBufferLength()},t.startBufferMonitoring=function(){var e=this;if(!this.bufferCheckAnimationId){this.lastBufferCheckTime=0;var t=function(n){n-e.lastBufferCheckTime>=100&&(e.sessionStarted&&e.videoOutput.getBufferLength()>0?e.hideIdleVideoBeforeStream():e.videoOutput.getStreamingStatus()||0!==e.videoOutput.getBufferLength()||e.showIdleVideoAfterStream(),e.lastBufferCheckTime=n),e.bufferCheckAnimationId=requestAnimationFrame(t)};this.bufferCheckAnimationId=requestAnimationFrame(t)}},t.toggleCacheVideoMute=function(){this.cachedVideo&&(this.cachedVideo.muted=!this.cachedVideo.muted)},t.playCachedVideo=function(e){try{var t=this;if(t.isShowingCachedVideo||!t.cachedVideo||!e||t.isTransitioning)return Promise.resolve();t.isShowingCachedVideo=!0;var n=N(function(){return t.cachedVideo.src=e,t.cachedVideo.style.opacity="0",Promise.resolve(new Promise(function(e,n){t.cachedVideo.addEventListener("loadeddata",function(){return e()},{once:!0}),t.cachedVideo.addEventListener("error",function(){return n(new Error("Video failed to load"))},{once:!0}),t.cachedVideo.load()})).then(function(){return t.crossfadeFromIdleToCached(),Promise.resolve(t.cachedVideo.play()).then(function(){t.cachedVideo.addEventListener("ended",function(){try{return Promise.resolve(t.crossfadeFromCachedToIdle()).then(function(){return Promise.resolve(t.cleanupCachedVideo()).then(function(){return Promise.resolve(t.showIdleVideo()).then(function(){})})})}catch(e){return Promise.reject(e)}},{once:!0})})})},function(e){return console.error("Failed to play cached video:",e),t.cachedVideo.style.opacity="0",t.isShowingCachedVideo=!1,Promise.resolve(t.showIdleVideo()).then(function(){})});return Promise.resolve(n&&n.then?n.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},t.crossfadeFromIdleToCached=function(){try{var e=this;return e.idleVideo&&e.cachedVideo&&!e.isTransitioning?(e.isTransitioning=!0,e.idleVideo.style.opacity="1",e.cachedVideo.style.opacity="1",Promise.resolve(new Promise(function(t){return setTimeout(t,e.CROSSFADE_DURATION)})).then(function(){e.idleVideo&&(e.idleVideo.style.opacity="0"),e.isShowingIdleVideo=!1,null==e.onIdleVideoHidden||e.onIdleVideoHidden(),e.isTransitioning=!1})):Promise.resolve()}catch(e){return Promise.reject(e)}},t.crossfadeFromCachedToIdle=function(){try{var e=function(){return t.cachedVideo.style.opacity="0",Promise.resolve(new Promise(function(e){return setTimeout(e,t.CROSSFADE_DURATION)})).then(function(){t.isShowingIdleVideo=!0,null==t.onSpeakingEndCallback||t.onSpeakingEndCallback(),null==t.onIdleVideoShown||t.onIdleVideoShown(),t.isTransitioning=!1})},t=this;if(!t.idleVideo||!t.cachedVideo||t.isTransitioning)return Promise.resolve();t.isTransitioning=!0,t.idleVideo.style.opacity="1";var n=function(){if(t.idleVideo.paused){var e=N(function(){return Promise.resolve(t.idleVideo.play()).then(function(){})},function(e){console.error("Failed to play idle video during crossfade:",e)});if(e&&e.then)return e.then(function(){})}}();return Promise.resolve(n&&n.then?n.then(e):e())}catch(e){return Promise.reject(e)}},t.cleanupCachedVideo=function(){try{var e=this;return e.cachedVideo&&(e.cachedVideo.pause(),e.cachedVideo.currentTime=0,e.cachedVideo.src="",e.cachedVideo.style.opacity="0"),e.isShowingCachedVideo=!1,Promise.resolve()}catch(e){return Promise.reject(e)}},t.hideIdleVideo=function(){var e,t;this.idleVideo&&this.isShowingIdleVideo&&(null==(e=this.onSpeakingStartCallback)||e.call(this),this.isShowingIdleVideo=!1,this.idleVideo.style.opacity="0",null==(t=this.onIdleVideoHidden)||t.call(this))},t.hideIdleVideoBeforeStream=function(){var e,t;this.idleVideo&&this.isShowingIdleVideo&&(null==(e=this.onSpeakingStartCallback)||e.call(this),this.idleVideo.style.transition="opacity "+this.CROSSFADE_DURATION+"ms ease-in-out",this.isShowingIdleVideo=!1,this.idleVideo.style.opacity="0",null==(t=this.onIdleVideoHidden)||t.call(this))},t.setEventCallbacks=function(e){this.onIdleVideoShown=e.onIdleVideoShown,this.onIdleVideoHidden=e.onIdleVideoHidden},t.getStreamingStatus=function(){return this.videoOutput.getStreamingStatus()},t.showIdleVideo=function(){try{var e=this;return!e.idleVideo||e.isShowingIdleVideo?Promise.resolve():(null==e.onSpeakingEndCallback||e.onSpeakingEndCallback(),null==e.onIdleVideoShown||e.onIdleVideoShown(),e.isShowingIdleVideo=!0,e.idleVideo.style.opacity="1",Promise.resolve(N(function(){var t=function(){if(e.idleVideo.paused)return Promise.resolve(e.idleVideo.play()).then(function(){})}();if(t&&t.then)return t.then(function(){})},function(e){console.error("failed to play idle video:",e)})))}catch(e){return Promise.reject(e)}},t.showIdleVideoAfterStream=function(){try{var e=this;return!e.idleVideo||e.isShowingIdleVideo?Promise.resolve():(null==e.onSpeakingEndCallback||e.onSpeakingEndCallback(),null==e.onIdleVideoShown||e.onIdleVideoShown(),e.isShowingIdleVideo=!0,e.idleVideo.style.opacity="1",Promise.resolve(N(function(){var t=function(){if(e.idleVideo.paused)return Promise.resolve(e.idleVideo.play()).then(function(){})}();if(t&&t.then)return t.then(function(){})},function(e){console.error("failed to play idle video:",e)})))}catch(e){return Promise.reject(e)}},t.addFrame=function(e,t,n){try{var i=function(e){var i=o?new Uint8Array(e):e;return r.videoOutput.addFrame(i,t,n)},r=this,o=e instanceof Blob;return Promise.resolve(o?Promise.resolve(e.arrayBuffer()).then(i):i(new Uint8Array(e)))}catch(e){return Promise.reject(e)}},t.clearFrame=function(){return this.showIdleVideo(),this.videoOutput.clearFrame()},t.toggleStream=function(e){try{return Promise.resolve(this.videoOutput.toggleStream(e))}catch(e){return Promise.reject(e)}},t.interrupt=function(e){this.videoOutput.interrupt(e)},t.destroy=function(){this.bufferCheckAnimationId&&(cancelAnimationFrame(this.bufferCheckAnimationId),this.bufferCheckAnimationId=null),this.idleVideo&&(this.idleVideo.pause(),this.idleVideo.parentNode&&this.idleVideo.parentNode.removeChild(this.idleVideo),this.idleVideo=null),this.cachedVideo&&(this.cachedVideo.pause(),this.cachedVideo.parentNode&&this.cachedVideo.parentNode.removeChild(this.cachedVideo),this.cachedVideo=null),this.videoOutput.destroy()},e}(),L={tolerance:40,softCorrectionThreshold:100,hardCorrectionThreshold:200,historyLength:50,maxCorrectionRate:.02,correctionCoolDown:500,correctionFadeTime:1e3,minAudioBuffer:100,maxAudioBuffer:500,minVideoBuffer:3,maxVideoBuffer:10};function U(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}exports.Conversation=/*#__PURE__*/function(){function e(e,t,n,i,r,o,s,a,u){var c=this,d=this,h=this,v=this,y=this,w=this,E=this,T=this;this.options=void 0,this.microphoneAccess=void 0,this.connection=void 0,this.idleVideo=void 0,this.wakeLock=void 0,this.user=void 0,this.audioOutput=void 0,this.videoOutput=void 0,this.headInfo=void 0,this.status="connecting",this.volume=1,this.sessionStarted=!1,this.messageCounter=0,this.syncController=void 0,this.avController=void 0,this.monitor=null,this.videoFrameQueue=[],this.cachedResponseQueue=[],this.onOutputWorkletMessage=function(e){T.avController.handleAudioWorkletMessage(e.data)},this.handleMessage=function(e){try{return c.options.onMessage({timestamp:e.timestamp,sender:e.speaker,text:e.text,visible:e.visible}),Promise.resolve()}catch(e){return Promise.reject(e)}},this.handleStreamError=function(e){var t=e.error_type;if(t&&["resource_exhausted","deadline_exceeded","inactivity_timeout"].includes(t)){if("resource_exhausted"===t){if(!T.avController.isPlaying)return void T.options.onError({message:"The system is experiencing heavy traffic. Please try again later.",endConversation:!0,type:"toast"});T.options.onError({message:"We are experiencing heavy traffic and we can't deliver the response, try again",endConversation:!1,type:"toast"})}else if("deadline_exceeded"===t)T.options.onError({message:"We are experiencing heavy traffic and we can't deliver the response, try again",endConversation:!1,type:"toast"});else if("inactivity_timeout"===t)return void T.options.onTimeout()}else T.options.onError({message:"A connection error occurred. Please try again.",endConversation:!0,type:"toast"})},this.handleStreamingEvent=function(e){try{var t,n=function(n){if(t)return n;if("metadata"===e.type&&("start"!==e.metadata_type&&"end"!==e.metadata_type||(d.avController.isStoppingAV=!1,d.videoOutput.toggleStream("start"===e.metadata_type),"start"===e.metadata_type&&(d.videoFrameQueue=[],d.syncController.resetTiming()))),"audio_frame"===e.type){if(d.avController.isStoppingAV)return;d.handleAudioFrame(e)}if("video_frame"===e.type){if(d.avController.isStoppingAV)return;d.handleVideoFrame(e)}d.avController.playAudioVideo()};if("error"===e.type)return d.handleStreamError(e),Promise.resolve();var i=function(){if("cache"===e.type){var n,i=function(){t=1},r={id:e.session_id||Math.random().toString(36).substring(2),timestamp:new Date,isSent:!0,visible:!0,event:exports.EventType.TEXT,user_id:e.user_id,username:e.username,text:null!=(n=e.text)?n:"",speaker:"ai",session_id:e.session_id||"",suggestions:[]},o=function(){if(d.sessionStarted)return Promise.resolve(d.videoOutput.playCachedVideo(e.video_url||"")).then(function(){d.handleMessage(r)});d.cachedResponseQueue.push({video_url:e.video_url||"",textEventData:r})}();return o&&o.then?o.then(i):i()}}();return Promise.resolve(i&&i.then?i.then(n):n(i))}catch(e){return Promise.reject(e)}},this.handleVideoFrame=function(e){try{var t;return e.frame_data||h.videoFrameQueue.push({timeStamp:e.event_timestamp_ms,isKeyframe:null!=(t=e.is_keyframe)&&t}),Promise.resolve()}catch(e){return Promise.reject(e)}},this.handleBinaryData=function(e){try{if(v.videoFrameQueue.length>0){var t=v.videoFrameQueue.shift();v.updateStatus("connected"),v.videoOutput.addFrame(e.data,t.timeStamp,t.isKeyframe),v.syncController.updateVideoTime(t.timeStamp)}return Promise.resolve()}catch(e){return Promise.reject(e)}},this.handleAudioFrame=function(e){try{if(!e.frame_data)return console.warn("Audio frame data is missing in the event:",e),Promise.resolve();var t,n=function(e){for(var t=window.atob(e),n=t.length,i=new Uint8Array(n),r=0;r<n;r++)i[r]=t.charCodeAt(r);return i.buffer}(e.frame_data);return t=new Int16Array(n),y.audioOutput.gain.gain.value=y.volume,y.audioOutput.worklet.port.postMessage({type:"clearInterrupted"}),y.audioOutput.worklet.port.postMessage({type:"buffer",buffer:t,time_stamp:e.event_timestamp_ms}),y.syncController.updateAudioTime(e.event_timestamp_ms),Promise.resolve()}catch(e){return Promise.reject(e)}},this.onMessage=function(e){try{switch(e.event){case exports.EventType.JOIN:return Promise.resolve();case exports.EventType.TEXT:if(f(e)){var t=e;t.timestamp=new Date,t.isSent=!0,t.visible=!0,w.handleMessage(t)}return Promise.resolve();case exports.EventType.RESPONSE:if(m(e)){var n=e;n.timestamp=new Date,n.speaker="ai",n.isSent=!0,w.handleMessage(n)}return Promise.resolve();case exports.EventType.STREAMING:return p(e)&&w.handleStreamingEvent(e),Promise.resolve();case exports.EventType.BINARY:g(e)&&w.handleBinaryData(e);case exports.EventType.TIMEOUT_WARNING:return P(e)&&w.options.onTimeoutWarning(),Promise.resolve();case exports.EventType.TIME_OUT:return S(e)&&w.options.onTimeout(),Promise.resolve();case exports.EventType.KEEP_SESSION:return I(e)&&w.options.onKeepSession({granted:e.granted}),Promise.resolve();default:return console.warn("Unhandled event type:",e.event),Promise.resolve()}}catch(e){return Promise.reject(e)}},this.endSessionWithDetails=function(e){try{return"connected"!==E.status&&"connecting"!==E.status?Promise.resolve():(E.sessionStarted=!1,E.updateStatus("disconnecting"),Promise.resolve(E.handleEndSession()).then(function(){var t;E.updateStatus("disconnected"),null==(t=E.monitor)||t.stop(),E.options.onDisconnect(e)}))}catch(e){return Promise.reject(e)}},this.options=e,this.microphoneAccess=t,this.connection=n,this.idleVideo=i,this.wakeLock=r,this.user=o,this.audioOutput=s,this.videoOutput=a,this.headInfo=u,this.syncController=new b(L),this.avController=new l(this.syncController,this.audioOutput,this.videoOutput),this.options.onConnect({userId:n.userId,headInfo:{name:this.headInfo.name,phrases:this.headInfo.phrases,language:this.headInfo.language,avatar:this.headInfo.avatarSrc},microphoneAccess:t}),this.connection.onDisconnect(this.endSessionWithDetails),this.connection.onMessage(this.onMessage),this.videoOutput.onSpeakingStart(this.options.onSpeakingStart),this.videoOutput.onSpeakingEnd(this.options.onSpeakingEnd),this.updateStatus("connected"),this.audioOutput.worklet.port.onmessage=this.onOutputWorkletMessage,this.handleIOSSilentMode(),this.startLatencyMonitoring()}e.getFullOptions=function(e){return t({username:"anonymous",environment:"production",mode:"default",apiKey:"",onStatusChange:function(){},onConnect:function(){},onDisconnect:function(){},onMessage:function(){},onMuteStatusChange:function(){},onSpeakingStart:function(){},onSpeakingEnd:function(){},onStoppingEnd:function(){},onTimeout:function(){},onTimeoutWarning:function(){},onKeepSession:function(){},onError:function(){}},e)},e.startDigitalHuman=function(t){try{var n=function(){var n=w(o);return U(function(){return Promise.resolve(M.loginUser(r,"Password1",n,s,a)).then(function(r){return p=r,Promise.resolve(V.getIdleVideo(n,s,a)).then(function(r){return Promise.resolve(p.getHeadDetails(c)).then(function(l){return Promise.resolve(r.getAvatarSrc(n,s,a)).then(function(n){l.avatarSrc=n;var m=h||l.language||navigator.language;return l.language=m,Promise.resolve(T.create({environment:o,orgId:s,headId:a,token:p.accessToken,mode:u,apiKey:c,language:m})).then(function(n){function o(){return Promise.resolve(Promise.all([d.createAudioOutput(P),j.createVideoOutput(s,{width:s.getBoundingClientRect().width,height:s.getBoundingClientRect().height,frameRate:30,backgroundColor:"transparent",format:"jpeg",idleVideo:{src:r.idleVideoSource,enabled:!0},transition:null!=f?f:exports.VideoTransitionType.NONE})])).then(function(t){return new e(i,a,v,r,S,p,y=t[0],g=t[1],l)})}v=n;var s=t.element,a=!1,u=U(function(){return Promise.resolve(navigator.mediaDevices.getUserMedia({audio:!0})).then(function(e){e.getTracks().forEach(function(e){e.stop()}),a=!0})},function(){a=!1});return u&&u.then?u.then(o):o()})})})})})},function(e){var t,n;return m({status:"disconnected"}),null==(t=v)||t.close(),Promise.resolve(null==(n=y)?void 0:n.close()).then(function(){var t;return Promise.resolve(null==(t=g)?void 0:t.destroy()).then(function(){function t(){throw e}var n=U(function(){var e;return Promise.resolve(null==(e=S)?void 0:e.release()).then(function(){S=null})},function(){});return n&&n.then?n.then(t):t()})})})},i=e.getFullOptions(t),r=i.username,o=i.environment,s=i.orgId,a=i.headId,u=i.mode,c=i.apiKey,l=i.allowWakeLock,h=i.language,f=i.fadeTransitionsType,m=i.onStatusChange;m({status:"connecting"});var p=null,v=null,g=null,y=null,P={sampleRate:16e3,format:"pcm"},S=null,I=function(){if(null==l||l){var e=U(function(){return Promise.resolve(navigator.wakeLock.request("screen")).then(function(e){S=e})},function(){});if(e&&e.then)return e.then(function(){})}}();return Promise.resolve(I&&I.then?I.then(n):n())}catch(e){return Promise.reject(e)}},e.getBackgroundVideo=function(e){try{var t=e.environment,n=e.orgId,i=e.headId,r=w(null!=t?t:"production");return Promise.resolve(V.getIdleVideo(null!=r?r:"https://chat-origin.api.unith.live",n,i)).then(function(e){return e.idleVideoSource})}catch(e){return Promise.reject(e)}};var n=e.prototype;return n.startLatencyMonitoring=function(){this.monitor=new k(this.connection,{onUpdate:function(e){}})},n.handleIOSSilentMode=function(){var e=this;/iPad|iPhone|iPod/.test(navigator.userAgent)&&this.audioOutput.context.addEventListener("statechange",function(){"suspended"===e.audioOutput.context.state&&(console.warn("Audio context suspended - likely due to iOS silent mode"),e.audioOutput.context.resume())})},n.getUserId=function(){return this.connection.userId},n.handleEndSession=function(){try{return this.connection.close(),Promise.resolve()}catch(e){return Promise.reject(e)}},n.updateStatus=function(e){e!==this.status&&(this.status=e,this.options.onStatusChange({status:e}))},n.stopCurrentResponse=function(){this.avController.toggleStoppingVideo(!0),this.videoOutput.clearFrame(),this.audioOutput.worklet.port.postMessage({type:"stopPlayback"}),this.videoOutput.getStreamingStatus()||(this.options.onStoppingEnd(),this.avController.toggleStoppingVideo(!1))},n.toggleMuteStatus=function(){try{var e=this;return e.volume=0===e.volume?1:0,e.audioOutput.toggleMute(),e.videoOutput.toggleCacheVideoMute(),e.options.onMuteStatusChange({isMuted:0===e.volume}),Promise.resolve(e.volume)}catch(e){return Promise.reject(e)}},n.startSession=function(){try{var e=function(){return Promise.resolve(t.avController.startPlayback(!0)).then(function(){function e(){return t.connection}var n=function(){if(t.cachedResponseQueue.length){var e=t.cachedResponseQueue[t.cachedResponseQueue.length-1];return Promise.resolve(new Promise(function(e){return setTimeout(e,50)})).then(function(){return Promise.resolve(t.videoOutput.playCachedVideo(e.video_url)).then(function(){t.handleMessage(e.textEventData)})})}}();return n&&n.then?n.then(e):e()})},t=this;t.sessionStarted=!0;var n=function(){if("suspended"===t.audioOutput.context.state)return Promise.resolve(t.audioOutput.context.resume()).then(function(){})}();return Promise.resolve(n&&n.then?n.then(e):e())}catch(e){return Promise.reject(e)}},n.initializeMicrophone=function(){try{return Promise.resolve(this.user.getAsrToken())}catch(e){return Promise.reject(e)}},n.endSession=function(){return this.endSessionWithDetails({reason:"user"})},n.sendMessage=function(e){if(!this.connection)throw new Error("Connection not established");var t=this.user.id+"::"+this.user.orgId+"::"+this.user.headId+"::"+this.user.sessionId.toString().padStart(5,"0"),n={id:this.messageCounter++,timestamp:(new Date).toISOString(),speaker:"user",text:e,isSent:!1,user_id:this.user.id,username:this.user.username,event:exports.EventType.TEXT,visible:!0,session_id:t};return this.connection.sendMessage(n)},n.keepSession=function(){if(!this.connection)throw new Error("Connection not established");var e=this.user.id+"::"+this.user.orgId+"::"+this.user.headId+"::"+this.user.sessionId.toString().padStart(5,"0"),t={id:this.messageCounter,timestamp:(new Date).toISOString(),speaker:"user",text:"",isSent:!1,user_id:this.user.id,username:this.user.username,event:exports.EventType.KEEP_SESSION,visible:!0,session_id:e};return this.connection.sendMessage(t)},e}(),exports.isBinaryEvent=g,exports.isConversationEndEvent=function(e){return e.event===exports.EventType.CONVERSATION_END},exports.isJoinEvent=h,exports.isKeepSessionEvent=I,exports.isPongEvent=y,exports.isResponseEvent=m,exports.isStreamingErrorEvent=v,exports.isStreamingEvent=p,exports.isTextEvent=f,exports.isTimeoutEvent=S,exports.isTimeoutWarningEvent=P;
|
|
2
|
+
//# sourceMappingURL=lib.js.map
|