@absolutejs/voice 0.0.22-beta.90 → 0.0.22-beta.91

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.
@@ -4,5 +4,6 @@ export { VoiceControllerService } from './voice-controller.service';
4
4
  export { VoiceProviderCapabilitiesService } from './voice-provider-capabilities.service';
5
5
  export { VoiceProviderStatusService } from './voice-provider-status.service';
6
6
  export { VoiceRoutingStatusService } from './voice-routing-status.service';
7
+ export { VoiceTraceTimelineService } from './voice-trace-timeline.service';
7
8
  export { VoiceTurnQualityService } from './voice-turn-quality.service';
8
9
  export { VoiceWorkflowStatusService } from './voice-workflow-status.service';
@@ -1826,9 +1826,132 @@ VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusServi
1826
1826
  __runInitializers(_init, 1, VoiceRoutingStatusService);
1827
1827
  __decoratorMetadata(_init, VoiceRoutingStatusService);
1828
1828
  let _VoiceRoutingStatusService = VoiceRoutingStatusService;
1829
- // src/angular/voice-turn-quality.service.ts
1829
+ // src/angular/voice-trace-timeline.service.ts
1830
1830
  import { computed as computed6, Injectable as Injectable7, signal as signal7 } from "@angular/core";
1831
1831
 
1832
+ // src/client/traceTimeline.ts
1833
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
1834
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1835
+ const response = await fetchImpl(path);
1836
+ if (!response.ok) {
1837
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
1838
+ }
1839
+ return await response.json();
1840
+ };
1841
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
1842
+ const listeners = new Set;
1843
+ let closed = false;
1844
+ let timer;
1845
+ let snapshot = {
1846
+ error: null,
1847
+ isLoading: false,
1848
+ report: null
1849
+ };
1850
+ const emit = () => {
1851
+ for (const listener of listeners) {
1852
+ listener();
1853
+ }
1854
+ };
1855
+ const refresh = async () => {
1856
+ if (closed) {
1857
+ return snapshot.report;
1858
+ }
1859
+ snapshot = {
1860
+ ...snapshot,
1861
+ error: null,
1862
+ isLoading: true
1863
+ };
1864
+ emit();
1865
+ try {
1866
+ const report = await fetchVoiceTraceTimeline(path, options);
1867
+ snapshot = {
1868
+ error: null,
1869
+ isLoading: false,
1870
+ report,
1871
+ updatedAt: Date.now()
1872
+ };
1873
+ emit();
1874
+ return report;
1875
+ } catch (error) {
1876
+ snapshot = {
1877
+ ...snapshot,
1878
+ error: error instanceof Error ? error.message : String(error),
1879
+ isLoading: false
1880
+ };
1881
+ emit();
1882
+ throw error;
1883
+ }
1884
+ };
1885
+ const close = () => {
1886
+ closed = true;
1887
+ if (timer) {
1888
+ clearInterval(timer);
1889
+ timer = undefined;
1890
+ }
1891
+ listeners.clear();
1892
+ };
1893
+ if (options.intervalMs && options.intervalMs > 0) {
1894
+ timer = setInterval(() => {
1895
+ refresh().catch(() => {});
1896
+ }, options.intervalMs);
1897
+ }
1898
+ return {
1899
+ close,
1900
+ getServerSnapshot: () => snapshot,
1901
+ getSnapshot: () => snapshot,
1902
+ refresh,
1903
+ subscribe: (listener) => {
1904
+ listeners.add(listener);
1905
+ return () => {
1906
+ listeners.delete(listener);
1907
+ };
1908
+ }
1909
+ };
1910
+ };
1911
+
1912
+ // src/angular/voice-trace-timeline.service.ts
1913
+ var _dec = [
1914
+ Injectable7({ providedIn: "root" })
1915
+ ];
1916
+ var _init = __decoratorStart(undefined);
1917
+
1918
+ class VoiceTraceTimelineService {
1919
+ connect(path = "/api/voice-traces", options = {}) {
1920
+ const store = createVoiceTraceTimelineStore(path, options);
1921
+ const errorSignal = signal7(null);
1922
+ const isLoadingSignal = signal7(false);
1923
+ const reportSignal = signal7(null);
1924
+ const updatedAtSignal = signal7(undefined);
1925
+ const sync = () => {
1926
+ const snapshot = store.getSnapshot();
1927
+ errorSignal.set(snapshot.error);
1928
+ isLoadingSignal.set(snapshot.isLoading);
1929
+ reportSignal.set(snapshot.report);
1930
+ updatedAtSignal.set(snapshot.updatedAt);
1931
+ };
1932
+ const unsubscribe = store.subscribe(sync);
1933
+ sync();
1934
+ store.refresh().catch(() => {});
1935
+ return {
1936
+ close: () => {
1937
+ unsubscribe();
1938
+ store.close();
1939
+ },
1940
+ error: computed6(() => errorSignal()),
1941
+ isLoading: computed6(() => isLoadingSignal()),
1942
+ refresh: store.refresh,
1943
+ report: computed6(() => reportSignal()),
1944
+ updatedAt: computed6(() => updatedAtSignal())
1945
+ };
1946
+ }
1947
+ }
1948
+ VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
1949
+ __runInitializers(_init, 1, VoiceTraceTimelineService);
1950
+ __decoratorMetadata(_init, VoiceTraceTimelineService);
1951
+ let _VoiceTraceTimelineService = VoiceTraceTimelineService;
1952
+ // src/angular/voice-turn-quality.service.ts
1953
+ import { computed as computed7, Injectable as Injectable8, signal as signal8 } from "@angular/core";
1954
+
1832
1955
  // src/client/turnQuality.ts
1833
1956
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
1834
1957
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -1910,17 +2033,17 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
1910
2033
 
1911
2034
  // src/angular/voice-turn-quality.service.ts
1912
2035
  var _dec = [
1913
- Injectable7({ providedIn: "root" })
2036
+ Injectable8({ providedIn: "root" })
1914
2037
  ];
1915
2038
  var _init = __decoratorStart(undefined);
1916
2039
 
1917
2040
  class VoiceTurnQualityService {
1918
2041
  connect(path = "/api/turn-quality", options = {}) {
1919
2042
  const store = createVoiceTurnQualityStore(path, options);
1920
- const errorSignal = signal7(null);
1921
- const isLoadingSignal = signal7(false);
1922
- const reportSignal = signal7(undefined);
1923
- const updatedAtSignal = signal7(undefined);
2043
+ const errorSignal = signal8(null);
2044
+ const isLoadingSignal = signal8(false);
2045
+ const reportSignal = signal8(undefined);
2046
+ const updatedAtSignal = signal8(undefined);
1924
2047
  const sync = () => {
1925
2048
  const snapshot = store.getSnapshot();
1926
2049
  errorSignal.set(snapshot.error);
@@ -1936,11 +2059,11 @@ class VoiceTurnQualityService {
1936
2059
  unsubscribe();
1937
2060
  store.close();
1938
2061
  },
1939
- error: computed6(() => errorSignal()),
1940
- isLoading: computed6(() => isLoadingSignal()),
2062
+ error: computed7(() => errorSignal()),
2063
+ isLoading: computed7(() => isLoadingSignal()),
1941
2064
  refresh: store.refresh,
1942
- report: computed6(() => reportSignal()),
1943
- updatedAt: computed6(() => updatedAtSignal())
2065
+ report: computed7(() => reportSignal()),
2066
+ updatedAt: computed7(() => updatedAtSignal())
1944
2067
  };
1945
2068
  }
1946
2069
  }
@@ -1949,7 +2072,7 @@ __runInitializers(_init, 1, VoiceTurnQualityService);
1949
2072
  __decoratorMetadata(_init, VoiceTurnQualityService);
1950
2073
  let _VoiceTurnQualityService = VoiceTurnQualityService;
1951
2074
  // src/angular/voice-workflow-status.service.ts
1952
- import { computed as computed7, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2075
+ import { computed as computed8, Injectable as Injectable9, signal as signal9 } from "@angular/core";
1953
2076
 
1954
2077
  // src/client/workflowStatus.ts
1955
2078
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -2032,17 +2155,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
2032
2155
 
2033
2156
  // src/angular/voice-workflow-status.service.ts
2034
2157
  var _dec = [
2035
- Injectable8({ providedIn: "root" })
2158
+ Injectable9({ providedIn: "root" })
2036
2159
  ];
2037
2160
  var _init = __decoratorStart(undefined);
2038
2161
 
2039
2162
  class VoiceWorkflowStatusService {
2040
2163
  connect(path = "/evals/scenarios/json", options = {}) {
2041
2164
  const store = createVoiceWorkflowStatusStore(path, options);
2042
- const errorSignal = signal8(null);
2043
- const isLoadingSignal = signal8(false);
2044
- const reportSignal = signal8(undefined);
2045
- const updatedAtSignal = signal8(undefined);
2165
+ const errorSignal = signal9(null);
2166
+ const isLoadingSignal = signal9(false);
2167
+ const reportSignal = signal9(undefined);
2168
+ const updatedAtSignal = signal9(undefined);
2046
2169
  const sync = () => {
2047
2170
  const snapshot = store.getSnapshot();
2048
2171
  errorSignal.set(snapshot.error);
@@ -2060,11 +2183,11 @@ class VoiceWorkflowStatusService {
2060
2183
  unsubscribe();
2061
2184
  store.close();
2062
2185
  },
2063
- error: computed7(() => errorSignal()),
2064
- isLoading: computed7(() => isLoadingSignal()),
2186
+ error: computed8(() => errorSignal()),
2187
+ isLoading: computed8(() => isLoadingSignal()),
2065
2188
  refresh: store.refresh,
2066
- report: computed7(() => reportSignal()),
2067
- updatedAt: computed7(() => updatedAtSignal())
2189
+ report: computed8(() => reportSignal()),
2190
+ updatedAt: computed8(() => updatedAtSignal())
2068
2191
  };
2069
2192
  }
2070
2193
  }
@@ -2075,6 +2198,7 @@ let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
2075
2198
  export {
2076
2199
  VoiceWorkflowStatusService,
2077
2200
  VoiceTurnQualityService,
2201
+ VoiceTraceTimelineService,
2078
2202
  VoiceStreamService,
2079
2203
  VoiceRoutingStatusService,
2080
2204
  VoiceProviderStatusService,
@@ -0,0 +1,12 @@
1
+ import { type VoiceTraceTimelineClientOptions } from '../client/traceTimeline';
2
+ import type { VoiceTraceTimelineReport } from '../traceTimeline';
3
+ export declare class VoiceTraceTimelineService {
4
+ connect(path?: string, options?: VoiceTraceTimelineClientOptions): {
5
+ close: () => void;
6
+ error: import("@angular/core").Signal<string | null>;
7
+ isLoading: import("@angular/core").Signal<boolean>;
8
+ refresh: () => Promise<VoiceTraceTimelineReport | null>;
9
+ report: import("@angular/core").Signal<VoiceTraceTimelineReport | null>;
10
+ updatedAt: import("@angular/core").Signal<number | undefined>;
11
+ };
12
+ }
@@ -12,11 +12,13 @@ export { createVoiceRoutingStatusViewModel, defineVoiceRoutingStatusElement, get
12
12
  export { createVoiceProviderStatusStore, fetchVoiceProviderStatus } from './providerStatus';
13
13
  export { createVoiceProviderCapabilitiesStore, fetchVoiceProviderCapabilities } from './providerCapabilities';
14
14
  export { createVoiceTurnQualityStore, fetchVoiceTurnQuality } from './turnQuality';
15
+ export { createVoiceTraceTimelineStore, fetchVoiceTraceTimeline } from './traceTimeline';
15
16
  export { createVoiceProviderSimulationControlsStore } from './providerSimulationControls';
16
17
  export { bindVoiceProviderSimulationControls, createVoiceProviderSimulationControlsViewModel, defineVoiceProviderSimulationControlsElement, mountVoiceProviderSimulationControls, renderVoiceProviderSimulationControlsHTML } from './providerSimulationControlsWidget';
17
18
  export { createVoiceProviderStatusViewModel, defineVoiceProviderStatusElement, getVoiceProviderStatusCSS, mountVoiceProviderStatus, renderVoiceProviderStatusHTML } from './providerStatusWidget';
18
19
  export { createVoiceProviderCapabilitiesViewModel, defineVoiceProviderCapabilitiesElement, getVoiceProviderCapabilitiesCSS, mountVoiceProviderCapabilities, renderVoiceProviderCapabilitiesHTML } from './providerCapabilitiesWidget';
19
20
  export { createVoiceTurnQualityViewModel, defineVoiceTurnQualityElement, getVoiceTurnQualityCSS, mountVoiceTurnQuality, renderVoiceTurnQualityHTML } from './turnQualityWidget';
21
+ export { createVoiceTraceTimelineViewModel, defineVoiceTraceTimelineElement, getVoiceTraceTimelineCSS, mountVoiceTraceTimeline, renderVoiceTraceTimelineWidgetHTML } from './traceTimelineWidget';
20
22
  export { createVoiceWorkflowStatusStore, fetchVoiceWorkflowStatus } from './workflowStatus';
21
23
  export type { VoiceAppKitStatusClientOptions, VoiceAppKitStatusSnapshot } from './appKitStatus';
22
24
  export type { VoiceOpsStatusSurfaceView, VoiceOpsStatusViewModel, VoiceOpsStatusWidgetOptions } from './opsStatusWidget';
@@ -25,9 +27,11 @@ export type { VoiceRoutingStatusViewModel, VoiceRoutingStatusWidgetOptions } fro
25
27
  export type { VoiceProviderStatusClientOptions, VoiceProviderStatusSnapshot } from './providerStatus';
26
28
  export type { VoiceProviderCapabilitiesClientOptions, VoiceProviderCapabilitiesSnapshot } from './providerCapabilities';
27
29
  export type { VoiceTurnQualityClientOptions, VoiceTurnQualitySnapshot } from './turnQuality';
30
+ export type { VoiceTraceTimelineClientOptions, VoiceTraceTimelineSnapshot } from './traceTimeline';
28
31
  export type { VoiceProviderSimulationControlsOptions, VoiceProviderSimulationControlsSnapshot, VoiceProviderSimulationProvider } from './providerSimulationControls';
29
32
  export type { VoiceProviderSimulationControlsViewModel } from './providerSimulationControlsWidget';
30
33
  export type { VoiceProviderStatusCardView, VoiceProviderStatusViewModel, VoiceProviderStatusWidgetOptions } from './providerStatusWidget';
31
34
  export type { VoiceProviderCapabilitiesViewModel, VoiceProviderCapabilitiesWidgetOptions, VoiceProviderCapabilityCardView } from './providerCapabilitiesWidget';
32
35
  export type { VoiceTurnQualityCardView, VoiceTurnQualityViewModel, VoiceTurnQualityWidgetOptions } from './turnQualityWidget';
36
+ export type { VoiceTraceTimelineSessionView, VoiceTraceTimelineViewModel, VoiceTraceTimelineWidgetOptions } from './traceTimelineWidget';
33
37
  export type { VoiceWorkflowStatusClientOptions, VoiceWorkflowStatusSnapshot } from './workflowStatus';
@@ -2229,6 +2229,85 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
2229
2229
  }
2230
2230
  };
2231
2231
  };
2232
+ // src/client/traceTimeline.ts
2233
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
2234
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2235
+ const response = await fetchImpl(path);
2236
+ if (!response.ok) {
2237
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
2238
+ }
2239
+ return await response.json();
2240
+ };
2241
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
2242
+ const listeners = new Set;
2243
+ let closed = false;
2244
+ let timer;
2245
+ let snapshot = {
2246
+ error: null,
2247
+ isLoading: false,
2248
+ report: null
2249
+ };
2250
+ const emit = () => {
2251
+ for (const listener of listeners) {
2252
+ listener();
2253
+ }
2254
+ };
2255
+ const refresh = async () => {
2256
+ if (closed) {
2257
+ return snapshot.report;
2258
+ }
2259
+ snapshot = {
2260
+ ...snapshot,
2261
+ error: null,
2262
+ isLoading: true
2263
+ };
2264
+ emit();
2265
+ try {
2266
+ const report = await fetchVoiceTraceTimeline(path, options);
2267
+ snapshot = {
2268
+ error: null,
2269
+ isLoading: false,
2270
+ report,
2271
+ updatedAt: Date.now()
2272
+ };
2273
+ emit();
2274
+ return report;
2275
+ } catch (error) {
2276
+ snapshot = {
2277
+ ...snapshot,
2278
+ error: error instanceof Error ? error.message : String(error),
2279
+ isLoading: false
2280
+ };
2281
+ emit();
2282
+ throw error;
2283
+ }
2284
+ };
2285
+ const close = () => {
2286
+ closed = true;
2287
+ if (timer) {
2288
+ clearInterval(timer);
2289
+ timer = undefined;
2290
+ }
2291
+ listeners.clear();
2292
+ };
2293
+ if (options.intervalMs && options.intervalMs > 0) {
2294
+ timer = setInterval(() => {
2295
+ refresh().catch(() => {});
2296
+ }, options.intervalMs);
2297
+ }
2298
+ return {
2299
+ close,
2300
+ getServerSnapshot: () => snapshot,
2301
+ getSnapshot: () => snapshot,
2302
+ refresh,
2303
+ subscribe: (listener) => {
2304
+ listeners.add(listener);
2305
+ return () => {
2306
+ listeners.delete(listener);
2307
+ };
2308
+ }
2309
+ };
2310
+ };
2232
2311
  // src/client/providerSimulationControls.ts
2233
2312
  var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
2234
2313
  const response = await fetchImpl(`${pathPrefix}/${mode}?provider=${encodeURIComponent(provider)}`, { method: "POST" });
@@ -2747,6 +2826,93 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
2747
2826
  }
2748
2827
  });
2749
2828
  };
2829
+ // src/client/traceTimelineWidget.ts
2830
+ var DEFAULT_TITLE6 = "Voice Traces";
2831
+ var DEFAULT_DESCRIPTION6 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
2832
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2833
+ var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
2834
+ var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
2835
+ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
2836
+ const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
2837
+ ...session,
2838
+ detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
2839
+ durationLabel: formatMs(session.summary.callDurationMs),
2840
+ label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
2841
+ providerLabel: formatProviders(session)
2842
+ }));
2843
+ const failed = sessions.filter((session) => session.status === "failed").length;
2844
+ const warnings = sessions.filter((session) => session.status === "warning").length;
2845
+ return {
2846
+ description: options.description ?? DEFAULT_DESCRIPTION6,
2847
+ error: snapshot.error,
2848
+ isLoading: snapshot.isLoading,
2849
+ label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
2850
+ sessions,
2851
+ status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
2852
+ title: options.title ?? DEFAULT_TITLE6,
2853
+ updatedAt: snapshot.updatedAt
2854
+ };
2855
+ };
2856
+ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
2857
+ const model = createVoiceTraceTimelineViewModel(snapshot, options);
2858
+ 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--${escapeHtml7(session.status)}">
2859
+ <header>
2860
+ <strong>${escapeHtml7(session.sessionId)}</strong>
2861
+ <span>${escapeHtml7(session.status)}</span>
2862
+ </header>
2863
+ <p>${escapeHtml7(session.label)} \xB7 ${escapeHtml7(session.durationLabel)} \xB7 ${escapeHtml7(session.providerLabel)}</p>
2864
+ <a href="${escapeHtml7(session.detailHref)}">Open timeline</a>
2865
+ </article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
2866
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml7(model.status)}">
2867
+ <header class="absolute-voice-trace-timeline__header">
2868
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml7(model.title)}</span>
2869
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml7(model.label)}</strong>
2870
+ </header>
2871
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml7(model.description)}</p>
2872
+ ${sessions}
2873
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml7(model.error)}</p>` : ""}
2874
+ </section>`;
2875
+ };
2876
+ 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}`;
2877
+ var mountVoiceTraceTimeline = (element, path = "/api/voice-traces", options = {}) => {
2878
+ const store = createVoiceTraceTimelineStore(path, options);
2879
+ const render = () => {
2880
+ element.innerHTML = renderVoiceTraceTimelineWidgetHTML(store.getSnapshot(), options);
2881
+ };
2882
+ const unsubscribe = store.subscribe(render);
2883
+ render();
2884
+ store.refresh().catch(() => {});
2885
+ return {
2886
+ close: () => {
2887
+ unsubscribe();
2888
+ store.close();
2889
+ },
2890
+ refresh: store.refresh
2891
+ };
2892
+ };
2893
+ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline") => {
2894
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2895
+ return;
2896
+ }
2897
+ customElements.define(tagName, class AbsoluteVoiceTraceTimelineElement extends HTMLElement {
2898
+ mounted;
2899
+ connectedCallback() {
2900
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
2901
+ const limit = Number(this.getAttribute("limit") ?? 3);
2902
+ this.mounted = mountVoiceTraceTimeline(this, this.getAttribute("path") ?? "/api/voice-traces", {
2903
+ description: this.getAttribute("description") ?? undefined,
2904
+ detailBasePath: this.getAttribute("detail-base-path") ?? undefined,
2905
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
2906
+ limit: Number.isFinite(limit) ? limit : 3,
2907
+ title: this.getAttribute("title") ?? undefined
2908
+ });
2909
+ }
2910
+ disconnectedCallback() {
2911
+ this.mounted?.close();
2912
+ this.mounted = undefined;
2913
+ }
2914
+ });
2915
+ };
2750
2916
  // src/client/workflowStatus.ts
2751
2917
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
2752
2918
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -2827,18 +2993,21 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
2827
2993
  };
2828
2994
  export {
2829
2995
  renderVoiceTurnQualityHTML,
2996
+ renderVoiceTraceTimelineWidgetHTML,
2830
2997
  renderVoiceRoutingStatusHTML,
2831
2998
  renderVoiceProviderStatusHTML,
2832
2999
  renderVoiceProviderSimulationControlsHTML,
2833
3000
  renderVoiceProviderCapabilitiesHTML,
2834
3001
  renderVoiceOpsStatusHTML,
2835
3002
  mountVoiceTurnQuality,
3003
+ mountVoiceTraceTimeline,
2836
3004
  mountVoiceRoutingStatus,
2837
3005
  mountVoiceProviderStatus,
2838
3006
  mountVoiceProviderSimulationControls,
2839
3007
  mountVoiceProviderCapabilities,
2840
3008
  mountVoiceOpsStatus,
2841
3009
  getVoiceTurnQualityCSS,
3010
+ getVoiceTraceTimelineCSS,
2842
3011
  getVoiceRoutingStatusCSS,
2843
3012
  getVoiceProviderStatusCSS,
2844
3013
  getVoiceProviderCapabilitiesCSS,
@@ -2846,11 +3015,13 @@ export {
2846
3015
  getVoiceOpsStatusCSS,
2847
3016
  fetchVoiceWorkflowStatus,
2848
3017
  fetchVoiceTurnQuality,
3018
+ fetchVoiceTraceTimeline,
2849
3019
  fetchVoiceRoutingStatus,
2850
3020
  fetchVoiceProviderStatus,
2851
3021
  fetchVoiceProviderCapabilities,
2852
3022
  fetchVoiceAppKitStatus,
2853
3023
  defineVoiceTurnQualityElement,
3024
+ defineVoiceTraceTimelineElement,
2854
3025
  defineVoiceRoutingStatusElement,
2855
3026
  defineVoiceProviderStatusElement,
2856
3027
  defineVoiceProviderSimulationControlsElement,
@@ -2860,6 +3031,8 @@ export {
2860
3031
  createVoiceWorkflowStatusStore,
2861
3032
  createVoiceTurnQualityViewModel,
2862
3033
  createVoiceTurnQualityStore,
3034
+ createVoiceTraceTimelineViewModel,
3035
+ createVoiceTraceTimelineStore,
2863
3036
  createVoiceStream,
2864
3037
  createVoiceRoutingStatusViewModel,
2865
3038
  createVoiceRoutingStatusStore,
@@ -0,0 +1,19 @@
1
+ import type { VoiceTraceTimelineReport } from '../traceTimeline';
2
+ export type VoiceTraceTimelineClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceTraceTimelineSnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report: VoiceTraceTimelineReport | null;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceTraceTimeline: (path?: string, options?: Pick<VoiceTraceTimelineClientOptions, "fetch">) => Promise<VoiceTraceTimelineReport>;
13
+ export declare const createVoiceTraceTimelineStore: (path?: string, options?: VoiceTraceTimelineClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceTraceTimelineSnapshot;
16
+ getSnapshot: () => VoiceTraceTimelineSnapshot;
17
+ refresh: () => Promise<VoiceTraceTimelineReport | null>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,32 @@
1
+ import type { VoiceTraceTimelineSession } from '../traceTimeline';
2
+ import { type VoiceTraceTimelineClientOptions, type VoiceTraceTimelineSnapshot } from './traceTimeline';
3
+ export type VoiceTraceTimelineSessionView = VoiceTraceTimelineSession & {
4
+ detailHref: string;
5
+ durationLabel: string;
6
+ label: string;
7
+ providerLabel: string;
8
+ };
9
+ export type VoiceTraceTimelineViewModel = {
10
+ description: string;
11
+ error: string | null;
12
+ isLoading: boolean;
13
+ label: string;
14
+ sessions: VoiceTraceTimelineSessionView[];
15
+ status: 'empty' | 'error' | 'failed' | 'loading' | 'ready' | 'warning';
16
+ title: string;
17
+ updatedAt?: number;
18
+ };
19
+ export type VoiceTraceTimelineWidgetOptions = VoiceTraceTimelineClientOptions & {
20
+ description?: string;
21
+ detailBasePath?: string;
22
+ limit?: number;
23
+ title?: string;
24
+ };
25
+ export declare const createVoiceTraceTimelineViewModel: (snapshot: VoiceTraceTimelineSnapshot, options?: VoiceTraceTimelineWidgetOptions) => VoiceTraceTimelineViewModel;
26
+ export declare const renderVoiceTraceTimelineWidgetHTML: (snapshot: VoiceTraceTimelineSnapshot, options?: VoiceTraceTimelineWidgetOptions) => string;
27
+ export declare const getVoiceTraceTimelineCSS: () => string;
28
+ export declare const mountVoiceTraceTimeline: (element: Element, path?: string, options?: VoiceTraceTimelineWidgetOptions) => {
29
+ close: () => void;
30
+ refresh: () => Promise<import("..").VoiceTraceTimelineReport | null>;
31
+ };
32
+ export declare const defineVoiceTraceTimelineElement: (tagName?: string) => void;
@@ -0,0 +1,6 @@
1
+ import { type VoiceTraceTimelineWidgetOptions } from '../client/traceTimelineWidget';
2
+ export type VoiceTraceTimelineProps = VoiceTraceTimelineWidgetOptions & {
3
+ className?: string;
4
+ path?: string;
5
+ };
6
+ export declare const VoiceTraceTimeline: ({ className, path, ...options }: VoiceTraceTimelineProps) => import("react/jsx-runtime").JSX.Element;
@@ -3,6 +3,7 @@ export { VoiceProviderSimulationControls } from './VoiceProviderSimulationContro
3
3
  export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
4
4
  export { VoiceProviderStatus } from './VoiceProviderStatus';
5
5
  export { VoiceRoutingStatus } from './VoiceRoutingStatus';
6
+ export { VoiceTraceTimeline } from './VoiceTraceTimeline';
6
7
  export { VoiceTurnQuality } from './VoiceTurnQuality';
7
8
  export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
8
9
  export { useVoiceStream } from './useVoiceStream';
@@ -11,5 +12,6 @@ export { useVoiceProviderStatus } from './useVoiceProviderStatus';
11
12
  export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
12
13
  export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
13
14
  export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
15
+ export { useVoiceTraceTimeline } from './useVoiceTraceTimeline';
14
16
  export { useVoiceTurnQuality } from './useVoiceTurnQuality';
15
17
  export { useVoiceWorkflowStatus } from './useVoiceWorkflowStatus';