@skippr/live-agent-sdk 0.35.0 → 0.37.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.
@@ -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 useMemo6, useRef as useRef10, 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";
@@ -137,12 +137,24 @@ function useAuth({ appKey }) {
137
137
  setIsSubmitting(false);
138
138
  }
139
139
  }, [appKey]);
140
- const logout = useCallback(() => {
140
+ const logout = useCallback(async () => {
141
+ const token = authToken;
141
142
  if (appKey)
142
143
  clearStoredToken(appKey);
143
144
  setAuthToken(null);
144
145
  setError("");
145
- }, [appKey]);
146
+ if (!token)
147
+ return;
148
+ try {
149
+ await fetch(`${API_URL}/v1/auth/logout`, {
150
+ method: "POST",
151
+ credentials: "omit",
152
+ headers: { Authorization: `Bearer ${token}` }
153
+ });
154
+ } catch (e) {
155
+ console.warn("[Skippr] Failed to revoke session on logout:", e);
156
+ }
157
+ }, [appKey, authToken]);
146
158
  return {
147
159
  isAuthenticated,
148
160
  isValidating,
@@ -160,23 +172,17 @@ import { useCallback as useCallback2, useEffect as useEffect2, useState as useSt
160
172
  var API_URL2 = "https://specialist.skippr.ai/api";
161
173
  function useAvailableModules({
162
174
  enabled,
163
- bearerToken
175
+ bearerToken,
176
+ authedFetch
164
177
  }) {
165
178
  const [modules, setModules] = useState2([]);
166
179
  const [isLoading, setIsLoading] = useState2(false);
167
180
  const [error, setError] = useState2(null);
168
181
  const fetchModules = useCallback2(async () => {
169
- if (!bearerToken) {
170
- setError("No auth token available");
171
- return;
172
- }
173
182
  setIsLoading(true);
174
183
  setError(null);
175
184
  try {
176
- const resp = await fetch(`${API_URL2}/v1/modules/available`, {
177
- credentials: "omit",
178
- headers: { Authorization: `Bearer ${bearerToken}` }
179
- });
185
+ const resp = await authedFetch(`${API_URL2}/v1/modules/available`);
180
186
  if (!resp.ok) {
181
187
  const body = await resp.json().catch(() => null);
182
188
  throw new Error(body?.detail || `Failed to load modules: ${resp.status}`);
@@ -188,7 +194,7 @@ function useAvailableModules({
188
194
  } finally {
189
195
  setIsLoading(false);
190
196
  }
191
- }, [bearerToken]);
197
+ }, [authedFetch]);
192
198
  useEffect2(() => {
193
199
  if (!enabled || !bearerToken)
194
200
  return;
@@ -205,12 +211,9 @@ function useAvailableModules({
205
211
  // src/hooks/useSession.ts
206
212
  import { useCallback as useCallback3, useEffect as useEffect3, useRef, useState as useState3 } from "react";
207
213
  var API_URL3 = "https://specialist.skippr.ai/api";
208
- async function fetchSessionMessages(sessionId, bearerToken) {
214
+ async function fetchSessionMessages(sessionId, authedFetch) {
209
215
  try {
210
- const resp = await fetch(`${API_URL3}/v1/sessions/${sessionId}/messages`, {
211
- credentials: "omit",
212
- headers: { Authorization: `Bearer ${bearerToken}` }
213
- });
216
+ const resp = await authedFetch(`${API_URL3}/v1/sessions/${sessionId}/messages`);
214
217
  if (!resp.ok)
215
218
  return [];
216
219
  const { messages } = await resp.json();
@@ -225,6 +228,7 @@ async function fetchSessionMessages(sessionId, bearerToken) {
225
228
  return [];
226
229
  }
227
230
  }
231
+ var REFRESH_BUFFER_MS = 180000;
228
232
  async function requestScreenShare() {
229
233
  try {
230
234
  return await navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: "browser" } });
@@ -250,13 +254,14 @@ async function exchangeForBearerToken(appKey, userToken) {
250
254
  if (!resp.ok) {
251
255
  throw new Error(`Token exchange failed: ${resp.status}`);
252
256
  }
253
- const { token } = await resp.json();
254
- return token;
257
+ const { token, expiresAt } = await resp.json();
258
+ return { token, expiresAt: new Date(expiresAt).getTime() };
255
259
  }
256
260
  function useSession({
257
261
  captureMode = "screenshare",
258
262
  authToken,
259
263
  appKey,
264
+ getUserToken,
260
265
  userToken,
261
266
  onStart,
262
267
  onStartError,
@@ -273,50 +278,107 @@ function useSession({
273
278
  const [pendingScreenStream, setPendingScreenStream] = useState3(null);
274
279
  const [isPaused, setIsPaused] = useState3(false);
275
280
  const [isPausing, setIsPausing] = useState3(false);
276
- const [resumableSessions, setResumableSessions] = useState3([]);
277
281
  const [historyMessages, setHistoryMessages] = useState3([]);
282
+ const [authFailed, setAuthFailed] = useState3(false);
283
+ const tokenRef = useRef(authToken ? { token: authToken, expiresAt: null } : null);
284
+ const getUserTokenRef = useRef(getUserToken);
285
+ getUserTokenRef.current = getUserToken ?? (userToken ? () => Promise.resolve(userToken) : undefined);
286
+ const failedBearerRef = useRef(null);
287
+ const inFlightExchangeRef = useRef(null);
288
+ const canExchange = useCallback3(() => !!appKey && !!getUserTokenRef.current, [appKey]);
289
+ const reExchange = useCallback3(async () => {
290
+ if (inFlightExchangeRef.current)
291
+ return inFlightExchangeRef.current;
292
+ const provider = getUserTokenRef.current;
293
+ if (!appKey || !provider)
294
+ throw new Error("No token provider available");
295
+ const exchange = (async () => {
296
+ const userToken2 = await provider();
297
+ const { token, expiresAt } = await exchangeForBearerToken(appKey, userToken2);
298
+ tokenRef.current = { token, expiresAt };
299
+ setBearerToken(token);
300
+ return token;
301
+ })();
302
+ inFlightExchangeRef.current = exchange;
303
+ try {
304
+ return await exchange;
305
+ } finally {
306
+ inFlightExchangeRef.current = null;
307
+ }
308
+ }, [appKey]);
309
+ const getValidBearer = useCallback3(async () => {
310
+ const current = tokenRef.current;
311
+ if (current) {
312
+ if (current.expiresAt === null)
313
+ return current.token;
314
+ if (Date.now() < current.expiresAt - REFRESH_BUFFER_MS)
315
+ return current.token;
316
+ }
317
+ if (canExchange())
318
+ return reExchange();
319
+ return current?.token ?? null;
320
+ }, [canExchange, reExchange]);
321
+ const authedFetch = useCallback3(async (input, init = {}) => {
322
+ const isSecretMode = canExchange();
323
+ const onTerminalAuthFailure = () => {
324
+ if (isSecretMode)
325
+ setAuthFailed(true);
326
+ else
327
+ window.dispatchEvent(new Event("skippr:logout"));
328
+ };
329
+ const baseHeaders = init.headers ?? {};
330
+ const run = (token) => fetch(input, {
331
+ ...init,
332
+ credentials: "omit",
333
+ headers: token ? { ...baseHeaders, Authorization: `Bearer ${token}` } : baseHeaders
334
+ });
335
+ let bearer;
336
+ try {
337
+ bearer = await getValidBearer();
338
+ } catch (e) {
339
+ onTerminalAuthFailure();
340
+ throw e;
341
+ }
342
+ let resp = await run(bearer);
343
+ const canRetry = resp.status === 401 && isSecretMode && bearer !== failedBearerRef.current;
344
+ if (canRetry) {
345
+ let refreshed;
346
+ try {
347
+ refreshed = await reExchange();
348
+ } catch (e) {
349
+ onTerminalAuthFailure();
350
+ throw e;
351
+ }
352
+ resp = await run(refreshed);
353
+ failedBearerRef.current = resp.status === 401 ? refreshed : null;
354
+ } else if (resp.status !== 401) {
355
+ failedBearerRef.current = null;
356
+ }
357
+ if (resp.status === 401)
358
+ onTerminalAuthFailure();
359
+ else if (resp.ok)
360
+ setAuthFailed(false);
361
+ return resp;
362
+ }, [canExchange, getValidBearer, reExchange]);
278
363
  useEffect3(() => {
279
364
  let stale = false;
280
365
  if (authToken) {
366
+ tokenRef.current = { token: authToken, expiresAt: null };
281
367
  setBearerToken(authToken);
282
368
  return;
283
369
  }
284
- if (appKey && userToken) {
285
- exchangeForBearerToken(appKey, userToken).then((token) => {
286
- if (!stale)
287
- setBearerToken(token);
288
- }).catch((e) => {
289
- if (!stale)
290
- setError(e instanceof Error ? e.message : "Token exchange failed");
370
+ if (canExchange()) {
371
+ reExchange().catch((e) => {
372
+ if (stale)
373
+ return;
374
+ setError(e instanceof Error ? e.message : "Token exchange failed");
375
+ setAuthFailed(true);
291
376
  });
292
377
  }
293
378
  return () => {
294
379
  stale = true;
295
380
  };
296
- }, [authToken, appKey, userToken]);
297
- const refetchResumable = useCallback3(async () => {
298
- if (!bearerToken) {
299
- setResumableSessions([]);
300
- return;
301
- }
302
- try {
303
- const resp = await fetch(`${API_URL3}/v1/sessions/resumable`, {
304
- credentials: "omit",
305
- headers: { Authorization: `Bearer ${bearerToken}` }
306
- });
307
- if (!resp.ok) {
308
- setResumableSessions([]);
309
- return;
310
- }
311
- const { sessions } = await resp.json();
312
- setResumableSessions(sessions);
313
- } catch {
314
- setResumableSessions([]);
315
- }
316
- }, [bearerToken]);
317
- useEffect3(() => {
318
- refetchResumable();
319
- }, [refetchResumable]);
381
+ }, [authToken, canExchange, reExchange]);
320
382
  const pauseOnUnloadRef = useRef(null);
321
383
  pauseOnUnloadRef.current = connection !== null && !isPaused && sessionId && bearerToken ? { sessionId, bearerToken } : null;
322
384
  useEffect3(() => {
@@ -334,12 +396,12 @@ function useSession({
334
396
  window.addEventListener("pagehide", onPageHide);
335
397
  return () => window.removeEventListener("pagehide", onPageHide);
336
398
  }, []);
337
- const startSession = useCallback3(async ({ agentId, agentControls }) => {
399
+ const startSession = useCallback3(async ({ agentId, agentControls, existingSessionId }) => {
338
400
  if (!bearerToken) {
339
401
  setError("No auth token available");
340
402
  return;
341
403
  }
342
- if (!agentId) {
404
+ if (!agentId && !existingSessionId) {
343
405
  setError("No agent selected");
344
406
  return;
345
407
  }
@@ -352,37 +414,40 @@ function useSession({
352
414
  screenStream = await requestScreenShare();
353
415
  }
354
416
  const requestAgentControls = agentControls?.highlight === true ? { highlight: true } : undefined;
355
- const headers = { Authorization: `Bearer ${bearerToken}` };
356
417
  try {
357
- const createResp = await fetch(`${API_URL3}/v1/sessions`, {
358
- method: "POST",
359
- credentials: "omit",
360
- headers: { "Content-Type": "application/json", ...headers },
361
- body: JSON.stringify({
362
- agentId,
363
- captureMode,
364
- agentControls: requestAgentControls
365
- })
366
- });
367
- if (!createResp.ok) {
368
- const body = await createResp.json().catch(() => null);
369
- setErrorCode(createResp.status);
370
- throw new Error(body?.detail || `Failed to create session: ${createResp.status}`);
418
+ let resolvedSessionId = existingSessionId;
419
+ if (!resolvedSessionId) {
420
+ const createResp = await authedFetch(`${API_URL3}/v1/sessions`, {
421
+ method: "POST",
422
+ headers: { "Content-Type": "application/json" },
423
+ body: JSON.stringify({
424
+ agentId,
425
+ captureMode,
426
+ agentControls: requestAgentControls
427
+ })
428
+ });
429
+ if (!createResp.ok) {
430
+ const body = await createResp.json().catch(() => null);
431
+ setErrorCode(createResp.status);
432
+ throw new Error(body?.detail || `Failed to create session: ${createResp.status}`);
433
+ }
434
+ const { session: session2 } = await createResp.json();
435
+ resolvedSessionId = session2.id;
371
436
  }
372
- const { session } = await createResp.json();
373
- const startResp = await fetch(`${API_URL3}/v1/sessions/${session.id}/start`, {
437
+ const startResp = await authedFetch(`${API_URL3}/v1/sessions/${resolvedSessionId}/start`, {
374
438
  method: "POST",
375
- credentials: "omit",
376
- headers
439
+ headers: { "Content-Type": "application/json" },
440
+ body: JSON.stringify({ captureMode, agentControls: requestAgentControls })
377
441
  });
378
442
  if (!startResp.ok) {
379
443
  const body = await startResp.json().catch(() => null);
380
444
  setErrorCode(startResp.status);
381
445
  throw new Error(body?.detail || `Failed to start session: ${startResp.status}`);
382
446
  }
383
- const { connection: conn } = await startResp.json();
447
+ const { session, connection: conn } = await startResp.json();
448
+ const history2 = existingSessionId ? await fetchSessionMessages(session.id, authedFetch) : [];
384
449
  setSessionId(session.id);
385
- setHistoryMessages([]);
450
+ setHistoryMessages(history2);
386
451
  setConnection({
387
452
  livekitUrl: conn.livekitUrl,
388
453
  token: conn.token
@@ -397,16 +462,14 @@ function useSession({
397
462
  } finally {
398
463
  setIsStarting(false);
399
464
  }
400
- }, [captureMode, bearerToken, onStart, onStartError]);
465
+ }, [captureMode, bearerToken, authedFetch, onStart, onStartError]);
401
466
  const pauseSession = useCallback3(async () => {
402
467
  if (!sessionId || !bearerToken)
403
468
  return;
404
469
  setIsPausing(true);
405
470
  try {
406
- const resp = await fetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
407
- method: "POST",
408
- credentials: "omit",
409
- headers: { Authorization: `Bearer ${bearerToken}` }
471
+ const resp = await authedFetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
472
+ method: "POST"
410
473
  });
411
474
  if (!resp.ok) {
412
475
  const body = await resp.json().catch(() => null);
@@ -417,7 +480,7 @@ function useSession({
417
480
  setIsPausing(false);
418
481
  return;
419
482
  }
420
- const history2 = await fetchSessionMessages(sessionId, bearerToken);
483
+ const history2 = await fetchSessionMessages(sessionId, authedFetch);
421
484
  stopStream(pendingScreenStream);
422
485
  setPendingScreenStream(null);
423
486
  setShouldConnect(false);
@@ -425,64 +488,14 @@ function useSession({
425
488
  setHistoryMessages(history2);
426
489
  setIsPaused(true);
427
490
  setIsPausing(false);
428
- await refetchResumable();
429
- }, [sessionId, bearerToken, pendingScreenStream, refetchResumable]);
430
- const resumeSession = useCallback3(async ({
431
- sessionId: resumeId,
432
- agentControls
433
- }) => {
434
- if (!bearerToken) {
435
- setError("No auth token available");
436
- return;
437
- }
438
- setIsStarting(true);
439
- setError("");
440
- setErrorCode(null);
441
- onStart?.();
442
- let screenStream = null;
443
- if (captureMode === "screenshare") {
444
- screenStream = await requestScreenShare();
445
- }
446
- const requestAgentControls = agentControls?.highlight === true ? { highlight: true } : undefined;
447
- try {
448
- const resp = await fetch(`${API_URL3}/v1/sessions/${resumeId}/resume`, {
449
- method: "POST",
450
- credentials: "omit",
451
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${bearerToken}` },
452
- body: JSON.stringify({ captureMode, agentControls: requestAgentControls })
453
- });
454
- if (!resp.ok) {
455
- const body = await resp.json().catch(() => null);
456
- setErrorCode(resp.status);
457
- throw new Error(body?.detail || `Failed to resume: ${resp.status}`);
458
- }
459
- const { session, connection: conn } = await resp.json();
460
- const history2 = await fetchSessionMessages(session.id, bearerToken);
461
- setSessionId(session.id);
462
- setConnection({ livekitUrl: conn.livekitUrl, token: conn.token });
463
- setPendingScreenStream(screenStream);
464
- setHistoryMessages(history2);
465
- setShouldConnect(true);
466
- setIsPaused(false);
467
- setResumableSessions((prev) => prev.filter((s) => s.id !== resumeId));
468
- } catch (e) {
469
- stopStream(screenStream);
470
- setError(e instanceof Error ? e.message : "Failed to resume session");
471
- onStartError?.();
472
- } finally {
473
- setIsStarting(false);
474
- }
475
- }, [captureMode, bearerToken, onStart, onStartError]);
491
+ }, [sessionId, bearerToken, authedFetch, pendingScreenStream]);
476
492
  const disconnect = useCallback3(async () => {
477
493
  setIsDisconnecting(true);
478
494
  try {
479
495
  if (sessionId && bearerToken) {
480
496
  try {
481
- await fetch(`${API_URL3}/v1/sessions/${sessionId}/complete`, {
482
- method: "POST",
483
- credentials: "omit",
484
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${bearerToken}` },
485
- body: JSON.stringify({})
497
+ await authedFetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
498
+ method: "POST"
486
499
  });
487
500
  } catch {}
488
501
  }
@@ -495,11 +508,10 @@ function useSession({
495
508
  setHistoryMessages([]);
496
509
  setIsPaused(false);
497
510
  onDisconnect?.();
498
- await refetchResumable();
499
511
  } finally {
500
512
  setIsDisconnecting(false);
501
513
  }
502
- }, [sessionId, bearerToken, pendingScreenStream, onDisconnect, refetchResumable]);
514
+ }, [sessionId, bearerToken, authedFetch, pendingScreenStream, onDisconnect]);
503
515
  return {
504
516
  connection,
505
517
  shouldConnect,
@@ -509,15 +521,14 @@ function useSession({
509
521
  errorCode,
510
522
  startSession,
511
523
  pauseSession,
512
- resumeSession,
513
524
  disconnect,
514
525
  isPaused,
515
526
  isPausing,
516
- resumableSessions,
517
527
  historyMessages,
518
- refetchResumable,
519
528
  pendingScreenStream,
520
- bearerToken
529
+ bearerToken,
530
+ authedFetch,
531
+ authFailed
521
532
  };
522
533
  }
523
534
 
@@ -531,6 +542,27 @@ var DOM_EVENTS_TOPIC = "skippr.dom-events";
531
542
  var HIGHLIGHT_TOPIC = "skippr.highlight";
532
543
  var NAME_MAX_CHARS = 80;
533
544
 
545
+ // src/lib/session.ts
546
+ function getResumableSessionId(currentSession, mode) {
547
+ if (!currentSession)
548
+ return;
549
+ const { id, status } = currentSession;
550
+ if (status === "paused" || status === "active")
551
+ return id;
552
+ if (status === "expired" && mode === "always_on")
553
+ return id;
554
+ return;
555
+ }
556
+ function canResumeSession(currentSession, mode) {
557
+ return getResumableSessionId(currentSession, mode) !== undefined;
558
+ }
559
+ function getResumableSession(module) {
560
+ if (!module)
561
+ return null;
562
+ const id = getResumableSessionId(module.currentSession, module.mode);
563
+ return id ? { id, agentId: module.id } : null;
564
+ }
565
+
534
566
  // src/components/AutoStartMedia.tsx
535
567
  import { useConnectionState, useLocalParticipant } from "@livekit/components-react/hooks";
536
568
  import { ConnectionState, Track } from "livekit-client";
@@ -1499,17 +1531,24 @@ var createLucideIcon = (iconName, iconNode) => {
1499
1531
  return Component;
1500
1532
  };
1501
1533
 
1502
- // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle-check.js
1534
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle-alert.js
1503
1535
  var __iconNode = [
1536
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
1537
+ ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
1538
+ ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
1539
+ ];
1540
+ var CircleAlert = createLucideIcon("circle-alert", __iconNode);
1541
+ // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle-check.js
1542
+ var __iconNode2 = [
1504
1543
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
1505
1544
  ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
1506
1545
  ];
1507
- var CircleCheck = createLucideIcon("circle-check", __iconNode);
1546
+ var CircleCheck = createLucideIcon("circle-check", __iconNode2);
1508
1547
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/loader-circle.js
1509
- var __iconNode2 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1510
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode2);
1548
+ var __iconNode3 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1549
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode3);
1511
1550
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/sparkles.js
1512
- var __iconNode3 = [
1551
+ var __iconNode4 = [
1513
1552
  [
1514
1553
  "path",
1515
1554
  {
@@ -1521,9 +1560,9 @@ var __iconNode3 = [
1521
1560
  ["path", { d: "M22 4h-4", key: "gwowj6" }],
1522
1561
  ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
1523
1562
  ];
1524
- var Sparkles = createLucideIcon("sparkles", __iconNode3);
1563
+ var Sparkles = createLucideIcon("sparkles", __iconNode4);
1525
1564
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/bot.js
1526
- var __iconNode4 = [
1565
+ var __iconNode5 = [
1527
1566
  ["path", { d: "M12 8V4H8", key: "hb8ula" }],
1528
1567
  ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
1529
1568
  ["path", { d: "M2 14h2", key: "vft8re" }],
@@ -1531,23 +1570,23 @@ var __iconNode4 = [
1531
1570
  ["path", { d: "M15 13v2", key: "1xurst" }],
1532
1571
  ["path", { d: "M9 13v2", key: "rq6x2g" }]
1533
1572
  ];
1534
- var Bot = createLucideIcon("bot", __iconNode4);
1573
+ var Bot = createLucideIcon("bot", __iconNode5);
1535
1574
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/calendar.js
1536
- var __iconNode5 = [
1575
+ var __iconNode6 = [
1537
1576
  ["path", { d: "M8 2v4", key: "1cmpym" }],
1538
1577
  ["path", { d: "M16 2v4", key: "4m81vk" }],
1539
1578
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
1540
1579
  ["path", { d: "M3 10h18", key: "8toen8" }]
1541
1580
  ];
1542
- var Calendar = createLucideIcon("calendar", __iconNode5);
1581
+ var Calendar = createLucideIcon("calendar", __iconNode6);
1543
1582
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/chevron-down.js
1544
- var __iconNode6 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
1545
- var ChevronDown = createLucideIcon("chevron-down", __iconNode6);
1583
+ var __iconNode7 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
1584
+ var ChevronDown = createLucideIcon("chevron-down", __iconNode7);
1546
1585
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle.js
1547
- var __iconNode7 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
1548
- var Circle = createLucideIcon("circle", __iconNode7);
1586
+ var __iconNode8 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
1587
+ var Circle = createLucideIcon("circle", __iconNode8);
1549
1588
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/graduation-cap.js
1550
- var __iconNode8 = [
1589
+ var __iconNode9 = [
1551
1590
  [
1552
1591
  "path",
1553
1592
  {
@@ -1558,9 +1597,9 @@ var __iconNode8 = [
1558
1597
  ["path", { d: "M22 10v6", key: "1lu8f3" }],
1559
1598
  ["path", { d: "M6 12.5V16a6 3 0 0 0 12 0v-3.5", key: "1r8lef" }]
1560
1599
  ];
1561
- var GraduationCap = createLucideIcon("graduation-cap", __iconNode8);
1600
+ var GraduationCap = createLucideIcon("graduation-cap", __iconNode9);
1562
1601
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/headset.js
1563
- var __iconNode9 = [
1602
+ var __iconNode10 = [
1564
1603
  [
1565
1604
  "path",
1566
1605
  {
@@ -1570,15 +1609,15 @@ var __iconNode9 = [
1570
1609
  ],
1571
1610
  ["path", { d: "M21 16v2a4 4 0 0 1-4 4h-5", key: "1x7m43" }]
1572
1611
  ];
1573
- var Headset = createLucideIcon("headset", __iconNode9);
1612
+ var Headset = createLucideIcon("headset", __iconNode10);
1574
1613
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mail.js
1575
- var __iconNode10 = [
1614
+ var __iconNode11 = [
1576
1615
  ["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7", key: "132q7q" }],
1577
1616
  ["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }]
1578
1617
  ];
1579
- var Mail = createLucideIcon("mail", __iconNode10);
1618
+ var Mail = createLucideIcon("mail", __iconNode11);
1580
1619
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-circle.js
1581
- var __iconNode11 = [
1620
+ var __iconNode12 = [
1582
1621
  [
1583
1622
  "path",
1584
1623
  {
@@ -1587,9 +1626,9 @@ var __iconNode11 = [
1587
1626
  }
1588
1627
  ]
1589
1628
  ];
1590
- var MessageCircle = createLucideIcon("message-circle", __iconNode11);
1629
+ var MessageCircle = createLucideIcon("message-circle", __iconNode12);
1591
1630
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-square.js
1592
- var __iconNode12 = [
1631
+ var __iconNode13 = [
1593
1632
  [
1594
1633
  "path",
1595
1634
  {
@@ -1598,9 +1637,9 @@ var __iconNode12 = [
1598
1637
  }
1599
1638
  ]
1600
1639
  ];
1601
- var MessageSquare = createLucideIcon("message-square", __iconNode12);
1640
+ var MessageSquare = createLucideIcon("message-square", __iconNode13);
1602
1641
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic-off.js
1603
- var __iconNode13 = [
1642
+ var __iconNode14 = [
1604
1643
  ["path", { d: "M12 19v3", key: "npa21l" }],
1605
1644
  ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
1606
1645
  ["path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2", key: "cqa7eg" }],
@@ -1608,40 +1647,40 @@ var __iconNode13 = [
1608
1647
  ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1609
1648
  ["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }]
1610
1649
  ];
1611
- var MicOff = createLucideIcon("mic-off", __iconNode13);
1650
+ var MicOff = createLucideIcon("mic-off", __iconNode14);
1612
1651
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic.js
1613
- var __iconNode14 = [
1652
+ var __iconNode15 = [
1614
1653
  ["path", { d: "M12 19v3", key: "npa21l" }],
1615
1654
  ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
1616
1655
  ["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
1617
1656
  ];
1618
- var Mic = createLucideIcon("mic", __iconNode14);
1657
+ var Mic = createLucideIcon("mic", __iconNode15);
1619
1658
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/minimize-2.js
1620
- var __iconNode15 = [
1659
+ var __iconNode16 = [
1621
1660
  ["path", { d: "m14 10 7-7", key: "oa77jy" }],
1622
1661
  ["path", { d: "M20 10h-6V4", key: "mjg0md" }],
1623
1662
  ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
1624
1663
  ["path", { d: "M4 14h6v6", key: "rmj7iw" }]
1625
1664
  ];
1626
- var Minimize2 = createLucideIcon("minimize-2", __iconNode15);
1665
+ var Minimize2 = createLucideIcon("minimize-2", __iconNode16);
1627
1666
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor-off.js
1628
- var __iconNode16 = [
1667
+ var __iconNode17 = [
1629
1668
  ["path", { d: "M12 17v4", key: "1riwvh" }],
1630
1669
  ["path", { d: "M17 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 1.184-1.826", key: "cv7jms" }],
1631
1670
  ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1632
1671
  ["path", { d: "M8 21h8", key: "1ev6f3" }],
1633
1672
  ["path", { d: "M8.656 3H20a2 2 0 0 1 2 2v10a2 2 0 0 1-.293 1.042", key: "z8ni2w" }]
1634
1673
  ];
1635
- var MonitorOff = createLucideIcon("monitor-off", __iconNode16);
1674
+ var MonitorOff = createLucideIcon("monitor-off", __iconNode17);
1636
1675
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.js
1637
- var __iconNode17 = [
1676
+ var __iconNode18 = [
1638
1677
  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
1639
1678
  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
1640
1679
  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
1641
1680
  ];
1642
- var Monitor = createLucideIcon("monitor", __iconNode17);
1681
+ var Monitor = createLucideIcon("monitor", __iconNode18);
1643
1682
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mouse-pointer-2.js
1644
- var __iconNode18 = [
1683
+ var __iconNode19 = [
1645
1684
  [
1646
1685
  "path",
1647
1686
  {
@@ -1650,15 +1689,15 @@ var __iconNode18 = [
1650
1689
  }
1651
1690
  ]
1652
1691
  ];
1653
- var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode18);
1692
+ var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode19);
1654
1693
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/pause.js
1655
- var __iconNode19 = [
1694
+ var __iconNode20 = [
1656
1695
  ["rect", { x: "14", y: "3", width: "5", height: "18", rx: "1", key: "kaeet6" }],
1657
1696
  ["rect", { x: "5", y: "3", width: "5", height: "18", rx: "1", key: "1wsw3u" }]
1658
1697
  ];
1659
- var Pause = createLucideIcon("pause", __iconNode19);
1698
+ var Pause = createLucideIcon("pause", __iconNode20);
1660
1699
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
1661
- var __iconNode20 = [
1700
+ var __iconNode21 = [
1662
1701
  [
1663
1702
  "path",
1664
1703
  {
@@ -1675,9 +1714,9 @@ var __iconNode20 = [
1675
1714
  }
1676
1715
  ]
1677
1716
  ];
1678
- var PhoneOff = createLucideIcon("phone-off", __iconNode20);
1717
+ var PhoneOff = createLucideIcon("phone-off", __iconNode21);
1679
1718
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/play.js
1680
- var __iconNode21 = [
1719
+ var __iconNode22 = [
1681
1720
  [
1682
1721
  "path",
1683
1722
  {
@@ -1686,9 +1725,9 @@ var __iconNode21 = [
1686
1725
  }
1687
1726
  ]
1688
1727
  ];
1689
- var Play = createLucideIcon("play", __iconNode21);
1728
+ var Play = createLucideIcon("play", __iconNode22);
1690
1729
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/rocket.js
1691
- var __iconNode22 = [
1730
+ var __iconNode23 = [
1692
1731
  ["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5", key: "qeys4" }],
1693
1732
  [
1694
1733
  "path",
@@ -1706,9 +1745,9 @@ var __iconNode22 = [
1706
1745
  ],
1707
1746
  ["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05", key: "92ym6u" }]
1708
1747
  ];
1709
- var Rocket = createLucideIcon("rocket", __iconNode22);
1748
+ var Rocket = createLucideIcon("rocket", __iconNode23);
1710
1749
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
1711
- var __iconNode23 = [
1750
+ var __iconNode24 = [
1712
1751
  [
1713
1752
  "path",
1714
1753
  {
@@ -1718,15 +1757,15 @@ var __iconNode23 = [
1718
1757
  ],
1719
1758
  ["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
1720
1759
  ];
1721
- var Send = createLucideIcon("send", __iconNode23);
1760
+ var Send = createLucideIcon("send", __iconNode24);
1722
1761
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/user-plus.js
1723
- var __iconNode24 = [
1762
+ var __iconNode25 = [
1724
1763
  ["path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" }],
1725
1764
  ["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }],
1726
1765
  ["line", { x1: "19", x2: "19", y1: "8", y2: "14", key: "1bvyxn" }],
1727
1766
  ["line", { x1: "22", x2: "16", y1: "11", y2: "11", key: "1shjgl" }]
1728
1767
  ];
1729
- var UserPlus = createLucideIcon("user-plus", __iconNode24);
1768
+ var UserPlus = createLucideIcon("user-plus", __iconNode25);
1730
1769
  // src/components/HighlightOverlay.tsx
1731
1770
  import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef4, useState as useState4 } from "react";
1732
1771
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1975,6 +2014,8 @@ function useLiveAgent() {
1975
2014
  throw new Error("useLiveAgent must be used within a <LiveAgent> provider");
1976
2015
  }
1977
2016
  const {
2017
+ usesHostAuth,
2018
+ authFailed,
1978
2019
  connection,
1979
2020
  shouldConnect,
1980
2021
  historyMessages,
@@ -3279,7 +3320,7 @@ function MessageList({
3279
3320
  }
3280
3321
 
3281
3322
  // src/components/ModuleSelector.tsx
3282
- import { useEffect as useEffect15, useMemo as useMemo5, useRef as useRef9, useState as useState10 } from "react";
3323
+ import { useEffect as useEffect15, useRef as useRef9, useState as useState10 } from "react";
3283
3324
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
3284
3325
  var AGENT_TYPE_ICONS = {
3285
3326
  onboarding: UserPlus,
@@ -3299,11 +3340,9 @@ function ModuleSelector() {
3299
3340
  selectModule,
3300
3341
  isStarting,
3301
3342
  isDisconnecting,
3302
- error,
3303
- resumableSessions
3343
+ error
3304
3344
  } = useLiveAgent();
3305
3345
  const isBusy = isStarting || isDisconnecting;
3306
- const resumableAgentIds = useMemo5(() => new Set(resumableSessions.map((s) => s.agentId)), [resumableSessions]);
3307
3346
  const scrollRef = useRef9(null);
3308
3347
  const [showScrollHint, setShowScrollHint] = useState10(false);
3309
3348
  const [isScrolled, setIsScrolled] = useState10(false);
@@ -3391,7 +3430,7 @@ function ModuleSelector() {
3391
3430
  const isFeatured = index2 === 0;
3392
3431
  const isWide = index2 === availableModules.length - 1 && availableModules.length % 2 === 1;
3393
3432
  const Icon2 = getAgentIcon(module.type);
3394
- const canResume = resumableAgentIds.has(module.id);
3433
+ const canResume = canResumeSession(module.currentSession, module.mode);
3395
3434
  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";
3396
3435
  const layout = isWide ? "skippr:items-center skippr:p-3.5 skippr:pb-5" : "skippr:flex-col skippr:items-start skippr:p-3.5";
3397
3436
  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";
@@ -3597,8 +3636,13 @@ function Sidebar({
3597
3636
  captureMode,
3598
3637
  hasModuleSelector,
3599
3638
  agentId,
3639
+ agentMode,
3600
3640
  agentControls
3601
3641
  } = useLiveAgent();
3642
+ const internalCtx = useContextValue(LiveAgentContext);
3643
+ const usesHostAuth = internalCtx?.usesHostAuth ?? false;
3644
+ const authFailed = internalCtx?.authFailed ?? false;
3645
+ const showAgenda = agentMode !== "always_on";
3602
3646
  const isFloating = variant === "floating";
3603
3647
  const isSidebar = variant === "sidebar";
3604
3648
  useEffect16(() => {
@@ -3620,17 +3664,7 @@ function Sidebar({
3620
3664
  style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
3621
3665
  children: [
3622
3666
  !hideHeader && /* @__PURE__ */ jsx18(ChatHeader, {}),
3623
- !isAuthenticated && isValidating ? /* @__PURE__ */ jsx18("div", {
3624
- className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
3625
- children: /* @__PURE__ */ jsx18(LoadingDots, {
3626
- label: "Loading..."
3627
- })
3628
- }) : !isAuthenticated ? /* @__PURE__ */ jsx18(LoginFlow, {
3629
- requestOtp,
3630
- verifyOtp,
3631
- error: authError,
3632
- isSubmitting: isAuthSubmitting
3633
- }) : /* @__PURE__ */ jsx18(AuthenticatedContent, {
3667
+ authFailed ? /* @__PURE__ */ jsx18(AuthError, {}) : isAuthenticated ? /* @__PURE__ */ jsx18(AuthenticatedContent, {
3634
3668
  isConnected,
3635
3669
  isPaused,
3636
3670
  isPausing,
@@ -3650,7 +3684,18 @@ function Sidebar({
3650
3684
  showScreenShareToggle: captureMode === "screenshare",
3651
3685
  hasModuleSelector,
3652
3686
  agentId,
3653
- agentControls
3687
+ agentControls,
3688
+ showAgenda
3689
+ }) : usesHostAuth || isValidating ? /* @__PURE__ */ jsx18("div", {
3690
+ className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
3691
+ children: /* @__PURE__ */ jsx18(LoadingDots, {
3692
+ label: "Loading..."
3693
+ })
3694
+ }) : /* @__PURE__ */ jsx18(LoginFlow, {
3695
+ requestOtp,
3696
+ verifyOtp,
3697
+ error: authError,
3698
+ isSubmitting: isAuthSubmitting
3654
3699
  })
3655
3700
  ]
3656
3701
  });
@@ -3675,11 +3720,13 @@ function AuthenticatedContent({
3675
3720
  showScreenShareToggle,
3676
3721
  hasModuleSelector,
3677
3722
  agentId,
3678
- agentControls
3723
+ agentControls,
3724
+ showAgenda
3679
3725
  }) {
3680
3726
  const inSession = isConnected || isStarting || isPaused || isPausing;
3681
3727
  const showSelectorAsPrompt = hasModuleSelector && !inSession && !isDisconnecting;
3682
3728
  const showTabBar = !showSelectorAsPrompt;
3729
+ const effectiveTab = showAgenda ? activeTab : "chat";
3683
3730
  let transitionLabel = null;
3684
3731
  if (isPausing) {
3685
3732
  transitionLabel = "Pausing...";
@@ -3708,7 +3755,7 @@ function AuthenticatedContent({
3708
3755
  })
3709
3756
  ]
3710
3757
  }),
3711
- /* @__PURE__ */ jsxs16("button", {
3758
+ showAgenda && /* @__PURE__ */ jsxs16("button", {
3712
3759
  type: "button",
3713
3760
  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"),
3714
3761
  onClick: () => onTabChange("agenda"),
@@ -3738,7 +3785,7 @@ function AuthenticatedContent({
3738
3785
  children: transitionLabel
3739
3786
  }),
3740
3787
  /* @__PURE__ */ jsx18(ConnectedBody, {
3741
- activeTab,
3788
+ activeTab: effectiveTab,
3742
3789
  autoFocusChat
3743
3790
  })
3744
3791
  ]
@@ -3767,6 +3814,24 @@ function AuthenticatedContent({
3767
3814
  ]
3768
3815
  });
3769
3816
  }
3817
+ function AuthError() {
3818
+ return /* @__PURE__ */ jsxs16("div", {
3819
+ className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:justify-center skippr:px-6 skippr:py-4 skippr:text-center",
3820
+ children: [
3821
+ /* @__PURE__ */ jsx18(CircleAlert, {
3822
+ className: "skippr:mb-3 skippr:size-7 skippr:text-destructive"
3823
+ }),
3824
+ /* @__PURE__ */ jsx18("p", {
3825
+ className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
3826
+ children: "We couldn't verify your session"
3827
+ }),
3828
+ /* @__PURE__ */ jsx18("p", {
3829
+ className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
3830
+ children: "Please contact administrator."
3831
+ })
3832
+ ]
3833
+ });
3834
+ }
3770
3835
  function ConnectedBanner() {
3771
3836
  const remaining = useSessionRemaining();
3772
3837
  return /* @__PURE__ */ jsx18(SessionWarningBanner, {
@@ -3828,6 +3893,7 @@ function LiveAgent(props) {
3828
3893
  agentId: hostAgentId,
3829
3894
  authToken: authTokenProp,
3830
3895
  appKey,
3896
+ getUserToken,
3831
3897
  userToken,
3832
3898
  position = "right",
3833
3899
  variant = "floating",
@@ -3850,7 +3916,8 @@ function LiveAgent(props) {
3850
3916
  }
3851
3917
  }
3852
3918
  const auth = useAuth({ appKey });
3853
- const effectiveAuthToken = authTokenProp || auth.authToken || undefined;
3919
+ const usesHostAuth = !!getUserToken || !!userToken || !!authTokenProp;
3920
+ const effectiveAuthToken = usesHostAuth ? authTokenProp : auth.authToken ?? undefined;
3854
3921
  const hasModuleSelector = !hostAgentId;
3855
3922
  const [activeModule, setActiveModule] = useState11(null);
3856
3923
  const agentId = hasModuleSelector ? activeModule?.id ?? null : hostAgentId;
@@ -3884,17 +3951,18 @@ function LiveAgent(props) {
3884
3951
  errorCode,
3885
3952
  startSession,
3886
3953
  pauseSession,
3887
- resumeSession: resumeSessionById,
3888
3954
  disconnect,
3889
3955
  isPaused,
3890
- resumableSessions,
3891
3956
  historyMessages,
3892
3957
  pendingScreenStream,
3893
- bearerToken
3958
+ bearerToken,
3959
+ authedFetch,
3960
+ authFailed
3894
3961
  } = useSession({
3895
3962
  captureMode,
3896
3963
  authToken: effectiveAuthToken,
3897
3964
  appKey,
3965
+ getUserToken,
3898
3966
  userToken,
3899
3967
  onStart: minimizeOnSessionStart,
3900
3968
  onStartError: expandOnSessionStartError,
@@ -3907,12 +3975,6 @@ function LiveAgent(props) {
3907
3975
  return;
3908
3976
  disconnect();
3909
3977
  }, [disconnect]);
3910
- const resumableSession = resumableSessions.find((s) => s.agentId === agentId) ?? null;
3911
- const resumeSession = useCallback8(async () => {
3912
- if (!resumableSession)
3913
- return;
3914
- await resumeSessionById({ sessionId: resumableSession.id, agentControls });
3915
- }, [resumableSession, resumeSessionById, agentControls]);
3916
3978
  const [isPanelOpen, setIsPanelOpen] = useState11(defaultOpen);
3917
3979
  const [isMinimized, setIsMinimized] = useState11(minimizable && !defaultOpen);
3918
3980
  const [sidebarTab, setSidebarTab] = useState11("agenda");
@@ -3924,20 +3986,38 @@ function LiveAgent(props) {
3924
3986
  refetch: refetchModules
3925
3987
  } = useAvailableModules({
3926
3988
  enabled: hasModuleSelector && isPanelOpen,
3927
- bearerToken
3989
+ bearerToken,
3990
+ authedFetch
3928
3991
  });
3992
+ const activeModuleForAgent = useMemo5(() => {
3993
+ if (activeModule)
3994
+ return activeModule;
3995
+ if (!hostAgentId)
3996
+ return null;
3997
+ return availableModules.find((m) => m.id === hostAgentId) ?? null;
3998
+ }, [activeModule, hostAgentId, availableModules]);
3999
+ const agentMode = activeModuleForAgent?.mode ?? null;
4000
+ const resumableSession = useMemo5(() => getResumableSession(activeModuleForAgent), [activeModuleForAgent]);
4001
+ const resumeSession = useCallback8(async () => {
4002
+ if (!resumableSession)
4003
+ return;
4004
+ await startSession({
4005
+ agentId: resumableSession.agentId,
4006
+ agentControls,
4007
+ existingSessionId: resumableSession.id
4008
+ });
4009
+ }, [resumableSession, startSession, agentControls]);
3929
4010
  const selectModule = useCallback8((moduleId) => {
3930
4011
  const found = availableModules.find((m) => m.id === moduleId);
3931
4012
  if (!found)
3932
4013
  return;
3933
4014
  setActiveModule(found);
3934
- const resumable = resumableSessions.find((s) => s.agentId === found.id);
3935
- if (resumable) {
3936
- resumeSessionById({ sessionId: resumable.id, agentControls: found.controls });
3937
- } else {
3938
- startSession({ agentId: found.id, agentControls: found.controls });
3939
- }
3940
- }, [availableModules, resumableSessions, startSession, resumeSessionById]);
4015
+ startSession({
4016
+ agentId: found.id,
4017
+ agentControls: found.controls,
4018
+ existingSessionId: getResumableSessionId(found.currentSession, found.mode)
4019
+ });
4020
+ }, [availableModules, startSession]);
3941
4021
  const [welcomeDismissed, setWelcomeDismissed] = useState11(false);
3942
4022
  const dismissWelcome = useCallback8(() => setWelcomeDismissed(true), []);
3943
4023
  const [currentPosition, setCurrentPosition] = useState11(() => {
@@ -3968,8 +4048,8 @@ function LiveAgent(props) {
3968
4048
  setIsPanelOpen(false);
3969
4049
  }, [minimizable]);
3970
4050
  const isConnected = connection !== null;
3971
- const isAuthenticated = !!userToken || !!authTokenProp || auth.isAuthenticated;
3972
- const ctx = useMemo6(() => ({
4051
+ const isAuthenticated = bearerToken !== null || auth.isAuthenticated;
4052
+ const ctx = useMemo5(() => ({
3973
4053
  connection,
3974
4054
  shouldConnect,
3975
4055
  isConnected,
@@ -3984,7 +4064,6 @@ function LiveAgent(props) {
3984
4064
  disconnect,
3985
4065
  isPaused,
3986
4066
  resumableSession,
3987
- resumableSessions,
3988
4067
  historyMessages,
3989
4068
  phasesSnapshot,
3990
4069
  setPhasesSnapshot,
@@ -4000,6 +4079,8 @@ function LiveAgent(props) {
4000
4079
  expandPanel,
4001
4080
  minimizePanel,
4002
4081
  isAuthenticated,
4082
+ usesHostAuth,
4083
+ authFailed,
4003
4084
  isValidating: auth.isValidating,
4004
4085
  authError: auth.error,
4005
4086
  requestOtp: auth.requestOtp,
@@ -4011,6 +4092,7 @@ function LiveAgent(props) {
4011
4092
  autoFocusChat,
4012
4093
  captureMode,
4013
4094
  agentId,
4095
+ agentMode,
4014
4096
  agentControls,
4015
4097
  hasModuleSelector,
4016
4098
  availableModules,
@@ -4034,7 +4116,6 @@ function LiveAgent(props) {
4034
4116
  disconnect,
4035
4117
  isPaused,
4036
4118
  resumableSession,
4037
- resumableSessions,
4038
4119
  historyMessages,
4039
4120
  phasesSnapshot,
4040
4121
  isPanelOpen,
@@ -4049,6 +4130,8 @@ function LiveAgent(props) {
4049
4130
  expandPanel,
4050
4131
  minimizePanel,
4051
4132
  isAuthenticated,
4133
+ usesHostAuth,
4134
+ authFailed,
4052
4135
  auth.isValidating,
4053
4136
  auth.error,
4054
4137
  auth.requestOtp,
@@ -4059,6 +4142,7 @@ function LiveAgent(props) {
4059
4142
  autoFocusChat,
4060
4143
  captureMode,
4061
4144
  agentId,
4145
+ agentMode,
4062
4146
  agentControls,
4063
4147
  hasModuleSelector,
4064
4148
  availableModules,