@meridial/react 0.1.1 → 0.1.5
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/{chunk-RJFQIVZM.js → chunk-3DTMJFPY.js} +3 -2
- package/dist/chunk-3DTMJFPY.js.map +1 -0
- package/dist/{chunk-BWBGNRKO.js → chunk-N4DZEH4G.js} +819 -780
- package/dist/chunk-N4DZEH4G.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/recorder.js +1 -1
- package/dist/styles.css +153 -9
- package/dist/voicebox.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-BWBGNRKO.js.map +0 -1
- package/dist/chunk-RJFQIVZM.js.map +0 -1
|
@@ -22,107 +22,438 @@ import {
|
|
|
22
22
|
} from "./chunk-PRTYKFO3.js";
|
|
23
23
|
|
|
24
24
|
// src/voicebox.tsx
|
|
25
|
+
import { AnimatePresence as AnimatePresence4 } from "motion/react";
|
|
26
|
+
import { useState as useState10, useEffect as useEffect7 } from "react";
|
|
27
|
+
|
|
28
|
+
// src/components/workflow-execution.tsx
|
|
29
|
+
import { useState, useCallback, useEffect, useRef } from "react";
|
|
30
|
+
import { createPortal } from "react-dom";
|
|
25
31
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} from "
|
|
31
|
-
import { AnimatePresence as AnimatePresence3, motion as motion3 } from "motion/react";
|
|
32
|
-
import { TokenSource, RpcError as RpcError2 } from "livekit-client";
|
|
33
|
-
import { useDraggable } from "@neodrag/react";
|
|
32
|
+
motion,
|
|
33
|
+
useMotionValue,
|
|
34
|
+
useSpring,
|
|
35
|
+
AnimatePresence
|
|
36
|
+
} from "motion/react";
|
|
34
37
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} from "react";
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
default: defaultProp,
|
|
52
|
-
name,
|
|
53
|
-
state = "value"
|
|
38
|
+
Cursor02Icon,
|
|
39
|
+
ArrowLeft01Icon,
|
|
40
|
+
ArrowRight01Icon,
|
|
41
|
+
Tick01Icon
|
|
42
|
+
} from "@hugeicons/core-free-icons";
|
|
43
|
+
import { HugeiconsIcon } from "@hugeicons/react";
|
|
44
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
45
|
+
var SPRING_CONFIG = { stiffness: 120, damping: 20, mass: 0.8 };
|
|
46
|
+
var CURSOR_OFFSET = 16;
|
|
47
|
+
function WorkflowExecution({
|
|
48
|
+
workflow,
|
|
49
|
+
attribute = "data-meridial-id",
|
|
50
|
+
cursor,
|
|
51
|
+
onClose,
|
|
52
|
+
onStepChange,
|
|
53
|
+
onError
|
|
54
54
|
}) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
console.error([`Base UI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. To suppress this warning opt to use a controlled ${name}.`].join("\n"));
|
|
55
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
56
|
+
const steps = workflow.steps;
|
|
57
|
+
const currentStep = steps[currentIndex];
|
|
58
|
+
const isFirstStep = currentIndex === 0;
|
|
59
|
+
const isLastStep = currentIndex === steps.length - 1;
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
onStepChange?.(currentIndex);
|
|
62
|
+
}, [currentIndex, onStepChange]);
|
|
63
|
+
const handleBack = useCallback(() => {
|
|
64
|
+
setCurrentIndex((prev) => Math.max(0, prev - 1));
|
|
65
|
+
}, []);
|
|
66
|
+
const handleNext = useCallback(() => {
|
|
67
|
+
setCurrentIndex((prev) => {
|
|
68
|
+
if (prev >= steps.length - 1) {
|
|
69
|
+
onClose();
|
|
70
|
+
return prev;
|
|
72
71
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
return prev + 1;
|
|
73
|
+
});
|
|
74
|
+
}, [steps.length, onClose]);
|
|
75
|
+
if (!currentStep) return null;
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
ExecutionOverlay,
|
|
78
|
+
{
|
|
79
|
+
step: currentStep,
|
|
80
|
+
stepIndex: currentIndex,
|
|
81
|
+
totalSteps: steps.length,
|
|
82
|
+
isFirstStep,
|
|
83
|
+
isLastStep,
|
|
84
|
+
attribute,
|
|
85
|
+
cursor,
|
|
86
|
+
onBack: handleBack,
|
|
87
|
+
onNext: handleNext,
|
|
88
|
+
onError
|
|
78
89
|
}
|
|
79
|
-
|
|
80
|
-
return [value, setValueIfUncontrolled];
|
|
90
|
+
);
|
|
81
91
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
function ExecutionOverlay({
|
|
93
|
+
step,
|
|
94
|
+
stepIndex,
|
|
95
|
+
totalSteps,
|
|
96
|
+
isFirstStep,
|
|
97
|
+
isLastStep,
|
|
98
|
+
attribute,
|
|
99
|
+
cursor,
|
|
100
|
+
onBack,
|
|
101
|
+
onNext,
|
|
102
|
+
onError
|
|
103
|
+
}) {
|
|
104
|
+
const cssSelector = `[${attribute}="${step.elementId}"]`;
|
|
105
|
+
const { rect } = useElementTracker({
|
|
106
|
+
selector: cssSelector,
|
|
107
|
+
urlPath: step.urlPath,
|
|
108
|
+
onError: onError ? (msg) => {
|
|
109
|
+
if (msg !== null) onError(msg);
|
|
110
|
+
} : void 0,
|
|
111
|
+
onClick: onNext
|
|
112
|
+
});
|
|
113
|
+
const hasAnimated = useRef(false);
|
|
114
|
+
const springX = useSpring(useMotionValue(0), SPRING_CONFIG);
|
|
115
|
+
const springY = useSpring(useMotionValue(0), SPRING_CONFIG);
|
|
116
|
+
if (rect) {
|
|
117
|
+
const targetX = rect.right + CURSOR_OFFSET;
|
|
118
|
+
const targetY = rect.bottom + CURSOR_OFFSET;
|
|
119
|
+
if (!hasAnimated.current) {
|
|
120
|
+
springX.jump(targetX);
|
|
121
|
+
springY.jump(targetY);
|
|
122
|
+
hasAnimated.current = true;
|
|
123
|
+
} else {
|
|
124
|
+
springX.set(targetX);
|
|
125
|
+
springY.set(targetY);
|
|
93
126
|
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
var maybeReactUseId = SafeReact.useId;
|
|
98
|
-
function useId(idOverride, prefix) {
|
|
99
|
-
if (maybeReactUseId !== void 0) {
|
|
100
|
-
const reactId = maybeReactUseId();
|
|
101
|
-
return idOverride ?? (prefix ? `${prefix}-${reactId}` : reactId);
|
|
102
|
-
}
|
|
103
|
-
return useGlobalId(idOverride, prefix);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/useBaseUiId.js
|
|
107
|
-
function useBaseUiId(idOverride) {
|
|
108
|
-
return useId(idOverride, "base-ui");
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/toggle-group/ToggleGroupContext.js
|
|
112
|
-
import * as React3 from "react";
|
|
113
|
-
var ToggleGroupContext = /* @__PURE__ */ React3.createContext(void 0);
|
|
114
|
-
if (process.env.NODE_ENV !== "production") ToggleGroupContext.displayName = "ToggleGroupContext";
|
|
115
|
-
function useToggleGroupContext(optional = true) {
|
|
116
|
-
const context = React3.useContext(ToggleGroupContext);
|
|
117
|
-
if (context === void 0 && !optional) {
|
|
118
|
-
throw new Error(process.env.NODE_ENV !== "production" ? "Base UI: ToggleGroupContext is missing. ToggleGroup parts must be placed within <ToggleGroup>." : formatErrorMessage(7));
|
|
127
|
+
} else {
|
|
128
|
+
hasAnimated.current = false;
|
|
119
129
|
}
|
|
120
|
-
return
|
|
130
|
+
return createPortal(
|
|
131
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: rect && /* @__PURE__ */ jsxs(
|
|
132
|
+
motion.div,
|
|
133
|
+
{
|
|
134
|
+
"data-meridial-ui": true,
|
|
135
|
+
className: "pointer-events-none fixed z-[99999] flex items-start gap-3",
|
|
136
|
+
style: { top: springY, left: springX },
|
|
137
|
+
initial: { opacity: 0, scale: 0.6 },
|
|
138
|
+
animate: { opacity: 1, scale: 1 },
|
|
139
|
+
exit: { opacity: 0, scale: 0.6 },
|
|
140
|
+
transition: { duration: 0.2 },
|
|
141
|
+
children: [
|
|
142
|
+
cursor ?? /* @__PURE__ */ jsx(
|
|
143
|
+
HugeiconsIcon,
|
|
144
|
+
{
|
|
145
|
+
icon: Cursor02Icon,
|
|
146
|
+
strokeWidth: 2,
|
|
147
|
+
size: 32,
|
|
148
|
+
className: "mt-1 shrink-0 fill-primary/60 text-primary"
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
/* @__PURE__ */ jsxs(
|
|
152
|
+
"div",
|
|
153
|
+
{
|
|
154
|
+
"data-meridial-ui": true,
|
|
155
|
+
className: "pointer-events-auto w-72 overflow-hidden rounded-lg border border-border bg-card shadow-lg",
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxs(
|
|
158
|
+
motion.div,
|
|
159
|
+
{
|
|
160
|
+
initial: { opacity: 0, y: 8 },
|
|
161
|
+
animate: { opacity: 1, y: 0 },
|
|
162
|
+
exit: { opacity: 0, y: -8 },
|
|
163
|
+
transition: { duration: 0.2, ease: "easeInOut" },
|
|
164
|
+
className: "px-4 pt-3 pb-2",
|
|
165
|
+
children: [
|
|
166
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm leading-relaxed text-foreground", children: step.description || /* @__PURE__ */ jsx("span", { className: "text-muted-foreground italic", children: "No description" }) }),
|
|
167
|
+
/* @__PURE__ */ jsxs("span", { className: "mt-1 block text-xs text-muted-foreground", children: [
|
|
168
|
+
"Step ",
|
|
169
|
+
stepIndex + 1,
|
|
170
|
+
" of ",
|
|
171
|
+
totalSteps
|
|
172
|
+
] })
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
step.id
|
|
176
|
+
) }),
|
|
177
|
+
/* @__PURE__ */ jsxs(
|
|
178
|
+
"div",
|
|
179
|
+
{
|
|
180
|
+
"data-meridial-ui": true,
|
|
181
|
+
className: "flex justify-end gap-2 border-t px-3 py-2",
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsxs(
|
|
184
|
+
Button,
|
|
185
|
+
{
|
|
186
|
+
variant: "outline",
|
|
187
|
+
size: "sm",
|
|
188
|
+
"data-meridial-ui": true,
|
|
189
|
+
onClick: onBack,
|
|
190
|
+
disabled: isFirstStep,
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ jsx(HugeiconsIcon, { icon: ArrowLeft01Icon, size: 14 }),
|
|
193
|
+
"Back"
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
/* @__PURE__ */ jsx(
|
|
198
|
+
Button,
|
|
199
|
+
{
|
|
200
|
+
variant: "default",
|
|
201
|
+
size: "sm",
|
|
202
|
+
"data-meridial-ui": true,
|
|
203
|
+
onClick: onNext,
|
|
204
|
+
children: isLastStep ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
205
|
+
"Finish",
|
|
206
|
+
/* @__PURE__ */ jsx(HugeiconsIcon, { icon: Tick01Icon, size: 14 })
|
|
207
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
208
|
+
"Next",
|
|
209
|
+
/* @__PURE__ */ jsx(HugeiconsIcon, { icon: ArrowRight01Icon, size: 14 })
|
|
210
|
+
] })
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
) }),
|
|
222
|
+
document.body
|
|
223
|
+
);
|
|
121
224
|
}
|
|
122
225
|
|
|
123
|
-
//
|
|
124
|
-
import
|
|
125
|
-
|
|
226
|
+
// src/components/meridial-logo.tsx
|
|
227
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
228
|
+
function MeridialLogo(props) {
|
|
229
|
+
return /* @__PURE__ */ jsxs2(
|
|
230
|
+
"svg",
|
|
231
|
+
{
|
|
232
|
+
viewBox: "0 0 120 120",
|
|
233
|
+
fill: "none",
|
|
234
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
235
|
+
...props,
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ jsx2(
|
|
238
|
+
"path",
|
|
239
|
+
{
|
|
240
|
+
d: "M13.281 74.0881L15.7251 69.8003L37.7371 89.6218L83.4484 98.732L102.441 97.8991L83.2815 101.205L35.3287 95.2458L13.281 74.0881Z",
|
|
241
|
+
fill: "#009EBC",
|
|
242
|
+
stroke: "#009EBC",
|
|
243
|
+
strokeWidth: "0.5"
|
|
244
|
+
}
|
|
245
|
+
),
|
|
246
|
+
/* @__PURE__ */ jsx2(
|
|
247
|
+
"path",
|
|
248
|
+
{
|
|
249
|
+
d: "M88.6986 90.1613L15.4758 69.5032L36.8477 90.3775L83.0111 99.2024L102.445 97.7944L88.6986 90.1613Z",
|
|
250
|
+
fill: "url(#fl-g0)"
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
/* @__PURE__ */ jsx2(
|
|
254
|
+
"path",
|
|
255
|
+
{
|
|
256
|
+
d: "M9.59212 38.8499L12.934 33.2319L34.6462 62.7104L86.7973 80.1624L108.813 81.1994L86.6098 82.9394L33.6228 69.8917L9.59212 38.8499Z",
|
|
257
|
+
fill: "#009EBC",
|
|
258
|
+
stroke: "#009EBC",
|
|
259
|
+
strokeWidth: "0.5"
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
/* @__PURE__ */ jsx2(
|
|
263
|
+
"path",
|
|
264
|
+
{
|
|
265
|
+
d: "M94.1734 69.4478L12.7627 33.0524L34.7293 62.7357L86.5626 80.2897L109.003 81.1016L94.1734 69.4478Z",
|
|
266
|
+
fill: "url(#fl-g1)"
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ jsx2(
|
|
270
|
+
"path",
|
|
271
|
+
{
|
|
272
|
+
d: "M28.3329 17.4895L33.7347 13.5331L45.9901 38.7534L78.8505 55.5351L93.5023 57.1106L78.3627 57.1381L38.9556 40.7981L28.3329 17.4895Z",
|
|
273
|
+
fill: "#009EBC",
|
|
274
|
+
stroke: "#009EBC",
|
|
275
|
+
strokeWidth: "0.5"
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
/* @__PURE__ */ jsx2(
|
|
279
|
+
"path",
|
|
280
|
+
{
|
|
281
|
+
d: "M84.6112 46.7121L33.6396 12.9639L46.1488 38.6786L78.9538 55.4676L93.5814 57.0605L84.6112 46.7121Z",
|
|
282
|
+
fill: "url(#fl-g2)"
|
|
283
|
+
}
|
|
284
|
+
),
|
|
285
|
+
/* @__PURE__ */ jsxs2("defs", { children: [
|
|
286
|
+
/* @__PURE__ */ jsxs2(
|
|
287
|
+
"linearGradient",
|
|
288
|
+
{
|
|
289
|
+
id: "fl-g0",
|
|
290
|
+
x1: "57.7988",
|
|
291
|
+
y1: "66.4369",
|
|
292
|
+
x2: "60.2919",
|
|
293
|
+
y2: "100.848",
|
|
294
|
+
gradientUnits: "userSpaceOnUse",
|
|
295
|
+
children: [
|
|
296
|
+
/* @__PURE__ */ jsx2("stop", { stopColor: "#C3F6FF" }),
|
|
297
|
+
/* @__PURE__ */ jsx2("stop", { offset: "1", stopColor: "#007B92" })
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
),
|
|
301
|
+
/* @__PURE__ */ jsxs2(
|
|
302
|
+
"linearGradient",
|
|
303
|
+
{
|
|
304
|
+
id: "fl-g1",
|
|
305
|
+
x1: "61.633",
|
|
306
|
+
y1: "34.8205",
|
|
307
|
+
x2: "60.0227",
|
|
308
|
+
y2: "79.3295",
|
|
309
|
+
gradientUnits: "userSpaceOnUse",
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ jsx2("stop", { stopColor: "#B8F3FF" }),
|
|
312
|
+
/* @__PURE__ */ jsx2("stop", { offset: "1", stopColor: "#007F99" })
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsxs2(
|
|
317
|
+
"linearGradient",
|
|
318
|
+
{
|
|
319
|
+
id: "fl-g2",
|
|
320
|
+
x1: "65.4953",
|
|
321
|
+
y1: "16.4329",
|
|
322
|
+
x2: "61.4521",
|
|
323
|
+
y2: "53.5618",
|
|
324
|
+
gradientUnits: "userSpaceOnUse",
|
|
325
|
+
children: [
|
|
326
|
+
/* @__PURE__ */ jsx2("stop", { stopColor: "#D0F8FF" }),
|
|
327
|
+
/* @__PURE__ */ jsx2("stop", { offset: "1", stopColor: "#009EBC" })
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
)
|
|
331
|
+
] })
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/components/voicebox-badge.tsx
|
|
338
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
339
|
+
function VoiceboxBadge({
|
|
340
|
+
triggerIcon,
|
|
341
|
+
onClick
|
|
342
|
+
}) {
|
|
343
|
+
return /* @__PURE__ */ jsx3(
|
|
344
|
+
"button",
|
|
345
|
+
{
|
|
346
|
+
"data-meridial-ui": true,
|
|
347
|
+
onClick,
|
|
348
|
+
"aria-label": "Open assistant menu",
|
|
349
|
+
className: "group size-10 flex cursor-pointer items-center justify-center rounded-full border border-border bg-background shadow-lg transition-transform duration-200 ease-out hover:scale-110",
|
|
350
|
+
children: triggerIcon ?? /* @__PURE__ */ jsx3(MeridialLogo, { className: "size-6" })
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/components/voicebox-content.tsx
|
|
356
|
+
import {
|
|
357
|
+
useSession,
|
|
358
|
+
useAgent,
|
|
359
|
+
useSessionContext as useSessionContext3,
|
|
360
|
+
useEnsureRoom as useEnsureRoom3
|
|
361
|
+
} from "@livekit/components-react";
|
|
362
|
+
import { AnimatePresence as AnimatePresence2, motion as motion2 } from "motion/react";
|
|
363
|
+
import { TokenSource, RpcError as RpcError2 } from "livekit-client";
|
|
364
|
+
import { useDraggable } from "@neodrag/react";
|
|
365
|
+
import {
|
|
366
|
+
useRef as useRef6,
|
|
367
|
+
useState as useState8,
|
|
368
|
+
useMemo as useMemo5,
|
|
369
|
+
useEffect as useEffect6,
|
|
370
|
+
useCallback as useCallback5
|
|
371
|
+
} from "react";
|
|
372
|
+
import { ChatFeedback01Icon, Loading03Icon as Loading03Icon3 } from "@hugeicons/core-free-icons";
|
|
373
|
+
import { HugeiconsIcon as HugeiconsIcon6 } from "@hugeicons/react";
|
|
374
|
+
|
|
375
|
+
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/toggle/Toggle.js
|
|
376
|
+
import * as React7 from "react";
|
|
377
|
+
|
|
378
|
+
// ../../node_modules/.pnpm/@base-ui+utils@0.2.5_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/useControlled.js
|
|
379
|
+
import * as React from "react";
|
|
380
|
+
function useControlled({
|
|
381
|
+
controlled,
|
|
382
|
+
default: defaultProp,
|
|
383
|
+
name,
|
|
384
|
+
state = "value"
|
|
385
|
+
}) {
|
|
386
|
+
const {
|
|
387
|
+
current: isControlled
|
|
388
|
+
} = React.useRef(controlled !== void 0);
|
|
389
|
+
const [valueState, setValue] = React.useState(defaultProp);
|
|
390
|
+
const value = isControlled ? controlled : valueState;
|
|
391
|
+
if (process.env.NODE_ENV !== "production") {
|
|
392
|
+
React.useEffect(() => {
|
|
393
|
+
if (isControlled !== (controlled !== void 0)) {
|
|
394
|
+
console.error([`Base UI: A component is changing the ${isControlled ? "" : "un"}controlled ${state} state of ${name} to be ${isControlled ? "un" : ""}controlled.`, "Elements should not switch from uncontrolled to controlled (or vice versa).", `Decide between using a controlled or uncontrolled ${name} element for the lifetime of the component.`, "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", "More info: https://fb.me/react-controlled-components"].join("\n"));
|
|
395
|
+
}
|
|
396
|
+
}, [state, name, controlled]);
|
|
397
|
+
const {
|
|
398
|
+
current: defaultValue
|
|
399
|
+
} = React.useRef(defaultProp);
|
|
400
|
+
React.useEffect(() => {
|
|
401
|
+
if (!isControlled && JSON.stringify(defaultValue) !== JSON.stringify(defaultProp)) {
|
|
402
|
+
console.error([`Base UI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. To suppress this warning opt to use a controlled ${name}.`].join("\n"));
|
|
403
|
+
}
|
|
404
|
+
}, [JSON.stringify(defaultProp)]);
|
|
405
|
+
}
|
|
406
|
+
const setValueIfUncontrolled = React.useCallback((newValue) => {
|
|
407
|
+
if (!isControlled) {
|
|
408
|
+
setValue(newValue);
|
|
409
|
+
}
|
|
410
|
+
}, []);
|
|
411
|
+
return [value, setValueIfUncontrolled];
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ../../node_modules/.pnpm/@base-ui+utils@0.2.5_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/useId.js
|
|
415
|
+
import * as React2 from "react";
|
|
416
|
+
var globalId = 0;
|
|
417
|
+
function useGlobalId(idOverride, prefix = "mui") {
|
|
418
|
+
const [defaultId, setDefaultId] = React2.useState(idOverride);
|
|
419
|
+
const id = idOverride || defaultId;
|
|
420
|
+
React2.useEffect(() => {
|
|
421
|
+
if (defaultId == null) {
|
|
422
|
+
globalId += 1;
|
|
423
|
+
setDefaultId(`${prefix}-${globalId}`);
|
|
424
|
+
}
|
|
425
|
+
}, [defaultId, prefix]);
|
|
426
|
+
return id;
|
|
427
|
+
}
|
|
428
|
+
var maybeReactUseId = SafeReact.useId;
|
|
429
|
+
function useId(idOverride, prefix) {
|
|
430
|
+
if (maybeReactUseId !== void 0) {
|
|
431
|
+
const reactId = maybeReactUseId();
|
|
432
|
+
return idOverride ?? (prefix ? `${prefix}-${reactId}` : reactId);
|
|
433
|
+
}
|
|
434
|
+
return useGlobalId(idOverride, prefix);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/useBaseUiId.js
|
|
438
|
+
function useBaseUiId(idOverride) {
|
|
439
|
+
return useId(idOverride, "base-ui");
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/toggle-group/ToggleGroupContext.js
|
|
443
|
+
import * as React3 from "react";
|
|
444
|
+
var ToggleGroupContext = /* @__PURE__ */ React3.createContext(void 0);
|
|
445
|
+
if (process.env.NODE_ENV !== "production") ToggleGroupContext.displayName = "ToggleGroupContext";
|
|
446
|
+
function useToggleGroupContext(optional = true) {
|
|
447
|
+
const context = React3.useContext(ToggleGroupContext);
|
|
448
|
+
if (context === void 0 && !optional) {
|
|
449
|
+
throw new Error(process.env.NODE_ENV !== "production" ? "Base UI: ToggleGroupContext is missing. ToggleGroup parts must be placed within <ToggleGroup>." : formatErrorMessage(7));
|
|
450
|
+
}
|
|
451
|
+
return context;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/composite/item/useCompositeItem.js
|
|
455
|
+
import * as React6 from "react";
|
|
456
|
+
|
|
126
457
|
// ../../node_modules/.pnpm/@base-ui+react@1.2.0_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/composite/list/useCompositeListItem.js
|
|
127
458
|
import * as React5 from "react";
|
|
128
459
|
|
|
@@ -469,7 +800,7 @@ var Toggle = /* @__PURE__ */ React7.forwardRef(function Toggle2(componentProps,
|
|
|
469
800
|
if (process.env.NODE_ENV !== "production") Toggle.displayName = "Toggle";
|
|
470
801
|
|
|
471
802
|
// ../ui/src/components/toggle.tsx
|
|
472
|
-
import { jsx } from "react/jsx-runtime";
|
|
803
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
473
804
|
var toggleVariants = cva(
|
|
474
805
|
"group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
475
806
|
{
|
|
@@ -496,7 +827,7 @@ function Toggle3({
|
|
|
496
827
|
size = "default",
|
|
497
828
|
...props
|
|
498
829
|
}) {
|
|
499
|
-
return /* @__PURE__ */
|
|
830
|
+
return /* @__PURE__ */ jsx4(
|
|
500
831
|
Toggle,
|
|
501
832
|
{
|
|
502
833
|
"data-slot": "toggle",
|
|
@@ -519,12 +850,12 @@ function serializeTools(tools) {
|
|
|
519
850
|
}
|
|
520
851
|
|
|
521
852
|
// src/hooks/use-tool-registration.ts
|
|
522
|
-
import { useEffect as
|
|
853
|
+
import { useEffect as useEffect4 } from "react";
|
|
523
854
|
import { RpcError } from "livekit-client";
|
|
524
855
|
import { useEnsureRoom } from "@livekit/components-react";
|
|
525
856
|
function useToolRegistration(tools, onToolComplete) {
|
|
526
857
|
const room = useEnsureRoom();
|
|
527
|
-
|
|
858
|
+
useEffect4(() => {
|
|
528
859
|
if (!tools || tools.length === 0) return;
|
|
529
860
|
const cleanups = [];
|
|
530
861
|
for (const tool of tools) {
|
|
@@ -558,26 +889,26 @@ import {
|
|
|
558
889
|
SessionProvider,
|
|
559
890
|
RoomAudioRenderer
|
|
560
891
|
} from "@livekit/components-react";
|
|
561
|
-
import { jsx as
|
|
892
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
562
893
|
function AgentSessionProvider({
|
|
563
894
|
session,
|
|
564
895
|
children,
|
|
565
896
|
...roomAudioRendererProps
|
|
566
897
|
}) {
|
|
567
|
-
return /* @__PURE__ */
|
|
898
|
+
return /* @__PURE__ */ jsxs3(SessionProvider, { session, children: [
|
|
568
899
|
children,
|
|
569
|
-
/* @__PURE__ */
|
|
900
|
+
/* @__PURE__ */ jsx5(RoomAudioRenderer, { ...roomAudioRendererProps })
|
|
570
901
|
] });
|
|
571
902
|
}
|
|
572
903
|
|
|
573
904
|
// src/components/agent-audio-visualizer-bar.tsx
|
|
574
|
-
import { Fragment, useMemo as useMemo3 } from "react";
|
|
905
|
+
import { Fragment as Fragment2, useMemo as useMemo3 } from "react";
|
|
575
906
|
import {
|
|
576
907
|
useMultibandTrackVolume
|
|
577
908
|
} from "@livekit/components-react";
|
|
578
909
|
|
|
579
910
|
// src/hooks/use-agent-audio-visualizer-bar.ts
|
|
580
|
-
import { useEffect as
|
|
911
|
+
import { useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
|
|
581
912
|
function generateConnectingSequenceBar(columns) {
|
|
582
913
|
const seq = [];
|
|
583
914
|
for (let x = 0; x < columns; x++) {
|
|
@@ -590,9 +921,9 @@ function generateListeningSequenceBar(columns) {
|
|
|
590
921
|
return [[center], [-1]];
|
|
591
922
|
}
|
|
592
923
|
function useAgentAudioVisualizerBarAnimator(state, columns, interval) {
|
|
593
|
-
const [index, setIndex] =
|
|
594
|
-
const [sequence, setSequence] =
|
|
595
|
-
|
|
924
|
+
const [index, setIndex] = useState5(0);
|
|
925
|
+
const [sequence, setSequence] = useState5([[]]);
|
|
926
|
+
useEffect5(() => {
|
|
596
927
|
if (state === "thinking") {
|
|
597
928
|
setSequence(generateListeningSequenceBar(columns));
|
|
598
929
|
} else if (state === "connecting" || state === "initializing") {
|
|
@@ -606,8 +937,8 @@ function useAgentAudioVisualizerBarAnimator(state, columns, interval) {
|
|
|
606
937
|
}
|
|
607
938
|
setIndex(0);
|
|
608
939
|
}, [state, columns]);
|
|
609
|
-
const animationFrameId =
|
|
610
|
-
|
|
940
|
+
const animationFrameId = useRef5(null);
|
|
941
|
+
useEffect5(() => {
|
|
611
942
|
let startTime = performance.now();
|
|
612
943
|
const animate = (time) => {
|
|
613
944
|
if (time - startTime >= interval) {
|
|
@@ -627,7 +958,7 @@ function useAgentAudioVisualizerBarAnimator(state, columns, interval) {
|
|
|
627
958
|
}
|
|
628
959
|
|
|
629
960
|
// src/components/agent-audio-visualizer-bar.tsx
|
|
630
|
-
import { jsx as
|
|
961
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
631
962
|
function AgentAudioVisualizerBar({
|
|
632
963
|
state = "connecting",
|
|
633
964
|
barCount = 3,
|
|
@@ -663,7 +994,7 @@ function AgentAudioVisualizerBar({
|
|
|
663
994
|
() => state === "speaking" ? volumeBands : new Array(barCount).fill(0),
|
|
664
995
|
[state, volumeBands, barCount]
|
|
665
996
|
);
|
|
666
|
-
return /* @__PURE__ */
|
|
997
|
+
return /* @__PURE__ */ jsx6(
|
|
667
998
|
"div",
|
|
668
999
|
{
|
|
669
1000
|
"data-lk-state": state,
|
|
@@ -672,7 +1003,7 @@ function AgentAudioVisualizerBar({
|
|
|
672
1003
|
className
|
|
673
1004
|
),
|
|
674
1005
|
children: bands.map(
|
|
675
|
-
(band, idx) => children ? /* @__PURE__ */
|
|
1006
|
+
(band, idx) => children ? /* @__PURE__ */ jsx6(Fragment2, { children }, idx) : /* @__PURE__ */ jsx6(
|
|
676
1007
|
"div",
|
|
677
1008
|
{
|
|
678
1009
|
"data-lk-index": idx,
|
|
@@ -688,7 +1019,7 @@ function AgentAudioVisualizerBar({
|
|
|
688
1019
|
}
|
|
689
1020
|
|
|
690
1021
|
// src/components/agent-track-toggle.tsx
|
|
691
|
-
import { useMemo as useMemo4, useState as
|
|
1022
|
+
import { useMemo as useMemo4, useState as useState6 } from "react";
|
|
692
1023
|
import { Track } from "livekit-client";
|
|
693
1024
|
import {
|
|
694
1025
|
MicIcon,
|
|
@@ -697,8 +1028,8 @@ import {
|
|
|
697
1028
|
VideoIcon,
|
|
698
1029
|
VideoOffIcon
|
|
699
1030
|
} from "@hugeicons/core-free-icons";
|
|
700
|
-
import { HugeiconsIcon } from "@hugeicons/react";
|
|
701
|
-
import { jsx as
|
|
1031
|
+
import { HugeiconsIcon as HugeiconsIcon2 } from "@hugeicons/react";
|
|
1032
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
702
1033
|
function getSourceIcon(source, enabled, pending = false) {
|
|
703
1034
|
if (pending) return Loading03Icon;
|
|
704
1035
|
switch (source) {
|
|
@@ -719,7 +1050,7 @@ function AgentTrackToggle({
|
|
|
719
1050
|
onPressedChange,
|
|
720
1051
|
...props
|
|
721
1052
|
}) {
|
|
722
|
-
const [uncontrolledPressed, setUncontrolledPressed] =
|
|
1053
|
+
const [uncontrolledPressed, setUncontrolledPressed] = useState6(
|
|
723
1054
|
defaultPressed ?? false
|
|
724
1055
|
);
|
|
725
1056
|
const isControlled = pressed !== void 0;
|
|
@@ -736,7 +1067,7 @@ function AgentTrackToggle({
|
|
|
736
1067
|
if (!isControlled) setUncontrolledPressed(nextPressed);
|
|
737
1068
|
onPressedChange?.(nextPressed);
|
|
738
1069
|
};
|
|
739
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ jsxs4(
|
|
740
1071
|
Toggle3,
|
|
741
1072
|
{
|
|
742
1073
|
pressed: isControlled ? pressed : void 0,
|
|
@@ -751,8 +1082,8 @@ function AgentTrackToggle({
|
|
|
751
1082
|
),
|
|
752
1083
|
...props,
|
|
753
1084
|
children: [
|
|
754
|
-
/* @__PURE__ */
|
|
755
|
-
|
|
1085
|
+
/* @__PURE__ */ jsx7(
|
|
1086
|
+
HugeiconsIcon2,
|
|
756
1087
|
{
|
|
757
1088
|
icon: IconComponent,
|
|
758
1089
|
className: cn(pending && "animate-spin")
|
|
@@ -765,7 +1096,7 @@ function AgentTrackToggle({
|
|
|
765
1096
|
}
|
|
766
1097
|
|
|
767
1098
|
// src/components/agent-track-control.tsx
|
|
768
|
-
import { jsx as
|
|
1099
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
769
1100
|
function AgentTrackControl({
|
|
770
1101
|
source,
|
|
771
1102
|
pressed,
|
|
@@ -775,7 +1106,7 @@ function AgentTrackControl({
|
|
|
775
1106
|
audioTrack,
|
|
776
1107
|
onPressedChange
|
|
777
1108
|
}) {
|
|
778
|
-
return /* @__PURE__ */
|
|
1109
|
+
return /* @__PURE__ */ jsx8("div", { className: cn("flex items-center gap-0 rounded-md", className), children: /* @__PURE__ */ jsx8(
|
|
779
1110
|
AgentTrackToggle,
|
|
780
1111
|
{
|
|
781
1112
|
source,
|
|
@@ -784,7 +1115,7 @@ function AgentTrackControl({
|
|
|
784
1115
|
disabled: disabled2,
|
|
785
1116
|
onPressedChange,
|
|
786
1117
|
className: "peer/track group/track focus:z-10 has-[.audiovisualizer]:w-auto has-[.audiovisualizer]:px-3 has-[~_button]:rounded-r-none has-[~_button]:border-r-0 has-[~_button]:pr-2 has-[~_button]:pl-3",
|
|
787
|
-
children: audioTrack && /* @__PURE__ */
|
|
1118
|
+
children: audioTrack && /* @__PURE__ */ jsx8(
|
|
788
1119
|
AgentAudioVisualizerBar,
|
|
789
1120
|
{
|
|
790
1121
|
barCount: 3,
|
|
@@ -800,8 +1131,8 @@ function AgentTrackControl({
|
|
|
800
1131
|
// src/components/agent-disconnect-button.tsx
|
|
801
1132
|
import { useSessionContext } from "@livekit/components-react";
|
|
802
1133
|
import { CallEnd03Icon } from "@hugeicons/core-free-icons";
|
|
803
|
-
import { HugeiconsIcon as
|
|
804
|
-
import { jsx as
|
|
1134
|
+
import { HugeiconsIcon as HugeiconsIcon3 } from "@hugeicons/react";
|
|
1135
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
805
1136
|
function AgentDisconnectButton({
|
|
806
1137
|
children,
|
|
807
1138
|
onClick,
|
|
@@ -813,7 +1144,7 @@ function AgentDisconnectButton({
|
|
|
813
1144
|
onClick?.(event);
|
|
814
1145
|
if (typeof end === "function") end();
|
|
815
1146
|
};
|
|
816
|
-
return /* @__PURE__ */
|
|
1147
|
+
return /* @__PURE__ */ jsx9(
|
|
817
1148
|
Button,
|
|
818
1149
|
{
|
|
819
1150
|
variant: "destructive",
|
|
@@ -821,21 +1152,21 @@ function AgentDisconnectButton({
|
|
|
821
1152
|
onClick: handleClick,
|
|
822
1153
|
className,
|
|
823
1154
|
...props,
|
|
824
|
-
children: children ?? /* @__PURE__ */
|
|
1155
|
+
children: children ?? /* @__PURE__ */ jsx9(HugeiconsIcon3, { icon: CallEnd03Icon })
|
|
825
1156
|
}
|
|
826
1157
|
);
|
|
827
1158
|
}
|
|
828
1159
|
|
|
829
1160
|
// src/components/agent-transcript-panel.tsx
|
|
830
|
-
import { useState as
|
|
1161
|
+
import { useState as useState7 } from "react";
|
|
831
1162
|
import { useChat } from "@livekit/components-react";
|
|
832
|
-
import { HugeiconsIcon as
|
|
1163
|
+
import { HugeiconsIcon as HugeiconsIcon4 } from "@hugeicons/react";
|
|
833
1164
|
import { Loading03Icon as Loading03Icon2, Navigation03Icon } from "@hugeicons/core-free-icons";
|
|
834
|
-
import { jsx as
|
|
1165
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
835
1166
|
function AgentTranscriptPanel() {
|
|
836
1167
|
const { send } = useChat();
|
|
837
|
-
const [message, setMessage] =
|
|
838
|
-
const [isSending, setIsSending] =
|
|
1168
|
+
const [message, setMessage] = useState7("");
|
|
1169
|
+
const [isSending, setIsSending] = useState7(false);
|
|
839
1170
|
const isDisabled = isSending || message.trim().length === 0;
|
|
840
1171
|
const handleSend = async () => {
|
|
841
1172
|
if (isDisabled) return;
|
|
@@ -854,20 +1185,21 @@ function AgentTranscriptPanel() {
|
|
|
854
1185
|
handleSend();
|
|
855
1186
|
}
|
|
856
1187
|
};
|
|
857
|
-
return /* @__PURE__ */
|
|
858
|
-
/* @__PURE__ */
|
|
1188
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-1 px-2 py-1 border-b relative", children: [
|
|
1189
|
+
/* @__PURE__ */ jsx10(
|
|
859
1190
|
"textarea",
|
|
860
1191
|
{
|
|
861
1192
|
autoFocus: true,
|
|
862
1193
|
value: message,
|
|
863
1194
|
disabled: isSending,
|
|
1195
|
+
maxLength: 500,
|
|
864
1196
|
placeholder: "Type something...",
|
|
865
1197
|
onKeyDown: handleKeyDown,
|
|
866
|
-
onChange: (e) => setMessage(e.target.value),
|
|
867
|
-
className: "field-sizing-content
|
|
1198
|
+
onChange: (e) => setMessage(e.target.value.slice(0, 500)),
|
|
1199
|
+
className: "field-sizing-content h-16 min-h-6 flex-1 resize-none py-1 text-xs [scrollbar-width:thin] focus:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
|
868
1200
|
}
|
|
869
1201
|
),
|
|
870
|
-
/* @__PURE__ */
|
|
1202
|
+
/* @__PURE__ */ jsx10(
|
|
871
1203
|
"button",
|
|
872
1204
|
{
|
|
873
1205
|
type: "button",
|
|
@@ -875,18 +1207,18 @@ function AgentTranscriptPanel() {
|
|
|
875
1207
|
onClick: handleSend,
|
|
876
1208
|
title: isSending ? "Sending\u2026" : "Send",
|
|
877
1209
|
className: cn(
|
|
878
|
-
"flex size-6 flex-shrink-0 items-center justify-center self-end rounded",
|
|
1210
|
+
"flex size-6 flex-shrink-0 items-center justify-center self-end rounded absolute bottom-2 right-2",
|
|
879
1211
|
isDisabled ? "cursor-not-allowed text-muted-foreground" : "cursor-pointer text-foreground hover:opacity-80"
|
|
880
1212
|
),
|
|
881
|
-
children: isSending ? /* @__PURE__ */
|
|
882
|
-
|
|
1213
|
+
children: isSending ? /* @__PURE__ */ jsx10(
|
|
1214
|
+
HugeiconsIcon4,
|
|
883
1215
|
{
|
|
884
1216
|
icon: Loading03Icon2,
|
|
885
1217
|
size: 18,
|
|
886
1218
|
className: "animate-spin"
|
|
887
1219
|
}
|
|
888
|
-
) : /* @__PURE__ */
|
|
889
|
-
|
|
1220
|
+
) : /* @__PURE__ */ jsx10(
|
|
1221
|
+
HugeiconsIcon4,
|
|
890
1222
|
{
|
|
891
1223
|
icon: Navigation03Icon,
|
|
892
1224
|
size: 18,
|
|
@@ -895,11 +1227,11 @@ function AgentTranscriptPanel() {
|
|
|
895
1227
|
)
|
|
896
1228
|
}
|
|
897
1229
|
)
|
|
898
|
-
] })
|
|
1230
|
+
] });
|
|
899
1231
|
}
|
|
900
1232
|
|
|
901
1233
|
// src/hooks/use-input-controls.ts
|
|
902
|
-
import { useCallback as
|
|
1234
|
+
import { useCallback as useCallback4 } from "react";
|
|
903
1235
|
import { Track as Track2 } from "livekit-client";
|
|
904
1236
|
import {
|
|
905
1237
|
useTrackToggle,
|
|
@@ -932,19 +1264,19 @@ function useInputControls({
|
|
|
932
1264
|
saveAudioInputDeviceId,
|
|
933
1265
|
saveVideoInputDeviceId
|
|
934
1266
|
} = usePersistentUserChoices({ preventSave: !saveUserChoices });
|
|
935
|
-
const handleAudioDeviceChange =
|
|
1267
|
+
const handleAudioDeviceChange = useCallback4(
|
|
936
1268
|
(deviceId) => {
|
|
937
1269
|
saveAudioInputDeviceId(deviceId ?? "default");
|
|
938
1270
|
},
|
|
939
1271
|
[saveAudioInputDeviceId]
|
|
940
1272
|
);
|
|
941
|
-
const handleVideoDeviceChange =
|
|
1273
|
+
const handleVideoDeviceChange = useCallback4(
|
|
942
1274
|
(deviceId) => {
|
|
943
1275
|
saveVideoInputDeviceId(deviceId ?? "default");
|
|
944
1276
|
},
|
|
945
1277
|
[saveVideoInputDeviceId]
|
|
946
1278
|
);
|
|
947
|
-
const handleToggleCamera =
|
|
1279
|
+
const handleToggleCamera = useCallback4(
|
|
948
1280
|
async (enabled) => {
|
|
949
1281
|
if (screenShareToggle.enabled) {
|
|
950
1282
|
screenShareToggle.toggle(false);
|
|
@@ -954,14 +1286,14 @@ function useInputControls({
|
|
|
954
1286
|
},
|
|
955
1287
|
[cameraToggle, screenShareToggle, saveVideoInputEnabled]
|
|
956
1288
|
);
|
|
957
|
-
const handleToggleMicrophone =
|
|
1289
|
+
const handleToggleMicrophone = useCallback4(
|
|
958
1290
|
async (enabled) => {
|
|
959
1291
|
await microphoneToggle.toggle(enabled);
|
|
960
1292
|
saveAudioInputEnabled(!microphoneToggle.enabled);
|
|
961
1293
|
},
|
|
962
1294
|
[microphoneToggle, saveAudioInputEnabled]
|
|
963
1295
|
);
|
|
964
|
-
const handleToggleScreenShare =
|
|
1296
|
+
const handleToggleScreenShare = useCallback4(
|
|
965
1297
|
async (enabled) => {
|
|
966
1298
|
if (cameraToggle.enabled) {
|
|
967
1299
|
cameraToggle.toggle(false);
|
|
@@ -970,11 +1302,11 @@ function useInputControls({
|
|
|
970
1302
|
},
|
|
971
1303
|
[cameraToggle, screenShareToggle]
|
|
972
1304
|
);
|
|
973
|
-
const handleMicrophoneDeviceSelectError =
|
|
1305
|
+
const handleMicrophoneDeviceSelectError = useCallback4(
|
|
974
1306
|
(error2) => onDeviceError?.({ source: Track2.Source.Microphone, error: error2 }),
|
|
975
1307
|
[onDeviceError]
|
|
976
1308
|
);
|
|
977
|
-
const handleCameraDeviceSelectError =
|
|
1309
|
+
const handleCameraDeviceSelectError = useCallback4(
|
|
978
1310
|
(error2) => onDeviceError?.({ source: Track2.Source.Camera, error: error2 }),
|
|
979
1311
|
[onDeviceError]
|
|
980
1312
|
);
|
|
@@ -1001,7 +1333,7 @@ function useInputControls({
|
|
|
1001
1333
|
|
|
1002
1334
|
// src/components/start-audio-button.tsx
|
|
1003
1335
|
import { useEnsureRoom as useEnsureRoom2, useStartAudio } from "@livekit/components-react";
|
|
1004
|
-
import { jsx as
|
|
1336
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1005
1337
|
function StartAudioButton({
|
|
1006
1338
|
size = "default",
|
|
1007
1339
|
variant = "default",
|
|
@@ -1011,368 +1343,329 @@ function StartAudioButton({
|
|
|
1011
1343
|
}) {
|
|
1012
1344
|
const roomEnsured = useEnsureRoom2(room);
|
|
1013
1345
|
const { mergedProps } = useStartAudio({ room: roomEnsured, props });
|
|
1014
|
-
return /* @__PURE__ */
|
|
1346
|
+
return /* @__PURE__ */ jsx11(Button, { size, variant, ...props, ...mergedProps, children: label });
|
|
1015
1347
|
}
|
|
1016
1348
|
|
|
1017
|
-
// src/components/
|
|
1018
|
-
import { useState as useState7, useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
1019
|
-
import { createPortal } from "react-dom";
|
|
1020
|
-
import {
|
|
1021
|
-
motion,
|
|
1022
|
-
useMotionValue,
|
|
1023
|
-
useSpring,
|
|
1024
|
-
AnimatePresence
|
|
1025
|
-
} from "motion/react";
|
|
1349
|
+
// src/components/outcome-bar.tsx
|
|
1026
1350
|
import {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
Tick01Icon
|
|
1031
|
-
} from "@hugeicons/core-free-icons";
|
|
1032
|
-
import { HugeiconsIcon as HugeiconsIcon4 } from "@hugeicons/react";
|
|
1033
|
-
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1034
|
-
var SPRING_CONFIG = { stiffness: 120, damping: 20, mass: 0.8 };
|
|
1035
|
-
var CURSOR_OFFSET = 16;
|
|
1036
|
-
function WorkflowExecution({
|
|
1037
|
-
workflow,
|
|
1038
|
-
attribute = "data-meridial-id",
|
|
1039
|
-
cursor,
|
|
1040
|
-
onClose,
|
|
1041
|
-
onStepChange,
|
|
1042
|
-
onError
|
|
1043
|
-
}) {
|
|
1044
|
-
const [currentIndex, setCurrentIndex] = useState7(0);
|
|
1045
|
-
const steps = workflow.steps;
|
|
1046
|
-
const currentStep = steps[currentIndex];
|
|
1047
|
-
const isFirstStep = currentIndex === 0;
|
|
1048
|
-
const isLastStep = currentIndex === steps.length - 1;
|
|
1049
|
-
useEffect5(() => {
|
|
1050
|
-
onStepChange?.(currentIndex);
|
|
1051
|
-
}, [currentIndex, onStepChange]);
|
|
1052
|
-
const handleBack = useCallback4(() => {
|
|
1053
|
-
setCurrentIndex((prev) => Math.max(0, prev - 1));
|
|
1054
|
-
}, []);
|
|
1055
|
-
const handleNext = useCallback4(() => {
|
|
1056
|
-
setCurrentIndex((prev) => {
|
|
1057
|
-
if (prev >= steps.length - 1) {
|
|
1058
|
-
onClose();
|
|
1059
|
-
return prev;
|
|
1060
|
-
}
|
|
1061
|
-
return prev + 1;
|
|
1062
|
-
});
|
|
1063
|
-
}, [steps.length, onClose]);
|
|
1064
|
-
if (!currentStep) return null;
|
|
1065
|
-
return /* @__PURE__ */ jsx9(
|
|
1066
|
-
ExecutionOverlay,
|
|
1067
|
-
{
|
|
1068
|
-
step: currentStep,
|
|
1069
|
-
stepIndex: currentIndex,
|
|
1070
|
-
totalSteps: steps.length,
|
|
1071
|
-
isFirstStep,
|
|
1072
|
-
isLastStep,
|
|
1073
|
-
attribute,
|
|
1074
|
-
cursor,
|
|
1075
|
-
onBack: handleBack,
|
|
1076
|
-
onNext: handleNext,
|
|
1077
|
-
onError
|
|
1078
|
-
}
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
function ExecutionOverlay({
|
|
1082
|
-
step,
|
|
1083
|
-
stepIndex,
|
|
1084
|
-
totalSteps,
|
|
1085
|
-
isFirstStep,
|
|
1086
|
-
isLastStep,
|
|
1087
|
-
attribute,
|
|
1088
|
-
cursor,
|
|
1089
|
-
onBack,
|
|
1090
|
-
onNext,
|
|
1091
|
-
onError
|
|
1092
|
-
}) {
|
|
1093
|
-
const cssSelector = `[${attribute}="${step.elementId}"]`;
|
|
1094
|
-
const { rect } = useElementTracker({
|
|
1095
|
-
selector: cssSelector,
|
|
1096
|
-
urlPath: step.urlPath,
|
|
1097
|
-
onError: onError ? (msg) => {
|
|
1098
|
-
if (msg !== null) onError(msg);
|
|
1099
|
-
} : void 0,
|
|
1100
|
-
onClick: onNext
|
|
1101
|
-
});
|
|
1102
|
-
const hasAnimated = useRef5(false);
|
|
1103
|
-
const springX = useSpring(useMotionValue(0), SPRING_CONFIG);
|
|
1104
|
-
const springY = useSpring(useMotionValue(0), SPRING_CONFIG);
|
|
1105
|
-
if (rect) {
|
|
1106
|
-
const targetX = rect.right + CURSOR_OFFSET;
|
|
1107
|
-
const targetY = rect.bottom + CURSOR_OFFSET;
|
|
1108
|
-
if (!hasAnimated.current) {
|
|
1109
|
-
springX.jump(targetX);
|
|
1110
|
-
springY.jump(targetY);
|
|
1111
|
-
hasAnimated.current = true;
|
|
1112
|
-
} else {
|
|
1113
|
-
springX.set(targetX);
|
|
1114
|
-
springY.set(targetY);
|
|
1115
|
-
}
|
|
1116
|
-
} else {
|
|
1117
|
-
hasAnimated.current = false;
|
|
1118
|
-
}
|
|
1119
|
-
return createPortal(
|
|
1120
|
-
/* @__PURE__ */ jsx9(AnimatePresence, { children: rect && /* @__PURE__ */ jsxs4(
|
|
1121
|
-
motion.div,
|
|
1122
|
-
{
|
|
1123
|
-
"data-meridial-ui": true,
|
|
1124
|
-
className: "pointer-events-none fixed z-[99999] flex items-start gap-3",
|
|
1125
|
-
style: { top: springY, left: springX },
|
|
1126
|
-
initial: { opacity: 0, scale: 0.6 },
|
|
1127
|
-
animate: { opacity: 1, scale: 1 },
|
|
1128
|
-
exit: { opacity: 0, scale: 0.6 },
|
|
1129
|
-
transition: { duration: 0.2 },
|
|
1130
|
-
children: [
|
|
1131
|
-
cursor ?? /* @__PURE__ */ jsx9(
|
|
1132
|
-
HugeiconsIcon4,
|
|
1133
|
-
{
|
|
1134
|
-
icon: Cursor02Icon,
|
|
1135
|
-
strokeWidth: 2,
|
|
1136
|
-
size: 32,
|
|
1137
|
-
className: "mt-1 shrink-0 fill-primary/60 text-primary"
|
|
1138
|
-
}
|
|
1139
|
-
),
|
|
1140
|
-
/* @__PURE__ */ jsxs4(
|
|
1141
|
-
"div",
|
|
1142
|
-
{
|
|
1143
|
-
"data-meridial-ui": true,
|
|
1144
|
-
className: "pointer-events-auto w-72 overflow-hidden rounded-lg border border-border bg-card shadow-lg",
|
|
1145
|
-
children: [
|
|
1146
|
-
/* @__PURE__ */ jsx9(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsxs4(
|
|
1147
|
-
motion.div,
|
|
1148
|
-
{
|
|
1149
|
-
initial: { opacity: 0, y: 8 },
|
|
1150
|
-
animate: { opacity: 1, y: 0 },
|
|
1151
|
-
exit: { opacity: 0, y: -8 },
|
|
1152
|
-
transition: { duration: 0.2, ease: "easeInOut" },
|
|
1153
|
-
className: "px-4 pt-3 pb-2",
|
|
1154
|
-
children: [
|
|
1155
|
-
/* @__PURE__ */ jsx9("p", { className: "text-sm leading-relaxed text-foreground", children: step.description || /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground italic", children: "No description" }) }),
|
|
1156
|
-
/* @__PURE__ */ jsxs4("span", { className: "mt-1 block text-xs text-muted-foreground", children: [
|
|
1157
|
-
"Step ",
|
|
1158
|
-
stepIndex + 1,
|
|
1159
|
-
" of ",
|
|
1160
|
-
totalSteps
|
|
1161
|
-
] })
|
|
1162
|
-
]
|
|
1163
|
-
},
|
|
1164
|
-
step.id
|
|
1165
|
-
) }),
|
|
1166
|
-
/* @__PURE__ */ jsxs4(
|
|
1167
|
-
"div",
|
|
1168
|
-
{
|
|
1169
|
-
"data-meridial-ui": true,
|
|
1170
|
-
className: "flex justify-end gap-2 border-t px-3 py-2",
|
|
1171
|
-
children: [
|
|
1172
|
-
/* @__PURE__ */ jsxs4(
|
|
1173
|
-
Button,
|
|
1174
|
-
{
|
|
1175
|
-
variant: "outline",
|
|
1176
|
-
size: "sm",
|
|
1177
|
-
"data-meridial-ui": true,
|
|
1178
|
-
onClick: onBack,
|
|
1179
|
-
disabled: isFirstStep,
|
|
1180
|
-
children: [
|
|
1181
|
-
/* @__PURE__ */ jsx9(HugeiconsIcon4, { icon: ArrowLeft01Icon, size: 14 }),
|
|
1182
|
-
"Back"
|
|
1183
|
-
]
|
|
1184
|
-
}
|
|
1185
|
-
),
|
|
1186
|
-
/* @__PURE__ */ jsx9(
|
|
1187
|
-
Button,
|
|
1188
|
-
{
|
|
1189
|
-
variant: "default",
|
|
1190
|
-
size: "sm",
|
|
1191
|
-
"data-meridial-ui": true,
|
|
1192
|
-
onClick: onNext,
|
|
1193
|
-
children: isLastStep ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1194
|
-
"Finish",
|
|
1195
|
-
/* @__PURE__ */ jsx9(HugeiconsIcon4, { icon: Tick01Icon, size: 14 })
|
|
1196
|
-
] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1197
|
-
"Next",
|
|
1198
|
-
/* @__PURE__ */ jsx9(HugeiconsIcon4, { icon: ArrowRight01Icon, size: 14 })
|
|
1199
|
-
] })
|
|
1200
|
-
}
|
|
1201
|
-
)
|
|
1202
|
-
]
|
|
1203
|
-
}
|
|
1204
|
-
)
|
|
1205
|
-
]
|
|
1206
|
-
}
|
|
1207
|
-
)
|
|
1208
|
-
]
|
|
1209
|
-
}
|
|
1210
|
-
) }),
|
|
1211
|
-
document.body
|
|
1212
|
-
);
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
// src/components/outcome-bar.tsx
|
|
1216
|
-
import {
|
|
1217
|
-
ThumbsUpIcon,
|
|
1218
|
-
ThumbsDownIcon,
|
|
1219
|
-
MultiplicationSignIcon
|
|
1351
|
+
ThumbsUpIcon,
|
|
1352
|
+
ThumbsDownIcon,
|
|
1353
|
+
MultiplicationSignIcon
|
|
1220
1354
|
} from "@hugeicons/core-free-icons";
|
|
1221
1355
|
import { HugeiconsIcon as HugeiconsIcon5 } from "@hugeicons/react";
|
|
1222
|
-
import { jsx as
|
|
1356
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1223
1357
|
function OutcomeBar({ onSubmit }) {
|
|
1224
|
-
return /* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1227
|
-
/* @__PURE__ */
|
|
1358
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between border-b px-3 py-2", children: [
|
|
1359
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm text-muted-foreground", children: "Did we help?" }),
|
|
1360
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
|
|
1361
|
+
/* @__PURE__ */ jsx12(
|
|
1228
1362
|
Button,
|
|
1229
1363
|
{
|
|
1230
1364
|
variant: "ghost",
|
|
1231
1365
|
size: "icon-sm",
|
|
1232
1366
|
onClick: () => onSubmit("POSITIVE"),
|
|
1233
1367
|
"aria-label": "Yes, this helped",
|
|
1234
|
-
children: /* @__PURE__ */
|
|
1368
|
+
children: /* @__PURE__ */ jsx12(HugeiconsIcon5, { icon: ThumbsUpIcon, className: "size-4" })
|
|
1235
1369
|
}
|
|
1236
1370
|
),
|
|
1237
|
-
/* @__PURE__ */
|
|
1371
|
+
/* @__PURE__ */ jsx12(
|
|
1238
1372
|
Button,
|
|
1239
1373
|
{
|
|
1240
1374
|
variant: "ghost",
|
|
1241
1375
|
size: "icon-sm",
|
|
1242
1376
|
onClick: () => onSubmit("NEGATIVE"),
|
|
1243
1377
|
"aria-label": "No, this didn't help",
|
|
1244
|
-
children: /* @__PURE__ */
|
|
1378
|
+
children: /* @__PURE__ */ jsx12(HugeiconsIcon5, { icon: ThumbsDownIcon, className: "size-4" })
|
|
1245
1379
|
}
|
|
1246
1380
|
),
|
|
1247
|
-
/* @__PURE__ */
|
|
1381
|
+
/* @__PURE__ */ jsx12(
|
|
1248
1382
|
Button,
|
|
1249
1383
|
{
|
|
1250
1384
|
variant: "ghost",
|
|
1251
1385
|
size: "icon-sm",
|
|
1252
1386
|
onClick: () => onSubmit("NEUTRAL"),
|
|
1253
1387
|
"aria-label": "Dismiss",
|
|
1254
|
-
children: /* @__PURE__ */
|
|
1388
|
+
children: /* @__PURE__ */ jsx12(HugeiconsIcon5, { icon: MultiplicationSignIcon, className: "size-4" })
|
|
1255
1389
|
}
|
|
1256
1390
|
)
|
|
1257
1391
|
] })
|
|
1258
1392
|
] });
|
|
1259
1393
|
}
|
|
1260
1394
|
|
|
1261
|
-
// src/components/
|
|
1262
|
-
import { jsx as
|
|
1263
|
-
function
|
|
1264
|
-
|
|
1265
|
-
|
|
1395
|
+
// src/components/voicebox-content.tsx
|
|
1396
|
+
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1397
|
+
function VoiceboxContent({
|
|
1398
|
+
baseUrl,
|
|
1399
|
+
publishableKey,
|
|
1400
|
+
identifier,
|
|
1401
|
+
firstMessage,
|
|
1402
|
+
instructions,
|
|
1403
|
+
attribute,
|
|
1404
|
+
tools,
|
|
1405
|
+
cursor,
|
|
1406
|
+
metadata,
|
|
1407
|
+
initialWorkflow,
|
|
1408
|
+
onDisconnect,
|
|
1409
|
+
onError
|
|
1410
|
+
}) {
|
|
1411
|
+
const serializedTools = useMemo5(
|
|
1412
|
+
() => tools && tools.length > 0 ? serializeTools(tools) : [],
|
|
1413
|
+
[tools]
|
|
1414
|
+
);
|
|
1415
|
+
const tokenSource = useMemo5(
|
|
1416
|
+
() => TokenSource.custom(async () => {
|
|
1417
|
+
const response = await fetch(`${baseUrl}/api/auth/livekit`, {
|
|
1418
|
+
method: "POST",
|
|
1419
|
+
body: JSON.stringify({
|
|
1420
|
+
publishableKey,
|
|
1421
|
+
identifier,
|
|
1422
|
+
firstMessage,
|
|
1423
|
+
instructions,
|
|
1424
|
+
tools: serializedTools,
|
|
1425
|
+
metadata
|
|
1426
|
+
})
|
|
1427
|
+
});
|
|
1428
|
+
if (!response.ok) {
|
|
1429
|
+
const body = await response.json().catch(() => ({}));
|
|
1430
|
+
onError?.(body.error ?? `Token request failed (${response.status})`);
|
|
1431
|
+
return null;
|
|
1432
|
+
}
|
|
1433
|
+
return response.json();
|
|
1434
|
+
}),
|
|
1435
|
+
[
|
|
1436
|
+
baseUrl,
|
|
1437
|
+
publishableKey,
|
|
1438
|
+
identifier,
|
|
1439
|
+
firstMessage,
|
|
1440
|
+
instructions,
|
|
1441
|
+
serializedTools,
|
|
1442
|
+
metadata,
|
|
1443
|
+
onError
|
|
1444
|
+
]
|
|
1445
|
+
);
|
|
1446
|
+
const session = useSession(tokenSource);
|
|
1447
|
+
return /* @__PURE__ */ jsx13(AgentSessionProvider, { session, children: /* @__PURE__ */ jsx13(
|
|
1448
|
+
VoiceboxContentInner,
|
|
1266
1449
|
{
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
d: "M94.1734 69.4478L12.7627 33.0524L34.7293 62.7357L86.5626 80.2897L109.003 81.1016L94.1734 69.4478Z",
|
|
1301
|
-
fill: "url(#fl-g1)"
|
|
1302
|
-
}
|
|
1303
|
-
),
|
|
1304
|
-
/* @__PURE__ */ jsx11(
|
|
1305
|
-
"path",
|
|
1306
|
-
{
|
|
1307
|
-
d: "M28.3329 17.4895L33.7347 13.5331L45.9901 38.7534L78.8505 55.5351L93.5023 57.1106L78.3627 57.1381L38.9556 40.7981L28.3329 17.4895Z",
|
|
1308
|
-
fill: "#009EBC",
|
|
1309
|
-
stroke: "#009EBC",
|
|
1310
|
-
strokeWidth: "0.5"
|
|
1311
|
-
}
|
|
1312
|
-
),
|
|
1313
|
-
/* @__PURE__ */ jsx11(
|
|
1314
|
-
"path",
|
|
1315
|
-
{
|
|
1316
|
-
d: "M84.6112 46.7121L33.6396 12.9639L46.1488 38.6786L78.9538 55.4676L93.5814 57.0605L84.6112 46.7121Z",
|
|
1317
|
-
fill: "url(#fl-g2)"
|
|
1318
|
-
}
|
|
1319
|
-
),
|
|
1320
|
-
/* @__PURE__ */ jsxs6("defs", { children: [
|
|
1321
|
-
/* @__PURE__ */ jsxs6(
|
|
1322
|
-
"linearGradient",
|
|
1323
|
-
{
|
|
1324
|
-
id: "fl-g0",
|
|
1325
|
-
x1: "57.7988",
|
|
1326
|
-
y1: "66.4369",
|
|
1327
|
-
x2: "60.2919",
|
|
1328
|
-
y2: "100.848",
|
|
1329
|
-
gradientUnits: "userSpaceOnUse",
|
|
1330
|
-
children: [
|
|
1331
|
-
/* @__PURE__ */ jsx11("stop", { stopColor: "#C3F6FF" }),
|
|
1332
|
-
/* @__PURE__ */ jsx11("stop", { offset: "1", stopColor: "#007B92" })
|
|
1333
|
-
]
|
|
1334
|
-
}
|
|
1335
|
-
),
|
|
1336
|
-
/* @__PURE__ */ jsxs6(
|
|
1337
|
-
"linearGradient",
|
|
1338
|
-
{
|
|
1339
|
-
id: "fl-g1",
|
|
1340
|
-
x1: "61.633",
|
|
1341
|
-
y1: "34.8205",
|
|
1342
|
-
x2: "60.0227",
|
|
1343
|
-
y2: "79.3295",
|
|
1344
|
-
gradientUnits: "userSpaceOnUse",
|
|
1345
|
-
children: [
|
|
1346
|
-
/* @__PURE__ */ jsx11("stop", { stopColor: "#B8F3FF" }),
|
|
1347
|
-
/* @__PURE__ */ jsx11("stop", { offset: "1", stopColor: "#007F99" })
|
|
1348
|
-
]
|
|
1349
|
-
}
|
|
1350
|
-
),
|
|
1351
|
-
/* @__PURE__ */ jsxs6(
|
|
1352
|
-
"linearGradient",
|
|
1353
|
-
{
|
|
1354
|
-
id: "fl-g2",
|
|
1355
|
-
x1: "65.4953",
|
|
1356
|
-
y1: "16.4329",
|
|
1357
|
-
x2: "61.4521",
|
|
1358
|
-
y2: "53.5618",
|
|
1359
|
-
gradientUnits: "userSpaceOnUse",
|
|
1360
|
-
children: [
|
|
1361
|
-
/* @__PURE__ */ jsx11("stop", { stopColor: "#D0F8FF" }),
|
|
1362
|
-
/* @__PURE__ */ jsx11("stop", { offset: "1", stopColor: "#009EBC" })
|
|
1363
|
-
]
|
|
1364
|
-
}
|
|
1365
|
-
)
|
|
1366
|
-
] })
|
|
1367
|
-
]
|
|
1450
|
+
baseUrl,
|
|
1451
|
+
publishableKey,
|
|
1452
|
+
attribute,
|
|
1453
|
+
tools,
|
|
1454
|
+
cursor,
|
|
1455
|
+
initialWorkflow,
|
|
1456
|
+
onDisconnect,
|
|
1457
|
+
onError
|
|
1458
|
+
}
|
|
1459
|
+
) });
|
|
1460
|
+
}
|
|
1461
|
+
function VoiceboxContentInner({
|
|
1462
|
+
baseUrl,
|
|
1463
|
+
publishableKey,
|
|
1464
|
+
attribute,
|
|
1465
|
+
tools,
|
|
1466
|
+
cursor,
|
|
1467
|
+
initialWorkflow,
|
|
1468
|
+
onDisconnect,
|
|
1469
|
+
onError
|
|
1470
|
+
}) {
|
|
1471
|
+
const [showTranscript, setShowTranscript] = useState8(false);
|
|
1472
|
+
const [showOutcomeBar, setShowOutcomeBar] = useState8(false);
|
|
1473
|
+
const [activeWorkflow, setActiveWorkflow] = useState8(initialWorkflow ?? null);
|
|
1474
|
+
const workflowsRef = useRef6([]);
|
|
1475
|
+
const room = useEnsureRoom3();
|
|
1476
|
+
const autoStarted = useRef6(false);
|
|
1477
|
+
const outcomeShown = useRef6(false);
|
|
1478
|
+
const draggableRef = useRef6(null);
|
|
1479
|
+
const triggerOutcomeBar = useCallback5(() => {
|
|
1480
|
+
if (!outcomeShown.current) {
|
|
1481
|
+
outcomeShown.current = true;
|
|
1482
|
+
setShowOutcomeBar(true);
|
|
1368
1483
|
}
|
|
1484
|
+
}, []);
|
|
1485
|
+
const handleOutcomeSubmit = useCallback5(
|
|
1486
|
+
async (outcome) => {
|
|
1487
|
+
setShowOutcomeBar(false);
|
|
1488
|
+
try {
|
|
1489
|
+
const sessionId = await room.getSid();
|
|
1490
|
+
await fetch(`${baseUrl}/api/outcome`, {
|
|
1491
|
+
method: "POST",
|
|
1492
|
+
headers: { "Content-Type": "application/json" },
|
|
1493
|
+
body: JSON.stringify({ publishableKey, sessionId, outcome })
|
|
1494
|
+
});
|
|
1495
|
+
} catch {
|
|
1496
|
+
}
|
|
1497
|
+
},
|
|
1498
|
+
[room, baseUrl, publishableKey]
|
|
1369
1499
|
);
|
|
1500
|
+
useToolRegistration(tools, triggerOutcomeBar);
|
|
1501
|
+
useDraggable(draggableRef);
|
|
1502
|
+
useEffect6(() => {
|
|
1503
|
+
if (!publishableKey) return;
|
|
1504
|
+
fetch(`${baseUrl}/api/workflows`, {
|
|
1505
|
+
headers: { Authorization: `Bearer ${publishableKey}` }
|
|
1506
|
+
}).then((r) => r.json()).then((data) => {
|
|
1507
|
+
if (data.workflows) workflowsRef.current = data.workflows;
|
|
1508
|
+
}).catch((error2) => {
|
|
1509
|
+
onError?.(
|
|
1510
|
+
error2 instanceof Error ? error2.message : "Workflows fetch failed"
|
|
1511
|
+
);
|
|
1512
|
+
});
|
|
1513
|
+
}, [baseUrl, publishableKey]);
|
|
1514
|
+
useEffect6(() => {
|
|
1515
|
+
room.registerRpcMethod("workflow:execute", async (rpcData) => {
|
|
1516
|
+
try {
|
|
1517
|
+
const { slug } = JSON.parse(rpcData.payload);
|
|
1518
|
+
const apiWf = workflowsRef.current.find((w) => w.slug === slug);
|
|
1519
|
+
if (!apiWf) throw new Error(`Workflow '${slug}' not found`);
|
|
1520
|
+
const workflow = {
|
|
1521
|
+
id: apiWf.id,
|
|
1522
|
+
name: apiWf.name,
|
|
1523
|
+
steps: apiWf.steps,
|
|
1524
|
+
configured: true,
|
|
1525
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1526
|
+
};
|
|
1527
|
+
setActiveWorkflow({ id: apiWf.id, workflow });
|
|
1528
|
+
triggerOutcomeBar();
|
|
1529
|
+
return JSON.stringify({ success: true });
|
|
1530
|
+
} catch (error2) {
|
|
1531
|
+
onError?.(
|
|
1532
|
+
error2 instanceof Error ? error2.message : "Workflow execution failed"
|
|
1533
|
+
);
|
|
1534
|
+
throw new RpcError2(
|
|
1535
|
+
1,
|
|
1536
|
+
error2 instanceof Error ? error2.message : "Workflow execution failed"
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
});
|
|
1540
|
+
return () => {
|
|
1541
|
+
room.unregisterRpcMethod("workflow:execute");
|
|
1542
|
+
};
|
|
1543
|
+
}, [room]);
|
|
1544
|
+
const { state } = useAgent();
|
|
1545
|
+
const { start } = useSessionContext3();
|
|
1546
|
+
useEffect6(() => {
|
|
1547
|
+
if (!autoStarted.current) {
|
|
1548
|
+
autoStarted.current = true;
|
|
1549
|
+
start();
|
|
1550
|
+
}
|
|
1551
|
+
}, [start]);
|
|
1552
|
+
const isConnecting = state === "connecting" || state === "initializing" || state === "pre-connect-buffering";
|
|
1553
|
+
const isDisconnected = state === "disconnected" || state === "failed";
|
|
1554
|
+
const { microphoneTrack, microphoneToggle } = useInputControls();
|
|
1555
|
+
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1556
|
+
activeWorkflow && /* @__PURE__ */ jsx13(
|
|
1557
|
+
WorkflowExecution,
|
|
1558
|
+
{
|
|
1559
|
+
workflow: activeWorkflow.workflow,
|
|
1560
|
+
attribute,
|
|
1561
|
+
cursor,
|
|
1562
|
+
onClose: () => {
|
|
1563
|
+
setActiveWorkflow(null);
|
|
1564
|
+
triggerOutcomeBar();
|
|
1565
|
+
},
|
|
1566
|
+
onError
|
|
1567
|
+
}
|
|
1568
|
+
),
|
|
1569
|
+
/* @__PURE__ */ jsx13(
|
|
1570
|
+
motion2.div,
|
|
1571
|
+
{
|
|
1572
|
+
initial: { opacity: 0, y: 20 },
|
|
1573
|
+
animate: { opacity: 1, y: 0 },
|
|
1574
|
+
transition: { duration: 0.3, ease: "easeOut" },
|
|
1575
|
+
className: "fixed inset-x-0 bottom-8 z-50 flex justify-center",
|
|
1576
|
+
children: /* @__PURE__ */ jsxs7(
|
|
1577
|
+
"div",
|
|
1578
|
+
{
|
|
1579
|
+
ref: draggableRef,
|
|
1580
|
+
"data-meridial-ui": true,
|
|
1581
|
+
className: "w-72 items-stretch rounded border border-border bg-card shadow-md",
|
|
1582
|
+
children: [
|
|
1583
|
+
/* @__PURE__ */ jsx13(AnimatePresence2, { initial: false, children: showTranscript && /* @__PURE__ */ jsx13(
|
|
1584
|
+
motion2.div,
|
|
1585
|
+
{
|
|
1586
|
+
initial: { height: 0, opacity: 0 },
|
|
1587
|
+
animate: { height: "auto", opacity: 1 },
|
|
1588
|
+
exit: { height: 0, opacity: 0 },
|
|
1589
|
+
transition: { duration: 0.24, ease: "easeOut" },
|
|
1590
|
+
style: { overflow: "hidden" },
|
|
1591
|
+
children: /* @__PURE__ */ jsx13(AgentTranscriptPanel, {})
|
|
1592
|
+
}
|
|
1593
|
+
) }),
|
|
1594
|
+
/* @__PURE__ */ jsx13(AnimatePresence2, { initial: false, children: showOutcomeBar && /* @__PURE__ */ jsx13(
|
|
1595
|
+
motion2.div,
|
|
1596
|
+
{
|
|
1597
|
+
initial: { height: 0, opacity: 0 },
|
|
1598
|
+
animate: { height: "auto", opacity: 1 },
|
|
1599
|
+
exit: { height: 0, opacity: 0 },
|
|
1600
|
+
transition: { duration: 0.24, ease: "easeOut" },
|
|
1601
|
+
style: { overflow: "hidden" },
|
|
1602
|
+
children: /* @__PURE__ */ jsx13(OutcomeBar, { onSubmit: handleOutcomeSubmit })
|
|
1603
|
+
}
|
|
1604
|
+
) }),
|
|
1605
|
+
/* @__PURE__ */ jsxs7("div", { "data-meridial-ui": true, className: "flex h-12 items-center", children: [
|
|
1606
|
+
/* @__PURE__ */ jsx13(DragHandle, { className: "px-2" }),
|
|
1607
|
+
/* @__PURE__ */ jsx13(Separator, { orientation: "vertical", className: "h-full" }),
|
|
1608
|
+
/* @__PURE__ */ jsxs7("div", { className: "relative flex h-full flex-1 items-center justify-between px-2", children: [
|
|
1609
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1610
|
+
/* @__PURE__ */ jsx13(
|
|
1611
|
+
AgentTrackControl,
|
|
1612
|
+
{
|
|
1613
|
+
source: "microphone",
|
|
1614
|
+
pressed: microphoneToggle.enabled,
|
|
1615
|
+
pending: microphoneToggle.pending,
|
|
1616
|
+
disabled: microphoneToggle.pending,
|
|
1617
|
+
audioTrack: microphoneTrack,
|
|
1618
|
+
onPressedChange: microphoneToggle.toggle
|
|
1619
|
+
}
|
|
1620
|
+
),
|
|
1621
|
+
/* @__PURE__ */ jsx13(
|
|
1622
|
+
Toggle3,
|
|
1623
|
+
{
|
|
1624
|
+
disabled: isDisconnected || isConnecting,
|
|
1625
|
+
pressed: showTranscript,
|
|
1626
|
+
"aria-label": "Toggle transcript",
|
|
1627
|
+
onPressedChange: setShowTranscript,
|
|
1628
|
+
className: cn(
|
|
1629
|
+
"size-9 rounded-lg",
|
|
1630
|
+
showTranscript ? "bg-muted text-foreground" : "bg-transparent text-muted-foreground hover:text-foreground"
|
|
1631
|
+
),
|
|
1632
|
+
children: /* @__PURE__ */ jsx13(HugeiconsIcon6, { icon: ChatFeedback01Icon })
|
|
1633
|
+
}
|
|
1634
|
+
)
|
|
1635
|
+
] }),
|
|
1636
|
+
/* @__PURE__ */ jsx13(
|
|
1637
|
+
AgentAudioVisualizerBar,
|
|
1638
|
+
{
|
|
1639
|
+
barCount: 16,
|
|
1640
|
+
state,
|
|
1641
|
+
audioTrack: microphoneTrack
|
|
1642
|
+
}
|
|
1643
|
+
),
|
|
1644
|
+
isConnecting ? /* @__PURE__ */ jsxs7(Button, { variant: "outline", children: [
|
|
1645
|
+
/* @__PURE__ */ jsx13("span", { children: "Connecting" }),
|
|
1646
|
+
/* @__PURE__ */ jsx13(
|
|
1647
|
+
HugeiconsIcon6,
|
|
1648
|
+
{
|
|
1649
|
+
icon: Loading03Icon3,
|
|
1650
|
+
className: "animate-spin"
|
|
1651
|
+
}
|
|
1652
|
+
)
|
|
1653
|
+
] }) : /* @__PURE__ */ jsx13(AgentDisconnectButton, { onClick: onDisconnect }),
|
|
1654
|
+
/* @__PURE__ */ jsx13(StartAudioButton, { label: "Start Audio" })
|
|
1655
|
+
] })
|
|
1656
|
+
] })
|
|
1657
|
+
]
|
|
1658
|
+
}
|
|
1659
|
+
)
|
|
1660
|
+
}
|
|
1661
|
+
)
|
|
1662
|
+
] });
|
|
1370
1663
|
}
|
|
1371
1664
|
|
|
1372
1665
|
// src/components/voicebox-menu.tsx
|
|
1373
|
-
import { useState as
|
|
1374
|
-
import { motion as
|
|
1375
|
-
import { HugeiconsIcon as
|
|
1666
|
+
import { useState as useState9 } from "react";
|
|
1667
|
+
import { motion as motion3, AnimatePresence as AnimatePresence3 } from "motion/react";
|
|
1668
|
+
import { HugeiconsIcon as HugeiconsIcon7 } from "@hugeicons/react";
|
|
1376
1669
|
import {
|
|
1377
1670
|
Call02Icon,
|
|
1378
1671
|
ViewOffSlashIcon,
|
|
@@ -1380,7 +1673,7 @@ import {
|
|
|
1380
1673
|
Cancel01Icon,
|
|
1381
1674
|
StarIcon
|
|
1382
1675
|
} from "@hugeicons/core-free-icons";
|
|
1383
|
-
import { jsx as
|
|
1676
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1384
1677
|
var POSITION_LABELS = {
|
|
1385
1678
|
"top-left": "Top Left",
|
|
1386
1679
|
"top-right": "Top Right",
|
|
@@ -1421,14 +1714,14 @@ function VoiceboxMenu({
|
|
|
1421
1714
|
onAbortGuide
|
|
1422
1715
|
}) {
|
|
1423
1716
|
const placement = MENU_PLACEMENT[position];
|
|
1424
|
-
const [activeTab, setActiveTab] =
|
|
1717
|
+
const [activeTab, setActiveTab] = useState9("settings");
|
|
1425
1718
|
const sortedWorkflows = [...workflows].sort((a, b) => {
|
|
1426
1719
|
if (a.isFavorite && !b.isFavorite) return -1;
|
|
1427
1720
|
if (!a.isFavorite && b.isFavorite) return 1;
|
|
1428
1721
|
return 0;
|
|
1429
1722
|
});
|
|
1430
|
-
return /* @__PURE__ */
|
|
1431
|
-
|
|
1723
|
+
return /* @__PURE__ */ jsxs8(
|
|
1724
|
+
motion3.div,
|
|
1432
1725
|
{
|
|
1433
1726
|
"data-meridial-ui": true,
|
|
1434
1727
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -1445,8 +1738,8 @@ function VoiceboxMenu({
|
|
|
1445
1738
|
},
|
|
1446
1739
|
transition: { duration: 0.15, ease: "easeOut" },
|
|
1447
1740
|
children: [
|
|
1448
|
-
/* @__PURE__ */
|
|
1449
|
-
/* @__PURE__ */
|
|
1741
|
+
/* @__PURE__ */ jsxs8("div", { "data-meridial-ui": true, className: "flex border-b border-border", children: [
|
|
1742
|
+
/* @__PURE__ */ jsx14(
|
|
1450
1743
|
"button",
|
|
1451
1744
|
{
|
|
1452
1745
|
"data-meridial-ui": true,
|
|
@@ -1458,7 +1751,7 @@ function VoiceboxMenu({
|
|
|
1458
1751
|
children: "Settings"
|
|
1459
1752
|
}
|
|
1460
1753
|
),
|
|
1461
|
-
/* @__PURE__ */
|
|
1754
|
+
/* @__PURE__ */ jsx14(
|
|
1462
1755
|
"button",
|
|
1463
1756
|
{
|
|
1464
1757
|
"data-meridial-ui": true,
|
|
@@ -1471,8 +1764,8 @@ function VoiceboxMenu({
|
|
|
1471
1764
|
}
|
|
1472
1765
|
)
|
|
1473
1766
|
] }),
|
|
1474
|
-
/* @__PURE__ */
|
|
1475
|
-
|
|
1767
|
+
/* @__PURE__ */ jsx14(AnimatePresence3, { mode: "wait", children: activeTab === "settings" ? /* @__PURE__ */ jsxs8(
|
|
1768
|
+
motion3.div,
|
|
1476
1769
|
{
|
|
1477
1770
|
initial: { opacity: 0 },
|
|
1478
1771
|
animate: { opacity: 1 },
|
|
@@ -1480,14 +1773,14 @@ function VoiceboxMenu({
|
|
|
1480
1773
|
transition: { duration: 0.1 },
|
|
1481
1774
|
className: "flex flex-col gap-0 h-[200px]",
|
|
1482
1775
|
children: [
|
|
1483
|
-
/* @__PURE__ */
|
|
1776
|
+
/* @__PURE__ */ jsxs8(
|
|
1484
1777
|
"div",
|
|
1485
1778
|
{
|
|
1486
1779
|
"data-meridial-ui": true,
|
|
1487
1780
|
className: "border-b border-border px-3 py-2.5",
|
|
1488
1781
|
children: [
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__PURE__ */
|
|
1782
|
+
/* @__PURE__ */ jsx14("span", { className: "mb-1.5 block text-xs font-medium tracking-wider text-muted-foreground", children: "Position" }),
|
|
1783
|
+
/* @__PURE__ */ jsx14("div", { className: "grid grid-cols-2 gap-1", children: Object.entries(POSITION_LABELS).map(([pos, label]) => /* @__PURE__ */ jsx14(
|
|
1491
1784
|
"button",
|
|
1492
1785
|
{
|
|
1493
1786
|
"data-meridial-ui": true,
|
|
@@ -1503,17 +1796,17 @@ function VoiceboxMenu({
|
|
|
1503
1796
|
]
|
|
1504
1797
|
}
|
|
1505
1798
|
),
|
|
1506
|
-
/* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1508
|
-
/* @__PURE__ */
|
|
1799
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-b border-border px-3 py-2.5", children: [
|
|
1800
|
+
/* @__PURE__ */ jsx14("span", { className: "text-xs font-medium tracking-wider text-muted-foreground", children: "Hide Until Next Visit" }),
|
|
1801
|
+
/* @__PURE__ */ jsx14(
|
|
1509
1802
|
Button,
|
|
1510
1803
|
{
|
|
1511
1804
|
variant: "ghost",
|
|
1512
1805
|
size: "sm",
|
|
1513
1806
|
"data-meridial-ui": true,
|
|
1514
1807
|
onClick: onHide,
|
|
1515
|
-
children: /* @__PURE__ */
|
|
1516
|
-
|
|
1808
|
+
children: /* @__PURE__ */ jsx14(
|
|
1809
|
+
HugeiconsIcon7,
|
|
1517
1810
|
{
|
|
1518
1811
|
icon: ViewOffSlashIcon,
|
|
1519
1812
|
size: 16,
|
|
@@ -1523,7 +1816,7 @@ function VoiceboxMenu({
|
|
|
1523
1816
|
}
|
|
1524
1817
|
)
|
|
1525
1818
|
] }),
|
|
1526
|
-
/* @__PURE__ */
|
|
1819
|
+
/* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center p-2", children: /* @__PURE__ */ jsxs8(
|
|
1527
1820
|
Button,
|
|
1528
1821
|
{
|
|
1529
1822
|
"data-meridial-ui": true,
|
|
@@ -1531,8 +1824,8 @@ function VoiceboxMenu({
|
|
|
1531
1824
|
variant: "default",
|
|
1532
1825
|
className: "w-full",
|
|
1533
1826
|
children: [
|
|
1534
|
-
/* @__PURE__ */
|
|
1535
|
-
|
|
1827
|
+
/* @__PURE__ */ jsx14(
|
|
1828
|
+
HugeiconsIcon7,
|
|
1536
1829
|
{
|
|
1537
1830
|
icon: Call02Icon,
|
|
1538
1831
|
size: 16,
|
|
@@ -1546,55 +1839,55 @@ function VoiceboxMenu({
|
|
|
1546
1839
|
]
|
|
1547
1840
|
},
|
|
1548
1841
|
"settings"
|
|
1549
|
-
) : /* @__PURE__ */
|
|
1550
|
-
|
|
1842
|
+
) : /* @__PURE__ */ jsx14(
|
|
1843
|
+
motion3.div,
|
|
1551
1844
|
{
|
|
1552
1845
|
initial: { opacity: 0 },
|
|
1553
1846
|
animate: { opacity: 1 },
|
|
1554
1847
|
exit: { opacity: 0 },
|
|
1555
1848
|
transition: { duration: 0.1 },
|
|
1556
1849
|
className: "h-[200px] overflow-y-auto",
|
|
1557
|
-
children: sortedWorkflows.length === 0 ? /* @__PURE__ */
|
|
1850
|
+
children: sortedWorkflows.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "flex h-full items-center justify-center text-xs text-muted-foreground", children: "No guides available" }) : /* @__PURE__ */ jsx14("div", { className: "flex flex-col gap-0.5 p-2", children: sortedWorkflows.map((wf) => {
|
|
1558
1851
|
const isPlaying = wf.id === playingWorkflowId;
|
|
1559
1852
|
const totalSteps = wf.steps.length;
|
|
1560
1853
|
const progressPercent = isPlaying && totalSteps > 0 ? (playingStepIndex + 1) / totalSteps * 100 : 0;
|
|
1561
|
-
return /* @__PURE__ */
|
|
1854
|
+
return /* @__PURE__ */ jsxs8(
|
|
1562
1855
|
"div",
|
|
1563
1856
|
{
|
|
1564
1857
|
"data-meridial-ui": true,
|
|
1565
1858
|
className: "relative overflow-hidden rounded-md px-3 py-2 hover:bg-muted",
|
|
1566
1859
|
children: [
|
|
1567
|
-
isPlaying && /* @__PURE__ */
|
|
1860
|
+
isPlaying && /* @__PURE__ */ jsx14(
|
|
1568
1861
|
"div",
|
|
1569
1862
|
{
|
|
1570
1863
|
className: "absolute inset-0 bg-primary/10 transition-[width] duration-300 ease-out",
|
|
1571
1864
|
style: { width: `${progressPercent}%` }
|
|
1572
1865
|
}
|
|
1573
1866
|
),
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
wf.isFavorite && /* @__PURE__ */
|
|
1578
|
-
|
|
1867
|
+
/* @__PURE__ */ jsxs8("div", { className: "relative flex items-start gap-2", children: [
|
|
1868
|
+
/* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
|
|
1869
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1", children: [
|
|
1870
|
+
wf.isFavorite && /* @__PURE__ */ jsx14(
|
|
1871
|
+
HugeiconsIcon7,
|
|
1579
1872
|
{
|
|
1580
1873
|
icon: StarIcon,
|
|
1581
1874
|
size: 12,
|
|
1582
1875
|
className: "shrink-0 fill-amber-400 text-amber-400"
|
|
1583
1876
|
}
|
|
1584
1877
|
),
|
|
1585
|
-
/* @__PURE__ */
|
|
1878
|
+
/* @__PURE__ */ jsx14("span", { className: "line-clamp-1 text-sm font-medium text-foreground", children: wf.name })
|
|
1586
1879
|
] }),
|
|
1587
|
-
wf.description && /* @__PURE__ */
|
|
1880
|
+
wf.description && /* @__PURE__ */ jsx14("p", { className: "line-clamp-2 mt-0.5 text-xs text-muted-foreground", children: wf.description })
|
|
1588
1881
|
] }),
|
|
1589
|
-
/* @__PURE__ */
|
|
1882
|
+
/* @__PURE__ */ jsx14(
|
|
1590
1883
|
Button,
|
|
1591
1884
|
{
|
|
1592
1885
|
variant: "ghost",
|
|
1593
1886
|
size: "icon",
|
|
1594
1887
|
"data-meridial-ui": true,
|
|
1595
1888
|
onClick: () => isPlaying ? onAbortGuide() : onPlayGuide(wf),
|
|
1596
|
-
children: /* @__PURE__ */
|
|
1597
|
-
|
|
1889
|
+
children: /* @__PURE__ */ jsx14(
|
|
1890
|
+
HugeiconsIcon7,
|
|
1598
1891
|
{
|
|
1599
1892
|
icon: isPlaying ? Cancel01Icon : PlayIcon,
|
|
1600
1893
|
size: 16,
|
|
@@ -1618,235 +1911,13 @@ function VoiceboxMenu({
|
|
|
1618
1911
|
}
|
|
1619
1912
|
|
|
1620
1913
|
// src/voicebox.tsx
|
|
1621
|
-
import { Fragment as
|
|
1914
|
+
import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1622
1915
|
var BADGE_POSITION_CLASSES = {
|
|
1623
1916
|
"bottom-right": "right-6 bottom-6",
|
|
1624
1917
|
"bottom-left": "left-6 bottom-6",
|
|
1625
1918
|
"top-right": "right-6 top-6",
|
|
1626
1919
|
"top-left": "left-6 top-6"
|
|
1627
1920
|
};
|
|
1628
|
-
function VoiceboxBadge({
|
|
1629
|
-
triggerIcon,
|
|
1630
|
-
onClick
|
|
1631
|
-
}) {
|
|
1632
|
-
return /* @__PURE__ */ jsx13(
|
|
1633
|
-
"button",
|
|
1634
|
-
{
|
|
1635
|
-
"data-meridial-ui": true,
|
|
1636
|
-
onClick,
|
|
1637
|
-
"aria-label": "Open assistant menu",
|
|
1638
|
-
className: "group size-10 flex cursor-pointer items-center justify-center rounded-full border border-border bg-background shadow-lg transition-transform duration-200 ease-out hover:scale-110",
|
|
1639
|
-
children: triggerIcon ?? /* @__PURE__ */ jsx13(MeridialLogo, { className: "size-6" })
|
|
1640
|
-
}
|
|
1641
|
-
);
|
|
1642
|
-
}
|
|
1643
|
-
function VoiceboxContent({
|
|
1644
|
-
baseUrl,
|
|
1645
|
-
publishableKey,
|
|
1646
|
-
attribute,
|
|
1647
|
-
tools,
|
|
1648
|
-
cursor,
|
|
1649
|
-
initialWorkflow,
|
|
1650
|
-
onDisconnect,
|
|
1651
|
-
onError
|
|
1652
|
-
}) {
|
|
1653
|
-
const [showTranscript, setShowTranscript] = useState9(false);
|
|
1654
|
-
const [showOutcomeBar, setShowOutcomeBar] = useState9(false);
|
|
1655
|
-
const [activeWorkflow, setActiveWorkflow] = useState9(initialWorkflow ?? null);
|
|
1656
|
-
const workflowsRef = useRef6([]);
|
|
1657
|
-
const room = useEnsureRoom3();
|
|
1658
|
-
const autoStarted = useRef6(false);
|
|
1659
|
-
const outcomeShown = useRef6(false);
|
|
1660
|
-
const draggableRef = useRef6(null);
|
|
1661
|
-
const triggerOutcomeBar = useCallback5(() => {
|
|
1662
|
-
if (!outcomeShown.current) {
|
|
1663
|
-
outcomeShown.current = true;
|
|
1664
|
-
setShowOutcomeBar(true);
|
|
1665
|
-
}
|
|
1666
|
-
}, []);
|
|
1667
|
-
const handleOutcomeSubmit = useCallback5(
|
|
1668
|
-
async (outcome) => {
|
|
1669
|
-
setShowOutcomeBar(false);
|
|
1670
|
-
try {
|
|
1671
|
-
const sessionId = await room.getSid();
|
|
1672
|
-
await fetch(`${baseUrl}/api/outcome`, {
|
|
1673
|
-
method: "POST",
|
|
1674
|
-
headers: { "Content-Type": "application/json" },
|
|
1675
|
-
body: JSON.stringify({ publishableKey, sessionId, outcome })
|
|
1676
|
-
});
|
|
1677
|
-
} catch {
|
|
1678
|
-
}
|
|
1679
|
-
},
|
|
1680
|
-
[room, baseUrl, publishableKey]
|
|
1681
|
-
);
|
|
1682
|
-
useToolRegistration(tools, triggerOutcomeBar);
|
|
1683
|
-
useDraggable(draggableRef);
|
|
1684
|
-
useEffect6(() => {
|
|
1685
|
-
if (!publishableKey) return;
|
|
1686
|
-
fetch(`${baseUrl}/api/workflows`, {
|
|
1687
|
-
headers: { Authorization: `Bearer ${publishableKey}` }
|
|
1688
|
-
}).then((r) => r.json()).then((data) => {
|
|
1689
|
-
if (data.workflows) workflowsRef.current = data.workflows;
|
|
1690
|
-
}).catch((error2) => {
|
|
1691
|
-
onError?.(
|
|
1692
|
-
error2 instanceof Error ? error2.message : "Workflows fetch failed"
|
|
1693
|
-
);
|
|
1694
|
-
});
|
|
1695
|
-
}, [baseUrl, publishableKey]);
|
|
1696
|
-
useEffect6(() => {
|
|
1697
|
-
room.registerRpcMethod("workflow:execute", async (rpcData) => {
|
|
1698
|
-
try {
|
|
1699
|
-
const { slug } = JSON.parse(rpcData.payload);
|
|
1700
|
-
const apiWf = workflowsRef.current.find((w) => w.slug === slug);
|
|
1701
|
-
if (!apiWf) throw new Error(`Workflow '${slug}' not found`);
|
|
1702
|
-
const workflow = {
|
|
1703
|
-
id: apiWf.id,
|
|
1704
|
-
name: apiWf.name,
|
|
1705
|
-
steps: apiWf.steps,
|
|
1706
|
-
configured: true,
|
|
1707
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1708
|
-
};
|
|
1709
|
-
setActiveWorkflow({ id: apiWf.id, workflow });
|
|
1710
|
-
triggerOutcomeBar();
|
|
1711
|
-
return JSON.stringify({ success: true });
|
|
1712
|
-
} catch (error2) {
|
|
1713
|
-
onError?.(
|
|
1714
|
-
error2 instanceof Error ? error2.message : "Workflow execution failed"
|
|
1715
|
-
);
|
|
1716
|
-
throw new RpcError2(
|
|
1717
|
-
1,
|
|
1718
|
-
error2 instanceof Error ? error2.message : "Workflow execution failed"
|
|
1719
|
-
);
|
|
1720
|
-
}
|
|
1721
|
-
});
|
|
1722
|
-
return () => {
|
|
1723
|
-
room.unregisterRpcMethod("workflow:execute");
|
|
1724
|
-
};
|
|
1725
|
-
}, [room]);
|
|
1726
|
-
const { state } = useAgent();
|
|
1727
|
-
const { start } = useSessionContext3();
|
|
1728
|
-
useEffect6(() => {
|
|
1729
|
-
if (!autoStarted.current) {
|
|
1730
|
-
autoStarted.current = true;
|
|
1731
|
-
start();
|
|
1732
|
-
}
|
|
1733
|
-
}, [start]);
|
|
1734
|
-
const isConnecting = state === "connecting" || state === "initializing" || state === "pre-connect-buffering";
|
|
1735
|
-
const isDisconnected = state === "disconnected" || state === "failed";
|
|
1736
|
-
const { microphoneTrack, microphoneToggle } = useInputControls();
|
|
1737
|
-
const handleDisconnect = () => {
|
|
1738
|
-
onDisconnect();
|
|
1739
|
-
};
|
|
1740
|
-
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
1741
|
-
activeWorkflow && /* @__PURE__ */ jsx13(
|
|
1742
|
-
WorkflowExecution,
|
|
1743
|
-
{
|
|
1744
|
-
workflow: activeWorkflow.workflow,
|
|
1745
|
-
attribute,
|
|
1746
|
-
cursor,
|
|
1747
|
-
onClose: () => {
|
|
1748
|
-
setActiveWorkflow(null);
|
|
1749
|
-
triggerOutcomeBar();
|
|
1750
|
-
},
|
|
1751
|
-
onError
|
|
1752
|
-
}
|
|
1753
|
-
),
|
|
1754
|
-
/* @__PURE__ */ jsx13(
|
|
1755
|
-
motion3.div,
|
|
1756
|
-
{
|
|
1757
|
-
initial: { opacity: 0, y: 20 },
|
|
1758
|
-
animate: { opacity: 1, y: 0 },
|
|
1759
|
-
transition: { duration: 0.3, ease: "easeOut" },
|
|
1760
|
-
className: "fixed inset-x-0 bottom-8 z-50 flex justify-center",
|
|
1761
|
-
children: /* @__PURE__ */ jsxs8(
|
|
1762
|
-
"div",
|
|
1763
|
-
{
|
|
1764
|
-
ref: draggableRef,
|
|
1765
|
-
"data-meridial-ui": true,
|
|
1766
|
-
className: "w-96 items-stretch rounded border border-border bg-card shadow-md",
|
|
1767
|
-
children: [
|
|
1768
|
-
/* @__PURE__ */ jsx13(AnimatePresence3, { initial: false, children: showTranscript && /* @__PURE__ */ jsx13(
|
|
1769
|
-
motion3.div,
|
|
1770
|
-
{
|
|
1771
|
-
initial: { height: 0, opacity: 0 },
|
|
1772
|
-
animate: { height: "auto", opacity: 1 },
|
|
1773
|
-
exit: { height: 0, opacity: 0 },
|
|
1774
|
-
transition: { duration: 0.24, ease: "easeOut" },
|
|
1775
|
-
style: { overflow: "hidden" },
|
|
1776
|
-
children: /* @__PURE__ */ jsx13(AgentTranscriptPanel, {})
|
|
1777
|
-
}
|
|
1778
|
-
) }),
|
|
1779
|
-
/* @__PURE__ */ jsx13(AnimatePresence3, { initial: false, children: showOutcomeBar && /* @__PURE__ */ jsx13(
|
|
1780
|
-
motion3.div,
|
|
1781
|
-
{
|
|
1782
|
-
initial: { height: 0, opacity: 0 },
|
|
1783
|
-
animate: { height: "auto", opacity: 1 },
|
|
1784
|
-
exit: { height: 0, opacity: 0 },
|
|
1785
|
-
transition: { duration: 0.24, ease: "easeOut" },
|
|
1786
|
-
style: { overflow: "hidden" },
|
|
1787
|
-
children: /* @__PURE__ */ jsx13(OutcomeBar, { onSubmit: handleOutcomeSubmit })
|
|
1788
|
-
}
|
|
1789
|
-
) }),
|
|
1790
|
-
/* @__PURE__ */ jsxs8("div", { "data-meridial-ui": true, className: "flex h-12 items-center", children: [
|
|
1791
|
-
/* @__PURE__ */ jsx13(DragHandle, { className: "px-2" }),
|
|
1792
|
-
/* @__PURE__ */ jsx13(Separator, { orientation: "vertical", className: "h-full" }),
|
|
1793
|
-
/* @__PURE__ */ jsxs8("div", { className: "relative flex h-full flex-1 items-center justify-between px-2", children: [
|
|
1794
|
-
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
1795
|
-
/* @__PURE__ */ jsx13(
|
|
1796
|
-
AgentTrackControl,
|
|
1797
|
-
{
|
|
1798
|
-
source: "microphone",
|
|
1799
|
-
pressed: microphoneToggle.enabled,
|
|
1800
|
-
pending: microphoneToggle.pending,
|
|
1801
|
-
disabled: microphoneToggle.pending,
|
|
1802
|
-
audioTrack: microphoneTrack,
|
|
1803
|
-
onPressedChange: microphoneToggle.toggle
|
|
1804
|
-
}
|
|
1805
|
-
),
|
|
1806
|
-
/* @__PURE__ */ jsx13(
|
|
1807
|
-
Toggle3,
|
|
1808
|
-
{
|
|
1809
|
-
disabled: isDisconnected || isConnecting,
|
|
1810
|
-
pressed: showTranscript,
|
|
1811
|
-
"aria-label": "Toggle transcript",
|
|
1812
|
-
onPressedChange: setShowTranscript,
|
|
1813
|
-
className: cn(
|
|
1814
|
-
"size-9 rounded-lg",
|
|
1815
|
-
showTranscript ? "bg-muted text-foreground" : "bg-transparent text-muted-foreground hover:text-foreground"
|
|
1816
|
-
),
|
|
1817
|
-
children: /* @__PURE__ */ jsx13(HugeiconsIcon7, { icon: ChatFeedback01Icon })
|
|
1818
|
-
}
|
|
1819
|
-
),
|
|
1820
|
-
/* @__PURE__ */ jsx13(
|
|
1821
|
-
AgentAudioVisualizerBar,
|
|
1822
|
-
{
|
|
1823
|
-
barCount: 12,
|
|
1824
|
-
state,
|
|
1825
|
-
audioTrack: microphoneTrack,
|
|
1826
|
-
className: "mx-4"
|
|
1827
|
-
}
|
|
1828
|
-
)
|
|
1829
|
-
] }),
|
|
1830
|
-
isConnecting ? /* @__PURE__ */ jsxs8(Button, { variant: "outline", children: [
|
|
1831
|
-
/* @__PURE__ */ jsx13("span", { children: "Connecting" }),
|
|
1832
|
-
/* @__PURE__ */ jsx13(
|
|
1833
|
-
HugeiconsIcon7,
|
|
1834
|
-
{
|
|
1835
|
-
icon: Loading03Icon3,
|
|
1836
|
-
className: "animate-spin"
|
|
1837
|
-
}
|
|
1838
|
-
)
|
|
1839
|
-
] }) : /* @__PURE__ */ jsx13(AgentDisconnectButton, { onClick: handleDisconnect }),
|
|
1840
|
-
/* @__PURE__ */ jsx13(StartAudioButton, { label: "Start Audio" })
|
|
1841
|
-
] })
|
|
1842
|
-
] })
|
|
1843
|
-
]
|
|
1844
|
-
}
|
|
1845
|
-
)
|
|
1846
|
-
}
|
|
1847
|
-
)
|
|
1848
|
-
] });
|
|
1849
|
-
}
|
|
1850
1921
|
function Voicebox({
|
|
1851
1922
|
baseUrl = "",
|
|
1852
1923
|
publishableKey,
|
|
@@ -1860,25 +1931,25 @@ function Voicebox({
|
|
|
1860
1931
|
metadata,
|
|
1861
1932
|
onError
|
|
1862
1933
|
}) {
|
|
1863
|
-
const [view, setView] =
|
|
1864
|
-
const [hidden, setHidden] =
|
|
1865
|
-
const [badgePosition, setBadgePosition] =
|
|
1934
|
+
const [view, setView] = useState10("badge");
|
|
1935
|
+
const [hidden, setHidden] = useState10(false);
|
|
1936
|
+
const [badgePosition, setBadgePosition] = useState10(() => {
|
|
1866
1937
|
if (typeof window === "undefined") return "bottom-right";
|
|
1867
1938
|
return localStorage.getItem(STORAGE_KEYS.triggerPos) || "bottom-right";
|
|
1868
1939
|
});
|
|
1869
|
-
const [allWorkflows, setAllWorkflows] =
|
|
1870
|
-
const [initialWorkflow, setInitialWorkflow] =
|
|
1871
|
-
const [guideWorkflow, setGuideWorkflow] =
|
|
1872
|
-
const [playingWorkflowId, setPlayingWorkflowId] =
|
|
1940
|
+
const [allWorkflows, setAllWorkflows] = useState10([]);
|
|
1941
|
+
const [initialWorkflow, setInitialWorkflow] = useState10(null);
|
|
1942
|
+
const [guideWorkflow, setGuideWorkflow] = useState10(null);
|
|
1943
|
+
const [playingWorkflowId, setPlayingWorkflowId] = useState10(
|
|
1873
1944
|
null
|
|
1874
1945
|
);
|
|
1875
|
-
const [playingStepIndex, setPlayingStepIndex] =
|
|
1876
|
-
|
|
1946
|
+
const [playingStepIndex, setPlayingStepIndex] = useState10(0);
|
|
1947
|
+
useEffect7(() => {
|
|
1877
1948
|
if (sessionStorage.getItem(STORAGE_KEYS.hidden) === "true") {
|
|
1878
1949
|
setHidden(true);
|
|
1879
1950
|
}
|
|
1880
1951
|
}, []);
|
|
1881
|
-
|
|
1952
|
+
useEffect7(() => {
|
|
1882
1953
|
if (!publishableKey) return;
|
|
1883
1954
|
fetch(`${baseUrl}/api/workflows`, {
|
|
1884
1955
|
headers: { Authorization: `Bearer ${publishableKey}` }
|
|
@@ -1890,42 +1961,6 @@ function Voicebox({
|
|
|
1890
1961
|
}).catch(() => {
|
|
1891
1962
|
});
|
|
1892
1963
|
}, [baseUrl, publishableKey]);
|
|
1893
|
-
const serializedTools = useMemo5(
|
|
1894
|
-
() => tools && tools.length > 0 ? serializeTools(tools) : [],
|
|
1895
|
-
[tools]
|
|
1896
|
-
);
|
|
1897
|
-
const tokenSource = useMemo5(
|
|
1898
|
-
() => TokenSource.custom(async () => {
|
|
1899
|
-
const response = await fetch(`${baseUrl}/api/auth/livekit`, {
|
|
1900
|
-
method: "POST",
|
|
1901
|
-
body: JSON.stringify({
|
|
1902
|
-
publishableKey,
|
|
1903
|
-
identifier,
|
|
1904
|
-
firstMessage,
|
|
1905
|
-
instructions,
|
|
1906
|
-
tools: serializedTools,
|
|
1907
|
-
metadata
|
|
1908
|
-
})
|
|
1909
|
-
});
|
|
1910
|
-
if (!response.ok) {
|
|
1911
|
-
const body = await response.json().catch(() => ({}));
|
|
1912
|
-
onError?.(body.error ?? `Token request failed (${response.status})`);
|
|
1913
|
-
return null;
|
|
1914
|
-
}
|
|
1915
|
-
return response.json();
|
|
1916
|
-
}),
|
|
1917
|
-
[
|
|
1918
|
-
baseUrl,
|
|
1919
|
-
publishableKey,
|
|
1920
|
-
identifier,
|
|
1921
|
-
firstMessage,
|
|
1922
|
-
instructions,
|
|
1923
|
-
serializedTools,
|
|
1924
|
-
metadata,
|
|
1925
|
-
onError
|
|
1926
|
-
]
|
|
1927
|
-
);
|
|
1928
|
-
const session = useSession(tokenSource);
|
|
1929
1964
|
const handleDisconnect = () => {
|
|
1930
1965
|
setView("badge");
|
|
1931
1966
|
setInitialWorkflow(null);
|
|
@@ -1963,8 +1998,8 @@ function Voicebox({
|
|
|
1963
1998
|
setView((prev) => prev === "menu" ? "badge" : "menu");
|
|
1964
1999
|
};
|
|
1965
2000
|
if (hidden) return null;
|
|
1966
|
-
return /* @__PURE__ */
|
|
1967
|
-
guideWorkflow && /* @__PURE__ */
|
|
2001
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2002
|
+
guideWorkflow && /* @__PURE__ */ jsx15(
|
|
1968
2003
|
WorkflowExecution,
|
|
1969
2004
|
{
|
|
1970
2005
|
workflow: guideWorkflow,
|
|
@@ -1979,24 +2014,28 @@ function Voicebox({
|
|
|
1979
2014
|
onError
|
|
1980
2015
|
}
|
|
1981
2016
|
),
|
|
1982
|
-
view === "call" ? /* @__PURE__ */
|
|
2017
|
+
view === "call" ? /* @__PURE__ */ jsx15(
|
|
1983
2018
|
VoiceboxContent,
|
|
1984
2019
|
{
|
|
1985
2020
|
baseUrl,
|
|
1986
2021
|
publishableKey,
|
|
2022
|
+
identifier,
|
|
2023
|
+
firstMessage,
|
|
2024
|
+
instructions,
|
|
1987
2025
|
attribute,
|
|
1988
2026
|
tools,
|
|
1989
2027
|
cursor,
|
|
2028
|
+
metadata,
|
|
1990
2029
|
initialWorkflow,
|
|
1991
2030
|
onDisconnect: handleDisconnect,
|
|
1992
2031
|
onError
|
|
1993
2032
|
}
|
|
1994
|
-
) : /* @__PURE__ */
|
|
2033
|
+
) : /* @__PURE__ */ jsxs9(
|
|
1995
2034
|
"div",
|
|
1996
2035
|
{
|
|
1997
2036
|
className: cn("fixed z-50", BADGE_POSITION_CLASSES[badgePosition]),
|
|
1998
2037
|
children: [
|
|
1999
|
-
/* @__PURE__ */
|
|
2038
|
+
/* @__PURE__ */ jsx15(AnimatePresence4, { children: view === "menu" && /* @__PURE__ */ jsx15(
|
|
2000
2039
|
VoiceboxMenu,
|
|
2001
2040
|
{
|
|
2002
2041
|
workflows: allWorkflows,
|
|
@@ -2010,7 +2049,7 @@ function Voicebox({
|
|
|
2010
2049
|
onAbortGuide: handleAbortGuide
|
|
2011
2050
|
}
|
|
2012
2051
|
) }),
|
|
2013
|
-
/* @__PURE__ */
|
|
2052
|
+
/* @__PURE__ */ jsx15(VoiceboxBadge, { triggerIcon, onClick: handleBadgeClick })
|
|
2014
2053
|
]
|
|
2015
2054
|
}
|
|
2016
2055
|
)
|
|
@@ -2020,4 +2059,4 @@ function Voicebox({
|
|
|
2020
2059
|
export {
|
|
2021
2060
|
Voicebox
|
|
2022
2061
|
};
|
|
2023
|
-
//# sourceMappingURL=chunk-
|
|
2062
|
+
//# sourceMappingURL=chunk-N4DZEH4G.js.map
|