@skippr/live-agent-sdk 0.7.0 → 0.8.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/dist/esm/lib-exports.js +231 -131
- package/dist/skippr-sdk.css +1 -1
- package/dist/skippr-sdk.js +106 -106
- package/dist/types/components/ChatInput.d.ts +6 -0
- package/dist/types/components/MessageList.d.ts +3 -1
- package/dist/types/hooks/useChatMessages.d.ts +6 -0
- package/dist/types/hooks/useCombinedMessages.d.ts +8 -0
- package/dist/types/hooks/useStreamingTranscript.d.ts +4 -0
- package/dist/types/lib/filterSystemMessages.d.ts +2 -0
- package/dist/types/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/types/hooks/useTranscriptMessages.d.ts +0 -6
package/dist/esm/lib-exports.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/components/LiveAgent.tsx
|
|
2
2
|
import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
|
|
3
|
-
import { useCallback as
|
|
3
|
+
import { useCallback as useCallback5, useMemo as useMemo4, useState as useState5 } from "react";
|
|
4
4
|
|
|
5
5
|
// src/context/LiveAgentContext.tsx
|
|
6
6
|
import { createContext } from "react";
|
|
@@ -68,7 +68,87 @@ function useSession({ organizationId, agentId }) {
|
|
|
68
68
|
// src/components/Sidebar.tsx
|
|
69
69
|
import { useConnectionState } from "@livekit/components-react";
|
|
70
70
|
import { ConnectionState } from "livekit-client";
|
|
71
|
-
import { useEffect as
|
|
71
|
+
import { useEffect as useEffect4 } from "react";
|
|
72
|
+
|
|
73
|
+
// src/hooks/useCombinedMessages.ts
|
|
74
|
+
import { useVoiceAssistant } from "@livekit/components-react";
|
|
75
|
+
import { useMemo as useMemo3 } from "react";
|
|
76
|
+
|
|
77
|
+
// src/hooks/useChatMessages.ts
|
|
78
|
+
import { useChat, useLocalParticipant } from "@livekit/components-react";
|
|
79
|
+
import { useMemo } from "react";
|
|
80
|
+
|
|
81
|
+
// src/lib/filterSystemMessages.ts
|
|
82
|
+
var SYSTEM_MESSAGE_PATTERN = /^\[\w+\]$/;
|
|
83
|
+
function filterSystemMessages(messages) {
|
|
84
|
+
return messages.filter((m) => !SYSTEM_MESSAGE_PATTERN.test(m.content.trim()));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/hooks/useChatMessages.ts
|
|
88
|
+
function useChatMessages() {
|
|
89
|
+
const { chatMessages: rawMessages, send, isSending } = useChat();
|
|
90
|
+
const { localParticipant } = useLocalParticipant();
|
|
91
|
+
const localIdentity = localParticipant.identity;
|
|
92
|
+
const chatMessages = useMemo(() => {
|
|
93
|
+
const sortedMessages = rawMessages.map((msg) => ({
|
|
94
|
+
id: msg.id,
|
|
95
|
+
role: msg.from?.identity === localIdentity ? "user" : "assistant",
|
|
96
|
+
content: msg.message,
|
|
97
|
+
source: "chat",
|
|
98
|
+
timestamp: msg.timestamp
|
|
99
|
+
})).sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0));
|
|
100
|
+
return filterSystemMessages(sortedMessages);
|
|
101
|
+
}, [rawMessages, localIdentity]);
|
|
102
|
+
return { chatMessages, sendChatMessage: send, isSendingChat: isSending };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/hooks/useStreamingTranscript.ts
|
|
106
|
+
import { useLocalParticipant as useLocalParticipant2, useTranscriptions } from "@livekit/components-react";
|
|
107
|
+
import { useMemo as useMemo2 } from "react";
|
|
108
|
+
function useStreamingTranscript() {
|
|
109
|
+
const transcriptions = useTranscriptions();
|
|
110
|
+
const { localParticipant } = useLocalParticipant2();
|
|
111
|
+
const localIdentity = localParticipant.identity;
|
|
112
|
+
const transcriptMessages = useMemo2(() => filterSystemMessages(transcriptions.filter((stream) => stream.text.trim().length > 0).map((stream) => ({
|
|
113
|
+
id: stream.streamInfo.id,
|
|
114
|
+
role: stream.participantInfo.identity === localIdentity ? "user" : "assistant",
|
|
115
|
+
content: stream.text,
|
|
116
|
+
source: "voice-transcript",
|
|
117
|
+
timestamp: stream.streamInfo.timestamp
|
|
118
|
+
}))), [transcriptions, localIdentity]);
|
|
119
|
+
return { transcriptMessages };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/hooks/useCombinedMessages.ts
|
|
123
|
+
function mergeChatsIntoTranscripts(transcripts, chats) {
|
|
124
|
+
const merged = [];
|
|
125
|
+
let chatIndex = 0;
|
|
126
|
+
for (const transcript of transcripts) {
|
|
127
|
+
while (chatIndex < chats.length && (chats[chatIndex].timestamp ?? 0) <= (transcript.timestamp ?? 0)) {
|
|
128
|
+
merged.push(chats[chatIndex]);
|
|
129
|
+
chatIndex++;
|
|
130
|
+
}
|
|
131
|
+
merged.push(transcript);
|
|
132
|
+
}
|
|
133
|
+
while (chatIndex < chats.length) {
|
|
134
|
+
merged.push(chats[chatIndex]);
|
|
135
|
+
chatIndex++;
|
|
136
|
+
}
|
|
137
|
+
return merged;
|
|
138
|
+
}
|
|
139
|
+
function useCombinedMessages() {
|
|
140
|
+
const { transcriptMessages } = useStreamingTranscript();
|
|
141
|
+
const { chatMessages, sendChatMessage, isSendingChat } = useChatMessages();
|
|
142
|
+
const { state: agentState } = useVoiceAssistant();
|
|
143
|
+
const allMessages = useMemo3(() => {
|
|
144
|
+
if (chatMessages.length === 0)
|
|
145
|
+
return transcriptMessages;
|
|
146
|
+
if (transcriptMessages.length === 0)
|
|
147
|
+
return chatMessages;
|
|
148
|
+
return mergeChatsIntoTranscripts(transcriptMessages, chatMessages);
|
|
149
|
+
}, [transcriptMessages, chatMessages]);
|
|
150
|
+
return { allMessages, agentState, sendChatMessage, isSendingChat };
|
|
151
|
+
}
|
|
72
152
|
|
|
73
153
|
// src/hooks/useLiveAgent.ts
|
|
74
154
|
import { use } from "react";
|
|
@@ -158,43 +238,6 @@ function useQuestionUpdates() {
|
|
|
158
238
|
return { questions };
|
|
159
239
|
}
|
|
160
240
|
|
|
161
|
-
// src/hooks/useTranscriptMessages.ts
|
|
162
|
-
import {
|
|
163
|
-
useLocalParticipant,
|
|
164
|
-
useTrackTranscription,
|
|
165
|
-
useVoiceAssistant
|
|
166
|
-
} from "@livekit/components-react";
|
|
167
|
-
import { Track } from "livekit-client";
|
|
168
|
-
import { useMemo } from "react";
|
|
169
|
-
function segmentsToMessages(segments, role) {
|
|
170
|
-
return segments.filter((s) => s.final && s.text.trim().length > 0).map((s) => ({
|
|
171
|
-
id: s.id,
|
|
172
|
-
role,
|
|
173
|
-
content: s.text
|
|
174
|
-
}));
|
|
175
|
-
}
|
|
176
|
-
function useTranscriptMessages() {
|
|
177
|
-
const { agentTranscriptions, state } = useVoiceAssistant();
|
|
178
|
-
const { localParticipant } = useLocalParticipant();
|
|
179
|
-
const localMicTrack = useMemo(() => localParticipant.getTrackPublication(Track.Source.Microphone) ? {
|
|
180
|
-
participant: localParticipant,
|
|
181
|
-
source: Track.Source.Microphone,
|
|
182
|
-
publication: localParticipant.getTrackPublication(Track.Source.Microphone)
|
|
183
|
-
} : undefined, [localParticipant]);
|
|
184
|
-
const { segments: userSegments } = useTrackTranscription(localMicTrack);
|
|
185
|
-
const messages = useMemo(() => {
|
|
186
|
-
const agent = segmentsToMessages(agentTranscriptions, "assistant");
|
|
187
|
-
const user = segmentsToMessages(userSegments, "user");
|
|
188
|
-
const timeMap = new Map;
|
|
189
|
-
for (const s of agentTranscriptions)
|
|
190
|
-
timeMap.set(s.id, s.firstReceivedTime);
|
|
191
|
-
for (const s of userSegments)
|
|
192
|
-
timeMap.set(s.id, s.firstReceivedTime);
|
|
193
|
-
return [...agent, ...user].sort((a, b) => (timeMap.get(a.id) ?? 0) - (timeMap.get(b.id) ?? 0));
|
|
194
|
-
}, [agentTranscriptions, userSegments]);
|
|
195
|
-
return { messages, agentState: state };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
241
|
// src/lib/constants.ts
|
|
199
242
|
var SIDEBAR_WIDTH = 600;
|
|
200
243
|
|
|
@@ -270,7 +313,7 @@ function ChatHeader({ onClose }) {
|
|
|
270
313
|
}
|
|
271
314
|
|
|
272
315
|
// src/components/MeetingControls.tsx
|
|
273
|
-
import { useLocalParticipant as
|
|
316
|
+
import { useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react";
|
|
274
317
|
import { ScreenSharePresets } from "livekit-client";
|
|
275
318
|
import { Mic, MicOff, Monitor, MonitorOff, PhoneOff } from "lucide-react";
|
|
276
319
|
import { useCallback as useCallback4, useEffect as useEffect2, useState as useState3 } from "react";
|
|
@@ -285,7 +328,7 @@ function formatTime(seconds) {
|
|
|
285
328
|
// src/components/MeetingControls.tsx
|
|
286
329
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
287
330
|
function MeetingControls({ onHangUp }) {
|
|
288
|
-
const { localParticipant } =
|
|
331
|
+
const { localParticipant } = useLocalParticipant3();
|
|
289
332
|
const isMuted = !localParticipant.isMicrophoneEnabled;
|
|
290
333
|
const isScreenSharing = localParticipant.isScreenShareEnabled;
|
|
291
334
|
const [elapsed, setElapsed] = useState3(0);
|
|
@@ -362,15 +405,55 @@ function MeetingControls({ onHangUp }) {
|
|
|
362
405
|
}
|
|
363
406
|
|
|
364
407
|
// src/components/MessageList.tsx
|
|
365
|
-
import {
|
|
408
|
+
import { useEffect as useEffect3, useRef } from "react";
|
|
409
|
+
|
|
410
|
+
// src/components/ChatInput.tsx
|
|
411
|
+
import { SendHorizontal } from "lucide-react";
|
|
412
|
+
import { useState as useState4 } from "react";
|
|
413
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
414
|
+
function ChatInput({ sendChatMessage, isSendingChat }) {
|
|
415
|
+
const [inputText, setInputText] = useState4("");
|
|
416
|
+
const canSend = inputText.trim().length > 0 && !isSendingChat;
|
|
417
|
+
function handleSubmit(e) {
|
|
418
|
+
e.preventDefault();
|
|
419
|
+
const text = inputText.trim();
|
|
420
|
+
if (!text || isSendingChat)
|
|
421
|
+
return;
|
|
422
|
+
setInputText("");
|
|
423
|
+
sendChatMessage(text).catch(() => setInputText(text));
|
|
424
|
+
}
|
|
425
|
+
return /* @__PURE__ */ jsxs3("form", {
|
|
426
|
+
onSubmit: handleSubmit,
|
|
427
|
+
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:border-t skippr:border-border skippr:px-3 skippr:py-2",
|
|
428
|
+
children: [
|
|
429
|
+
/* @__PURE__ */ jsx4("input", {
|
|
430
|
+
type: "text",
|
|
431
|
+
value: inputText,
|
|
432
|
+
onChange: (e) => setInputText(e.target.value),
|
|
433
|
+
placeholder: "Type a message...",
|
|
434
|
+
className: cn("skippr:flex-1 skippr:rounded-lg skippr:border skippr:border-border skippr:bg-background", "skippr:px-3 skippr:py-2 skippr:text-sm skippr:text-foreground", "skippr:placeholder:text-muted-foreground skippr:outline-none", "skippr:focus:ring-1 skippr:focus:ring-ring"),
|
|
435
|
+
disabled: isSendingChat
|
|
436
|
+
}),
|
|
437
|
+
/* @__PURE__ */ jsx4("button", {
|
|
438
|
+
type: "submit",
|
|
439
|
+
disabled: !canSend,
|
|
440
|
+
"aria-label": "Send message",
|
|
441
|
+
className: cn("skippr:flex skippr:size-9 skippr:shrink-0 skippr:items-center skippr:justify-center", "skippr:rounded-lg skippr:bg-primary skippr:text-primary-foreground", "skippr:transition-opacity", !canSend && "skippr:opacity-50 skippr:cursor-not-allowed"),
|
|
442
|
+
children: /* @__PURE__ */ jsx4(SendHorizontal, {
|
|
443
|
+
className: "skippr:size-4"
|
|
444
|
+
})
|
|
445
|
+
})
|
|
446
|
+
]
|
|
447
|
+
});
|
|
448
|
+
}
|
|
366
449
|
|
|
367
450
|
// src/components/ChatMessage.tsx
|
|
368
|
-
import { jsx as
|
|
451
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
369
452
|
function ChatMessage({ message }) {
|
|
370
453
|
const isUser = message.role === "user";
|
|
371
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ jsx5("div", {
|
|
372
455
|
className: cn("skippr:flex skippr:w-full skippr:px-4 skippr:py-1", isUser ? "skippr:justify-end" : "skippr:justify-start"),
|
|
373
|
-
children: /* @__PURE__ */
|
|
456
|
+
children: /* @__PURE__ */ jsx5("div", {
|
|
374
457
|
className: cn("skippr:max-w-[85%] skippr:whitespace-pre-wrap skippr:rounded-2xl skippr:px-4 skippr:py-2.5 skippr:text-sm skippr:leading-relaxed", isUser ? "skippr:rounded-br-sm skippr:bg-primary skippr:text-primary-foreground" : "skippr:rounded-bl-sm skippr:bg-muted skippr:text-foreground"),
|
|
375
458
|
children: message.content
|
|
376
459
|
})
|
|
@@ -378,20 +461,20 @@ function ChatMessage({ message }) {
|
|
|
378
461
|
}
|
|
379
462
|
|
|
380
463
|
// src/components/TypingIndicator.tsx
|
|
381
|
-
import { jsx as
|
|
464
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
382
465
|
function TypingIndicator() {
|
|
383
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsx6("div", {
|
|
384
467
|
className: "skippr:flex skippr:items-center skippr:gap-1 skippr:px-4 skippr:py-3",
|
|
385
|
-
children: /* @__PURE__ */
|
|
468
|
+
children: /* @__PURE__ */ jsxs4("div", {
|
|
386
469
|
className: "skippr:flex skippr:items-center skippr:gap-1 skippr:rounded-2xl skippr:rounded-bl-sm skippr:bg-muted skippr:px-4 skippr:py-2.5",
|
|
387
470
|
children: [
|
|
388
|
-
/* @__PURE__ */
|
|
471
|
+
/* @__PURE__ */ jsx6("span", {
|
|
389
472
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:0ms]"
|
|
390
473
|
}),
|
|
391
|
-
/* @__PURE__ */
|
|
474
|
+
/* @__PURE__ */ jsx6("span", {
|
|
392
475
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:150ms]"
|
|
393
476
|
}),
|
|
394
|
-
/* @__PURE__ */
|
|
477
|
+
/* @__PURE__ */ jsx6("span", {
|
|
395
478
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:300ms]"
|
|
396
479
|
})
|
|
397
480
|
]
|
|
@@ -400,56 +483,71 @@ function TypingIndicator() {
|
|
|
400
483
|
}
|
|
401
484
|
|
|
402
485
|
// src/components/MessageList.tsx
|
|
403
|
-
import { jsx as
|
|
404
|
-
function MessageList({
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
486
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
487
|
+
function MessageList({
|
|
488
|
+
messages,
|
|
489
|
+
isStreaming,
|
|
490
|
+
sendChatMessage,
|
|
491
|
+
isSendingChat
|
|
492
|
+
}) {
|
|
493
|
+
const scrollRef = useRef(null);
|
|
408
494
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
495
|
+
useEffect3(() => {
|
|
496
|
+
scrollRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
497
|
+
}, [messages.length, lastMessage?.content]);
|
|
409
498
|
const showTyping = isStreaming && lastMessage?.role === "assistant" && lastMessage.content === "";
|
|
410
|
-
return /* @__PURE__ */
|
|
411
|
-
className: "skippr:flex-1 skippr:
|
|
412
|
-
children:
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
499
|
+
return /* @__PURE__ */ jsxs5("div", {
|
|
500
|
+
className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
|
|
501
|
+
children: [
|
|
502
|
+
/* @__PURE__ */ jsx7("div", {
|
|
503
|
+
className: "skippr:min-h-0 skippr:flex-1 skippr:overflow-y-auto",
|
|
504
|
+
children: /* @__PURE__ */ jsxs5("div", {
|
|
505
|
+
className: "skippr:flex skippr:flex-col skippr:gap-1 skippr:py-3",
|
|
506
|
+
children: [
|
|
507
|
+
messages.map((message) => /* @__PURE__ */ jsx7(ChatMessage, {
|
|
508
|
+
message
|
|
509
|
+
}, message.id)),
|
|
510
|
+
showTyping && /* @__PURE__ */ jsx7(TypingIndicator, {}),
|
|
511
|
+
/* @__PURE__ */ jsx7("div", {
|
|
512
|
+
ref: scrollRef
|
|
513
|
+
})
|
|
514
|
+
]
|
|
515
|
+
})
|
|
516
|
+
}),
|
|
517
|
+
/* @__PURE__ */ jsx7(ChatInput, {
|
|
518
|
+
sendChatMessage,
|
|
519
|
+
isSendingChat
|
|
520
|
+
})
|
|
521
|
+
]
|
|
424
522
|
});
|
|
425
523
|
}
|
|
426
524
|
|
|
427
525
|
// src/components/QuickActions.tsx
|
|
428
526
|
import { Loader2, MessageCircleQuestion } from "lucide-react";
|
|
429
|
-
import { jsx as
|
|
527
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
430
528
|
function QuickActions({ onStartSession, isStarting, error }) {
|
|
431
|
-
return /* @__PURE__ */
|
|
529
|
+
return /* @__PURE__ */ jsxs6("div", {
|
|
432
530
|
className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:gap-6 skippr:overflow-y-auto skippr:px-4 skippr:py-4",
|
|
433
531
|
children: [
|
|
434
|
-
/* @__PURE__ */
|
|
532
|
+
/* @__PURE__ */ jsx8("p", {
|
|
435
533
|
className: "skippr:mb-1 skippr:text-sm skippr:text-muted-foreground",
|
|
436
534
|
children: "How can I help you today?"
|
|
437
535
|
}),
|
|
438
|
-
/* @__PURE__ */
|
|
536
|
+
/* @__PURE__ */ jsxs6(Button, {
|
|
439
537
|
variant: "outline",
|
|
440
538
|
className: "skippr:h-auto skippr:flex-col skippr:gap-1.5 skippr:whitespace-normal skippr:py-3 skippr:text-xs",
|
|
441
539
|
onClick: onStartSession,
|
|
442
540
|
disabled: isStarting,
|
|
443
541
|
children: [
|
|
444
|
-
isStarting ? /* @__PURE__ */
|
|
542
|
+
isStarting ? /* @__PURE__ */ jsx8(Loader2, {
|
|
445
543
|
className: "skippr:size-4 skippr:animate-spin skippr:text-primary"
|
|
446
|
-
}) : /* @__PURE__ */
|
|
544
|
+
}) : /* @__PURE__ */ jsx8(MessageCircleQuestion, {
|
|
447
545
|
className: "skippr:size-4 skippr:text-primary"
|
|
448
546
|
}),
|
|
449
547
|
isStarting ? "Starting..." : "Start Session"
|
|
450
548
|
]
|
|
451
549
|
}),
|
|
452
|
-
error && /* @__PURE__ */
|
|
550
|
+
error && /* @__PURE__ */ jsx8("p", {
|
|
453
551
|
className: "skippr:text-xs skippr:text-destructive",
|
|
454
552
|
children: error
|
|
455
553
|
})
|
|
@@ -459,52 +557,52 @@ function QuickActions({ onStartSession, isStarting, error }) {
|
|
|
459
557
|
|
|
460
558
|
// src/components/SessionAgenda.tsx
|
|
461
559
|
import { Check, Circle, Loader2 as Loader22 } from "lucide-react";
|
|
462
|
-
import { jsx as
|
|
560
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
463
561
|
function SessionAgenda({ phases, questions = [] }) {
|
|
464
562
|
if (phases.length === 0) {
|
|
465
|
-
return /* @__PURE__ */
|
|
563
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
466
564
|
className: "skippr:flex skippr:flex-col skippr:gap-3 skippr:p-4",
|
|
467
565
|
children: [
|
|
468
|
-
/* @__PURE__ */
|
|
566
|
+
/* @__PURE__ */ jsx9("h3", {
|
|
469
567
|
className: "skippr:text-sm skippr:font-semibold",
|
|
470
568
|
children: "Agenda"
|
|
471
569
|
}),
|
|
472
|
-
/* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ jsx9("p", {
|
|
473
571
|
className: "skippr:text-xs skippr:text-muted-foreground",
|
|
474
572
|
children: "Waiting for session..."
|
|
475
573
|
})
|
|
476
574
|
]
|
|
477
575
|
});
|
|
478
576
|
}
|
|
479
|
-
return /* @__PURE__ */
|
|
577
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
480
578
|
className: "skippr:flex skippr:flex-col skippr:gap-3 skippr:p-4",
|
|
481
579
|
children: [
|
|
482
|
-
/* @__PURE__ */
|
|
580
|
+
/* @__PURE__ */ jsx9("h3", {
|
|
483
581
|
className: "skippr:text-sm skippr:font-semibold",
|
|
484
582
|
children: "Agenda"
|
|
485
583
|
}),
|
|
486
|
-
/* @__PURE__ */
|
|
584
|
+
/* @__PURE__ */ jsx9("ul", {
|
|
487
585
|
className: "skippr:flex skippr:flex-col skippr:gap-2",
|
|
488
586
|
children: phases.map((phase) => {
|
|
489
587
|
const phaseQuestions = questions.filter((q) => q.phaseName === phase.name);
|
|
490
588
|
const answeredCount = phaseQuestions.filter((q) => q.status === "answered").length;
|
|
491
589
|
const totalCount = phaseQuestions.length;
|
|
492
|
-
return /* @__PURE__ */
|
|
590
|
+
return /* @__PURE__ */ jsxs7("li", {
|
|
493
591
|
className: "skippr:flex skippr:flex-col skippr:gap-0.5",
|
|
494
592
|
children: [
|
|
495
|
-
/* @__PURE__ */
|
|
593
|
+
/* @__PURE__ */ jsxs7("div", {
|
|
496
594
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:text-sm",
|
|
497
595
|
children: [
|
|
498
|
-
/* @__PURE__ */
|
|
596
|
+
/* @__PURE__ */ jsx9(PhaseIcon, {
|
|
499
597
|
status: phase.status
|
|
500
598
|
}),
|
|
501
|
-
/* @__PURE__ */
|
|
599
|
+
/* @__PURE__ */ jsx9("span", {
|
|
502
600
|
className: cn(phase.status === "completed" && "skippr:text-muted-foreground skippr:line-through", phase.status === "active" && "skippr:font-medium skippr:text-primary"),
|
|
503
601
|
children: phase.name
|
|
504
602
|
})
|
|
505
603
|
]
|
|
506
604
|
}),
|
|
507
|
-
totalCount > 0 && /* @__PURE__ */
|
|
605
|
+
totalCount > 0 && /* @__PURE__ */ jsxs7("span", {
|
|
508
606
|
className: "skippr:ml-6 skippr:text-xs skippr:text-muted-foreground",
|
|
509
607
|
children: [
|
|
510
608
|
answeredCount,
|
|
@@ -522,56 +620,56 @@ function SessionAgenda({ phases, questions = [] }) {
|
|
|
522
620
|
}
|
|
523
621
|
function PhaseIcon({ status }) {
|
|
524
622
|
if (status === "completed") {
|
|
525
|
-
return /* @__PURE__ */
|
|
623
|
+
return /* @__PURE__ */ jsx9("div", {
|
|
526
624
|
className: "skippr:flex skippr:size-4 skippr:shrink-0 skippr:items-center skippr:justify-center skippr:rounded-full skippr:bg-primary",
|
|
527
|
-
children: /* @__PURE__ */
|
|
625
|
+
children: /* @__PURE__ */ jsx9(Check, {
|
|
528
626
|
className: "skippr:size-2.5 skippr:text-primary-foreground",
|
|
529
627
|
strokeWidth: 3
|
|
530
628
|
})
|
|
531
629
|
});
|
|
532
630
|
}
|
|
533
631
|
if (status === "active") {
|
|
534
|
-
return /* @__PURE__ */
|
|
632
|
+
return /* @__PURE__ */ jsx9(Loader22, {
|
|
535
633
|
className: "skippr:size-4 skippr:shrink-0 skippr:text-primary skippr:animate-spin"
|
|
536
634
|
});
|
|
537
635
|
}
|
|
538
|
-
return /* @__PURE__ */
|
|
636
|
+
return /* @__PURE__ */ jsx9(Circle, {
|
|
539
637
|
className: "skippr:size-4 skippr:shrink-0 skippr:text-muted-foreground"
|
|
540
638
|
});
|
|
541
639
|
}
|
|
542
640
|
|
|
543
641
|
// src/components/Sidebar.tsx
|
|
544
|
-
import { jsx as
|
|
642
|
+
import { jsx as jsx10, jsxs as jsxs8, Fragment } from "react/jsx-runtime";
|
|
545
643
|
function Sidebar() {
|
|
546
644
|
const { isConnected, isStarting, error, startSession, disconnect, isPanelOpen, closePanel } = useLiveAgent();
|
|
547
|
-
|
|
645
|
+
useEffect4(() => {
|
|
548
646
|
document.body.style.transition = "margin-right 300ms ease-in-out";
|
|
549
647
|
document.body.style.marginRight = isPanelOpen ? `${SIDEBAR_WIDTH}px` : "0px";
|
|
550
648
|
}, [isPanelOpen]);
|
|
551
|
-
|
|
649
|
+
useEffect4(() => {
|
|
552
650
|
return () => {
|
|
553
651
|
document.body.style.marginRight = "";
|
|
554
652
|
document.body.style.transition = "";
|
|
555
653
|
};
|
|
556
654
|
}, []);
|
|
557
|
-
return /* @__PURE__ */
|
|
655
|
+
return /* @__PURE__ */ jsx10("div", {
|
|
558
656
|
className: cn("skippr:fixed skippr:top-0 skippr:right-0 skippr:h-full skippr:z-[9999]", "skippr:bg-background skippr:border-l skippr:border-border", "skippr:flex skippr:flex-col", "skippr:transition-all skippr:duration-300 skippr:ease-in-out skippr:overflow-hidden", !isPanelOpen && "skippr:w-0 skippr:border-l-0"),
|
|
559
657
|
style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
|
|
560
|
-
children: isConnected ? /* @__PURE__ */
|
|
658
|
+
children: isConnected ? /* @__PURE__ */ jsxs8(Fragment, {
|
|
561
659
|
children: [
|
|
562
|
-
/* @__PURE__ */
|
|
660
|
+
/* @__PURE__ */ jsx10(ChatHeader, {
|
|
563
661
|
onClose: closePanel
|
|
564
662
|
}),
|
|
565
|
-
/* @__PURE__ */
|
|
663
|
+
/* @__PURE__ */ jsx10(ConnectedContent, {
|
|
566
664
|
onDisconnect: disconnect
|
|
567
665
|
})
|
|
568
666
|
]
|
|
569
|
-
}) : /* @__PURE__ */
|
|
667
|
+
}) : /* @__PURE__ */ jsxs8(Fragment, {
|
|
570
668
|
children: [
|
|
571
|
-
/* @__PURE__ */
|
|
669
|
+
/* @__PURE__ */ jsx10(ChatHeader, {
|
|
572
670
|
onClose: closePanel
|
|
573
671
|
}),
|
|
574
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx10(QuickActions, {
|
|
575
673
|
onStartSession: startSession,
|
|
576
674
|
isStarting,
|
|
577
675
|
error
|
|
@@ -583,39 +681,41 @@ function Sidebar() {
|
|
|
583
681
|
function ConnectedContent({ onDisconnect }) {
|
|
584
682
|
const connectionState = useConnectionState();
|
|
585
683
|
const isConnected = connectionState === ConnectionState.Connected;
|
|
586
|
-
const {
|
|
684
|
+
const { allMessages, agentState, sendChatMessage, isSendingChat } = useCombinedMessages();
|
|
587
685
|
const { phases } = usePhaseUpdates();
|
|
588
686
|
const { questions } = useQuestionUpdates();
|
|
589
687
|
if (!isConnected) {
|
|
590
|
-
return /* @__PURE__ */
|
|
688
|
+
return /* @__PURE__ */ jsx10("div", {
|
|
591
689
|
className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
|
|
592
|
-
children: /* @__PURE__ */
|
|
690
|
+
children: /* @__PURE__ */ jsx10("p", {
|
|
593
691
|
className: "skippr:text-sm skippr:text-muted-foreground",
|
|
594
692
|
children: "Connecting..."
|
|
595
693
|
})
|
|
596
694
|
});
|
|
597
695
|
}
|
|
598
696
|
const isAgentSpeaking = agentState === "speaking";
|
|
599
|
-
return /* @__PURE__ */
|
|
697
|
+
return /* @__PURE__ */ jsxs8(Fragment, {
|
|
600
698
|
children: [
|
|
601
|
-
/* @__PURE__ */
|
|
699
|
+
/* @__PURE__ */ jsx10(MeetingControls, {
|
|
602
700
|
onHangUp: onDisconnect
|
|
603
701
|
}),
|
|
604
|
-
/* @__PURE__ */
|
|
702
|
+
/* @__PURE__ */ jsxs8("div", {
|
|
605
703
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1",
|
|
606
704
|
children: [
|
|
607
|
-
/* @__PURE__ */
|
|
705
|
+
/* @__PURE__ */ jsx10("div", {
|
|
608
706
|
className: "skippr:w-[260px] skippr:shrink-0 skippr:overflow-y-auto skippr:border-r",
|
|
609
|
-
children: /* @__PURE__ */
|
|
707
|
+
children: /* @__PURE__ */ jsx10(SessionAgenda, {
|
|
610
708
|
phases,
|
|
611
709
|
questions
|
|
612
710
|
})
|
|
613
711
|
}),
|
|
614
|
-
/* @__PURE__ */
|
|
712
|
+
/* @__PURE__ */ jsx10("div", {
|
|
615
713
|
className: "skippr:flex skippr:min-w-0 skippr:flex-1 skippr:flex-col",
|
|
616
|
-
children: /* @__PURE__ */
|
|
617
|
-
messages,
|
|
618
|
-
isStreaming: isAgentSpeaking
|
|
714
|
+
children: /* @__PURE__ */ jsx10(MessageList, {
|
|
715
|
+
messages: allMessages,
|
|
716
|
+
isStreaming: isAgentSpeaking,
|
|
717
|
+
sendChatMessage,
|
|
718
|
+
isSendingChat
|
|
619
719
|
})
|
|
620
720
|
})
|
|
621
721
|
]
|
|
@@ -626,27 +726,27 @@ function ConnectedContent({ onDisconnect }) {
|
|
|
626
726
|
|
|
627
727
|
// src/components/SidebarTrigger.tsx
|
|
628
728
|
import { MessageCircle, X as X2 } from "lucide-react";
|
|
629
|
-
import { jsx as
|
|
729
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
630
730
|
var TRIGGER_GAP = 16;
|
|
631
731
|
var TRIGGER_DEFAULT_RIGHT = 24;
|
|
632
732
|
function SidebarTrigger() {
|
|
633
733
|
const { isPanelOpen, togglePanel } = useLiveAgent();
|
|
634
|
-
return /* @__PURE__ */
|
|
734
|
+
return /* @__PURE__ */ jsx11(Button, {
|
|
635
735
|
size: "icon-lg",
|
|
636
736
|
onClick: togglePanel,
|
|
637
737
|
className: "skippr:fixed skippr:bottom-6 skippr:z-[9998] skippr:size-14 skippr:rounded-full skippr:shadow-lg skippr:transition-all skippr:duration-300",
|
|
638
738
|
style: { right: isPanelOpen ? SIDEBAR_WIDTH + TRIGGER_GAP : TRIGGER_DEFAULT_RIGHT },
|
|
639
739
|
title: isPanelOpen ? "Close chat" : "Chat with us",
|
|
640
|
-
children: isPanelOpen ? /* @__PURE__ */
|
|
740
|
+
children: isPanelOpen ? /* @__PURE__ */ jsx11(X2, {
|
|
641
741
|
className: "skippr:size-6"
|
|
642
|
-
}) : /* @__PURE__ */
|
|
742
|
+
}) : /* @__PURE__ */ jsx11(MessageCircle, {
|
|
643
743
|
className: "skippr:size-6"
|
|
644
744
|
})
|
|
645
745
|
});
|
|
646
746
|
}
|
|
647
747
|
|
|
648
748
|
// src/components/LiveAgent.tsx
|
|
649
|
-
import { jsx as
|
|
749
|
+
import { jsx as jsx12, jsxs as jsxs9, Fragment as Fragment2 } from "react/jsx-runtime";
|
|
650
750
|
function LiveAgent({
|
|
651
751
|
organizationId,
|
|
652
752
|
agentId,
|
|
@@ -657,12 +757,12 @@ function LiveAgent({
|
|
|
657
757
|
organizationId,
|
|
658
758
|
agentId
|
|
659
759
|
});
|
|
660
|
-
const [isPanelOpen, setIsPanelOpen] =
|
|
661
|
-
const openPanel =
|
|
662
|
-
const closePanel =
|
|
663
|
-
const togglePanel =
|
|
760
|
+
const [isPanelOpen, setIsPanelOpen] = useState5(defaultOpen);
|
|
761
|
+
const openPanel = useCallback5(() => setIsPanelOpen(true), []);
|
|
762
|
+
const closePanel = useCallback5(() => setIsPanelOpen(false), []);
|
|
763
|
+
const togglePanel = useCallback5(() => setIsPanelOpen((prev) => !prev), []);
|
|
664
764
|
const isConnected = connection !== null;
|
|
665
|
-
const ctx =
|
|
765
|
+
const ctx = useMemo4(() => ({
|
|
666
766
|
connection,
|
|
667
767
|
shouldConnect,
|
|
668
768
|
isConnected,
|
|
@@ -687,17 +787,17 @@ function LiveAgent({
|
|
|
687
787
|
closePanel,
|
|
688
788
|
togglePanel
|
|
689
789
|
]);
|
|
690
|
-
const widgetContent = /* @__PURE__ */
|
|
790
|
+
const widgetContent = /* @__PURE__ */ jsxs9(Fragment2, {
|
|
691
791
|
children: [
|
|
692
|
-
connection && /* @__PURE__ */
|
|
693
|
-
/* @__PURE__ */
|
|
694
|
-
/* @__PURE__ */
|
|
792
|
+
connection && /* @__PURE__ */ jsx12(RoomAudioRenderer, {}),
|
|
793
|
+
/* @__PURE__ */ jsx12(SidebarTrigger, {}),
|
|
794
|
+
/* @__PURE__ */ jsx12(Sidebar, {}),
|
|
695
795
|
children
|
|
696
796
|
]
|
|
697
797
|
});
|
|
698
|
-
return /* @__PURE__ */
|
|
798
|
+
return /* @__PURE__ */ jsx12(LiveAgentContext.Provider, {
|
|
699
799
|
value: ctx,
|
|
700
|
-
children: connection ? /* @__PURE__ */
|
|
800
|
+
children: connection ? /* @__PURE__ */ jsx12(LiveKitRoom, {
|
|
701
801
|
serverUrl: connection.livekitUrl,
|
|
702
802
|
token: connection.token,
|
|
703
803
|
connect: shouldConnect,
|