@unctad-ai/voice-agent-ui 5.1.2 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{VoiceSettingsView-DAYBNBVA.js → VoiceSettingsView-OPMI5HCP.js} +2 -2
- package/dist/{chunk-OUTD6CWN.js → chunk-IMDRPZ6B.js} +2 -2
- package/dist/index.js +207 -23
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- /package/dist/{VoiceSettingsView-DAYBNBVA.js.map → VoiceSettingsView-OPMI5HCP.js.map} +0 -0
- /package/dist/{chunk-OUTD6CWN.js.map → chunk-IMDRPZ6B.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
SliderSetting,
|
|
6
6
|
ToggleSetting,
|
|
7
7
|
VoiceSettingsView
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IMDRPZ6B.js";
|
|
9
9
|
export {
|
|
10
10
|
Divider,
|
|
11
11
|
SelectSetting,
|
|
@@ -14,4 +14,4 @@ export {
|
|
|
14
14
|
ToggleSetting,
|
|
15
15
|
VoiceSettingsView as default
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=VoiceSettingsView-
|
|
17
|
+
//# sourceMappingURL=VoiceSettingsView-OPMI5HCP.js.map
|
|
@@ -1902,7 +1902,7 @@ function VoiceSettingsView({ onBack, onVolumeChange }) {
|
|
|
1902
1902
|
) : /* @__PURE__ */ jsx3("span", {}),
|
|
1903
1903
|
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1904
1904
|
"Kit v",
|
|
1905
|
-
/* @__PURE__ */ jsx3("span", { style: { fontWeight: 500, color: "#6b7280" }, children: "5.
|
|
1905
|
+
/* @__PURE__ */ jsx3("span", { style: { fontWeight: 500, color: "#6b7280" }, children: "5.2.0" })
|
|
1906
1906
|
] })
|
|
1907
1907
|
] }) })
|
|
1908
1908
|
]
|
|
@@ -1994,4 +1994,4 @@ export {
|
|
|
1994
1994
|
SettingsSection,
|
|
1995
1995
|
Divider
|
|
1996
1996
|
};
|
|
1997
|
-
//# sourceMappingURL=chunk-
|
|
1997
|
+
//# sourceMappingURL=chunk-IMDRPZ6B.js.map
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
VoiceSettingsProvider,
|
|
9
9
|
VoiceSettingsView,
|
|
10
10
|
useVoiceSettings
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IMDRPZ6B.js";
|
|
12
12
|
|
|
13
13
|
// src/VoiceAgentProvider.tsx
|
|
14
14
|
import { SiteConfigProvider } from "@unctad-ai/voice-agent-core";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
Component as Component2
|
|
33
33
|
} from "react";
|
|
34
34
|
import { createPortal } from "react-dom";
|
|
35
|
-
import { motion as motion5, AnimatePresence as AnimatePresence5 } from "motion/react";
|
|
35
|
+
import { motion as motion5, AnimatePresence as AnimatePresence5, useReducedMotion as useReducedMotion2 } from "motion/react";
|
|
36
36
|
import { ChevronDown as ChevronDown2, X, Mic as Mic3, ArrowUp, Keyboard as Keyboard2, RotateCw, Settings, VolumeX as VolumeX2, Flag as Flag2 } from "lucide-react";
|
|
37
37
|
import {
|
|
38
38
|
useVoiceAgent,
|
|
@@ -1764,7 +1764,7 @@ function PipelineMetricsBar({
|
|
|
1764
1764
|
|
|
1765
1765
|
// src/components/GlassCopilotPanel.tsx
|
|
1766
1766
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1767
|
-
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-
|
|
1767
|
+
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-OPMI5HCP.js"));
|
|
1768
1768
|
var RETRY_INITIAL_MS = 3e3;
|
|
1769
1769
|
var RETRY_MAX_MS = 3e4;
|
|
1770
1770
|
var STATE_LABELS = {
|
|
@@ -1795,12 +1795,12 @@ function CopilotFAB({ onClick, portraitSrc, isOffline = false }) {
|
|
|
1795
1795
|
border: "none",
|
|
1796
1796
|
padding: 0,
|
|
1797
1797
|
borderRadius: "50%",
|
|
1798
|
-
width:
|
|
1799
|
-
height:
|
|
1798
|
+
width: 68,
|
|
1799
|
+
height: 68
|
|
1800
1800
|
},
|
|
1801
1801
|
"aria-label": "Open voice assistant",
|
|
1802
1802
|
"data-testid": "voice-agent-fab",
|
|
1803
|
-
children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border", style: { width:
|
|
1803
|
+
children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border", style: { width: 68, height: 68, "--agent-primary": isOffline ? "#9ca3af" : colors.primary, animation: isOffline ? "none" : void 0 }, children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border-inner", children: portraitSrc ? /* @__PURE__ */ jsx9(
|
|
1804
1804
|
"img",
|
|
1805
1805
|
{
|
|
1806
1806
|
src: portraitSrc,
|
|
@@ -1819,7 +1819,7 @@ function CopilotFAB({ onClick, portraitSrc, isOffline = false }) {
|
|
|
1819
1819
|
justifyContent: "center",
|
|
1820
1820
|
backgroundColor: "#6b7280",
|
|
1821
1821
|
color: "white",
|
|
1822
|
-
fontSize:
|
|
1822
|
+
fontSize: 24,
|
|
1823
1823
|
fontWeight: 700
|
|
1824
1824
|
},
|
|
1825
1825
|
children: "AI"
|
|
@@ -1828,6 +1828,176 @@ function CopilotFAB({ onClick, portraitSrc, isOffline = false }) {
|
|
|
1828
1828
|
}
|
|
1829
1829
|
);
|
|
1830
1830
|
}
|
|
1831
|
+
var FAB_GREETED_KEY = (name) => `voice-fab-greeted:${name}`;
|
|
1832
|
+
var FAB_LAST_SHOWN_KEY = (name) => `voice-fab-last-shown:${name}`;
|
|
1833
|
+
var FAB_COOLDOWN_MS = 30 * 60 * 1e3;
|
|
1834
|
+
var FAB_TOOLTIP_NARROW_QUERY = "(max-width: 479px)";
|
|
1835
|
+
function safeStorage(op) {
|
|
1836
|
+
try {
|
|
1837
|
+
return op();
|
|
1838
|
+
} catch {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
function CopilotFABTooltip({ onClick }) {
|
|
1843
|
+
const { copilotName, colors, fabTooltip } = useSiteConfig4();
|
|
1844
|
+
const prefersReduced = useReducedMotion2();
|
|
1845
|
+
const [visible, setVisible] = useState5(false);
|
|
1846
|
+
const [dismissed, setDismissed] = useState5(false);
|
|
1847
|
+
const [isFirstVisit] = useState5(() => !safeStorage(() => localStorage.getItem(FAB_GREETED_KEY(copilotName))));
|
|
1848
|
+
useEffect6(() => {
|
|
1849
|
+
if (typeof window === "undefined") return;
|
|
1850
|
+
const mql = window.matchMedia(FAB_TOOLTIP_NARROW_QUERY);
|
|
1851
|
+
if (mql.matches) {
|
|
1852
|
+
setDismissed(true);
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1855
|
+
const handler = (e) => {
|
|
1856
|
+
if (e.matches) setDismissed(true);
|
|
1857
|
+
};
|
|
1858
|
+
mql.addEventListener("change", handler);
|
|
1859
|
+
return () => mql.removeEventListener("change", handler);
|
|
1860
|
+
}, []);
|
|
1861
|
+
useEffect6(() => {
|
|
1862
|
+
if (isFirstVisit) {
|
|
1863
|
+
const timer2 = setTimeout(() => {
|
|
1864
|
+
setVisible(true);
|
|
1865
|
+
safeStorage(() => localStorage.setItem(FAB_GREETED_KEY(copilotName), "true"));
|
|
1866
|
+
safeStorage(() => localStorage.setItem(FAB_LAST_SHOWN_KEY(copilotName), (/* @__PURE__ */ new Date()).toISOString()));
|
|
1867
|
+
}, 2e3);
|
|
1868
|
+
return () => clearTimeout(timer2);
|
|
1869
|
+
}
|
|
1870
|
+
const lastShown = safeStorage(() => localStorage.getItem(FAB_LAST_SHOWN_KEY(copilotName)));
|
|
1871
|
+
if (lastShown && Date.now() - new Date(lastShown).getTime() < FAB_COOLDOWN_MS) return;
|
|
1872
|
+
const timer = setTimeout(() => {
|
|
1873
|
+
setVisible(true);
|
|
1874
|
+
safeStorage(() => localStorage.setItem(FAB_LAST_SHOWN_KEY(copilotName), (/* @__PURE__ */ new Date()).toISOString()));
|
|
1875
|
+
}, 5e3);
|
|
1876
|
+
return () => clearTimeout(timer);
|
|
1877
|
+
}, [copilotName, isFirstVisit]);
|
|
1878
|
+
useEffect6(() => {
|
|
1879
|
+
if (!visible || isFirstVisit) return;
|
|
1880
|
+
const timer = setTimeout(() => setDismissed(true), 5e3);
|
|
1881
|
+
return () => clearTimeout(timer);
|
|
1882
|
+
}, [visible, isFirstVisit]);
|
|
1883
|
+
useEffect6(() => {
|
|
1884
|
+
if (!visible || dismissed || isFirstVisit) return;
|
|
1885
|
+
const handleScroll = () => setDismissed(true);
|
|
1886
|
+
window.addEventListener("scroll", handleScroll, { passive: true, once: true });
|
|
1887
|
+
return () => window.removeEventListener("scroll", handleScroll);
|
|
1888
|
+
}, [visible, dismissed, isFirstVisit]);
|
|
1889
|
+
const handleTryNow = () => {
|
|
1890
|
+
setDismissed(true);
|
|
1891
|
+
onClick();
|
|
1892
|
+
};
|
|
1893
|
+
const handleDismiss = (e) => {
|
|
1894
|
+
e.stopPropagation();
|
|
1895
|
+
setDismissed(true);
|
|
1896
|
+
};
|
|
1897
|
+
const firstVisitText = fabTooltip?.firstVisit ? fabTooltip.firstVisit.replaceAll("{name}", copilotName) : `I'm ${copilotName}, your virtual civil servant.
|
|
1898
|
+
How may I help you?`;
|
|
1899
|
+
const returnVisitText = fabTooltip?.returnVisit ?? "How may I help you?";
|
|
1900
|
+
const show = visible && !dismissed;
|
|
1901
|
+
return /* @__PURE__ */ jsx9(AnimatePresence5, { children: show && /* @__PURE__ */ jsxs8(
|
|
1902
|
+
motion5.div,
|
|
1903
|
+
{
|
|
1904
|
+
role: "status",
|
|
1905
|
+
"aria-live": "polite",
|
|
1906
|
+
"data-testid": "voice-agent-fab-tooltip",
|
|
1907
|
+
initial: prefersReduced ? { opacity: 0 } : { opacity: 0, x: 20 },
|
|
1908
|
+
animate: prefersReduced ? { opacity: 1 } : { opacity: 1, x: 0 },
|
|
1909
|
+
exit: prefersReduced ? { opacity: 0 } : { opacity: 0, x: 10 },
|
|
1910
|
+
transition: prefersReduced ? { duration: 0.2 } : { type: "spring", stiffness: 300, damping: 25 },
|
|
1911
|
+
onClick: isFirstVisit ? void 0 : handleTryNow,
|
|
1912
|
+
style: {
|
|
1913
|
+
display: "flex",
|
|
1914
|
+
alignItems: "center",
|
|
1915
|
+
gap: 0,
|
|
1916
|
+
cursor: isFirstVisit ? "default" : "pointer"
|
|
1917
|
+
},
|
|
1918
|
+
children: [
|
|
1919
|
+
/* @__PURE__ */ jsxs8(
|
|
1920
|
+
"div",
|
|
1921
|
+
{
|
|
1922
|
+
style: {
|
|
1923
|
+
background: "white",
|
|
1924
|
+
borderRadius: 20,
|
|
1925
|
+
padding: isFirstVisit ? "12px 20px" : "10px 18px",
|
|
1926
|
+
boxShadow: "0 2px 12px rgba(0,0,0,0.10), 0 0 0 1px rgba(0,0,0,0.04)",
|
|
1927
|
+
maxWidth: 340
|
|
1928
|
+
},
|
|
1929
|
+
children: [
|
|
1930
|
+
/* @__PURE__ */ jsx9(
|
|
1931
|
+
"div",
|
|
1932
|
+
{
|
|
1933
|
+
style: {
|
|
1934
|
+
fontSize: isFirstVisit ? 14 : 13,
|
|
1935
|
+
color: "#1a1a1a",
|
|
1936
|
+
fontWeight: 500,
|
|
1937
|
+
lineHeight: 1.4,
|
|
1938
|
+
whiteSpace: "pre-line"
|
|
1939
|
+
},
|
|
1940
|
+
children: isFirstVisit ? firstVisitText : returnVisitText
|
|
1941
|
+
}
|
|
1942
|
+
),
|
|
1943
|
+
isFirstVisit && /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: 8, marginTop: 8 }, children: [
|
|
1944
|
+
/* @__PURE__ */ jsx9(
|
|
1945
|
+
"button",
|
|
1946
|
+
{
|
|
1947
|
+
"data-testid": "voice-agent-fab-tooltip-cta",
|
|
1948
|
+
"aria-label": `Open ${copilotName} voice assistant`,
|
|
1949
|
+
onClick: handleTryNow,
|
|
1950
|
+
style: {
|
|
1951
|
+
padding: "6px 16px",
|
|
1952
|
+
background: colors.primary,
|
|
1953
|
+
color: "white",
|
|
1954
|
+
border: "none",
|
|
1955
|
+
borderRadius: 12,
|
|
1956
|
+
fontSize: 12,
|
|
1957
|
+
fontWeight: 600,
|
|
1958
|
+
cursor: "pointer"
|
|
1959
|
+
},
|
|
1960
|
+
children: "Try it now"
|
|
1961
|
+
}
|
|
1962
|
+
),
|
|
1963
|
+
/* @__PURE__ */ jsx9(
|
|
1964
|
+
"button",
|
|
1965
|
+
{
|
|
1966
|
+
onClick: handleDismiss,
|
|
1967
|
+
style: {
|
|
1968
|
+
padding: "6px 12px",
|
|
1969
|
+
background: "transparent",
|
|
1970
|
+
color: "#6b7280",
|
|
1971
|
+
border: "none",
|
|
1972
|
+
borderRadius: 12,
|
|
1973
|
+
fontSize: 12,
|
|
1974
|
+
cursor: "pointer"
|
|
1975
|
+
},
|
|
1976
|
+
children: "Maybe later"
|
|
1977
|
+
}
|
|
1978
|
+
)
|
|
1979
|
+
] })
|
|
1980
|
+
]
|
|
1981
|
+
}
|
|
1982
|
+
),
|
|
1983
|
+
/* @__PURE__ */ jsx9(
|
|
1984
|
+
"div",
|
|
1985
|
+
{
|
|
1986
|
+
style: {
|
|
1987
|
+
width: 0,
|
|
1988
|
+
height: 0,
|
|
1989
|
+
borderTop: "8px solid transparent",
|
|
1990
|
+
borderBottom: "8px solid transparent",
|
|
1991
|
+
borderLeft: "8px solid white",
|
|
1992
|
+
flexShrink: 0,
|
|
1993
|
+
filter: "drop-shadow(2px 0 1px rgba(0,0,0,0.06))"
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
)
|
|
1997
|
+
]
|
|
1998
|
+
}
|
|
1999
|
+
) });
|
|
2000
|
+
}
|
|
1831
2001
|
function CollapsedBar({
|
|
1832
2002
|
orbState,
|
|
1833
2003
|
getAmplitude,
|
|
@@ -2673,19 +2843,30 @@ function WiredPanelInner({
|
|
|
2673
2843
|
useEffect6(() => {
|
|
2674
2844
|
if (panelState === "hidden") stopRef.current(true);
|
|
2675
2845
|
}, [panelState]);
|
|
2846
|
+
const micOpen = state === "LISTENING" || state === "USER_SPEAKING";
|
|
2847
|
+
const stateRef = useRef4(state);
|
|
2848
|
+
stateRef.current = state;
|
|
2676
2849
|
useEffect6(() => {
|
|
2677
2850
|
if (panelState === "hidden" || micPaused || showSettings) return;
|
|
2678
|
-
if (
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2851
|
+
if (!micOpen) return;
|
|
2852
|
+
let timer;
|
|
2853
|
+
const schedule = () => {
|
|
2854
|
+
timer = setTimeout(() => {
|
|
2855
|
+
if (stateRef.current === "USER_SPEAKING") {
|
|
2856
|
+
schedule();
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2859
|
+
stopRef.current();
|
|
2860
|
+
if (hasConversationRef.current) {
|
|
2861
|
+
setMicPaused(true);
|
|
2862
|
+
} else {
|
|
2863
|
+
onCollapseRef.current();
|
|
2864
|
+
}
|
|
2865
|
+
}, settings.idleTimeoutMs);
|
|
2866
|
+
};
|
|
2867
|
+
schedule();
|
|
2687
2868
|
return () => clearTimeout(timer);
|
|
2688
|
-
}, [
|
|
2869
|
+
}, [micOpen, panelState, micPaused, showSettings, activity, settings.idleTimeoutMs]);
|
|
2689
2870
|
useEffect6(() => {
|
|
2690
2871
|
if (!micPaused || panelState !== "expanded" || showSettings) return;
|
|
2691
2872
|
if (settings.panelCollapseTimeoutMs === 0) return;
|
|
@@ -2721,7 +2902,7 @@ function WiredPanelInner({
|
|
|
2721
2902
|
timings: lastTimings ?? void 0,
|
|
2722
2903
|
route: window.location.pathname,
|
|
2723
2904
|
copilotName: config.copilotName,
|
|
2724
|
-
kitVersion: "5.
|
|
2905
|
+
kitVersion: "5.2.0"
|
|
2725
2906
|
})
|
|
2726
2907
|
});
|
|
2727
2908
|
const body = await res.json().catch(() => ({ ticketId: void 0 }));
|
|
@@ -2859,7 +3040,10 @@ function GlassCopilotPanel({ isOpen: isOpenProp, onOpen: onOpenProp, onClose: on
|
|
|
2859
3040
|
] }) }) }),
|
|
2860
3041
|
/* @__PURE__ */ jsx9("span", { "aria-live": "polite", "aria-atomic": "true", style: { position: "absolute", width: 1, height: 1, padding: 0, margin: -1, overflow: "hidden", clip: "rect(0,0,0,0)", whiteSpace: "nowrap", borderWidth: 0 }, children: ariaAnnouncement }),
|
|
2861
3042
|
/* @__PURE__ */ jsxs8(AnimatePresence5, { children: [
|
|
2862
|
-
!isVisible && /* @__PURE__ */
|
|
3043
|
+
!isVisible && /* @__PURE__ */ jsxs8(motion5.div, { ref: fabRef, initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, exit: { scale: 0, opacity: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: "fixed", style: { bottom: PANEL_BOTTOM, right: PANEL_RIGHT, zIndex: PANEL_Z_INDEX, display: "flex", alignItems: "flex-end", gap: 12 }, children: [
|
|
3044
|
+
/* @__PURE__ */ jsx9(CopilotFABTooltip, { onClick: handleOpen }),
|
|
3045
|
+
/* @__PURE__ */ jsx9(CopilotFAB, { onClick: handleOpen, portraitSrc: resolvedPortrait, isOffline: fabOffline })
|
|
3046
|
+
] }, "copilot-fab"),
|
|
2863
3047
|
isVisible && /* @__PURE__ */ jsxs8(
|
|
2864
3048
|
motion5.div,
|
|
2865
3049
|
{
|
|
@@ -2869,9 +3053,9 @@ function GlassCopilotPanel({ isOpen: isOpenProp, onOpen: onOpenProp, onClose: on
|
|
|
2869
3053
|
"aria-label": "Voice Assistant",
|
|
2870
3054
|
"aria-modal": "false",
|
|
2871
3055
|
"data-testid": "voice-agent-panel",
|
|
2872
|
-
initial: { width:
|
|
3056
|
+
initial: { width: 68, height: 68, borderRadius: 34, opacity: 0, scale: 0.9 },
|
|
2873
3057
|
animate: { width: PANEL_WIDTH, height: Math.min(targetHeight, window.innerHeight - 48), borderRadius: PANEL_BORDER_RADIUS, opacity: 1, scale: 1, transition: SPRING_PANEL },
|
|
2874
|
-
exit: { width:
|
|
3058
|
+
exit: { width: 68, height: 68, borderRadius: 34, opacity: 0, scale: 0.95, transition: SPRING_PANEL_EXIT },
|
|
2875
3059
|
className: "fixed",
|
|
2876
3060
|
style: { bottom: PANEL_BOTTOM, right: PANEL_RIGHT, zIndex: PANEL_Z_INDEX, transformOrigin: "bottom right", maxWidth: "calc(100vw - 32px)", outline: "none", fontFamily: config.fontFamily ?? DEFAULT_FONT_FAMILY2 },
|
|
2877
3061
|
children: [
|
|
@@ -2928,7 +3112,7 @@ function VoiceA11yAnnouncer({ isOpen, orbState }) {
|
|
|
2928
3112
|
}
|
|
2929
3113
|
|
|
2930
3114
|
// src/components/VoiceCopilotFAB.tsx
|
|
2931
|
-
import { motion as motion6, AnimatePresence as AnimatePresence6, useReducedMotion as
|
|
3115
|
+
import { motion as motion6, AnimatePresence as AnimatePresence6, useReducedMotion as useReducedMotion3 } from "motion/react";
|
|
2932
3116
|
import { Mic as Mic4 } from "lucide-react";
|
|
2933
3117
|
import { useSiteConfig as useSiteConfig5 } from "@unctad-ai/voice-agent-core";
|
|
2934
3118
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
@@ -2938,7 +3122,7 @@ function VoiceCopilotFAB({
|
|
|
2938
3122
|
isOverlayOpen,
|
|
2939
3123
|
onMouseEnter
|
|
2940
3124
|
}) {
|
|
2941
|
-
const prefersReduced =
|
|
3125
|
+
const prefersReduced = useReducedMotion3();
|
|
2942
3126
|
const { colors } = useSiteConfig5();
|
|
2943
3127
|
return /* @__PURE__ */ jsx11(AnimatePresence6, { children: !isOverlayOpen && /* @__PURE__ */ jsx11(
|
|
2944
3128
|
motion6.div,
|