@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.
- package/dist/angular/index.d.ts +2 -0
- package/dist/angular/index.js +272 -26
- package/dist/angular/voice-provider-capabilities.service.d.ts +12 -0
- package/dist/angular/voice-turn-quality.service.d.ts +12 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +397 -0
- package/dist/client/providerCapabilities.d.ts +19 -0
- package/dist/client/providerCapabilitiesWidget.d.ts +32 -0
- package/dist/client/turnQuality.d.ts +19 -0
- package/dist/client/turnQualityWidget.d.ts +32 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +123 -2
- package/dist/react/VoiceProviderCapabilities.d.ts +6 -0
- package/dist/react/VoiceTurnQuality.d.ts +6 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.js +672 -83
- package/dist/react/useVoiceProviderCapabilities.d.ts +8 -0
- package/dist/react/useVoiceTurnQuality.d.ts +8 -0
- package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
- package/dist/svelte/createVoiceTurnQuality.d.ts +10 -0
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.js +440 -33
- package/dist/turnQuality.d.ts +94 -0
- package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
- package/dist/vue/VoiceTurnQuality.d.ts +51 -0
- package/dist/vue/index.d.ts +4 -0
- package/dist/vue/index.js +664 -84
- package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
- package/dist/vue/useVoiceTurnQuality.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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';
|