@absolutejs/voice 0.0.22-beta.167 → 0.0.22-beta.169

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.
@@ -1674,9 +1674,306 @@ var VoiceProviderCapabilities = ({
1674
1674
  ]
1675
1675
  }, undefined, true, undefined, this);
1676
1676
  };
1677
- // src/react/useVoiceProviderStatus.tsx
1677
+ // src/react/useVoiceProviderContracts.tsx
1678
1678
  import { useEffect as useEffect6, useRef as useRef6, useSyncExternalStore as useSyncExternalStore6 } from "react";
1679
1679
 
1680
+ // src/client/providerContracts.ts
1681
+ var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
1682
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1683
+ const response = await fetchImpl(path);
1684
+ if (!response.ok) {
1685
+ throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
1686
+ }
1687
+ return await response.json();
1688
+ };
1689
+ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
1690
+ const listeners = new Set;
1691
+ let closed = false;
1692
+ let timer;
1693
+ let snapshot = {
1694
+ error: null,
1695
+ isLoading: false
1696
+ };
1697
+ const emit = () => {
1698
+ for (const listener of listeners) {
1699
+ listener();
1700
+ }
1701
+ };
1702
+ const refresh = async () => {
1703
+ if (closed) {
1704
+ return snapshot.report;
1705
+ }
1706
+ snapshot = { ...snapshot, error: null, isLoading: true };
1707
+ emit();
1708
+ try {
1709
+ const report = await fetchVoiceProviderContracts(path, options);
1710
+ snapshot = {
1711
+ error: null,
1712
+ isLoading: false,
1713
+ report,
1714
+ updatedAt: Date.now()
1715
+ };
1716
+ emit();
1717
+ return report;
1718
+ } catch (error) {
1719
+ snapshot = {
1720
+ ...snapshot,
1721
+ error: error instanceof Error ? error.message : String(error),
1722
+ isLoading: false
1723
+ };
1724
+ emit();
1725
+ throw error;
1726
+ }
1727
+ };
1728
+ const close = () => {
1729
+ closed = true;
1730
+ if (timer) {
1731
+ clearInterval(timer);
1732
+ timer = undefined;
1733
+ }
1734
+ listeners.clear();
1735
+ };
1736
+ if (options.intervalMs && options.intervalMs > 0) {
1737
+ timer = setInterval(() => {
1738
+ refresh().catch(() => {});
1739
+ }, options.intervalMs);
1740
+ }
1741
+ return {
1742
+ close,
1743
+ getServerSnapshot: () => snapshot,
1744
+ getSnapshot: () => snapshot,
1745
+ refresh,
1746
+ subscribe: (listener) => {
1747
+ listeners.add(listener);
1748
+ return () => {
1749
+ listeners.delete(listener);
1750
+ };
1751
+ }
1752
+ };
1753
+ };
1754
+
1755
+ // src/react/useVoiceProviderContracts.tsx
1756
+ var useVoiceProviderContracts = (path = "/api/provider-contracts", options = {}) => {
1757
+ const storeRef = useRef6(null);
1758
+ if (!storeRef.current) {
1759
+ storeRef.current = createVoiceProviderContractsStore(path, options);
1760
+ }
1761
+ const store = storeRef.current;
1762
+ useEffect6(() => {
1763
+ store.refresh().catch(() => {});
1764
+ return () => store.close();
1765
+ }, [store]);
1766
+ return {
1767
+ ...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1768
+ refresh: store.refresh
1769
+ };
1770
+ };
1771
+
1772
+ // src/client/providerContractsWidget.ts
1773
+ var DEFAULT_TITLE5 = "Provider Contracts";
1774
+ var DEFAULT_DESCRIPTION5 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
1775
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1776
+ var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
1777
+ var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1778
+ var contractDetail = (row) => {
1779
+ const failing = row.checks.filter((check) => check.status !== "pass");
1780
+ if (failing.length === 0) {
1781
+ return "Provider contract is production-ready.";
1782
+ }
1783
+ return failing.map((check) => `${check.label}: ${check.detail ?? check.status}`).join(" ");
1784
+ };
1785
+ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
1786
+ const rows = (snapshot.report?.rows ?? []).map((row) => ({
1787
+ ...row,
1788
+ detail: contractDetail(row),
1789
+ label: `${formatProvider2(row.provider)} ${row.kind.toUpperCase()}`,
1790
+ remediations: row.checks.filter((check) => check.status !== "pass" && check.remediation).map((check) => ({
1791
+ detail: check.remediation?.detail ?? "",
1792
+ href: check.remediation?.href,
1793
+ label: check.remediation?.label ?? check.label
1794
+ })),
1795
+ rows: [
1796
+ { label: "Status", value: formatStatus2(row.status) },
1797
+ { label: "Selected", value: row.selected ? "Yes" : "No" },
1798
+ { label: "Configured", value: row.configured ? "Yes" : "No" },
1799
+ {
1800
+ label: "Checks",
1801
+ value: row.checks.map((check) => `${check.label}: ${formatStatus2(check.status)}`).join(", ")
1802
+ }
1803
+ ]
1804
+ }));
1805
+ const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
1806
+ return {
1807
+ description: options.description ?? DEFAULT_DESCRIPTION5,
1808
+ error: snapshot.error,
1809
+ isLoading: snapshot.isLoading,
1810
+ label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
1811
+ rows,
1812
+ status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1813
+ title: options.title ?? DEFAULT_TITLE5,
1814
+ updatedAt: snapshot.updatedAt
1815
+ };
1816
+ };
1817
+ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1818
+ const model = createVoiceProviderContractsViewModel(snapshot, options);
1819
+ const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml6(row.status)}">
1820
+ <header>
1821
+ <strong>${escapeHtml6(row.label)}</strong>
1822
+ <span>${escapeHtml6(formatStatus2(row.status))}</span>
1823
+ </header>
1824
+ <p>${escapeHtml6(row.detail)}</p>
1825
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml6(remediation.href)}">${escapeHtml6(remediation.label)}</a>` : `<strong>${escapeHtml6(remediation.label)}</strong>`}<span>${escapeHtml6(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
1826
+ <dl>${row.rows.map((item) => `<div>
1827
+ <dt>${escapeHtml6(item.label)}</dt>
1828
+ <dd>${escapeHtml6(item.value)}</dd>
1829
+ </div>`).join("")}</dl>
1830
+ </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
1831
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml6(model.status)}">
1832
+ <header class="absolute-voice-provider-contracts__header">
1833
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml6(model.title)}</span>
1834
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml6(model.label)}</strong>
1835
+ </header>
1836
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml6(model.description)}</p>
1837
+ ${rows}
1838
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
1839
+ </section>`;
1840
+ };
1841
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1842
+ var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
1843
+ const store = createVoiceProviderContractsStore(path, options);
1844
+ const render = () => {
1845
+ element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
1846
+ };
1847
+ const unsubscribe = store.subscribe(render);
1848
+ render();
1849
+ store.refresh().catch(() => {});
1850
+ return {
1851
+ close: () => {
1852
+ unsubscribe();
1853
+ store.close();
1854
+ },
1855
+ refresh: store.refresh
1856
+ };
1857
+ };
1858
+ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
1859
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
1860
+ return;
1861
+ }
1862
+ customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
1863
+ mounted;
1864
+ connectedCallback() {
1865
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
1866
+ this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
1867
+ description: this.getAttribute("description") ?? undefined,
1868
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
1869
+ title: this.getAttribute("title") ?? undefined
1870
+ });
1871
+ }
1872
+ disconnectedCallback() {
1873
+ this.mounted?.close();
1874
+ this.mounted = undefined;
1875
+ }
1876
+ });
1877
+ };
1878
+
1879
+ // src/react/VoiceProviderContracts.tsx
1880
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
1881
+ var VoiceProviderContracts = ({
1882
+ className,
1883
+ path = "/api/provider-contracts",
1884
+ ...options
1885
+ }) => {
1886
+ const snapshot = useVoiceProviderContracts(path, options);
1887
+ const model = createVoiceProviderContractsViewModel(snapshot, options);
1888
+ return /* @__PURE__ */ jsxDEV6("section", {
1889
+ className: [
1890
+ "absolute-voice-provider-contracts",
1891
+ `absolute-voice-provider-contracts--${model.status}`,
1892
+ className
1893
+ ].filter(Boolean).join(" "),
1894
+ children: [
1895
+ /* @__PURE__ */ jsxDEV6("header", {
1896
+ className: "absolute-voice-provider-contracts__header",
1897
+ children: [
1898
+ /* @__PURE__ */ jsxDEV6("span", {
1899
+ className: "absolute-voice-provider-contracts__eyebrow",
1900
+ children: model.title
1901
+ }, undefined, false, undefined, this),
1902
+ /* @__PURE__ */ jsxDEV6("strong", {
1903
+ className: "absolute-voice-provider-contracts__label",
1904
+ children: model.label
1905
+ }, undefined, false, undefined, this)
1906
+ ]
1907
+ }, undefined, true, undefined, this),
1908
+ /* @__PURE__ */ jsxDEV6("p", {
1909
+ className: "absolute-voice-provider-contracts__description",
1910
+ children: model.description
1911
+ }, undefined, false, undefined, this),
1912
+ model.rows.length ? /* @__PURE__ */ jsxDEV6("div", {
1913
+ className: "absolute-voice-provider-contracts__rows",
1914
+ children: model.rows.map((row) => /* @__PURE__ */ jsxDEV6("article", {
1915
+ className: [
1916
+ "absolute-voice-provider-contracts__row",
1917
+ `absolute-voice-provider-contracts__row--${row.status}`
1918
+ ].join(" "),
1919
+ children: [
1920
+ /* @__PURE__ */ jsxDEV6("header", {
1921
+ children: [
1922
+ /* @__PURE__ */ jsxDEV6("strong", {
1923
+ children: row.label
1924
+ }, undefined, false, undefined, this),
1925
+ /* @__PURE__ */ jsxDEV6("span", {
1926
+ children: row.status
1927
+ }, undefined, false, undefined, this)
1928
+ ]
1929
+ }, undefined, true, undefined, this),
1930
+ /* @__PURE__ */ jsxDEV6("p", {
1931
+ children: row.detail
1932
+ }, undefined, false, undefined, this),
1933
+ row.remediations.length ? /* @__PURE__ */ jsxDEV6("ul", {
1934
+ className: "absolute-voice-provider-contracts__remediations",
1935
+ children: row.remediations.map((remediation) => /* @__PURE__ */ jsxDEV6("li", {
1936
+ children: [
1937
+ remediation.href ? /* @__PURE__ */ jsxDEV6("a", {
1938
+ href: remediation.href,
1939
+ children: remediation.label
1940
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("strong", {
1941
+ children: remediation.label
1942
+ }, undefined, false, undefined, this),
1943
+ /* @__PURE__ */ jsxDEV6("span", {
1944
+ children: remediation.detail
1945
+ }, undefined, false, undefined, this)
1946
+ ]
1947
+ }, `${row.kind}:${row.provider}:${remediation.label}`, true, undefined, this))
1948
+ }, undefined, false, undefined, this) : null,
1949
+ /* @__PURE__ */ jsxDEV6("dl", {
1950
+ children: row.rows.map((item) => /* @__PURE__ */ jsxDEV6("div", {
1951
+ children: [
1952
+ /* @__PURE__ */ jsxDEV6("dt", {
1953
+ children: item.label
1954
+ }, undefined, false, undefined, this),
1955
+ /* @__PURE__ */ jsxDEV6("dd", {
1956
+ children: item.value
1957
+ }, undefined, false, undefined, this)
1958
+ ]
1959
+ }, item.label, true, undefined, this))
1960
+ }, undefined, false, undefined, this)
1961
+ ]
1962
+ }, `${row.kind}:${row.provider}`, true, undefined, this))
1963
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
1964
+ className: "absolute-voice-provider-contracts__empty",
1965
+ children: "Configure provider contracts to see production coverage."
1966
+ }, undefined, false, undefined, this),
1967
+ model.error ? /* @__PURE__ */ jsxDEV6("p", {
1968
+ className: "absolute-voice-provider-contracts__error",
1969
+ children: model.error
1970
+ }, undefined, false, undefined, this) : null
1971
+ ]
1972
+ }, undefined, true, undefined, this);
1973
+ };
1974
+ // src/react/useVoiceProviderStatus.tsx
1975
+ import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
1976
+
1680
1977
  // src/client/providerStatus.ts
1681
1978
  var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1682
1979
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -1759,27 +2056,27 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1759
2056
 
1760
2057
  // src/react/useVoiceProviderStatus.tsx
1761
2058
  var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
1762
- const storeRef = useRef6(null);
2059
+ const storeRef = useRef7(null);
1763
2060
  if (!storeRef.current) {
1764
2061
  storeRef.current = createVoiceProviderStatusStore(path, options);
1765
2062
  }
1766
2063
  const store = storeRef.current;
1767
- useEffect6(() => {
2064
+ useEffect7(() => {
1768
2065
  store.refresh().catch(() => {});
1769
2066
  return () => store.close();
1770
2067
  }, [store]);
1771
2068
  return {
1772
- ...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2069
+ ...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1773
2070
  refresh: store.refresh
1774
2071
  };
1775
2072
  };
1776
2073
 
1777
2074
  // src/client/providerStatusWidget.ts
1778
- var DEFAULT_TITLE5 = "Voice Providers";
1779
- var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
1780
- var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1781
- var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
1782
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
2075
+ var DEFAULT_TITLE6 = "Voice Providers";
2076
+ var DEFAULT_DESCRIPTION6 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
2077
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2078
+ var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
2079
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1783
2080
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
1784
2081
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
1785
2082
  var getProviderDetail = (provider) => {
@@ -1805,7 +2102,7 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
1805
2102
  const providers = snapshot.providers.map((provider) => ({
1806
2103
  ...provider,
1807
2104
  detail: getProviderDetail(provider),
1808
- label: `${formatProvider2(provider.provider)}${provider.recommended ? " recommended" : ""}`,
2105
+ label: `${formatProvider3(provider.provider)}${provider.recommended ? " recommended" : ""}`,
1809
2106
  rows: [
1810
2107
  { label: "Runs", value: String(provider.runCount) },
1811
2108
  { label: "Avg latency", value: formatLatency(provider.averageElapsedMs) },
@@ -1821,37 +2118,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
1821
2118
  const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
1822
2119
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
1823
2120
  return {
1824
- description: options.description ?? DEFAULT_DESCRIPTION5,
2121
+ description: options.description ?? DEFAULT_DESCRIPTION6,
1825
2122
  error: snapshot.error,
1826
2123
  isLoading: snapshot.isLoading,
1827
2124
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
1828
2125
  providers,
1829
2126
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1830
- title: options.title ?? DEFAULT_TITLE5,
2127
+ title: options.title ?? DEFAULT_TITLE6,
1831
2128
  updatedAt: snapshot.updatedAt
1832
2129
  };
1833
2130
  };
1834
2131
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
1835
2132
  const model = createVoiceProviderStatusViewModel(snapshot, options);
1836
- const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml6(provider.status)}">
2133
+ const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml7(provider.status)}">
1837
2134
  <header>
1838
- <strong>${escapeHtml6(provider.label)}</strong>
1839
- <span>${escapeHtml6(formatStatus2(provider.status))}</span>
2135
+ <strong>${escapeHtml7(provider.label)}</strong>
2136
+ <span>${escapeHtml7(formatStatus3(provider.status))}</span>
1840
2137
  </header>
1841
- <p>${escapeHtml6(provider.detail)}</p>
2138
+ <p>${escapeHtml7(provider.detail)}</p>
1842
2139
  <dl>${provider.rows.map((row) => `<div>
1843
- <dt>${escapeHtml6(row.label)}</dt>
1844
- <dd>${escapeHtml6(row.value)}</dd>
2140
+ <dt>${escapeHtml7(row.label)}</dt>
2141
+ <dd>${escapeHtml7(row.value)}</dd>
1845
2142
  </div>`).join("")}</dl>
1846
2143
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
1847
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
2144
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml7(model.status)}">
1848
2145
  <header class="absolute-voice-provider-status__header">
1849
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
1850
- <strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
2146
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml7(model.title)}</span>
2147
+ <strong class="absolute-voice-provider-status__label">${escapeHtml7(model.label)}</strong>
1851
2148
  </header>
1852
- <p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
2149
+ <p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
1853
2150
  ${providers}
1854
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
2151
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
1855
2152
  </section>`;
1856
2153
  };
1857
2154
  var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
@@ -1893,7 +2190,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
1893
2190
  };
1894
2191
 
1895
2192
  // src/react/VoiceProviderStatus.tsx
1896
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2193
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
1897
2194
  var VoiceProviderStatus = ({
1898
2195
  className,
1899
2196
  path = "/api/provider-status",
@@ -1901,58 +2198,58 @@ var VoiceProviderStatus = ({
1901
2198
  }) => {
1902
2199
  const snapshot = useVoiceProviderStatus(path, options);
1903
2200
  const model = createVoiceProviderStatusViewModel(snapshot, options);
1904
- return /* @__PURE__ */ jsxDEV6("section", {
2201
+ return /* @__PURE__ */ jsxDEV7("section", {
1905
2202
  className: [
1906
2203
  "absolute-voice-provider-status",
1907
2204
  `absolute-voice-provider-status--${model.status}`,
1908
2205
  className
1909
2206
  ].filter(Boolean).join(" "),
1910
2207
  children: [
1911
- /* @__PURE__ */ jsxDEV6("header", {
2208
+ /* @__PURE__ */ jsxDEV7("header", {
1912
2209
  className: "absolute-voice-provider-status__header",
1913
2210
  children: [
1914
- /* @__PURE__ */ jsxDEV6("span", {
2211
+ /* @__PURE__ */ jsxDEV7("span", {
1915
2212
  className: "absolute-voice-provider-status__eyebrow",
1916
2213
  children: model.title
1917
2214
  }, undefined, false, undefined, this),
1918
- /* @__PURE__ */ jsxDEV6("strong", {
2215
+ /* @__PURE__ */ jsxDEV7("strong", {
1919
2216
  className: "absolute-voice-provider-status__label",
1920
2217
  children: model.label
1921
2218
  }, undefined, false, undefined, this)
1922
2219
  ]
1923
2220
  }, undefined, true, undefined, this),
1924
- /* @__PURE__ */ jsxDEV6("p", {
2221
+ /* @__PURE__ */ jsxDEV7("p", {
1925
2222
  className: "absolute-voice-provider-status__description",
1926
2223
  children: model.description
1927
2224
  }, undefined, false, undefined, this),
1928
- model.providers.length ? /* @__PURE__ */ jsxDEV6("div", {
2225
+ model.providers.length ? /* @__PURE__ */ jsxDEV7("div", {
1929
2226
  className: "absolute-voice-provider-status__providers",
1930
- children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV6("article", {
2227
+ children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV7("article", {
1931
2228
  className: [
1932
2229
  "absolute-voice-provider-status__provider",
1933
2230
  `absolute-voice-provider-status__provider--${provider.status}`
1934
2231
  ].join(" "),
1935
2232
  children: [
1936
- /* @__PURE__ */ jsxDEV6("header", {
2233
+ /* @__PURE__ */ jsxDEV7("header", {
1937
2234
  children: [
1938
- /* @__PURE__ */ jsxDEV6("strong", {
2235
+ /* @__PURE__ */ jsxDEV7("strong", {
1939
2236
  children: provider.label
1940
2237
  }, undefined, false, undefined, this),
1941
- /* @__PURE__ */ jsxDEV6("span", {
2238
+ /* @__PURE__ */ jsxDEV7("span", {
1942
2239
  children: provider.status
1943
2240
  }, undefined, false, undefined, this)
1944
2241
  ]
1945
2242
  }, undefined, true, undefined, this),
1946
- /* @__PURE__ */ jsxDEV6("p", {
2243
+ /* @__PURE__ */ jsxDEV7("p", {
1947
2244
  children: provider.detail
1948
2245
  }, undefined, false, undefined, this),
1949
- /* @__PURE__ */ jsxDEV6("dl", {
1950
- children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV6("div", {
2246
+ /* @__PURE__ */ jsxDEV7("dl", {
2247
+ children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
1951
2248
  children: [
1952
- /* @__PURE__ */ jsxDEV6("dt", {
2249
+ /* @__PURE__ */ jsxDEV7("dt", {
1953
2250
  children: row.label
1954
2251
  }, undefined, false, undefined, this),
1955
- /* @__PURE__ */ jsxDEV6("dd", {
2252
+ /* @__PURE__ */ jsxDEV7("dd", {
1956
2253
  children: row.value
1957
2254
  }, undefined, false, undefined, this)
1958
2255
  ]
@@ -1960,11 +2257,11 @@ var VoiceProviderStatus = ({
1960
2257
  }, undefined, false, undefined, this)
1961
2258
  ]
1962
2259
  }, provider.provider, true, undefined, this))
1963
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
2260
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
1964
2261
  className: "absolute-voice-provider-status__empty",
1965
2262
  children: "Run voice traffic to see provider health."
1966
2263
  }, undefined, false, undefined, this),
1967
- model.error ? /* @__PURE__ */ jsxDEV6("p", {
2264
+ model.error ? /* @__PURE__ */ jsxDEV7("p", {
1968
2265
  className: "absolute-voice-provider-status__error",
1969
2266
  children: model.error
1970
2267
  }, undefined, false, undefined, this) : null
@@ -1972,7 +2269,7 @@ var VoiceProviderStatus = ({
1972
2269
  }, undefined, true, undefined, this);
1973
2270
  };
1974
2271
  // src/react/useVoiceRoutingStatus.tsx
1975
- import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
2272
+ import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
1976
2273
 
1977
2274
  // src/client/routingStatus.ts
1978
2275
  var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
@@ -2056,25 +2353,25 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
2056
2353
 
2057
2354
  // src/react/useVoiceRoutingStatus.tsx
2058
2355
  var useVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
2059
- const storeRef = useRef7(null);
2356
+ const storeRef = useRef8(null);
2060
2357
  if (!storeRef.current) {
2061
2358
  storeRef.current = createVoiceRoutingStatusStore(path, options);
2062
2359
  }
2063
2360
  const store = storeRef.current;
2064
- useEffect7(() => {
2361
+ useEffect8(() => {
2065
2362
  store.refresh().catch(() => {});
2066
2363
  return () => store.close();
2067
2364
  }, [store]);
2068
2365
  return {
2069
- ...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2366
+ ...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2070
2367
  refresh: store.refresh
2071
2368
  };
2072
2369
  };
2073
2370
 
2074
2371
  // src/client/routingStatusWidget.ts
2075
- var DEFAULT_TITLE6 = "Voice Routing";
2076
- var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
2077
- var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2372
+ var DEFAULT_TITLE7 = "Voice Routing";
2373
+ var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hosted trace store.";
2374
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2078
2375
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
2079
2376
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2080
2377
  const decision = snapshot.decision;
@@ -2098,30 +2395,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2098
2395
  ] : [];
2099
2396
  return {
2100
2397
  decision,
2101
- description: options.description ?? DEFAULT_DESCRIPTION6,
2398
+ description: options.description ?? DEFAULT_DESCRIPTION7,
2102
2399
  error: snapshot.error,
2103
2400
  isLoading: snapshot.isLoading,
2104
2401
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
2105
2402
  rows,
2106
2403
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
2107
- title: options.title ?? DEFAULT_TITLE6,
2404
+ title: options.title ?? DEFAULT_TITLE7,
2108
2405
  updatedAt: snapshot.updatedAt
2109
2406
  };
2110
2407
  };
2111
2408
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
2112
2409
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2113
2410
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
2114
- <span>${escapeHtml7(row.label)}</span>
2115
- <strong>${escapeHtml7(row.value)}</strong>
2411
+ <span>${escapeHtml8(row.label)}</span>
2412
+ <strong>${escapeHtml8(row.value)}</strong>
2116
2413
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
2117
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml7(model.status)}">
2414
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml8(model.status)}">
2118
2415
  <header class="absolute-voice-routing-status__header">
2119
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml7(model.title)}</span>
2120
- <strong class="absolute-voice-routing-status__label">${escapeHtml7(model.label)}</strong>
2416
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml8(model.title)}</span>
2417
+ <strong class="absolute-voice-routing-status__label">${escapeHtml8(model.label)}</strong>
2121
2418
  </header>
2122
- <p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
2419
+ <p class="absolute-voice-routing-status__description">${escapeHtml8(model.description)}</p>
2123
2420
  ${rows}
2124
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
2421
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml8(model.error)}</p>` : ""}
2125
2422
  </section>`;
2126
2423
  };
2127
2424
  var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
@@ -2163,7 +2460,7 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
2163
2460
  };
2164
2461
 
2165
2462
  // src/react/VoiceRoutingStatus.tsx
2166
- import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
2463
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
2167
2464
  var VoiceRoutingStatus = ({
2168
2465
  className,
2169
2466
  path = "/api/routing/latest",
@@ -2171,47 +2468,47 @@ var VoiceRoutingStatus = ({
2171
2468
  }) => {
2172
2469
  const snapshot = useVoiceRoutingStatus(path, options);
2173
2470
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2174
- return /* @__PURE__ */ jsxDEV7("section", {
2471
+ return /* @__PURE__ */ jsxDEV8("section", {
2175
2472
  className: [
2176
2473
  "absolute-voice-routing-status",
2177
2474
  `absolute-voice-routing-status--${model.status}`,
2178
2475
  className
2179
2476
  ].filter(Boolean).join(" "),
2180
2477
  children: [
2181
- /* @__PURE__ */ jsxDEV7("header", {
2478
+ /* @__PURE__ */ jsxDEV8("header", {
2182
2479
  className: "absolute-voice-routing-status__header",
2183
2480
  children: [
2184
- /* @__PURE__ */ jsxDEV7("span", {
2481
+ /* @__PURE__ */ jsxDEV8("span", {
2185
2482
  className: "absolute-voice-routing-status__eyebrow",
2186
2483
  children: model.title
2187
2484
  }, undefined, false, undefined, this),
2188
- /* @__PURE__ */ jsxDEV7("strong", {
2485
+ /* @__PURE__ */ jsxDEV8("strong", {
2189
2486
  className: "absolute-voice-routing-status__label",
2190
2487
  children: model.label
2191
2488
  }, undefined, false, undefined, this)
2192
2489
  ]
2193
2490
  }, undefined, true, undefined, this),
2194
- /* @__PURE__ */ jsxDEV7("p", {
2491
+ /* @__PURE__ */ jsxDEV8("p", {
2195
2492
  className: "absolute-voice-routing-status__description",
2196
2493
  children: model.description
2197
2494
  }, undefined, false, undefined, this),
2198
- model.rows.length ? /* @__PURE__ */ jsxDEV7("div", {
2495
+ model.rows.length ? /* @__PURE__ */ jsxDEV8("div", {
2199
2496
  className: "absolute-voice-routing-status__grid",
2200
- children: model.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
2497
+ children: model.rows.map((row) => /* @__PURE__ */ jsxDEV8("div", {
2201
2498
  children: [
2202
- /* @__PURE__ */ jsxDEV7("span", {
2499
+ /* @__PURE__ */ jsxDEV8("span", {
2203
2500
  children: row.label
2204
2501
  }, undefined, false, undefined, this),
2205
- /* @__PURE__ */ jsxDEV7("strong", {
2502
+ /* @__PURE__ */ jsxDEV8("strong", {
2206
2503
  children: row.value
2207
2504
  }, undefined, false, undefined, this)
2208
2505
  ]
2209
2506
  }, row.label, true, undefined, this))
2210
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
2507
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
2211
2508
  className: "absolute-voice-routing-status__empty",
2212
2509
  children: "Start a voice session to see the selected provider."
2213
2510
  }, undefined, false, undefined, this),
2214
- model.error ? /* @__PURE__ */ jsxDEV7("p", {
2511
+ model.error ? /* @__PURE__ */ jsxDEV8("p", {
2215
2512
  className: "absolute-voice-routing-status__error",
2216
2513
  children: model.error
2217
2514
  }, undefined, false, undefined, this) : null
@@ -2299,9 +2596,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
2299
2596
  };
2300
2597
 
2301
2598
  // src/client/traceTimelineWidget.ts
2302
- var DEFAULT_TITLE7 = "Voice Traces";
2303
- var DEFAULT_DESCRIPTION7 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
2304
- var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2599
+ var DEFAULT_TITLE8 = "Voice Traces";
2600
+ var DEFAULT_DESCRIPTION8 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
2601
+ var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2305
2602
  var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
2306
2603
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
2307
2604
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
@@ -2315,34 +2612,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
2315
2612
  const failed = sessions.filter((session) => session.status === "failed").length;
2316
2613
  const warnings = sessions.filter((session) => session.status === "warning").length;
2317
2614
  return {
2318
- description: options.description ?? DEFAULT_DESCRIPTION7,
2615
+ description: options.description ?? DEFAULT_DESCRIPTION8,
2319
2616
  error: snapshot.error,
2320
2617
  isLoading: snapshot.isLoading,
2321
2618
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
2322
2619
  sessions,
2323
2620
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
2324
- title: options.title ?? DEFAULT_TITLE7,
2621
+ title: options.title ?? DEFAULT_TITLE8,
2325
2622
  updatedAt: snapshot.updatedAt
2326
2623
  };
2327
2624
  };
2328
2625
  var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
2329
2626
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
2330
- const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml8(session.status)}">
2627
+ const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml9(session.status)}">
2331
2628
  <header>
2332
- <strong>${escapeHtml8(session.sessionId)}</strong>
2333
- <span>${escapeHtml8(session.status)}</span>
2629
+ <strong>${escapeHtml9(session.sessionId)}</strong>
2630
+ <span>${escapeHtml9(session.status)}</span>
2334
2631
  </header>
2335
- <p>${escapeHtml8(session.label)} \xB7 ${escapeHtml8(session.durationLabel)} \xB7 ${escapeHtml8(session.providerLabel)}</p>
2336
- <a href="${escapeHtml8(session.detailHref)}">Open timeline</a>
2632
+ <p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
2633
+ <a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
2337
2634
  </article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
2338
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml8(model.status)}">
2635
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
2339
2636
  <header class="absolute-voice-trace-timeline__header">
2340
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml8(model.title)}</span>
2341
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml8(model.label)}</strong>
2637
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
2638
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
2342
2639
  </header>
2343
- <p class="absolute-voice-trace-timeline__description">${escapeHtml8(model.description)}</p>
2640
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
2344
2641
  ${sessions}
2345
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml8(model.error)}</p>` : ""}
2642
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
2346
2643
  </section>`;
2347
2644
  };
2348
2645
  var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
@@ -2387,25 +2684,25 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
2387
2684
  };
2388
2685
 
2389
2686
  // src/react/useVoiceTraceTimeline.tsx
2390
- import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
2687
+ import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
2391
2688
  var useVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
2392
- const storeRef = useRef8(null);
2689
+ const storeRef = useRef9(null);
2393
2690
  if (!storeRef.current) {
2394
2691
  storeRef.current = createVoiceTraceTimelineStore(path, options);
2395
2692
  }
2396
2693
  const store = storeRef.current;
2397
- useEffect8(() => {
2694
+ useEffect9(() => {
2398
2695
  store.refresh().catch(() => {});
2399
2696
  return () => store.close();
2400
2697
  }, [store]);
2401
2698
  return {
2402
- ...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2699
+ ...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2403
2700
  refresh: store.refresh
2404
2701
  };
2405
2702
  };
2406
2703
 
2407
2704
  // src/react/VoiceTraceTimeline.tsx
2408
- import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
2705
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
2409
2706
  var VoiceTraceTimeline = ({
2410
2707
  className,
2411
2708
  path = "/api/voice-traces",
@@ -2413,49 +2710,49 @@ var VoiceTraceTimeline = ({
2413
2710
  }) => {
2414
2711
  const snapshot = useVoiceTraceTimeline(path, options);
2415
2712
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
2416
- return /* @__PURE__ */ jsxDEV8("section", {
2713
+ return /* @__PURE__ */ jsxDEV9("section", {
2417
2714
  className: [
2418
2715
  "absolute-voice-trace-timeline",
2419
2716
  `absolute-voice-trace-timeline--${model.status}`,
2420
2717
  className
2421
2718
  ].filter(Boolean).join(" "),
2422
2719
  children: [
2423
- /* @__PURE__ */ jsxDEV8("header", {
2720
+ /* @__PURE__ */ jsxDEV9("header", {
2424
2721
  className: "absolute-voice-trace-timeline__header",
2425
2722
  children: [
2426
- /* @__PURE__ */ jsxDEV8("span", {
2723
+ /* @__PURE__ */ jsxDEV9("span", {
2427
2724
  className: "absolute-voice-trace-timeline__eyebrow",
2428
2725
  children: model.title
2429
2726
  }, undefined, false, undefined, this),
2430
- /* @__PURE__ */ jsxDEV8("strong", {
2727
+ /* @__PURE__ */ jsxDEV9("strong", {
2431
2728
  className: "absolute-voice-trace-timeline__label",
2432
2729
  children: model.label
2433
2730
  }, undefined, false, undefined, this)
2434
2731
  ]
2435
2732
  }, undefined, true, undefined, this),
2436
- /* @__PURE__ */ jsxDEV8("p", {
2733
+ /* @__PURE__ */ jsxDEV9("p", {
2437
2734
  className: "absolute-voice-trace-timeline__description",
2438
2735
  children: model.description
2439
2736
  }, undefined, false, undefined, this),
2440
- model.sessions.length ? /* @__PURE__ */ jsxDEV8("div", {
2737
+ model.sessions.length ? /* @__PURE__ */ jsxDEV9("div", {
2441
2738
  className: "absolute-voice-trace-timeline__sessions",
2442
- children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV8("article", {
2739
+ children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV9("article", {
2443
2740
  className: [
2444
2741
  "absolute-voice-trace-timeline__session",
2445
2742
  `absolute-voice-trace-timeline__session--${session.status}`
2446
2743
  ].join(" "),
2447
2744
  children: [
2448
- /* @__PURE__ */ jsxDEV8("header", {
2745
+ /* @__PURE__ */ jsxDEV9("header", {
2449
2746
  children: [
2450
- /* @__PURE__ */ jsxDEV8("strong", {
2747
+ /* @__PURE__ */ jsxDEV9("strong", {
2451
2748
  children: session.sessionId
2452
2749
  }, undefined, false, undefined, this),
2453
- /* @__PURE__ */ jsxDEV8("span", {
2750
+ /* @__PURE__ */ jsxDEV9("span", {
2454
2751
  children: session.status
2455
2752
  }, undefined, false, undefined, this)
2456
2753
  ]
2457
2754
  }, undefined, true, undefined, this),
2458
- /* @__PURE__ */ jsxDEV8("p", {
2755
+ /* @__PURE__ */ jsxDEV9("p", {
2459
2756
  children: [
2460
2757
  session.label,
2461
2758
  " \xB7 ",
@@ -2465,17 +2762,17 @@ var VoiceTraceTimeline = ({
2465
2762
  session.providerLabel
2466
2763
  ]
2467
2764
  }, undefined, true, undefined, this),
2468
- /* @__PURE__ */ jsxDEV8("a", {
2765
+ /* @__PURE__ */ jsxDEV9("a", {
2469
2766
  href: session.detailHref,
2470
2767
  children: "Open timeline"
2471
2768
  }, undefined, false, undefined, this)
2472
2769
  ]
2473
2770
  }, session.sessionId, true, undefined, this))
2474
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
2771
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
2475
2772
  className: "absolute-voice-trace-timeline__empty",
2476
2773
  children: "Run a voice session to see call timelines."
2477
2774
  }, undefined, false, undefined, this),
2478
- model.error ? /* @__PURE__ */ jsxDEV8("p", {
2775
+ model.error ? /* @__PURE__ */ jsxDEV9("p", {
2479
2776
  className: "absolute-voice-trace-timeline__error",
2480
2777
  children: model.error
2481
2778
  }, undefined, false, undefined, this) : null
@@ -2483,7 +2780,7 @@ var VoiceTraceTimeline = ({
2483
2780
  }, undefined, true, undefined, this);
2484
2781
  };
2485
2782
  // src/react/useVoiceTurnLatency.tsx
2486
- import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
2783
+ import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
2487
2784
 
2488
2785
  // src/client/turnLatency.ts
2489
2786
  var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
@@ -2590,27 +2887,27 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
2590
2887
 
2591
2888
  // src/react/useVoiceTurnLatency.tsx
2592
2889
  var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
2593
- const storeRef = useRef9(null);
2890
+ const storeRef = useRef10(null);
2594
2891
  if (!storeRef.current) {
2595
2892
  storeRef.current = createVoiceTurnLatencyStore(path, options);
2596
2893
  }
2597
2894
  const store = storeRef.current;
2598
- useEffect9(() => {
2895
+ useEffect10(() => {
2599
2896
  store.refresh().catch(() => {});
2600
2897
  return () => store.close();
2601
2898
  }, [store]);
2602
2899
  return {
2603
- ...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2900
+ ...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2604
2901
  refresh: store.refresh,
2605
2902
  runProof: store.runProof
2606
2903
  };
2607
2904
  };
2608
2905
 
2609
2906
  // src/client/turnLatencyWidget.ts
2610
- var DEFAULT_TITLE8 = "Turn Latency";
2611
- var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
2907
+ var DEFAULT_TITLE9 = "Turn Latency";
2908
+ var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
2612
2909
  var DEFAULT_PROOF_LABEL = "Run latency proof";
2613
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2910
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2614
2911
  var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
2615
2912
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2616
2913
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -2624,39 +2921,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2624
2921
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2625
2922
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2626
2923
  return {
2627
- description: options.description ?? DEFAULT_DESCRIPTION8,
2924
+ description: options.description ?? DEFAULT_DESCRIPTION9,
2628
2925
  error: snapshot.error,
2629
2926
  isLoading: snapshot.isLoading,
2630
2927
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
2631
2928
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
2632
2929
  showProofAction: Boolean(options.proofPath),
2633
2930
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2634
- title: options.title ?? DEFAULT_TITLE8,
2931
+ title: options.title ?? DEFAULT_TITLE9,
2635
2932
  turns,
2636
2933
  updatedAt: snapshot.updatedAt
2637
2934
  };
2638
2935
  };
2639
2936
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
2640
2937
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
2641
- 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--${escapeHtml9(turn.status)}">
2938
+ 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--${escapeHtml10(turn.status)}">
2642
2939
  <header>
2643
- <strong>${escapeHtml9(turn.label)}</strong>
2644
- <span>${escapeHtml9(turn.status)}</span>
2940
+ <strong>${escapeHtml10(turn.label)}</strong>
2941
+ <span>${escapeHtml10(turn.status)}</span>
2645
2942
  </header>
2646
2943
  <dl>${turn.rows.map((row) => `<div>
2647
- <dt>${escapeHtml9(row.label)}</dt>
2648
- <dd>${escapeHtml9(row.value)}</dd>
2944
+ <dt>${escapeHtml10(row.label)}</dt>
2945
+ <dd>${escapeHtml10(row.value)}</dd>
2649
2946
  </div>`).join("")}</dl>
2650
2947
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
2651
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
2948
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
2652
2949
  <header class="absolute-voice-turn-latency__header">
2653
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
2654
- <strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
2950
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
2951
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
2655
2952
  </header>
2656
- <p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
2657
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml9(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
2953
+ <p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
2954
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml10(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
2658
2955
  ${turns}
2659
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
2956
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
2660
2957
  </section>`;
2661
2958
  };
2662
2959
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -2707,7 +3004,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
2707
3004
  };
2708
3005
 
2709
3006
  // src/react/VoiceTurnLatency.tsx
2710
- import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
3007
+ import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
2711
3008
  var VoiceTurnLatency = ({
2712
3009
  className,
2713
3010
  path = "/api/turn-latency",
@@ -2715,31 +3012,31 @@ var VoiceTurnLatency = ({
2715
3012
  }) => {
2716
3013
  const latency = useVoiceTurnLatency(path, options);
2717
3014
  const model = createVoiceTurnLatencyViewModel(latency, options);
2718
- return /* @__PURE__ */ jsxDEV9("section", {
3015
+ return /* @__PURE__ */ jsxDEV10("section", {
2719
3016
  className: [
2720
3017
  "absolute-voice-turn-latency",
2721
3018
  `absolute-voice-turn-latency--${model.status}`,
2722
3019
  className
2723
3020
  ].filter(Boolean).join(" "),
2724
3021
  children: [
2725
- /* @__PURE__ */ jsxDEV9("header", {
3022
+ /* @__PURE__ */ jsxDEV10("header", {
2726
3023
  className: "absolute-voice-turn-latency__header",
2727
3024
  children: [
2728
- /* @__PURE__ */ jsxDEV9("span", {
3025
+ /* @__PURE__ */ jsxDEV10("span", {
2729
3026
  className: "absolute-voice-turn-latency__eyebrow",
2730
3027
  children: model.title
2731
3028
  }, undefined, false, undefined, this),
2732
- /* @__PURE__ */ jsxDEV9("strong", {
3029
+ /* @__PURE__ */ jsxDEV10("strong", {
2733
3030
  className: "absolute-voice-turn-latency__label",
2734
3031
  children: model.label
2735
3032
  }, undefined, false, undefined, this)
2736
3033
  ]
2737
3034
  }, undefined, true, undefined, this),
2738
- /* @__PURE__ */ jsxDEV9("p", {
3035
+ /* @__PURE__ */ jsxDEV10("p", {
2739
3036
  className: "absolute-voice-turn-latency__description",
2740
3037
  children: model.description
2741
3038
  }, undefined, false, undefined, this),
2742
- model.showProofAction ? /* @__PURE__ */ jsxDEV9("button", {
3039
+ model.showProofAction ? /* @__PURE__ */ jsxDEV10("button", {
2743
3040
  className: "absolute-voice-turn-latency__proof",
2744
3041
  onClick: () => {
2745
3042
  latency.runProof().catch(() => {});
@@ -2747,31 +3044,31 @@ var VoiceTurnLatency = ({
2747
3044
  type: "button",
2748
3045
  children: model.proofLabel
2749
3046
  }, undefined, false, undefined, this) : null,
2750
- model.turns.length ? /* @__PURE__ */ jsxDEV9("div", {
3047
+ model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
2751
3048
  className: "absolute-voice-turn-latency__turns",
2752
- children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV9("article", {
3049
+ children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
2753
3050
  className: [
2754
3051
  "absolute-voice-turn-latency__turn",
2755
3052
  `absolute-voice-turn-latency__turn--${turn.status}`
2756
3053
  ].join(" "),
2757
3054
  children: [
2758
- /* @__PURE__ */ jsxDEV9("header", {
3055
+ /* @__PURE__ */ jsxDEV10("header", {
2759
3056
  children: [
2760
- /* @__PURE__ */ jsxDEV9("strong", {
3057
+ /* @__PURE__ */ jsxDEV10("strong", {
2761
3058
  children: turn.label
2762
3059
  }, undefined, false, undefined, this),
2763
- /* @__PURE__ */ jsxDEV9("span", {
3060
+ /* @__PURE__ */ jsxDEV10("span", {
2764
3061
  children: turn.status
2765
3062
  }, undefined, false, undefined, this)
2766
3063
  ]
2767
3064
  }, undefined, true, undefined, this),
2768
- /* @__PURE__ */ jsxDEV9("dl", {
2769
- children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV9("div", {
3065
+ /* @__PURE__ */ jsxDEV10("dl", {
3066
+ children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
2770
3067
  children: [
2771
- /* @__PURE__ */ jsxDEV9("dt", {
3068
+ /* @__PURE__ */ jsxDEV10("dt", {
2772
3069
  children: row.label
2773
3070
  }, undefined, false, undefined, this),
2774
- /* @__PURE__ */ jsxDEV9("dd", {
3071
+ /* @__PURE__ */ jsxDEV10("dd", {
2775
3072
  children: row.value
2776
3073
  }, undefined, false, undefined, this)
2777
3074
  ]
@@ -2779,11 +3076,11 @@ var VoiceTurnLatency = ({
2779
3076
  }, undefined, false, undefined, this)
2780
3077
  ]
2781
3078
  }, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
2782
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
3079
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
2783
3080
  className: "absolute-voice-turn-latency__empty",
2784
3081
  children: "Complete a voice turn to see latency diagnostics."
2785
3082
  }, undefined, false, undefined, this),
2786
- model.error ? /* @__PURE__ */ jsxDEV9("p", {
3083
+ model.error ? /* @__PURE__ */ jsxDEV10("p", {
2787
3084
  className: "absolute-voice-turn-latency__error",
2788
3085
  children: model.error
2789
3086
  }, undefined, false, undefined, this) : null
@@ -2791,7 +3088,7 @@ var VoiceTurnLatency = ({
2791
3088
  }, undefined, true, undefined, this);
2792
3089
  };
2793
3090
  // src/react/useVoiceTurnQuality.tsx
2794
- import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
3091
+ import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
2795
3092
 
2796
3093
  // src/client/turnQuality.ts
2797
3094
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
@@ -2874,25 +3171,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
2874
3171
 
2875
3172
  // src/react/useVoiceTurnQuality.tsx
2876
3173
  var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
2877
- const storeRef = useRef10(null);
3174
+ const storeRef = useRef11(null);
2878
3175
  if (!storeRef.current) {
2879
3176
  storeRef.current = createVoiceTurnQualityStore(path, options);
2880
3177
  }
2881
3178
  const store = storeRef.current;
2882
- useEffect10(() => {
3179
+ useEffect11(() => {
2883
3180
  store.refresh().catch(() => {});
2884
3181
  return () => store.close();
2885
3182
  }, [store]);
2886
3183
  return {
2887
- ...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3184
+ ...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2888
3185
  refresh: store.refresh
2889
3186
  };
2890
3187
  };
2891
3188
 
2892
3189
  // src/client/turnQualityWidget.ts
2893
- var DEFAULT_TITLE9 = "Turn Quality";
2894
- var DEFAULT_DESCRIPTION9 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
2895
- var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3190
+ var DEFAULT_TITLE10 = "Turn Quality";
3191
+ var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3192
+ var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2896
3193
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
2897
3194
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
2898
3195
  var getTurnDetail = (turn) => {
@@ -2930,37 +3227,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
2930
3227
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2931
3228
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2932
3229
  return {
2933
- description: options.description ?? DEFAULT_DESCRIPTION9,
3230
+ description: options.description ?? DEFAULT_DESCRIPTION10,
2934
3231
  error: snapshot.error,
2935
3232
  isLoading: snapshot.isLoading,
2936
3233
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
2937
3234
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2938
- title: options.title ?? DEFAULT_TITLE9,
3235
+ title: options.title ?? DEFAULT_TITLE10,
2939
3236
  turns,
2940
3237
  updatedAt: snapshot.updatedAt
2941
3238
  };
2942
3239
  };
2943
3240
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
2944
3241
  const model = createVoiceTurnQualityViewModel(snapshot, options);
2945
- 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--${escapeHtml10(turn.status)}">
3242
+ 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--${escapeHtml11(turn.status)}">
2946
3243
  <header>
2947
- <strong>${escapeHtml10(turn.label)}</strong>
2948
- <span>${escapeHtml10(turn.status)}</span>
3244
+ <strong>${escapeHtml11(turn.label)}</strong>
3245
+ <span>${escapeHtml11(turn.status)}</span>
2949
3246
  </header>
2950
- <p>${escapeHtml10(turn.detail)}</p>
3247
+ <p>${escapeHtml11(turn.detail)}</p>
2951
3248
  <dl>${turn.rows.map((row) => `<div>
2952
- <dt>${escapeHtml10(row.label)}</dt>
2953
- <dd>${escapeHtml10(row.value)}</dd>
3249
+ <dt>${escapeHtml11(row.label)}</dt>
3250
+ <dd>${escapeHtml11(row.value)}</dd>
2954
3251
  </div>`).join("")}</dl>
2955
3252
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
2956
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml10(model.status)}">
3253
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml11(model.status)}">
2957
3254
  <header class="absolute-voice-turn-quality__header">
2958
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml10(model.title)}</span>
2959
- <strong class="absolute-voice-turn-quality__label">${escapeHtml10(model.label)}</strong>
3255
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml11(model.title)}</span>
3256
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml11(model.label)}</strong>
2960
3257
  </header>
2961
- <p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
3258
+ <p class="absolute-voice-turn-quality__description">${escapeHtml11(model.description)}</p>
2962
3259
  ${turns}
2963
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
3260
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml11(model.error)}</p>` : ""}
2964
3261
  </section>`;
2965
3262
  };
2966
3263
  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}`;
@@ -3002,7 +3299,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
3002
3299
  };
3003
3300
 
3004
3301
  // src/react/VoiceTurnQuality.tsx
3005
- import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
3302
+ import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
3006
3303
  var VoiceTurnQuality = ({
3007
3304
  className,
3008
3305
  path = "/api/turn-quality",
@@ -3010,58 +3307,58 @@ var VoiceTurnQuality = ({
3010
3307
  }) => {
3011
3308
  const snapshot = useVoiceTurnQuality(path, options);
3012
3309
  const model = createVoiceTurnQualityViewModel(snapshot, options);
3013
- return /* @__PURE__ */ jsxDEV10("section", {
3310
+ return /* @__PURE__ */ jsxDEV11("section", {
3014
3311
  className: [
3015
3312
  "absolute-voice-turn-quality",
3016
3313
  `absolute-voice-turn-quality--${model.status}`,
3017
3314
  className
3018
3315
  ].filter(Boolean).join(" "),
3019
3316
  children: [
3020
- /* @__PURE__ */ jsxDEV10("header", {
3317
+ /* @__PURE__ */ jsxDEV11("header", {
3021
3318
  className: "absolute-voice-turn-quality__header",
3022
3319
  children: [
3023
- /* @__PURE__ */ jsxDEV10("span", {
3320
+ /* @__PURE__ */ jsxDEV11("span", {
3024
3321
  className: "absolute-voice-turn-quality__eyebrow",
3025
3322
  children: model.title
3026
3323
  }, undefined, false, undefined, this),
3027
- /* @__PURE__ */ jsxDEV10("strong", {
3324
+ /* @__PURE__ */ jsxDEV11("strong", {
3028
3325
  className: "absolute-voice-turn-quality__label",
3029
3326
  children: model.label
3030
3327
  }, undefined, false, undefined, this)
3031
3328
  ]
3032
3329
  }, undefined, true, undefined, this),
3033
- /* @__PURE__ */ jsxDEV10("p", {
3330
+ /* @__PURE__ */ jsxDEV11("p", {
3034
3331
  className: "absolute-voice-turn-quality__description",
3035
3332
  children: model.description
3036
3333
  }, undefined, false, undefined, this),
3037
- model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
3334
+ model.turns.length ? /* @__PURE__ */ jsxDEV11("div", {
3038
3335
  className: "absolute-voice-turn-quality__turns",
3039
- children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
3336
+ children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV11("article", {
3040
3337
  className: [
3041
3338
  "absolute-voice-turn-quality__turn",
3042
3339
  `absolute-voice-turn-quality__turn--${turn.status}`
3043
3340
  ].join(" "),
3044
3341
  children: [
3045
- /* @__PURE__ */ jsxDEV10("header", {
3342
+ /* @__PURE__ */ jsxDEV11("header", {
3046
3343
  children: [
3047
- /* @__PURE__ */ jsxDEV10("strong", {
3344
+ /* @__PURE__ */ jsxDEV11("strong", {
3048
3345
  children: turn.label
3049
3346
  }, undefined, false, undefined, this),
3050
- /* @__PURE__ */ jsxDEV10("span", {
3347
+ /* @__PURE__ */ jsxDEV11("span", {
3051
3348
  children: turn.status
3052
3349
  }, undefined, false, undefined, this)
3053
3350
  ]
3054
3351
  }, undefined, true, undefined, this),
3055
- /* @__PURE__ */ jsxDEV10("p", {
3352
+ /* @__PURE__ */ jsxDEV11("p", {
3056
3353
  children: turn.detail
3057
3354
  }, undefined, false, undefined, this),
3058
- /* @__PURE__ */ jsxDEV10("dl", {
3059
- children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
3355
+ /* @__PURE__ */ jsxDEV11("dl", {
3356
+ children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV11("div", {
3060
3357
  children: [
3061
- /* @__PURE__ */ jsxDEV10("dt", {
3358
+ /* @__PURE__ */ jsxDEV11("dt", {
3062
3359
  children: row.label
3063
3360
  }, undefined, false, undefined, this),
3064
- /* @__PURE__ */ jsxDEV10("dd", {
3361
+ /* @__PURE__ */ jsxDEV11("dd", {
3065
3362
  children: row.value
3066
3363
  }, undefined, false, undefined, this)
3067
3364
  ]
@@ -3069,11 +3366,11 @@ var VoiceTurnQuality = ({
3069
3366
  }, undefined, false, undefined, this)
3070
3367
  ]
3071
3368
  }, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
3072
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
3369
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV11("p", {
3073
3370
  className: "absolute-voice-turn-quality__empty",
3074
3371
  children: "Complete a voice turn to see STT quality diagnostics."
3075
3372
  }, undefined, false, undefined, this),
3076
- model.error ? /* @__PURE__ */ jsxDEV10("p", {
3373
+ model.error ? /* @__PURE__ */ jsxDEV11("p", {
3077
3374
  className: "absolute-voice-turn-quality__error",
3078
3375
  children: model.error
3079
3376
  }, undefined, false, undefined, this) : null
@@ -3081,7 +3378,7 @@ var VoiceTurnQuality = ({
3081
3378
  }, undefined, true, undefined, this);
3082
3379
  };
3083
3380
  // src/react/useVoiceCampaignDialerProof.tsx
3084
- import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
3381
+ import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
3085
3382
 
3086
3383
  // src/client/campaignDialerProof.ts
3087
3384
  var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
@@ -3203,23 +3500,23 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
3203
3500
 
3204
3501
  // src/react/useVoiceCampaignDialerProof.tsx
3205
3502
  var useVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3206
- const storeRef = useRef11(null);
3503
+ const storeRef = useRef12(null);
3207
3504
  if (!storeRef.current) {
3208
3505
  storeRef.current = createVoiceCampaignDialerProofStore(path, options);
3209
3506
  }
3210
3507
  const store = storeRef.current;
3211
- useEffect11(() => {
3508
+ useEffect12(() => {
3212
3509
  store.refresh().catch(() => {});
3213
3510
  return () => store.close();
3214
3511
  }, [store]);
3215
3512
  return {
3216
- ...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3513
+ ...useSyncExternalStore12(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3217
3514
  refresh: store.refresh,
3218
3515
  runProof: store.runProof
3219
3516
  };
3220
3517
  };
3221
3518
  // src/react/useVoiceStream.tsx
3222
- import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
3519
+ import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
3223
3520
 
3224
3521
  // src/client/actions.ts
3225
3522
  var normalizeErrorMessage = (value) => {
@@ -3879,13 +4176,13 @@ var EMPTY_SNAPSHOT = {
3879
4176
  turns: []
3880
4177
  };
3881
4178
  var useVoiceStream = (path, options = {}) => {
3882
- const streamRef = useRef12(null);
4179
+ const streamRef = useRef13(null);
3883
4180
  if (!streamRef.current) {
3884
4181
  streamRef.current = createVoiceStream(path, options);
3885
4182
  }
3886
4183
  const stream = streamRef.current;
3887
- useEffect12(() => () => stream.close(), [stream]);
3888
- const snapshot = useSyncExternalStore12(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
4184
+ useEffect13(() => () => stream.close(), [stream]);
4185
+ const snapshot = useSyncExternalStore13(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
3889
4186
  return {
3890
4187
  ...snapshot,
3891
4188
  callControl: (message) => stream.callControl(message),
@@ -3895,7 +4192,7 @@ var useVoiceStream = (path, options = {}) => {
3895
4192
  };
3896
4193
  };
3897
4194
  // src/react/useVoiceController.tsx
3898
- import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
4195
+ import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
3899
4196
 
3900
4197
  // src/client/htmx.ts
3901
4198
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -4558,13 +4855,13 @@ var EMPTY_SNAPSHOT2 = {
4558
4855
  turns: []
4559
4856
  };
4560
4857
  var useVoiceController = (path, options = {}) => {
4561
- const controllerRef = useRef13(null);
4858
+ const controllerRef = useRef14(null);
4562
4859
  if (!controllerRef.current) {
4563
4860
  controllerRef.current = createVoiceController(path, options);
4564
4861
  }
4565
4862
  const controller = controllerRef.current;
4566
- useEffect13(() => () => controller.close(), [controller]);
4567
- const snapshot = useSyncExternalStore13(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
4863
+ useEffect14(() => () => controller.close(), [controller]);
4864
+ const snapshot = useSyncExternalStore14(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
4568
4865
  return {
4569
4866
  ...snapshot,
4570
4867
  bindHTMX: controller.bindHTMX,
@@ -4578,7 +4875,7 @@ var useVoiceController = (path, options = {}) => {
4578
4875
  };
4579
4876
  };
4580
4877
  // src/react/useVoiceWorkflowStatus.tsx
4581
- import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
4878
+ import { useEffect as useEffect15, useRef as useRef15, useSyncExternalStore as useSyncExternalStore15 } from "react";
4582
4879
 
4583
4880
  // src/client/workflowStatus.ts
4584
4881
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -4661,17 +4958,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
4661
4958
 
4662
4959
  // src/react/useVoiceWorkflowStatus.tsx
4663
4960
  var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
4664
- const storeRef = useRef14(null);
4961
+ const storeRef = useRef15(null);
4665
4962
  if (!storeRef.current) {
4666
4963
  storeRef.current = createVoiceWorkflowStatusStore(path, options);
4667
4964
  }
4668
4965
  const store = storeRef.current;
4669
- useEffect14(() => {
4966
+ useEffect15(() => {
4670
4967
  store.refresh().catch(() => {});
4671
4968
  return () => store.close();
4672
4969
  }, [store]);
4673
4970
  return {
4674
- ...useSyncExternalStore14(store.subscribe, store.getSnapshot, store.getServerSnapshot),
4971
+ ...useSyncExternalStore15(store.subscribe, store.getSnapshot, store.getServerSnapshot),
4675
4972
  refresh: store.refresh
4676
4973
  };
4677
4974
  };
@@ -4684,6 +4981,7 @@ export {
4684
4981
  useVoiceRoutingStatus,
4685
4982
  useVoiceProviderStatus,
4686
4983
  useVoiceProviderSimulationControls,
4984
+ useVoiceProviderContracts,
4687
4985
  useVoiceProviderCapabilities,
4688
4986
  useVoiceOpsStatus,
4689
4987
  useVoiceOpsActionCenter,
@@ -4696,6 +4994,7 @@ export {
4696
4994
  VoiceRoutingStatus,
4697
4995
  VoiceProviderStatus,
4698
4996
  VoiceProviderSimulationControls,
4997
+ VoiceProviderContracts,
4699
4998
  VoiceProviderCapabilities,
4700
4999
  VoiceOpsStatus,
4701
5000
  VoiceOpsActionCenter,