@absolutejs/voice 0.0.22-beta.93 → 0.0.22-beta.95

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.
@@ -2330,6 +2330,80 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
2330
2330
  }
2331
2331
  };
2332
2332
  };
2333
+ // src/client/turnLatency.ts
2334
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
2335
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2336
+ const response = await fetchImpl(path);
2337
+ if (!response.ok) {
2338
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
2339
+ }
2340
+ return await response.json();
2341
+ };
2342
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
2343
+ const listeners = new Set;
2344
+ let closed = false;
2345
+ let timer;
2346
+ let snapshot = {
2347
+ error: null,
2348
+ isLoading: false
2349
+ };
2350
+ const emit = () => {
2351
+ for (const listener of listeners) {
2352
+ listener();
2353
+ }
2354
+ };
2355
+ const refresh = async () => {
2356
+ if (closed) {
2357
+ return snapshot.report;
2358
+ }
2359
+ snapshot = { ...snapshot, error: null, isLoading: true };
2360
+ emit();
2361
+ try {
2362
+ const report = await fetchVoiceTurnLatency(path, options);
2363
+ snapshot = {
2364
+ error: null,
2365
+ isLoading: false,
2366
+ report,
2367
+ updatedAt: Date.now()
2368
+ };
2369
+ emit();
2370
+ return report;
2371
+ } catch (error) {
2372
+ snapshot = {
2373
+ ...snapshot,
2374
+ error: error instanceof Error ? error.message : String(error),
2375
+ isLoading: false
2376
+ };
2377
+ emit();
2378
+ throw error;
2379
+ }
2380
+ };
2381
+ const close = () => {
2382
+ closed = true;
2383
+ if (timer) {
2384
+ clearInterval(timer);
2385
+ timer = undefined;
2386
+ }
2387
+ listeners.clear();
2388
+ };
2389
+ if (options.intervalMs && options.intervalMs > 0) {
2390
+ timer = setInterval(() => {
2391
+ refresh().catch(() => {});
2392
+ }, options.intervalMs);
2393
+ }
2394
+ return {
2395
+ close,
2396
+ getServerSnapshot: () => snapshot,
2397
+ getSnapshot: () => snapshot,
2398
+ refresh,
2399
+ subscribe: (listener) => {
2400
+ listeners.add(listener);
2401
+ return () => {
2402
+ listeners.delete(listener);
2403
+ };
2404
+ }
2405
+ };
2406
+ };
2333
2407
  // src/client/traceTimeline.ts
2334
2408
  var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
2335
2409
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -2927,51 +3001,136 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
2927
3001
  }
2928
3002
  });
2929
3003
  };
2930
- // src/client/traceTimelineWidget.ts
2931
- var DEFAULT_TITLE6 = "Voice Traces";
2932
- var DEFAULT_DESCRIPTION6 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
3004
+ // src/client/turnLatencyWidget.ts
3005
+ var DEFAULT_TITLE6 = "Turn Latency";
3006
+ var DEFAULT_DESCRIPTION6 = "Per-turn timing from first transcript to commit and assistant response start.";
2933
3007
  var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2934
- var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
3008
+ var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
3009
+ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
3010
+ const turns = (snapshot.report?.turns ?? []).map((turn) => ({
3011
+ ...turn,
3012
+ label: turn.text || "Empty turn",
3013
+ rows: turn.stages.map((stage) => ({
3014
+ label: stage.label,
3015
+ value: formatMs(stage.valueMs)
3016
+ }))
3017
+ }));
3018
+ const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
3019
+ const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
3020
+ return {
3021
+ description: options.description ?? DEFAULT_DESCRIPTION6,
3022
+ error: snapshot.error,
3023
+ isLoading: snapshot.isLoading,
3024
+ label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
3025
+ status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3026
+ title: options.title ?? DEFAULT_TITLE6,
3027
+ turns,
3028
+ updatedAt: snapshot.updatedAt
3029
+ };
3030
+ };
3031
+ var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
3032
+ const model = createVoiceTurnLatencyViewModel(snapshot, options);
3033
+ 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)}">
3034
+ <header>
3035
+ <strong>${escapeHtml7(turn.label)}</strong>
3036
+ <span>${escapeHtml7(turn.status)}</span>
3037
+ </header>
3038
+ <dl>${turn.rows.map((row) => `<div>
3039
+ <dt>${escapeHtml7(row.label)}</dt>
3040
+ <dd>${escapeHtml7(row.value)}</dd>
3041
+ </div>`).join("")}</dl>
3042
+ </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
3043
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml7(model.status)}">
3044
+ <header class="absolute-voice-turn-latency__header">
3045
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml7(model.title)}</span>
3046
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml7(model.label)}</strong>
3047
+ </header>
3048
+ <p class="absolute-voice-turn-latency__description">${escapeHtml7(model.description)}</p>
3049
+ ${turns}
3050
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml7(model.error)}</p>` : ""}
3051
+ </section>`;
3052
+ };
3053
+ var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
3054
+ const store = createVoiceTurnLatencyStore(path, options);
3055
+ const render = () => {
3056
+ element.innerHTML = renderVoiceTurnLatencyHTML(store.getSnapshot(), options);
3057
+ };
3058
+ const unsubscribe = store.subscribe(render);
3059
+ render();
3060
+ store.refresh().catch(() => {});
3061
+ return {
3062
+ close: () => {
3063
+ unsubscribe();
3064
+ store.close();
3065
+ },
3066
+ refresh: store.refresh
3067
+ };
3068
+ };
3069
+ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") => {
3070
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
3071
+ return;
3072
+ }
3073
+ customElements.define(tagName, class AbsoluteVoiceTurnLatencyElement extends HTMLElement {
3074
+ mounted;
3075
+ connectedCallback() {
3076
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
3077
+ this.mounted = mountVoiceTurnLatency(this, this.getAttribute("path") ?? "/api/turn-latency", {
3078
+ description: this.getAttribute("description") ?? undefined,
3079
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
3080
+ title: this.getAttribute("title") ?? undefined
3081
+ });
3082
+ }
3083
+ disconnectedCallback() {
3084
+ this.mounted?.close();
3085
+ this.mounted = undefined;
3086
+ }
3087
+ });
3088
+ };
3089
+ // src/client/traceTimelineWidget.ts
3090
+ var DEFAULT_TITLE7 = "Voice Traces";
3091
+ var DEFAULT_DESCRIPTION7 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
3092
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3093
+ var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
2935
3094
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
2936
3095
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
2937
3096
  const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
2938
3097
  ...session,
2939
3098
  detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
2940
- durationLabel: formatMs(session.summary.callDurationMs),
3099
+ durationLabel: formatMs2(session.summary.callDurationMs),
2941
3100
  label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
2942
3101
  providerLabel: formatProviders(session)
2943
3102
  }));
2944
3103
  const failed = sessions.filter((session) => session.status === "failed").length;
2945
3104
  const warnings = sessions.filter((session) => session.status === "warning").length;
2946
3105
  return {
2947
- description: options.description ?? DEFAULT_DESCRIPTION6,
3106
+ description: options.description ?? DEFAULT_DESCRIPTION7,
2948
3107
  error: snapshot.error,
2949
3108
  isLoading: snapshot.isLoading,
2950
3109
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
2951
3110
  sessions,
2952
3111
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
2953
- title: options.title ?? DEFAULT_TITLE6,
3112
+ title: options.title ?? DEFAULT_TITLE7,
2954
3113
  updatedAt: snapshot.updatedAt
2955
3114
  };
2956
3115
  };
2957
3116
  var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
2958
3117
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
2959
- 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)}">
3118
+ 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)}">
2960
3119
  <header>
2961
- <strong>${escapeHtml7(session.sessionId)}</strong>
2962
- <span>${escapeHtml7(session.status)}</span>
3120
+ <strong>${escapeHtml8(session.sessionId)}</strong>
3121
+ <span>${escapeHtml8(session.status)}</span>
2963
3122
  </header>
2964
- <p>${escapeHtml7(session.label)} \xB7 ${escapeHtml7(session.durationLabel)} \xB7 ${escapeHtml7(session.providerLabel)}</p>
2965
- <a href="${escapeHtml7(session.detailHref)}">Open timeline</a>
3123
+ <p>${escapeHtml8(session.label)} \xB7 ${escapeHtml8(session.durationLabel)} \xB7 ${escapeHtml8(session.providerLabel)}</p>
3124
+ <a href="${escapeHtml8(session.detailHref)}">Open timeline</a>
2966
3125
  </article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
2967
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml7(model.status)}">
3126
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml8(model.status)}">
2968
3127
  <header class="absolute-voice-trace-timeline__header">
2969
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml7(model.title)}</span>
2970
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml7(model.label)}</strong>
3128
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml8(model.title)}</span>
3129
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml8(model.label)}</strong>
2971
3130
  </header>
2972
- <p class="absolute-voice-trace-timeline__description">${escapeHtml7(model.description)}</p>
3131
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml8(model.description)}</p>
2973
3132
  ${sessions}
2974
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml7(model.error)}</p>` : ""}
3133
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml8(model.error)}</p>` : ""}
2975
3134
  </section>`;
2976
3135
  };
2977
3136
  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}`;
@@ -3094,6 +3253,7 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
3094
3253
  };
3095
3254
  export {
3096
3255
  renderVoiceTurnQualityHTML,
3256
+ renderVoiceTurnLatencyHTML,
3097
3257
  renderVoiceTraceTimelineWidgetHTML,
3098
3258
  renderVoiceRoutingStatusHTML,
3099
3259
  renderVoiceProviderStatusHTML,
@@ -3101,6 +3261,7 @@ export {
3101
3261
  renderVoiceProviderCapabilitiesHTML,
3102
3262
  renderVoiceOpsStatusHTML,
3103
3263
  mountVoiceTurnQuality,
3264
+ mountVoiceTurnLatency,
3104
3265
  mountVoiceTraceTimeline,
3105
3266
  mountVoiceRoutingStatus,
3106
3267
  mountVoiceProviderStatus,
@@ -3116,12 +3277,14 @@ export {
3116
3277
  getVoiceOpsStatusCSS,
3117
3278
  fetchVoiceWorkflowStatus,
3118
3279
  fetchVoiceTurnQuality,
3280
+ fetchVoiceTurnLatency,
3119
3281
  fetchVoiceTraceTimeline,
3120
3282
  fetchVoiceRoutingStatus,
3121
3283
  fetchVoiceProviderStatus,
3122
3284
  fetchVoiceProviderCapabilities,
3123
3285
  fetchVoiceAppKitStatus,
3124
3286
  defineVoiceTurnQualityElement,
3287
+ defineVoiceTurnLatencyElement,
3125
3288
  defineVoiceTraceTimelineElement,
3126
3289
  defineVoiceRoutingStatusElement,
3127
3290
  defineVoiceProviderStatusElement,
@@ -3132,6 +3295,8 @@ export {
3132
3295
  createVoiceWorkflowStatusStore,
3133
3296
  createVoiceTurnQualityViewModel,
3134
3297
  createVoiceTurnQualityStore,
3298
+ createVoiceTurnLatencyViewModel,
3299
+ createVoiceTurnLatencyStore,
3135
3300
  createVoiceTraceTimelineViewModel,
3136
3301
  createVoiceTraceTimelineStore,
3137
3302
  createVoiceStream,
@@ -0,0 +1,19 @@
1
+ import type { VoiceTurnLatencyReport } from '../turnLatency';
2
+ export type VoiceTurnLatencyClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceTurnLatencySnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report?: VoiceTurnLatencyReport;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceTurnLatency: (path?: string, options?: Pick<VoiceTurnLatencyClientOptions, "fetch">) => Promise<VoiceTurnLatencyReport>;
13
+ export declare const createVoiceTurnLatencyStore: (path?: string, options?: VoiceTurnLatencyClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceTurnLatencySnapshot;
16
+ getSnapshot: () => VoiceTurnLatencySnapshot;
17
+ refresh: () => Promise<VoiceTurnLatencyReport | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,30 @@
1
+ import type { VoiceTurnLatencyItem } from '../turnLatency';
2
+ import { type VoiceTurnLatencyClientOptions, type VoiceTurnLatencySnapshot } from './turnLatency';
3
+ export type VoiceTurnLatencyCardView = VoiceTurnLatencyItem & {
4
+ label: string;
5
+ rows: Array<{
6
+ label: string;
7
+ value: string;
8
+ }>;
9
+ };
10
+ export type VoiceTurnLatencyViewModel = {
11
+ description: string;
12
+ error: string | null;
13
+ isLoading: boolean;
14
+ label: string;
15
+ status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
16
+ title: string;
17
+ turns: VoiceTurnLatencyCardView[];
18
+ updatedAt?: number;
19
+ };
20
+ export type VoiceTurnLatencyWidgetOptions = VoiceTurnLatencyClientOptions & {
21
+ description?: string;
22
+ title?: string;
23
+ };
24
+ export declare const createVoiceTurnLatencyViewModel: (snapshot: VoiceTurnLatencySnapshot, options?: VoiceTurnLatencyWidgetOptions) => VoiceTurnLatencyViewModel;
25
+ export declare const renderVoiceTurnLatencyHTML: (snapshot: VoiceTurnLatencySnapshot, options?: VoiceTurnLatencyWidgetOptions) => string;
26
+ export declare const mountVoiceTurnLatency: (element: Element, path?: string, options?: VoiceTurnLatencyWidgetOptions) => {
27
+ close: () => void;
28
+ refresh: () => Promise<import("..").VoiceTurnLatencyReport | undefined>;
29
+ };
30
+ export declare const defineVoiceTurnLatencyElement: (tagName?: string) => void;
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, crea
10
10
  export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
11
11
  export { createVoiceToolIdempotencyKey, createVoiceToolRuntime } from './toolRuntime';
12
12
  export { createVoiceToolContract, createVoiceToolContractHTMLHandler, createVoiceToolContractJSONHandler, createVoiceToolContractRoutes, createVoiceToolRuntimeContractDefaults, renderVoiceToolContractHTML, runVoiceToolContractSuite, runVoiceToolContract } from './toolContract';
13
+ export { createVoiceTurnLatencyHTMLHandler, createVoiceTurnLatencyJSONHandler, createVoiceTurnLatencyRoutes, renderVoiceTurnLatencyHTML, summarizeVoiceTurnLatency } from './turnLatency';
13
14
  export { createVoiceTurnQualityHTMLHandler, createVoiceTurnQualityJSONHandler, createVoiceTurnQualityRoutes, renderVoiceTurnQualityHTML, summarizeVoiceTurnQuality } from './turnQuality';
14
15
  export { createVoiceOutcomeContractHTMLHandler, createVoiceOutcomeContractJSONHandler, createVoiceOutcomeContractRoutes, renderVoiceOutcomeContractHTML, runVoiceOutcomeContractSuite } from './outcomeContract';
15
16
  export { applyVoiceTelephonyOutcome, createMemoryVoiceTelephonyWebhookIdempotencyStore, createVoiceTelephonyOutcomePolicy, createVoiceTelephonyWebhookHandler, createVoiceTelephonyWebhookRoutes, parseVoiceTelephonyWebhookEvent, resolveVoiceTelephonyOutcome, signVoiceTwilioWebhook, verifyVoiceTwilioWebhookSignature, voiceTelephonyOutcomeToRouteResult } from './telephonyOutcome';
@@ -61,6 +62,7 @@ export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOpti
61
62
  export type { OpenAIVoiceTTSOptions, OpenAIVoiceTTSVoice } from './openaiTTS';
62
63
  export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProviderHealthSummaryOptions } from './providerHealth';
63
64
  export type { VoiceProviderCapabilityDefinition, VoiceProviderCapabilityHandlerOptions, VoiceProviderCapabilityHTMLHandlerOptions, VoiceProviderCapabilityKind, VoiceProviderCapabilityOptions, VoiceProviderCapabilityReport, VoiceProviderCapabilityRoutesOptions, VoiceProviderCapabilitySummary } from './providerCapabilities';
65
+ export type { VoiceTurnLatencyHTMLHandlerOptions, VoiceTurnLatencyItem, VoiceTurnLatencyOptions, VoiceTurnLatencyReport, VoiceTurnLatencyRoutesOptions, VoiceTurnLatencyStage, VoiceTurnLatencyStatus } from './turnLatency';
64
66
  export type { VoiceTurnQualityHTMLHandlerOptions, VoiceTurnQualityItem, VoiceTurnQualityOptions, VoiceTurnQualityReport, VoiceTurnQualityRoutesOptions, VoiceTurnQualityStatus } from './turnQuality';
65
67
  export type { VoiceOutcomeContractDefinition, VoiceOutcomeContractHTMLHandlerOptions, VoiceOutcomeContractIssue, VoiceOutcomeContractOptions, VoiceOutcomeContractReport, VoiceOutcomeContractRoutesOptions, VoiceOutcomeContractStatus, VoiceOutcomeContractSuiteReport } from './outcomeContract';
66
68
  export type { VoiceTelephonyOutcomeAction, VoiceTelephonyOutcomeDecision, VoiceTelephonyOutcomePolicy, VoiceTelephonyOutcomeProviderEvent, VoiceTelephonyOutcomeRouteResult, VoiceTelephonyOutcomeStatusDecision, VoiceTelephonyWebhookDecision, VoiceTelephonyWebhookHandlerOptions, VoiceTelephonyWebhookIdempotencyStore, VoiceTelephonyWebhookParseInput, VoiceTelephonyWebhookProvider, VoiceTelephonyWebhookRoutesOptions, VoiceTelephonyWebhookVerificationResult, StoredVoiceTelephonyWebhookDecision } from './telephonyOutcome';