@skippr/live-agent-sdk 0.36.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.
@@ -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,
@@ -274,25 +279,106 @@ function useSession({
274
279
  const [isPaused, setIsPaused] = useState3(false);
275
280
  const [isPausing, setIsPausing] = useState3(false);
276
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]);
277
363
  useEffect3(() => {
278
364
  let stale = false;
279
365
  if (authToken) {
366
+ tokenRef.current = { token: authToken, expiresAt: null };
280
367
  setBearerToken(authToken);
281
368
  return;
282
369
  }
283
- if (appKey && userToken) {
284
- exchangeForBearerToken(appKey, userToken).then((token) => {
285
- if (!stale)
286
- setBearerToken(token);
287
- }).catch((e) => {
288
- if (!stale)
289
- 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);
290
376
  });
291
377
  }
292
378
  return () => {
293
379
  stale = true;
294
380
  };
295
- }, [authToken, appKey, userToken]);
381
+ }, [authToken, canExchange, reExchange]);
296
382
  const pauseOnUnloadRef = useRef(null);
297
383
  pauseOnUnloadRef.current = connection !== null && !isPaused && sessionId && bearerToken ? { sessionId, bearerToken } : null;
298
384
  useEffect3(() => {
@@ -328,14 +414,12 @@ function useSession({
328
414
  screenStream = await requestScreenShare();
329
415
  }
330
416
  const requestAgentControls = agentControls?.highlight === true ? { highlight: true } : undefined;
331
- const headers = { Authorization: `Bearer ${bearerToken}` };
332
417
  try {
333
418
  let resolvedSessionId = existingSessionId;
334
419
  if (!resolvedSessionId) {
335
- const createResp = await fetch(`${API_URL3}/v1/sessions`, {
420
+ const createResp = await authedFetch(`${API_URL3}/v1/sessions`, {
336
421
  method: "POST",
337
- credentials: "omit",
338
- headers: { "Content-Type": "application/json", ...headers },
422
+ headers: { "Content-Type": "application/json" },
339
423
  body: JSON.stringify({
340
424
  agentId,
341
425
  captureMode,
@@ -350,10 +434,9 @@ function useSession({
350
434
  const { session: session2 } = await createResp.json();
351
435
  resolvedSessionId = session2.id;
352
436
  }
353
- const startResp = await fetch(`${API_URL3}/v1/sessions/${resolvedSessionId}/start`, {
437
+ const startResp = await authedFetch(`${API_URL3}/v1/sessions/${resolvedSessionId}/start`, {
354
438
  method: "POST",
355
- credentials: "omit",
356
- headers: { "Content-Type": "application/json", ...headers },
439
+ headers: { "Content-Type": "application/json" },
357
440
  body: JSON.stringify({ captureMode, agentControls: requestAgentControls })
358
441
  });
359
442
  if (!startResp.ok) {
@@ -362,7 +445,7 @@ function useSession({
362
445
  throw new Error(body?.detail || `Failed to start session: ${startResp.status}`);
363
446
  }
364
447
  const { session, connection: conn } = await startResp.json();
365
- const history2 = existingSessionId ? await fetchSessionMessages(session.id, bearerToken) : [];
448
+ const history2 = existingSessionId ? await fetchSessionMessages(session.id, authedFetch) : [];
366
449
  setSessionId(session.id);
367
450
  setHistoryMessages(history2);
368
451
  setConnection({
@@ -379,16 +462,14 @@ function useSession({
379
462
  } finally {
380
463
  setIsStarting(false);
381
464
  }
382
- }, [captureMode, bearerToken, onStart, onStartError]);
465
+ }, [captureMode, bearerToken, authedFetch, onStart, onStartError]);
383
466
  const pauseSession = useCallback3(async () => {
384
467
  if (!sessionId || !bearerToken)
385
468
  return;
386
469
  setIsPausing(true);
387
470
  try {
388
- const resp = await fetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
389
- method: "POST",
390
- credentials: "omit",
391
- headers: { Authorization: `Bearer ${bearerToken}` }
471
+ const resp = await authedFetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
472
+ method: "POST"
392
473
  });
393
474
  if (!resp.ok) {
394
475
  const body = await resp.json().catch(() => null);
@@ -399,7 +480,7 @@ function useSession({
399
480
  setIsPausing(false);
400
481
  return;
401
482
  }
402
- const history2 = await fetchSessionMessages(sessionId, bearerToken);
483
+ const history2 = await fetchSessionMessages(sessionId, authedFetch);
403
484
  stopStream(pendingScreenStream);
404
485
  setPendingScreenStream(null);
405
486
  setShouldConnect(false);
@@ -407,16 +488,14 @@ function useSession({
407
488
  setHistoryMessages(history2);
408
489
  setIsPaused(true);
409
490
  setIsPausing(false);
410
- }, [sessionId, bearerToken, pendingScreenStream]);
491
+ }, [sessionId, bearerToken, authedFetch, pendingScreenStream]);
411
492
  const disconnect = useCallback3(async () => {
412
493
  setIsDisconnecting(true);
413
494
  try {
414
495
  if (sessionId && bearerToken) {
415
496
  try {
416
- await fetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
417
- method: "POST",
418
- credentials: "omit",
419
- headers: { Authorization: `Bearer ${bearerToken}` }
497
+ await authedFetch(`${API_URL3}/v1/sessions/${sessionId}/pause`, {
498
+ method: "POST"
420
499
  });
421
500
  } catch {}
422
501
  }
@@ -432,7 +511,7 @@ function useSession({
432
511
  } finally {
433
512
  setIsDisconnecting(false);
434
513
  }
435
- }, [sessionId, bearerToken, pendingScreenStream, onDisconnect]);
514
+ }, [sessionId, bearerToken, authedFetch, pendingScreenStream, onDisconnect]);
436
515
  return {
437
516
  connection,
438
517
  shouldConnect,
@@ -447,7 +526,9 @@ function useSession({
447
526
  isPausing,
448
527
  historyMessages,
449
528
  pendingScreenStream,
450
- bearerToken
529
+ bearerToken,
530
+ authedFetch,
531
+ authFailed
451
532
  };
452
533
  }
453
534
 
@@ -1450,17 +1531,24 @@ var createLucideIcon = (iconName, iconNode) => {
1450
1531
  return Component;
1451
1532
  };
1452
1533
 
1453
- // ../../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
1454
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 = [
1455
1543
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
1456
1544
  ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
1457
1545
  ];
1458
- var CircleCheck = createLucideIcon("circle-check", __iconNode);
1546
+ var CircleCheck = createLucideIcon("circle-check", __iconNode2);
1459
1547
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/loader-circle.js
1460
- var __iconNode2 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1461
- 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);
1462
1550
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/sparkles.js
1463
- var __iconNode3 = [
1551
+ var __iconNode4 = [
1464
1552
  [
1465
1553
  "path",
1466
1554
  {
@@ -1472,9 +1560,9 @@ var __iconNode3 = [
1472
1560
  ["path", { d: "M22 4h-4", key: "gwowj6" }],
1473
1561
  ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
1474
1562
  ];
1475
- var Sparkles = createLucideIcon("sparkles", __iconNode3);
1563
+ var Sparkles = createLucideIcon("sparkles", __iconNode4);
1476
1564
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/bot.js
1477
- var __iconNode4 = [
1565
+ var __iconNode5 = [
1478
1566
  ["path", { d: "M12 8V4H8", key: "hb8ula" }],
1479
1567
  ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
1480
1568
  ["path", { d: "M2 14h2", key: "vft8re" }],
@@ -1482,23 +1570,23 @@ var __iconNode4 = [
1482
1570
  ["path", { d: "M15 13v2", key: "1xurst" }],
1483
1571
  ["path", { d: "M9 13v2", key: "rq6x2g" }]
1484
1572
  ];
1485
- var Bot = createLucideIcon("bot", __iconNode4);
1573
+ var Bot = createLucideIcon("bot", __iconNode5);
1486
1574
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/calendar.js
1487
- var __iconNode5 = [
1575
+ var __iconNode6 = [
1488
1576
  ["path", { d: "M8 2v4", key: "1cmpym" }],
1489
1577
  ["path", { d: "M16 2v4", key: "4m81vk" }],
1490
1578
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
1491
1579
  ["path", { d: "M3 10h18", key: "8toen8" }]
1492
1580
  ];
1493
- var Calendar = createLucideIcon("calendar", __iconNode5);
1581
+ var Calendar = createLucideIcon("calendar", __iconNode6);
1494
1582
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/chevron-down.js
1495
- var __iconNode6 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
1496
- 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);
1497
1585
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle.js
1498
- var __iconNode7 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
1499
- var Circle = createLucideIcon("circle", __iconNode7);
1586
+ var __iconNode8 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
1587
+ var Circle = createLucideIcon("circle", __iconNode8);
1500
1588
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/graduation-cap.js
1501
- var __iconNode8 = [
1589
+ var __iconNode9 = [
1502
1590
  [
1503
1591
  "path",
1504
1592
  {
@@ -1509,9 +1597,9 @@ var __iconNode8 = [
1509
1597
  ["path", { d: "M22 10v6", key: "1lu8f3" }],
1510
1598
  ["path", { d: "M6 12.5V16a6 3 0 0 0 12 0v-3.5", key: "1r8lef" }]
1511
1599
  ];
1512
- var GraduationCap = createLucideIcon("graduation-cap", __iconNode8);
1600
+ var GraduationCap = createLucideIcon("graduation-cap", __iconNode9);
1513
1601
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/headset.js
1514
- var __iconNode9 = [
1602
+ var __iconNode10 = [
1515
1603
  [
1516
1604
  "path",
1517
1605
  {
@@ -1521,15 +1609,15 @@ var __iconNode9 = [
1521
1609
  ],
1522
1610
  ["path", { d: "M21 16v2a4 4 0 0 1-4 4h-5", key: "1x7m43" }]
1523
1611
  ];
1524
- var Headset = createLucideIcon("headset", __iconNode9);
1612
+ var Headset = createLucideIcon("headset", __iconNode10);
1525
1613
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mail.js
1526
- var __iconNode10 = [
1614
+ var __iconNode11 = [
1527
1615
  ["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7", key: "132q7q" }],
1528
1616
  ["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }]
1529
1617
  ];
1530
- var Mail = createLucideIcon("mail", __iconNode10);
1618
+ var Mail = createLucideIcon("mail", __iconNode11);
1531
1619
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-circle.js
1532
- var __iconNode11 = [
1620
+ var __iconNode12 = [
1533
1621
  [
1534
1622
  "path",
1535
1623
  {
@@ -1538,9 +1626,9 @@ var __iconNode11 = [
1538
1626
  }
1539
1627
  ]
1540
1628
  ];
1541
- var MessageCircle = createLucideIcon("message-circle", __iconNode11);
1629
+ var MessageCircle = createLucideIcon("message-circle", __iconNode12);
1542
1630
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-square.js
1543
- var __iconNode12 = [
1631
+ var __iconNode13 = [
1544
1632
  [
1545
1633
  "path",
1546
1634
  {
@@ -1549,9 +1637,9 @@ var __iconNode12 = [
1549
1637
  }
1550
1638
  ]
1551
1639
  ];
1552
- var MessageSquare = createLucideIcon("message-square", __iconNode12);
1640
+ var MessageSquare = createLucideIcon("message-square", __iconNode13);
1553
1641
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic-off.js
1554
- var __iconNode13 = [
1642
+ var __iconNode14 = [
1555
1643
  ["path", { d: "M12 19v3", key: "npa21l" }],
1556
1644
  ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
1557
1645
  ["path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2", key: "cqa7eg" }],
@@ -1559,40 +1647,40 @@ var __iconNode13 = [
1559
1647
  ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1560
1648
  ["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }]
1561
1649
  ];
1562
- var MicOff = createLucideIcon("mic-off", __iconNode13);
1650
+ var MicOff = createLucideIcon("mic-off", __iconNode14);
1563
1651
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic.js
1564
- var __iconNode14 = [
1652
+ var __iconNode15 = [
1565
1653
  ["path", { d: "M12 19v3", key: "npa21l" }],
1566
1654
  ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
1567
1655
  ["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
1568
1656
  ];
1569
- var Mic = createLucideIcon("mic", __iconNode14);
1657
+ var Mic = createLucideIcon("mic", __iconNode15);
1570
1658
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/minimize-2.js
1571
- var __iconNode15 = [
1659
+ var __iconNode16 = [
1572
1660
  ["path", { d: "m14 10 7-7", key: "oa77jy" }],
1573
1661
  ["path", { d: "M20 10h-6V4", key: "mjg0md" }],
1574
1662
  ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
1575
1663
  ["path", { d: "M4 14h6v6", key: "rmj7iw" }]
1576
1664
  ];
1577
- var Minimize2 = createLucideIcon("minimize-2", __iconNode15);
1665
+ var Minimize2 = createLucideIcon("minimize-2", __iconNode16);
1578
1666
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor-off.js
1579
- var __iconNode16 = [
1667
+ var __iconNode17 = [
1580
1668
  ["path", { d: "M12 17v4", key: "1riwvh" }],
1581
1669
  ["path", { d: "M17 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 1.184-1.826", key: "cv7jms" }],
1582
1670
  ["path", { d: "m2 2 20 20", key: "1ooewy" }],
1583
1671
  ["path", { d: "M8 21h8", key: "1ev6f3" }],
1584
1672
  ["path", { d: "M8.656 3H20a2 2 0 0 1 2 2v10a2 2 0 0 1-.293 1.042", key: "z8ni2w" }]
1585
1673
  ];
1586
- var MonitorOff = createLucideIcon("monitor-off", __iconNode16);
1674
+ var MonitorOff = createLucideIcon("monitor-off", __iconNode17);
1587
1675
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.js
1588
- var __iconNode17 = [
1676
+ var __iconNode18 = [
1589
1677
  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
1590
1678
  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
1591
1679
  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
1592
1680
  ];
1593
- var Monitor = createLucideIcon("monitor", __iconNode17);
1681
+ var Monitor = createLucideIcon("monitor", __iconNode18);
1594
1682
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mouse-pointer-2.js
1595
- var __iconNode18 = [
1683
+ var __iconNode19 = [
1596
1684
  [
1597
1685
  "path",
1598
1686
  {
@@ -1601,15 +1689,15 @@ var __iconNode18 = [
1601
1689
  }
1602
1690
  ]
1603
1691
  ];
1604
- var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode18);
1692
+ var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode19);
1605
1693
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/pause.js
1606
- var __iconNode19 = [
1694
+ var __iconNode20 = [
1607
1695
  ["rect", { x: "14", y: "3", width: "5", height: "18", rx: "1", key: "kaeet6" }],
1608
1696
  ["rect", { x: "5", y: "3", width: "5", height: "18", rx: "1", key: "1wsw3u" }]
1609
1697
  ];
1610
- var Pause = createLucideIcon("pause", __iconNode19);
1698
+ var Pause = createLucideIcon("pause", __iconNode20);
1611
1699
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
1612
- var __iconNode20 = [
1700
+ var __iconNode21 = [
1613
1701
  [
1614
1702
  "path",
1615
1703
  {
@@ -1626,9 +1714,9 @@ var __iconNode20 = [
1626
1714
  }
1627
1715
  ]
1628
1716
  ];
1629
- var PhoneOff = createLucideIcon("phone-off", __iconNode20);
1717
+ var PhoneOff = createLucideIcon("phone-off", __iconNode21);
1630
1718
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/play.js
1631
- var __iconNode21 = [
1719
+ var __iconNode22 = [
1632
1720
  [
1633
1721
  "path",
1634
1722
  {
@@ -1637,9 +1725,9 @@ var __iconNode21 = [
1637
1725
  }
1638
1726
  ]
1639
1727
  ];
1640
- var Play = createLucideIcon("play", __iconNode21);
1728
+ var Play = createLucideIcon("play", __iconNode22);
1641
1729
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/rocket.js
1642
- var __iconNode22 = [
1730
+ var __iconNode23 = [
1643
1731
  ["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5", key: "qeys4" }],
1644
1732
  [
1645
1733
  "path",
@@ -1657,9 +1745,9 @@ var __iconNode22 = [
1657
1745
  ],
1658
1746
  ["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05", key: "92ym6u" }]
1659
1747
  ];
1660
- var Rocket = createLucideIcon("rocket", __iconNode22);
1748
+ var Rocket = createLucideIcon("rocket", __iconNode23);
1661
1749
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
1662
- var __iconNode23 = [
1750
+ var __iconNode24 = [
1663
1751
  [
1664
1752
  "path",
1665
1753
  {
@@ -1669,15 +1757,15 @@ var __iconNode23 = [
1669
1757
  ],
1670
1758
  ["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
1671
1759
  ];
1672
- var Send = createLucideIcon("send", __iconNode23);
1760
+ var Send = createLucideIcon("send", __iconNode24);
1673
1761
  // ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/user-plus.js
1674
- var __iconNode24 = [
1762
+ var __iconNode25 = [
1675
1763
  ["path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" }],
1676
1764
  ["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }],
1677
1765
  ["line", { x1: "19", x2: "19", y1: "8", y2: "14", key: "1bvyxn" }],
1678
1766
  ["line", { x1: "22", x2: "16", y1: "11", y2: "11", key: "1shjgl" }]
1679
1767
  ];
1680
- var UserPlus = createLucideIcon("user-plus", __iconNode24);
1768
+ var UserPlus = createLucideIcon("user-plus", __iconNode25);
1681
1769
  // src/components/HighlightOverlay.tsx
1682
1770
  import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef4, useState as useState4 } from "react";
1683
1771
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1926,6 +2014,8 @@ function useLiveAgent() {
1926
2014
  throw new Error("useLiveAgent must be used within a <LiveAgent> provider");
1927
2015
  }
1928
2016
  const {
2017
+ usesHostAuth,
2018
+ authFailed,
1929
2019
  connection,
1930
2020
  shouldConnect,
1931
2021
  historyMessages,
@@ -3549,6 +3639,9 @@ function Sidebar({
3549
3639
  agentMode,
3550
3640
  agentControls
3551
3641
  } = useLiveAgent();
3642
+ const internalCtx = useContextValue(LiveAgentContext);
3643
+ const usesHostAuth = internalCtx?.usesHostAuth ?? false;
3644
+ const authFailed = internalCtx?.authFailed ?? false;
3552
3645
  const showAgenda = agentMode !== "always_on";
3553
3646
  const isFloating = variant === "floating";
3554
3647
  const isSidebar = variant === "sidebar";
@@ -3571,17 +3664,7 @@ function Sidebar({
3571
3664
  style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
3572
3665
  children: [
3573
3666
  !hideHeader && /* @__PURE__ */ jsx18(ChatHeader, {}),
3574
- !isAuthenticated && isValidating ? /* @__PURE__ */ jsx18("div", {
3575
- className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
3576
- children: /* @__PURE__ */ jsx18(LoadingDots, {
3577
- label: "Loading..."
3578
- })
3579
- }) : !isAuthenticated ? /* @__PURE__ */ jsx18(LoginFlow, {
3580
- requestOtp,
3581
- verifyOtp,
3582
- error: authError,
3583
- isSubmitting: isAuthSubmitting
3584
- }) : /* @__PURE__ */ jsx18(AuthenticatedContent, {
3667
+ authFailed ? /* @__PURE__ */ jsx18(AuthError, {}) : isAuthenticated ? /* @__PURE__ */ jsx18(AuthenticatedContent, {
3585
3668
  isConnected,
3586
3669
  isPaused,
3587
3670
  isPausing,
@@ -3603,6 +3686,16 @@ function Sidebar({
3603
3686
  agentId,
3604
3687
  agentControls,
3605
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
3606
3699
  })
3607
3700
  ]
3608
3701
  });
@@ -3721,6 +3814,24 @@ function AuthenticatedContent({
3721
3814
  ]
3722
3815
  });
3723
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
+ }
3724
3835
  function ConnectedBanner() {
3725
3836
  const remaining = useSessionRemaining();
3726
3837
  return /* @__PURE__ */ jsx18(SessionWarningBanner, {
@@ -3782,6 +3893,7 @@ function LiveAgent(props) {
3782
3893
  agentId: hostAgentId,
3783
3894
  authToken: authTokenProp,
3784
3895
  appKey,
3896
+ getUserToken,
3785
3897
  userToken,
3786
3898
  position = "right",
3787
3899
  variant = "floating",
@@ -3804,7 +3916,8 @@ function LiveAgent(props) {
3804
3916
  }
3805
3917
  }
3806
3918
  const auth = useAuth({ appKey });
3807
- const effectiveAuthToken = authTokenProp || auth.authToken || undefined;
3919
+ const usesHostAuth = !!getUserToken || !!userToken || !!authTokenProp;
3920
+ const effectiveAuthToken = usesHostAuth ? authTokenProp : auth.authToken ?? undefined;
3808
3921
  const hasModuleSelector = !hostAgentId;
3809
3922
  const [activeModule, setActiveModule] = useState11(null);
3810
3923
  const agentId = hasModuleSelector ? activeModule?.id ?? null : hostAgentId;
@@ -3842,11 +3955,14 @@ function LiveAgent(props) {
3842
3955
  isPaused,
3843
3956
  historyMessages,
3844
3957
  pendingScreenStream,
3845
- bearerToken
3958
+ bearerToken,
3959
+ authedFetch,
3960
+ authFailed
3846
3961
  } = useSession({
3847
3962
  captureMode,
3848
3963
  authToken: effectiveAuthToken,
3849
3964
  appKey,
3965
+ getUserToken,
3850
3966
  userToken,
3851
3967
  onStart: minimizeOnSessionStart,
3852
3968
  onStartError: expandOnSessionStartError,
@@ -3870,7 +3986,8 @@ function LiveAgent(props) {
3870
3986
  refetch: refetchModules
3871
3987
  } = useAvailableModules({
3872
3988
  enabled: hasModuleSelector && isPanelOpen,
3873
- bearerToken
3989
+ bearerToken,
3990
+ authedFetch
3874
3991
  });
3875
3992
  const activeModuleForAgent = useMemo5(() => {
3876
3993
  if (activeModule)
@@ -3931,7 +4048,7 @@ function LiveAgent(props) {
3931
4048
  setIsPanelOpen(false);
3932
4049
  }, [minimizable]);
3933
4050
  const isConnected = connection !== null;
3934
- const isAuthenticated = !!userToken || !!authTokenProp || auth.isAuthenticated;
4051
+ const isAuthenticated = bearerToken !== null || auth.isAuthenticated;
3935
4052
  const ctx = useMemo5(() => ({
3936
4053
  connection,
3937
4054
  shouldConnect,
@@ -3962,6 +4079,8 @@ function LiveAgent(props) {
3962
4079
  expandPanel,
3963
4080
  minimizePanel,
3964
4081
  isAuthenticated,
4082
+ usesHostAuth,
4083
+ authFailed,
3965
4084
  isValidating: auth.isValidating,
3966
4085
  authError: auth.error,
3967
4086
  requestOtp: auth.requestOtp,
@@ -4011,6 +4130,8 @@ function LiveAgent(props) {
4011
4130
  expandPanel,
4012
4131
  minimizePanel,
4013
4132
  isAuthenticated,
4133
+ usesHostAuth,
4134
+ authFailed,
4014
4135
  auth.isValidating,
4015
4136
  auth.error,
4016
4137
  auth.requestOtp,