@unctad-ai/voice-agent-ui 1.0.0 → 1.0.1
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/VoiceSettingsView-LVFUTFOG.js +17 -0
- package/dist/chunk-BFDEQ5XG.js +1238 -0
- package/dist/chunk-BFDEQ5XG.js.map +1 -0
- package/dist/index.d.ts +50 -2
- package/dist/index.js +185 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/VoiceSettingsView-J4OIRJ23.js +0 -7
- package/dist/chunk-IYKRYBBO.js +0 -629
- package/dist/chunk-IYKRYBBO.js.map +0 -1
- /package/dist/{VoiceSettingsView-J4OIRJ23.js.map → VoiceSettingsView-LVFUTFOG.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Divider,
|
|
3
|
+
PersonaSettings,
|
|
4
|
+
SelectSetting,
|
|
5
|
+
SettingsSection,
|
|
6
|
+
SliderSetting,
|
|
7
|
+
ToggleSetting,
|
|
2
8
|
VoiceSettingsProvider,
|
|
3
9
|
VoiceSettingsView,
|
|
4
10
|
useVoiceSettings
|
|
5
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BFDEQ5XG.js";
|
|
6
12
|
|
|
7
13
|
// src/VoiceAgentProvider.tsx
|
|
8
14
|
import { SiteConfigProvider } from "@unctad-ai/voice-agent-core";
|
|
@@ -27,7 +33,7 @@ import {
|
|
|
27
33
|
} from "react";
|
|
28
34
|
import { createPortal } from "react-dom";
|
|
29
35
|
import { motion as motion5, AnimatePresence as AnimatePresence5 } from "motion/react";
|
|
30
|
-
import { ChevronDown as ChevronDown2, X, Mic as
|
|
36
|
+
import { ChevronDown as ChevronDown2, X, Mic as Mic3, ArrowUp, Keyboard as Keyboard2, RotateCw, Settings, VolumeX as VolumeX2 } from "lucide-react";
|
|
31
37
|
import {
|
|
32
38
|
useVoiceAgent,
|
|
33
39
|
voiceStateToOrbState,
|
|
@@ -657,7 +663,7 @@ import {
|
|
|
657
663
|
DEFAULT_FONT_FAMILY,
|
|
658
664
|
useSiteConfig as useSiteConfig3
|
|
659
665
|
} from "@unctad-ai/voice-agent-core";
|
|
660
|
-
import { ArrowRight, PenLine, MousePointerClick, Search, Info, ChevronDown } from "lucide-react";
|
|
666
|
+
import { ArrowRight, PenLine, MousePointerClick, Search, Info, ChevronDown, Mic, Keyboard } from "lucide-react";
|
|
661
667
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
662
668
|
function cleanForDisplay(text) {
|
|
663
669
|
return text.replace(/\[(laugh|chuckle|sigh|gasp|cough|clear throat|sniff|groan|shush)\]/gi, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/^\s*\*\s+/gm, "- ").replace(/\*(.*?)\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/<br\s*\/?>/gi, "\n").replace(/<[^>]+>/g, "").replace(/\|[-:\s|]+\|/g, "").replace(/\|/g, "\n").replace(/\p{Emoji_Presentation}|\p{Extended_Pictographic}/gu, "").replace(/[ \t]{3,}/g, " ").replace(/\n{3,}/g, "\n\n").replace(/^[\s-]{3,}$/gm, "").trim();
|
|
@@ -830,10 +836,14 @@ function VoiceTranscript({
|
|
|
830
836
|
messages,
|
|
831
837
|
isTyping,
|
|
832
838
|
variant = "overlay",
|
|
833
|
-
voiceError
|
|
839
|
+
voiceError,
|
|
840
|
+
voiceState,
|
|
841
|
+
onStartMic,
|
|
842
|
+
onSwitchToKeyboard
|
|
834
843
|
}) {
|
|
835
844
|
const config = useSiteConfig3();
|
|
836
845
|
const fontFamily = config.fontFamily ?? DEFAULT_FONT_FAMILY;
|
|
846
|
+
const assistantLabel = config.copilotName || "Assistant";
|
|
837
847
|
const containerRef = useRef3(null);
|
|
838
848
|
const isPanel = variant === "panel";
|
|
839
849
|
const maxVisible = isPanel ? PANEL_MAX_VISIBLE_MESSAGES : MAX_VISIBLE_MESSAGES;
|
|
@@ -891,18 +901,21 @@ function VoiceTranscript({
|
|
|
891
901
|
}
|
|
892
902
|
};
|
|
893
903
|
if (isPanel) {
|
|
894
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
904
|
+
return /* @__PURE__ */ jsxs3("div", { style: { flex: 1, minHeight: 0, position: "relative", fontFamily }, children: [
|
|
895
905
|
/* @__PURE__ */ jsx4(
|
|
896
906
|
"div",
|
|
897
907
|
{
|
|
898
908
|
ref: containerRef,
|
|
899
|
-
className: "absolute inset-0 overflow-y-auto overscroll-contain",
|
|
900
909
|
style: {
|
|
910
|
+
position: "absolute",
|
|
911
|
+
inset: 0,
|
|
912
|
+
overflowY: "auto",
|
|
913
|
+
overscrollBehavior: "contain",
|
|
901
914
|
padding: "16px 16px 12px",
|
|
902
915
|
maskImage: "linear-gradient(to bottom, transparent 0%, black 8px, black calc(100% - 8px), transparent 100%)",
|
|
903
916
|
WebkitMaskImage: "linear-gradient(to bottom, transparent 0%, black 8px, black calc(100% - 8px), transparent 100%)"
|
|
904
917
|
},
|
|
905
|
-
children: /* @__PURE__ */ jsxs3("div", { ref: contentRef,
|
|
918
|
+
children: /* @__PURE__ */ jsxs3("div", { ref: contentRef, style: { display: "flex", flexDirection: "column", paddingBottom: 24 }, children: [
|
|
906
919
|
/* @__PURE__ */ jsx4(AnimatePresence, { mode: "popLayout", children: groupDisplayItems(visible).map((item, idx, arr) => {
|
|
907
920
|
if (item.type === "action") {
|
|
908
921
|
const prevIsAction = idx > 0 && arr[idx - 1].type === "action";
|
|
@@ -932,7 +945,7 @@ function VoiceTranscript({
|
|
|
932
945
|
color: "rgba(0,0,0,0.35)",
|
|
933
946
|
marginBottom: "4px"
|
|
934
947
|
},
|
|
935
|
-
children:
|
|
948
|
+
children: assistantLabel
|
|
936
949
|
}
|
|
937
950
|
),
|
|
938
951
|
/* @__PURE__ */ jsx4(ActionBadge, { msg: item.msg, count: item.count })
|
|
@@ -971,7 +984,7 @@ function VoiceTranscript({
|
|
|
971
984
|
color: isAI ? "rgba(0,0,0,0.35)" : "rgba(219,33,41,0.5)",
|
|
972
985
|
marginBottom: "4px"
|
|
973
986
|
},
|
|
974
|
-
children: isAI ?
|
|
987
|
+
children: isAI ? assistantLabel : "You"
|
|
975
988
|
}
|
|
976
989
|
),
|
|
977
990
|
/* @__PURE__ */ jsx4(
|
|
@@ -1086,17 +1099,7 @@ function VoiceTranscript({
|
|
|
1086
1099
|
)
|
|
1087
1100
|
]
|
|
1088
1101
|
}
|
|
1089
|
-
) : /* @__PURE__ */ jsx4(
|
|
1090
|
-
motion.p,
|
|
1091
|
-
{
|
|
1092
|
-
initial: { opacity: 0, y: 4 },
|
|
1093
|
-
animate: { opacity: 1, y: 0 },
|
|
1094
|
-
transition: { duration: 0.4, delay: 0.2 },
|
|
1095
|
-
className: "text-center italic",
|
|
1096
|
-
style: { fontSize: "14px", color: "rgba(0,0,0,0.4)", paddingTop: "60px" },
|
|
1097
|
-
children: "Ask me anything"
|
|
1098
|
-
}
|
|
1099
|
-
)),
|
|
1102
|
+
) : /* @__PURE__ */ jsx4("div", { style: { paddingTop: 40 }, children: /* @__PURE__ */ jsx4(EmptyStateGraphic, { primaryColor: config.colors.primary }) })),
|
|
1100
1103
|
isTyping && visible.length === 0 && /* @__PURE__ */ jsx4(
|
|
1101
1104
|
motion.p,
|
|
1102
1105
|
{
|
|
@@ -1213,14 +1216,12 @@ function VoiceTranscript({
|
|
|
1213
1216
|
);
|
|
1214
1217
|
}) }),
|
|
1215
1218
|
visible.length === 0 && !isTyping && /* @__PURE__ */ jsx4(
|
|
1216
|
-
|
|
1219
|
+
EmptyStateGraphic,
|
|
1217
1220
|
{
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
style: { color: "rgba(0,0,0,0.5)" },
|
|
1223
|
-
children: "Ask me anything"
|
|
1221
|
+
primaryColor: config.colors.primary,
|
|
1222
|
+
voiceState,
|
|
1223
|
+
onStartMic,
|
|
1224
|
+
onSwitchToKeyboard
|
|
1224
1225
|
}
|
|
1225
1226
|
),
|
|
1226
1227
|
isTyping && visible.length === 0 && /* @__PURE__ */ jsx4(
|
|
@@ -1237,6 +1238,114 @@ function VoiceTranscript({
|
|
|
1237
1238
|
}
|
|
1238
1239
|
);
|
|
1239
1240
|
}
|
|
1241
|
+
function EmptyStateGraphic({ primaryColor, voiceState, onStartMic, onSwitchToKeyboard }) {
|
|
1242
|
+
const isListening = voiceState === "LISTENING" || voiceState === "USER_SPEAKING";
|
|
1243
|
+
if (isListening) {
|
|
1244
|
+
return /* @__PURE__ */ jsxs3(
|
|
1245
|
+
motion.div,
|
|
1246
|
+
{
|
|
1247
|
+
initial: { opacity: 0 },
|
|
1248
|
+
animate: { opacity: 1 },
|
|
1249
|
+
transition: { duration: 0.3 },
|
|
1250
|
+
style: {
|
|
1251
|
+
display: "flex",
|
|
1252
|
+
flexDirection: "column",
|
|
1253
|
+
alignItems: "center",
|
|
1254
|
+
justifyContent: "center",
|
|
1255
|
+
gap: 6,
|
|
1256
|
+
paddingTop: 60
|
|
1257
|
+
},
|
|
1258
|
+
children: [
|
|
1259
|
+
/* @__PURE__ */ jsx4("p", { style: { fontSize: 16, fontWeight: 500, color: primaryColor, margin: 0, opacity: 0.7 }, children: "Listening..." }),
|
|
1260
|
+
/* @__PURE__ */ jsx4("p", { style: { fontSize: 12, color: "rgba(0,0,0,0.3)", margin: 0 }, children: "Go ahead, I can hear you" })
|
|
1261
|
+
]
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
return /* @__PURE__ */ jsxs3(
|
|
1266
|
+
motion.div,
|
|
1267
|
+
{
|
|
1268
|
+
initial: { opacity: 0, y: 6 },
|
|
1269
|
+
animate: { opacity: 1, y: 0 },
|
|
1270
|
+
transition: { duration: 0.5, delay: 0.15 },
|
|
1271
|
+
style: {
|
|
1272
|
+
display: "flex",
|
|
1273
|
+
flexDirection: "column",
|
|
1274
|
+
alignItems: "center",
|
|
1275
|
+
justifyContent: "center",
|
|
1276
|
+
gap: 16,
|
|
1277
|
+
paddingTop: 60
|
|
1278
|
+
},
|
|
1279
|
+
children: [
|
|
1280
|
+
/* @__PURE__ */ jsx4("p", { style: { fontSize: 18, fontWeight: 500, color: primaryColor, margin: 0, opacity: 0.6 }, children: "How can I help?" }),
|
|
1281
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1282
|
+
onStartMic && /* @__PURE__ */ jsxs3(
|
|
1283
|
+
"button",
|
|
1284
|
+
{
|
|
1285
|
+
onClick: onStartMic,
|
|
1286
|
+
style: {
|
|
1287
|
+
display: "flex",
|
|
1288
|
+
alignItems: "center",
|
|
1289
|
+
gap: 8,
|
|
1290
|
+
padding: "8px 16px",
|
|
1291
|
+
borderRadius: 20,
|
|
1292
|
+
border: `1px solid ${primaryColor}22`,
|
|
1293
|
+
backgroundColor: `${primaryColor}08`,
|
|
1294
|
+
cursor: "pointer",
|
|
1295
|
+
fontFamily: "inherit",
|
|
1296
|
+
fontSize: 13,
|
|
1297
|
+
color: "rgba(0,0,0,0.5)",
|
|
1298
|
+
transition: "background-color 0.15s, border-color 0.15s"
|
|
1299
|
+
},
|
|
1300
|
+
onMouseEnter: (e) => {
|
|
1301
|
+
e.currentTarget.style.backgroundColor = `${primaryColor}14`;
|
|
1302
|
+
e.currentTarget.style.borderColor = `${primaryColor}33`;
|
|
1303
|
+
},
|
|
1304
|
+
onMouseLeave: (e) => {
|
|
1305
|
+
e.currentTarget.style.backgroundColor = `${primaryColor}08`;
|
|
1306
|
+
e.currentTarget.style.borderColor = `${primaryColor}22`;
|
|
1307
|
+
},
|
|
1308
|
+
children: [
|
|
1309
|
+
/* @__PURE__ */ jsx4(Mic, { style: { width: 14, height: 14, color: primaryColor, opacity: 0.7 } }),
|
|
1310
|
+
"Start talking"
|
|
1311
|
+
]
|
|
1312
|
+
}
|
|
1313
|
+
),
|
|
1314
|
+
onSwitchToKeyboard && /* @__PURE__ */ jsxs3(
|
|
1315
|
+
"button",
|
|
1316
|
+
{
|
|
1317
|
+
onClick: onSwitchToKeyboard,
|
|
1318
|
+
style: {
|
|
1319
|
+
display: "flex",
|
|
1320
|
+
alignItems: "center",
|
|
1321
|
+
gap: 8,
|
|
1322
|
+
padding: "8px 16px",
|
|
1323
|
+
borderRadius: 20,
|
|
1324
|
+
border: "1px solid rgba(0,0,0,0.06)",
|
|
1325
|
+
backgroundColor: "transparent",
|
|
1326
|
+
cursor: "pointer",
|
|
1327
|
+
fontFamily: "inherit",
|
|
1328
|
+
fontSize: 13,
|
|
1329
|
+
color: "rgba(0,0,0,0.35)",
|
|
1330
|
+
transition: "background-color 0.15s"
|
|
1331
|
+
},
|
|
1332
|
+
onMouseEnter: (e) => {
|
|
1333
|
+
e.currentTarget.style.backgroundColor = "rgba(0,0,0,0.03)";
|
|
1334
|
+
},
|
|
1335
|
+
onMouseLeave: (e) => {
|
|
1336
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
1337
|
+
},
|
|
1338
|
+
children: [
|
|
1339
|
+
/* @__PURE__ */ jsx4(Keyboard, { style: { width: 14, height: 14, opacity: 0.5 } }),
|
|
1340
|
+
"Type a message"
|
|
1341
|
+
]
|
|
1342
|
+
}
|
|
1343
|
+
)
|
|
1344
|
+
] })
|
|
1345
|
+
]
|
|
1346
|
+
}
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1240
1349
|
|
|
1241
1350
|
// src/components/VoiceToolCard.tsx
|
|
1242
1351
|
import { useEffect as useEffect4 } from "react";
|
|
@@ -1355,7 +1464,7 @@ var VoiceErrorBoundary = class extends Component {
|
|
|
1355
1464
|
|
|
1356
1465
|
// src/components/VoiceErrorDisplay.tsx
|
|
1357
1466
|
import { motion as motion3, AnimatePresence as AnimatePresence3 } from "motion/react";
|
|
1358
|
-
import { AlertTriangle as AlertTriangle2, Hourglass, Mic, MicOff, VolumeX, Wifi, WifiOff } from "lucide-react";
|
|
1467
|
+
import { AlertTriangle as AlertTriangle2, Hourglass, Mic as Mic2, MicOff, VolumeX, Wifi, WifiOff } from "lucide-react";
|
|
1359
1468
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1360
1469
|
var SEVERITY_STYLES = {
|
|
1361
1470
|
error: {
|
|
@@ -1397,7 +1506,7 @@ var ERROR_CONFIG = {
|
|
|
1397
1506
|
severity: "warning"
|
|
1398
1507
|
},
|
|
1399
1508
|
stt_failed: {
|
|
1400
|
-
icon:
|
|
1509
|
+
icon: Mic2,
|
|
1401
1510
|
title: "Didn't catch that",
|
|
1402
1511
|
severity: "info"
|
|
1403
1512
|
},
|
|
@@ -1417,7 +1526,7 @@ var ERROR_CONFIG = {
|
|
|
1417
1526
|
severity: "error"
|
|
1418
1527
|
},
|
|
1419
1528
|
speech_too_short: {
|
|
1420
|
-
icon:
|
|
1529
|
+
icon: Mic2,
|
|
1421
1530
|
title: "Didn't catch that",
|
|
1422
1531
|
severity: "info"
|
|
1423
1532
|
},
|
|
@@ -1556,7 +1665,7 @@ function PipelineMetricsBar({
|
|
|
1556
1665
|
|
|
1557
1666
|
// src/components/GlassCopilotPanel.tsx
|
|
1558
1667
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1559
|
-
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-
|
|
1668
|
+
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-LVFUTFOG.js"));
|
|
1560
1669
|
var STATE_LABELS = {
|
|
1561
1670
|
IDLE: "Tap mic to speak",
|
|
1562
1671
|
LISTENING: "Listening...",
|
|
@@ -1759,7 +1868,7 @@ function CollapsedBar({
|
|
|
1759
1868
|
style: { backgroundColor: `${colors.primary}40` }
|
|
1760
1869
|
}
|
|
1761
1870
|
),
|
|
1762
|
-
/* @__PURE__ */ jsx9(
|
|
1871
|
+
/* @__PURE__ */ jsx9(Mic3, { style: { width: 16, height: 16, position: "relative", zIndex: 1 } })
|
|
1763
1872
|
]
|
|
1764
1873
|
}
|
|
1765
1874
|
),
|
|
@@ -1807,12 +1916,16 @@ function ComposerBar({
|
|
|
1807
1916
|
micPaused = false,
|
|
1808
1917
|
onTextSubmit,
|
|
1809
1918
|
onMicToggle,
|
|
1810
|
-
disabled = false
|
|
1919
|
+
disabled = false,
|
|
1920
|
+
switchToTextRef
|
|
1811
1921
|
}) {
|
|
1812
1922
|
const { colors } = useSiteConfig4();
|
|
1813
1923
|
const [mode, setMode] = useState5("voice");
|
|
1814
1924
|
const [text, setText] = useState5("");
|
|
1815
1925
|
const inputRef = useRef4(null);
|
|
1926
|
+
useEffect6(() => {
|
|
1927
|
+
if (switchToTextRef) switchToTextRef.current = () => setMode("text");
|
|
1928
|
+
}, [switchToTextRef]);
|
|
1816
1929
|
useEffect6(() => {
|
|
1817
1930
|
if (mode === "text") {
|
|
1818
1931
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
@@ -1852,7 +1965,7 @@ function ComposerBar({
|
|
|
1852
1965
|
color: "rgba(0,0,0,0.2)",
|
|
1853
1966
|
opacity: 0.5
|
|
1854
1967
|
},
|
|
1855
|
-
children: /* @__PURE__ */ jsx9(
|
|
1968
|
+
children: /* @__PURE__ */ jsx9(Mic3, { style: { width: 18, height: 18 } })
|
|
1856
1969
|
}
|
|
1857
1970
|
),
|
|
1858
1971
|
/* @__PURE__ */ jsx9(
|
|
@@ -1908,7 +2021,7 @@ function ComposerBar({
|
|
|
1908
2021
|
style: { backgroundColor: `${colors.primary}33`, filter: "blur(4px)" }
|
|
1909
2022
|
}
|
|
1910
2023
|
),
|
|
1911
|
-
/* @__PURE__ */ jsx9(
|
|
2024
|
+
/* @__PURE__ */ jsx9(Mic3, { style: { width: 18, height: 18, position: "relative", zIndex: 1 } })
|
|
1912
2025
|
]
|
|
1913
2026
|
}
|
|
1914
2027
|
),
|
|
@@ -1947,7 +2060,7 @@ function ComposerBar({
|
|
|
1947
2060
|
},
|
|
1948
2061
|
"aria-label": "Type a message",
|
|
1949
2062
|
"data-testid": "voice-agent-keyboard",
|
|
1950
|
-
children: /* @__PURE__ */ jsx9(
|
|
2063
|
+
children: /* @__PURE__ */ jsx9(Keyboard2, { style: { width: 18, height: 18 } })
|
|
1951
2064
|
}
|
|
1952
2065
|
)
|
|
1953
2066
|
]
|
|
@@ -2052,7 +2165,7 @@ function ComposerBar({
|
|
|
2052
2165
|
},
|
|
2053
2166
|
"aria-label": "Back to voice mode",
|
|
2054
2167
|
"data-testid": "voice-agent-voice-mode",
|
|
2055
|
-
children: /* @__PURE__ */ jsx9(
|
|
2168
|
+
children: /* @__PURE__ */ jsx9(Mic3, { style: { width: 18, height: 18 } })
|
|
2056
2169
|
}
|
|
2057
2170
|
)
|
|
2058
2171
|
]
|
|
@@ -2088,7 +2201,10 @@ function ExpandedContent({
|
|
|
2088
2201
|
onSettingsToggle,
|
|
2089
2202
|
ttsEnabled = true,
|
|
2090
2203
|
copilotName,
|
|
2091
|
-
portraitSrc
|
|
2204
|
+
portraitSrc,
|
|
2205
|
+
onStartMic,
|
|
2206
|
+
onSwitchToKeyboard,
|
|
2207
|
+
switchToTextRef
|
|
2092
2208
|
}) {
|
|
2093
2209
|
const { colors } = useSiteConfig4();
|
|
2094
2210
|
const isListening = voiceState === "LISTENING" || voiceState === "USER_SPEAKING";
|
|
@@ -2096,7 +2212,7 @@ function ExpandedContent({
|
|
|
2096
2212
|
return /* @__PURE__ */ jsxs8(
|
|
2097
2213
|
"div",
|
|
2098
2214
|
{
|
|
2099
|
-
|
|
2215
|
+
style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" },
|
|
2100
2216
|
onClick: onInteraction,
|
|
2101
2217
|
onKeyDown: onInteraction,
|
|
2102
2218
|
children: [
|
|
@@ -2172,9 +2288,9 @@ function ExpandedContent({
|
|
|
2172
2288
|
]
|
|
2173
2289
|
}
|
|
2174
2290
|
),
|
|
2175
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2176
|
-
/* @__PURE__ */ jsx9("div", { "data-testid": "voice-agent-transcript", children: /* @__PURE__ */ jsx9(VoiceTranscript, { messages, isTyping, variant: "panel", voiceError }) }),
|
|
2177
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2291
|
+
/* @__PURE__ */ jsxs8("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
|
|
2292
|
+
/* @__PURE__ */ jsx9("div", { "data-testid": "voice-agent-transcript", style: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx9(VoiceTranscript, { messages, isTyping, variant: "panel", voiceError, voiceState, onStartMic, onSwitchToKeyboard }) }),
|
|
2293
|
+
/* @__PURE__ */ jsxs8("div", { style: { flexShrink: 0 }, children: [
|
|
2178
2294
|
/* @__PURE__ */ jsx9(PipelineMetricsBar, { timings: lastTimings ?? null, show: showPipelineMetrics, autoHideMs: pipelineMetricsAutoHideMs }),
|
|
2179
2295
|
isOffline && onRetry && /* @__PURE__ */ jsx9("div", { style: { padding: "0 16px 8px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs8(motion5.button, { whileHover: { scale: 1.04 }, whileTap: { scale: 0.96 }, onClick: onRetry, disabled: isRetrying, className: "inline-flex items-center gap-2 rounded-full cursor-pointer transition-colors", style: { padding: "8px 18px", fontSize: "13px", fontWeight: 500, color: isRetrying ? "rgba(0,0,0,0.35)" : "rgba(220,38,38,0.8)", backgroundColor: isRetrying ? "rgba(0,0,0,0.04)" : "rgba(220,38,38,0.08)", border: "1px solid", borderColor: isRetrying ? "rgba(0,0,0,0.06)" : "rgba(220,38,38,0.15)" }, "aria-label": "Retry connection", children: [
|
|
2180
2296
|
/* @__PURE__ */ jsx9(motion5.span, { animate: isRetrying ? { rotate: 360 } : { rotate: 0 }, transition: isRetrying ? { duration: 0.8, repeat: Infinity, ease: "linear" } : { duration: 0.3 }, style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx9(RotateCw, { style: { width: 14, height: 14 } }) }),
|
|
@@ -2184,7 +2300,7 @@ function ExpandedContent({
|
|
|
2184
2300
|
/* @__PURE__ */ jsx9("div", { style: { padding: "0 16px 8px" }, children: /* @__PURE__ */ jsx9(VoiceToolCard, { result: toolResult, onDismiss: onToolDismiss, variant: "capsule" }) })
|
|
2185
2301
|
] })
|
|
2186
2302
|
] }),
|
|
2187
|
-
/* @__PURE__ */ jsx9(motion5.div, { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, transition: { ...SPRING_MICRO, delay: 0.2 }, className: "shrink-0", children: /* @__PURE__ */ jsx9(ComposerBar, { voiceState, isListening, micPaused, onTextSubmit, onMicToggle, disabled: voiceError === "network_error" }) })
|
|
2303
|
+
/* @__PURE__ */ jsx9(motion5.div, { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, transition: { ...SPRING_MICRO, delay: 0.2 }, className: "shrink-0", children: /* @__PURE__ */ jsx9(ComposerBar, { voiceState, isListening, micPaused, onTextSubmit, onMicToggle, disabled: voiceError === "network_error", switchToTextRef }) })
|
|
2188
2304
|
]
|
|
2189
2305
|
}
|
|
2190
2306
|
);
|
|
@@ -2261,8 +2377,8 @@ function WiredPanelInner({
|
|
|
2261
2377
|
const { settings: voiceSettings, volumeRef, speedRef } = useVoiceSettings();
|
|
2262
2378
|
const { state, start, stop, messages, isLLMLoading, getAmplitude, analyser, sendTextMessage, voiceError, dismissError, sessionEnded, lastTimings, applyVolume, settings } = useVoiceAgent({ settings: voiceSettings, volumeRef, speedRef });
|
|
2263
2379
|
useEffect6(() => {
|
|
2264
|
-
if (sessionEnded)
|
|
2265
|
-
}, [sessionEnded,
|
|
2380
|
+
if (sessionEnded) onCollapse();
|
|
2381
|
+
}, [sessionEnded, onCollapse]);
|
|
2266
2382
|
const [toolResult, setToolResult] = useState5(null);
|
|
2267
2383
|
const orbState = voiceStateToOrbState(state);
|
|
2268
2384
|
const [backendDown, setBackendDown] = useState5(false);
|
|
@@ -2385,13 +2501,26 @@ function WiredPanelInner({
|
|
|
2385
2501
|
}
|
|
2386
2502
|
}).catch(() => setIsRetrying(false));
|
|
2387
2503
|
}, [isRetrying, runHealthCheck, dismissError, settings.autoListen]);
|
|
2504
|
+
const onExpandRef = useRef4(onExpand);
|
|
2505
|
+
useEffect6(() => {
|
|
2506
|
+
onExpandRef.current = onExpand;
|
|
2507
|
+
});
|
|
2508
|
+
useEffect6(() => {
|
|
2509
|
+
if (panelState === "collapsed" && messages.length > 0) {
|
|
2510
|
+
onExpandRef.current();
|
|
2511
|
+
}
|
|
2512
|
+
}, [panelState, messages.length]);
|
|
2513
|
+
const switchToTextRef = useRef4(null);
|
|
2514
|
+
const handleSwitchToKeyboard = useCallback3(() => {
|
|
2515
|
+
switchToTextRef.current?.();
|
|
2516
|
+
}, []);
|
|
2388
2517
|
const [showSettings, setShowSettings] = useState5(false);
|
|
2389
2518
|
const toggleSettings = useCallback3(() => setShowSettings((p) => !p), []);
|
|
2390
2519
|
if (panelState === "collapsed") {
|
|
2391
2520
|
return /* @__PURE__ */ jsx9(CollapsedBar, { orbState, getAmplitude, analyser, voiceState: state, onExpand, onClose, onRetry: handleRetryClick, isRetrying, voiceError: effectiveError, micPaused, onMicToggle: handleMicToggle, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait });
|
|
2392
2521
|
}
|
|
2393
2522
|
return /* @__PURE__ */ jsxs8("div", { className: "relative h-full", children: [
|
|
2394
|
-
/* @__PURE__ */ jsx9(ExpandedContent, { orbState, getAmplitude, analyser, voiceState: state, messages, isTyping, toolResult, voiceError: effectiveError, dismissError, onCollapse, onClose, onTextSubmit: handleTextSubmit, onMicToggle: handleMicToggle, micPaused, onToolDismiss: () => setToolResult(null), onInteraction: bumpActivity, onRetry: handleRetryClick, isRetrying, lastTimings, showPipelineMetrics: settings.showPipelineMetrics, pipelineMetricsAutoHideMs: settings.pipelineMetricsAutoHideMs, showSettings, onSettingsToggle: toggleSettings, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait }),
|
|
2523
|
+
/* @__PURE__ */ jsx9(ExpandedContent, { orbState, getAmplitude, analyser, voiceState: state, messages, isTyping, toolResult, voiceError: effectiveError, dismissError, onCollapse, onClose, onTextSubmit: handleTextSubmit, onMicToggle: handleMicToggle, micPaused, onToolDismiss: () => setToolResult(null), onInteraction: bumpActivity, onRetry: handleRetryClick, isRetrying, lastTimings, showPipelineMetrics: settings.showPipelineMetrics, pipelineMetricsAutoHideMs: settings.pipelineMetricsAutoHideMs, showSettings, onSettingsToggle: toggleSettings, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait, onStartMic: handleMicToggle, onSwitchToKeyboard: handleSwitchToKeyboard, switchToTextRef }),
|
|
2395
2524
|
/* @__PURE__ */ jsx9(AnimatePresence5, { children: showSettings && /* @__PURE__ */ jsx9(Suspense, { fallback: null, children: /* @__PURE__ */ jsx9(VoiceSettingsView2, { onBack: toggleSettings, onVolumeChange: applyVolume }) }) })
|
|
2396
2525
|
] });
|
|
2397
2526
|
}
|
|
@@ -2511,7 +2640,7 @@ function VoiceA11yAnnouncer({ isOpen, orbState }) {
|
|
|
2511
2640
|
|
|
2512
2641
|
// src/components/VoiceCopilotFAB.tsx
|
|
2513
2642
|
import { motion as motion6, AnimatePresence as AnimatePresence6, useReducedMotion as useReducedMotion2 } from "motion/react";
|
|
2514
|
-
import { Mic as
|
|
2643
|
+
import { Mic as Mic4 } from "lucide-react";
|
|
2515
2644
|
import { useSiteConfig as useSiteConfig5 } from "@unctad-ai/voice-agent-core";
|
|
2516
2645
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2517
2646
|
function VoiceCopilotFAB({
|
|
@@ -2542,7 +2671,7 @@ function VoiceCopilotFAB({
|
|
|
2542
2671
|
className: "relative rounded-full p-3 shadow-lg text-white transition-all cursor-pointer",
|
|
2543
2672
|
style: { backgroundColor: colors.primary },
|
|
2544
2673
|
"aria-label": "Open voice assistant",
|
|
2545
|
-
children: isActive ? /* @__PURE__ */ jsx11("span", { className: "h-3 w-3 rounded-full bg-white animate-pulse" }) : /* @__PURE__ */ jsx11(
|
|
2674
|
+
children: isActive ? /* @__PURE__ */ jsx11("span", { className: "h-3 w-3 rounded-full bg-white animate-pulse" }) : /* @__PURE__ */ jsx11(Mic4, { className: "w-6 h-6" })
|
|
2546
2675
|
}
|
|
2547
2676
|
)
|
|
2548
2677
|
},
|
|
@@ -2553,7 +2682,7 @@ function VoiceCopilotFAB({
|
|
|
2553
2682
|
// src/components/VoiceControls.tsx
|
|
2554
2683
|
import { useState as useState6, useRef as useRef6, useEffect as useEffect8 } from "react";
|
|
2555
2684
|
import { motion as motion7, AnimatePresence as AnimatePresence7 } from "motion/react";
|
|
2556
|
-
import { Keyboard as
|
|
2685
|
+
import { Keyboard as Keyboard3, Send, X as X2 } from "lucide-react";
|
|
2557
2686
|
import { useSiteConfig as useSiteConfig6 } from "@unctad-ai/voice-agent-core";
|
|
2558
2687
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2559
2688
|
var STATE_LABELS2 = {
|
|
@@ -2722,7 +2851,7 @@ function VoiceControls({ state, onTextSubmit, isListening }) {
|
|
|
2722
2851
|
"transition-all duration-200 cursor-pointer"
|
|
2723
2852
|
),
|
|
2724
2853
|
"aria-label": "Type a message",
|
|
2725
|
-
children: /* @__PURE__ */ jsx12(
|
|
2854
|
+
children: /* @__PURE__ */ jsx12(Keyboard3, { className: "h-4 w-4" })
|
|
2726
2855
|
}
|
|
2727
2856
|
)
|
|
2728
2857
|
]
|
|
@@ -3364,8 +3493,14 @@ function VoiceOverlay({ isOpen, onClose, onStateChange }) {
|
|
|
3364
3493
|
}
|
|
3365
3494
|
export {
|
|
3366
3495
|
AgentAvatar,
|
|
3496
|
+
Divider,
|
|
3367
3497
|
GlassCopilotPanel,
|
|
3498
|
+
PersonaSettings,
|
|
3368
3499
|
PipelineMetricsBar,
|
|
3500
|
+
SelectSetting,
|
|
3501
|
+
SettingsSection,
|
|
3502
|
+
SliderSetting,
|
|
3503
|
+
ToggleSetting,
|
|
3369
3504
|
VoiceA11yAnnouncer,
|
|
3370
3505
|
VoiceAgentProvider,
|
|
3371
3506
|
VoiceControls,
|