@absolutejs/voice 0.0.22-beta.94 → 0.0.22-beta.96
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/angular/index.d.ts +1 -0
- package/dist/angular/index.js +139 -20
- package/dist/angular/voice-turn-latency.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +182 -17
- package/dist/client/turnLatency.d.ts +19 -0
- package/dist/client/turnLatencyWidget.d.ts +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +278 -68
- package/dist/react/VoiceTurnLatency.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +309 -50
- package/dist/react/useVoiceTurnLatency.d.ts +8 -0
- package/dist/svelte/createVoiceTurnLatency.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +187 -16
- package/dist/testing/index.js +57 -1
- package/dist/trace.d.ts +1 -1
- package/dist/turnLatency.d.ts +95 -0
- package/dist/vue/VoiceTurnLatency.d.ts +51 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +303 -57
- package/dist/vue/useVoiceTurnLatency.d.ts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type VoiceTurnLatencyWidgetOptions } from '../client/turnLatencyWidget';
|
|
2
|
+
export type VoiceTurnLatencyProps = VoiceTurnLatencyWidgetOptions & {
|
|
3
|
+
className?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const VoiceTurnLatency: ({ className, path, ...options }: VoiceTurnLatencyProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
|
|
|
4
4
|
export { VoiceProviderStatus } from './VoiceProviderStatus';
|
|
5
5
|
export { VoiceRoutingStatus } from './VoiceRoutingStatus';
|
|
6
6
|
export { VoiceTraceTimeline } from './VoiceTraceTimeline';
|
|
7
|
+
export { VoiceTurnLatency } from './VoiceTurnLatency';
|
|
7
8
|
export { VoiceTurnQuality } from './VoiceTurnQuality';
|
|
8
9
|
export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
|
|
9
10
|
export { useVoiceStream } from './useVoiceStream';
|
|
@@ -13,5 +14,6 @@ export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
|
|
|
13
14
|
export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
|
|
14
15
|
export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
|
|
15
16
|
export { useVoiceTraceTimeline } from './useVoiceTraceTimeline';
|
|
17
|
+
export { useVoiceTurnLatency } from './useVoiceTurnLatency';
|
|
16
18
|
export { useVoiceTurnQuality } from './useVoiceTurnQuality';
|
|
17
19
|
export { useVoiceWorkflowStatus } from './useVoiceWorkflowStatus';
|
package/dist/react/index.js
CHANGED
|
@@ -1759,9 +1759,266 @@ var VoiceTraceTimeline = ({
|
|
|
1759
1759
|
]
|
|
1760
1760
|
}, undefined, true, undefined, this);
|
|
1761
1761
|
};
|
|
1762
|
-
// src/react/
|
|
1762
|
+
// src/react/useVoiceTurnLatency.tsx
|
|
1763
1763
|
import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
1764
1764
|
|
|
1765
|
+
// src/client/turnLatency.ts
|
|
1766
|
+
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
1767
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1768
|
+
const response = await fetchImpl(path);
|
|
1769
|
+
if (!response.ok) {
|
|
1770
|
+
throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
|
|
1771
|
+
}
|
|
1772
|
+
return await response.json();
|
|
1773
|
+
};
|
|
1774
|
+
var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
|
|
1775
|
+
const listeners = new Set;
|
|
1776
|
+
let closed = false;
|
|
1777
|
+
let timer;
|
|
1778
|
+
let snapshot = {
|
|
1779
|
+
error: null,
|
|
1780
|
+
isLoading: false
|
|
1781
|
+
};
|
|
1782
|
+
const emit = () => {
|
|
1783
|
+
for (const listener of listeners) {
|
|
1784
|
+
listener();
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
const refresh = async () => {
|
|
1788
|
+
if (closed) {
|
|
1789
|
+
return snapshot.report;
|
|
1790
|
+
}
|
|
1791
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
1792
|
+
emit();
|
|
1793
|
+
try {
|
|
1794
|
+
const report = await fetchVoiceTurnLatency(path, options);
|
|
1795
|
+
snapshot = {
|
|
1796
|
+
error: null,
|
|
1797
|
+
isLoading: false,
|
|
1798
|
+
report,
|
|
1799
|
+
updatedAt: Date.now()
|
|
1800
|
+
};
|
|
1801
|
+
emit();
|
|
1802
|
+
return report;
|
|
1803
|
+
} catch (error) {
|
|
1804
|
+
snapshot = {
|
|
1805
|
+
...snapshot,
|
|
1806
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1807
|
+
isLoading: false
|
|
1808
|
+
};
|
|
1809
|
+
emit();
|
|
1810
|
+
throw error;
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
const close = () => {
|
|
1814
|
+
closed = true;
|
|
1815
|
+
if (timer) {
|
|
1816
|
+
clearInterval(timer);
|
|
1817
|
+
timer = undefined;
|
|
1818
|
+
}
|
|
1819
|
+
listeners.clear();
|
|
1820
|
+
};
|
|
1821
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
1822
|
+
timer = setInterval(() => {
|
|
1823
|
+
refresh().catch(() => {});
|
|
1824
|
+
}, options.intervalMs);
|
|
1825
|
+
}
|
|
1826
|
+
return {
|
|
1827
|
+
close,
|
|
1828
|
+
getServerSnapshot: () => snapshot,
|
|
1829
|
+
getSnapshot: () => snapshot,
|
|
1830
|
+
refresh,
|
|
1831
|
+
subscribe: (listener) => {
|
|
1832
|
+
listeners.add(listener);
|
|
1833
|
+
return () => {
|
|
1834
|
+
listeners.delete(listener);
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
};
|
|
1839
|
+
|
|
1840
|
+
// src/react/useVoiceTurnLatency.tsx
|
|
1841
|
+
var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
|
|
1842
|
+
const storeRef = useRef7(null);
|
|
1843
|
+
if (!storeRef.current) {
|
|
1844
|
+
storeRef.current = createVoiceTurnLatencyStore(path, options);
|
|
1845
|
+
}
|
|
1846
|
+
const store = storeRef.current;
|
|
1847
|
+
useEffect7(() => {
|
|
1848
|
+
store.refresh().catch(() => {});
|
|
1849
|
+
return () => store.close();
|
|
1850
|
+
}, [store]);
|
|
1851
|
+
return {
|
|
1852
|
+
...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1853
|
+
refresh: store.refresh
|
|
1854
|
+
};
|
|
1855
|
+
};
|
|
1856
|
+
|
|
1857
|
+
// src/client/turnLatencyWidget.ts
|
|
1858
|
+
var DEFAULT_TITLE6 = "Turn Latency";
|
|
1859
|
+
var DEFAULT_DESCRIPTION6 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
1860
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1861
|
+
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
1862
|
+
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
1863
|
+
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
1864
|
+
...turn,
|
|
1865
|
+
label: turn.text || "Empty turn",
|
|
1866
|
+
rows: turn.stages.map((stage) => ({
|
|
1867
|
+
label: stage.label,
|
|
1868
|
+
value: formatMs2(stage.valueMs)
|
|
1869
|
+
}))
|
|
1870
|
+
}));
|
|
1871
|
+
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
1872
|
+
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
1873
|
+
return {
|
|
1874
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1875
|
+
error: snapshot.error,
|
|
1876
|
+
isLoading: snapshot.isLoading,
|
|
1877
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
1878
|
+
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1879
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1880
|
+
turns,
|
|
1881
|
+
updatedAt: snapshot.updatedAt
|
|
1882
|
+
};
|
|
1883
|
+
};
|
|
1884
|
+
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
1885
|
+
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
1886
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml7(turn.status)}">
|
|
1887
|
+
<header>
|
|
1888
|
+
<strong>${escapeHtml7(turn.label)}</strong>
|
|
1889
|
+
<span>${escapeHtml7(turn.status)}</span>
|
|
1890
|
+
</header>
|
|
1891
|
+
<dl>${turn.rows.map((row) => `<div>
|
|
1892
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
1893
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
1894
|
+
</div>`).join("")}</dl>
|
|
1895
|
+
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
1896
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml7(model.status)}">
|
|
1897
|
+
<header class="absolute-voice-turn-latency__header">
|
|
1898
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml7(model.title)}</span>
|
|
1899
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml7(model.label)}</strong>
|
|
1900
|
+
</header>
|
|
1901
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml7(model.description)}</p>
|
|
1902
|
+
${turns}
|
|
1903
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1904
|
+
</section>`;
|
|
1905
|
+
};
|
|
1906
|
+
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
1907
|
+
const store = createVoiceTurnLatencyStore(path, options);
|
|
1908
|
+
const render = () => {
|
|
1909
|
+
element.innerHTML = renderVoiceTurnLatencyHTML(store.getSnapshot(), options);
|
|
1910
|
+
};
|
|
1911
|
+
const unsubscribe = store.subscribe(render);
|
|
1912
|
+
render();
|
|
1913
|
+
store.refresh().catch(() => {});
|
|
1914
|
+
return {
|
|
1915
|
+
close: () => {
|
|
1916
|
+
unsubscribe();
|
|
1917
|
+
store.close();
|
|
1918
|
+
},
|
|
1919
|
+
refresh: store.refresh
|
|
1920
|
+
};
|
|
1921
|
+
};
|
|
1922
|
+
var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") => {
|
|
1923
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
1924
|
+
return;
|
|
1925
|
+
}
|
|
1926
|
+
customElements.define(tagName, class AbsoluteVoiceTurnLatencyElement extends HTMLElement {
|
|
1927
|
+
mounted;
|
|
1928
|
+
connectedCallback() {
|
|
1929
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
1930
|
+
this.mounted = mountVoiceTurnLatency(this, this.getAttribute("path") ?? "/api/turn-latency", {
|
|
1931
|
+
description: this.getAttribute("description") ?? undefined,
|
|
1932
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
1933
|
+
title: this.getAttribute("title") ?? undefined
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
disconnectedCallback() {
|
|
1937
|
+
this.mounted?.close();
|
|
1938
|
+
this.mounted = undefined;
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
// src/react/VoiceTurnLatency.tsx
|
|
1944
|
+
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
1945
|
+
var VoiceTurnLatency = ({
|
|
1946
|
+
className,
|
|
1947
|
+
path = "/api/turn-latency",
|
|
1948
|
+
...options
|
|
1949
|
+
}) => {
|
|
1950
|
+
const snapshot = useVoiceTurnLatency(path, options);
|
|
1951
|
+
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
1952
|
+
return /* @__PURE__ */ jsxDEV7("section", {
|
|
1953
|
+
className: [
|
|
1954
|
+
"absolute-voice-turn-latency",
|
|
1955
|
+
`absolute-voice-turn-latency--${model.status}`,
|
|
1956
|
+
className
|
|
1957
|
+
].filter(Boolean).join(" "),
|
|
1958
|
+
children: [
|
|
1959
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1960
|
+
className: "absolute-voice-turn-latency__header",
|
|
1961
|
+
children: [
|
|
1962
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1963
|
+
className: "absolute-voice-turn-latency__eyebrow",
|
|
1964
|
+
children: model.title
|
|
1965
|
+
}, undefined, false, undefined, this),
|
|
1966
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1967
|
+
className: "absolute-voice-turn-latency__label",
|
|
1968
|
+
children: model.label
|
|
1969
|
+
}, undefined, false, undefined, this)
|
|
1970
|
+
]
|
|
1971
|
+
}, undefined, true, undefined, this),
|
|
1972
|
+
/* @__PURE__ */ jsxDEV7("p", {
|
|
1973
|
+
className: "absolute-voice-turn-latency__description",
|
|
1974
|
+
children: model.description
|
|
1975
|
+
}, undefined, false, undefined, this),
|
|
1976
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV7("div", {
|
|
1977
|
+
className: "absolute-voice-turn-latency__turns",
|
|
1978
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV7("article", {
|
|
1979
|
+
className: [
|
|
1980
|
+
"absolute-voice-turn-latency__turn",
|
|
1981
|
+
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
1982
|
+
].join(" "),
|
|
1983
|
+
children: [
|
|
1984
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1985
|
+
children: [
|
|
1986
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1987
|
+
children: turn.label
|
|
1988
|
+
}, undefined, false, undefined, this),
|
|
1989
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1990
|
+
children: turn.status
|
|
1991
|
+
}, undefined, false, undefined, this)
|
|
1992
|
+
]
|
|
1993
|
+
}, undefined, true, undefined, this),
|
|
1994
|
+
/* @__PURE__ */ jsxDEV7("dl", {
|
|
1995
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
|
|
1996
|
+
children: [
|
|
1997
|
+
/* @__PURE__ */ jsxDEV7("dt", {
|
|
1998
|
+
children: row.label
|
|
1999
|
+
}, undefined, false, undefined, this),
|
|
2000
|
+
/* @__PURE__ */ jsxDEV7("dd", {
|
|
2001
|
+
children: row.value
|
|
2002
|
+
}, undefined, false, undefined, this)
|
|
2003
|
+
]
|
|
2004
|
+
}, row.label, true, undefined, this))
|
|
2005
|
+
}, undefined, false, undefined, this)
|
|
2006
|
+
]
|
|
2007
|
+
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2008
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
|
|
2009
|
+
className: "absolute-voice-turn-latency__empty",
|
|
2010
|
+
children: "Complete a voice turn to see latency diagnostics."
|
|
2011
|
+
}, undefined, false, undefined, this),
|
|
2012
|
+
model.error ? /* @__PURE__ */ jsxDEV7("p", {
|
|
2013
|
+
className: "absolute-voice-turn-latency__error",
|
|
2014
|
+
children: model.error
|
|
2015
|
+
}, undefined, false, undefined, this) : null
|
|
2016
|
+
]
|
|
2017
|
+
}, undefined, true, undefined, this);
|
|
2018
|
+
};
|
|
2019
|
+
// src/react/useVoiceTurnQuality.tsx
|
|
2020
|
+
import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
2021
|
+
|
|
1765
2022
|
// src/client/turnQuality.ts
|
|
1766
2023
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
1767
2024
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -1843,25 +2100,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
1843
2100
|
|
|
1844
2101
|
// src/react/useVoiceTurnQuality.tsx
|
|
1845
2102
|
var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
|
|
1846
|
-
const storeRef =
|
|
2103
|
+
const storeRef = useRef8(null);
|
|
1847
2104
|
if (!storeRef.current) {
|
|
1848
2105
|
storeRef.current = createVoiceTurnQualityStore(path, options);
|
|
1849
2106
|
}
|
|
1850
2107
|
const store = storeRef.current;
|
|
1851
|
-
|
|
2108
|
+
useEffect8(() => {
|
|
1852
2109
|
store.refresh().catch(() => {});
|
|
1853
2110
|
return () => store.close();
|
|
1854
2111
|
}, [store]);
|
|
1855
2112
|
return {
|
|
1856
|
-
...
|
|
2113
|
+
...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1857
2114
|
refresh: store.refresh
|
|
1858
2115
|
};
|
|
1859
2116
|
};
|
|
1860
2117
|
|
|
1861
2118
|
// src/client/turnQualityWidget.ts
|
|
1862
|
-
var
|
|
1863
|
-
var
|
|
1864
|
-
var
|
|
2119
|
+
var DEFAULT_TITLE7 = "Turn Quality";
|
|
2120
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2121
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1865
2122
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
1866
2123
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
1867
2124
|
var getTurnDetail = (turn) => {
|
|
@@ -1899,37 +2156,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
1899
2156
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
1900
2157
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
1901
2158
|
return {
|
|
1902
|
-
description: options.description ??
|
|
2159
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
1903
2160
|
error: snapshot.error,
|
|
1904
2161
|
isLoading: snapshot.isLoading,
|
|
1905
2162
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
1906
2163
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1907
|
-
title: options.title ??
|
|
2164
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
1908
2165
|
turns,
|
|
1909
2166
|
updatedAt: snapshot.updatedAt
|
|
1910
2167
|
};
|
|
1911
2168
|
};
|
|
1912
2169
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
1913
2170
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
1914
|
-
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${
|
|
2171
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml8(turn.status)}">
|
|
1915
2172
|
<header>
|
|
1916
|
-
<strong>${
|
|
1917
|
-
<span>${
|
|
2173
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
2174
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
1918
2175
|
</header>
|
|
1919
|
-
<p>${
|
|
2176
|
+
<p>${escapeHtml8(turn.detail)}</p>
|
|
1920
2177
|
<dl>${turn.rows.map((row) => `<div>
|
|
1921
|
-
<dt>${
|
|
1922
|
-
<dd>${
|
|
2178
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
2179
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
1923
2180
|
</div>`).join("")}</dl>
|
|
1924
2181
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
1925
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
2182
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml8(model.status)}">
|
|
1926
2183
|
<header class="absolute-voice-turn-quality__header">
|
|
1927
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
1928
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2184
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2185
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml8(model.label)}</strong>
|
|
1929
2186
|
</header>
|
|
1930
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2187
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml8(model.description)}</p>
|
|
1931
2188
|
${turns}
|
|
1932
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2189
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
1933
2190
|
</section>`;
|
|
1934
2191
|
};
|
|
1935
2192
|
var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;
|
|
@@ -1971,7 +2228,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
1971
2228
|
};
|
|
1972
2229
|
|
|
1973
2230
|
// src/react/VoiceTurnQuality.tsx
|
|
1974
|
-
import { jsxDEV as
|
|
2231
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
1975
2232
|
var VoiceTurnQuality = ({
|
|
1976
2233
|
className,
|
|
1977
2234
|
path = "/api/turn-quality",
|
|
@@ -1979,58 +2236,58 @@ var VoiceTurnQuality = ({
|
|
|
1979
2236
|
}) => {
|
|
1980
2237
|
const snapshot = useVoiceTurnQuality(path, options);
|
|
1981
2238
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
1982
|
-
return /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsxDEV8("section", {
|
|
1983
2240
|
className: [
|
|
1984
2241
|
"absolute-voice-turn-quality",
|
|
1985
2242
|
`absolute-voice-turn-quality--${model.status}`,
|
|
1986
2243
|
className
|
|
1987
2244
|
].filter(Boolean).join(" "),
|
|
1988
2245
|
children: [
|
|
1989
|
-
/* @__PURE__ */
|
|
2246
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
1990
2247
|
className: "absolute-voice-turn-quality__header",
|
|
1991
2248
|
children: [
|
|
1992
|
-
/* @__PURE__ */
|
|
2249
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
1993
2250
|
className: "absolute-voice-turn-quality__eyebrow",
|
|
1994
2251
|
children: model.title
|
|
1995
2252
|
}, undefined, false, undefined, this),
|
|
1996
|
-
/* @__PURE__ */
|
|
2253
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
1997
2254
|
className: "absolute-voice-turn-quality__label",
|
|
1998
2255
|
children: model.label
|
|
1999
2256
|
}, undefined, false, undefined, this)
|
|
2000
2257
|
]
|
|
2001
2258
|
}, undefined, true, undefined, this),
|
|
2002
|
-
/* @__PURE__ */
|
|
2259
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2003
2260
|
className: "absolute-voice-turn-quality__description",
|
|
2004
2261
|
children: model.description
|
|
2005
2262
|
}, undefined, false, undefined, this),
|
|
2006
|
-
model.turns.length ? /* @__PURE__ */
|
|
2263
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV8("div", {
|
|
2007
2264
|
className: "absolute-voice-turn-quality__turns",
|
|
2008
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
2265
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV8("article", {
|
|
2009
2266
|
className: [
|
|
2010
2267
|
"absolute-voice-turn-quality__turn",
|
|
2011
2268
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
2012
2269
|
].join(" "),
|
|
2013
2270
|
children: [
|
|
2014
|
-
/* @__PURE__ */
|
|
2271
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2015
2272
|
children: [
|
|
2016
|
-
/* @__PURE__ */
|
|
2273
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2017
2274
|
children: turn.label
|
|
2018
2275
|
}, undefined, false, undefined, this),
|
|
2019
|
-
/* @__PURE__ */
|
|
2276
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2020
2277
|
children: turn.status
|
|
2021
2278
|
}, undefined, false, undefined, this)
|
|
2022
2279
|
]
|
|
2023
2280
|
}, undefined, true, undefined, this),
|
|
2024
|
-
/* @__PURE__ */
|
|
2281
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2025
2282
|
children: turn.detail
|
|
2026
2283
|
}, undefined, false, undefined, this),
|
|
2027
|
-
/* @__PURE__ */
|
|
2028
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
2284
|
+
/* @__PURE__ */ jsxDEV8("dl", {
|
|
2285
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV8("div", {
|
|
2029
2286
|
children: [
|
|
2030
|
-
/* @__PURE__ */
|
|
2287
|
+
/* @__PURE__ */ jsxDEV8("dt", {
|
|
2031
2288
|
children: row.label
|
|
2032
2289
|
}, undefined, false, undefined, this),
|
|
2033
|
-
/* @__PURE__ */
|
|
2290
|
+
/* @__PURE__ */ jsxDEV8("dd", {
|
|
2034
2291
|
children: row.value
|
|
2035
2292
|
}, undefined, false, undefined, this)
|
|
2036
2293
|
]
|
|
@@ -2038,11 +2295,11 @@ var VoiceTurnQuality = ({
|
|
|
2038
2295
|
}, undefined, false, undefined, this)
|
|
2039
2296
|
]
|
|
2040
2297
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2041
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2298
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
|
|
2042
2299
|
className: "absolute-voice-turn-quality__empty",
|
|
2043
2300
|
children: "Complete a voice turn to see STT quality diagnostics."
|
|
2044
2301
|
}, undefined, false, undefined, this),
|
|
2045
|
-
model.error ? /* @__PURE__ */
|
|
2302
|
+
model.error ? /* @__PURE__ */ jsxDEV8("p", {
|
|
2046
2303
|
className: "absolute-voice-turn-quality__error",
|
|
2047
2304
|
children: model.error
|
|
2048
2305
|
}, undefined, false, undefined, this) : null
|
|
@@ -2050,7 +2307,7 @@ var VoiceTurnQuality = ({
|
|
|
2050
2307
|
}, undefined, true, undefined, this);
|
|
2051
2308
|
};
|
|
2052
2309
|
// src/react/useVoiceStream.tsx
|
|
2053
|
-
import { useEffect as
|
|
2310
|
+
import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
2054
2311
|
|
|
2055
2312
|
// src/client/actions.ts
|
|
2056
2313
|
var normalizeErrorMessage = (value) => {
|
|
@@ -2578,13 +2835,13 @@ var EMPTY_SNAPSHOT = {
|
|
|
2578
2835
|
turns: []
|
|
2579
2836
|
};
|
|
2580
2837
|
var useVoiceStream = (path, options = {}) => {
|
|
2581
|
-
const streamRef =
|
|
2838
|
+
const streamRef = useRef9(null);
|
|
2582
2839
|
if (!streamRef.current) {
|
|
2583
2840
|
streamRef.current = createVoiceStream(path, options);
|
|
2584
2841
|
}
|
|
2585
2842
|
const stream = streamRef.current;
|
|
2586
|
-
|
|
2587
|
-
const snapshot =
|
|
2843
|
+
useEffect9(() => () => stream.close(), [stream]);
|
|
2844
|
+
const snapshot = useSyncExternalStore9(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
|
|
2588
2845
|
return {
|
|
2589
2846
|
...snapshot,
|
|
2590
2847
|
callControl: (message) => stream.callControl(message),
|
|
@@ -2594,7 +2851,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
2594
2851
|
};
|
|
2595
2852
|
};
|
|
2596
2853
|
// src/react/useVoiceController.tsx
|
|
2597
|
-
import { useEffect as
|
|
2854
|
+
import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
2598
2855
|
|
|
2599
2856
|
// src/client/htmx.ts
|
|
2600
2857
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -3247,13 +3504,13 @@ var EMPTY_SNAPSHOT2 = {
|
|
|
3247
3504
|
turns: []
|
|
3248
3505
|
};
|
|
3249
3506
|
var useVoiceController = (path, options = {}) => {
|
|
3250
|
-
const controllerRef =
|
|
3507
|
+
const controllerRef = useRef10(null);
|
|
3251
3508
|
if (!controllerRef.current) {
|
|
3252
3509
|
controllerRef.current = createVoiceController(path, options);
|
|
3253
3510
|
}
|
|
3254
3511
|
const controller = controllerRef.current;
|
|
3255
|
-
|
|
3256
|
-
const snapshot =
|
|
3512
|
+
useEffect10(() => () => controller.close(), [controller]);
|
|
3513
|
+
const snapshot = useSyncExternalStore10(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
|
|
3257
3514
|
return {
|
|
3258
3515
|
...snapshot,
|
|
3259
3516
|
bindHTMX: controller.bindHTMX,
|
|
@@ -3267,7 +3524,7 @@ var useVoiceController = (path, options = {}) => {
|
|
|
3267
3524
|
};
|
|
3268
3525
|
};
|
|
3269
3526
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
3270
|
-
import { useEffect as
|
|
3527
|
+
import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
3271
3528
|
|
|
3272
3529
|
// src/client/workflowStatus.ts
|
|
3273
3530
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -3350,23 +3607,24 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
3350
3607
|
|
|
3351
3608
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
3352
3609
|
var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
|
|
3353
|
-
const storeRef =
|
|
3610
|
+
const storeRef = useRef11(null);
|
|
3354
3611
|
if (!storeRef.current) {
|
|
3355
3612
|
storeRef.current = createVoiceWorkflowStatusStore(path, options);
|
|
3356
3613
|
}
|
|
3357
3614
|
const store = storeRef.current;
|
|
3358
|
-
|
|
3615
|
+
useEffect11(() => {
|
|
3359
3616
|
store.refresh().catch(() => {});
|
|
3360
3617
|
return () => store.close();
|
|
3361
3618
|
}, [store]);
|
|
3362
3619
|
return {
|
|
3363
|
-
...
|
|
3620
|
+
...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
3364
3621
|
refresh: store.refresh
|
|
3365
3622
|
};
|
|
3366
3623
|
};
|
|
3367
3624
|
export {
|
|
3368
3625
|
useVoiceWorkflowStatus,
|
|
3369
3626
|
useVoiceTurnQuality,
|
|
3627
|
+
useVoiceTurnLatency,
|
|
3370
3628
|
useVoiceTraceTimeline,
|
|
3371
3629
|
useVoiceStream,
|
|
3372
3630
|
useVoiceRoutingStatus,
|
|
@@ -3376,6 +3634,7 @@ export {
|
|
|
3376
3634
|
useVoiceController,
|
|
3377
3635
|
useVoiceAppKitStatus,
|
|
3378
3636
|
VoiceTurnQuality,
|
|
3637
|
+
VoiceTurnLatency,
|
|
3379
3638
|
VoiceTraceTimeline,
|
|
3380
3639
|
VoiceRoutingStatus,
|
|
3381
3640
|
VoiceProviderStatus,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VoiceTurnLatencyClientOptions } from '../client/turnLatency';
|
|
2
|
+
export declare const useVoiceTurnLatency: (path?: string, options?: VoiceTurnLatencyClientOptions) => {
|
|
3
|
+
refresh: () => Promise<import("..").VoiceTurnLatencyReport | undefined>;
|
|
4
|
+
error: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
report?: import("..").VoiceTurnLatencyReport;
|
|
7
|
+
updatedAt?: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type VoiceTurnLatencyWidgetOptions } from '../client/turnLatencyWidget';
|
|
2
|
+
export declare const createVoiceTurnLatency: (path?: string, options?: VoiceTurnLatencyWidgetOptions) => {
|
|
3
|
+
getHTML: () => string;
|
|
4
|
+
getViewModel: () => import("../client").VoiceTurnLatencyViewModel;
|
|
5
|
+
close: () => void;
|
|
6
|
+
getServerSnapshot: () => import("../client").VoiceTurnLatencySnapshot;
|
|
7
|
+
getSnapshot: () => import("../client").VoiceTurnLatencySnapshot;
|
|
8
|
+
refresh: () => Promise<import("..").VoiceTurnLatencyReport | undefined>;
|
|
9
|
+
subscribe: (listener: () => void) => () => void;
|
|
10
|
+
};
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { createVoiceStream } from './createVoiceStream';
|
|
|
6
6
|
export { createVoiceProviderStatus } from './createVoiceProviderStatus';
|
|
7
7
|
export { createVoiceRoutingStatus } from './createVoiceRoutingStatus';
|
|
8
8
|
export { createVoiceTraceTimeline } from './createVoiceTraceTimeline';
|
|
9
|
+
export { createVoiceTurnLatency } from './createVoiceTurnLatency';
|
|
9
10
|
export { createVoiceTurnQuality } from './createVoiceTurnQuality';
|
|
10
11
|
export { createVoiceWorkflowStatus } from './createVoiceWorkflowStatus';
|
|
11
12
|
export { createVoiceController } from '../client/controller';
|