@absolutejs/voice 0.0.22-beta.65 → 0.0.22-beta.67

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.
@@ -2073,6 +2073,162 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
2073
2073
  }
2074
2074
  };
2075
2075
  };
2076
+ // src/client/providerCapabilities.ts
2077
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
2078
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2079
+ const response = await fetchImpl(path);
2080
+ if (!response.ok) {
2081
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
2082
+ }
2083
+ return await response.json();
2084
+ };
2085
+ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
2086
+ const listeners = new Set;
2087
+ let closed = false;
2088
+ let timer;
2089
+ let snapshot = {
2090
+ error: null,
2091
+ isLoading: false
2092
+ };
2093
+ const emit = () => {
2094
+ for (const listener of listeners) {
2095
+ listener();
2096
+ }
2097
+ };
2098
+ const refresh = async () => {
2099
+ if (closed) {
2100
+ return snapshot.report;
2101
+ }
2102
+ snapshot = {
2103
+ ...snapshot,
2104
+ error: null,
2105
+ isLoading: true
2106
+ };
2107
+ emit();
2108
+ try {
2109
+ const report = await fetchVoiceProviderCapabilities(path, options);
2110
+ snapshot = {
2111
+ error: null,
2112
+ isLoading: false,
2113
+ report,
2114
+ updatedAt: Date.now()
2115
+ };
2116
+ emit();
2117
+ return report;
2118
+ } catch (error) {
2119
+ snapshot = {
2120
+ ...snapshot,
2121
+ error: error instanceof Error ? error.message : String(error),
2122
+ isLoading: false
2123
+ };
2124
+ emit();
2125
+ throw error;
2126
+ }
2127
+ };
2128
+ const close = () => {
2129
+ closed = true;
2130
+ if (timer) {
2131
+ clearInterval(timer);
2132
+ timer = undefined;
2133
+ }
2134
+ listeners.clear();
2135
+ };
2136
+ if (options.intervalMs && options.intervalMs > 0) {
2137
+ timer = setInterval(() => {
2138
+ refresh().catch(() => {});
2139
+ }, options.intervalMs);
2140
+ }
2141
+ return {
2142
+ close,
2143
+ getServerSnapshot: () => snapshot,
2144
+ getSnapshot: () => snapshot,
2145
+ refresh,
2146
+ subscribe: (listener) => {
2147
+ listeners.add(listener);
2148
+ return () => {
2149
+ listeners.delete(listener);
2150
+ };
2151
+ }
2152
+ };
2153
+ };
2154
+ // src/client/turnQuality.ts
2155
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
2156
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2157
+ const response = await fetchImpl(path);
2158
+ if (!response.ok) {
2159
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
2160
+ }
2161
+ return await response.json();
2162
+ };
2163
+ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
2164
+ const listeners = new Set;
2165
+ let closed = false;
2166
+ let timer;
2167
+ let snapshot = {
2168
+ error: null,
2169
+ isLoading: false
2170
+ };
2171
+ const emit = () => {
2172
+ for (const listener of listeners) {
2173
+ listener();
2174
+ }
2175
+ };
2176
+ const refresh = async () => {
2177
+ if (closed) {
2178
+ return snapshot.report;
2179
+ }
2180
+ snapshot = {
2181
+ ...snapshot,
2182
+ error: null,
2183
+ isLoading: true
2184
+ };
2185
+ emit();
2186
+ try {
2187
+ const report = await fetchVoiceTurnQuality(path, options);
2188
+ snapshot = {
2189
+ error: null,
2190
+ isLoading: false,
2191
+ report,
2192
+ updatedAt: Date.now()
2193
+ };
2194
+ emit();
2195
+ return report;
2196
+ } catch (error) {
2197
+ snapshot = {
2198
+ ...snapshot,
2199
+ error: error instanceof Error ? error.message : String(error),
2200
+ isLoading: false
2201
+ };
2202
+ emit();
2203
+ throw error;
2204
+ }
2205
+ };
2206
+ const close = () => {
2207
+ closed = true;
2208
+ if (timer) {
2209
+ clearInterval(timer);
2210
+ timer = undefined;
2211
+ }
2212
+ listeners.clear();
2213
+ };
2214
+ if (options.intervalMs && options.intervalMs > 0) {
2215
+ timer = setInterval(() => {
2216
+ refresh().catch(() => {});
2217
+ }, options.intervalMs);
2218
+ }
2219
+ return {
2220
+ close,
2221
+ getServerSnapshot: () => snapshot,
2222
+ getSnapshot: () => snapshot,
2223
+ refresh,
2224
+ subscribe: (listener) => {
2225
+ listeners.add(listener);
2226
+ return () => {
2227
+ listeners.delete(listener);
2228
+ };
2229
+ }
2230
+ };
2231
+ };
2076
2232
  // src/client/providerSimulationControls.ts
2077
2233
  var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
2078
2234
  const response = await fetchImpl(`${pathPrefix}/${mode}?provider=${encodeURIComponent(provider)}`, { method: "POST" });
@@ -2364,6 +2520,233 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
2364
2520
  }
2365
2521
  });
2366
2522
  };
2523
+ // src/client/providerCapabilitiesWidget.ts
2524
+ var DEFAULT_TITLE4 = "Provider Capabilities";
2525
+ var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
2526
+ var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2527
+ var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
2528
+ var formatKind2 = (kind) => kind.toUpperCase();
2529
+ var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
2530
+ var getCapabilityDetail = (capability) => {
2531
+ if (!capability.configured) {
2532
+ return "Not configured in this deployment.";
2533
+ }
2534
+ if (capability.selected) {
2535
+ return `Selected ${capability.kind.toUpperCase()} provider for new sessions.`;
2536
+ }
2537
+ if (capability.health?.status === "healthy") {
2538
+ return "Configured and healthy fallback candidate.";
2539
+ }
2540
+ if (capability.health?.status === "idle") {
2541
+ return "Configured; no traffic observed yet.";
2542
+ }
2543
+ if (capability.health?.lastError) {
2544
+ return capability.health.lastError;
2545
+ }
2546
+ return "Configured and available.";
2547
+ };
2548
+ var isWarningStatus2 = (status) => status === "degraded" || status === "rate-limited" || status === "suppressed" || status === "unconfigured";
2549
+ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
2550
+ const capabilities = (snapshot.report?.capabilities ?? []).map((capability) => ({
2551
+ ...capability,
2552
+ detail: getCapabilityDetail(capability),
2553
+ label: `${formatProvider2(capability.provider)} ${formatKind2(capability.kind)}`,
2554
+ rows: [
2555
+ { label: "Status", value: formatStatus2(capability.status) },
2556
+ { label: "Selected", value: capability.selected ? "Yes" : "No" },
2557
+ { label: "Model", value: capability.model ?? "Default" },
2558
+ {
2559
+ label: "Features",
2560
+ value: capability.features?.join(", ") || "Not specified"
2561
+ },
2562
+ { label: "Runs", value: String(capability.health?.runCount ?? 0) },
2563
+ { label: "Errors", value: String(capability.health?.errorCount ?? 0) }
2564
+ ]
2565
+ }));
2566
+ const warningCount = capabilities.filter((capability) => isWarningStatus2(capability.status)).length;
2567
+ const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
2568
+ return {
2569
+ capabilities,
2570
+ description: options.description ?? DEFAULT_DESCRIPTION4,
2571
+ error: snapshot.error,
2572
+ isLoading: snapshot.isLoading,
2573
+ label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
2574
+ status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2575
+ title: options.title ?? DEFAULT_TITLE4,
2576
+ updatedAt: snapshot.updatedAt
2577
+ };
2578
+ };
2579
+ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
2580
+ const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
2581
+ const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml5(capability.status)}">
2582
+ <header>
2583
+ <strong>${escapeHtml5(capability.label)}</strong>
2584
+ <span>${escapeHtml5(formatStatus2(capability.status))}</span>
2585
+ </header>
2586
+ <p>${escapeHtml5(capability.detail)}</p>
2587
+ <dl>${capability.rows.map((row) => `<div>
2588
+ <dt>${escapeHtml5(row.label)}</dt>
2589
+ <dd>${escapeHtml5(row.value)}</dd>
2590
+ </div>`).join("")}</dl>
2591
+ </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
2592
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
2593
+ <header class="absolute-voice-provider-capabilities__header">
2594
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
2595
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
2596
+ </header>
2597
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
2598
+ ${capabilities}
2599
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
2600
+ </section>`;
2601
+ };
2602
+ var getVoiceProviderCapabilitiesCSS = () => `.absolute-voice-provider-capabilities{border:1px solid #bfd7ea;border-radius:20px;background:#f6fbff;color:#08131f;padding:18px;box-shadow:0 18px 40px rgba(14,51,78,.12);font-family:inherit}.absolute-voice-provider-capabilities--error,.absolute-voice-provider-capabilities--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-capabilities__header,.absolute-voice-provider-capabilities__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-capabilities__eyebrow{color:#255f85;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-capabilities__label{font-size:24px;line-height:1}.absolute-voice-provider-capabilities__description,.absolute-voice-provider-capabilities__provider p,.absolute-voice-provider-capabilities__provider dt,.absolute-voice-provider-capabilities__empty{color:#405467}.absolute-voice-provider-capabilities__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-capabilities__provider{background:#fff;border:1px solid #d7e7f3;border-radius:16px;padding:14px}.absolute-voice-provider-capabilities__provider--selected,.absolute-voice-provider-capabilities__provider--healthy{border-color:#86efac}.absolute-voice-provider-capabilities__provider--degraded,.absolute-voice-provider-capabilities__provider--rate-limited,.absolute-voice-provider-capabilities__provider--suppressed,.absolute-voice-provider-capabilities__provider--unconfigured{border-color:#f2a7a7}.absolute-voice-provider-capabilities__provider p{margin:10px 0}.absolute-voice-provider-capabilities__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-capabilities__provider div{background:#f6fbff;border:1px solid #d7e7f3;border-radius:12px;padding:8px}.absolute-voice-provider-capabilities__provider dt{font-size:12px}.absolute-voice-provider-capabilities__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-capabilities__empty{margin:14px 0 0}.absolute-voice-provider-capabilities__error{color:#9f1239;font-weight:700}`;
2603
+ var mountVoiceProviderCapabilities = (element, path = "/api/provider-capabilities", options = {}) => {
2604
+ const store = createVoiceProviderCapabilitiesStore(path, options);
2605
+ const render = () => {
2606
+ element.innerHTML = renderVoiceProviderCapabilitiesHTML(store.getSnapshot(), options);
2607
+ };
2608
+ const unsubscribe = store.subscribe(render);
2609
+ render();
2610
+ store.refresh().catch(() => {});
2611
+ return {
2612
+ close: () => {
2613
+ unsubscribe();
2614
+ store.close();
2615
+ },
2616
+ refresh: store.refresh
2617
+ };
2618
+ };
2619
+ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider-capabilities") => {
2620
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2621
+ return;
2622
+ }
2623
+ customElements.define(tagName, class AbsoluteVoiceProviderCapabilitiesElement extends HTMLElement {
2624
+ mounted;
2625
+ connectedCallback() {
2626
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
2627
+ this.mounted = mountVoiceProviderCapabilities(this, this.getAttribute("path") ?? "/api/provider-capabilities", {
2628
+ description: this.getAttribute("description") ?? undefined,
2629
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
2630
+ title: this.getAttribute("title") ?? undefined
2631
+ });
2632
+ }
2633
+ disconnectedCallback() {
2634
+ this.mounted?.close();
2635
+ this.mounted = undefined;
2636
+ }
2637
+ });
2638
+ };
2639
+ // src/client/turnQualityWidget.ts
2640
+ var DEFAULT_TITLE5 = "Turn Quality";
2641
+ var DEFAULT_DESCRIPTION5 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
2642
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2643
+ var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
2644
+ var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
2645
+ var getTurnDetail = (turn) => {
2646
+ if (turn.status === "fail") {
2647
+ return "Empty or unusable committed turn; inspect transcripts and adapter events.";
2648
+ }
2649
+ if (turn.fallbackUsed) {
2650
+ return `Fallback STT selected${turn.fallbackSelectionReason ? ` by ${turn.fallbackSelectionReason}` : ""}.`;
2651
+ }
2652
+ if (turn.correctionChanged) {
2653
+ return `Correction changed the turn${turn.correctionProvider ? ` via ${turn.correctionProvider}` : ""}.`;
2654
+ }
2655
+ if (turn.status === "warn") {
2656
+ return "Turn completed with quality warnings.";
2657
+ }
2658
+ if (turn.status === "unknown") {
2659
+ return "No quality diagnostics were recorded for this turn.";
2660
+ }
2661
+ return "Turn quality looks healthy.";
2662
+ };
2663
+ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
2664
+ const turns = (snapshot.report?.turns ?? []).map((turn) => ({
2665
+ ...turn,
2666
+ detail: getTurnDetail(turn),
2667
+ label: turn.text || "Empty turn",
2668
+ rows: [
2669
+ { label: "Source", value: turn.source ?? "unknown" },
2670
+ { label: "Confidence", value: formatConfidence(turn.averageConfidence) },
2671
+ { label: "Fallback", value: turn.fallbackUsed ? "Yes" : "No" },
2672
+ { label: "Correction", value: turn.correctionChanged ? "Changed" : "None" },
2673
+ { label: "Transcripts", value: `${turn.selectedTranscriptCount} selected` },
2674
+ { label: "Cost", value: formatMaybe(turn.costUnits) }
2675
+ ]
2676
+ }));
2677
+ const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2678
+ const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2679
+ return {
2680
+ description: options.description ?? DEFAULT_DESCRIPTION5,
2681
+ error: snapshot.error,
2682
+ isLoading: snapshot.isLoading,
2683
+ label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
2684
+ status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2685
+ title: options.title ?? DEFAULT_TITLE5,
2686
+ turns,
2687
+ updatedAt: snapshot.updatedAt
2688
+ };
2689
+ };
2690
+ var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
2691
+ const model = createVoiceTurnQualityViewModel(snapshot, options);
2692
+ 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--${escapeHtml6(turn.status)}">
2693
+ <header>
2694
+ <strong>${escapeHtml6(turn.label)}</strong>
2695
+ <span>${escapeHtml6(turn.status)}</span>
2696
+ </header>
2697
+ <p>${escapeHtml6(turn.detail)}</p>
2698
+ <dl>${turn.rows.map((row) => `<div>
2699
+ <dt>${escapeHtml6(row.label)}</dt>
2700
+ <dd>${escapeHtml6(row.value)}</dd>
2701
+ </div>`).join("")}</dl>
2702
+ </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
2703
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml6(model.status)}">
2704
+ <header class="absolute-voice-turn-quality__header">
2705
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml6(model.title)}</span>
2706
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml6(model.label)}</strong>
2707
+ </header>
2708
+ <p class="absolute-voice-turn-quality__description">${escapeHtml6(model.description)}</p>
2709
+ ${turns}
2710
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml6(model.error)}</p>` : ""}
2711
+ </section>`;
2712
+ };
2713
+ 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}`;
2714
+ var mountVoiceTurnQuality = (element, path = "/api/turn-quality", options = {}) => {
2715
+ const store = createVoiceTurnQualityStore(path, options);
2716
+ const render = () => {
2717
+ element.innerHTML = renderVoiceTurnQualityHTML(store.getSnapshot(), options);
2718
+ };
2719
+ const unsubscribe = store.subscribe(render);
2720
+ render();
2721
+ store.refresh().catch(() => {});
2722
+ return {
2723
+ close: () => {
2724
+ unsubscribe();
2725
+ store.close();
2726
+ },
2727
+ refresh: store.refresh
2728
+ };
2729
+ };
2730
+ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") => {
2731
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2732
+ return;
2733
+ }
2734
+ customElements.define(tagName, class AbsoluteVoiceTurnQualityElement extends HTMLElement {
2735
+ mounted;
2736
+ connectedCallback() {
2737
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
2738
+ this.mounted = mountVoiceTurnQuality(this, this.getAttribute("path") ?? "/api/turn-quality", {
2739
+ description: this.getAttribute("description") ?? undefined,
2740
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
2741
+ title: this.getAttribute("title") ?? undefined
2742
+ });
2743
+ }
2744
+ disconnectedCallback() {
2745
+ this.mounted?.close();
2746
+ this.mounted = undefined;
2747
+ }
2748
+ });
2749
+ };
2367
2750
  // src/client/workflowStatus.ts
2368
2751
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
2369
2752
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -2443,28 +2826,40 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
2443
2826
  };
2444
2827
  };
2445
2828
  export {
2829
+ renderVoiceTurnQualityHTML,
2446
2830
  renderVoiceRoutingStatusHTML,
2447
2831
  renderVoiceProviderStatusHTML,
2448
2832
  renderVoiceProviderSimulationControlsHTML,
2833
+ renderVoiceProviderCapabilitiesHTML,
2449
2834
  renderVoiceOpsStatusHTML,
2835
+ mountVoiceTurnQuality,
2450
2836
  mountVoiceRoutingStatus,
2451
2837
  mountVoiceProviderStatus,
2452
2838
  mountVoiceProviderSimulationControls,
2839
+ mountVoiceProviderCapabilities,
2453
2840
  mountVoiceOpsStatus,
2841
+ getVoiceTurnQualityCSS,
2454
2842
  getVoiceRoutingStatusCSS,
2455
2843
  getVoiceProviderStatusCSS,
2844
+ getVoiceProviderCapabilitiesCSS,
2456
2845
  getVoiceOpsStatusLabel,
2457
2846
  getVoiceOpsStatusCSS,
2458
2847
  fetchVoiceWorkflowStatus,
2848
+ fetchVoiceTurnQuality,
2459
2849
  fetchVoiceRoutingStatus,
2460
2850
  fetchVoiceProviderStatus,
2851
+ fetchVoiceProviderCapabilities,
2461
2852
  fetchVoiceAppKitStatus,
2853
+ defineVoiceTurnQualityElement,
2462
2854
  defineVoiceRoutingStatusElement,
2463
2855
  defineVoiceProviderStatusElement,
2464
2856
  defineVoiceProviderSimulationControlsElement,
2857
+ defineVoiceProviderCapabilitiesElement,
2465
2858
  defineVoiceOpsStatusElement,
2466
2859
  decodeVoiceAudioChunk,
2467
2860
  createVoiceWorkflowStatusStore,
2861
+ createVoiceTurnQualityViewModel,
2862
+ createVoiceTurnQualityStore,
2468
2863
  createVoiceStream,
2469
2864
  createVoiceRoutingStatusViewModel,
2470
2865
  createVoiceRoutingStatusStore,
@@ -2472,6 +2867,8 @@ export {
2472
2867
  createVoiceProviderStatusStore,
2473
2868
  createVoiceProviderSimulationControlsViewModel,
2474
2869
  createVoiceProviderSimulationControlsStore,
2870
+ createVoiceProviderCapabilitiesViewModel,
2871
+ createVoiceProviderCapabilitiesStore,
2475
2872
  createVoiceOpsStatusViewModel,
2476
2873
  createVoiceDuplexController,
2477
2874
  createVoiceController,
@@ -0,0 +1,19 @@
1
+ import type { VoiceProviderCapabilityReport } from '../providerCapabilities';
2
+ export type VoiceProviderCapabilitiesClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceProviderCapabilitiesSnapshot<TProvider extends string = string> = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report?: VoiceProviderCapabilityReport<TProvider>;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceProviderCapabilities: <TProvider extends string = string>(path?: string, options?: Pick<VoiceProviderCapabilitiesClientOptions, "fetch">) => Promise<VoiceProviderCapabilityReport<TProvider>>;
13
+ export declare const createVoiceProviderCapabilitiesStore: <TProvider extends string = string>(path?: string, options?: VoiceProviderCapabilitiesClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceProviderCapabilitiesSnapshot<TProvider>;
16
+ getSnapshot: () => VoiceProviderCapabilitiesSnapshot<TProvider>;
17
+ refresh: () => Promise<VoiceProviderCapabilityReport<TProvider> | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,32 @@
1
+ import type { VoiceProviderCapabilitySummary } from '../providerCapabilities';
2
+ import { type VoiceProviderCapabilitiesClientOptions, type VoiceProviderCapabilitiesSnapshot } from './providerCapabilities';
3
+ export type VoiceProviderCapabilityCardView<TProvider extends string = string> = VoiceProviderCapabilitySummary<TProvider> & {
4
+ detail: string;
5
+ label: string;
6
+ rows: Array<{
7
+ label: string;
8
+ value: string;
9
+ }>;
10
+ };
11
+ export type VoiceProviderCapabilitiesViewModel<TProvider extends string = string> = {
12
+ capabilities: VoiceProviderCapabilityCardView<TProvider>[];
13
+ description: string;
14
+ error: string | null;
15
+ isLoading: boolean;
16
+ label: string;
17
+ status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
18
+ title: string;
19
+ updatedAt?: number;
20
+ };
21
+ export type VoiceProviderCapabilitiesWidgetOptions = VoiceProviderCapabilitiesClientOptions & {
22
+ description?: string;
23
+ title?: string;
24
+ };
25
+ export declare const createVoiceProviderCapabilitiesViewModel: <TProvider extends string = string>(snapshot: VoiceProviderCapabilitiesSnapshot<TProvider>, options?: VoiceProviderCapabilitiesWidgetOptions) => VoiceProviderCapabilitiesViewModel<TProvider>;
26
+ export declare const renderVoiceProviderCapabilitiesHTML: <TProvider extends string = string>(snapshot: VoiceProviderCapabilitiesSnapshot<TProvider>, options?: VoiceProviderCapabilitiesWidgetOptions) => string;
27
+ export declare const getVoiceProviderCapabilitiesCSS: () => string;
28
+ export declare const mountVoiceProviderCapabilities: <TProvider extends string = string>(element: Element, path?: string, options?: VoiceProviderCapabilitiesWidgetOptions) => {
29
+ close: () => void;
30
+ refresh: () => Promise<import("..").VoiceProviderCapabilityReport<TProvider> | undefined>;
31
+ };
32
+ export declare const defineVoiceProviderCapabilitiesElement: (tagName?: string) => void;
@@ -0,0 +1,19 @@
1
+ import type { VoiceTurnQualityReport } from '../turnQuality';
2
+ export type VoiceTurnQualityClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceTurnQualitySnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report?: VoiceTurnQualityReport;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceTurnQuality: (path?: string, options?: Pick<VoiceTurnQualityClientOptions, "fetch">) => Promise<VoiceTurnQualityReport>;
13
+ export declare const createVoiceTurnQualityStore: (path?: string, options?: VoiceTurnQualityClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceTurnQualitySnapshot;
16
+ getSnapshot: () => VoiceTurnQualitySnapshot;
17
+ refresh: () => Promise<VoiceTurnQualityReport | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,32 @@
1
+ import type { VoiceTurnQualityItem } from '../turnQuality';
2
+ import { type VoiceTurnQualityClientOptions, type VoiceTurnQualitySnapshot } from './turnQuality';
3
+ export type VoiceTurnQualityCardView = VoiceTurnQualityItem & {
4
+ detail: string;
5
+ label: string;
6
+ rows: Array<{
7
+ label: string;
8
+ value: string;
9
+ }>;
10
+ };
11
+ export type VoiceTurnQualityViewModel = {
12
+ description: string;
13
+ error: string | null;
14
+ isLoading: boolean;
15
+ label: string;
16
+ status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
17
+ title: string;
18
+ turns: VoiceTurnQualityCardView[];
19
+ updatedAt?: number;
20
+ };
21
+ export type VoiceTurnQualityWidgetOptions = VoiceTurnQualityClientOptions & {
22
+ description?: string;
23
+ title?: string;
24
+ };
25
+ export declare const createVoiceTurnQualityViewModel: (snapshot: VoiceTurnQualitySnapshot, options?: VoiceTurnQualityWidgetOptions) => VoiceTurnQualityViewModel;
26
+ export declare const renderVoiceTurnQualityHTML: (snapshot: VoiceTurnQualitySnapshot, options?: VoiceTurnQualityWidgetOptions) => string;
27
+ export declare const getVoiceTurnQualityCSS: () => string;
28
+ export declare const mountVoiceTurnQuality: (element: Element, path?: string, options?: VoiceTurnQualityWidgetOptions) => {
29
+ close: () => void;
30
+ refresh: () => Promise<import("..").VoiceTurnQualityReport | undefined>;
31
+ };
32
+ export declare const defineVoiceTurnQualityElement: (tagName?: string) => void;
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, crea
9
9
  export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
10
10
  export { createVoiceToolIdempotencyKey, createVoiceToolRuntime } from './toolRuntime';
11
11
  export { createVoiceToolContract, createVoiceToolContractHTMLHandler, createVoiceToolContractJSONHandler, createVoiceToolContractRoutes, createVoiceToolRuntimeContractDefaults, renderVoiceToolContractHTML, runVoiceToolContractSuite, runVoiceToolContract } from './toolContract';
12
+ export { createVoiceTurnQualityHTMLHandler, createVoiceTurnQualityJSONHandler, createVoiceTurnQualityRoutes, renderVoiceTurnQualityHTML, summarizeVoiceTurnQuality } from './turnQuality';
12
13
  export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
13
14
  export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
14
15
  export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, resolveVoiceProviderRoutingPolicyPreset, createVoiceProviderRouter } from './modelAdapters';
@@ -52,6 +53,7 @@ export type { VoiceSessionListHTMLHandlerOptions, VoiceSessionListItem, VoiceSes
52
53
  export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceProviderRouterEvent, VoiceProviderRouterFallbackMode, VoiceProviderRouterHealthOptions, VoiceProviderRouterOptions, VoiceProviderRouterPolicy, VoiceProviderRouterPolicyPreset, VoiceProviderRouterPolicyWeights, VoiceProviderRouterProviderHealth, VoiceProviderRouterProviderProfile, VoiceProviderRouterStrategy, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
53
54
  export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProviderHealthSummaryOptions } from './providerHealth';
54
55
  export type { VoiceProviderCapabilityDefinition, VoiceProviderCapabilityHandlerOptions, VoiceProviderCapabilityHTMLHandlerOptions, VoiceProviderCapabilityKind, VoiceProviderCapabilityOptions, VoiceProviderCapabilityReport, VoiceProviderCapabilityRoutesOptions, VoiceProviderCapabilitySummary } from './providerCapabilities';
56
+ export type { VoiceTurnQualityHTMLHandlerOptions, VoiceTurnQualityItem, VoiceTurnQualityOptions, VoiceTurnQualityReport, VoiceTurnQualityRoutesOptions, VoiceTurnQualityStatus } from './turnQuality';
55
57
  export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesOptions } from './opsConsoleRoutes';
56
58
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
57
59
  export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind } from './resilienceRoutes';