@absolutejs/voice 0.0.22-beta.94 → 0.0.22-beta.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1757,6 +1757,176 @@ var createVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
1757
1757
  getViewModel: () => createVoiceTraceTimelineViewModel(store.getSnapshot(), options)
1758
1758
  };
1759
1759
  };
1760
+ // src/client/turnLatency.ts
1761
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
1762
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1763
+ const response = await fetchImpl(path);
1764
+ if (!response.ok) {
1765
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
1766
+ }
1767
+ return await response.json();
1768
+ };
1769
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
1770
+ const listeners = new Set;
1771
+ let closed = false;
1772
+ let timer;
1773
+ let snapshot = {
1774
+ error: null,
1775
+ isLoading: false
1776
+ };
1777
+ const emit = () => {
1778
+ for (const listener of listeners) {
1779
+ listener();
1780
+ }
1781
+ };
1782
+ const refresh = async () => {
1783
+ if (closed) {
1784
+ return snapshot.report;
1785
+ }
1786
+ snapshot = { ...snapshot, error: null, isLoading: true };
1787
+ emit();
1788
+ try {
1789
+ const report = await fetchVoiceTurnLatency(path, options);
1790
+ snapshot = {
1791
+ error: null,
1792
+ isLoading: false,
1793
+ report,
1794
+ updatedAt: Date.now()
1795
+ };
1796
+ emit();
1797
+ return report;
1798
+ } catch (error) {
1799
+ snapshot = {
1800
+ ...snapshot,
1801
+ error: error instanceof Error ? error.message : String(error),
1802
+ isLoading: false
1803
+ };
1804
+ emit();
1805
+ throw error;
1806
+ }
1807
+ };
1808
+ const close = () => {
1809
+ closed = true;
1810
+ if (timer) {
1811
+ clearInterval(timer);
1812
+ timer = undefined;
1813
+ }
1814
+ listeners.clear();
1815
+ };
1816
+ if (options.intervalMs && options.intervalMs > 0) {
1817
+ timer = setInterval(() => {
1818
+ refresh().catch(() => {});
1819
+ }, options.intervalMs);
1820
+ }
1821
+ return {
1822
+ close,
1823
+ getServerSnapshot: () => snapshot,
1824
+ getSnapshot: () => snapshot,
1825
+ refresh,
1826
+ subscribe: (listener) => {
1827
+ listeners.add(listener);
1828
+ return () => {
1829
+ listeners.delete(listener);
1830
+ };
1831
+ }
1832
+ };
1833
+ };
1834
+
1835
+ // src/client/turnLatencyWidget.ts
1836
+ var DEFAULT_TITLE6 = "Turn Latency";
1837
+ var DEFAULT_DESCRIPTION6 = "Per-turn timing from first transcript to commit and assistant response start.";
1838
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1839
+ var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
1840
+ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
1841
+ const turns = (snapshot.report?.turns ?? []).map((turn) => ({
1842
+ ...turn,
1843
+ label: turn.text || "Empty turn",
1844
+ rows: turn.stages.map((stage) => ({
1845
+ label: stage.label,
1846
+ value: formatMs2(stage.valueMs)
1847
+ }))
1848
+ }));
1849
+ const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
1850
+ const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
1851
+ return {
1852
+ description: options.description ?? DEFAULT_DESCRIPTION6,
1853
+ error: snapshot.error,
1854
+ isLoading: snapshot.isLoading,
1855
+ label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
1856
+ status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1857
+ title: options.title ?? DEFAULT_TITLE6,
1858
+ turns,
1859
+ updatedAt: snapshot.updatedAt
1860
+ };
1861
+ };
1862
+ var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
1863
+ const model = createVoiceTurnLatencyViewModel(snapshot, options);
1864
+ const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml7(turn.status)}">
1865
+ <header>
1866
+ <strong>${escapeHtml7(turn.label)}</strong>
1867
+ <span>${escapeHtml7(turn.status)}</span>
1868
+ </header>
1869
+ <dl>${turn.rows.map((row) => `<div>
1870
+ <dt>${escapeHtml7(row.label)}</dt>
1871
+ <dd>${escapeHtml7(row.value)}</dd>
1872
+ </div>`).join("")}</dl>
1873
+ </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
1874
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml7(model.status)}">
1875
+ <header class="absolute-voice-turn-latency__header">
1876
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml7(model.title)}</span>
1877
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml7(model.label)}</strong>
1878
+ </header>
1879
+ <p class="absolute-voice-turn-latency__description">${escapeHtml7(model.description)}</p>
1880
+ ${turns}
1881
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml7(model.error)}</p>` : ""}
1882
+ </section>`;
1883
+ };
1884
+ var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
1885
+ const store = createVoiceTurnLatencyStore(path, options);
1886
+ const render = () => {
1887
+ element.innerHTML = renderVoiceTurnLatencyHTML(store.getSnapshot(), options);
1888
+ };
1889
+ const unsubscribe = store.subscribe(render);
1890
+ render();
1891
+ store.refresh().catch(() => {});
1892
+ return {
1893
+ close: () => {
1894
+ unsubscribe();
1895
+ store.close();
1896
+ },
1897
+ refresh: store.refresh
1898
+ };
1899
+ };
1900
+ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") => {
1901
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
1902
+ return;
1903
+ }
1904
+ customElements.define(tagName, class AbsoluteVoiceTurnLatencyElement extends HTMLElement {
1905
+ mounted;
1906
+ connectedCallback() {
1907
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
1908
+ this.mounted = mountVoiceTurnLatency(this, this.getAttribute("path") ?? "/api/turn-latency", {
1909
+ description: this.getAttribute("description") ?? undefined,
1910
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
1911
+ title: this.getAttribute("title") ?? undefined
1912
+ });
1913
+ }
1914
+ disconnectedCallback() {
1915
+ this.mounted?.close();
1916
+ this.mounted = undefined;
1917
+ }
1918
+ });
1919
+ };
1920
+
1921
+ // src/svelte/createVoiceTurnLatency.ts
1922
+ var createVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
1923
+ const store = createVoiceTurnLatencyStore(path, options);
1924
+ return {
1925
+ ...store,
1926
+ getHTML: () => renderVoiceTurnLatencyHTML(store.getSnapshot(), options),
1927
+ getViewModel: () => createVoiceTurnLatencyViewModel(store.getSnapshot(), options)
1928
+ };
1929
+ };
1760
1930
  // src/client/turnQuality.ts
1761
1931
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
1762
1932
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -1837,9 +2007,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
1837
2007
  };
1838
2008
 
1839
2009
  // src/client/turnQualityWidget.ts
1840
- var DEFAULT_TITLE6 = "Turn Quality";
1841
- var DEFAULT_DESCRIPTION6 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
1842
- var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2010
+ var DEFAULT_TITLE7 = "Turn Quality";
2011
+ var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
2012
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1843
2013
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
1844
2014
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
1845
2015
  var getTurnDetail = (turn) => {
@@ -1877,37 +2047,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
1877
2047
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
1878
2048
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
1879
2049
  return {
1880
- description: options.description ?? DEFAULT_DESCRIPTION6,
2050
+ description: options.description ?? DEFAULT_DESCRIPTION7,
1881
2051
  error: snapshot.error,
1882
2052
  isLoading: snapshot.isLoading,
1883
2053
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
1884
2054
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1885
- title: options.title ?? DEFAULT_TITLE6,
2055
+ title: options.title ?? DEFAULT_TITLE7,
1886
2056
  turns,
1887
2057
  updatedAt: snapshot.updatedAt
1888
2058
  };
1889
2059
  };
1890
2060
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
1891
2061
  const model = createVoiceTurnQualityViewModel(snapshot, options);
1892
- 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--${escapeHtml7(turn.status)}">
2062
+ const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml8(turn.status)}">
1893
2063
  <header>
1894
- <strong>${escapeHtml7(turn.label)}</strong>
1895
- <span>${escapeHtml7(turn.status)}</span>
2064
+ <strong>${escapeHtml8(turn.label)}</strong>
2065
+ <span>${escapeHtml8(turn.status)}</span>
1896
2066
  </header>
1897
- <p>${escapeHtml7(turn.detail)}</p>
2067
+ <p>${escapeHtml8(turn.detail)}</p>
1898
2068
  <dl>${turn.rows.map((row) => `<div>
1899
- <dt>${escapeHtml7(row.label)}</dt>
1900
- <dd>${escapeHtml7(row.value)}</dd>
2069
+ <dt>${escapeHtml8(row.label)}</dt>
2070
+ <dd>${escapeHtml8(row.value)}</dd>
1901
2071
  </div>`).join("")}</dl>
1902
2072
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
1903
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml7(model.status)}">
2073
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml8(model.status)}">
1904
2074
  <header class="absolute-voice-turn-quality__header">
1905
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml7(model.title)}</span>
1906
- <strong class="absolute-voice-turn-quality__label">${escapeHtml7(model.label)}</strong>
2075
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml8(model.title)}</span>
2076
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml8(model.label)}</strong>
1907
2077
  </header>
1908
- <p class="absolute-voice-turn-quality__description">${escapeHtml7(model.description)}</p>
2078
+ <p class="absolute-voice-turn-quality__description">${escapeHtml8(model.description)}</p>
1909
2079
  ${turns}
1910
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml7(model.error)}</p>` : ""}
2080
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml8(model.error)}</p>` : ""}
1911
2081
  </section>`;
1912
2082
  };
1913
2083
  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}`;
@@ -2676,6 +2846,7 @@ var createVoiceController = (path, options = {}) => {
2676
2846
  export {
2677
2847
  createVoiceWorkflowStatus,
2678
2848
  createVoiceTurnQuality,
2849
+ createVoiceTurnLatency,
2679
2850
  createVoiceTraceTimeline,
2680
2851
  createVoiceStream2 as createVoiceStream,
2681
2852
  createVoiceRoutingStatus,
@@ -5216,7 +5216,7 @@ var createVoiceSession = (options) => {
5216
5216
  } : undefined;
5217
5217
  const appendTrace = async (input) => {
5218
5218
  await options.trace?.append({
5219
- at: Date.now(),
5219
+ at: input.at ?? Date.now(),
5220
5220
  metadata: input.metadata,
5221
5221
  payload: input.payload,
5222
5222
  scenarioId: input.session?.scenarioId ?? options.scenarioId,
@@ -5225,6 +5225,13 @@ var createVoiceSession = (options) => {
5225
5225
  type: input.type
5226
5226
  });
5227
5227
  };
5228
+ const appendTurnLatencyStage = async (input) => appendTrace({
5229
+ at: input.at,
5230
+ payload: { stage: input.stage },
5231
+ session: input.session,
5232
+ turnId: input.turnId,
5233
+ type: "turn_latency.stage"
5234
+ });
5228
5235
  const phraseHints = options.phraseHints ?? [];
5229
5236
  const lexicon = options.lexicon ?? [];
5230
5237
  let socket = options.socket;
@@ -6175,6 +6182,13 @@ var createVoiceSession = (options) => {
6175
6182
  turnId: activeTTSTurnId,
6176
6183
  type: "audio"
6177
6184
  });
6185
+ if (activeTTSTurnId) {
6186
+ await appendTurnLatencyStage({
6187
+ at: receivedAt,
6188
+ stage: "assistant_audio_received",
6189
+ turnId: activeTTSTurnId
6190
+ });
6191
+ }
6178
6192
  });
6179
6193
  });
6180
6194
  openedSession.on("error", (event) => {
@@ -6233,6 +6247,7 @@ var createVoiceSession = (options) => {
6233
6247
  voicemail: committedOutput?.voicemail
6234
6248
  };
6235
6249
  if (output?.assistantText) {
6250
+ const assistantTextStartedAt = Date.now();
6236
6251
  await writeSession((currentSession) => {
6237
6252
  setTurnResult(currentSession, turn.id, {
6238
6253
  assistantText: output.assistantText
@@ -6243,6 +6258,12 @@ var createVoiceSession = (options) => {
6243
6258
  turnId: turn.id,
6244
6259
  type: "assistant"
6245
6260
  });
6261
+ await appendTurnLatencyStage({
6262
+ at: assistantTextStartedAt,
6263
+ session,
6264
+ stage: "assistant_text_started",
6265
+ turnId: turn.id
6266
+ });
6246
6267
  await appendTrace({
6247
6268
  payload: {
6248
6269
  text: output.assistantText,
@@ -6257,7 +6278,18 @@ var createVoiceSession = (options) => {
6257
6278
  if (activeTTSSession) {
6258
6279
  const ttsStartedAt = Date.now();
6259
6280
  activeTTSTurnId = turn.id;
6281
+ await appendTurnLatencyStage({
6282
+ at: ttsStartedAt,
6283
+ session,
6284
+ stage: "tts_send_started",
6285
+ turnId: turn.id
6286
+ });
6260
6287
  await activeTTSSession.send(output.assistantText);
6288
+ await appendTurnLatencyStage({
6289
+ session,
6290
+ stage: "tts_send_completed",
6291
+ turnId: turn.id
6292
+ });
6261
6293
  await appendTrace({
6262
6294
  payload: {
6263
6295
  elapsedMs: Date.now() - ttsStartedAt,
@@ -6454,6 +6486,30 @@ var createVoiceSession = (options) => {
6454
6486
  turnId: turn.id,
6455
6487
  type: "turn.cost"
6456
6488
  });
6489
+ const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
6490
+ const finalTranscriptAt = turn.transcripts.filter((transcript) => transcript.isFinal).map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
6491
+ if (firstTranscriptAt !== undefined) {
6492
+ await appendTurnLatencyStage({
6493
+ at: firstTranscriptAt,
6494
+ session: updatedSession,
6495
+ stage: "speech_detected",
6496
+ turnId: turn.id
6497
+ });
6498
+ }
6499
+ if (finalTranscriptAt !== undefined) {
6500
+ await appendTurnLatencyStage({
6501
+ at: finalTranscriptAt,
6502
+ session: updatedSession,
6503
+ stage: "final_transcript",
6504
+ turnId: turn.id
6505
+ });
6506
+ }
6507
+ await appendTurnLatencyStage({
6508
+ at: turn.committedAt,
6509
+ session: updatedSession,
6510
+ stage: "turn_committed",
6511
+ turnId: turn.id
6512
+ });
6457
6513
  await send({
6458
6514
  turn,
6459
6515
  type: "turn"
package/dist/trace.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn.transcript' | 'workflow.contract';
1
+ export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
2
2
  export type VoiceTraceEvent<TPayload extends Record<string, unknown> = Record<string, unknown>> = {
3
3
  at: number;
4
4
  id?: string;
@@ -0,0 +1,95 @@
1
+ import { Elysia } from 'elysia';
2
+ import type { VoiceTraceEventStore } from './trace';
3
+ import type { VoiceSessionRecord, VoiceSessionStore } from './types';
4
+ export type VoiceTurnLatencyStatus = 'pass' | 'warn' | 'fail' | 'empty';
5
+ export type VoiceTurnLatencyStage = {
6
+ label: string;
7
+ valueMs?: number;
8
+ };
9
+ export type VoiceTurnLatencyItem = {
10
+ assistantTextStartedAt?: number;
11
+ committedAt: number;
12
+ finalTranscriptAt?: number;
13
+ firstTranscriptAt?: number;
14
+ sessionId: string;
15
+ stages: VoiceTurnLatencyStage[];
16
+ status: VoiceTurnLatencyStatus;
17
+ text: string;
18
+ totalMs?: number;
19
+ turnId: string;
20
+ };
21
+ export type VoiceTurnLatencyReport = {
22
+ averageTotalMs?: number;
23
+ checkedAt: number;
24
+ failed: number;
25
+ sessions: number;
26
+ status: VoiceTurnLatencyStatus;
27
+ total: number;
28
+ turns: VoiceTurnLatencyItem[];
29
+ warnings: number;
30
+ };
31
+ export type VoiceTurnLatencyOptions<TSession extends VoiceSessionRecord = VoiceSessionRecord> = {
32
+ limit?: number;
33
+ sessionIds?: string[];
34
+ sessions?: TSession[];
35
+ store?: VoiceSessionStore<TSession>;
36
+ traceStore?: VoiceTraceEventStore;
37
+ warnAfterMs?: number;
38
+ failAfterMs?: number;
39
+ };
40
+ export type VoiceTurnLatencyHTMLHandlerOptions<TSession extends VoiceSessionRecord = VoiceSessionRecord> = VoiceTurnLatencyOptions<TSession> & {
41
+ headers?: HeadersInit;
42
+ render?: (report: VoiceTurnLatencyReport) => string | Promise<string>;
43
+ title?: string;
44
+ };
45
+ export type VoiceTurnLatencyRoutesOptions<TSession extends VoiceSessionRecord = VoiceSessionRecord> = VoiceTurnLatencyHTMLHandlerOptions<TSession> & {
46
+ htmlPath?: false | string;
47
+ name?: string;
48
+ path?: string;
49
+ };
50
+ export declare const summarizeVoiceTurnLatency: <TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: VoiceTurnLatencyOptions<TSession>) => Promise<VoiceTurnLatencyReport>;
51
+ export declare const renderVoiceTurnLatencyHTML: (report: VoiceTurnLatencyReport, options?: {
52
+ title?: string;
53
+ }) => string;
54
+ export declare const createVoiceTurnLatencyJSONHandler: <TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: VoiceTurnLatencyOptions<TSession>) => () => Promise<VoiceTurnLatencyReport>;
55
+ export declare const createVoiceTurnLatencyHTMLHandler: <TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: VoiceTurnLatencyHTMLHandlerOptions<TSession>) => () => Promise<Response>;
56
+ export declare const createVoiceTurnLatencyRoutes: <TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: VoiceTurnLatencyRoutesOptions<TSession>) => Elysia<"", {
57
+ decorator: {};
58
+ store: {};
59
+ derive: {};
60
+ resolve: {};
61
+ }, {
62
+ typebox: {};
63
+ error: {};
64
+ }, {
65
+ schema: {};
66
+ standaloneSchema: {};
67
+ macro: {};
68
+ macroFn: {};
69
+ parser: {};
70
+ response: {};
71
+ }, {
72
+ [x: string]: {
73
+ get: {
74
+ body: unknown;
75
+ params: {};
76
+ query: unknown;
77
+ headers: unknown;
78
+ response: {
79
+ 200: VoiceTurnLatencyReport;
80
+ };
81
+ };
82
+ };
83
+ }, {
84
+ derive: {};
85
+ resolve: {};
86
+ schema: {};
87
+ standaloneSchema: {};
88
+ response: {};
89
+ }, {
90
+ derive: {};
91
+ resolve: {};
92
+ schema: {};
93
+ standaloneSchema: {};
94
+ response: {};
95
+ }>;
@@ -0,0 +1,51 @@
1
+ export declare const VoiceTurnLatency: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
+ class: {
3
+ default: string;
4
+ type: StringConstructor;
5
+ };
6
+ description: {
7
+ default: undefined;
8
+ type: StringConstructor;
9
+ };
10
+ intervalMs: {
11
+ default: number;
12
+ type: NumberConstructor;
13
+ };
14
+ path: {
15
+ default: string;
16
+ type: StringConstructor;
17
+ };
18
+ title: {
19
+ default: undefined;
20
+ type: StringConstructor;
21
+ };
22
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
23
+ [key: string]: any;
24
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
25
+ class: {
26
+ default: string;
27
+ type: StringConstructor;
28
+ };
29
+ description: {
30
+ default: undefined;
31
+ type: StringConstructor;
32
+ };
33
+ intervalMs: {
34
+ default: number;
35
+ type: NumberConstructor;
36
+ };
37
+ path: {
38
+ default: string;
39
+ type: StringConstructor;
40
+ };
41
+ title: {
42
+ default: undefined;
43
+ type: StringConstructor;
44
+ };
45
+ }>> & Readonly<{}>, {
46
+ description: string;
47
+ title: string;
48
+ path: string;
49
+ intervalMs: number;
50
+ class: string;
51
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -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 { VoiceTurnLatency } from './VoiceTurnLatency';
6
7
  export { VoiceTurnQuality } from './VoiceTurnQuality';
7
8
  export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
8
9
  export { useVoiceStream } from './useVoiceStream';
@@ -12,5 +13,6 @@ export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
12
13
  export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
13
14
  export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
14
15
  export { useVoiceTraceTimeline } from './useVoiceTraceTimeline';
16
+ export { useVoiceTurnLatency } from './useVoiceTurnLatency';
15
17
  export { useVoiceTurnQuality } from './useVoiceTurnQuality';
16
18
  export { useVoiceWorkflowStatus } from './useVoiceWorkflowStatus';