@skippr/live-agent-sdk 0.82.0 → 0.83.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 +1 -0
- package/dist/esm/lib-exports.js +377 -229
- package/dist/skippr-sdk.js +121 -121
- package/dist/types/capture/pausedScreenTrack.d.ts +2 -0
- package/dist/types/hooks/useElapsedSeconds.d.ts +1 -1
- package/dist/types/hooks/useIsSessionHeld.d.ts +1 -0
- package/dist/types/hooks/useSessionHold.d.ts +3 -1
- package/dist/types/lib-exports.d.ts +1 -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 useCallback18, useEffect as useEffect29, useMemo as useMemo7, useRef as
|
|
11
|
+
import { useCallback as useCallback18, useEffect as useEffect29, useMemo as useMemo7, useRef as useRef25, useState as useState21 } from "react";
|
|
12
12
|
|
|
13
13
|
// src/capture/useAgentCursor.ts
|
|
14
14
|
import { useEffect, useState } from "react";
|
|
@@ -118,42 +118,177 @@ function useLiveAgent() {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
// src/hooks/useSessionHold.ts
|
|
121
|
+
import { useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
|
|
122
|
+
import { Track } from "livekit-client";
|
|
123
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
124
|
+
|
|
125
|
+
// src/capture/pausedScreenTrack.ts
|
|
126
|
+
var FALLBACK_WIDTH = 1280;
|
|
127
|
+
var FALLBACK_HEIGHT = 720;
|
|
128
|
+
var DIM_OVERLAY = "rgba(15, 15, 20, 0.55)";
|
|
129
|
+
var AMBER = "#F5B300";
|
|
130
|
+
var LABEL = "Paused";
|
|
131
|
+
var PAUSED_FRAME_FPS = 30;
|
|
132
|
+
var LAST_FRAME_READY_TIMEOUT_MS = 500;
|
|
133
|
+
function drawPausedOverlay(canvas, ctx) {
|
|
134
|
+
const { width, height } = canvas;
|
|
135
|
+
ctx.fillStyle = DIM_OVERLAY;
|
|
136
|
+
ctx.fillRect(0, 0, width, height);
|
|
137
|
+
const fontSize = Math.round(height * 0.07);
|
|
138
|
+
ctx.font = `600 ${fontSize}px system-ui, sans-serif`;
|
|
139
|
+
ctx.textAlign = "center";
|
|
140
|
+
ctx.textBaseline = "middle";
|
|
141
|
+
ctx.fillStyle = AMBER;
|
|
142
|
+
ctx.fillText(LABEL, width / 2, height / 2);
|
|
143
|
+
}
|
|
144
|
+
async function drawLiveScreenFrameInto(ctx, sourceTrack, width, height) {
|
|
145
|
+
const video = document.createElement("video");
|
|
146
|
+
video.muted = true;
|
|
147
|
+
video.srcObject = new MediaStream([sourceTrack]);
|
|
148
|
+
try {
|
|
149
|
+
await video.play();
|
|
150
|
+
await waitForDecodedFrame(video);
|
|
151
|
+
ctx.drawImage(video, 0, 0, width, height);
|
|
152
|
+
return true;
|
|
153
|
+
} catch {
|
|
154
|
+
return false;
|
|
155
|
+
} finally {
|
|
156
|
+
video.srcObject = null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function waitForDecodedFrame(video) {
|
|
160
|
+
if (video.readyState >= video.HAVE_CURRENT_DATA)
|
|
161
|
+
return;
|
|
162
|
+
await new Promise((resolve) => {
|
|
163
|
+
const timeout = setTimeout(resolve, LAST_FRAME_READY_TIMEOUT_MS);
|
|
164
|
+
video.addEventListener("loadeddata", () => {
|
|
165
|
+
clearTimeout(timeout);
|
|
166
|
+
resolve();
|
|
167
|
+
}, { once: true });
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function createPausedScreenTrack(sourceTrack) {
|
|
171
|
+
const settings = sourceTrack.getSettings();
|
|
172
|
+
const width = settings.width ?? FALLBACK_WIDTH;
|
|
173
|
+
const height = settings.height ?? FALLBACK_HEIGHT;
|
|
174
|
+
const canvas = document.createElement("canvas");
|
|
175
|
+
canvas.width = width;
|
|
176
|
+
canvas.height = height;
|
|
177
|
+
const ctx = canvas.getContext("2d");
|
|
178
|
+
if (!ctx)
|
|
179
|
+
return null;
|
|
180
|
+
const captureStream = canvas.captureStream;
|
|
181
|
+
if (typeof captureStream !== "function")
|
|
182
|
+
return null;
|
|
183
|
+
const capturedLiveFrame = await drawLiveScreenFrameInto(ctx, sourceTrack, width, height);
|
|
184
|
+
if (!capturedLiveFrame) {
|
|
185
|
+
ctx.fillStyle = "#0f0f14";
|
|
186
|
+
ctx.fillRect(0, 0, width, height);
|
|
187
|
+
}
|
|
188
|
+
drawPausedOverlay(canvas, ctx);
|
|
189
|
+
const track = captureStream.call(canvas, PAUSED_FRAME_FPS).getVideoTracks()[0] ?? null;
|
|
190
|
+
if (!track)
|
|
191
|
+
return null;
|
|
192
|
+
track.contentHint = "text";
|
|
193
|
+
return track;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/hooks/useMediaControls.ts
|
|
121
197
|
import { useLocalParticipant } from "@livekit/components-react/hooks";
|
|
122
|
-
import {
|
|
198
|
+
import { ScreenSharePresets } from "livekit-client";
|
|
199
|
+
import { useCallback } from "react";
|
|
200
|
+
var SCREEN_SHARE_OPTIONS = {
|
|
201
|
+
video: { displaySurface: "browser" },
|
|
202
|
+
resolution: ScreenSharePresets.h720fps30.resolution,
|
|
203
|
+
contentHint: "detail"
|
|
204
|
+
};
|
|
205
|
+
function useMediaControls() {
|
|
206
|
+
const { localParticipant } = useLocalParticipant();
|
|
207
|
+
const isMuted = !localParticipant.isMicrophoneEnabled;
|
|
208
|
+
const isScreenSharing = localParticipant.isScreenShareEnabled;
|
|
209
|
+
const toggleMute = useCallback(async () => {
|
|
210
|
+
try {
|
|
211
|
+
await localParticipant.setMicrophoneEnabled(isMuted);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error("Failed to toggle microphone:", error);
|
|
214
|
+
}
|
|
215
|
+
}, [localParticipant, isMuted]);
|
|
216
|
+
const toggleScreenShare = useCallback(async () => {
|
|
217
|
+
try {
|
|
218
|
+
await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error("Failed to toggle screen share:", error);
|
|
221
|
+
}
|
|
222
|
+
}, [localParticipant, isScreenSharing]);
|
|
223
|
+
return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/hooks/useSessionHold.ts
|
|
123
227
|
var textEncoder = new TextEncoder;
|
|
124
228
|
var FALLBACK_PAUSE_TIMEOUT_SECONDS = 120;
|
|
125
229
|
function useSessionHold({
|
|
126
230
|
pauseSession,
|
|
127
|
-
pauseTimeoutSeconds
|
|
231
|
+
pauseTimeoutSeconds,
|
|
232
|
+
captureMode
|
|
128
233
|
}) {
|
|
129
|
-
const { localParticipant } =
|
|
234
|
+
const { localParticipant } = useLocalParticipant2();
|
|
130
235
|
const timeoutSeconds = pauseTimeoutSeconds ?? FALLBACK_PAUSE_TIMEOUT_SECONDS;
|
|
131
236
|
const [isHeld, setIsHeld] = useState2(false);
|
|
132
237
|
const [countdown, setCountdown] = useState2(timeoutSeconds);
|
|
133
|
-
const
|
|
238
|
+
const screenWasSharedBeforeHoldRef = useRef(false);
|
|
239
|
+
const holdTransitionInFlightRef = useRef(false);
|
|
240
|
+
const publish = useCallback2(async (type) => {
|
|
134
241
|
await localParticipant.publishData(textEncoder.encode(JSON.stringify({ type })), {
|
|
135
242
|
reliable: true,
|
|
136
243
|
topic: SESSION_HOLD_TOPIC
|
|
137
244
|
});
|
|
138
245
|
}, [localParticipant]);
|
|
139
|
-
const
|
|
246
|
+
const screenShareTrack = useCallback2(() => {
|
|
247
|
+
return localParticipant.getTrackPublication(Track.Source.ScreenShare)?.videoTrack;
|
|
248
|
+
}, [localParticipant]);
|
|
249
|
+
const pauseScreenShareForHold = useCallback2(async () => {
|
|
250
|
+
if (captureMode !== CAPTURE_MODE.Screenshare)
|
|
251
|
+
return;
|
|
252
|
+
screenWasSharedBeforeHoldRef.current = localParticipant.isScreenShareEnabled;
|
|
253
|
+
const track = screenShareTrack();
|
|
254
|
+
const liveScreenTrack = track?.mediaStreamTrack;
|
|
255
|
+
if (!track || !liveScreenTrack)
|
|
256
|
+
return;
|
|
257
|
+
const pausedFrame = await createPausedScreenTrack(liveScreenTrack);
|
|
258
|
+
if (pausedFrame)
|
|
259
|
+
await track.replaceTrack(pausedFrame);
|
|
260
|
+
liveScreenTrack.stop();
|
|
261
|
+
}, [captureMode, localParticipant, screenShareTrack]);
|
|
262
|
+
const resumeScreenShareOnResume = useCallback2(async () => {
|
|
263
|
+
if (captureMode !== CAPTURE_MODE.Screenshare || !screenWasSharedBeforeHoldRef.current)
|
|
264
|
+
return;
|
|
265
|
+
await localParticipant.setScreenShareEnabled(false);
|
|
266
|
+
await localParticipant.setScreenShareEnabled(true, SCREEN_SHARE_OPTIONS);
|
|
267
|
+
}, [captureMode, localParticipant]);
|
|
268
|
+
const micTrack = useCallback2(() => {
|
|
269
|
+
return localParticipant.getTrackPublication(Track.Source.Microphone)?.audioTrack;
|
|
270
|
+
}, [localParticipant]);
|
|
271
|
+
const hold = useCallback2(async () => {
|
|
140
272
|
try {
|
|
141
273
|
await localParticipant.setMicrophoneEnabled(false);
|
|
274
|
+
micTrack()?.mediaStreamTrack?.stop();
|
|
275
|
+
await pauseScreenShareForHold();
|
|
142
276
|
await publish("pause");
|
|
143
277
|
setIsHeld(true);
|
|
144
278
|
} catch (error) {
|
|
145
279
|
console.error("Failed to hold session:", error);
|
|
146
280
|
}
|
|
147
|
-
}, [localParticipant, publish]);
|
|
148
|
-
const release =
|
|
281
|
+
}, [localParticipant, publish, pauseScreenShareForHold, micTrack]);
|
|
282
|
+
const release = useCallback2(async () => {
|
|
149
283
|
try {
|
|
150
284
|
await localParticipant.setMicrophoneEnabled(true);
|
|
285
|
+
await resumeScreenShareOnResume();
|
|
151
286
|
await publish("resume");
|
|
152
287
|
setIsHeld(false);
|
|
153
288
|
} catch (error) {
|
|
154
289
|
console.error("Failed to release session:", error);
|
|
155
290
|
}
|
|
156
|
-
}, [localParticipant, publish]);
|
|
291
|
+
}, [localParticipant, publish, resumeScreenShareOnResume]);
|
|
157
292
|
useEffect2(() => {
|
|
158
293
|
if (!isHeld) {
|
|
159
294
|
setCountdown(timeoutSeconds);
|
|
@@ -170,12 +305,14 @@ function useSessionHold({
|
|
|
170
305
|
pauseSession();
|
|
171
306
|
}
|
|
172
307
|
}, [isHeld, countdown, pauseSession]);
|
|
173
|
-
const toggle =
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
308
|
+
const toggle = useCallback2(() => {
|
|
309
|
+
if (holdTransitionInFlightRef.current)
|
|
310
|
+
return;
|
|
311
|
+
holdTransitionInFlightRef.current = true;
|
|
312
|
+
const transition = isHeld ? release : hold;
|
|
313
|
+
transition().finally(() => {
|
|
314
|
+
holdTransitionInFlightRef.current = false;
|
|
315
|
+
});
|
|
179
316
|
}, [isHeld, hold, release]);
|
|
180
317
|
return { isHeld, countdown, toggle };
|
|
181
318
|
}
|
|
@@ -195,7 +332,8 @@ function SessionHoldProvider({ children }) {
|
|
|
195
332
|
}
|
|
196
333
|
const hold = useSessionHold({
|
|
197
334
|
pauseSession,
|
|
198
|
-
pauseTimeoutSeconds: internalCtx.pauseTimeoutSeconds
|
|
335
|
+
pauseTimeoutSeconds: internalCtx.pauseTimeoutSeconds,
|
|
336
|
+
captureMode: internalCtx.captureMode
|
|
199
337
|
});
|
|
200
338
|
return /* @__PURE__ */ jsx(SessionHoldContext.Provider, {
|
|
201
339
|
value: hold,
|
|
@@ -226,20 +364,20 @@ function useSharedTranscriptions() {
|
|
|
226
364
|
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
227
365
|
|
|
228
366
|
// src/hooks/useVoiceTurn.ts
|
|
229
|
-
import { useLocalParticipant as
|
|
230
|
-
import { useCallback as
|
|
367
|
+
import { useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react/hooks";
|
|
368
|
+
import { useCallback as useCallback3, useRef as useRef2, useState as useState3 } from "react";
|
|
231
369
|
var textEncoder2 = new TextEncoder;
|
|
232
370
|
function useVoiceTurn() {
|
|
233
|
-
const { localParticipant } =
|
|
371
|
+
const { localParticipant } = useLocalParticipant3();
|
|
234
372
|
const [isCapturingSpeech, setIsCapturingSpeech] = useState3(false);
|
|
235
|
-
const capturingRef =
|
|
236
|
-
const publish =
|
|
373
|
+
const capturingRef = useRef2(false);
|
|
374
|
+
const publish = useCallback3(async (type) => {
|
|
237
375
|
await localParticipant.publishData(textEncoder2.encode(JSON.stringify({ type })), {
|
|
238
376
|
reliable: true,
|
|
239
377
|
topic: MIC_MODE_TURN_TOPIC
|
|
240
378
|
});
|
|
241
379
|
}, [localParticipant]);
|
|
242
|
-
const startRecording =
|
|
380
|
+
const startRecording = useCallback3(async () => {
|
|
243
381
|
try {
|
|
244
382
|
await localParticipant.setMicrophoneEnabled(true);
|
|
245
383
|
await publish("start");
|
|
@@ -247,7 +385,7 @@ function useVoiceTurn() {
|
|
|
247
385
|
console.error("Failed to start voice turn:", error);
|
|
248
386
|
}
|
|
249
387
|
}, [localParticipant, publish]);
|
|
250
|
-
const commitRecording =
|
|
388
|
+
const commitRecording = useCallback3(async () => {
|
|
251
389
|
try {
|
|
252
390
|
await localParticipant.setMicrophoneEnabled(false);
|
|
253
391
|
await publish("commit");
|
|
@@ -255,21 +393,21 @@ function useVoiceTurn() {
|
|
|
255
393
|
console.error("Failed to commit voice turn:", error);
|
|
256
394
|
}
|
|
257
395
|
}, [localParticipant, publish]);
|
|
258
|
-
const start =
|
|
396
|
+
const start = useCallback3(() => {
|
|
259
397
|
if (capturingRef.current)
|
|
260
398
|
return;
|
|
261
399
|
capturingRef.current = true;
|
|
262
400
|
setIsCapturingSpeech(true);
|
|
263
401
|
startRecording();
|
|
264
402
|
}, [startRecording]);
|
|
265
|
-
const commit =
|
|
403
|
+
const commit = useCallback3(() => {
|
|
266
404
|
if (!capturingRef.current)
|
|
267
405
|
return;
|
|
268
406
|
capturingRef.current = false;
|
|
269
407
|
setIsCapturingSpeech(false);
|
|
270
408
|
commitRecording();
|
|
271
409
|
}, [commitRecording]);
|
|
272
|
-
const toggle =
|
|
410
|
+
const toggle = useCallback3(() => {
|
|
273
411
|
if (capturingRef.current)
|
|
274
412
|
commit();
|
|
275
413
|
else
|
|
@@ -298,7 +436,7 @@ function useVoiceTurnContext() {
|
|
|
298
436
|
}
|
|
299
437
|
|
|
300
438
|
// src/hooks/useAdoptionGoals.ts
|
|
301
|
-
import { useCallback as
|
|
439
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useMemo, useState as useState4 } from "react";
|
|
302
440
|
|
|
303
441
|
// src/lib/hashMatch.ts
|
|
304
442
|
function globToRegExp(pattern) {
|
|
@@ -368,7 +506,7 @@ function useAdoptionGoals({
|
|
|
368
506
|
}) {
|
|
369
507
|
const [candidates, setCandidates] = useState4([]);
|
|
370
508
|
const [hash, setHash] = useState4(window.location.hash);
|
|
371
|
-
const match =
|
|
509
|
+
const match = useCallback4(async () => {
|
|
372
510
|
try {
|
|
373
511
|
const resp = await authedFetch(`${API_URL}/v1/adoption/goals/match`, {
|
|
374
512
|
method: "POST",
|
|
@@ -418,21 +556,21 @@ function useAdoptionGoals({
|
|
|
418
556
|
return hashSpecific;
|
|
419
557
|
return candidates.filter((goal) => goal.hashPattern === null);
|
|
420
558
|
}, [candidates, hash]);
|
|
421
|
-
const postStatus =
|
|
559
|
+
const postStatus = useCallback4((goalId, status) => {
|
|
422
560
|
authedFetch(`${API_URL}/v1/adoption/goals/${goalId}/status`, {
|
|
423
561
|
method: "POST",
|
|
424
562
|
headers: { "Content-Type": "application/json" },
|
|
425
563
|
body: JSON.stringify({ status })
|
|
426
564
|
}).catch((e) => console.warn("[Skippr] adoption status update failed", e));
|
|
427
565
|
}, [authedFetch]);
|
|
428
|
-
const attendGoal =
|
|
566
|
+
const attendGoal = useCallback4((goalId) => {
|
|
429
567
|
postStatus(goalId, "attended" /* Attended */);
|
|
430
568
|
}, [postStatus]);
|
|
431
569
|
return { goals, attendGoal };
|
|
432
570
|
}
|
|
433
571
|
|
|
434
572
|
// src/hooks/useAuth.ts
|
|
435
|
-
import { useCallback as
|
|
573
|
+
import { useCallback as useCallback5, useEffect as useEffect4, useState as useState5 } from "react";
|
|
436
574
|
var API_URL2 = "https://specialist.skippr.ai/api";
|
|
437
575
|
function storageKey(appKey) {
|
|
438
576
|
return `skippr_auth_${appKey}`;
|
|
@@ -498,7 +636,7 @@ function useAuth({ appKey }) {
|
|
|
498
636
|
window.addEventListener("skippr:logout", handleLogout);
|
|
499
637
|
return () => window.removeEventListener("skippr:logout", handleLogout);
|
|
500
638
|
}, []);
|
|
501
|
-
const requestOtp =
|
|
639
|
+
const requestOtp = useCallback5(async (email) => {
|
|
502
640
|
if (!appKey)
|
|
503
641
|
return false;
|
|
504
642
|
setIsSubmitting(true);
|
|
@@ -525,7 +663,7 @@ function useAuth({ appKey }) {
|
|
|
525
663
|
setIsSubmitting(false);
|
|
526
664
|
}
|
|
527
665
|
}, [appKey]);
|
|
528
|
-
const verifyOtp =
|
|
666
|
+
const verifyOtp = useCallback5(async (email, code) => {
|
|
529
667
|
if (!appKey)
|
|
530
668
|
return;
|
|
531
669
|
setIsSubmitting(true);
|
|
@@ -554,7 +692,7 @@ function useAuth({ appKey }) {
|
|
|
554
692
|
setIsSubmitting(false);
|
|
555
693
|
}
|
|
556
694
|
}, [appKey]);
|
|
557
|
-
const logout =
|
|
695
|
+
const logout = useCallback5(async () => {
|
|
558
696
|
const token = authToken;
|
|
559
697
|
if (appKey)
|
|
560
698
|
clearStoredToken(appKey);
|
|
@@ -585,7 +723,7 @@ function useAuth({ appKey }) {
|
|
|
585
723
|
}
|
|
586
724
|
|
|
587
725
|
// src/hooks/useAutoStart.ts
|
|
588
|
-
import { useEffect as useEffect5, useMemo as useMemo2, useRef as
|
|
726
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
589
727
|
|
|
590
728
|
// src/lib/agentMode.ts
|
|
591
729
|
var AGENT_MODE = {
|
|
@@ -665,7 +803,7 @@ function useAutoStart({
|
|
|
665
803
|
bearerToken,
|
|
666
804
|
selectModule
|
|
667
805
|
}) {
|
|
668
|
-
const hasAutoStartedRef =
|
|
806
|
+
const hasAutoStartedRef = useRef3(false);
|
|
669
807
|
const autoStartModule = useMemo2(() => availableModules.find((m) => {
|
|
670
808
|
if (!m.uiPreferences?.autoStart)
|
|
671
809
|
return false;
|
|
@@ -704,7 +842,7 @@ function useAutoStart({
|
|
|
704
842
|
}
|
|
705
843
|
|
|
706
844
|
// src/hooks/useAvailableModules.ts
|
|
707
|
-
import { useCallback as
|
|
845
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
|
|
708
846
|
var EMPTY_DEFAULT = { agentId: null, sessionId: null };
|
|
709
847
|
var API_URL3 = "https://specialist.skippr.ai/api";
|
|
710
848
|
function useAvailableModules({
|
|
@@ -718,7 +856,7 @@ function useAvailableModules({
|
|
|
718
856
|
const [isLoading, setIsLoading] = useState6(false);
|
|
719
857
|
const [hasResolved, setHasResolved] = useState6(false);
|
|
720
858
|
const [error, setError] = useState6(null);
|
|
721
|
-
const fetchModules =
|
|
859
|
+
const fetchModules = useCallback6(async () => {
|
|
722
860
|
setIsLoading(true);
|
|
723
861
|
setHasResolved(false);
|
|
724
862
|
setError(null);
|
|
@@ -755,7 +893,7 @@ function useAvailableModules({
|
|
|
755
893
|
}
|
|
756
894
|
|
|
757
895
|
// src/hooks/usePlanUpdates.ts
|
|
758
|
-
import { useCallback as
|
|
896
|
+
import { useCallback as useCallback7 } from "react";
|
|
759
897
|
|
|
760
898
|
// src/hooks/useAgentState.ts
|
|
761
899
|
import { useRemoteParticipants } from "@livekit/components-react/hooks";
|
|
@@ -809,12 +947,12 @@ function parsePlan(json) {
|
|
|
809
947
|
return null;
|
|
810
948
|
}
|
|
811
949
|
function usePlanUpdates() {
|
|
812
|
-
const parse =
|
|
950
|
+
const parse = useCallback7(parsePlan, []);
|
|
813
951
|
return useAgentState(PLAN_ATTR, parse, null);
|
|
814
952
|
}
|
|
815
953
|
|
|
816
954
|
// src/hooks/useSession.ts
|
|
817
|
-
import { useCallback as
|
|
955
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef4, useState as useState8 } from "react";
|
|
818
956
|
var API_URL4 = "https://specialist.skippr.ai/api";
|
|
819
957
|
async function fetchSessionMessages(sessionId, authedFetch) {
|
|
820
958
|
try {
|
|
@@ -880,13 +1018,13 @@ function useSession({
|
|
|
880
1018
|
const [pauseTimeoutSeconds, setPauseTimeoutSeconds] = useState8(null);
|
|
881
1019
|
const [historyMessages, setHistoryMessages] = useState8([]);
|
|
882
1020
|
const [authFailed, setAuthFailed] = useState8(false);
|
|
883
|
-
const tokenRef =
|
|
884
|
-
const getUserTokenRef =
|
|
1021
|
+
const tokenRef = useRef4(authToken ? { token: authToken, expiresAt: null } : null);
|
|
1022
|
+
const getUserTokenRef = useRef4(getUserToken);
|
|
885
1023
|
getUserTokenRef.current = getUserToken ?? (userToken ? () => Promise.resolve(userToken) : undefined);
|
|
886
|
-
const failedBearerRef =
|
|
887
|
-
const inFlightExchangeRef =
|
|
888
|
-
const canExchange =
|
|
889
|
-
const reExchange =
|
|
1024
|
+
const failedBearerRef = useRef4(null);
|
|
1025
|
+
const inFlightExchangeRef = useRef4(null);
|
|
1026
|
+
const canExchange = useCallback8(() => !!appKey && !!getUserTokenRef.current, [appKey]);
|
|
1027
|
+
const reExchange = useCallback8(async () => {
|
|
890
1028
|
if (inFlightExchangeRef.current)
|
|
891
1029
|
return inFlightExchangeRef.current;
|
|
892
1030
|
const provider = getUserTokenRef.current;
|
|
@@ -906,7 +1044,7 @@ function useSession({
|
|
|
906
1044
|
inFlightExchangeRef.current = null;
|
|
907
1045
|
}
|
|
908
1046
|
}, [appKey]);
|
|
909
|
-
const getValidBearer =
|
|
1047
|
+
const getValidBearer = useCallback8(async () => {
|
|
910
1048
|
const current = tokenRef.current;
|
|
911
1049
|
if (current) {
|
|
912
1050
|
if (current.expiresAt === null)
|
|
@@ -918,7 +1056,7 @@ function useSession({
|
|
|
918
1056
|
return reExchange();
|
|
919
1057
|
return current?.token ?? null;
|
|
920
1058
|
}, [canExchange, reExchange]);
|
|
921
|
-
const authedFetch =
|
|
1059
|
+
const authedFetch = useCallback8(async (input, init = {}) => {
|
|
922
1060
|
const isSecretMode = canExchange();
|
|
923
1061
|
const onTerminalAuthFailure = () => {
|
|
924
1062
|
if (isSecretMode)
|
|
@@ -979,8 +1117,8 @@ function useSession({
|
|
|
979
1117
|
stale = true;
|
|
980
1118
|
};
|
|
981
1119
|
}, [authToken, canExchange, reExchange]);
|
|
982
|
-
const isStartingRef =
|
|
983
|
-
const pauseOnUnloadRef =
|
|
1120
|
+
const isStartingRef = useRef4(false);
|
|
1121
|
+
const pauseOnUnloadRef = useRef4(null);
|
|
984
1122
|
pauseOnUnloadRef.current = connection !== null && !isPaused && sessionId && bearerToken ? { sessionId, bearerToken } : null;
|
|
985
1123
|
useEffect8(() => {
|
|
986
1124
|
const onPageHide = () => {
|
|
@@ -997,7 +1135,7 @@ function useSession({
|
|
|
997
1135
|
window.addEventListener("pagehide", onPageHide);
|
|
998
1136
|
return () => window.removeEventListener("pagehide", onPageHide);
|
|
999
1137
|
}, []);
|
|
1000
|
-
const startSession =
|
|
1138
|
+
const startSession = useCallback8(async ({
|
|
1001
1139
|
agentId,
|
|
1002
1140
|
agentControls,
|
|
1003
1141
|
existingSessionId,
|
|
@@ -1092,7 +1230,7 @@ function useSession({
|
|
|
1092
1230
|
setIsStarting(false);
|
|
1093
1231
|
}
|
|
1094
1232
|
}, [captureMode, bearerToken, authedFetch, onStart, onStartError]);
|
|
1095
|
-
const pauseSession =
|
|
1233
|
+
const pauseSession = useCallback8(async () => {
|
|
1096
1234
|
if (!sessionId || !bearerToken)
|
|
1097
1235
|
return;
|
|
1098
1236
|
setIsPausing(true);
|
|
@@ -1118,7 +1256,7 @@ function useSession({
|
|
|
1118
1256
|
setIsPaused(true);
|
|
1119
1257
|
setIsPausing(false);
|
|
1120
1258
|
}, [sessionId, bearerToken, authedFetch, pendingScreenStream]);
|
|
1121
|
-
const disconnect =
|
|
1259
|
+
const disconnect = useCallback8(async () => {
|
|
1122
1260
|
setIsDisconnecting(true);
|
|
1123
1261
|
try {
|
|
1124
1262
|
if (sessionId && bearerToken) {
|
|
@@ -1523,7 +1661,7 @@ var __iconNode24 = [
|
|
|
1523
1661
|
];
|
|
1524
1662
|
var X = createLucideIcon("x", __iconNode24);
|
|
1525
1663
|
// src/components/AgentCursor.tsx
|
|
1526
|
-
import { useContext as useContext6, useEffect as useEffect10, useLayoutEffect, useRef as
|
|
1664
|
+
import { useContext as useContext6, useEffect as useEffect10, useLayoutEffect, useRef as useRef5, useState as useState10 } from "react";
|
|
1527
1665
|
|
|
1528
1666
|
// src/capture/elementRef.ts
|
|
1529
1667
|
function safeGetIframeDocument(iframe) {
|
|
@@ -1711,13 +1849,13 @@ function AgentCursor({
|
|
|
1711
1849
|
const [phase, setPhase] = useState10("idle");
|
|
1712
1850
|
const [ringBox, setRingBox] = useState10(null);
|
|
1713
1851
|
const [clickPulse, setClickPulse] = useState10(0);
|
|
1714
|
-
const cursorElRef =
|
|
1715
|
-
const pathRef =
|
|
1716
|
-
const prevCursorRef =
|
|
1717
|
-
const traceRef =
|
|
1718
|
-
const timersRef =
|
|
1719
|
-
const trackFrameRef =
|
|
1720
|
-
const glideFrameRef =
|
|
1852
|
+
const cursorElRef = useRef5(null);
|
|
1853
|
+
const pathRef = useRef5(null);
|
|
1854
|
+
const prevCursorRef = useRef5(null);
|
|
1855
|
+
const traceRef = useRef5(null);
|
|
1856
|
+
const timersRef = useRef5(new Set);
|
|
1857
|
+
const trackFrameRef = useRef5(null);
|
|
1858
|
+
const glideFrameRef = useRef5(null);
|
|
1721
1859
|
const clearTimers = () => {
|
|
1722
1860
|
for (const t of timersRef.current)
|
|
1723
1861
|
clearTimeout(t);
|
|
@@ -1956,16 +2094,16 @@ function AgentCursor({
|
|
|
1956
2094
|
}
|
|
1957
2095
|
|
|
1958
2096
|
// src/components/AutoStartMedia.tsx
|
|
1959
|
-
import { useConnectionState, useLocalParticipant as
|
|
1960
|
-
import { ConnectionState, Track } from "livekit-client";
|
|
1961
|
-
import { useEffect as useEffect11, useRef as
|
|
2097
|
+
import { useConnectionState, useLocalParticipant as useLocalParticipant4 } from "@livekit/components-react/hooks";
|
|
2098
|
+
import { ConnectionState, Track as Track2 } from "livekit-client";
|
|
2099
|
+
import { useEffect as useEffect11, useRef as useRef6 } from "react";
|
|
1962
2100
|
function AutoStartMedia({
|
|
1963
2101
|
pendingScreenStream,
|
|
1964
2102
|
pushOrTapMicMode = false
|
|
1965
2103
|
}) {
|
|
1966
|
-
const { localParticipant } =
|
|
2104
|
+
const { localParticipant } = useLocalParticipant4();
|
|
1967
2105
|
const connectionState = useConnectionState();
|
|
1968
|
-
const didStartRef =
|
|
2106
|
+
const didStartRef = useRef6(false);
|
|
1969
2107
|
useEffect11(() => {
|
|
1970
2108
|
if (didStartRef.current)
|
|
1971
2109
|
return;
|
|
@@ -1979,7 +2117,7 @@ function AutoStartMedia({
|
|
|
1979
2117
|
const videoTrack = pendingScreenStream.getVideoTracks()[0];
|
|
1980
2118
|
if (videoTrack) {
|
|
1981
2119
|
videoTrack.contentHint = "detail";
|
|
1982
|
-
localParticipant.publishTrack(videoTrack, { source:
|
|
2120
|
+
localParticipant.publishTrack(videoTrack, { source: Track2.Source.ScreenShare }).catch((error) => {
|
|
1983
2121
|
console.error("Failed to publish screen share track:", error);
|
|
1984
2122
|
for (const track of pendingScreenStream.getTracks())
|
|
1985
2123
|
track.stop();
|
|
@@ -1991,9 +2129,9 @@ function AutoStartMedia({
|
|
|
1991
2129
|
}
|
|
1992
2130
|
|
|
1993
2131
|
// src/components/DomCapture.tsx
|
|
1994
|
-
import { useConnectionState as useConnectionState2, useLocalParticipant as
|
|
1995
|
-
import { ConnectionState as ConnectionState2, ScreenSharePresets, Track as
|
|
1996
|
-
import { useEffect as useEffect12, useRef as
|
|
2132
|
+
import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant5 } from "@livekit/components-react/hooks";
|
|
2133
|
+
import { ConnectionState as ConnectionState2, ScreenSharePresets as ScreenSharePresets2, Track as Track3 } from "livekit-client";
|
|
2134
|
+
import { useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
1997
2135
|
|
|
1998
2136
|
// src/capture/a11yUtils.ts
|
|
1999
2137
|
var ROLE_BY_TAG = {
|
|
@@ -2787,7 +2925,7 @@ async function snapToCanvas(element, options = {}) {
|
|
|
2787
2925
|
var SNAPSHOT_INTERVAL_MS = 3000;
|
|
2788
2926
|
var A11Y_PUBLISH_INTERVAL_MS = 2000;
|
|
2789
2927
|
var FIRST_SNAPSHOT_DELAY_MS = 400;
|
|
2790
|
-
var CAPTURE_PRESET =
|
|
2928
|
+
var CAPTURE_PRESET = ScreenSharePresets2.h1080fps30;
|
|
2791
2929
|
var CAPTURE_FPS = CAPTURE_PRESET.encoding.maxFramerate ?? 30;
|
|
2792
2930
|
var CAPTURE_BITRATE = 4000000;
|
|
2793
2931
|
var DOM_SNAPSHOT_GZIP_THRESHOLD_BYTES = 14000;
|
|
@@ -2823,7 +2961,7 @@ function getCanvasCaptureStream(canvas, fps) {
|
|
|
2823
2961
|
}
|
|
2824
2962
|
return captureStreamFn.call(canvas, fps);
|
|
2825
2963
|
}
|
|
2826
|
-
async function paintViewportSnapshot(canvas, ctx) {
|
|
2964
|
+
async function paintViewportSnapshot(canvas, ctx, isStillWanted) {
|
|
2827
2965
|
const dpr = window.devicePixelRatio || 1;
|
|
2828
2966
|
const snapshotCanvas = await snapToCanvas(document.documentElement, {
|
|
2829
2967
|
filter: shouldIncludeInSnapshot,
|
|
@@ -2832,6 +2970,8 @@ async function paintViewportSnapshot(canvas, ctx) {
|
|
|
2832
2970
|
fast: false,
|
|
2833
2971
|
dpr
|
|
2834
2972
|
});
|
|
2973
|
+
if (!isStillWanted())
|
|
2974
|
+
return;
|
|
2835
2975
|
const sourceX = window.scrollX * dpr;
|
|
2836
2976
|
const sourceY = window.scrollY * dpr;
|
|
2837
2977
|
const sourceWidth = window.innerWidth * dpr;
|
|
@@ -2892,9 +3032,13 @@ async function unpublishAndStopTrack(localParticipant, videoTrack) {
|
|
|
2892
3032
|
videoTrack.stop();
|
|
2893
3033
|
}
|
|
2894
3034
|
function DomCapture({ pushOrTapMicMode = false }) {
|
|
2895
|
-
const { localParticipant } =
|
|
3035
|
+
const { localParticipant } = useLocalParticipant5();
|
|
2896
3036
|
const connectionState = useConnectionState2();
|
|
2897
|
-
const
|
|
3037
|
+
const { isHeld } = useSessionHoldContext();
|
|
3038
|
+
const didStartRef = useRef7(false);
|
|
3039
|
+
const pausedRef = useRef7(false);
|
|
3040
|
+
const freezeCaptureRef = useRef7(null);
|
|
3041
|
+
const resumeCaptureRef = useRef7(null);
|
|
2898
3042
|
useEffect12(() => {
|
|
2899
3043
|
if (didStartRef.current)
|
|
2900
3044
|
return;
|
|
@@ -2916,11 +3060,11 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
2916
3060
|
let snapshotInFlight = false;
|
|
2917
3061
|
let a11yPublishInFlight = false;
|
|
2918
3062
|
let consecutiveCaptureFailures = 0;
|
|
2919
|
-
if (!pushOrTapMicMode) {
|
|
3063
|
+
if (!pushOrTapMicMode && !localParticipant.isMicrophoneEnabled) {
|
|
2920
3064
|
localParticipant.setMicrophoneEnabled(true).catch((error) => console.error("Failed to enable microphone:", error));
|
|
2921
3065
|
}
|
|
2922
3066
|
localParticipant.publishTrack(videoTrack, {
|
|
2923
|
-
source:
|
|
3067
|
+
source: Track3.Source.ScreenShare,
|
|
2924
3068
|
videoEncoding: {
|
|
2925
3069
|
maxBitrate: CAPTURE_BITRATE,
|
|
2926
3070
|
maxFramerate: CAPTURE_FPS
|
|
@@ -2932,11 +3076,11 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
2932
3076
|
track.stop();
|
|
2933
3077
|
});
|
|
2934
3078
|
const tickSnapshot = async () => {
|
|
2935
|
-
if (cancelled || snapshotInFlight)
|
|
3079
|
+
if (cancelled || snapshotInFlight || pausedRef.current)
|
|
2936
3080
|
return;
|
|
2937
3081
|
snapshotInFlight = true;
|
|
2938
3082
|
try {
|
|
2939
|
-
await paintViewportSnapshot(canvas, ctx);
|
|
3083
|
+
await paintViewportSnapshot(canvas, ctx, () => !cancelled && !pausedRef.current);
|
|
2940
3084
|
if (cancelled)
|
|
2941
3085
|
return;
|
|
2942
3086
|
consecutiveCaptureFailures = 0;
|
|
@@ -2952,7 +3096,7 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
2952
3096
|
}
|
|
2953
3097
|
};
|
|
2954
3098
|
const tickA11yPublish = async () => {
|
|
2955
|
-
if (cancelled || a11yPublishInFlight)
|
|
3099
|
+
if (cancelled || a11yPublishInFlight || pausedRef.current)
|
|
2956
3100
|
return;
|
|
2957
3101
|
a11yPublishInFlight = true;
|
|
2958
3102
|
try {
|
|
@@ -2989,9 +3133,20 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
2989
3133
|
scheduleNextSnapshot(FIRST_SNAPSHOT_DELAY_MS);
|
|
2990
3134
|
tickA11yPublish();
|
|
2991
3135
|
const a11yPublishTimer = setInterval(tickA11yPublish, A11Y_PUBLISH_INTERVAL_MS);
|
|
3136
|
+
freezeCaptureRef.current = () => {
|
|
3137
|
+
pausedRef.current = true;
|
|
3138
|
+
drawPausedOverlay(canvas, ctx);
|
|
3139
|
+
};
|
|
3140
|
+
resumeCaptureRef.current = () => {
|
|
3141
|
+
pausedRef.current = false;
|
|
3142
|
+
tickA11yPublish();
|
|
3143
|
+
tickSnapshot();
|
|
3144
|
+
};
|
|
2992
3145
|
return () => {
|
|
2993
3146
|
cancelled = true;
|
|
2994
3147
|
didStartRef.current = false;
|
|
3148
|
+
freezeCaptureRef.current = null;
|
|
3149
|
+
resumeCaptureRef.current = null;
|
|
2995
3150
|
if (snapshotTimer)
|
|
2996
3151
|
clearTimeout(snapshotTimer);
|
|
2997
3152
|
clearInterval(a11yPublishTimer);
|
|
@@ -3002,12 +3157,19 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
3002
3157
|
track.stop();
|
|
3003
3158
|
};
|
|
3004
3159
|
}, [connectionState, localParticipant, pushOrTapMicMode]);
|
|
3160
|
+
useEffect12(() => {
|
|
3161
|
+
if (isHeld) {
|
|
3162
|
+
freezeCaptureRef.current?.();
|
|
3163
|
+
} else {
|
|
3164
|
+
resumeCaptureRef.current?.();
|
|
3165
|
+
}
|
|
3166
|
+
}, [isHeld]);
|
|
3005
3167
|
return null;
|
|
3006
3168
|
}
|
|
3007
3169
|
|
|
3008
3170
|
// src/components/HighlightOverlay.tsx
|
|
3009
3171
|
import { useDataChannel } from "@livekit/components-react/hooks";
|
|
3010
|
-
import { useCallback as
|
|
3172
|
+
import { useCallback as useCallback9, useEffect as useEffect13, useRef as useRef8 } from "react";
|
|
3011
3173
|
var HIGHLIGHT_AUTO_CLEAR_MS = 25000;
|
|
3012
3174
|
var textDecoder = new TextDecoder;
|
|
3013
3175
|
function parseHighlightMessage(payload) {
|
|
@@ -3030,16 +3192,16 @@ function parseHighlightMessage(payload) {
|
|
|
3030
3192
|
}
|
|
3031
3193
|
}
|
|
3032
3194
|
function HighlightOverlay() {
|
|
3033
|
-
const targetRef =
|
|
3034
|
-
const autoClearRef =
|
|
3035
|
-
const clear =
|
|
3195
|
+
const targetRef = useRef8(null);
|
|
3196
|
+
const autoClearRef = useRef8(null);
|
|
3197
|
+
const clear = useCallback9(() => {
|
|
3036
3198
|
if (autoClearRef.current)
|
|
3037
3199
|
clearTimeout(autoClearRef.current);
|
|
3038
3200
|
autoClearRef.current = null;
|
|
3039
3201
|
targetRef.current = null;
|
|
3040
3202
|
clearCursorTarget("guide");
|
|
3041
3203
|
}, []);
|
|
3042
|
-
const onHighlightMessage =
|
|
3204
|
+
const onHighlightMessage = useCallback9((msg) => {
|
|
3043
3205
|
const parsed = parseHighlightMessage(msg.payload);
|
|
3044
3206
|
if (!parsed)
|
|
3045
3207
|
return;
|
|
@@ -3078,19 +3240,19 @@ function HighlightOverlay() {
|
|
|
3078
3240
|
}
|
|
3079
3241
|
|
|
3080
3242
|
// src/components/MinimizedBubble.tsx
|
|
3081
|
-
import { useContext as useContext7, useEffect as useEffect15, useRef as
|
|
3243
|
+
import { useContext as useContext7, useEffect as useEffect15, useRef as useRef10, useState as useState11 } from "react";
|
|
3082
3244
|
|
|
3083
3245
|
// src/hooks/useLauncherDrag.ts
|
|
3084
|
-
import { useEffect as useEffect14, useRef as
|
|
3246
|
+
import { useEffect as useEffect14, useRef as useRef9 } from "react";
|
|
3085
3247
|
import { flushSync } from "react-dom";
|
|
3086
3248
|
var DRAG_THRESHOLD_PX = 5;
|
|
3087
3249
|
function useLauncherDrag(containerRef, onDrop, followRefs, reportDragging) {
|
|
3088
|
-
const wasDraggedRef =
|
|
3089
|
-
const onDropRef =
|
|
3250
|
+
const wasDraggedRef = useRef9(false);
|
|
3251
|
+
const onDropRef = useRef9(onDrop);
|
|
3090
3252
|
onDropRef.current = onDrop;
|
|
3091
|
-
const followTargetsRef =
|
|
3253
|
+
const followTargetsRef = useRef9(followRefs);
|
|
3092
3254
|
followTargetsRef.current = followRefs;
|
|
3093
|
-
const reportDraggingRef =
|
|
3255
|
+
const reportDraggingRef = useRef9(reportDragging);
|
|
3094
3256
|
reportDraggingRef.current = reportDragging;
|
|
3095
3257
|
useEffect14(() => {
|
|
3096
3258
|
const el = containerRef.current;
|
|
@@ -3472,8 +3634,8 @@ function MinimizedBubble({
|
|
|
3472
3634
|
const [goalsAutoHidden, setGoalsAutoHidden] = useState11(false);
|
|
3473
3635
|
const [isLauncherHovered, setIsLauncherHovered] = useState11(false);
|
|
3474
3636
|
const [visitHref, setVisitHref] = useState11(() => window.location.href);
|
|
3475
|
-
const revealedHrefRef =
|
|
3476
|
-
const hoverContainerRef =
|
|
3637
|
+
const revealedHrefRef = useRef10(null);
|
|
3638
|
+
const hoverContainerRef = useRef10(null);
|
|
3477
3639
|
useEffect15(() => subscribeToLocationChange(() => setVisitHref(window.location.href)), []);
|
|
3478
3640
|
useEffect15(() => {
|
|
3479
3641
|
const el = hoverContainerRef.current;
|
|
@@ -3587,7 +3749,7 @@ function MinimizedBubble({
|
|
|
3587
3749
|
|
|
3588
3750
|
// src/components/PageActionHandler.tsx
|
|
3589
3751
|
import { useDataChannel as useDataChannel2 } from "@livekit/components-react/hooks";
|
|
3590
|
-
import { useCallback as
|
|
3752
|
+
import { useCallback as useCallback10, useEffect as useEffect16, useRef as useRef11 } from "react";
|
|
3591
3753
|
var STEP_MAX_WAIT_MS = 5000;
|
|
3592
3754
|
var POST_ACTION_SETTLE_SNAPSHOT_MS = 300;
|
|
3593
3755
|
var TRAILING_ACTION_FLUSH_AFTER_STOP_MS = 1000;
|
|
@@ -3805,14 +3967,14 @@ function labelFor(action) {
|
|
|
3805
3967
|
}
|
|
3806
3968
|
}
|
|
3807
3969
|
function PageActionHandler() {
|
|
3808
|
-
const mountedRef =
|
|
3809
|
-
const queueRef =
|
|
3810
|
-
const drainingRef =
|
|
3811
|
-
const settleTimerRef =
|
|
3812
|
-
const endStepRef =
|
|
3813
|
-
const actionsStoppedRef =
|
|
3814
|
-
const ignoreActionsArrivingBeforeRef =
|
|
3815
|
-
const runStep =
|
|
3970
|
+
const mountedRef = useRef11(true);
|
|
3971
|
+
const queueRef = useRef11([]);
|
|
3972
|
+
const drainingRef = useRef11(false);
|
|
3973
|
+
const settleTimerRef = useRef11(null);
|
|
3974
|
+
const endStepRef = useRef11(null);
|
|
3975
|
+
const actionsStoppedRef = useRef11(false);
|
|
3976
|
+
const ignoreActionsArrivingBeforeRef = useRef11(0);
|
|
3977
|
+
const runStep = useCallback10((action) => {
|
|
3816
3978
|
return new Promise((resolve) => {
|
|
3817
3979
|
if (action.type === "scroll_page") {
|
|
3818
3980
|
let scrolled = false;
|
|
@@ -3881,7 +4043,7 @@ function PageActionHandler() {
|
|
|
3881
4043
|
});
|
|
3882
4044
|
});
|
|
3883
4045
|
}, []);
|
|
3884
|
-
const drain =
|
|
4046
|
+
const drain = useCallback10(async () => {
|
|
3885
4047
|
if (drainingRef.current)
|
|
3886
4048
|
return;
|
|
3887
4049
|
drainingRef.current = true;
|
|
@@ -3902,7 +4064,7 @@ function PageActionHandler() {
|
|
|
3902
4064
|
}
|
|
3903
4065
|
}
|
|
3904
4066
|
}, [runStep]);
|
|
3905
|
-
const onMessage =
|
|
4067
|
+
const onMessage = useCallback10((msg) => {
|
|
3906
4068
|
const action = parsePageAction(msg.payload);
|
|
3907
4069
|
if (!action)
|
|
3908
4070
|
return;
|
|
@@ -3944,16 +4106,16 @@ function PageActionHandler() {
|
|
|
3944
4106
|
import { useCallback as useCallback13, useContext as useContext8, useEffect as useEffect21, useState as useState14 } from "react";
|
|
3945
4107
|
|
|
3946
4108
|
// src/hooks/useActionControl.ts
|
|
3947
|
-
import { useLocalParticipant as
|
|
3948
|
-
import { useCallback as
|
|
4109
|
+
import { useLocalParticipant as useLocalParticipant6 } from "@livekit/components-react/hooks";
|
|
4110
|
+
import { useCallback as useCallback11, useEffect as useEffect17, useState as useState12 } from "react";
|
|
3949
4111
|
var textEncoder5 = new TextEncoder;
|
|
3950
4112
|
function useActionControl() {
|
|
3951
|
-
const { localParticipant } =
|
|
4113
|
+
const { localParticipant } = useLocalParticipant6();
|
|
3952
4114
|
const plan = usePlanUpdates();
|
|
3953
4115
|
const [busy, setBusy] = useState12(isActionsBusy);
|
|
3954
4116
|
useEffect17(() => subscribeActionsBusy(setBusy), []);
|
|
3955
4117
|
const actionsActive = busy || plan?.state === "executing";
|
|
3956
|
-
const requestStop =
|
|
4118
|
+
const requestStop = useCallback11(async () => {
|
|
3957
4119
|
stopActions();
|
|
3958
4120
|
try {
|
|
3959
4121
|
await localParticipant.publishData(textEncoder5.encode(JSON.stringify({ type: "abort" })), {
|
|
@@ -3980,11 +4142,11 @@ function useAgentVoiceState() {
|
|
|
3980
4142
|
}
|
|
3981
4143
|
|
|
3982
4144
|
// src/hooks/useAudioLevelBars.ts
|
|
3983
|
-
import { useEffect as useEffect18, useRef as
|
|
4145
|
+
import { useEffect as useEffect18, useRef as useRef12, useState as useState13 } from "react";
|
|
3984
4146
|
var TALKING_LEVEL_THRESHOLD = 0.2;
|
|
3985
4147
|
var TALKING_HOLD_MS = 400;
|
|
3986
4148
|
function useAudioLevelBars(mediaStreamTrack, { barCount, idleHeightPx, maxGrowthPx, noiseGate }) {
|
|
3987
|
-
const barRefs =
|
|
4149
|
+
const barRefs = useRef12([]);
|
|
3988
4150
|
const [isTalking, setIsTalking] = useState13(false);
|
|
3989
4151
|
useEffect18(() => {
|
|
3990
4152
|
if (!mediaStreamTrack) {
|
|
@@ -4037,27 +4199,27 @@ function useAudioLevelBars(mediaStreamTrack, { barCount, idleHeightPx, maxGrowth
|
|
|
4037
4199
|
}
|
|
4038
4200
|
|
|
4039
4201
|
// src/hooks/useIdleAutoPause.ts
|
|
4040
|
-
import { useCallback as
|
|
4202
|
+
import { useCallback as useCallback12, useEffect as useEffect19, useRef as useRef13 } from "react";
|
|
4041
4203
|
function useIdleAutoPause({
|
|
4042
4204
|
enabled,
|
|
4043
4205
|
active,
|
|
4044
4206
|
isHeld,
|
|
4045
4207
|
pause
|
|
4046
4208
|
}) {
|
|
4047
|
-
const timerRef =
|
|
4048
|
-
const pauseRef =
|
|
4209
|
+
const timerRef = useRef13(null);
|
|
4210
|
+
const pauseRef = useRef13(pause);
|
|
4049
4211
|
pauseRef.current = pause;
|
|
4050
|
-
const clearTimer =
|
|
4212
|
+
const clearTimer = useCallback12(() => {
|
|
4051
4213
|
if (timerRef.current) {
|
|
4052
4214
|
clearTimeout(timerRef.current);
|
|
4053
4215
|
timerRef.current = null;
|
|
4054
4216
|
}
|
|
4055
4217
|
}, []);
|
|
4056
|
-
const armTimer =
|
|
4218
|
+
const armTimer = useCallback12(() => {
|
|
4057
4219
|
clearTimer();
|
|
4058
4220
|
timerRef.current = setTimeout(() => pauseRef.current(), IDLE_AUTO_PAUSE_MS);
|
|
4059
4221
|
}, [clearTimer]);
|
|
4060
|
-
const reportActivity =
|
|
4222
|
+
const reportActivity = useCallback12(() => {
|
|
4061
4223
|
if (enabled && !isHeld)
|
|
4062
4224
|
armTimer();
|
|
4063
4225
|
}, [enabled, isHeld, armTimer]);
|
|
@@ -4073,7 +4235,7 @@ function useIdleAutoPause({
|
|
|
4073
4235
|
}
|
|
4074
4236
|
|
|
4075
4237
|
// src/hooks/useKeyboardPushToTalk.ts
|
|
4076
|
-
import { useEffect as useEffect20, useRef as
|
|
4238
|
+
import { useEffect as useEffect20, useRef as useRef14 } from "react";
|
|
4077
4239
|
function isEditableTarget() {
|
|
4078
4240
|
const el = document.activeElement;
|
|
4079
4241
|
if (!el)
|
|
@@ -4087,7 +4249,7 @@ function useKeyboardPushToTalk({
|
|
|
4087
4249
|
onCommit,
|
|
4088
4250
|
onKeyUsed
|
|
4089
4251
|
}) {
|
|
4090
|
-
const handlers =
|
|
4252
|
+
const handlers = useRef14({ onStart, onCommit, onKeyUsed });
|
|
4091
4253
|
handlers.current = { onStart, onCommit, onKeyUsed };
|
|
4092
4254
|
useEffect20(() => {
|
|
4093
4255
|
if (!enabled)
|
|
@@ -4137,14 +4299,14 @@ function useKeyboardPushToTalk({
|
|
|
4137
4299
|
}
|
|
4138
4300
|
|
|
4139
4301
|
// src/hooks/useLiveUserTranscript.ts
|
|
4140
|
-
import { useLocalParticipant as
|
|
4141
|
-
import { useRef as
|
|
4302
|
+
import { useLocalParticipant as useLocalParticipant7 } from "@livekit/components-react/hooks";
|
|
4303
|
+
import { useRef as useRef15 } from "react";
|
|
4142
4304
|
function useLiveUserTranscript(active) {
|
|
4143
4305
|
const transcriptions = useSharedTranscriptions();
|
|
4144
|
-
const { localParticipant } =
|
|
4306
|
+
const { localParticipant } = useLocalParticipant7();
|
|
4145
4307
|
const localIdentity = localParticipant.identity;
|
|
4146
|
-
const priorStreamIdsRef =
|
|
4147
|
-
const wasActiveRef =
|
|
4308
|
+
const priorStreamIdsRef = useRef15(new Set);
|
|
4309
|
+
const wasActiveRef = useRef15(false);
|
|
4148
4310
|
const userStreams = transcriptions.filter((stream) => stream.participantInfo.identity === localIdentity);
|
|
4149
4311
|
if (active && !wasActiveRef.current) {
|
|
4150
4312
|
priorStreamIdsRef.current = new Set(userStreams.map((s) => s.streamInfo.id));
|
|
@@ -4155,36 +4317,6 @@ function useLiveUserTranscript(active) {
|
|
|
4155
4317
|
return userStreams.filter((stream) => !priorStreamIdsRef.current.has(stream.streamInfo.id)).map((stream) => stream.text.trim()).filter((text) => text.length > 0).join(" ");
|
|
4156
4318
|
}
|
|
4157
4319
|
|
|
4158
|
-
// src/hooks/useMediaControls.ts
|
|
4159
|
-
import { useLocalParticipant as useLocalParticipant7 } from "@livekit/components-react/hooks";
|
|
4160
|
-
import { ScreenSharePresets as ScreenSharePresets2 } from "livekit-client";
|
|
4161
|
-
import { useCallback as useCallback12 } from "react";
|
|
4162
|
-
var SCREEN_SHARE_OPTIONS = {
|
|
4163
|
-
video: { displaySurface: "browser" },
|
|
4164
|
-
resolution: ScreenSharePresets2.h720fps30.resolution,
|
|
4165
|
-
contentHint: "detail"
|
|
4166
|
-
};
|
|
4167
|
-
function useMediaControls() {
|
|
4168
|
-
const { localParticipant } = useLocalParticipant7();
|
|
4169
|
-
const isMuted = !localParticipant.isMicrophoneEnabled;
|
|
4170
|
-
const isScreenSharing = localParticipant.isScreenShareEnabled;
|
|
4171
|
-
const toggleMute = useCallback12(async () => {
|
|
4172
|
-
try {
|
|
4173
|
-
await localParticipant.setMicrophoneEnabled(isMuted);
|
|
4174
|
-
} catch (error) {
|
|
4175
|
-
console.error("Failed to toggle microphone:", error);
|
|
4176
|
-
}
|
|
4177
|
-
}, [localParticipant, isMuted]);
|
|
4178
|
-
const toggleScreenShare = useCallback12(async () => {
|
|
4179
|
-
try {
|
|
4180
|
-
await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
|
|
4181
|
-
} catch (error) {
|
|
4182
|
-
console.error("Failed to toggle screen share:", error);
|
|
4183
|
-
}
|
|
4184
|
-
}, [localParticipant, isScreenSharing]);
|
|
4185
|
-
return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
|
|
4186
|
-
}
|
|
4187
|
-
|
|
4188
4320
|
// src/hooks/useMicLevel.ts
|
|
4189
4321
|
import { useLocalParticipant as useLocalParticipant8 } from "@livekit/components-react/hooks";
|
|
4190
4322
|
var MIC_BARS = 5;
|
|
@@ -4795,7 +4927,7 @@ function SessionControlBar() {
|
|
|
4795
4927
|
}
|
|
4796
4928
|
|
|
4797
4929
|
// src/components/ShadowHost.tsx
|
|
4798
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
4930
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef16, useState as useState15 } from "react";
|
|
4799
4931
|
import { createPortal } from "react-dom";
|
|
4800
4932
|
import { jsx as jsx13, Fragment as Fragment2 } from "react/jsx-runtime";
|
|
4801
4933
|
var PROPERTIES_STYLE_ID = "skippr-tw-properties";
|
|
@@ -4812,7 +4944,7 @@ function hoistTailwindProperties(css) {
|
|
|
4812
4944
|
return css.replace(PROPERTY_RULE, "");
|
|
4813
4945
|
}
|
|
4814
4946
|
function ShadowHost({ children }) {
|
|
4815
|
-
const hostRef =
|
|
4947
|
+
const hostRef = useRef16(null);
|
|
4816
4948
|
const [shadowRoot, setShadowRoot] = useState15(null);
|
|
4817
4949
|
const css = `/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
|
|
4818
4950
|
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--skippr-font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--skippr-font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--skippr-color-red-50:oklch(97.1% .013 17.38);--skippr-color-red-100:oklch(93.6% .032 17.717);--skippr-color-red-200:oklch(88.5% .062 18.334);--skippr-color-red-300:oklch(80.8% .114 19.571);--skippr-color-red-400:oklch(70.4% .191 22.216);--skippr-color-red-500:oklch(63.7% .237 25.331);--skippr-color-red-600:oklch(57.7% .245 27.325);--skippr-color-red-700:oklch(50.5% .213 27.518);--skippr-color-amber-50:oklch(98.7% .022 95.277);--skippr-color-amber-100:oklch(96.2% .059 95.617);--skippr-color-amber-400:oklch(82.8% .189 84.429);--skippr-color-amber-700:oklch(55.5% .163 48.998);--skippr-color-amber-950:oklch(27.9% .077 45.635);--skippr-color-emerald-400:oklch(76.5% .177 163.223);--skippr-color-neutral-100:oklch(97% 0 0);--skippr-color-neutral-200:oklch(92.2% 0 0);--skippr-color-neutral-500:oklch(55.6% 0 0);--skippr-color-neutral-700:oklch(37.1% 0 0);--skippr-color-black:#000;--skippr-color-white:#fff;--skippr-spacing:.25rem;--skippr-text-xs:.75rem;--skippr-text-xs--line-height:calc(1/.75);--skippr-text-sm:.875rem;--skippr-text-sm--line-height:calc(1.25/.875);--skippr-font-weight-medium:500;--skippr-font-weight-semibold:600;--skippr-leading-tight:1.25;--skippr-leading-snug:1.375;--skippr-leading-relaxed:1.625;--skippr-ease-out:cubic-bezier(0,0,.2,1);--skippr-ease-in-out:cubic-bezier(.4,0,.2,1);--skippr-animate-spin:spin 1s linear infinite;--skippr-animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--skippr-animate-bounce:bounce 1s infinite;--skippr-blur-sm:8px;--skippr-default-transition-duration:.15s;--skippr-default-transition-timing-function:cubic-bezier(.4,0,.2,1);--skippr-default-font-family:var(--skippr-font-sans);--skippr-default-mono-font-family:var(--skippr-font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--skippr-default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--skippr-default-font-feature-settings,normal);font-variation-settings:var(--skippr-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--skippr-default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--skippr-default-mono-font-feature-settings,normal);font-variation-settings:var(--skippr-default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.skippr\\:pointer-events-none{pointer-events:none}.skippr\\:absolute{position:absolute}.skippr\\:fixed{position:fixed}.skippr\\:relative{position:relative}.skippr\\:sticky{position:sticky}.skippr\\:inset-0{inset:calc(var(--skippr-spacing)*0)}.skippr\\:inset-y-0{inset-block:calc(var(--skippr-spacing)*0)}.skippr\\:top-0{top:calc(var(--skippr-spacing)*0)}.skippr\\:top-1\\/2{top:50%}.skippr\\:top-full{top:100%}.skippr\\:-right-8{right:calc(var(--skippr-spacing)*-8)}.skippr\\:right-0{right:calc(var(--skippr-spacing)*0)}.skippr\\:right-3{right:calc(var(--skippr-spacing)*3)}.skippr\\:right-5{right:calc(var(--skippr-spacing)*5)}.skippr\\:right-6{right:calc(var(--skippr-spacing)*6)}.skippr\\:-bottom-1{bottom:calc(var(--skippr-spacing)*-1)}.skippr\\:-bottom-9{bottom:calc(var(--skippr-spacing)*-9)}.skippr\\:bottom-3{bottom:calc(var(--skippr-spacing)*3)}.skippr\\:bottom-20{bottom:calc(var(--skippr-spacing)*20)}.skippr\\:bottom-full{bottom:100%}.skippr\\:-left-8{left:calc(var(--skippr-spacing)*-8)}.skippr\\:left-0{left:calc(var(--skippr-spacing)*0)}.skippr\\:left-1\\/2{left:50%}.skippr\\:left-2{left:calc(var(--skippr-spacing)*2)}.skippr\\:left-3{left:calc(var(--skippr-spacing)*3)}.skippr\\:left-5{left:calc(var(--skippr-spacing)*5)}.skippr\\:left-6{left:calc(var(--skippr-spacing)*6)}.skippr\\:z-10{z-index:10}.skippr\\:z-20{z-index:20}.skippr\\:z-\\[9998\\]{z-index:9998}.skippr\\:z-\\[9999\\]{z-index:9999}.skippr\\:z-\\[10000\\]{z-index:10000}.skippr\\:order-first{order:-9999}.skippr\\:order-last{order:9999}.skippr\\:mx-auto{margin-inline:auto}.skippr\\:-mt-\\[5px\\]{margin-top:-5px}.skippr\\:-mt-\\[27px\\]{margin-top:-27px}.skippr\\:mt-0\\.5{margin-top:calc(var(--skippr-spacing)*.5)}.skippr\\:mt-1{margin-top:calc(var(--skippr-spacing)*1)}.skippr\\:mt-1\\.5{margin-top:calc(var(--skippr-spacing)*1.5)}.skippr\\:mt-2{margin-top:calc(var(--skippr-spacing)*2)}.skippr\\:mt-3{margin-top:calc(var(--skippr-spacing)*3)}.skippr\\:mt-3\\.5{margin-top:calc(var(--skippr-spacing)*3.5)}.skippr\\:mr-7{margin-right:calc(var(--skippr-spacing)*7)}.skippr\\:-mb-\\[5px\\]{margin-bottom:-5px}.skippr\\:mb-1\\.5{margin-bottom:calc(var(--skippr-spacing)*1.5)}.skippr\\:mb-2{margin-bottom:calc(var(--skippr-spacing)*2)}.skippr\\:mb-3{margin-bottom:calc(var(--skippr-spacing)*3)}.skippr\\:mb-4{margin-bottom:calc(var(--skippr-spacing)*4)}.skippr\\:ml-0\\.5{margin-left:calc(var(--skippr-spacing)*.5)}.skippr\\:ml-1{margin-left:calc(var(--skippr-spacing)*1)}.skippr\\:ml-7{margin-left:calc(var(--skippr-spacing)*7)}.skippr\\:flex{display:flex}.skippr\\:hidden{display:none}.skippr\\:inline-flex{display:inline-flex}.skippr\\:size-1{width:calc(var(--skippr-spacing)*1);height:calc(var(--skippr-spacing)*1)}.skippr\\:size-1\\.5{width:calc(var(--skippr-spacing)*1.5);height:calc(var(--skippr-spacing)*1.5)}.skippr\\:size-2{width:calc(var(--skippr-spacing)*2);height:calc(var(--skippr-spacing)*2)}.skippr\\:size-2\\.5{width:calc(var(--skippr-spacing)*2.5);height:calc(var(--skippr-spacing)*2.5)}.skippr\\:size-3{width:calc(var(--skippr-spacing)*3);height:calc(var(--skippr-spacing)*3)}.skippr\\:size-3\\.5{width:calc(var(--skippr-spacing)*3.5);height:calc(var(--skippr-spacing)*3.5)}.skippr\\:size-4{width:calc(var(--skippr-spacing)*4);height:calc(var(--skippr-spacing)*4)}.skippr\\:size-5{width:calc(var(--skippr-spacing)*5);height:calc(var(--skippr-spacing)*5)}.skippr\\:size-6{width:calc(var(--skippr-spacing)*6);height:calc(var(--skippr-spacing)*6)}.skippr\\:size-7{width:calc(var(--skippr-spacing)*7);height:calc(var(--skippr-spacing)*7)}.skippr\\:size-8{width:calc(var(--skippr-spacing)*8);height:calc(var(--skippr-spacing)*8)}.skippr\\:size-9{width:calc(var(--skippr-spacing)*9);height:calc(var(--skippr-spacing)*9)}.skippr\\:size-10{width:calc(var(--skippr-spacing)*10);height:calc(var(--skippr-spacing)*10)}.skippr\\:size-12{width:calc(var(--skippr-spacing)*12);height:calc(var(--skippr-spacing)*12)}.skippr\\:size-\\[5px\\]{width:5px;height:5px}.skippr\\:size-\\[38px\\]{width:38px;height:38px}.skippr\\:size-full{width:100%;height:100%}.skippr\\:h-0{height:calc(var(--skippr-spacing)*0)}.skippr\\:h-0\\.5{height:calc(var(--skippr-spacing)*.5)}.skippr\\:h-1{height:calc(var(--skippr-spacing)*1)}.skippr\\:h-1\\.5{height:calc(var(--skippr-spacing)*1.5)}.skippr\\:h-2{height:calc(var(--skippr-spacing)*2)}.skippr\\:h-3{height:calc(var(--skippr-spacing)*3)}.skippr\\:h-3\\.5{height:calc(var(--skippr-spacing)*3.5)}.skippr\\:h-4{height:calc(var(--skippr-spacing)*4)}.skippr\\:h-5{height:calc(var(--skippr-spacing)*5)}.skippr\\:h-6{height:calc(var(--skippr-spacing)*6)}.skippr\\:h-7{height:calc(var(--skippr-spacing)*7)}.skippr\\:h-8{height:calc(var(--skippr-spacing)*8)}.skippr\\:h-9{height:calc(var(--skippr-spacing)*9)}.skippr\\:h-10{height:calc(var(--skippr-spacing)*10)}.skippr\\:h-\\[18\\.5px\\]{height:18.5px}.skippr\\:h-\\[36px\\]{height:36px}.skippr\\:h-\\[38px\\]{height:38px}.skippr\\:h-\\[48px\\]{height:48px}.skippr\\:h-\\[54px\\]{height:54px}.skippr\\:h-full{height:100%}.skippr\\:min-h-0{min-height:calc(var(--skippr-spacing)*0)}.skippr\\:min-h-11{min-height:calc(var(--skippr-spacing)*11)}.skippr\\:w-0{width:calc(var(--skippr-spacing)*0)}.skippr\\:w-3\\.5{width:calc(var(--skippr-spacing)*3.5)}.skippr\\:w-4{width:calc(var(--skippr-spacing)*4)}.skippr\\:w-5{width:calc(var(--skippr-spacing)*5)}.skippr\\:w-6{width:calc(var(--skippr-spacing)*6)}.skippr\\:w-7{width:calc(var(--skippr-spacing)*7)}.skippr\\:w-8{width:calc(var(--skippr-spacing)*8)}.skippr\\:w-10{width:calc(var(--skippr-spacing)*10)}.skippr\\:w-40{width:calc(var(--skippr-spacing)*40)}.skippr\\:w-\\[2px\\]{width:2px}.skippr\\:w-\\[3px\\]{width:3px}.skippr\\:w-\\[15\\.4px\\]{width:15.4px}.skippr\\:w-\\[36px\\]{width:36px}.skippr\\:w-\\[38px\\]{width:38px}.skippr\\:w-\\[50px\\]{width:50px}.skippr\\:w-fit{width:fit-content}.skippr\\:w-full{width:100%}.skippr\\:max-w-64{max-width:calc(var(--skippr-spacing)*64)}.skippr\\:max-w-72{max-width:calc(var(--skippr-spacing)*72)}.skippr\\:max-w-\\[80\\%\\]{max-width:80%}.skippr\\:max-w-\\[280px\\]{max-width:280px}.skippr\\:min-w-0{min-width:calc(var(--skippr-spacing)*0)}.skippr\\:min-w-11{min-width:calc(var(--skippr-spacing)*11)}.skippr\\:flex-1{flex:1}.skippr\\:shrink-0{flex-shrink:0}.skippr\\:origin-bottom-left{transform-origin:0 100%}.skippr\\:origin-bottom-right{transform-origin:100% 100%}.skippr\\:origin-center{transform-origin:50%}.skippr\\:origin-left{transform-origin:0}.skippr\\:origin-right{transform-origin:100%}.skippr\\:origin-top-left{transform-origin:0 0}.skippr\\:origin-top-right{transform-origin:100% 0}.skippr\\:-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:-translate-x-3{--tw-translate-x:calc(var(--skippr-spacing)*-3);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:-translate-x-7{--tw-translate-x:calc(var(--skippr-spacing)*-7);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:translate-x-3{--tw-translate-x:calc(var(--skippr-spacing)*3);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:translate-x-7{--tw-translate-x:calc(var(--skippr-spacing)*7);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:scale-0{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-\\[0\\.94\\]{scale:.94}.skippr\\:-rotate-90{rotate:-90deg}.skippr\\:rotate-45{rotate:45deg}.skippr\\:rotate-\\[225deg\\]{rotate:225deg}.skippr\\:\\[animation\\:skippr-agent-in_200ms_ease-out\\]{animation:.2s ease-out skippr-agent-in}.skippr\\:\\[animation\\:skippr-agent-in_200ms_ease-out_240ms_both\\]{animation:.2s ease-out .24s both skippr-agent-in}.skippr\\:\\[animation\\:skippr-banner-look_2\\.4s_ease-in-out_infinite\\]{animation:2.4s ease-in-out infinite skippr-banner-look}.skippr\\:\\[animation\\:skippr-finger-tap_1\\.1s_ease-in-out_infinite\\]{animation:1.1s ease-in-out infinite skippr-finger-tap}.skippr\\:\\[animation\\:skippr-orb-in_320ms_cubic-bezier\\(0\\.34\\,1\\.3\\,0\\.64\\,1\\)\\]{animation:.32s cubic-bezier(.34,1.3,.64,1) skippr-orb-in}.skippr\\:\\[animation\\:skippr-stage-fade_240ms_ease-out\\]{animation:.24s ease-out skippr-stage-fade}.skippr\\:\\[animation\\:skippr-tip-in_360ms_cubic-bezier\\(0\\.34\\,1\\.3\\,0\\.64\\,1\\)_backwards\\]{animation:.36s cubic-bezier(.34,1.3,.64,1) backwards skippr-tip-in}.skippr\\:\\[animation\\:skippr-toolset-pop_280ms_cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{animation:.28s cubic-bezier(.22,1,.36,1) skippr-toolset-pop}.skippr\\:\\[animation\\:skippr-toolset-pop_440ms_cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{animation:.44s cubic-bezier(.22,1,.36,1) skippr-toolset-pop}.skippr\\:animate-\\[skippr-banner-look_2\\.4s_ease-in-out_infinite\\]{animation:2.4s ease-in-out infinite skippr-banner-look}.skippr\\:animate-\\[skippr-bubble-in_0\\.28s_ease-out\\]{animation:.28s ease-out skippr-bubble-in}.skippr\\:animate-\\[skippr-fade-in_0\\.3s_ease-out\\]{animation:.3s ease-out skippr-fade-in}.skippr\\:animate-\\[skippr-pill-content_0\\.22s_ease-out\\]{animation:.22s ease-out skippr-pill-content}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.3s_infinite\\]{animation:1.1s ease-in-out .3s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.6s_infinite\\]{animation:1.1s ease-in-out .6s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.15s_infinite\\]{animation:1.1s ease-in-out .15s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.45s_infinite\\]{animation:1.1s ease-in-out .45s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_infinite\\]{animation:1.1s ease-in-out infinite skippr-speak}.skippr\\:animate-bounce{animation:var(--skippr-animate-bounce)}.skippr\\:animate-ping{animation:var(--skippr-animate-ping)}.skippr\\:animate-skippr-annotation-pulse{animation:1.8s ease-in-out infinite skippr-annotation-pulse}.skippr\\:animate-skippr-click-ping{animation:.5s ease-out forwards skippr-click-ping}.skippr\\:animate-skippr-cursor-pop{animation:.22s ease-out skippr-cursor-pop}.skippr\\:animate-skippr-press{animation:.5s ease-in-out skippr-press}.skippr\\:animate-skippr-ptt-transmit{animation:1.4s ease-out infinite skippr-ptt-transmit}.skippr\\:animate-skippr-rec-ring{animation:2s ease-out infinite skippr-rec-ring}.skippr\\:animate-skippr-tab-fade{animation:.2s ease-out skippr-tab-fade}.skippr\\:animate-skippr-thinking-dot{animation:1.2s ease-in-out infinite skippr-thinking-dot}.skippr\\:animate-spin{animation:var(--skippr-animate-spin)}.skippr\\:cursor-default{cursor:default}.skippr\\:cursor-grab{cursor:grab}.skippr\\:cursor-not-allowed{cursor:not-allowed}.skippr\\:cursor-pointer{cursor:pointer}.skippr\\:touch-none{touch-action:none}.skippr\\:resize-none{resize:none}.skippr\\:flex-col{flex-direction:column}.skippr\\:flex-col-reverse{flex-direction:column-reverse}.skippr\\:items-center{align-items:center}.skippr\\:items-end{align-items:flex-end}.skippr\\:items-start{align-items:flex-start}.skippr\\:justify-between{justify-content:space-between}.skippr\\:justify-center{justify-content:center}.skippr\\:justify-end{justify-content:flex-end}.skippr\\:justify-start{justify-content:flex-start}.skippr\\:gap-0\\.5{gap:calc(var(--skippr-spacing)*.5)}.skippr\\:gap-1{gap:calc(var(--skippr-spacing)*1)}.skippr\\:gap-1\\.5{gap:calc(var(--skippr-spacing)*1.5)}.skippr\\:gap-2{gap:calc(var(--skippr-spacing)*2)}.skippr\\:gap-2\\.5{gap:calc(var(--skippr-spacing)*2.5)}.skippr\\:gap-3{gap:calc(var(--skippr-spacing)*3)}.skippr\\:gap-\\[2px\\]{gap:2px}.skippr\\:gap-\\[3px\\]{gap:3px}:where(.skippr\\:space-y-0\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.skippr\\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.skippr\\:overflow-hidden{overflow:hidden}.skippr\\:overflow-y-auto{overflow-y:auto}.skippr\\:rounded{border-radius:.25rem}.skippr\\:rounded-2xl{border-radius:1.125rem}.skippr\\:rounded-\\[1rem\\]{border-radius:1rem}.skippr\\:rounded-\\[10px\\]{border-radius:10px}.skippr\\:rounded-\\[11px\\]{border-radius:11px}.skippr\\:rounded-\\[12px\\]{border-radius:12px}.skippr\\:rounded-\\[14px\\]{border-radius:14px}.skippr\\:rounded-\\[16px\\]{border-radius:16px}.skippr\\:rounded-\\[20px\\]{border-radius:20px}.skippr\\:rounded-full{border-radius:3.40282e38px}.skippr\\:rounded-lg{border-radius:.625rem}.skippr\\:rounded-md{border-radius:.5rem}.skippr\\:rounded-sm{border-radius:.375rem}.skippr\\:rounded-xl{border-radius:.875rem}.skippr\\:rounded-l-\\[18px\\]{border-top-left-radius:18px;border-bottom-left-radius:18px}.skippr\\:rounded-tl-md{border-top-left-radius:.5rem}.skippr\\:rounded-r-\\[18px\\]{border-top-right-radius:18px;border-bottom-right-radius:18px}.skippr\\:border{border-style:var(--tw-border-style);border-width:1px}.skippr\\:border-0{border-style:var(--tw-border-style);border-width:0}.skippr\\:border-2{border-style:var(--tw-border-style);border-width:2px}.skippr\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.skippr\\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.skippr\\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.skippr\\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.skippr\\:border-\\[\\#2bc0ae\\]{border-color:#2bc0ae}.skippr\\:border-black\\/25{border-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:border-black\\/25{border-color:color-mix(in oklab,var(--skippr-color-black)25%,transparent)}}.skippr\\:border-border,.skippr\\:border-input{border-color:oklch(92.3% .003 48.717)}.skippr\\:border-primary\\/20{border-color:oklab(29.9244% .0107414 -.0305411/.2)}.skippr\\:border-r-border{border-right-color:oklch(92.3% .003 48.717)}.skippr\\:border-l-border{border-left-color:oklch(92.3% .003 48.717)}.skippr\\:bg-\\[\\#2bc0ae\\]{background-color:#2bc0ae}.skippr\\:bg-\\[\\#2bc0ae\\]\\/50{background-color:oklab(72.9347% -.121518 -.00545585/.5)}.skippr\\:bg-\\[\\#f4ecd8\\]{background-color:#f4ecd8}.skippr\\:bg-amber-50{background-color:var(--skippr-color-amber-50)}.skippr\\:bg-amber-400{background-color:var(--skippr-color-amber-400)}.skippr\\:bg-background{background-color:oklch(100% 0 0)}.skippr\\:bg-black\\/\\[0\\.07\\]{background-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-black\\/\\[0\\.07\\]{background-color:color-mix(in oklab,var(--skippr-color-black)7.0%,transparent)}}.skippr\\:bg-bubble{background-color:#2d2b3d}.skippr\\:bg-bubble\\/95{background-color:oklab(29.9244% .0107414 -.0305411/.95)}.skippr\\:bg-card{background-color:oklch(100% 0 0)}.skippr\\:bg-current{background-color:currentColor}.skippr\\:bg-destructive{background-color:#d94f4f}.skippr\\:bg-emerald-400{background-color:var(--skippr-color-emerald-400)}.skippr\\:bg-foreground{background-color:oklch(14.7% .004 49.25)}.skippr\\:bg-launcher{background-color:#2d2d3f}.skippr\\:bg-muted-foreground\\/20{background-color:oklab(55.3% .00687528 .0110332/.2)}.skippr\\:bg-muted-foreground\\/40{background-color:oklab(55.3% .00687528 .0110332/.4)}.skippr\\:bg-muted\\/50{background-color:oklab(97% -.000282743 .000959196/.5)}.skippr\\:bg-neutral-100{background-color:var(--skippr-color-neutral-100)}.skippr\\:bg-primary{background-color:#2d2b3d}.skippr\\:bg-primary-foreground\\/20{background-color:oklab(100% 0 5.96046e-8/.2)}.skippr\\:bg-primary\\/10{background-color:oklab(29.9244% .0107414 -.0305411/.1)}.skippr\\:bg-red-50{background-color:var(--skippr-color-red-50)}.skippr\\:bg-red-100{background-color:var(--skippr-color-red-100)}.skippr\\:bg-red-400{background-color:var(--skippr-color-red-400)}.skippr\\:bg-red-500{background-color:var(--skippr-color-red-500)}.skippr\\:bg-secondary{background-color:#ffdfb5}.skippr\\:bg-transparent{background-color:#0000}.skippr\\:bg-white,.skippr\\:bg-white\\/15{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-white\\/15{background-color:color-mix(in oklab,var(--skippr-color-white)15%,transparent)}}.skippr\\:bg-white\\/70{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-white\\/70{background-color:color-mix(in oklab,var(--skippr-color-white)70%,transparent)}}.skippr\\:fill-brand{fill:#2bc0ae}.skippr\\:fill-primary\\/30{fill:oklab(29.9244% .0107414 -.0305411/.3)}.skippr\\:stroke-black\\/15{stroke:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:stroke-black\\/15{stroke:color-mix(in oklab,var(--skippr-color-black)15%,transparent)}}.skippr\\:stroke-bubble{stroke:#2d2b3d}.skippr\\:p-0{padding:calc(var(--skippr-spacing)*0)}.skippr\\:p-0\\.5{padding:calc(var(--skippr-spacing)*.5)}.skippr\\:p-1\\.5{padding:calc(var(--skippr-spacing)*1.5)}.skippr\\:p-2{padding:calc(var(--skippr-spacing)*2)}.skippr\\:p-3{padding:calc(var(--skippr-spacing)*3)}.skippr\\:p-3\\.5{padding:calc(var(--skippr-spacing)*3.5)}.skippr\\:p-4{padding:calc(var(--skippr-spacing)*4)}.skippr\\:px-1{padding-inline:calc(var(--skippr-spacing)*1)}.skippr\\:px-1\\.5{padding-inline:calc(var(--skippr-spacing)*1.5)}.skippr\\:px-2{padding-inline:calc(var(--skippr-spacing)*2)}.skippr\\:px-2\\.5{padding-inline:calc(var(--skippr-spacing)*2.5)}.skippr\\:px-3{padding-inline:calc(var(--skippr-spacing)*3)}.skippr\\:px-3\\.5{padding-inline:calc(var(--skippr-spacing)*3.5)}.skippr\\:px-4{padding-inline:calc(var(--skippr-spacing)*4)}.skippr\\:px-6{padding-inline:calc(var(--skippr-spacing)*6)}.skippr\\:px-8{padding-inline:calc(var(--skippr-spacing)*8)}.skippr\\:py-0\\.5{padding-block:calc(var(--skippr-spacing)*.5)}.skippr\\:py-1{padding-block:calc(var(--skippr-spacing)*1)}.skippr\\:py-1\\.5{padding-block:calc(var(--skippr-spacing)*1.5)}.skippr\\:py-2{padding-block:calc(var(--skippr-spacing)*2)}.skippr\\:py-2\\.5{padding-block:calc(var(--skippr-spacing)*2.5)}.skippr\\:py-3{padding-block:calc(var(--skippr-spacing)*3)}.skippr\\:py-4{padding-block:calc(var(--skippr-spacing)*4)}.skippr\\:py-6{padding-block:calc(var(--skippr-spacing)*6)}.skippr\\:pt-1\\.5{padding-top:calc(var(--skippr-spacing)*1.5)}.skippr\\:pr-2\\.5{padding-right:calc(var(--skippr-spacing)*2.5)}.skippr\\:pr-3{padding-right:calc(var(--skippr-spacing)*3)}.skippr\\:pb-2{padding-bottom:calc(var(--skippr-spacing)*2)}.skippr\\:pl-1\\.5{padding-left:calc(var(--skippr-spacing)*1.5)}.skippr\\:pl-2\\.5{padding-left:calc(var(--skippr-spacing)*2.5)}.skippr\\:pl-3\\.5{padding-left:calc(var(--skippr-spacing)*3.5)}.skippr\\:text-center{text-align:center}.skippr\\:text-left{text-align:left}.skippr\\:font-mono{font-family:var(--skippr-font-mono)}.skippr\\:text-sm{font-size:var(--skippr-text-sm);line-height:var(--tw-leading,var(--skippr-text-sm--line-height))}.skippr\\:text-xs{font-size:var(--skippr-text-xs);line-height:var(--tw-leading,var(--skippr-text-xs--line-height))}.skippr\\:text-\\[10px\\]{font-size:10px}.skippr\\:text-\\[11px\\]{font-size:11px}.skippr\\:text-\\[13px\\]{font-size:13px}.skippr\\:leading-5{--tw-leading:calc(var(--skippr-spacing)*5);line-height:calc(var(--skippr-spacing)*5)}.skippr\\:leading-none{--tw-leading:1;line-height:1}.skippr\\:leading-relaxed{--tw-leading:var(--skippr-leading-relaxed);line-height:var(--skippr-leading-relaxed)}.skippr\\:leading-snug{--tw-leading:var(--skippr-leading-snug);line-height:var(--skippr-leading-snug)}.skippr\\:leading-tight{--tw-leading:var(--skippr-leading-tight);line-height:var(--skippr-leading-tight)}.skippr\\:font-medium{--tw-font-weight:var(--skippr-font-weight-medium);font-weight:var(--skippr-font-weight-medium)}.skippr\\:font-semibold{--tw-font-weight:var(--skippr-font-weight-semibold);font-weight:var(--skippr-font-weight-semibold)}.skippr\\:whitespace-nowrap{white-space:nowrap}.skippr\\:text-\\[\\#2bc0ae\\]{color:#2bc0ae}.skippr\\:text-amber-700{color:var(--skippr-color-amber-700)}.skippr\\:text-amber-950{color:var(--skippr-color-amber-950)}.skippr\\:text-background{color:oklch(100% 0 0)}.skippr\\:text-black,.skippr\\:text-black\\/40{color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:text-black\\/40{color:color-mix(in oklab,var(--skippr-color-black)40%,transparent)}}.skippr\\:text-brand{color:#2bc0ae}.skippr\\:text-bubble{color:#2d2b3d}.skippr\\:text-chart-3{color:oklch(66.6% .179 58.318)}.skippr\\:text-destructive{color:#d94f4f}.skippr\\:text-foreground{color:oklch(14.7% .004 49.25)}.skippr\\:text-muted-foreground{color:oklch(55.3% .013 58.071)}.skippr\\:text-muted-foreground\\/30{color:oklab(55.3% .00687528 .0110332/.3)}.skippr\\:text-muted-foreground\\/40{color:oklab(55.3% .00687528 .0110332/.4)}.skippr\\:text-muted-foreground\\/60{color:oklab(55.3% .00687528 .0110332/.6)}.skippr\\:text-muted-foreground\\/70{color:oklab(55.3% .00687528 .0110332/.7)}.skippr\\:text-neutral-500{color:var(--skippr-color-neutral-500)}.skippr\\:text-neutral-700{color:var(--skippr-color-neutral-700)}.skippr\\:text-primary{color:#2d2b3d}.skippr\\:text-primary-foreground{color:#fff}.skippr\\:text-primary-foreground\\/70{color:oklab(100% 0 5.96046e-8/.7)}.skippr\\:text-red-400{color:var(--skippr-color-red-400)}.skippr\\:text-red-600{color:var(--skippr-color-red-600)}.skippr\\:text-red-700{color:var(--skippr-color-red-700)}.skippr\\:text-secondary-foreground{color:#613700}.skippr\\:text-white,.skippr\\:text-white\\/60{color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:text-white\\/60{color:color-mix(in oklab,var(--skippr-color-white)60%,transparent)}}.skippr\\:capitalize{text-transform:capitalize}.skippr\\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.skippr\\:line-through{text-decoration-line:line-through}.skippr\\:placeholder-muted-foreground::placeholder{color:oklch(55.3% .013 58.071)}.skippr\\:opacity-0{opacity:0}.skippr\\:opacity-40{opacity:.4}.skippr\\:opacity-75{opacity:.75}.skippr\\:opacity-100{opacity:1}.skippr\\:shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[-6px_8px_30px_rgba\\(15\\,18\\,26\\,0\\.32\\)\\]{--tw-shadow:-6px 8px 30px var(--tw-shadow-color,#0f121a52);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_2px_6px_rgba\\(0\\,0\\,0\\,0\\.28\\)\\]{--tw-shadow:0 2px 6px var(--tw-shadow-color,#00000047);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_12px_rgba\\(0\\,0\\,0\\,0\\.12\\)\\]{--tw-shadow:0 4px 12px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_14px_rgba\\(0\\,0\\,0\\,0\\.12\\)\\]{--tw-shadow:0 4px 14px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_14px_rgba\\(239\\,68\\,68\\,0\\.45\\)\\]{--tw-shadow:0 4px 14px var(--tw-shadow-color,#ef444473);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_16px_rgba\\(45\\,43\\,61\\,0\\.45\\)\\,0_2px_4px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 16px var(--tw-shadow-color,#2d2b3d73),0 2px 4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_24px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 8px 24px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_24px_rgba\\(45\\,43\\,61\\,0\\.35\\)\\]{--tw-shadow:0 8px 24px var(--tw-shadow-color,#2d2b3d59);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_30px_rgba\\(0\\,0\\,0\\,0\\.16\\)\\,0_4px_12px_rgba\\(0\\,0\\,0\\,0\\.08\\)\\]{--tw-shadow:0 8px 30px var(--tw-shadow-color,#00000029),0 4px 12px var(--tw-shadow-color,#00000014);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_10px_32px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 10px 32px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-black\\/5{--tw-ring-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-black\\/5{--tw-ring-color:color-mix(in oklab,var(--skippr-color-black)5%,transparent)}}.skippr\\:ring-brand{--tw-ring-color:#2bc0ae}.skippr\\:ring-foreground\\/10{--tw-ring-color:oklab(14.7% .00261104 .00303026/.1)}.skippr\\:ring-white\\/15{--tw-ring-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-white\\/15{--tw-ring-color:color-mix(in oklab,var(--skippr-color-white)15%,transparent)}}.skippr\\:ring-white\\/30{--tw-ring-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-white\\/30{--tw-ring-color:color-mix(in oklab,var(--skippr-color-white)30%,transparent)}}.skippr\\:ring-offset-background{--tw-ring-offset-color:oklch(100% 0 0)}.skippr\\:drop-shadow-\\[0_2px_5px_rgba\\(0\\,0\\,0\\,0\\.4\\)\\]{--tw-drop-shadow-size:drop-shadow(0 2px 5px var(--tw-drop-shadow-color,#0006));--tw-drop-shadow:var(--tw-drop-shadow-size);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.skippr\\:backdrop-blur-sm{--tw-backdrop-blur:blur(var(--skippr-blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.skippr\\:transition-\\[height\\]{transition-property:height;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[opacity\\,transform\\,height\\]{transition-property:opacity,transform,height;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[width\\,margin\\]{transition-property:width,margin;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[width\\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:duration-75{--tw-duration:75ms;transition-duration:75ms}.skippr\\:duration-100{--tw-duration:.1s;transition-duration:.1s}.skippr\\:duration-150{--tw-duration:.15s;transition-duration:.15s}.skippr\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.skippr\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.skippr\\:duration-\\[400ms\\]{--tw-duration:.4s;transition-duration:.4s}.skippr\\:ease-\\[cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{--tw-ease:cubic-bezier(.22,1,.36,1);transition-timing-function:cubic-bezier(.22,1,.36,1)}.skippr\\:ease-\\[cubic-bezier\\(0\\.34\\,1\\.56\\,0\\.64\\,1\\)\\]{--tw-ease:cubic-bezier(.34,1.56,.64,1);transition-timing-function:cubic-bezier(.34,1.56,.64,1)}.skippr\\:ease-in-out{--tw-ease:var(--skippr-ease-in-out);transition-timing-function:var(--skippr-ease-in-out)}.skippr\\:ease-out{--tw-ease:var(--skippr-ease-out);transition-timing-function:var(--skippr-ease-out)}.skippr\\:outline-none{--tw-outline-style:none;outline-style:none}.skippr\\:select-none{-webkit-user-select:none;user-select:none}.skippr\\:\\[animation-delay\\:0ms\\]{animation-delay:0s}.skippr\\:\\[animation-delay\\:150ms\\]{animation-delay:.15s}.skippr\\:\\[animation-delay\\:200ms\\]{animation-delay:.2s}.skippr\\:\\[animation-delay\\:300ms\\]{animation-delay:.3s}.skippr\\:\\[animation-delay\\:400ms\\]{animation-delay:.4s}.skippr\\:\\[overflow-anchor\\:none\\]{overflow-anchor:none}.skippr\\:group-focus-within\\:scale-100:is(:where(.skippr\\:group):focus-within *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:group-focus-within\\:opacity-100:is(:where(.skippr\\:group):focus-within *){opacity:1}@media (hover:hover){.skippr\\:group-hover\\:scale-100:is(:where(.skippr\\:group):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:group-hover\\:text-red-300:is(:where(.skippr\\:group):hover *){color:var(--skippr-color-red-300)}.skippr\\:group-hover\\:text-white\\/80:is(:where(.skippr\\:group):hover *){color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:group-hover\\:text-white\\/80:is(:where(.skippr\\:group):hover *){color:color-mix(in oklab,var(--skippr-color-white)80%,transparent)}}.skippr\\:group-hover\\:opacity-100:is(:where(.skippr\\:group):hover *){opacity:1}}.skippr\\:placeholder\\:text-muted-foreground::placeholder{color:oklch(55.3% .013 58.071)}@media (hover:hover){.skippr\\:hover\\:-translate-y-0\\.5:hover{--tw-translate-y:calc(var(--skippr-spacing)*-.5);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:hover\\:bg-\\[\\#3a384b\\]:hover{background-color:#3a384b}.skippr\\:hover\\:bg-accent:hover{background-color:#e7e5e4}.skippr\\:hover\\:bg-amber-100:hover{background-color:var(--skippr-color-amber-100)}.skippr\\:hover\\:bg-bubble:hover{background-color:#2d2b3d}.skippr\\:hover\\:bg-destructive\\/90:hover{background-color:oklab(61.4357% .15892 .0698893/.9)}.skippr\\:hover\\:bg-muted:hover{background-color:oklch(97% .001 106.424)}.skippr\\:hover\\:bg-neutral-100:hover{background-color:var(--skippr-color-neutral-100)}.skippr\\:hover\\:bg-neutral-200:hover{background-color:var(--skippr-color-neutral-200)}.skippr\\:hover\\:bg-primary\\/90:hover{background-color:oklab(29.9244% .0107414 -.0305411/.9)}.skippr\\:hover\\:bg-red-200:hover{background-color:var(--skippr-color-red-200)}.skippr\\:hover\\:bg-red-600:hover{background-color:var(--skippr-color-red-600)}.skippr\\:hover\\:bg-secondary\\/80:hover{background-color:oklab(91.9963% .0175391 .0626889/.8)}.skippr\\:hover\\:bg-white\\/10:hover{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:hover\\:bg-white\\/10:hover{background-color:color-mix(in oklab,var(--skippr-color-white)10%,transparent)}}.skippr\\:hover\\:text-accent-foreground:hover{color:oklch(21.6% .006 56.043)}.skippr\\:hover\\:text-foreground:hover{color:oklch(14.7% .004 49.25)}.skippr\\:hover\\:text-primary-foreground:hover{color:#fff}.skippr\\:hover\\:brightness-110:hover{--tw-brightness:brightness(110%);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}}.skippr\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:focus-visible\\:ring-brand:focus-visible{--tw-ring-color:#2bc0ae}.skippr\\:focus-visible\\:ring-bubble\\/60:focus-visible{--tw-ring-color:oklab(29.9244% .0107414 -.0305411/.6)}.skippr\\:focus-visible\\:ring-ring:focus-visible{--tw-ring-color:oklch(70.9% .01 56.259)}.skippr\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.skippr\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.skippr\\:active\\:translate-y-0:active{--tw-translate-y:calc(var(--skippr-spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.skippr\\:disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.skippr\\:disabled\\:opacity-50:disabled{opacity:.5}.skippr\\:disabled\\:opacity-60:disabled{opacity:.6}@media (prefers-reduced-motion:reduce){.skippr\\:motion-reduce\\:hidden{display:none}.skippr\\:motion-reduce\\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:motion-reduce\\:animate-none{animation:none}}.skippr\\:\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.skippr\\:\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.skippr\\:\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--skippr-spacing)*4);height:calc(var(--skippr-spacing)*4)}}@keyframes skippr-tap{0%{transform:scale(1)}45%{transform:scale(.7)}to{transform:scale(1)}}@keyframes skippr-press{0%{transform:scale(1)}55%{transform:scale(1)}85%{transform:scale(.68)}to{transform:scale(1)}}@keyframes skippr-cursor-pop{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes skippr-click-ping{0%{opacity:.9;transform:translate(-50%,-50%)scale(.4)}to{opacity:0;transform:translate(-50%,-50%)scale(2.4)}}@keyframes skippr-tab-fade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes skippr-speak{0%,to{opacity:.6;transform:scaleY(.4)}50%{opacity:1;transform:scaleY(1)}}@keyframes skippr-thinking-dot{0%,80%,to{opacity:.2;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}@keyframes skippr-pulse-ring{0%,to{box-shadow:0 0 #2d2b3d66}50%{box-shadow:0 0 0 10px #2d2b3d00}}@keyframes skippr-rec-ring{0%{box-shadow:0 0 #2bc0ae8c}70%{box-shadow:0 0 0 11px #2bc0ae00}to{box-shadow:0 0 #2bc0ae00}}@keyframes skippr-ptt-transmit{0%{box-shadow:0 0 #2bc0ae99,0 0 #2bc0ae59}70%{box-shadow:0 0 0 9px #2bc0ae00,0 0 0 16px #2bc0ae00}to{box-shadow:0 0 #2bc0ae00,0 0 #2bc0ae00}}@keyframes skippr-annotation-pulse{0%,to{box-shadow:0 0 #2bc0ae80}50%{box-shadow:0 0 0 6px #2bc0ae00}}@keyframes skippr-speak-ripple{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(1.8)}}@keyframes skippr-bar{0%,to{transform:scaleY(.35)}50%{transform:scaleY(1)}}@keyframes skippr-breathe{0%,to{opacity:.85;transform:scale(1)}50%{opacity:1;transform:scale(1.08)}}@keyframes skippr-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes skippr-wave{0%,to{opacity:.4;transform:scaleY(.4)}50%{opacity:1;transform:scaleY(1)}}@keyframes skippr-bubble-in{0%{opacity:0;transform:translateY(12px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes skippr-tip-in{0%{opacity:0;transform:translateY(14px)scale(.96)}60%{opacity:1;transform:translateY(-2px)scale(1.01)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes skippr-pill-content{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}@keyframes skippr-banner-look{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}@keyframes skippr-finger-tap{0%,to{transform:translateY(0)rotate(0)}50%{transform:translateY(2px)rotate(-6deg)}}@keyframes skippr-toolset-pop{0%{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}@keyframes skippr-stage-fade{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes skippr-agent-in{0%{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}@keyframes skippr-orb-in{0%{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}.skippr-no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}.skippr-no-scrollbar::-webkit-scrollbar{display:none}:host{color:var(--color-foreground)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}`;
|
|
@@ -4875,14 +5007,14 @@ function useChatMessages() {
|
|
|
4875
5007
|
|
|
4876
5008
|
// src/hooks/useStreamingTranscript.ts
|
|
4877
5009
|
import { useLocalParticipant as useLocalParticipant10 } from "@livekit/components-react/hooks";
|
|
4878
|
-
import { useMemo as useMemo5, useRef as
|
|
5010
|
+
import { useMemo as useMemo5, useRef as useRef17 } from "react";
|
|
4879
5011
|
function useStreamingTranscript() {
|
|
4880
5012
|
const transcriptions = useSharedTranscriptions();
|
|
4881
5013
|
const { localParticipant } = useLocalParticipant10();
|
|
4882
5014
|
const { isCapturingSpeech } = useVoiceTurnContext();
|
|
4883
5015
|
const localIdentity = localParticipant.identity;
|
|
4884
|
-
const priorUserStreamIdsRef =
|
|
4885
|
-
const wasCapturingSpeechRef =
|
|
5016
|
+
const priorUserStreamIdsRef = useRef17(new Set);
|
|
5017
|
+
const wasCapturingSpeechRef = useRef17(false);
|
|
4886
5018
|
if (isCapturingSpeech && !wasCapturingSpeechRef.current) {
|
|
4887
5019
|
priorUserStreamIdsRef.current = new Set(transcriptions.filter((stream) => stream.participantInfo.identity === localIdentity).map((stream) => stream.streamInfo.id));
|
|
4888
5020
|
}
|
|
@@ -4966,7 +5098,7 @@ function usePhaseUpdates() {
|
|
|
4966
5098
|
}
|
|
4967
5099
|
|
|
4968
5100
|
// src/hooks/useSessionRemaining.ts
|
|
4969
|
-
import { useEffect as useEffect23, useRef as
|
|
5101
|
+
import { useEffect as useEffect23, useRef as useRef18, useState as useState16 } from "react";
|
|
4970
5102
|
|
|
4971
5103
|
// src/lib/format.ts
|
|
4972
5104
|
function formatTime(seconds) {
|
|
@@ -4982,7 +5114,7 @@ function parseNumber(s) {
|
|
|
4982
5114
|
// src/hooks/useSessionRemaining.ts
|
|
4983
5115
|
function useSessionRemaining() {
|
|
4984
5116
|
const maxCallDuration = useAgentState("maxCallDuration", parseNumber, null);
|
|
4985
|
-
const endTimeRef =
|
|
5117
|
+
const endTimeRef = useRef18(null);
|
|
4986
5118
|
const [remaining, setRemaining] = useState16(null);
|
|
4987
5119
|
useEffect23(() => {
|
|
4988
5120
|
if (maxCallDuration === null || endTimeRef.current !== null)
|
|
@@ -5001,30 +5133,38 @@ function useSessionRemaining() {
|
|
|
5001
5133
|
}
|
|
5002
5134
|
|
|
5003
5135
|
// src/components/ChatHeader.tsx
|
|
5004
|
-
import { useContext as useContext12, useRef as
|
|
5136
|
+
import { useContext as useContext12, useRef as useRef21 } from "react";
|
|
5005
5137
|
|
|
5006
5138
|
// src/hooks/useElapsedSeconds.ts
|
|
5007
|
-
import { useEffect as useEffect24, useState as useState17 } from "react";
|
|
5008
|
-
function useElapsedSeconds(isRunning) {
|
|
5139
|
+
import { useEffect as useEffect24, useRef as useRef19, useState as useState17 } from "react";
|
|
5140
|
+
function useElapsedSeconds(isRunning, resetSignal) {
|
|
5009
5141
|
const [elapsed, setElapsed] = useState17(0);
|
|
5142
|
+
const accumulatedSecondsRef = useRef19(0);
|
|
5010
5143
|
useEffect24(() => {
|
|
5011
|
-
|
|
5012
|
-
setElapsed(0);
|
|
5013
|
-
return;
|
|
5014
|
-
}
|
|
5015
|
-
const startedAt = Date.now();
|
|
5144
|
+
accumulatedSecondsRef.current = 0;
|
|
5016
5145
|
setElapsed(0);
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5146
|
+
}, [resetSignal]);
|
|
5147
|
+
useEffect24(() => {
|
|
5148
|
+
if (!isRunning)
|
|
5149
|
+
return;
|
|
5150
|
+
const resumedAt = Date.now();
|
|
5151
|
+
const accumulatedSeconds = accumulatedSecondsRef.current;
|
|
5152
|
+
const totalSeconds = () => accumulatedSeconds + Math.floor((Date.now() - resumedAt) / 1000);
|
|
5153
|
+
const tick = () => setElapsed(totalSeconds());
|
|
5154
|
+
tick();
|
|
5155
|
+
const id = setInterval(tick, 1000);
|
|
5156
|
+
return () => {
|
|
5157
|
+
clearInterval(id);
|
|
5158
|
+
accumulatedSecondsRef.current = totalSeconds();
|
|
5159
|
+
setElapsed(accumulatedSecondsRef.current);
|
|
5160
|
+
};
|
|
5021
5161
|
}, [isRunning]);
|
|
5022
5162
|
return elapsed;
|
|
5023
5163
|
}
|
|
5024
5164
|
|
|
5025
5165
|
// src/hooks/useTextMode.ts
|
|
5026
5166
|
import { useLocalParticipant as useLocalParticipant11 } from "@livekit/components-react/hooks";
|
|
5027
|
-
import { useCallback as useCallback15, useContext as useContext11, useRef as
|
|
5167
|
+
import { useCallback as useCallback15, useContext as useContext11, useRef as useRef20 } from "react";
|
|
5028
5168
|
var textEncoder6 = new TextEncoder;
|
|
5029
5169
|
function useTextMode() {
|
|
5030
5170
|
const ctx = useContext11(LiveAgentContext);
|
|
@@ -5033,7 +5173,7 @@ function useTextMode() {
|
|
|
5033
5173
|
}
|
|
5034
5174
|
const { textMode, setTextModeState, sidebarTab, setSidebarTab } = ctx;
|
|
5035
5175
|
const { localParticipant } = useLocalParticipant11();
|
|
5036
|
-
const confirmedTextModeRef =
|
|
5176
|
+
const confirmedTextModeRef = useRef20(false);
|
|
5037
5177
|
const toggleTextMode = useCallback15(async () => {
|
|
5038
5178
|
const next = !textMode;
|
|
5039
5179
|
setTextModeState(next);
|
|
@@ -5073,8 +5213,9 @@ function ChatHeader() {
|
|
|
5073
5213
|
controlBarRef,
|
|
5074
5214
|
setIsDragging
|
|
5075
5215
|
} = ctx;
|
|
5076
|
-
const
|
|
5077
|
-
const
|
|
5216
|
+
const { isHeld } = useSessionHoldContext();
|
|
5217
|
+
const elapsed = useElapsedSeconds(isConnected && !isHeld, isConnected);
|
|
5218
|
+
const headerRef = useRef21(null);
|
|
5078
5219
|
const followsPanel = variant === "floating" && isPanelOpen;
|
|
5079
5220
|
const dragFollowers = followsPanel ? [panelRef, controlBarRef] : null;
|
|
5080
5221
|
const { wasDraggedRef } = useLauncherDrag(headerRef, commitLauncherDrop, dragFollowers, setIsDragging);
|
|
@@ -5086,7 +5227,7 @@ function ChatHeader() {
|
|
|
5086
5227
|
className: "skippr:flex skippr:items-center skippr:gap-3",
|
|
5087
5228
|
children: [
|
|
5088
5229
|
isConnected && /* @__PURE__ */ jsx14(HeaderModeToggle, {}),
|
|
5089
|
-
isConnected && /* @__PURE__ */ jsxs11("div", {
|
|
5230
|
+
isConnected && !isHeld && /* @__PURE__ */ jsxs11("div", {
|
|
5090
5231
|
className: "skippr:flex skippr:items-center skippr:gap-1.5 skippr:rounded-full skippr:bg-primary-foreground/20 skippr:px-2.5 skippr:py-1",
|
|
5091
5232
|
children: [
|
|
5092
5233
|
/* @__PURE__ */ jsxs11("span", {
|
|
@@ -5191,7 +5332,7 @@ function LoadingDots({ label }) {
|
|
|
5191
5332
|
}
|
|
5192
5333
|
|
|
5193
5334
|
// src/components/LoginFlow.tsx
|
|
5194
|
-
import { useCallback as useCallback16, useEffect as useEffect25, useRef as
|
|
5335
|
+
import { useCallback as useCallback16, useEffect as useEffect25, useRef as useRef22, useState as useState18 } from "react";
|
|
5195
5336
|
|
|
5196
5337
|
// src/components/ui/button.tsx
|
|
5197
5338
|
import { forwardRef as forwardRef3 } from "react";
|
|
@@ -5319,8 +5460,8 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
|
|
|
5319
5460
|
function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
|
|
5320
5461
|
const [digits, setDigits] = useState18(Array(OTP_LENGTH).fill(""));
|
|
5321
5462
|
const [resendCooldown, setResendCooldown] = useState18(0);
|
|
5322
|
-
const inputRefs =
|
|
5323
|
-
const submittedRef =
|
|
5463
|
+
const inputRefs = useRef22([]);
|
|
5464
|
+
const submittedRef = useRef22(false);
|
|
5324
5465
|
useEffect25(() => {
|
|
5325
5466
|
inputRefs.current[0]?.focus();
|
|
5326
5467
|
}, []);
|
|
@@ -5469,15 +5610,15 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
|
|
|
5469
5610
|
}
|
|
5470
5611
|
|
|
5471
5612
|
// src/components/MessageList.tsx
|
|
5472
|
-
import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3, useRef as
|
|
5613
|
+
import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3, useRef as useRef24, useState as useState20 } from "react";
|
|
5473
5614
|
|
|
5474
5615
|
// src/components/ChatInput.tsx
|
|
5475
|
-
import { useEffect as useEffect26, useRef as
|
|
5616
|
+
import { useEffect as useEffect26, useRef as useRef23, useState as useState19 } from "react";
|
|
5476
5617
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5477
5618
|
var MAX_INPUT_HEIGHT = 60;
|
|
5478
5619
|
function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
|
|
5479
5620
|
const [inputText, setInputText] = useState19("");
|
|
5480
|
-
const textareaRef =
|
|
5621
|
+
const textareaRef = useRef23(null);
|
|
5481
5622
|
const canSend = inputText.trim().length > 0 && !isSendingChat;
|
|
5482
5623
|
useEffect26(() => {
|
|
5483
5624
|
if (autoFocus)
|
|
@@ -5690,9 +5831,9 @@ function MessageList({
|
|
|
5690
5831
|
autoFocus = false,
|
|
5691
5832
|
readOnly = false
|
|
5692
5833
|
}) {
|
|
5693
|
-
const containerRef =
|
|
5694
|
-
const isPinnedToBottom =
|
|
5695
|
-
const lastSeenMessageId =
|
|
5834
|
+
const containerRef = useRef24(null);
|
|
5835
|
+
const isPinnedToBottom = useRef24(true);
|
|
5836
|
+
const lastSeenMessageId = useRef24(undefined);
|
|
5696
5837
|
const [showJumpToLatest, setShowJumpToLatest] = useState20(false);
|
|
5697
5838
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
5698
5839
|
const [dismissedPlanId, setDismissedPlanId] = useState20(null);
|
|
@@ -6283,7 +6424,7 @@ function AgentCursorMount({ animated }) {
|
|
|
6283
6424
|
function PlanPanelOpener() {
|
|
6284
6425
|
const plan = usePlanUpdates();
|
|
6285
6426
|
const { expandPanel } = useLiveAgent();
|
|
6286
|
-
const surfacedPlanIdRef =
|
|
6427
|
+
const surfacedPlanIdRef = useRef25(null);
|
|
6287
6428
|
useEffect29(() => {
|
|
6288
6429
|
if (plan?.state !== "proposed" || surfacedPlanIdRef.current === plan.planId)
|
|
6289
6430
|
return;
|
|
@@ -6370,7 +6511,7 @@ function LiveAgent(props) {
|
|
|
6370
6511
|
onStartError: expandOnSessionStartError,
|
|
6371
6512
|
onDisconnect: minimizeOnSessionDisconnect
|
|
6372
6513
|
});
|
|
6373
|
-
const teardownInFlightRef =
|
|
6514
|
+
const teardownInFlightRef = useRef25(false);
|
|
6374
6515
|
teardownInFlightRef.current = isPaused || isPausing || isDisconnecting;
|
|
6375
6516
|
const handleRoomDisconnected = useCallback18(() => {
|
|
6376
6517
|
if (teardownInFlightRef.current)
|
|
@@ -6385,8 +6526,8 @@ function LiveAgent(props) {
|
|
|
6385
6526
|
const [textMode, setTextMode] = useState21(false);
|
|
6386
6527
|
const [panelExpanded, setPanelExpanded] = useState21(false);
|
|
6387
6528
|
const togglePanelExpanded = useCallback18(() => setPanelExpanded((prev) => !prev), []);
|
|
6388
|
-
const panelRef =
|
|
6389
|
-
const controlBarRef =
|
|
6529
|
+
const panelRef = useRef25(null);
|
|
6530
|
+
const controlBarRef = useRef25(null);
|
|
6390
6531
|
const [isDragging, setIsDragging] = useState21(false);
|
|
6391
6532
|
const setTextModeState = useCallback18((enabled) => {
|
|
6392
6533
|
setTextMode(enabled);
|
|
@@ -6472,8 +6613,8 @@ function LiveAgent(props) {
|
|
|
6472
6613
|
} catch {}
|
|
6473
6614
|
}, []);
|
|
6474
6615
|
const savedLauncherBottom = readSavedLauncherBottom();
|
|
6475
|
-
const hasDraggedRef =
|
|
6476
|
-
const verticalAlignRef =
|
|
6616
|
+
const hasDraggedRef = useRef25(savedLauncherBottom !== null);
|
|
6617
|
+
const verticalAlignRef = useRef25(verticalAlign);
|
|
6477
6618
|
const [launcherBottomPx, setLauncherBottomPxState] = useState21(() => savedLauncherBottom !== null ? clampLauncherBottom(savedLauncherBottom) : verticalAlignToBottomPx(verticalAlign));
|
|
6478
6619
|
const [popsDown, setPopsDown] = useState21(() => launcherPopsDown(launcherBottomPx));
|
|
6479
6620
|
const setLauncherBottomPx = useCallback18((px) => {
|
|
@@ -6484,7 +6625,7 @@ function LiveAgent(props) {
|
|
|
6484
6625
|
localStorage.setItem("skippr_widget_bottom", String(px));
|
|
6485
6626
|
} catch {}
|
|
6486
6627
|
}, []);
|
|
6487
|
-
const launcherBottomPxRef =
|
|
6628
|
+
const launcherBottomPxRef = useRef25(launcherBottomPx);
|
|
6488
6629
|
launcherBottomPxRef.current = launcherBottomPx;
|
|
6489
6630
|
const commitLauncherDrop = useCallback18(({ side, bottomPx }) => {
|
|
6490
6631
|
setPositionWithPersist(side);
|
|
@@ -6692,47 +6833,49 @@ function LiveAgent(props) {
|
|
|
6692
6833
|
onDisconnected: handleRoomDisconnected,
|
|
6693
6834
|
children: [
|
|
6694
6835
|
connection && !textMode && /* @__PURE__ */ jsx28(RoomAudioRenderer, {}),
|
|
6695
|
-
|
|
6696
|
-
pendingScreenStream,
|
|
6697
|
-
pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
|
|
6698
|
-
}),
|
|
6699
|
-
connection && captureMode === CAPTURE_MODE.Auto && /* @__PURE__ */ jsx28(DomCapture, {
|
|
6700
|
-
pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
|
|
6701
|
-
}),
|
|
6702
|
-
/* @__PURE__ */ jsxs22(ShadowHost, {
|
|
6836
|
+
/* @__PURE__ */ jsxs22(SessionHoldProvider, {
|
|
6703
6837
|
children: [
|
|
6704
|
-
connection && captureMode === CAPTURE_MODE.
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
connection && captureMode === CAPTURE_MODE.Auto && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx28(AgentCursorMount, {
|
|
6708
|
-
animated: shouldAnimateCursor
|
|
6838
|
+
connection && captureMode === CAPTURE_MODE.Screenshare && /* @__PURE__ */ jsx28(AutoStartMedia, {
|
|
6839
|
+
pendingScreenStream,
|
|
6840
|
+
pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
|
|
6709
6841
|
}),
|
|
6710
|
-
/* @__PURE__ */ jsx28(
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6842
|
+
connection && captureMode === CAPTURE_MODE.Auto && /* @__PURE__ */ jsx28(DomCapture, {
|
|
6843
|
+
pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
|
|
6844
|
+
}),
|
|
6845
|
+
/* @__PURE__ */ jsxs22(ShadowHost, {
|
|
6846
|
+
children: [
|
|
6847
|
+
connection && captureMode === CAPTURE_MODE.Auto && agentControls?.highlight && /* @__PURE__ */ jsx28(HighlightOverlay, {}),
|
|
6848
|
+
connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PageActionHandler, {}),
|
|
6849
|
+
connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PlanPanelOpener, {}),
|
|
6850
|
+
connection && captureMode === CAPTURE_MODE.Auto && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx28(AgentCursorMount, {
|
|
6851
|
+
animated: shouldAnimateCursor
|
|
6852
|
+
}),
|
|
6853
|
+
/* @__PURE__ */ jsx28(VoiceTurnProvider, {
|
|
6854
|
+
children: /* @__PURE__ */ jsx28(TranscriptionsProvider, {
|
|
6855
|
+
children: /* @__PURE__ */ jsxs22("div", {
|
|
6856
|
+
id: WIDGET_ROOT_ID,
|
|
6857
|
+
children: [
|
|
6858
|
+
isMinimized && !showControlBar && /* @__PURE__ */ jsx28(MinimizedBubble, {
|
|
6859
|
+
welcomeMessage,
|
|
6860
|
+
welcomeDismissed,
|
|
6861
|
+
onDismissWelcome: dismissWelcome
|
|
6862
|
+
}),
|
|
6863
|
+
showControlBar && !hideControls && /* @__PURE__ */ jsx28(SessionControlBar, {}),
|
|
6864
|
+
/* @__PURE__ */ jsx28(SidebarTrigger, {}),
|
|
6865
|
+
/* @__PURE__ */ jsx28(Sidebar, {
|
|
6866
|
+
hideControls,
|
|
6867
|
+
hideHeader,
|
|
6868
|
+
startSessionLabel
|
|
6869
|
+
})
|
|
6870
|
+
]
|
|
6871
|
+
})
|
|
6729
6872
|
})
|
|
6730
6873
|
})
|
|
6731
|
-
|
|
6732
|
-
})
|
|
6874
|
+
]
|
|
6875
|
+
}),
|
|
6876
|
+
children
|
|
6733
6877
|
]
|
|
6734
|
-
})
|
|
6735
|
-
children
|
|
6878
|
+
})
|
|
6736
6879
|
]
|
|
6737
6880
|
})
|
|
6738
6881
|
});
|
|
@@ -6743,9 +6886,14 @@ function useIsLocalSpeaking() {
|
|
|
6743
6886
|
const { localParticipant } = useLocalParticipant12();
|
|
6744
6887
|
return useIsSpeaking(localParticipant);
|
|
6745
6888
|
}
|
|
6889
|
+
// src/hooks/useIsSessionHeld.ts
|
|
6890
|
+
function useIsSessionHeld() {
|
|
6891
|
+
return useSessionHoldContext().isHeld;
|
|
6892
|
+
}
|
|
6746
6893
|
export {
|
|
6747
6894
|
useMediaControls,
|
|
6748
6895
|
useLiveAgent,
|
|
6896
|
+
useIsSessionHeld,
|
|
6749
6897
|
useIsLocalSpeaking,
|
|
6750
6898
|
useElapsedSeconds,
|
|
6751
6899
|
useAgentVoiceState,
|