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

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,284 @@ 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
+ rows: [
1791
+ { label: "Status", value: formatStatus2(row.status) },
1792
+ { label: "Selected", value: row.selected ? "Yes" : "No" },
1793
+ { label: "Configured", value: row.configured ? "Yes" : "No" },
1794
+ {
1795
+ label: "Checks",
1796
+ value: row.checks.map((check) => `${check.label}: ${formatStatus2(check.status)}`).join(", ")
1797
+ }
1798
+ ]
1799
+ }));
1800
+ const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
1801
+ return {
1802
+ description: options.description ?? DEFAULT_DESCRIPTION5,
1803
+ error: snapshot.error,
1804
+ isLoading: snapshot.isLoading,
1805
+ label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
1806
+ rows,
1807
+ status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1808
+ title: options.title ?? DEFAULT_TITLE5,
1809
+ updatedAt: snapshot.updatedAt
1810
+ };
1811
+ };
1812
+ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1813
+ const model = createVoiceProviderContractsViewModel(snapshot, options);
1814
+ 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)}">
1815
+ <header>
1816
+ <strong>${escapeHtml6(row.label)}</strong>
1817
+ <span>${escapeHtml6(formatStatus2(row.status))}</span>
1818
+ </header>
1819
+ <p>${escapeHtml6(row.detail)}</p>
1820
+ <dl>${row.rows.map((item) => `<div>
1821
+ <dt>${escapeHtml6(item.label)}</dt>
1822
+ <dd>${escapeHtml6(item.value)}</dd>
1823
+ </div>`).join("")}</dl>
1824
+ </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
1825
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml6(model.status)}">
1826
+ <header class="absolute-voice-provider-contracts__header">
1827
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml6(model.title)}</span>
1828
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml6(model.label)}</strong>
1829
+ </header>
1830
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml6(model.description)}</p>
1831
+ ${rows}
1832
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
1833
+ </section>`;
1834
+ };
1835
+ 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__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}`;
1836
+ var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
1837
+ const store = createVoiceProviderContractsStore(path, options);
1838
+ const render = () => {
1839
+ element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
1840
+ };
1841
+ const unsubscribe = store.subscribe(render);
1842
+ render();
1843
+ store.refresh().catch(() => {});
1844
+ return {
1845
+ close: () => {
1846
+ unsubscribe();
1847
+ store.close();
1848
+ },
1849
+ refresh: store.refresh
1850
+ };
1851
+ };
1852
+ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
1853
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
1854
+ return;
1855
+ }
1856
+ customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
1857
+ mounted;
1858
+ connectedCallback() {
1859
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
1860
+ this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
1861
+ description: this.getAttribute("description") ?? undefined,
1862
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
1863
+ title: this.getAttribute("title") ?? undefined
1864
+ });
1865
+ }
1866
+ disconnectedCallback() {
1867
+ this.mounted?.close();
1868
+ this.mounted = undefined;
1869
+ }
1870
+ });
1871
+ };
1872
+
1873
+ // src/react/VoiceProviderContracts.tsx
1874
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
1875
+ var VoiceProviderContracts = ({
1876
+ className,
1877
+ path = "/api/provider-contracts",
1878
+ ...options
1879
+ }) => {
1880
+ const snapshot = useVoiceProviderContracts(path, options);
1881
+ const model = createVoiceProviderContractsViewModel(snapshot, options);
1882
+ return /* @__PURE__ */ jsxDEV6("section", {
1883
+ className: [
1884
+ "absolute-voice-provider-contracts",
1885
+ `absolute-voice-provider-contracts--${model.status}`,
1886
+ className
1887
+ ].filter(Boolean).join(" "),
1888
+ children: [
1889
+ /* @__PURE__ */ jsxDEV6("header", {
1890
+ className: "absolute-voice-provider-contracts__header",
1891
+ children: [
1892
+ /* @__PURE__ */ jsxDEV6("span", {
1893
+ className: "absolute-voice-provider-contracts__eyebrow",
1894
+ children: model.title
1895
+ }, undefined, false, undefined, this),
1896
+ /* @__PURE__ */ jsxDEV6("strong", {
1897
+ className: "absolute-voice-provider-contracts__label",
1898
+ children: model.label
1899
+ }, undefined, false, undefined, this)
1900
+ ]
1901
+ }, undefined, true, undefined, this),
1902
+ /* @__PURE__ */ jsxDEV6("p", {
1903
+ className: "absolute-voice-provider-contracts__description",
1904
+ children: model.description
1905
+ }, undefined, false, undefined, this),
1906
+ model.rows.length ? /* @__PURE__ */ jsxDEV6("div", {
1907
+ className: "absolute-voice-provider-contracts__rows",
1908
+ children: model.rows.map((row) => /* @__PURE__ */ jsxDEV6("article", {
1909
+ className: [
1910
+ "absolute-voice-provider-contracts__row",
1911
+ `absolute-voice-provider-contracts__row--${row.status}`
1912
+ ].join(" "),
1913
+ children: [
1914
+ /* @__PURE__ */ jsxDEV6("header", {
1915
+ children: [
1916
+ /* @__PURE__ */ jsxDEV6("strong", {
1917
+ children: row.label
1918
+ }, undefined, false, undefined, this),
1919
+ /* @__PURE__ */ jsxDEV6("span", {
1920
+ children: row.status
1921
+ }, undefined, false, undefined, this)
1922
+ ]
1923
+ }, undefined, true, undefined, this),
1924
+ /* @__PURE__ */ jsxDEV6("p", {
1925
+ children: row.detail
1926
+ }, undefined, false, undefined, this),
1927
+ /* @__PURE__ */ jsxDEV6("dl", {
1928
+ children: row.rows.map((item) => /* @__PURE__ */ jsxDEV6("div", {
1929
+ children: [
1930
+ /* @__PURE__ */ jsxDEV6("dt", {
1931
+ children: item.label
1932
+ }, undefined, false, undefined, this),
1933
+ /* @__PURE__ */ jsxDEV6("dd", {
1934
+ children: item.value
1935
+ }, undefined, false, undefined, this)
1936
+ ]
1937
+ }, item.label, true, undefined, this))
1938
+ }, undefined, false, undefined, this)
1939
+ ]
1940
+ }, `${row.kind}:${row.provider}`, true, undefined, this))
1941
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
1942
+ className: "absolute-voice-provider-contracts__empty",
1943
+ children: "Configure provider contracts to see production coverage."
1944
+ }, undefined, false, undefined, this),
1945
+ model.error ? /* @__PURE__ */ jsxDEV6("p", {
1946
+ className: "absolute-voice-provider-contracts__error",
1947
+ children: model.error
1948
+ }, undefined, false, undefined, this) : null
1949
+ ]
1950
+ }, undefined, true, undefined, this);
1951
+ };
1952
+ // src/react/useVoiceProviderStatus.tsx
1953
+ import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
1954
+
1680
1955
  // src/client/providerStatus.ts
1681
1956
  var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1682
1957
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -1759,27 +2034,27 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1759
2034
 
1760
2035
  // src/react/useVoiceProviderStatus.tsx
1761
2036
  var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
1762
- const storeRef = useRef6(null);
2037
+ const storeRef = useRef7(null);
1763
2038
  if (!storeRef.current) {
1764
2039
  storeRef.current = createVoiceProviderStatusStore(path, options);
1765
2040
  }
1766
2041
  const store = storeRef.current;
1767
- useEffect6(() => {
2042
+ useEffect7(() => {
1768
2043
  store.refresh().catch(() => {});
1769
2044
  return () => store.close();
1770
2045
  }, [store]);
1771
2046
  return {
1772
- ...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2047
+ ...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1773
2048
  refresh: store.refresh
1774
2049
  };
1775
2050
  };
1776
2051
 
1777
2052
  // 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(" ");
2053
+ var DEFAULT_TITLE6 = "Voice Providers";
2054
+ var DEFAULT_DESCRIPTION6 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
2055
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2056
+ var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
2057
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1783
2058
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
1784
2059
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
1785
2060
  var getProviderDetail = (provider) => {
@@ -1805,7 +2080,7 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
1805
2080
  const providers = snapshot.providers.map((provider) => ({
1806
2081
  ...provider,
1807
2082
  detail: getProviderDetail(provider),
1808
- label: `${formatProvider2(provider.provider)}${provider.recommended ? " recommended" : ""}`,
2083
+ label: `${formatProvider3(provider.provider)}${provider.recommended ? " recommended" : ""}`,
1809
2084
  rows: [
1810
2085
  { label: "Runs", value: String(provider.runCount) },
1811
2086
  { label: "Avg latency", value: formatLatency(provider.averageElapsedMs) },
@@ -1821,37 +2096,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
1821
2096
  const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
1822
2097
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
1823
2098
  return {
1824
- description: options.description ?? DEFAULT_DESCRIPTION5,
2099
+ description: options.description ?? DEFAULT_DESCRIPTION6,
1825
2100
  error: snapshot.error,
1826
2101
  isLoading: snapshot.isLoading,
1827
2102
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
1828
2103
  providers,
1829
2104
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1830
- title: options.title ?? DEFAULT_TITLE5,
2105
+ title: options.title ?? DEFAULT_TITLE6,
1831
2106
  updatedAt: snapshot.updatedAt
1832
2107
  };
1833
2108
  };
1834
2109
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
1835
2110
  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)}">
2111
+ 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
2112
  <header>
1838
- <strong>${escapeHtml6(provider.label)}</strong>
1839
- <span>${escapeHtml6(formatStatus2(provider.status))}</span>
2113
+ <strong>${escapeHtml7(provider.label)}</strong>
2114
+ <span>${escapeHtml7(formatStatus3(provider.status))}</span>
1840
2115
  </header>
1841
- <p>${escapeHtml6(provider.detail)}</p>
2116
+ <p>${escapeHtml7(provider.detail)}</p>
1842
2117
  <dl>${provider.rows.map((row) => `<div>
1843
- <dt>${escapeHtml6(row.label)}</dt>
1844
- <dd>${escapeHtml6(row.value)}</dd>
2118
+ <dt>${escapeHtml7(row.label)}</dt>
2119
+ <dd>${escapeHtml7(row.value)}</dd>
1845
2120
  </div>`).join("")}</dl>
1846
2121
  </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)}">
2122
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml7(model.status)}">
1848
2123
  <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>
2124
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml7(model.title)}</span>
2125
+ <strong class="absolute-voice-provider-status__label">${escapeHtml7(model.label)}</strong>
1851
2126
  </header>
1852
- <p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
2127
+ <p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
1853
2128
  ${providers}
1854
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
2129
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
1855
2130
  </section>`;
1856
2131
  };
1857
2132
  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 +2168,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
1893
2168
  };
1894
2169
 
1895
2170
  // src/react/VoiceProviderStatus.tsx
1896
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2171
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
1897
2172
  var VoiceProviderStatus = ({
1898
2173
  className,
1899
2174
  path = "/api/provider-status",
@@ -1901,58 +2176,58 @@ var VoiceProviderStatus = ({
1901
2176
  }) => {
1902
2177
  const snapshot = useVoiceProviderStatus(path, options);
1903
2178
  const model = createVoiceProviderStatusViewModel(snapshot, options);
1904
- return /* @__PURE__ */ jsxDEV6("section", {
2179
+ return /* @__PURE__ */ jsxDEV7("section", {
1905
2180
  className: [
1906
2181
  "absolute-voice-provider-status",
1907
2182
  `absolute-voice-provider-status--${model.status}`,
1908
2183
  className
1909
2184
  ].filter(Boolean).join(" "),
1910
2185
  children: [
1911
- /* @__PURE__ */ jsxDEV6("header", {
2186
+ /* @__PURE__ */ jsxDEV7("header", {
1912
2187
  className: "absolute-voice-provider-status__header",
1913
2188
  children: [
1914
- /* @__PURE__ */ jsxDEV6("span", {
2189
+ /* @__PURE__ */ jsxDEV7("span", {
1915
2190
  className: "absolute-voice-provider-status__eyebrow",
1916
2191
  children: model.title
1917
2192
  }, undefined, false, undefined, this),
1918
- /* @__PURE__ */ jsxDEV6("strong", {
2193
+ /* @__PURE__ */ jsxDEV7("strong", {
1919
2194
  className: "absolute-voice-provider-status__label",
1920
2195
  children: model.label
1921
2196
  }, undefined, false, undefined, this)
1922
2197
  ]
1923
2198
  }, undefined, true, undefined, this),
1924
- /* @__PURE__ */ jsxDEV6("p", {
2199
+ /* @__PURE__ */ jsxDEV7("p", {
1925
2200
  className: "absolute-voice-provider-status__description",
1926
2201
  children: model.description
1927
2202
  }, undefined, false, undefined, this),
1928
- model.providers.length ? /* @__PURE__ */ jsxDEV6("div", {
2203
+ model.providers.length ? /* @__PURE__ */ jsxDEV7("div", {
1929
2204
  className: "absolute-voice-provider-status__providers",
1930
- children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV6("article", {
2205
+ children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV7("article", {
1931
2206
  className: [
1932
2207
  "absolute-voice-provider-status__provider",
1933
2208
  `absolute-voice-provider-status__provider--${provider.status}`
1934
2209
  ].join(" "),
1935
2210
  children: [
1936
- /* @__PURE__ */ jsxDEV6("header", {
2211
+ /* @__PURE__ */ jsxDEV7("header", {
1937
2212
  children: [
1938
- /* @__PURE__ */ jsxDEV6("strong", {
2213
+ /* @__PURE__ */ jsxDEV7("strong", {
1939
2214
  children: provider.label
1940
2215
  }, undefined, false, undefined, this),
1941
- /* @__PURE__ */ jsxDEV6("span", {
2216
+ /* @__PURE__ */ jsxDEV7("span", {
1942
2217
  children: provider.status
1943
2218
  }, undefined, false, undefined, this)
1944
2219
  ]
1945
2220
  }, undefined, true, undefined, this),
1946
- /* @__PURE__ */ jsxDEV6("p", {
2221
+ /* @__PURE__ */ jsxDEV7("p", {
1947
2222
  children: provider.detail
1948
2223
  }, undefined, false, undefined, this),
1949
- /* @__PURE__ */ jsxDEV6("dl", {
1950
- children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV6("div", {
2224
+ /* @__PURE__ */ jsxDEV7("dl", {
2225
+ children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
1951
2226
  children: [
1952
- /* @__PURE__ */ jsxDEV6("dt", {
2227
+ /* @__PURE__ */ jsxDEV7("dt", {
1953
2228
  children: row.label
1954
2229
  }, undefined, false, undefined, this),
1955
- /* @__PURE__ */ jsxDEV6("dd", {
2230
+ /* @__PURE__ */ jsxDEV7("dd", {
1956
2231
  children: row.value
1957
2232
  }, undefined, false, undefined, this)
1958
2233
  ]
@@ -1960,11 +2235,11 @@ var VoiceProviderStatus = ({
1960
2235
  }, undefined, false, undefined, this)
1961
2236
  ]
1962
2237
  }, provider.provider, true, undefined, this))
1963
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
2238
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
1964
2239
  className: "absolute-voice-provider-status__empty",
1965
2240
  children: "Run voice traffic to see provider health."
1966
2241
  }, undefined, false, undefined, this),
1967
- model.error ? /* @__PURE__ */ jsxDEV6("p", {
2242
+ model.error ? /* @__PURE__ */ jsxDEV7("p", {
1968
2243
  className: "absolute-voice-provider-status__error",
1969
2244
  children: model.error
1970
2245
  }, undefined, false, undefined, this) : null
@@ -1972,7 +2247,7 @@ var VoiceProviderStatus = ({
1972
2247
  }, undefined, true, undefined, this);
1973
2248
  };
1974
2249
  // src/react/useVoiceRoutingStatus.tsx
1975
- import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
2250
+ import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
1976
2251
 
1977
2252
  // src/client/routingStatus.ts
1978
2253
  var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
@@ -2056,25 +2331,25 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
2056
2331
 
2057
2332
  // src/react/useVoiceRoutingStatus.tsx
2058
2333
  var useVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
2059
- const storeRef = useRef7(null);
2334
+ const storeRef = useRef8(null);
2060
2335
  if (!storeRef.current) {
2061
2336
  storeRef.current = createVoiceRoutingStatusStore(path, options);
2062
2337
  }
2063
2338
  const store = storeRef.current;
2064
- useEffect7(() => {
2339
+ useEffect8(() => {
2065
2340
  store.refresh().catch(() => {});
2066
2341
  return () => store.close();
2067
2342
  }, [store]);
2068
2343
  return {
2069
- ...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2344
+ ...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2070
2345
  refresh: store.refresh
2071
2346
  };
2072
2347
  };
2073
2348
 
2074
2349
  // 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;");
2350
+ var DEFAULT_TITLE7 = "Voice Routing";
2351
+ var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hosted trace store.";
2352
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2078
2353
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
2079
2354
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2080
2355
  const decision = snapshot.decision;
@@ -2098,30 +2373,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2098
2373
  ] : [];
2099
2374
  return {
2100
2375
  decision,
2101
- description: options.description ?? DEFAULT_DESCRIPTION6,
2376
+ description: options.description ?? DEFAULT_DESCRIPTION7,
2102
2377
  error: snapshot.error,
2103
2378
  isLoading: snapshot.isLoading,
2104
2379
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
2105
2380
  rows,
2106
2381
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
2107
- title: options.title ?? DEFAULT_TITLE6,
2382
+ title: options.title ?? DEFAULT_TITLE7,
2108
2383
  updatedAt: snapshot.updatedAt
2109
2384
  };
2110
2385
  };
2111
2386
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
2112
2387
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2113
2388
  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>
2389
+ <span>${escapeHtml8(row.label)}</span>
2390
+ <strong>${escapeHtml8(row.value)}</strong>
2116
2391
  </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)}">
2392
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml8(model.status)}">
2118
2393
  <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>
2394
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml8(model.title)}</span>
2395
+ <strong class="absolute-voice-routing-status__label">${escapeHtml8(model.label)}</strong>
2121
2396
  </header>
2122
- <p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
2397
+ <p class="absolute-voice-routing-status__description">${escapeHtml8(model.description)}</p>
2123
2398
  ${rows}
2124
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
2399
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml8(model.error)}</p>` : ""}
2125
2400
  </section>`;
2126
2401
  };
2127
2402
  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 +2438,7 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
2163
2438
  };
2164
2439
 
2165
2440
  // src/react/VoiceRoutingStatus.tsx
2166
- import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
2441
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
2167
2442
  var VoiceRoutingStatus = ({
2168
2443
  className,
2169
2444
  path = "/api/routing/latest",
@@ -2171,47 +2446,47 @@ var VoiceRoutingStatus = ({
2171
2446
  }) => {
2172
2447
  const snapshot = useVoiceRoutingStatus(path, options);
2173
2448
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2174
- return /* @__PURE__ */ jsxDEV7("section", {
2449
+ return /* @__PURE__ */ jsxDEV8("section", {
2175
2450
  className: [
2176
2451
  "absolute-voice-routing-status",
2177
2452
  `absolute-voice-routing-status--${model.status}`,
2178
2453
  className
2179
2454
  ].filter(Boolean).join(" "),
2180
2455
  children: [
2181
- /* @__PURE__ */ jsxDEV7("header", {
2456
+ /* @__PURE__ */ jsxDEV8("header", {
2182
2457
  className: "absolute-voice-routing-status__header",
2183
2458
  children: [
2184
- /* @__PURE__ */ jsxDEV7("span", {
2459
+ /* @__PURE__ */ jsxDEV8("span", {
2185
2460
  className: "absolute-voice-routing-status__eyebrow",
2186
2461
  children: model.title
2187
2462
  }, undefined, false, undefined, this),
2188
- /* @__PURE__ */ jsxDEV7("strong", {
2463
+ /* @__PURE__ */ jsxDEV8("strong", {
2189
2464
  className: "absolute-voice-routing-status__label",
2190
2465
  children: model.label
2191
2466
  }, undefined, false, undefined, this)
2192
2467
  ]
2193
2468
  }, undefined, true, undefined, this),
2194
- /* @__PURE__ */ jsxDEV7("p", {
2469
+ /* @__PURE__ */ jsxDEV8("p", {
2195
2470
  className: "absolute-voice-routing-status__description",
2196
2471
  children: model.description
2197
2472
  }, undefined, false, undefined, this),
2198
- model.rows.length ? /* @__PURE__ */ jsxDEV7("div", {
2473
+ model.rows.length ? /* @__PURE__ */ jsxDEV8("div", {
2199
2474
  className: "absolute-voice-routing-status__grid",
2200
- children: model.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
2475
+ children: model.rows.map((row) => /* @__PURE__ */ jsxDEV8("div", {
2201
2476
  children: [
2202
- /* @__PURE__ */ jsxDEV7("span", {
2477
+ /* @__PURE__ */ jsxDEV8("span", {
2203
2478
  children: row.label
2204
2479
  }, undefined, false, undefined, this),
2205
- /* @__PURE__ */ jsxDEV7("strong", {
2480
+ /* @__PURE__ */ jsxDEV8("strong", {
2206
2481
  children: row.value
2207
2482
  }, undefined, false, undefined, this)
2208
2483
  ]
2209
2484
  }, row.label, true, undefined, this))
2210
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
2485
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
2211
2486
  className: "absolute-voice-routing-status__empty",
2212
2487
  children: "Start a voice session to see the selected provider."
2213
2488
  }, undefined, false, undefined, this),
2214
- model.error ? /* @__PURE__ */ jsxDEV7("p", {
2489
+ model.error ? /* @__PURE__ */ jsxDEV8("p", {
2215
2490
  className: "absolute-voice-routing-status__error",
2216
2491
  children: model.error
2217
2492
  }, undefined, false, undefined, this) : null
@@ -2299,9 +2574,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
2299
2574
  };
2300
2575
 
2301
2576
  // 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;");
2577
+ var DEFAULT_TITLE8 = "Voice Traces";
2578
+ var DEFAULT_DESCRIPTION8 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
2579
+ var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2305
2580
  var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
2306
2581
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
2307
2582
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
@@ -2315,34 +2590,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
2315
2590
  const failed = sessions.filter((session) => session.status === "failed").length;
2316
2591
  const warnings = sessions.filter((session) => session.status === "warning").length;
2317
2592
  return {
2318
- description: options.description ?? DEFAULT_DESCRIPTION7,
2593
+ description: options.description ?? DEFAULT_DESCRIPTION8,
2319
2594
  error: snapshot.error,
2320
2595
  isLoading: snapshot.isLoading,
2321
2596
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
2322
2597
  sessions,
2323
2598
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
2324
- title: options.title ?? DEFAULT_TITLE7,
2599
+ title: options.title ?? DEFAULT_TITLE8,
2325
2600
  updatedAt: snapshot.updatedAt
2326
2601
  };
2327
2602
  };
2328
2603
  var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
2329
2604
  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)}">
2605
+ 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
2606
  <header>
2332
- <strong>${escapeHtml8(session.sessionId)}</strong>
2333
- <span>${escapeHtml8(session.status)}</span>
2607
+ <strong>${escapeHtml9(session.sessionId)}</strong>
2608
+ <span>${escapeHtml9(session.status)}</span>
2334
2609
  </header>
2335
- <p>${escapeHtml8(session.label)} \xB7 ${escapeHtml8(session.durationLabel)} \xB7 ${escapeHtml8(session.providerLabel)}</p>
2336
- <a href="${escapeHtml8(session.detailHref)}">Open timeline</a>
2610
+ <p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
2611
+ <a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
2337
2612
  </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)}">
2613
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
2339
2614
  <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>
2615
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
2616
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
2342
2617
  </header>
2343
- <p class="absolute-voice-trace-timeline__description">${escapeHtml8(model.description)}</p>
2618
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
2344
2619
  ${sessions}
2345
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml8(model.error)}</p>` : ""}
2620
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
2346
2621
  </section>`;
2347
2622
  };
2348
2623
  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 +2662,25 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
2387
2662
  };
2388
2663
 
2389
2664
  // src/react/useVoiceTraceTimeline.tsx
2390
- import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
2665
+ import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
2391
2666
  var useVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
2392
- const storeRef = useRef8(null);
2667
+ const storeRef = useRef9(null);
2393
2668
  if (!storeRef.current) {
2394
2669
  storeRef.current = createVoiceTraceTimelineStore(path, options);
2395
2670
  }
2396
2671
  const store = storeRef.current;
2397
- useEffect8(() => {
2672
+ useEffect9(() => {
2398
2673
  store.refresh().catch(() => {});
2399
2674
  return () => store.close();
2400
2675
  }, [store]);
2401
2676
  return {
2402
- ...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2677
+ ...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2403
2678
  refresh: store.refresh
2404
2679
  };
2405
2680
  };
2406
2681
 
2407
2682
  // src/react/VoiceTraceTimeline.tsx
2408
- import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
2683
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
2409
2684
  var VoiceTraceTimeline = ({
2410
2685
  className,
2411
2686
  path = "/api/voice-traces",
@@ -2413,49 +2688,49 @@ var VoiceTraceTimeline = ({
2413
2688
  }) => {
2414
2689
  const snapshot = useVoiceTraceTimeline(path, options);
2415
2690
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
2416
- return /* @__PURE__ */ jsxDEV8("section", {
2691
+ return /* @__PURE__ */ jsxDEV9("section", {
2417
2692
  className: [
2418
2693
  "absolute-voice-trace-timeline",
2419
2694
  `absolute-voice-trace-timeline--${model.status}`,
2420
2695
  className
2421
2696
  ].filter(Boolean).join(" "),
2422
2697
  children: [
2423
- /* @__PURE__ */ jsxDEV8("header", {
2698
+ /* @__PURE__ */ jsxDEV9("header", {
2424
2699
  className: "absolute-voice-trace-timeline__header",
2425
2700
  children: [
2426
- /* @__PURE__ */ jsxDEV8("span", {
2701
+ /* @__PURE__ */ jsxDEV9("span", {
2427
2702
  className: "absolute-voice-trace-timeline__eyebrow",
2428
2703
  children: model.title
2429
2704
  }, undefined, false, undefined, this),
2430
- /* @__PURE__ */ jsxDEV8("strong", {
2705
+ /* @__PURE__ */ jsxDEV9("strong", {
2431
2706
  className: "absolute-voice-trace-timeline__label",
2432
2707
  children: model.label
2433
2708
  }, undefined, false, undefined, this)
2434
2709
  ]
2435
2710
  }, undefined, true, undefined, this),
2436
- /* @__PURE__ */ jsxDEV8("p", {
2711
+ /* @__PURE__ */ jsxDEV9("p", {
2437
2712
  className: "absolute-voice-trace-timeline__description",
2438
2713
  children: model.description
2439
2714
  }, undefined, false, undefined, this),
2440
- model.sessions.length ? /* @__PURE__ */ jsxDEV8("div", {
2715
+ model.sessions.length ? /* @__PURE__ */ jsxDEV9("div", {
2441
2716
  className: "absolute-voice-trace-timeline__sessions",
2442
- children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV8("article", {
2717
+ children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV9("article", {
2443
2718
  className: [
2444
2719
  "absolute-voice-trace-timeline__session",
2445
2720
  `absolute-voice-trace-timeline__session--${session.status}`
2446
2721
  ].join(" "),
2447
2722
  children: [
2448
- /* @__PURE__ */ jsxDEV8("header", {
2723
+ /* @__PURE__ */ jsxDEV9("header", {
2449
2724
  children: [
2450
- /* @__PURE__ */ jsxDEV8("strong", {
2725
+ /* @__PURE__ */ jsxDEV9("strong", {
2451
2726
  children: session.sessionId
2452
2727
  }, undefined, false, undefined, this),
2453
- /* @__PURE__ */ jsxDEV8("span", {
2728
+ /* @__PURE__ */ jsxDEV9("span", {
2454
2729
  children: session.status
2455
2730
  }, undefined, false, undefined, this)
2456
2731
  ]
2457
2732
  }, undefined, true, undefined, this),
2458
- /* @__PURE__ */ jsxDEV8("p", {
2733
+ /* @__PURE__ */ jsxDEV9("p", {
2459
2734
  children: [
2460
2735
  session.label,
2461
2736
  " \xB7 ",
@@ -2465,17 +2740,17 @@ var VoiceTraceTimeline = ({
2465
2740
  session.providerLabel
2466
2741
  ]
2467
2742
  }, undefined, true, undefined, this),
2468
- /* @__PURE__ */ jsxDEV8("a", {
2743
+ /* @__PURE__ */ jsxDEV9("a", {
2469
2744
  href: session.detailHref,
2470
2745
  children: "Open timeline"
2471
2746
  }, undefined, false, undefined, this)
2472
2747
  ]
2473
2748
  }, session.sessionId, true, undefined, this))
2474
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
2749
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
2475
2750
  className: "absolute-voice-trace-timeline__empty",
2476
2751
  children: "Run a voice session to see call timelines."
2477
2752
  }, undefined, false, undefined, this),
2478
- model.error ? /* @__PURE__ */ jsxDEV8("p", {
2753
+ model.error ? /* @__PURE__ */ jsxDEV9("p", {
2479
2754
  className: "absolute-voice-trace-timeline__error",
2480
2755
  children: model.error
2481
2756
  }, undefined, false, undefined, this) : null
@@ -2483,7 +2758,7 @@ var VoiceTraceTimeline = ({
2483
2758
  }, undefined, true, undefined, this);
2484
2759
  };
2485
2760
  // src/react/useVoiceTurnLatency.tsx
2486
- import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
2761
+ import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
2487
2762
 
2488
2763
  // src/client/turnLatency.ts
2489
2764
  var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
@@ -2590,27 +2865,27 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
2590
2865
 
2591
2866
  // src/react/useVoiceTurnLatency.tsx
2592
2867
  var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
2593
- const storeRef = useRef9(null);
2868
+ const storeRef = useRef10(null);
2594
2869
  if (!storeRef.current) {
2595
2870
  storeRef.current = createVoiceTurnLatencyStore(path, options);
2596
2871
  }
2597
2872
  const store = storeRef.current;
2598
- useEffect9(() => {
2873
+ useEffect10(() => {
2599
2874
  store.refresh().catch(() => {});
2600
2875
  return () => store.close();
2601
2876
  }, [store]);
2602
2877
  return {
2603
- ...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2878
+ ...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2604
2879
  refresh: store.refresh,
2605
2880
  runProof: store.runProof
2606
2881
  };
2607
2882
  };
2608
2883
 
2609
2884
  // 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.";
2885
+ var DEFAULT_TITLE9 = "Turn Latency";
2886
+ var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
2612
2887
  var DEFAULT_PROOF_LABEL = "Run latency proof";
2613
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2888
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2614
2889
  var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
2615
2890
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2616
2891
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -2624,39 +2899,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2624
2899
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2625
2900
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2626
2901
  return {
2627
- description: options.description ?? DEFAULT_DESCRIPTION8,
2902
+ description: options.description ?? DEFAULT_DESCRIPTION9,
2628
2903
  error: snapshot.error,
2629
2904
  isLoading: snapshot.isLoading,
2630
2905
  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
2906
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
2632
2907
  showProofAction: Boolean(options.proofPath),
2633
2908
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2634
- title: options.title ?? DEFAULT_TITLE8,
2909
+ title: options.title ?? DEFAULT_TITLE9,
2635
2910
  turns,
2636
2911
  updatedAt: snapshot.updatedAt
2637
2912
  };
2638
2913
  };
2639
2914
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
2640
2915
  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)}">
2916
+ 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
2917
  <header>
2643
- <strong>${escapeHtml9(turn.label)}</strong>
2644
- <span>${escapeHtml9(turn.status)}</span>
2918
+ <strong>${escapeHtml10(turn.label)}</strong>
2919
+ <span>${escapeHtml10(turn.status)}</span>
2645
2920
  </header>
2646
2921
  <dl>${turn.rows.map((row) => `<div>
2647
- <dt>${escapeHtml9(row.label)}</dt>
2648
- <dd>${escapeHtml9(row.value)}</dd>
2922
+ <dt>${escapeHtml10(row.label)}</dt>
2923
+ <dd>${escapeHtml10(row.value)}</dd>
2649
2924
  </div>`).join("")}</dl>
2650
2925
  </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)}">
2926
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
2652
2927
  <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>
2928
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
2929
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
2655
2930
  </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>` : ""}
2931
+ <p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
2932
+ ${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
2933
  ${turns}
2659
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
2934
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
2660
2935
  </section>`;
2661
2936
  };
2662
2937
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -2707,7 +2982,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
2707
2982
  };
2708
2983
 
2709
2984
  // src/react/VoiceTurnLatency.tsx
2710
- import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
2985
+ import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
2711
2986
  var VoiceTurnLatency = ({
2712
2987
  className,
2713
2988
  path = "/api/turn-latency",
@@ -2715,31 +2990,31 @@ var VoiceTurnLatency = ({
2715
2990
  }) => {
2716
2991
  const latency = useVoiceTurnLatency(path, options);
2717
2992
  const model = createVoiceTurnLatencyViewModel(latency, options);
2718
- return /* @__PURE__ */ jsxDEV9("section", {
2993
+ return /* @__PURE__ */ jsxDEV10("section", {
2719
2994
  className: [
2720
2995
  "absolute-voice-turn-latency",
2721
2996
  `absolute-voice-turn-latency--${model.status}`,
2722
2997
  className
2723
2998
  ].filter(Boolean).join(" "),
2724
2999
  children: [
2725
- /* @__PURE__ */ jsxDEV9("header", {
3000
+ /* @__PURE__ */ jsxDEV10("header", {
2726
3001
  className: "absolute-voice-turn-latency__header",
2727
3002
  children: [
2728
- /* @__PURE__ */ jsxDEV9("span", {
3003
+ /* @__PURE__ */ jsxDEV10("span", {
2729
3004
  className: "absolute-voice-turn-latency__eyebrow",
2730
3005
  children: model.title
2731
3006
  }, undefined, false, undefined, this),
2732
- /* @__PURE__ */ jsxDEV9("strong", {
3007
+ /* @__PURE__ */ jsxDEV10("strong", {
2733
3008
  className: "absolute-voice-turn-latency__label",
2734
3009
  children: model.label
2735
3010
  }, undefined, false, undefined, this)
2736
3011
  ]
2737
3012
  }, undefined, true, undefined, this),
2738
- /* @__PURE__ */ jsxDEV9("p", {
3013
+ /* @__PURE__ */ jsxDEV10("p", {
2739
3014
  className: "absolute-voice-turn-latency__description",
2740
3015
  children: model.description
2741
3016
  }, undefined, false, undefined, this),
2742
- model.showProofAction ? /* @__PURE__ */ jsxDEV9("button", {
3017
+ model.showProofAction ? /* @__PURE__ */ jsxDEV10("button", {
2743
3018
  className: "absolute-voice-turn-latency__proof",
2744
3019
  onClick: () => {
2745
3020
  latency.runProof().catch(() => {});
@@ -2747,31 +3022,31 @@ var VoiceTurnLatency = ({
2747
3022
  type: "button",
2748
3023
  children: model.proofLabel
2749
3024
  }, undefined, false, undefined, this) : null,
2750
- model.turns.length ? /* @__PURE__ */ jsxDEV9("div", {
3025
+ model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
2751
3026
  className: "absolute-voice-turn-latency__turns",
2752
- children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV9("article", {
3027
+ children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
2753
3028
  className: [
2754
3029
  "absolute-voice-turn-latency__turn",
2755
3030
  `absolute-voice-turn-latency__turn--${turn.status}`
2756
3031
  ].join(" "),
2757
3032
  children: [
2758
- /* @__PURE__ */ jsxDEV9("header", {
3033
+ /* @__PURE__ */ jsxDEV10("header", {
2759
3034
  children: [
2760
- /* @__PURE__ */ jsxDEV9("strong", {
3035
+ /* @__PURE__ */ jsxDEV10("strong", {
2761
3036
  children: turn.label
2762
3037
  }, undefined, false, undefined, this),
2763
- /* @__PURE__ */ jsxDEV9("span", {
3038
+ /* @__PURE__ */ jsxDEV10("span", {
2764
3039
  children: turn.status
2765
3040
  }, undefined, false, undefined, this)
2766
3041
  ]
2767
3042
  }, undefined, true, undefined, this),
2768
- /* @__PURE__ */ jsxDEV9("dl", {
2769
- children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV9("div", {
3043
+ /* @__PURE__ */ jsxDEV10("dl", {
3044
+ children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
2770
3045
  children: [
2771
- /* @__PURE__ */ jsxDEV9("dt", {
3046
+ /* @__PURE__ */ jsxDEV10("dt", {
2772
3047
  children: row.label
2773
3048
  }, undefined, false, undefined, this),
2774
- /* @__PURE__ */ jsxDEV9("dd", {
3049
+ /* @__PURE__ */ jsxDEV10("dd", {
2775
3050
  children: row.value
2776
3051
  }, undefined, false, undefined, this)
2777
3052
  ]
@@ -2779,11 +3054,11 @@ var VoiceTurnLatency = ({
2779
3054
  }, undefined, false, undefined, this)
2780
3055
  ]
2781
3056
  }, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
2782
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
3057
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
2783
3058
  className: "absolute-voice-turn-latency__empty",
2784
3059
  children: "Complete a voice turn to see latency diagnostics."
2785
3060
  }, undefined, false, undefined, this),
2786
- model.error ? /* @__PURE__ */ jsxDEV9("p", {
3061
+ model.error ? /* @__PURE__ */ jsxDEV10("p", {
2787
3062
  className: "absolute-voice-turn-latency__error",
2788
3063
  children: model.error
2789
3064
  }, undefined, false, undefined, this) : null
@@ -2791,7 +3066,7 @@ var VoiceTurnLatency = ({
2791
3066
  }, undefined, true, undefined, this);
2792
3067
  };
2793
3068
  // src/react/useVoiceTurnQuality.tsx
2794
- import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
3069
+ import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
2795
3070
 
2796
3071
  // src/client/turnQuality.ts
2797
3072
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
@@ -2874,25 +3149,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
2874
3149
 
2875
3150
  // src/react/useVoiceTurnQuality.tsx
2876
3151
  var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
2877
- const storeRef = useRef10(null);
3152
+ const storeRef = useRef11(null);
2878
3153
  if (!storeRef.current) {
2879
3154
  storeRef.current = createVoiceTurnQualityStore(path, options);
2880
3155
  }
2881
3156
  const store = storeRef.current;
2882
- useEffect10(() => {
3157
+ useEffect11(() => {
2883
3158
  store.refresh().catch(() => {});
2884
3159
  return () => store.close();
2885
3160
  }, [store]);
2886
3161
  return {
2887
- ...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3162
+ ...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
2888
3163
  refresh: store.refresh
2889
3164
  };
2890
3165
  };
2891
3166
 
2892
3167
  // 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;");
3168
+ var DEFAULT_TITLE10 = "Turn Quality";
3169
+ var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3170
+ var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2896
3171
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
2897
3172
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
2898
3173
  var getTurnDetail = (turn) => {
@@ -2930,37 +3205,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
2930
3205
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2931
3206
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2932
3207
  return {
2933
- description: options.description ?? DEFAULT_DESCRIPTION9,
3208
+ description: options.description ?? DEFAULT_DESCRIPTION10,
2934
3209
  error: snapshot.error,
2935
3210
  isLoading: snapshot.isLoading,
2936
3211
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
2937
3212
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2938
- title: options.title ?? DEFAULT_TITLE9,
3213
+ title: options.title ?? DEFAULT_TITLE10,
2939
3214
  turns,
2940
3215
  updatedAt: snapshot.updatedAt
2941
3216
  };
2942
3217
  };
2943
3218
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
2944
3219
  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)}">
3220
+ 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
3221
  <header>
2947
- <strong>${escapeHtml10(turn.label)}</strong>
2948
- <span>${escapeHtml10(turn.status)}</span>
3222
+ <strong>${escapeHtml11(turn.label)}</strong>
3223
+ <span>${escapeHtml11(turn.status)}</span>
2949
3224
  </header>
2950
- <p>${escapeHtml10(turn.detail)}</p>
3225
+ <p>${escapeHtml11(turn.detail)}</p>
2951
3226
  <dl>${turn.rows.map((row) => `<div>
2952
- <dt>${escapeHtml10(row.label)}</dt>
2953
- <dd>${escapeHtml10(row.value)}</dd>
3227
+ <dt>${escapeHtml11(row.label)}</dt>
3228
+ <dd>${escapeHtml11(row.value)}</dd>
2954
3229
  </div>`).join("")}</dl>
2955
3230
  </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)}">
3231
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml11(model.status)}">
2957
3232
  <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>
3233
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml11(model.title)}</span>
3234
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml11(model.label)}</strong>
2960
3235
  </header>
2961
- <p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
3236
+ <p class="absolute-voice-turn-quality__description">${escapeHtml11(model.description)}</p>
2962
3237
  ${turns}
2963
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
3238
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml11(model.error)}</p>` : ""}
2964
3239
  </section>`;
2965
3240
  };
2966
3241
  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 +3277,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
3002
3277
  };
3003
3278
 
3004
3279
  // src/react/VoiceTurnQuality.tsx
3005
- import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
3280
+ import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
3006
3281
  var VoiceTurnQuality = ({
3007
3282
  className,
3008
3283
  path = "/api/turn-quality",
@@ -3010,58 +3285,58 @@ var VoiceTurnQuality = ({
3010
3285
  }) => {
3011
3286
  const snapshot = useVoiceTurnQuality(path, options);
3012
3287
  const model = createVoiceTurnQualityViewModel(snapshot, options);
3013
- return /* @__PURE__ */ jsxDEV10("section", {
3288
+ return /* @__PURE__ */ jsxDEV11("section", {
3014
3289
  className: [
3015
3290
  "absolute-voice-turn-quality",
3016
3291
  `absolute-voice-turn-quality--${model.status}`,
3017
3292
  className
3018
3293
  ].filter(Boolean).join(" "),
3019
3294
  children: [
3020
- /* @__PURE__ */ jsxDEV10("header", {
3295
+ /* @__PURE__ */ jsxDEV11("header", {
3021
3296
  className: "absolute-voice-turn-quality__header",
3022
3297
  children: [
3023
- /* @__PURE__ */ jsxDEV10("span", {
3298
+ /* @__PURE__ */ jsxDEV11("span", {
3024
3299
  className: "absolute-voice-turn-quality__eyebrow",
3025
3300
  children: model.title
3026
3301
  }, undefined, false, undefined, this),
3027
- /* @__PURE__ */ jsxDEV10("strong", {
3302
+ /* @__PURE__ */ jsxDEV11("strong", {
3028
3303
  className: "absolute-voice-turn-quality__label",
3029
3304
  children: model.label
3030
3305
  }, undefined, false, undefined, this)
3031
3306
  ]
3032
3307
  }, undefined, true, undefined, this),
3033
- /* @__PURE__ */ jsxDEV10("p", {
3308
+ /* @__PURE__ */ jsxDEV11("p", {
3034
3309
  className: "absolute-voice-turn-quality__description",
3035
3310
  children: model.description
3036
3311
  }, undefined, false, undefined, this),
3037
- model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
3312
+ model.turns.length ? /* @__PURE__ */ jsxDEV11("div", {
3038
3313
  className: "absolute-voice-turn-quality__turns",
3039
- children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
3314
+ children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV11("article", {
3040
3315
  className: [
3041
3316
  "absolute-voice-turn-quality__turn",
3042
3317
  `absolute-voice-turn-quality__turn--${turn.status}`
3043
3318
  ].join(" "),
3044
3319
  children: [
3045
- /* @__PURE__ */ jsxDEV10("header", {
3320
+ /* @__PURE__ */ jsxDEV11("header", {
3046
3321
  children: [
3047
- /* @__PURE__ */ jsxDEV10("strong", {
3322
+ /* @__PURE__ */ jsxDEV11("strong", {
3048
3323
  children: turn.label
3049
3324
  }, undefined, false, undefined, this),
3050
- /* @__PURE__ */ jsxDEV10("span", {
3325
+ /* @__PURE__ */ jsxDEV11("span", {
3051
3326
  children: turn.status
3052
3327
  }, undefined, false, undefined, this)
3053
3328
  ]
3054
3329
  }, undefined, true, undefined, this),
3055
- /* @__PURE__ */ jsxDEV10("p", {
3330
+ /* @__PURE__ */ jsxDEV11("p", {
3056
3331
  children: turn.detail
3057
3332
  }, undefined, false, undefined, this),
3058
- /* @__PURE__ */ jsxDEV10("dl", {
3059
- children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
3333
+ /* @__PURE__ */ jsxDEV11("dl", {
3334
+ children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV11("div", {
3060
3335
  children: [
3061
- /* @__PURE__ */ jsxDEV10("dt", {
3336
+ /* @__PURE__ */ jsxDEV11("dt", {
3062
3337
  children: row.label
3063
3338
  }, undefined, false, undefined, this),
3064
- /* @__PURE__ */ jsxDEV10("dd", {
3339
+ /* @__PURE__ */ jsxDEV11("dd", {
3065
3340
  children: row.value
3066
3341
  }, undefined, false, undefined, this)
3067
3342
  ]
@@ -3069,11 +3344,11 @@ var VoiceTurnQuality = ({
3069
3344
  }, undefined, false, undefined, this)
3070
3345
  ]
3071
3346
  }, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
3072
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
3347
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV11("p", {
3073
3348
  className: "absolute-voice-turn-quality__empty",
3074
3349
  children: "Complete a voice turn to see STT quality diagnostics."
3075
3350
  }, undefined, false, undefined, this),
3076
- model.error ? /* @__PURE__ */ jsxDEV10("p", {
3351
+ model.error ? /* @__PURE__ */ jsxDEV11("p", {
3077
3352
  className: "absolute-voice-turn-quality__error",
3078
3353
  children: model.error
3079
3354
  }, undefined, false, undefined, this) : null
@@ -3081,7 +3356,7 @@ var VoiceTurnQuality = ({
3081
3356
  }, undefined, true, undefined, this);
3082
3357
  };
3083
3358
  // src/react/useVoiceCampaignDialerProof.tsx
3084
- import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
3359
+ import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
3085
3360
 
3086
3361
  // src/client/campaignDialerProof.ts
3087
3362
  var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
@@ -3203,23 +3478,23 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
3203
3478
 
3204
3479
  // src/react/useVoiceCampaignDialerProof.tsx
3205
3480
  var useVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3206
- const storeRef = useRef11(null);
3481
+ const storeRef = useRef12(null);
3207
3482
  if (!storeRef.current) {
3208
3483
  storeRef.current = createVoiceCampaignDialerProofStore(path, options);
3209
3484
  }
3210
3485
  const store = storeRef.current;
3211
- useEffect11(() => {
3486
+ useEffect12(() => {
3212
3487
  store.refresh().catch(() => {});
3213
3488
  return () => store.close();
3214
3489
  }, [store]);
3215
3490
  return {
3216
- ...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3491
+ ...useSyncExternalStore12(store.subscribe, store.getSnapshot, store.getServerSnapshot),
3217
3492
  refresh: store.refresh,
3218
3493
  runProof: store.runProof
3219
3494
  };
3220
3495
  };
3221
3496
  // src/react/useVoiceStream.tsx
3222
- import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
3497
+ import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
3223
3498
 
3224
3499
  // src/client/actions.ts
3225
3500
  var normalizeErrorMessage = (value) => {
@@ -3879,13 +4154,13 @@ var EMPTY_SNAPSHOT = {
3879
4154
  turns: []
3880
4155
  };
3881
4156
  var useVoiceStream = (path, options = {}) => {
3882
- const streamRef = useRef12(null);
4157
+ const streamRef = useRef13(null);
3883
4158
  if (!streamRef.current) {
3884
4159
  streamRef.current = createVoiceStream(path, options);
3885
4160
  }
3886
4161
  const stream = streamRef.current;
3887
- useEffect12(() => () => stream.close(), [stream]);
3888
- const snapshot = useSyncExternalStore12(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
4162
+ useEffect13(() => () => stream.close(), [stream]);
4163
+ const snapshot = useSyncExternalStore13(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
3889
4164
  return {
3890
4165
  ...snapshot,
3891
4166
  callControl: (message) => stream.callControl(message),
@@ -3895,7 +4170,7 @@ var useVoiceStream = (path, options = {}) => {
3895
4170
  };
3896
4171
  };
3897
4172
  // src/react/useVoiceController.tsx
3898
- import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
4173
+ import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
3899
4174
 
3900
4175
  // src/client/htmx.ts
3901
4176
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -4558,13 +4833,13 @@ var EMPTY_SNAPSHOT2 = {
4558
4833
  turns: []
4559
4834
  };
4560
4835
  var useVoiceController = (path, options = {}) => {
4561
- const controllerRef = useRef13(null);
4836
+ const controllerRef = useRef14(null);
4562
4837
  if (!controllerRef.current) {
4563
4838
  controllerRef.current = createVoiceController(path, options);
4564
4839
  }
4565
4840
  const controller = controllerRef.current;
4566
- useEffect13(() => () => controller.close(), [controller]);
4567
- const snapshot = useSyncExternalStore13(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
4841
+ useEffect14(() => () => controller.close(), [controller]);
4842
+ const snapshot = useSyncExternalStore14(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
4568
4843
  return {
4569
4844
  ...snapshot,
4570
4845
  bindHTMX: controller.bindHTMX,
@@ -4578,7 +4853,7 @@ var useVoiceController = (path, options = {}) => {
4578
4853
  };
4579
4854
  };
4580
4855
  // src/react/useVoiceWorkflowStatus.tsx
4581
- import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
4856
+ import { useEffect as useEffect15, useRef as useRef15, useSyncExternalStore as useSyncExternalStore15 } from "react";
4582
4857
 
4583
4858
  // src/client/workflowStatus.ts
4584
4859
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -4661,17 +4936,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
4661
4936
 
4662
4937
  // src/react/useVoiceWorkflowStatus.tsx
4663
4938
  var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
4664
- const storeRef = useRef14(null);
4939
+ const storeRef = useRef15(null);
4665
4940
  if (!storeRef.current) {
4666
4941
  storeRef.current = createVoiceWorkflowStatusStore(path, options);
4667
4942
  }
4668
4943
  const store = storeRef.current;
4669
- useEffect14(() => {
4944
+ useEffect15(() => {
4670
4945
  store.refresh().catch(() => {});
4671
4946
  return () => store.close();
4672
4947
  }, [store]);
4673
4948
  return {
4674
- ...useSyncExternalStore14(store.subscribe, store.getSnapshot, store.getServerSnapshot),
4949
+ ...useSyncExternalStore15(store.subscribe, store.getSnapshot, store.getServerSnapshot),
4675
4950
  refresh: store.refresh
4676
4951
  };
4677
4952
  };
@@ -4684,6 +4959,7 @@ export {
4684
4959
  useVoiceRoutingStatus,
4685
4960
  useVoiceProviderStatus,
4686
4961
  useVoiceProviderSimulationControls,
4962
+ useVoiceProviderContracts,
4687
4963
  useVoiceProviderCapabilities,
4688
4964
  useVoiceOpsStatus,
4689
4965
  useVoiceOpsActionCenter,
@@ -4696,6 +4972,7 @@ export {
4696
4972
  VoiceRoutingStatus,
4697
4973
  VoiceProviderStatus,
4698
4974
  VoiceProviderSimulationControls,
4975
+ VoiceProviderContracts,
4699
4976
  VoiceProviderCapabilities,
4700
4977
  VoiceOpsStatus,
4701
4978
  VoiceOpsActionCenter,