@skippr/live-agent-sdk 0.34.0 → 0.36.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 +8 -1
- package/dist/esm/lib-exports.js +501 -144
- package/dist/skippr-sdk.css +1 -1
- package/dist/skippr-sdk.js +146 -146
- package/dist/types/components/MeetingControls.d.ts +5 -1
- package/dist/types/components/StartSessionPrompt.d.ts +3 -1
- package/dist/types/context/LiveAgentContext.d.ts +24 -1
- package/dist/types/hooks/useLiveAgent.d.ts +1 -0
- package/dist/types/hooks/useSession.d.ts +8 -2
- package/dist/types/lib/react-compat.d.ts +26 -0
- package/dist/types/lib/session.d.ts +4 -0
- package/package.json +1 -1
package/dist/esm/lib-exports.js
CHANGED
|
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
|
|
9
9
|
// src/components/LiveAgent.tsx
|
|
10
10
|
import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
|
|
11
|
-
import { useCallback as useCallback8, useMemo as useMemo5, useState as useState11 } from "react";
|
|
11
|
+
import { useCallback as useCallback8, useMemo as useMemo5, useRef as useRef10, useState as useState11 } from "react";
|
|
12
12
|
|
|
13
13
|
// src/context/LiveAgentContext.tsx
|
|
14
14
|
import { createContext } from "react";
|
|
@@ -203,8 +203,41 @@ function useAvailableModules({
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
// src/hooks/useSession.ts
|
|
206
|
-
import { useCallback as useCallback3, useEffect as useEffect3, useState as useState3 } from "react";
|
|
206
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useRef, useState as useState3 } from "react";
|
|
207
207
|
var API_URL3 = "https://specialist.skippr.ai/api";
|
|
208
|
+
async function fetchSessionMessages(sessionId, bearerToken) {
|
|
209
|
+
try {
|
|
210
|
+
const resp = await fetch(`${API_URL3}/v1/sessions/${sessionId}/messages`, {
|
|
211
|
+
credentials: "omit",
|
|
212
|
+
headers: { Authorization: `Bearer ${bearerToken}` }
|
|
213
|
+
});
|
|
214
|
+
if (!resp.ok)
|
|
215
|
+
return [];
|
|
216
|
+
const { messages } = await resp.json();
|
|
217
|
+
return messages.filter((message) => message.role !== "system").map((message) => ({
|
|
218
|
+
id: message.id,
|
|
219
|
+
role: message.role === "user" ? "user" : "assistant",
|
|
220
|
+
content: message.content,
|
|
221
|
+
source: "chat",
|
|
222
|
+
timestamp: new Date(message.createdAt).getTime()
|
|
223
|
+
}));
|
|
224
|
+
} catch {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async function requestScreenShare() {
|
|
229
|
+
try {
|
|
230
|
+
return await navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: "browser" } });
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function stopStream(stream) {
|
|
236
|
+
if (!stream)
|
|
237
|
+
return;
|
|
238
|
+
for (const track of stream.getTracks())
|
|
239
|
+
track.stop();
|
|
240
|
+
}
|
|
208
241
|
async function exchangeForBearerToken(appKey, userToken) {
|
|
209
242
|
const resp = await fetch(`${API_URL3}/v1/auth/token-exchange`, {
|
|
210
243
|
method: "POST",
|
|
@@ -238,6 +271,9 @@ function useSession({
|
|
|
238
271
|
const [sessionId, setSessionId] = useState3(null);
|
|
239
272
|
const [bearerToken, setBearerToken] = useState3(authToken ?? null);
|
|
240
273
|
const [pendingScreenStream, setPendingScreenStream] = useState3(null);
|
|
274
|
+
const [isPaused, setIsPaused] = useState3(false);
|
|
275
|
+
const [isPausing, setIsPausing] = useState3(false);
|
|
276
|
+
const [historyMessages, setHistoryMessages] = useState3([]);
|
|
241
277
|
useEffect3(() => {
|
|
242
278
|
let stale = false;
|
|
243
279
|
if (authToken) {
|
|
@@ -257,12 +293,29 @@ function useSession({
|
|
|
257
293
|
stale = true;
|
|
258
294
|
};
|
|
259
295
|
}, [authToken, appKey, userToken]);
|
|
260
|
-
const
|
|
296
|
+
const pauseOnUnloadRef = useRef(null);
|
|
297
|
+
pauseOnUnloadRef.current = connection !== null && !isPaused && sessionId && bearerToken ? { sessionId, bearerToken } : null;
|
|
298
|
+
useEffect3(() => {
|
|
299
|
+
const onPageHide = () => {
|
|
300
|
+
const pending = pauseOnUnloadRef.current;
|
|
301
|
+
if (!pending)
|
|
302
|
+
return;
|
|
303
|
+
fetch(`${API_URL3}/v1/sessions/${pending.sessionId}/pause`, {
|
|
304
|
+
method: "POST",
|
|
305
|
+
credentials: "omit",
|
|
306
|
+
keepalive: true,
|
|
307
|
+
headers: { Authorization: `Bearer ${pending.bearerToken}` }
|
|
308
|
+
}).catch(() => {});
|
|
309
|
+
};
|
|
310
|
+
window.addEventListener("pagehide", onPageHide);
|
|
311
|
+
return () => window.removeEventListener("pagehide", onPageHide);
|
|
312
|
+
}, []);
|
|
313
|
+
const startSession = useCallback3(async ({ agentId, agentControls, existingSessionId }) => {
|
|
261
314
|
if (!bearerToken) {
|
|
262
315
|
setError("No auth token available");
|
|
263
316
|
return;
|
|
264
317
|
}
|
|
265
|
-
if (!agentId) {
|
|
318
|
+
if (!agentId && !existingSessionId) {
|
|
266
319
|
setError("No agent selected");
|
|
267
320
|
return;
|
|
268
321
|
}
|
|
@@ -272,84 +325,109 @@ function useSession({
|
|
|
272
325
|
onStart?.();
|
|
273
326
|
let screenStream = null;
|
|
274
327
|
if (captureMode === "screenshare") {
|
|
275
|
-
|
|
276
|
-
screenStream = await navigator.mediaDevices.getDisplayMedia({
|
|
277
|
-
video: { displaySurface: "browser" }
|
|
278
|
-
});
|
|
279
|
-
} catch {
|
|
280
|
-
screenStream = null;
|
|
281
|
-
}
|
|
328
|
+
screenStream = await requestScreenShare();
|
|
282
329
|
}
|
|
283
330
|
const requestAgentControls = agentControls?.highlight === true ? { highlight: true } : undefined;
|
|
284
331
|
const headers = { Authorization: `Bearer ${bearerToken}` };
|
|
285
332
|
try {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
333
|
+
let resolvedSessionId = existingSessionId;
|
|
334
|
+
if (!resolvedSessionId) {
|
|
335
|
+
const createResp = await fetch(`${API_URL3}/v1/sessions`, {
|
|
336
|
+
method: "POST",
|
|
337
|
+
credentials: "omit",
|
|
338
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
339
|
+
body: JSON.stringify({
|
|
340
|
+
agentId,
|
|
341
|
+
captureMode,
|
|
342
|
+
agentControls: requestAgentControls
|
|
343
|
+
})
|
|
344
|
+
});
|
|
345
|
+
if (!createResp.ok) {
|
|
346
|
+
const body = await createResp.json().catch(() => null);
|
|
347
|
+
setErrorCode(createResp.status);
|
|
348
|
+
throw new Error(body?.detail || `Failed to create session: ${createResp.status}`);
|
|
349
|
+
}
|
|
350
|
+
const { session: session2 } = await createResp.json();
|
|
351
|
+
resolvedSessionId = session2.id;
|
|
300
352
|
}
|
|
301
|
-
const
|
|
302
|
-
const startResp = await fetch(`${API_URL3}/v1/sessions/${session.id}/start`, {
|
|
353
|
+
const startResp = await fetch(`${API_URL3}/v1/sessions/${resolvedSessionId}/start`, {
|
|
303
354
|
method: "POST",
|
|
304
355
|
credentials: "omit",
|
|
305
|
-
headers
|
|
356
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
357
|
+
body: JSON.stringify({ captureMode, agentControls: requestAgentControls })
|
|
306
358
|
});
|
|
307
359
|
if (!startResp.ok) {
|
|
308
360
|
const body = await startResp.json().catch(() => null);
|
|
309
361
|
setErrorCode(startResp.status);
|
|
310
362
|
throw new Error(body?.detail || `Failed to start session: ${startResp.status}`);
|
|
311
363
|
}
|
|
312
|
-
const { connection: conn } = await startResp.json();
|
|
364
|
+
const { session, connection: conn } = await startResp.json();
|
|
365
|
+
const history2 = existingSessionId ? await fetchSessionMessages(session.id, bearerToken) : [];
|
|
313
366
|
setSessionId(session.id);
|
|
367
|
+
setHistoryMessages(history2);
|
|
314
368
|
setConnection({
|
|
315
369
|
livekitUrl: conn.livekitUrl,
|
|
316
370
|
token: conn.token
|
|
317
371
|
});
|
|
318
372
|
setPendingScreenStream(screenStream);
|
|
319
373
|
setShouldConnect(true);
|
|
374
|
+
setIsPaused(false);
|
|
320
375
|
} catch (e) {
|
|
321
|
-
|
|
322
|
-
for (const track of screenStream.getTracks())
|
|
323
|
-
track.stop();
|
|
324
|
-
}
|
|
376
|
+
stopStream(screenStream);
|
|
325
377
|
setError(e instanceof Error ? e.message : "Failed to start session");
|
|
326
378
|
onStartError?.();
|
|
327
379
|
} finally {
|
|
328
380
|
setIsStarting(false);
|
|
329
381
|
}
|
|
330
382
|
}, [captureMode, bearerToken, onStart, onStartError]);
|
|
383
|
+
const pauseSession = useCallback3(async () => {
|
|
384
|
+
if (!sessionId || !bearerToken)
|
|
385
|
+
return;
|
|
386
|
+
setIsPausing(true);
|
|
387
|
+
try {
|
|
388
|
+
const resp = await fetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
|
|
389
|
+
method: "POST",
|
|
390
|
+
credentials: "omit",
|
|
391
|
+
headers: { Authorization: `Bearer ${bearerToken}` }
|
|
392
|
+
});
|
|
393
|
+
if (!resp.ok) {
|
|
394
|
+
const body = await resp.json().catch(() => null);
|
|
395
|
+
throw new Error(body?.detail || `Failed to pause: ${resp.status}`);
|
|
396
|
+
}
|
|
397
|
+
} catch (e) {
|
|
398
|
+
setError(e instanceof Error ? e.message : "Failed to pause session");
|
|
399
|
+
setIsPausing(false);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const history2 = await fetchSessionMessages(sessionId, bearerToken);
|
|
403
|
+
stopStream(pendingScreenStream);
|
|
404
|
+
setPendingScreenStream(null);
|
|
405
|
+
setShouldConnect(false);
|
|
406
|
+
setConnection(null);
|
|
407
|
+
setHistoryMessages(history2);
|
|
408
|
+
setIsPaused(true);
|
|
409
|
+
setIsPausing(false);
|
|
410
|
+
}, [sessionId, bearerToken, pendingScreenStream]);
|
|
331
411
|
const disconnect = useCallback3(async () => {
|
|
332
412
|
setIsDisconnecting(true);
|
|
333
413
|
try {
|
|
334
414
|
if (sessionId && bearerToken) {
|
|
335
415
|
try {
|
|
336
|
-
await fetch(`${API_URL3}/v1/sessions/${sessionId}/
|
|
416
|
+
await fetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
|
|
337
417
|
method: "POST",
|
|
338
418
|
credentials: "omit",
|
|
339
|
-
headers: {
|
|
340
|
-
body: JSON.stringify({})
|
|
419
|
+
headers: { Authorization: `Bearer ${bearerToken}` }
|
|
341
420
|
});
|
|
342
421
|
} catch {}
|
|
343
422
|
}
|
|
344
|
-
|
|
345
|
-
for (const track of pendingScreenStream.getTracks())
|
|
346
|
-
track.stop();
|
|
347
|
-
}
|
|
423
|
+
stopStream(pendingScreenStream);
|
|
348
424
|
setError("");
|
|
349
425
|
setShouldConnect(false);
|
|
350
426
|
setConnection(null);
|
|
351
427
|
setSessionId(null);
|
|
352
428
|
setPendingScreenStream(null);
|
|
429
|
+
setHistoryMessages([]);
|
|
430
|
+
setIsPaused(false);
|
|
353
431
|
onDisconnect?.();
|
|
354
432
|
} finally {
|
|
355
433
|
setIsDisconnecting(false);
|
|
@@ -363,7 +441,11 @@ function useSession({
|
|
|
363
441
|
error,
|
|
364
442
|
errorCode,
|
|
365
443
|
startSession,
|
|
444
|
+
pauseSession,
|
|
366
445
|
disconnect,
|
|
446
|
+
isPaused,
|
|
447
|
+
isPausing,
|
|
448
|
+
historyMessages,
|
|
367
449
|
pendingScreenStream,
|
|
368
450
|
bearerToken
|
|
369
451
|
};
|
|
@@ -379,14 +461,35 @@ var DOM_EVENTS_TOPIC = "skippr.dom-events";
|
|
|
379
461
|
var HIGHLIGHT_TOPIC = "skippr.highlight";
|
|
380
462
|
var NAME_MAX_CHARS = 80;
|
|
381
463
|
|
|
464
|
+
// src/lib/session.ts
|
|
465
|
+
function getResumableSessionId(currentSession, mode) {
|
|
466
|
+
if (!currentSession)
|
|
467
|
+
return;
|
|
468
|
+
const { id, status } = currentSession;
|
|
469
|
+
if (status === "paused" || status === "active")
|
|
470
|
+
return id;
|
|
471
|
+
if (status === "expired" && mode === "always_on")
|
|
472
|
+
return id;
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
function canResumeSession(currentSession, mode) {
|
|
476
|
+
return getResumableSessionId(currentSession, mode) !== undefined;
|
|
477
|
+
}
|
|
478
|
+
function getResumableSession(module) {
|
|
479
|
+
if (!module)
|
|
480
|
+
return null;
|
|
481
|
+
const id = getResumableSessionId(module.currentSession, module.mode);
|
|
482
|
+
return id ? { id, agentId: module.id } : null;
|
|
483
|
+
}
|
|
484
|
+
|
|
382
485
|
// src/components/AutoStartMedia.tsx
|
|
383
486
|
import { useConnectionState, useLocalParticipant } from "@livekit/components-react/hooks";
|
|
384
487
|
import { ConnectionState, Track } from "livekit-client";
|
|
385
|
-
import { useEffect as useEffect4, useRef } from "react";
|
|
488
|
+
import { useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
386
489
|
function AutoStartMedia({ pendingScreenStream }) {
|
|
387
490
|
const { localParticipant } = useLocalParticipant();
|
|
388
491
|
const connectionState = useConnectionState();
|
|
389
|
-
const didStartRef =
|
|
492
|
+
const didStartRef = useRef2(false);
|
|
390
493
|
useEffect4(() => {
|
|
391
494
|
if (didStartRef.current)
|
|
392
495
|
return;
|
|
@@ -412,7 +515,7 @@ function AutoStartMedia({ pendingScreenStream }) {
|
|
|
412
515
|
// src/components/DomCapture.tsx
|
|
413
516
|
import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
|
|
414
517
|
import { ConnectionState as ConnectionState2, ScreenSharePresets, Track as Track2 } from "livekit-client";
|
|
415
|
-
import { useEffect as useEffect5, useRef as
|
|
518
|
+
import { useEffect as useEffect5, useRef as useRef3 } from "react";
|
|
416
519
|
|
|
417
520
|
// src/capture/a11yUtils.ts
|
|
418
521
|
var ROLE_BY_TAG = {
|
|
@@ -1159,7 +1262,7 @@ async function unpublishAndStopTrack(localParticipant, videoTrack) {
|
|
|
1159
1262
|
function DomCapture() {
|
|
1160
1263
|
const { localParticipant } = useLocalParticipant2();
|
|
1161
1264
|
const connectionState = useConnectionState2();
|
|
1162
|
-
const didStartRef =
|
|
1265
|
+
const didStartRef = useRef3(false);
|
|
1163
1266
|
useEffect5(() => {
|
|
1164
1267
|
if (didStartRef.current)
|
|
1165
1268
|
return;
|
|
@@ -1499,8 +1602,14 @@ var __iconNode18 = [
|
|
|
1499
1602
|
]
|
|
1500
1603
|
];
|
|
1501
1604
|
var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode18);
|
|
1502
|
-
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/
|
|
1605
|
+
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/pause.js
|
|
1503
1606
|
var __iconNode19 = [
|
|
1607
|
+
["rect", { x: "14", y: "3", width: "5", height: "18", rx: "1", key: "kaeet6" }],
|
|
1608
|
+
["rect", { x: "5", y: "3", width: "5", height: "18", rx: "1", key: "1wsw3u" }]
|
|
1609
|
+
];
|
|
1610
|
+
var Pause = createLucideIcon("pause", __iconNode19);
|
|
1611
|
+
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
|
|
1612
|
+
var __iconNode20 = [
|
|
1504
1613
|
[
|
|
1505
1614
|
"path",
|
|
1506
1615
|
{
|
|
@@ -1517,9 +1626,20 @@ var __iconNode19 = [
|
|
|
1517
1626
|
}
|
|
1518
1627
|
]
|
|
1519
1628
|
];
|
|
1520
|
-
var PhoneOff = createLucideIcon("phone-off",
|
|
1629
|
+
var PhoneOff = createLucideIcon("phone-off", __iconNode20);
|
|
1630
|
+
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/play.js
|
|
1631
|
+
var __iconNode21 = [
|
|
1632
|
+
[
|
|
1633
|
+
"path",
|
|
1634
|
+
{
|
|
1635
|
+
d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",
|
|
1636
|
+
key: "10ikf1"
|
|
1637
|
+
}
|
|
1638
|
+
]
|
|
1639
|
+
];
|
|
1640
|
+
var Play = createLucideIcon("play", __iconNode21);
|
|
1521
1641
|
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/rocket.js
|
|
1522
|
-
var
|
|
1642
|
+
var __iconNode22 = [
|
|
1523
1643
|
["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5", key: "qeys4" }],
|
|
1524
1644
|
[
|
|
1525
1645
|
"path",
|
|
@@ -1537,9 +1657,9 @@ var __iconNode20 = [
|
|
|
1537
1657
|
],
|
|
1538
1658
|
["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05", key: "92ym6u" }]
|
|
1539
1659
|
];
|
|
1540
|
-
var Rocket = createLucideIcon("rocket",
|
|
1660
|
+
var Rocket = createLucideIcon("rocket", __iconNode22);
|
|
1541
1661
|
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
|
|
1542
|
-
var
|
|
1662
|
+
var __iconNode23 = [
|
|
1543
1663
|
[
|
|
1544
1664
|
"path",
|
|
1545
1665
|
{
|
|
@@ -1549,17 +1669,17 @@ var __iconNode21 = [
|
|
|
1549
1669
|
],
|
|
1550
1670
|
["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
|
|
1551
1671
|
];
|
|
1552
|
-
var Send = createLucideIcon("send",
|
|
1672
|
+
var Send = createLucideIcon("send", __iconNode23);
|
|
1553
1673
|
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/user-plus.js
|
|
1554
|
-
var
|
|
1674
|
+
var __iconNode24 = [
|
|
1555
1675
|
["path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" }],
|
|
1556
1676
|
["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }],
|
|
1557
1677
|
["line", { x1: "19", x2: "19", y1: "8", y2: "14", key: "1bvyxn" }],
|
|
1558
1678
|
["line", { x1: "22", x2: "16", y1: "11", y2: "11", key: "1shjgl" }]
|
|
1559
1679
|
];
|
|
1560
|
-
var UserPlus = createLucideIcon("user-plus",
|
|
1680
|
+
var UserPlus = createLucideIcon("user-plus", __iconNode24);
|
|
1561
1681
|
// src/components/HighlightOverlay.tsx
|
|
1562
|
-
import { useCallback as useCallback4, useEffect as useEffect6, useRef as
|
|
1682
|
+
import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef4, useState as useState4 } from "react";
|
|
1563
1683
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1564
1684
|
var Z_INDEX = 2147483646;
|
|
1565
1685
|
var HIGHLIGHT_PADDING = 6;
|
|
@@ -1664,8 +1784,8 @@ function findScrollableAncestor(el) {
|
|
|
1664
1784
|
}
|
|
1665
1785
|
function HighlightOverlay() {
|
|
1666
1786
|
const [overlayState, setOverlayState] = useState4(null);
|
|
1667
|
-
const targetElementRef =
|
|
1668
|
-
const pendingFrameRef =
|
|
1787
|
+
const targetElementRef = useRef4(null);
|
|
1788
|
+
const pendingFrameRef = useRef4(null);
|
|
1669
1789
|
const clearOverlay = useCallback4(() => {
|
|
1670
1790
|
targetElementRef.current = null;
|
|
1671
1791
|
setOverlayState(null);
|
|
@@ -1792,14 +1912,27 @@ function HighlightOverlay() {
|
|
|
1792
1912
|
// src/components/MinimizedBubble.tsx
|
|
1793
1913
|
import { useEffect as useEffect7 } from "react";
|
|
1794
1914
|
|
|
1915
|
+
// src/lib/react-compat.ts
|
|
1916
|
+
import * as React from "react";
|
|
1917
|
+
function selectContextHook(use2, useContext3) {
|
|
1918
|
+
return use2 ?? useContext3;
|
|
1919
|
+
}
|
|
1920
|
+
var useContextValue = selectContextHook(React.use, React.useContext);
|
|
1921
|
+
|
|
1795
1922
|
// src/hooks/useLiveAgent.ts
|
|
1796
|
-
import { use } from "react";
|
|
1797
1923
|
function useLiveAgent() {
|
|
1798
|
-
const ctx =
|
|
1924
|
+
const ctx = useContextValue(LiveAgentContext);
|
|
1799
1925
|
if (!ctx) {
|
|
1800
1926
|
throw new Error("useLiveAgent must be used within a <LiveAgent> provider");
|
|
1801
1927
|
}
|
|
1802
|
-
const {
|
|
1928
|
+
const {
|
|
1929
|
+
connection,
|
|
1930
|
+
shouldConnect,
|
|
1931
|
+
historyMessages,
|
|
1932
|
+
phasesSnapshot,
|
|
1933
|
+
setPhasesSnapshot,
|
|
1934
|
+
...publicValue
|
|
1935
|
+
} = ctx;
|
|
1803
1936
|
return publicValue;
|
|
1804
1937
|
}
|
|
1805
1938
|
|
|
@@ -1861,14 +1994,29 @@ function pillStatusFromAgent(state, canSeePage) {
|
|
|
1861
1994
|
return canSeePage ? "observing" : "connected";
|
|
1862
1995
|
}
|
|
1863
1996
|
function LauncherStatusPill() {
|
|
1864
|
-
const { isConnected, isStarting, expandPanel, setSidebarTab, position, captureMode } = useLiveAgent();
|
|
1997
|
+
const { isConnected, isStarting, isPaused, expandPanel, setSidebarTab, position, captureMode } = useLiveAgent();
|
|
1865
1998
|
const { state } = useAgentVoiceState();
|
|
1866
1999
|
const { isScreenSharing } = useMediaControls();
|
|
1867
2000
|
const isStandingBy = isStarting && !isConnected;
|
|
1868
|
-
if (!isConnected && !isStandingBy)
|
|
2001
|
+
if (!isConnected && !isStandingBy && !isPaused)
|
|
1869
2002
|
return null;
|
|
1870
2003
|
const canSeePage = captureMode === "auto" || isScreenSharing;
|
|
1871
|
-
|
|
2004
|
+
let status;
|
|
2005
|
+
if (isPaused) {
|
|
2006
|
+
status = "paused";
|
|
2007
|
+
} else if (isStandingBy) {
|
|
2008
|
+
status = "standing-by";
|
|
2009
|
+
} else {
|
|
2010
|
+
status = pillStatusFromAgent(state, canSeePage);
|
|
2011
|
+
}
|
|
2012
|
+
let ariaLabel;
|
|
2013
|
+
if (isStandingBy) {
|
|
2014
|
+
ariaLabel = "Skippr is standing by — click to open";
|
|
2015
|
+
} else if (isPaused) {
|
|
2016
|
+
ariaLabel = "Session paused — click to open";
|
|
2017
|
+
} else {
|
|
2018
|
+
ariaLabel = `Skippr is ${status} — click to open chat`;
|
|
2019
|
+
}
|
|
1872
2020
|
const handleClick = () => {
|
|
1873
2021
|
if (!isStandingBy)
|
|
1874
2022
|
setSidebarTab("chat");
|
|
@@ -1878,7 +2026,7 @@ function LauncherStatusPill() {
|
|
|
1878
2026
|
type: "button",
|
|
1879
2027
|
onClick: handleClick,
|
|
1880
2028
|
className: cn("skippr:fixed skippr:bottom-20 skippr:z-[9999]", "skippr:flex skippr:items-center skippr:gap-2", "skippr:rounded-full skippr:bg-bubble/95 skippr:backdrop-blur-sm", "skippr:px-3 skippr:py-1.5", "skippr:text-xs skippr:font-medium skippr:text-white", "skippr:shadow-[0_8px_24px_rgba(45,43,61,0.35)]", "skippr:cursor-pointer skippr:transition-colors skippr:hover:bg-bubble", "skippr:animate-[skippr-bubble-in_0.28s_ease-out]", position === "right" ? "skippr:right-6" : "skippr:left-6"),
|
|
1881
|
-
"aria-label":
|
|
2029
|
+
"aria-label": ariaLabel,
|
|
1882
2030
|
children: /* @__PURE__ */ jsxs2("span", {
|
|
1883
2031
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:animate-[skippr-pill-content_0.22s_ease-out]",
|
|
1884
2032
|
children: [
|
|
@@ -1921,6 +2069,14 @@ function LauncherStatusPill() {
|
|
|
1921
2069
|
children: "Skippr is thinking"
|
|
1922
2070
|
})
|
|
1923
2071
|
]
|
|
2072
|
+
}),
|
|
2073
|
+
status === "paused" && /* @__PURE__ */ jsxs2(Fragment, {
|
|
2074
|
+
children: [
|
|
2075
|
+
/* @__PURE__ */ jsx2(PausedDot, {}),
|
|
2076
|
+
/* @__PURE__ */ jsx2("span", {
|
|
2077
|
+
children: "Session paused"
|
|
2078
|
+
})
|
|
2079
|
+
]
|
|
1924
2080
|
})
|
|
1925
2081
|
]
|
|
1926
2082
|
}, status)
|
|
@@ -1939,6 +2095,11 @@ function ConnectedDot() {
|
|
|
1939
2095
|
]
|
|
1940
2096
|
});
|
|
1941
2097
|
}
|
|
2098
|
+
function PausedDot() {
|
|
2099
|
+
return /* @__PURE__ */ jsx2("span", {
|
|
2100
|
+
className: "skippr:inline-flex skippr:size-2 skippr:rounded-full skippr:bg-amber-400"
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
1942
2103
|
function ObservingIcon() {
|
|
1943
2104
|
return /* @__PURE__ */ jsxs2("svg", {
|
|
1944
2105
|
viewBox: "0 0 24 24",
|
|
@@ -2090,34 +2251,60 @@ import { jsx as jsx4, jsxs as jsxs4, Fragment as Fragment2 } from "react/jsx-run
|
|
|
2090
2251
|
var CONTROL_BUTTON = "skippr:flex skippr:size-12 skippr:items-center skippr:justify-center skippr:rounded-[14px] skippr:cursor-pointer skippr:transition-all skippr:hover:-translate-y-0.5 skippr:active:translate-y-0";
|
|
2091
2252
|
var CONTROL_SHADOW = "skippr:shadow-[0_4px_16px_rgba(0,0,0,0.15),0_2px_4px_rgba(0,0,0,0.1)]";
|
|
2092
2253
|
function ConnectedLauncher() {
|
|
2093
|
-
const {
|
|
2254
|
+
const {
|
|
2255
|
+
expandPanel,
|
|
2256
|
+
disconnect,
|
|
2257
|
+
pauseSession,
|
|
2258
|
+
resumeSession,
|
|
2259
|
+
isPaused,
|
|
2260
|
+
isPausing,
|
|
2261
|
+
captureMode,
|
|
2262
|
+
setSidebarTab
|
|
2263
|
+
} = useLiveAgent();
|
|
2094
2264
|
const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
|
|
2095
2265
|
const showScreenShareToggle = captureMode === "screenshare";
|
|
2266
|
+
const showPaused = isPaused || isPausing;
|
|
2096
2267
|
const openChat = () => {
|
|
2097
2268
|
setSidebarTab("chat");
|
|
2098
2269
|
expandPanel();
|
|
2099
2270
|
};
|
|
2100
2271
|
return /* @__PURE__ */ jsxs4(Fragment2, {
|
|
2101
2272
|
children: [
|
|
2102
|
-
/* @__PURE__ */
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2273
|
+
!showPaused && /* @__PURE__ */ jsxs4(Fragment2, {
|
|
2274
|
+
children: [
|
|
2275
|
+
/* @__PURE__ */ jsx4("button", {
|
|
2276
|
+
type: "button",
|
|
2277
|
+
onClick: toggleMute,
|
|
2278
|
+
"aria-label": isMuted ? "Unmute" : "Mute",
|
|
2279
|
+
className: cn(CONTROL_BUTTON, CONTROL_SHADOW, isMuted ? "skippr:bg-destructive/10 skippr:text-destructive skippr:hover:bg-destructive/20" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
|
|
2280
|
+
children: isMuted ? /* @__PURE__ */ jsx4(MicOff, {
|
|
2281
|
+
className: "skippr:size-5"
|
|
2282
|
+
}) : /* @__PURE__ */ jsx4(Mic, {
|
|
2283
|
+
className: "skippr:size-5"
|
|
2284
|
+
})
|
|
2285
|
+
}),
|
|
2286
|
+
showScreenShareToggle && /* @__PURE__ */ jsx4("button", {
|
|
2287
|
+
type: "button",
|
|
2288
|
+
onClick: toggleScreenShare,
|
|
2289
|
+
"aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
|
|
2290
|
+
className: cn(CONTROL_BUTTON, CONTROL_SHADOW, isScreenSharing ? "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90" : "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted"),
|
|
2291
|
+
children: isScreenSharing ? /* @__PURE__ */ jsx4(MonitorOff, {
|
|
2292
|
+
className: "skippr:size-5"
|
|
2293
|
+
}) : /* @__PURE__ */ jsx4(Monitor, {
|
|
2294
|
+
className: "skippr:size-5"
|
|
2295
|
+
})
|
|
2296
|
+
})
|
|
2297
|
+
]
|
|
2112
2298
|
}),
|
|
2113
|
-
|
|
2299
|
+
/* @__PURE__ */ jsx4("button", {
|
|
2114
2300
|
type: "button",
|
|
2115
|
-
onClick:
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2301
|
+
onClick: () => isPaused ? resumeSession() : pauseSession(),
|
|
2302
|
+
disabled: isPausing,
|
|
2303
|
+
"aria-label": showPaused ? "Resume session" : "Pause session",
|
|
2304
|
+
className: cn(CONTROL_BUTTON, CONTROL_SHADOW, "skippr:bg-white skippr:text-foreground skippr:hover:bg-muted skippr:disabled:opacity-60"),
|
|
2305
|
+
children: showPaused ? /* @__PURE__ */ jsx4(Play, {
|
|
2119
2306
|
className: "skippr:size-5"
|
|
2120
|
-
}) : /* @__PURE__ */ jsx4(
|
|
2307
|
+
}) : /* @__PURE__ */ jsx4(Pause, {
|
|
2121
2308
|
className: "skippr:size-5"
|
|
2122
2309
|
})
|
|
2123
2310
|
}),
|
|
@@ -2130,7 +2317,7 @@ function ConnectedLauncher() {
|
|
|
2130
2317
|
className: "skippr:size-5"
|
|
2131
2318
|
})
|
|
2132
2319
|
}),
|
|
2133
|
-
/* @__PURE__ */ jsx4("button", {
|
|
2320
|
+
!showPaused && /* @__PURE__ */ jsx4("button", {
|
|
2134
2321
|
type: "button",
|
|
2135
2322
|
onClick: openChat,
|
|
2136
2323
|
"aria-label": "Open chat",
|
|
@@ -2181,8 +2368,8 @@ function MinimizedBubble({
|
|
|
2181
2368
|
welcomeDismissed,
|
|
2182
2369
|
onDismissWelcome
|
|
2183
2370
|
}) {
|
|
2184
|
-
const { isConnected, isStarting, position } = useLiveAgent();
|
|
2185
|
-
const inSession = isConnected;
|
|
2371
|
+
const { isConnected, isStarting, isPaused, isPausing, position } = useLiveAgent();
|
|
2372
|
+
const inSession = isConnected || isPaused || isPausing;
|
|
2186
2373
|
return /* @__PURE__ */ jsxs4(Fragment2, {
|
|
2187
2374
|
children: [
|
|
2188
2375
|
/* @__PURE__ */ jsx4(LauncherStatusPill, {}),
|
|
@@ -2202,7 +2389,7 @@ function MinimizedBubble({
|
|
|
2202
2389
|
}
|
|
2203
2390
|
|
|
2204
2391
|
// src/components/Sidebar.tsx
|
|
2205
|
-
import { useEffect as
|
|
2392
|
+
import { useEffect as useEffect16 } from "react";
|
|
2206
2393
|
|
|
2207
2394
|
// src/hooks/useCombinedMessages.ts
|
|
2208
2395
|
import { useMemo as useMemo4 } from "react";
|
|
@@ -2273,18 +2460,25 @@ function useCombinedMessages() {
|
|
|
2273
2460
|
const { transcriptMessages } = useStreamingTranscript();
|
|
2274
2461
|
const { chatMessages, sendChatMessage, isSendingChat } = useChatMessages();
|
|
2275
2462
|
const { state: agentState } = useAgentVoiceState();
|
|
2276
|
-
const
|
|
2463
|
+
const historyMessages = useContextValue(LiveAgentContext)?.historyMessages ?? [];
|
|
2464
|
+
const liveMessages = useMemo4(() => {
|
|
2277
2465
|
if (chatMessages.length === 0)
|
|
2278
2466
|
return transcriptMessages;
|
|
2279
2467
|
if (transcriptMessages.length === 0)
|
|
2280
2468
|
return chatMessages;
|
|
2281
2469
|
return mergeChatsIntoTranscripts(transcriptMessages, chatMessages);
|
|
2282
2470
|
}, [transcriptMessages, chatMessages]);
|
|
2471
|
+
const allMessages = useMemo4(() => {
|
|
2472
|
+
if (historyMessages.length === 0)
|
|
2473
|
+
return liveMessages;
|
|
2474
|
+
const seenIds = new Set(liveMessages.map((message) => message.id));
|
|
2475
|
+
return [...historyMessages.filter((message) => !seenIds.has(message.id)), ...liveMessages];
|
|
2476
|
+
}, [historyMessages, liveMessages]);
|
|
2283
2477
|
return { allMessages, agentState, sendChatMessage, isSendingChat };
|
|
2284
2478
|
}
|
|
2285
2479
|
|
|
2286
2480
|
// src/hooks/usePhaseUpdates.ts
|
|
2287
|
-
import { useCallback as useCallback6 } from "react";
|
|
2481
|
+
import { useCallback as useCallback6, useEffect as useEffect9 } from "react";
|
|
2288
2482
|
|
|
2289
2483
|
// src/hooks/useAgentState.ts
|
|
2290
2484
|
import { useRemoteParticipants } from "@livekit/components-react/hooks";
|
|
@@ -2339,12 +2533,18 @@ function parsePhases(json) {
|
|
|
2339
2533
|
}
|
|
2340
2534
|
function usePhaseUpdates() {
|
|
2341
2535
|
const parse = useCallback6(parsePhases, []);
|
|
2342
|
-
const
|
|
2536
|
+
const livePhases = useAgentState("phases", parse, []);
|
|
2537
|
+
const ctx = useContextValue(LiveAgentContext);
|
|
2538
|
+
useEffect9(() => {
|
|
2539
|
+
if (livePhases.length > 0)
|
|
2540
|
+
ctx?.setPhasesSnapshot(livePhases);
|
|
2541
|
+
}, [livePhases, ctx?.setPhasesSnapshot]);
|
|
2542
|
+
const phases = livePhases.length > 0 ? livePhases : ctx?.phasesSnapshot ?? [];
|
|
2343
2543
|
return { phases };
|
|
2344
2544
|
}
|
|
2345
2545
|
|
|
2346
2546
|
// src/hooks/useSessionRemaining.ts
|
|
2347
|
-
import { useEffect as
|
|
2547
|
+
import { useEffect as useEffect10, useRef as useRef5, useState as useState6 } from "react";
|
|
2348
2548
|
|
|
2349
2549
|
// src/lib/format.ts
|
|
2350
2550
|
function formatTime(seconds) {
|
|
@@ -2360,9 +2560,9 @@ function parseNumber(s) {
|
|
|
2360
2560
|
// src/hooks/useSessionRemaining.ts
|
|
2361
2561
|
function useSessionRemaining() {
|
|
2362
2562
|
const maxCallDuration = useAgentState("maxCallDuration", parseNumber, null);
|
|
2363
|
-
const endTimeRef =
|
|
2563
|
+
const endTimeRef = useRef5(null);
|
|
2364
2564
|
const [remaining, setRemaining] = useState6(null);
|
|
2365
|
-
|
|
2565
|
+
useEffect10(() => {
|
|
2366
2566
|
if (maxCallDuration === null || endTimeRef.current !== null)
|
|
2367
2567
|
return;
|
|
2368
2568
|
const endTime = Date.now() + maxCallDuration * 1000;
|
|
@@ -2379,10 +2579,10 @@ function useSessionRemaining() {
|
|
|
2379
2579
|
}
|
|
2380
2580
|
|
|
2381
2581
|
// src/hooks/useElapsedSeconds.ts
|
|
2382
|
-
import { useEffect as
|
|
2582
|
+
import { useEffect as useEffect11, useState as useState7 } from "react";
|
|
2383
2583
|
function useElapsedSeconds(isRunning) {
|
|
2384
2584
|
const [elapsed, setElapsed] = useState7(0);
|
|
2385
|
-
|
|
2585
|
+
useEffect11(() => {
|
|
2386
2586
|
if (!isRunning) {
|
|
2387
2587
|
setElapsed(0);
|
|
2388
2588
|
return;
|
|
@@ -2480,7 +2680,7 @@ function LoadingDots({ label }) {
|
|
|
2480
2680
|
}
|
|
2481
2681
|
|
|
2482
2682
|
// src/components/LoginFlow.tsx
|
|
2483
|
-
import { useCallback as useCallback7, useEffect as
|
|
2683
|
+
import { useCallback as useCallback7, useEffect as useEffect12, useRef as useRef6, useState as useState8 } from "react";
|
|
2484
2684
|
|
|
2485
2685
|
// src/components/ui/button.tsx
|
|
2486
2686
|
import { forwardRef as forwardRef3 } from "react";
|
|
@@ -2608,16 +2808,16 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
|
|
|
2608
2808
|
function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
|
|
2609
2809
|
const [digits, setDigits] = useState8(Array(OTP_LENGTH).fill(""));
|
|
2610
2810
|
const [resendCooldown, setResendCooldown] = useState8(0);
|
|
2611
|
-
const inputRefs =
|
|
2612
|
-
const submittedRef =
|
|
2613
|
-
|
|
2811
|
+
const inputRefs = useRef6([]);
|
|
2812
|
+
const submittedRef = useRef6(false);
|
|
2813
|
+
useEffect12(() => {
|
|
2614
2814
|
inputRefs.current[0]?.focus();
|
|
2615
2815
|
}, []);
|
|
2616
|
-
|
|
2816
|
+
useEffect12(() => {
|
|
2617
2817
|
if (error)
|
|
2618
2818
|
submittedRef.current = false;
|
|
2619
2819
|
}, [error]);
|
|
2620
|
-
|
|
2820
|
+
useEffect12(() => {
|
|
2621
2821
|
if (resendCooldown <= 0)
|
|
2622
2822
|
return;
|
|
2623
2823
|
const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1000);
|
|
@@ -2758,35 +2958,66 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
|
|
|
2758
2958
|
}
|
|
2759
2959
|
|
|
2760
2960
|
// src/components/MeetingControls.tsx
|
|
2761
|
-
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2762
|
-
var CONTROL_BUTTON2 = "skippr:flex skippr:size-11 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-full skippr:transition-colors";
|
|
2763
|
-
|
|
2961
|
+
import { jsx as jsx9, jsxs as jsxs8, Fragment as Fragment3 } from "react/jsx-runtime";
|
|
2962
|
+
var CONTROL_BUTTON2 = "skippr:flex skippr:size-11 skippr:cursor-pointer skippr:items-center skippr:justify-center skippr:rounded-full skippr:transition-colors skippr:disabled:cursor-not-allowed skippr:disabled:opacity-60";
|
|
2963
|
+
var MUTED_BUTTON = "skippr:bg-muted skippr:text-foreground skippr:hover:bg-muted/80";
|
|
2964
|
+
function MeetingControls({
|
|
2965
|
+
onHangUp,
|
|
2966
|
+
onPause,
|
|
2967
|
+
onResume,
|
|
2968
|
+
isPaused = false,
|
|
2969
|
+
isPausing = false,
|
|
2970
|
+
showScreenShareToggle = true
|
|
2971
|
+
}) {
|
|
2764
2972
|
const { isMuted, toggleMute, isScreenSharing, toggleScreenShare } = useMediaControls();
|
|
2973
|
+
const showPaused = isPaused || isPausing;
|
|
2765
2974
|
return /* @__PURE__ */ jsxs8("div", {
|
|
2766
2975
|
className: "skippr:shrink-0 skippr:border-t skippr:border-border skippr:bg-background skippr:px-4 skippr:py-4",
|
|
2767
2976
|
children: [
|
|
2768
2977
|
/* @__PURE__ */ jsxs8("div", {
|
|
2769
2978
|
className: "skippr:flex skippr:items-center skippr:justify-center skippr:gap-3",
|
|
2770
2979
|
children: [
|
|
2771
|
-
/* @__PURE__ */
|
|
2980
|
+
!showPaused && /* @__PURE__ */ jsxs8(Fragment3, {
|
|
2981
|
+
children: [
|
|
2982
|
+
/* @__PURE__ */ jsx9("button", {
|
|
2983
|
+
type: "button",
|
|
2984
|
+
onClick: toggleMute,
|
|
2985
|
+
"aria-label": isMuted ? "Unmute" : "Mute",
|
|
2986
|
+
className: cn(CONTROL_BUTTON2, isMuted ? "skippr:bg-destructive/15 skippr:text-destructive skippr:hover:bg-destructive/25" : MUTED_BUTTON),
|
|
2987
|
+
children: isMuted ? /* @__PURE__ */ jsx9(MicOff, {
|
|
2988
|
+
className: "skippr:size-5"
|
|
2989
|
+
}) : /* @__PURE__ */ jsx9(Mic, {
|
|
2990
|
+
className: "skippr:size-5"
|
|
2991
|
+
})
|
|
2992
|
+
}),
|
|
2993
|
+
showScreenShareToggle && /* @__PURE__ */ jsx9("button", {
|
|
2994
|
+
type: "button",
|
|
2995
|
+
onClick: toggleScreenShare,
|
|
2996
|
+
"aria-label": isScreenSharing ? "Stop sharing screen" : "Share screen",
|
|
2997
|
+
className: cn(CONTROL_BUTTON2, isScreenSharing ? "skippr:bg-bubble skippr:text-white skippr:hover:brightness-110" : MUTED_BUTTON),
|
|
2998
|
+
children: isScreenSharing ? /* @__PURE__ */ jsx9(MonitorOff, {
|
|
2999
|
+
className: "skippr:size-5"
|
|
3000
|
+
}) : /* @__PURE__ */ jsx9(Monitor, {
|
|
3001
|
+
className: "skippr:size-5"
|
|
3002
|
+
})
|
|
3003
|
+
})
|
|
3004
|
+
]
|
|
3005
|
+
}),
|
|
3006
|
+
showPaused ? onResume && /* @__PURE__ */ jsx9("button", {
|
|
2772
3007
|
type: "button",
|
|
2773
|
-
onClick:
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
}) : /* @__PURE__ */ jsx9(Mic, {
|
|
3008
|
+
onClick: onResume,
|
|
3009
|
+
disabled: isPausing,
|
|
3010
|
+
"aria-label": "Resume session",
|
|
3011
|
+
className: cn(CONTROL_BUTTON2, MUTED_BUTTON),
|
|
3012
|
+
children: /* @__PURE__ */ jsx9(Play, {
|
|
2779
3013
|
className: "skippr:size-5"
|
|
2780
3014
|
})
|
|
2781
|
-
}),
|
|
2782
|
-
showScreenShareToggle && /* @__PURE__ */ jsx9("button", {
|
|
3015
|
+
}) : onPause && /* @__PURE__ */ jsx9("button", {
|
|
2783
3016
|
type: "button",
|
|
2784
|
-
onClick:
|
|
2785
|
-
"aria-label":
|
|
2786
|
-
className: cn(CONTROL_BUTTON2,
|
|
2787
|
-
children:
|
|
2788
|
-
className: "skippr:size-5"
|
|
2789
|
-
}) : /* @__PURE__ */ jsx9(Monitor, {
|
|
3017
|
+
onClick: onPause,
|
|
3018
|
+
"aria-label": "Pause session",
|
|
3019
|
+
className: cn(CONTROL_BUTTON2, MUTED_BUTTON),
|
|
3020
|
+
children: /* @__PURE__ */ jsx9(Pause, {
|
|
2790
3021
|
className: "skippr:size-5"
|
|
2791
3022
|
})
|
|
2792
3023
|
}),
|
|
@@ -2810,17 +3041,17 @@ function MeetingControls({ onHangUp, showScreenShareToggle = true }) {
|
|
|
2810
3041
|
}
|
|
2811
3042
|
|
|
2812
3043
|
// src/components/MessageList.tsx
|
|
2813
|
-
import { useEffect as
|
|
3044
|
+
import { useEffect as useEffect14, useRef as useRef8 } from "react";
|
|
2814
3045
|
|
|
2815
3046
|
// src/components/ChatInput.tsx
|
|
2816
|
-
import { useEffect as
|
|
3047
|
+
import { useEffect as useEffect13, useRef as useRef7, useState as useState9 } from "react";
|
|
2817
3048
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2818
3049
|
var MAX_INPUT_HEIGHT = 60;
|
|
2819
3050
|
function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
|
|
2820
3051
|
const [inputText, setInputText] = useState9("");
|
|
2821
|
-
const textareaRef =
|
|
3052
|
+
const textareaRef = useRef7(null);
|
|
2822
3053
|
const canSend = inputText.trim().length > 0 && !isSendingChat;
|
|
2823
|
-
|
|
3054
|
+
useEffect13(() => {
|
|
2824
3055
|
if (autoFocus)
|
|
2825
3056
|
textareaRef.current?.focus();
|
|
2826
3057
|
}, [autoFocus]);
|
|
@@ -2965,9 +3196,9 @@ function MessageList({
|
|
|
2965
3196
|
isSendingChat,
|
|
2966
3197
|
autoFocus = false
|
|
2967
3198
|
}) {
|
|
2968
|
-
const scrollRef =
|
|
3199
|
+
const scrollRef = useRef8(null);
|
|
2969
3200
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
2970
|
-
|
|
3201
|
+
useEffect14(() => {
|
|
2971
3202
|
scrollRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2972
3203
|
}, [messages.length, lastMessage?.content]);
|
|
2973
3204
|
const showTyping = isStreaming && lastMessage?.role === "assistant" && lastMessage.content === "";
|
|
@@ -2999,7 +3230,7 @@ function MessageList({
|
|
|
2999
3230
|
}
|
|
3000
3231
|
|
|
3001
3232
|
// src/components/ModuleSelector.tsx
|
|
3002
|
-
import { useEffect as
|
|
3233
|
+
import { useEffect as useEffect15, useRef as useRef9, useState as useState10 } from "react";
|
|
3003
3234
|
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3004
3235
|
var AGENT_TYPE_ICONS = {
|
|
3005
3236
|
onboarding: UserPlus,
|
|
@@ -3022,10 +3253,10 @@ function ModuleSelector() {
|
|
|
3022
3253
|
error
|
|
3023
3254
|
} = useLiveAgent();
|
|
3024
3255
|
const isBusy = isStarting || isDisconnecting;
|
|
3025
|
-
const scrollRef =
|
|
3256
|
+
const scrollRef = useRef9(null);
|
|
3026
3257
|
const [showScrollHint, setShowScrollHint] = useState10(false);
|
|
3027
3258
|
const [isScrolled, setIsScrolled] = useState10(false);
|
|
3028
|
-
|
|
3259
|
+
useEffect15(() => {
|
|
3029
3260
|
const el = scrollRef.current;
|
|
3030
3261
|
if (!el)
|
|
3031
3262
|
return;
|
|
@@ -3109,6 +3340,7 @@ function ModuleSelector() {
|
|
|
3109
3340
|
const isFeatured = index2 === 0;
|
|
3110
3341
|
const isWide = index2 === availableModules.length - 1 && availableModules.length % 2 === 1;
|
|
3111
3342
|
const Icon2 = getAgentIcon(module.type);
|
|
3343
|
+
const canResume = canResumeSession(module.currentSession, module.mode);
|
|
3112
3344
|
const base = "skippr:group skippr:flex skippr:cursor-pointer skippr:gap-3 skippr:rounded-xl skippr:text-left skippr:transition-colors skippr:disabled:cursor-not-allowed skippr:disabled:opacity-50";
|
|
3113
3345
|
const layout = isWide ? "skippr:items-center skippr:p-3.5 skippr:pb-5" : "skippr:flex-col skippr:items-start skippr:p-3.5";
|
|
3114
3346
|
const variant = isFeatured ? "skippr:bg-primary skippr:text-primary-foreground skippr:hover:bg-primary/90" : "skippr:bg-background skippr:ring-1 skippr:ring-foreground/10 skippr:hover:bg-muted/50";
|
|
@@ -3128,9 +3360,23 @@ function ModuleSelector() {
|
|
|
3128
3360
|
/* @__PURE__ */ jsxs13("div", {
|
|
3129
3361
|
className: "skippr:min-w-0 skippr:w-full skippr:space-y-0.5",
|
|
3130
3362
|
children: [
|
|
3131
|
-
/* @__PURE__ */
|
|
3132
|
-
className: "skippr:
|
|
3133
|
-
children:
|
|
3363
|
+
/* @__PURE__ */ jsxs13("div", {
|
|
3364
|
+
className: "skippr:flex skippr:items-center skippr:gap-1.5",
|
|
3365
|
+
children: [
|
|
3366
|
+
/* @__PURE__ */ jsx14("p", {
|
|
3367
|
+
className: "skippr:line-clamp-1 skippr:text-sm skippr:font-semibold",
|
|
3368
|
+
children: module.name
|
|
3369
|
+
}),
|
|
3370
|
+
canResume && /* @__PURE__ */ jsxs13("span", {
|
|
3371
|
+
className: `skippr:inline-flex skippr:shrink-0 skippr:items-center skippr:gap-0.5 skippr:rounded-full skippr:px-1.5 skippr:py-0.5 skippr:text-[9px] skippr:font-medium skippr:uppercase skippr:tracking-wide ${isFeatured ? "skippr:bg-primary-foreground/20 skippr:text-primary-foreground" : "skippr:bg-bubble/15 skippr:text-bubble"}`,
|
|
3372
|
+
children: [
|
|
3373
|
+
/* @__PURE__ */ jsx14(Play, {
|
|
3374
|
+
className: "skippr:size-2.5"
|
|
3375
|
+
}),
|
|
3376
|
+
"Resume"
|
|
3377
|
+
]
|
|
3378
|
+
})
|
|
3379
|
+
]
|
|
3134
3380
|
}),
|
|
3135
3381
|
module.description && /* @__PURE__ */ jsx14("p", {
|
|
3136
3382
|
className: isFeatured ? "skippr:line-clamp-2 skippr:text-[11px] skippr:leading-snug skippr:text-primary-foreground/70" : "skippr:line-clamp-2 skippr:text-[11px] skippr:leading-snug skippr:text-muted-foreground",
|
|
@@ -3227,18 +3473,27 @@ function SessionWarningBanner({ remaining }) {
|
|
|
3227
3473
|
|
|
3228
3474
|
// src/components/StartSessionPrompt.tsx
|
|
3229
3475
|
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3476
|
+
var PROMPT_BUTTON = "skippr:cursor-pointer skippr:rounded-xl skippr:bg-primary skippr:px-8 skippr:py-3 skippr:text-sm skippr:font-medium skippr:text-primary-foreground skippr:transition-all skippr:hover:bg-primary/90 skippr:disabled:cursor-not-allowed skippr:disabled:opacity-60";
|
|
3230
3477
|
function StartSessionPrompt({
|
|
3231
3478
|
onStartSession,
|
|
3232
3479
|
agentId,
|
|
3233
3480
|
agentControls,
|
|
3234
3481
|
isStarting,
|
|
3235
3482
|
error,
|
|
3236
|
-
label = "Talk to Skippr"
|
|
3483
|
+
label = "Talk to Skippr",
|
|
3484
|
+
canResume = false,
|
|
3485
|
+
onResume
|
|
3237
3486
|
}) {
|
|
3238
3487
|
return /* @__PURE__ */ jsxs15("div", {
|
|
3239
3488
|
className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:justify-center skippr:gap-3 skippr:px-4",
|
|
3240
3489
|
children: [
|
|
3241
|
-
/* @__PURE__ */ jsx17("button", {
|
|
3490
|
+
canResume && onResume ? /* @__PURE__ */ jsx17("button", {
|
|
3491
|
+
type: "button",
|
|
3492
|
+
onClick: onResume,
|
|
3493
|
+
disabled: isStarting,
|
|
3494
|
+
className: PROMPT_BUTTON,
|
|
3495
|
+
children: isStarting ? "Resuming..." : "Resume session"
|
|
3496
|
+
}) : /* @__PURE__ */ jsx17("button", {
|
|
3242
3497
|
type: "button",
|
|
3243
3498
|
onClick: () => {
|
|
3244
3499
|
if (!agentId)
|
|
@@ -3246,7 +3501,7 @@ function StartSessionPrompt({
|
|
|
3246
3501
|
onStartSession(agentControls ? { agentId, agentControls } : { agentId });
|
|
3247
3502
|
},
|
|
3248
3503
|
disabled: isStarting || !agentId,
|
|
3249
|
-
className:
|
|
3504
|
+
className: PROMPT_BUTTON,
|
|
3250
3505
|
children: isStarting ? "Starting..." : label
|
|
3251
3506
|
}),
|
|
3252
3507
|
error && /* @__PURE__ */ jsx17("p", {
|
|
@@ -3258,7 +3513,7 @@ function StartSessionPrompt({
|
|
|
3258
3513
|
}
|
|
3259
3514
|
|
|
3260
3515
|
// src/components/Sidebar.tsx
|
|
3261
|
-
import { jsx as jsx18, jsxs as jsxs16, Fragment as
|
|
3516
|
+
import { jsx as jsx18, jsxs as jsxs16, Fragment as Fragment4 } from "react/jsx-runtime";
|
|
3262
3517
|
function Sidebar({
|
|
3263
3518
|
hideControls = false,
|
|
3264
3519
|
hideHeader = false,
|
|
@@ -3268,8 +3523,14 @@ function Sidebar({
|
|
|
3268
3523
|
variant,
|
|
3269
3524
|
isConnected,
|
|
3270
3525
|
isStarting,
|
|
3526
|
+
isDisconnecting,
|
|
3527
|
+
isPausing,
|
|
3528
|
+
isPaused,
|
|
3271
3529
|
error,
|
|
3272
3530
|
startSession,
|
|
3531
|
+
pauseSession,
|
|
3532
|
+
resumeSession,
|
|
3533
|
+
resumableSession,
|
|
3273
3534
|
disconnect,
|
|
3274
3535
|
isPanelOpen,
|
|
3275
3536
|
position,
|
|
@@ -3285,11 +3546,13 @@ function Sidebar({
|
|
|
3285
3546
|
captureMode,
|
|
3286
3547
|
hasModuleSelector,
|
|
3287
3548
|
agentId,
|
|
3549
|
+
agentMode,
|
|
3288
3550
|
agentControls
|
|
3289
3551
|
} = useLiveAgent();
|
|
3552
|
+
const showAgenda = agentMode !== "always_on";
|
|
3290
3553
|
const isFloating = variant === "floating";
|
|
3291
3554
|
const isSidebar = variant === "sidebar";
|
|
3292
|
-
|
|
3555
|
+
useEffect16(() => {
|
|
3293
3556
|
if (!isSidebar)
|
|
3294
3557
|
return;
|
|
3295
3558
|
const prop = position === "right" ? "marginRight" : "marginLeft";
|
|
@@ -3320,7 +3583,13 @@ function Sidebar({
|
|
|
3320
3583
|
isSubmitting: isAuthSubmitting
|
|
3321
3584
|
}) : /* @__PURE__ */ jsx18(AuthenticatedContent, {
|
|
3322
3585
|
isConnected,
|
|
3586
|
+
isPaused,
|
|
3587
|
+
isPausing,
|
|
3588
|
+
isDisconnecting,
|
|
3589
|
+
canResume: resumableSession !== null,
|
|
3323
3590
|
onStartSession: startSession,
|
|
3591
|
+
onPause: pauseSession,
|
|
3592
|
+
onResume: resumeSession,
|
|
3324
3593
|
onDisconnect: disconnect,
|
|
3325
3594
|
isStarting,
|
|
3326
3595
|
error,
|
|
@@ -3332,14 +3601,21 @@ function Sidebar({
|
|
|
3332
3601
|
showScreenShareToggle: captureMode === "screenshare",
|
|
3333
3602
|
hasModuleSelector,
|
|
3334
3603
|
agentId,
|
|
3335
|
-
agentControls
|
|
3604
|
+
agentControls,
|
|
3605
|
+
showAgenda
|
|
3336
3606
|
})
|
|
3337
3607
|
]
|
|
3338
3608
|
});
|
|
3339
3609
|
}
|
|
3340
3610
|
function AuthenticatedContent({
|
|
3341
3611
|
isConnected,
|
|
3612
|
+
isPaused,
|
|
3613
|
+
isPausing,
|
|
3614
|
+
isDisconnecting,
|
|
3615
|
+
canResume,
|
|
3342
3616
|
onStartSession,
|
|
3617
|
+
onPause,
|
|
3618
|
+
onResume,
|
|
3343
3619
|
onDisconnect,
|
|
3344
3620
|
isStarting,
|
|
3345
3621
|
error,
|
|
@@ -3351,11 +3627,22 @@ function AuthenticatedContent({
|
|
|
3351
3627
|
showScreenShareToggle,
|
|
3352
3628
|
hasModuleSelector,
|
|
3353
3629
|
agentId,
|
|
3354
|
-
agentControls
|
|
3630
|
+
agentControls,
|
|
3631
|
+
showAgenda
|
|
3355
3632
|
}) {
|
|
3356
|
-
const
|
|
3633
|
+
const inSession = isConnected || isStarting || isPaused || isPausing;
|
|
3634
|
+
const showSelectorAsPrompt = hasModuleSelector && !inSession && !isDisconnecting;
|
|
3357
3635
|
const showTabBar = !showSelectorAsPrompt;
|
|
3358
|
-
|
|
3636
|
+
const effectiveTab = showAgenda ? activeTab : "chat";
|
|
3637
|
+
let transitionLabel = null;
|
|
3638
|
+
if (isPausing) {
|
|
3639
|
+
transitionLabel = "Pausing...";
|
|
3640
|
+
} else if (isStarting && !isConnected) {
|
|
3641
|
+
transitionLabel = "Reconnecting...";
|
|
3642
|
+
} else if (isPaused) {
|
|
3643
|
+
transitionLabel = "Paused";
|
|
3644
|
+
}
|
|
3645
|
+
return /* @__PURE__ */ jsxs16(Fragment4, {
|
|
3359
3646
|
children: [
|
|
3360
3647
|
isConnected && /* @__PURE__ */ jsx18(ConnectedBanner, {}),
|
|
3361
3648
|
showTabBar && /* @__PURE__ */ jsxs16("div", {
|
|
@@ -3375,7 +3662,7 @@ function AuthenticatedContent({
|
|
|
3375
3662
|
})
|
|
3376
3663
|
]
|
|
3377
3664
|
}),
|
|
3378
|
-
/* @__PURE__ */ jsxs16("button", {
|
|
3665
|
+
showAgenda && /* @__PURE__ */ jsxs16("button", {
|
|
3379
3666
|
type: "button",
|
|
3380
3667
|
className: cn("skippr:relative skippr:inline-flex skippr:cursor-pointer skippr:items-center skippr:gap-1.5 skippr:rounded-lg skippr:px-3 skippr:py-2 skippr:text-sm skippr:font-medium skippr:transition-all", activeTab === "agenda" ? "skippr:text-foreground" : "skippr:text-muted-foreground skippr:hover:text-foreground"),
|
|
3381
3668
|
onClick: () => onTabChange("agenda"),
|
|
@@ -3393,9 +3680,22 @@ function AuthenticatedContent({
|
|
|
3393
3680
|
}),
|
|
3394
3681
|
/* @__PURE__ */ jsx18("div", {
|
|
3395
3682
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
|
|
3396
|
-
children:
|
|
3397
|
-
|
|
3398
|
-
|
|
3683
|
+
children: isDisconnecting ? /* @__PURE__ */ jsx18("div", {
|
|
3684
|
+
className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
|
|
3685
|
+
children: /* @__PURE__ */ jsx18(LoadingDots, {
|
|
3686
|
+
label: "Ending session..."
|
|
3687
|
+
})
|
|
3688
|
+
}) : showSelectorAsPrompt ? /* @__PURE__ */ jsx18(ModuleSelector, {}) : inSession ? /* @__PURE__ */ jsxs16(Fragment4, {
|
|
3689
|
+
children: [
|
|
3690
|
+
transitionLabel && /* @__PURE__ */ jsx18("div", {
|
|
3691
|
+
className: "skippr:shrink-0 skippr:border-b skippr:border-border skippr:bg-muted/50 skippr:px-3 skippr:py-1.5 skippr:text-center skippr:text-xs skippr:text-muted-foreground",
|
|
3692
|
+
children: transitionLabel
|
|
3693
|
+
}),
|
|
3694
|
+
/* @__PURE__ */ jsx18(ConnectedBody, {
|
|
3695
|
+
activeTab: effectiveTab,
|
|
3696
|
+
autoFocusChat
|
|
3697
|
+
})
|
|
3698
|
+
]
|
|
3399
3699
|
}) : /* @__PURE__ */ jsx18("div", {
|
|
3400
3700
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col skippr:animate-skippr-tab-fade",
|
|
3401
3701
|
children: /* @__PURE__ */ jsx18(StartSessionPrompt, {
|
|
@@ -3404,12 +3704,18 @@ function AuthenticatedContent({
|
|
|
3404
3704
|
agentControls,
|
|
3405
3705
|
isStarting,
|
|
3406
3706
|
error,
|
|
3407
|
-
label: startSessionLabel
|
|
3707
|
+
label: startSessionLabel,
|
|
3708
|
+
canResume,
|
|
3709
|
+
onResume
|
|
3408
3710
|
})
|
|
3409
3711
|
}, `${activeTab}-empty`)
|
|
3410
3712
|
}),
|
|
3411
|
-
isConnected && !hideControls && /* @__PURE__ */ jsx18(MeetingControls, {
|
|
3713
|
+
(isConnected || isPaused) && !isDisconnecting && !hideControls && /* @__PURE__ */ jsx18(MeetingControls, {
|
|
3412
3714
|
onHangUp: onDisconnect,
|
|
3715
|
+
onPause,
|
|
3716
|
+
onResume,
|
|
3717
|
+
isPaused,
|
|
3718
|
+
isPausing,
|
|
3413
3719
|
showScreenShareToggle
|
|
3414
3720
|
})
|
|
3415
3721
|
]
|
|
@@ -3527,10 +3833,14 @@ function LiveAgent(props) {
|
|
|
3527
3833
|
shouldConnect,
|
|
3528
3834
|
isStarting,
|
|
3529
3835
|
isDisconnecting,
|
|
3836
|
+
isPausing,
|
|
3530
3837
|
error,
|
|
3531
3838
|
errorCode,
|
|
3532
3839
|
startSession,
|
|
3840
|
+
pauseSession,
|
|
3533
3841
|
disconnect,
|
|
3842
|
+
isPaused,
|
|
3843
|
+
historyMessages,
|
|
3534
3844
|
pendingScreenStream,
|
|
3535
3845
|
bearerToken
|
|
3536
3846
|
} = useSession({
|
|
@@ -3542,9 +3852,17 @@ function LiveAgent(props) {
|
|
|
3542
3852
|
onStartError: expandOnSessionStartError,
|
|
3543
3853
|
onDisconnect: minimizeOnSessionDisconnect
|
|
3544
3854
|
});
|
|
3855
|
+
const teardownInFlightRef = useRef10(false);
|
|
3856
|
+
teardownInFlightRef.current = isPaused || isPausing || isDisconnecting;
|
|
3857
|
+
const handleRoomDisconnected = useCallback8(() => {
|
|
3858
|
+
if (teardownInFlightRef.current)
|
|
3859
|
+
return;
|
|
3860
|
+
disconnect();
|
|
3861
|
+
}, [disconnect]);
|
|
3545
3862
|
const [isPanelOpen, setIsPanelOpen] = useState11(defaultOpen);
|
|
3546
3863
|
const [isMinimized, setIsMinimized] = useState11(minimizable && !defaultOpen);
|
|
3547
3864
|
const [sidebarTab, setSidebarTab] = useState11("agenda");
|
|
3865
|
+
const [phasesSnapshot, setPhasesSnapshot] = useState11([]);
|
|
3548
3866
|
const {
|
|
3549
3867
|
modules: availableModules,
|
|
3550
3868
|
isLoading: isLoadingModules,
|
|
@@ -3554,12 +3872,34 @@ function LiveAgent(props) {
|
|
|
3554
3872
|
enabled: hasModuleSelector && isPanelOpen,
|
|
3555
3873
|
bearerToken
|
|
3556
3874
|
});
|
|
3875
|
+
const activeModuleForAgent = useMemo5(() => {
|
|
3876
|
+
if (activeModule)
|
|
3877
|
+
return activeModule;
|
|
3878
|
+
if (!hostAgentId)
|
|
3879
|
+
return null;
|
|
3880
|
+
return availableModules.find((m) => m.id === hostAgentId) ?? null;
|
|
3881
|
+
}, [activeModule, hostAgentId, availableModules]);
|
|
3882
|
+
const agentMode = activeModuleForAgent?.mode ?? null;
|
|
3883
|
+
const resumableSession = useMemo5(() => getResumableSession(activeModuleForAgent), [activeModuleForAgent]);
|
|
3884
|
+
const resumeSession = useCallback8(async () => {
|
|
3885
|
+
if (!resumableSession)
|
|
3886
|
+
return;
|
|
3887
|
+
await startSession({
|
|
3888
|
+
agentId: resumableSession.agentId,
|
|
3889
|
+
agentControls,
|
|
3890
|
+
existingSessionId: resumableSession.id
|
|
3891
|
+
});
|
|
3892
|
+
}, [resumableSession, startSession, agentControls]);
|
|
3557
3893
|
const selectModule = useCallback8((moduleId) => {
|
|
3558
3894
|
const found = availableModules.find((m) => m.id === moduleId);
|
|
3559
3895
|
if (!found)
|
|
3560
3896
|
return;
|
|
3561
3897
|
setActiveModule(found);
|
|
3562
|
-
startSession({
|
|
3898
|
+
startSession({
|
|
3899
|
+
agentId: found.id,
|
|
3900
|
+
agentControls: found.controls,
|
|
3901
|
+
existingSessionId: getResumableSessionId(found.currentSession, found.mode)
|
|
3902
|
+
});
|
|
3563
3903
|
}, [availableModules, startSession]);
|
|
3564
3904
|
const [welcomeDismissed, setWelcomeDismissed] = useState11(false);
|
|
3565
3905
|
const dismissWelcome = useCallback8(() => setWelcomeDismissed(true), []);
|
|
@@ -3598,10 +3938,18 @@ function LiveAgent(props) {
|
|
|
3598
3938
|
isConnected,
|
|
3599
3939
|
isStarting,
|
|
3600
3940
|
isDisconnecting,
|
|
3941
|
+
isPausing,
|
|
3601
3942
|
error,
|
|
3602
3943
|
errorCode,
|
|
3603
3944
|
startSession,
|
|
3945
|
+
pauseSession,
|
|
3946
|
+
resumeSession,
|
|
3604
3947
|
disconnect,
|
|
3948
|
+
isPaused,
|
|
3949
|
+
resumableSession,
|
|
3950
|
+
historyMessages,
|
|
3951
|
+
phasesSnapshot,
|
|
3952
|
+
setPhasesSnapshot,
|
|
3605
3953
|
isPanelOpen,
|
|
3606
3954
|
openPanel,
|
|
3607
3955
|
closePanel,
|
|
@@ -3625,6 +3973,7 @@ function LiveAgent(props) {
|
|
|
3625
3973
|
autoFocusChat,
|
|
3626
3974
|
captureMode,
|
|
3627
3975
|
agentId,
|
|
3976
|
+
agentMode,
|
|
3628
3977
|
agentControls,
|
|
3629
3978
|
hasModuleSelector,
|
|
3630
3979
|
availableModules,
|
|
@@ -3639,10 +3988,17 @@ function LiveAgent(props) {
|
|
|
3639
3988
|
isConnected,
|
|
3640
3989
|
isStarting,
|
|
3641
3990
|
isDisconnecting,
|
|
3991
|
+
isPausing,
|
|
3642
3992
|
error,
|
|
3643
3993
|
errorCode,
|
|
3644
3994
|
startSession,
|
|
3995
|
+
pauseSession,
|
|
3996
|
+
resumeSession,
|
|
3645
3997
|
disconnect,
|
|
3998
|
+
isPaused,
|
|
3999
|
+
resumableSession,
|
|
4000
|
+
historyMessages,
|
|
4001
|
+
phasesSnapshot,
|
|
3646
4002
|
isPanelOpen,
|
|
3647
4003
|
openPanel,
|
|
3648
4004
|
closePanel,
|
|
@@ -3665,6 +4021,7 @@ function LiveAgent(props) {
|
|
|
3665
4021
|
autoFocusChat,
|
|
3666
4022
|
captureMode,
|
|
3667
4023
|
agentId,
|
|
4024
|
+
agentMode,
|
|
3668
4025
|
agentControls,
|
|
3669
4026
|
hasModuleSelector,
|
|
3670
4027
|
availableModules,
|
|
@@ -3681,7 +4038,7 @@ function LiveAgent(props) {
|
|
|
3681
4038
|
token: connection?.token,
|
|
3682
4039
|
connect: shouldConnect,
|
|
3683
4040
|
audio: true,
|
|
3684
|
-
onDisconnected:
|
|
4041
|
+
onDisconnected: handleRoomDisconnected,
|
|
3685
4042
|
children: [
|
|
3686
4043
|
connection && /* @__PURE__ */ jsx20(RoomAudioRenderer, {}),
|
|
3687
4044
|
connection && captureMode === "screenshare" && /* @__PURE__ */ jsx20(AutoStartMedia, {
|