@absolutejs/voice 0.0.22-beta.166 → 0.0.22-beta.168
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 +1 -0
- package/dist/angular/index.js +177 -58
- package/dist/angular/voice-provider-contracts.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +228 -47
- package/dist/client/providerContracts.d.ts +19 -0
- package/dist/client/providerContractsWidget.d.ts +32 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +94 -33
- package/dist/providerStackRecommendations.d.ts +46 -0
- package/dist/react/VoiceProviderContracts.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +472 -195
- package/dist/react/useVoiceProviderContracts.d.ts +8 -0
- package/dist/svelte/createVoiceProviderContracts.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +264 -78
- package/dist/vue/VoiceProviderContracts.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +446 -170
- package/dist/vue/useVoiceProviderContracts.d.ts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VoiceProviderContractsClientOptions } from '../client/providerContracts';
|
|
2
|
+
export declare const useVoiceProviderContracts: <TProvider extends string = string>(path?: string, options?: VoiceProviderContractsClientOptions) => {
|
|
3
|
+
refresh: () => Promise<import("..").VoiceProviderContractMatrixReport<TProvider> | undefined>;
|
|
4
|
+
error: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
report?: import("..").VoiceProviderContractMatrixReport<TProvider> | undefined;
|
|
7
|
+
updatedAt?: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type VoiceProviderContractsWidgetOptions } from '../client/providerContractsWidget';
|
|
2
|
+
export declare const createVoiceProviderContracts: <TProvider extends string = string>(path?: string, options?: VoiceProviderContractsWidgetOptions) => {
|
|
3
|
+
getHTML: () => string;
|
|
4
|
+
getViewModel: () => import("../client").VoiceProviderContractsViewModel<TProvider>;
|
|
5
|
+
close: () => void;
|
|
6
|
+
getServerSnapshot: () => import("../client").VoiceProviderContractsSnapshot<TProvider>;
|
|
7
|
+
getSnapshot: () => import("../client").VoiceProviderContractsSnapshot<TProvider>;
|
|
8
|
+
refresh: () => Promise<import("..").VoiceProviderContractMatrixReport<TProvider> | undefined>;
|
|
9
|
+
subscribe: (listener: () => void) => () => void;
|
|
10
|
+
};
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { createVoiceOpsActionCenter } from './createVoiceOpsActionCenter';
|
|
|
4
4
|
export { createVoiceOpsStatus } from './createVoiceOpsStatus';
|
|
5
5
|
export { createVoiceProviderSimulationControls } from './createVoiceProviderSimulationControls';
|
|
6
6
|
export { createVoiceProviderCapabilities } from './createVoiceProviderCapabilities';
|
|
7
|
+
export { createVoiceProviderContracts } from './createVoiceProviderContracts';
|
|
7
8
|
export { createVoiceStream } from './createVoiceStream';
|
|
8
9
|
export { createVoiceProviderStatus } from './createVoiceProviderStatus';
|
|
9
10
|
export { createVoiceRoutingStatus } from './createVoiceRoutingStatus';
|
package/dist/svelte/index.js
CHANGED
|
@@ -1367,6 +1367,191 @@ var createVoiceProviderCapabilities = (path = "/api/provider-capabilities", opti
|
|
|
1367
1367
|
getViewModel: () => createVoiceProviderCapabilitiesViewModel(store.getSnapshot(), options)
|
|
1368
1368
|
};
|
|
1369
1369
|
};
|
|
1370
|
+
// src/client/providerContracts.ts
|
|
1371
|
+
var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
|
|
1372
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1373
|
+
const response = await fetchImpl(path);
|
|
1374
|
+
if (!response.ok) {
|
|
1375
|
+
throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
|
|
1376
|
+
}
|
|
1377
|
+
return await response.json();
|
|
1378
|
+
};
|
|
1379
|
+
var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
|
|
1380
|
+
const listeners = new Set;
|
|
1381
|
+
let closed = false;
|
|
1382
|
+
let timer;
|
|
1383
|
+
let snapshot = {
|
|
1384
|
+
error: null,
|
|
1385
|
+
isLoading: false
|
|
1386
|
+
};
|
|
1387
|
+
const emit = () => {
|
|
1388
|
+
for (const listener of listeners) {
|
|
1389
|
+
listener();
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
const refresh = async () => {
|
|
1393
|
+
if (closed) {
|
|
1394
|
+
return snapshot.report;
|
|
1395
|
+
}
|
|
1396
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
1397
|
+
emit();
|
|
1398
|
+
try {
|
|
1399
|
+
const report = await fetchVoiceProviderContracts(path, options);
|
|
1400
|
+
snapshot = {
|
|
1401
|
+
error: null,
|
|
1402
|
+
isLoading: false,
|
|
1403
|
+
report,
|
|
1404
|
+
updatedAt: Date.now()
|
|
1405
|
+
};
|
|
1406
|
+
emit();
|
|
1407
|
+
return report;
|
|
1408
|
+
} catch (error) {
|
|
1409
|
+
snapshot = {
|
|
1410
|
+
...snapshot,
|
|
1411
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1412
|
+
isLoading: false
|
|
1413
|
+
};
|
|
1414
|
+
emit();
|
|
1415
|
+
throw error;
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
const close = () => {
|
|
1419
|
+
closed = true;
|
|
1420
|
+
if (timer) {
|
|
1421
|
+
clearInterval(timer);
|
|
1422
|
+
timer = undefined;
|
|
1423
|
+
}
|
|
1424
|
+
listeners.clear();
|
|
1425
|
+
};
|
|
1426
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
1427
|
+
timer = setInterval(() => {
|
|
1428
|
+
refresh().catch(() => {});
|
|
1429
|
+
}, options.intervalMs);
|
|
1430
|
+
}
|
|
1431
|
+
return {
|
|
1432
|
+
close,
|
|
1433
|
+
getServerSnapshot: () => snapshot,
|
|
1434
|
+
getSnapshot: () => snapshot,
|
|
1435
|
+
refresh,
|
|
1436
|
+
subscribe: (listener) => {
|
|
1437
|
+
listeners.add(listener);
|
|
1438
|
+
return () => {
|
|
1439
|
+
listeners.delete(listener);
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1445
|
+
// src/client/providerContractsWidget.ts
|
|
1446
|
+
var DEFAULT_TITLE5 = "Provider Contracts";
|
|
1447
|
+
var DEFAULT_DESCRIPTION5 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
1448
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1449
|
+
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1450
|
+
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1451
|
+
var contractDetail = (row) => {
|
|
1452
|
+
const failing = row.checks.filter((check) => check.status !== "pass");
|
|
1453
|
+
if (failing.length === 0) {
|
|
1454
|
+
return "Provider contract is production-ready.";
|
|
1455
|
+
}
|
|
1456
|
+
return failing.map((check) => `${check.label}: ${check.detail ?? check.status}`).join(" ");
|
|
1457
|
+
};
|
|
1458
|
+
var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
1459
|
+
const rows = (snapshot.report?.rows ?? []).map((row) => ({
|
|
1460
|
+
...row,
|
|
1461
|
+
detail: contractDetail(row),
|
|
1462
|
+
label: `${formatProvider2(row.provider)} ${row.kind.toUpperCase()}`,
|
|
1463
|
+
rows: [
|
|
1464
|
+
{ label: "Status", value: formatStatus2(row.status) },
|
|
1465
|
+
{ label: "Selected", value: row.selected ? "Yes" : "No" },
|
|
1466
|
+
{ label: "Configured", value: row.configured ? "Yes" : "No" },
|
|
1467
|
+
{
|
|
1468
|
+
label: "Checks",
|
|
1469
|
+
value: row.checks.map((check) => `${check.label}: ${formatStatus2(check.status)}`).join(", ")
|
|
1470
|
+
}
|
|
1471
|
+
]
|
|
1472
|
+
}));
|
|
1473
|
+
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
1474
|
+
return {
|
|
1475
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1476
|
+
error: snapshot.error,
|
|
1477
|
+
isLoading: snapshot.isLoading,
|
|
1478
|
+
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
1479
|
+
rows,
|
|
1480
|
+
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1481
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1482
|
+
updatedAt: snapshot.updatedAt
|
|
1483
|
+
};
|
|
1484
|
+
};
|
|
1485
|
+
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
1486
|
+
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
1487
|
+
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml6(row.status)}">
|
|
1488
|
+
<header>
|
|
1489
|
+
<strong>${escapeHtml6(row.label)}</strong>
|
|
1490
|
+
<span>${escapeHtml6(formatStatus2(row.status))}</span>
|
|
1491
|
+
</header>
|
|
1492
|
+
<p>${escapeHtml6(row.detail)}</p>
|
|
1493
|
+
<dl>${row.rows.map((item) => `<div>
|
|
1494
|
+
<dt>${escapeHtml6(item.label)}</dt>
|
|
1495
|
+
<dd>${escapeHtml6(item.value)}</dd>
|
|
1496
|
+
</div>`).join("")}</dl>
|
|
1497
|
+
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
1498
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml6(model.status)}">
|
|
1499
|
+
<header class="absolute-voice-provider-contracts__header">
|
|
1500
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1501
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml6(model.label)}</strong>
|
|
1502
|
+
</header>
|
|
1503
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml6(model.description)}</p>
|
|
1504
|
+
${rows}
|
|
1505
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1506
|
+
</section>`;
|
|
1507
|
+
};
|
|
1508
|
+
var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
|
|
1509
|
+
var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
|
|
1510
|
+
const store = createVoiceProviderContractsStore(path, options);
|
|
1511
|
+
const render = () => {
|
|
1512
|
+
element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
|
|
1513
|
+
};
|
|
1514
|
+
const unsubscribe = store.subscribe(render);
|
|
1515
|
+
render();
|
|
1516
|
+
store.refresh().catch(() => {});
|
|
1517
|
+
return {
|
|
1518
|
+
close: () => {
|
|
1519
|
+
unsubscribe();
|
|
1520
|
+
store.close();
|
|
1521
|
+
},
|
|
1522
|
+
refresh: store.refresh
|
|
1523
|
+
};
|
|
1524
|
+
};
|
|
1525
|
+
var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
|
|
1526
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
|
|
1530
|
+
mounted;
|
|
1531
|
+
connectedCallback() {
|
|
1532
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
1533
|
+
this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
|
|
1534
|
+
description: this.getAttribute("description") ?? undefined,
|
|
1535
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
1536
|
+
title: this.getAttribute("title") ?? undefined
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
disconnectedCallback() {
|
|
1540
|
+
this.mounted?.close();
|
|
1541
|
+
this.mounted = undefined;
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1546
|
+
// src/svelte/createVoiceProviderContracts.ts
|
|
1547
|
+
var createVoiceProviderContracts = (path = "/api/provider-contracts", options = {}) => {
|
|
1548
|
+
const store = createVoiceProviderContractsStore(path, options);
|
|
1549
|
+
return {
|
|
1550
|
+
...store,
|
|
1551
|
+
getHTML: () => renderVoiceProviderContractsHTML(store.getSnapshot(), options),
|
|
1552
|
+
getViewModel: () => createVoiceProviderContractsViewModel(store.getSnapshot(), options)
|
|
1553
|
+
};
|
|
1554
|
+
};
|
|
1370
1555
|
// src/client/actions.ts
|
|
1371
1556
|
var normalizeErrorMessage = (value) => {
|
|
1372
1557
|
if (typeof value === "string" && value.trim()) {
|
|
@@ -2090,11 +2275,11 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
2090
2275
|
};
|
|
2091
2276
|
|
|
2092
2277
|
// src/client/providerStatusWidget.ts
|
|
2093
|
-
var
|
|
2094
|
-
var
|
|
2095
|
-
var
|
|
2096
|
-
var
|
|
2097
|
-
var
|
|
2278
|
+
var DEFAULT_TITLE6 = "Voice Providers";
|
|
2279
|
+
var DEFAULT_DESCRIPTION6 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
2280
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2281
|
+
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2282
|
+
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2098
2283
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
2099
2284
|
var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
|
|
2100
2285
|
var getProviderDetail = (provider) => {
|
|
@@ -2120,7 +2305,7 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
2120
2305
|
const providers = snapshot.providers.map((provider) => ({
|
|
2121
2306
|
...provider,
|
|
2122
2307
|
detail: getProviderDetail(provider),
|
|
2123
|
-
label: `${
|
|
2308
|
+
label: `${formatProvider3(provider.provider)}${provider.recommended ? " recommended" : ""}`,
|
|
2124
2309
|
rows: [
|
|
2125
2310
|
{ label: "Runs", value: String(provider.runCount) },
|
|
2126
2311
|
{ label: "Avg latency", value: formatLatency(provider.averageElapsedMs) },
|
|
@@ -2136,37 +2321,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
2136
2321
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
2137
2322
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
2138
2323
|
return {
|
|
2139
|
-
description: options.description ??
|
|
2324
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
2140
2325
|
error: snapshot.error,
|
|
2141
2326
|
isLoading: snapshot.isLoading,
|
|
2142
2327
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
2143
2328
|
providers,
|
|
2144
2329
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2145
|
-
title: options.title ??
|
|
2330
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
2146
2331
|
updatedAt: snapshot.updatedAt
|
|
2147
2332
|
};
|
|
2148
2333
|
};
|
|
2149
2334
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
2150
2335
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
2151
|
-
const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${
|
|
2336
|
+
const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml7(provider.status)}">
|
|
2152
2337
|
<header>
|
|
2153
|
-
<strong>${
|
|
2154
|
-
<span>${
|
|
2338
|
+
<strong>${escapeHtml7(provider.label)}</strong>
|
|
2339
|
+
<span>${escapeHtml7(formatStatus3(provider.status))}</span>
|
|
2155
2340
|
</header>
|
|
2156
|
-
<p>${
|
|
2341
|
+
<p>${escapeHtml7(provider.detail)}</p>
|
|
2157
2342
|
<dl>${provider.rows.map((row) => `<div>
|
|
2158
|
-
<dt>${
|
|
2159
|
-
<dd>${
|
|
2343
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
2344
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
2160
2345
|
</div>`).join("")}</dl>
|
|
2161
2346
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
2162
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
2347
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml7(model.status)}">
|
|
2163
2348
|
<header class="absolute-voice-provider-status__header">
|
|
2164
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
2165
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
2349
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2350
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml7(model.label)}</strong>
|
|
2166
2351
|
</header>
|
|
2167
|
-
<p class="absolute-voice-provider-status__description">${
|
|
2352
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
|
|
2168
2353
|
${providers}
|
|
2169
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
2354
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
2170
2355
|
</section>`;
|
|
2171
2356
|
};
|
|
2172
2357
|
var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2297,9 +2482,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2297
2482
|
};
|
|
2298
2483
|
|
|
2299
2484
|
// src/client/routingStatusWidget.ts
|
|
2300
|
-
var
|
|
2301
|
-
var
|
|
2302
|
-
var
|
|
2485
|
+
var DEFAULT_TITLE7 = "Voice Routing";
|
|
2486
|
+
var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2487
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2303
2488
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2304
2489
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2305
2490
|
const decision = snapshot.decision;
|
|
@@ -2323,30 +2508,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2323
2508
|
] : [];
|
|
2324
2509
|
return {
|
|
2325
2510
|
decision,
|
|
2326
|
-
description: options.description ??
|
|
2511
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2327
2512
|
error: snapshot.error,
|
|
2328
2513
|
isLoading: snapshot.isLoading,
|
|
2329
2514
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2330
2515
|
rows,
|
|
2331
2516
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2332
|
-
title: options.title ??
|
|
2517
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2333
2518
|
updatedAt: snapshot.updatedAt
|
|
2334
2519
|
};
|
|
2335
2520
|
};
|
|
2336
2521
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2337
2522
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2338
2523
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2339
|
-
<span>${
|
|
2340
|
-
<strong>${
|
|
2524
|
+
<span>${escapeHtml8(row.label)}</span>
|
|
2525
|
+
<strong>${escapeHtml8(row.value)}</strong>
|
|
2341
2526
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2342
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2527
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml8(model.status)}">
|
|
2343
2528
|
<header class="absolute-voice-routing-status__header">
|
|
2344
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2345
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2529
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2530
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml8(model.label)}</strong>
|
|
2346
2531
|
</header>
|
|
2347
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2532
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml8(model.description)}</p>
|
|
2348
2533
|
${rows}
|
|
2349
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2534
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2350
2535
|
</section>`;
|
|
2351
2536
|
};
|
|
2352
2537
|
var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2477,9 +2662,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
2477
2662
|
};
|
|
2478
2663
|
|
|
2479
2664
|
// src/client/traceTimelineWidget.ts
|
|
2480
|
-
var
|
|
2481
|
-
var
|
|
2482
|
-
var
|
|
2665
|
+
var DEFAULT_TITLE8 = "Voice Traces";
|
|
2666
|
+
var DEFAULT_DESCRIPTION8 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
2667
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2483
2668
|
var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
2484
2669
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
2485
2670
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -2493,34 +2678,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
2493
2678
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
2494
2679
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
2495
2680
|
return {
|
|
2496
|
-
description: options.description ??
|
|
2681
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2497
2682
|
error: snapshot.error,
|
|
2498
2683
|
isLoading: snapshot.isLoading,
|
|
2499
2684
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
2500
2685
|
sessions,
|
|
2501
2686
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2502
|
-
title: options.title ??
|
|
2687
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2503
2688
|
updatedAt: snapshot.updatedAt
|
|
2504
2689
|
};
|
|
2505
2690
|
};
|
|
2506
2691
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
2507
2692
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
2508
|
-
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--${
|
|
2693
|
+
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--${escapeHtml9(session.status)}">
|
|
2509
2694
|
<header>
|
|
2510
|
-
<strong>${
|
|
2511
|
-
<span>${
|
|
2695
|
+
<strong>${escapeHtml9(session.sessionId)}</strong>
|
|
2696
|
+
<span>${escapeHtml9(session.status)}</span>
|
|
2512
2697
|
</header>
|
|
2513
|
-
<p>${
|
|
2514
|
-
<a href="${
|
|
2698
|
+
<p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
|
|
2699
|
+
<a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
|
|
2515
2700
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
2516
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
2701
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
|
|
2517
2702
|
<header class="absolute-voice-trace-timeline__header">
|
|
2518
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
2519
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
2703
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2704
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
|
|
2520
2705
|
</header>
|
|
2521
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
2706
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
|
|
2522
2707
|
${sessions}
|
|
2523
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
2708
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2524
2709
|
</section>`;
|
|
2525
2710
|
};
|
|
2526
2711
|
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}`;
|
|
@@ -2677,10 +2862,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2677
2862
|
};
|
|
2678
2863
|
|
|
2679
2864
|
// src/client/turnLatencyWidget.ts
|
|
2680
|
-
var
|
|
2681
|
-
var
|
|
2865
|
+
var DEFAULT_TITLE9 = "Turn Latency";
|
|
2866
|
+
var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2682
2867
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2683
|
-
var
|
|
2868
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2684
2869
|
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2685
2870
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2686
2871
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2694,39 +2879,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2694
2879
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2695
2880
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2696
2881
|
return {
|
|
2697
|
-
description: options.description ??
|
|
2882
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
2698
2883
|
error: snapshot.error,
|
|
2699
2884
|
isLoading: snapshot.isLoading,
|
|
2700
2885
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2701
2886
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2702
2887
|
showProofAction: Boolean(options.proofPath),
|
|
2703
2888
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2704
|
-
title: options.title ??
|
|
2889
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
2705
2890
|
turns,
|
|
2706
2891
|
updatedAt: snapshot.updatedAt
|
|
2707
2892
|
};
|
|
2708
2893
|
};
|
|
2709
2894
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2710
2895
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
2711
|
-
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--${
|
|
2896
|
+
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--${escapeHtml10(turn.status)}">
|
|
2712
2897
|
<header>
|
|
2713
|
-
<strong>${
|
|
2714
|
-
<span>${
|
|
2898
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
2899
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
2715
2900
|
</header>
|
|
2716
2901
|
<dl>${turn.rows.map((row) => `<div>
|
|
2717
|
-
<dt>${
|
|
2718
|
-
<dd>${
|
|
2902
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
2903
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
2719
2904
|
</div>`).join("")}</dl>
|
|
2720
2905
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
2721
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
2906
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
|
|
2722
2907
|
<header class="absolute-voice-turn-latency__header">
|
|
2723
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2724
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2908
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
|
|
2909
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
|
|
2725
2910
|
</header>
|
|
2726
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
2727
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
2911
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
|
|
2912
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml10(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
2728
2913
|
${turns}
|
|
2729
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2914
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2730
2915
|
</section>`;
|
|
2731
2916
|
};
|
|
2732
2917
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2865,9 +3050,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2865
3050
|
};
|
|
2866
3051
|
|
|
2867
3052
|
// src/client/turnQualityWidget.ts
|
|
2868
|
-
var
|
|
2869
|
-
var
|
|
2870
|
-
var
|
|
3053
|
+
var DEFAULT_TITLE10 = "Turn Quality";
|
|
3054
|
+
var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3055
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2871
3056
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2872
3057
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2873
3058
|
var getTurnDetail = (turn) => {
|
|
@@ -2905,37 +3090,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2905
3090
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2906
3091
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2907
3092
|
return {
|
|
2908
|
-
description: options.description ??
|
|
3093
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
2909
3094
|
error: snapshot.error,
|
|
2910
3095
|
isLoading: snapshot.isLoading,
|
|
2911
3096
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2912
3097
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2913
|
-
title: options.title ??
|
|
3098
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
2914
3099
|
turns,
|
|
2915
3100
|
updatedAt: snapshot.updatedAt
|
|
2916
3101
|
};
|
|
2917
3102
|
};
|
|
2918
3103
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2919
3104
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2920
|
-
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--${
|
|
3105
|
+
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--${escapeHtml11(turn.status)}">
|
|
2921
3106
|
<header>
|
|
2922
|
-
<strong>${
|
|
2923
|
-
<span>${
|
|
3107
|
+
<strong>${escapeHtml11(turn.label)}</strong>
|
|
3108
|
+
<span>${escapeHtml11(turn.status)}</span>
|
|
2924
3109
|
</header>
|
|
2925
|
-
<p>${
|
|
3110
|
+
<p>${escapeHtml11(turn.detail)}</p>
|
|
2926
3111
|
<dl>${turn.rows.map((row) => `<div>
|
|
2927
|
-
<dt>${
|
|
2928
|
-
<dd>${
|
|
3112
|
+
<dt>${escapeHtml11(row.label)}</dt>
|
|
3113
|
+
<dd>${escapeHtml11(row.value)}</dd>
|
|
2929
3114
|
</div>`).join("")}</dl>
|
|
2930
3115
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
2931
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
3116
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml11(model.status)}">
|
|
2932
3117
|
<header class="absolute-voice-turn-quality__header">
|
|
2933
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2934
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
3118
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml11(model.title)}</span>
|
|
3119
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml11(model.label)}</strong>
|
|
2935
3120
|
</header>
|
|
2936
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
3121
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml11(model.description)}</p>
|
|
2937
3122
|
${turns}
|
|
2938
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
3123
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
2939
3124
|
</section>`;
|
|
2940
3125
|
};
|
|
2941
3126
|
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}`;
|
|
@@ -3715,6 +3900,7 @@ export {
|
|
|
3715
3900
|
createVoiceRoutingStatus,
|
|
3716
3901
|
createVoiceProviderStatus,
|
|
3717
3902
|
createVoiceProviderSimulationControls,
|
|
3903
|
+
createVoiceProviderContracts,
|
|
3718
3904
|
createVoiceProviderCapabilities,
|
|
3719
3905
|
createVoiceOpsStatus,
|
|
3720
3906
|
createVoiceOpsActionCenter,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const VoiceProviderContracts: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
description: StringConstructor;
|
|
3
|
+
intervalMs: NumberConstructor;
|
|
4
|
+
path: {
|
|
5
|
+
default: string;
|
|
6
|
+
type: StringConstructor;
|
|
7
|
+
};
|
|
8
|
+
title: StringConstructor;
|
|
9
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
12
|
+
description: StringConstructor;
|
|
13
|
+
intervalMs: NumberConstructor;
|
|
14
|
+
path: {
|
|
15
|
+
default: string;
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
};
|
|
18
|
+
title: StringConstructor;
|
|
19
|
+
}>> & Readonly<{}>, {
|
|
20
|
+
path: string;
|
|
21
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { VoiceOpsActionCenter } from './VoiceOpsActionCenter';
|
|
|
3
3
|
export { VoiceDeliveryRuntime } from './VoiceDeliveryRuntime';
|
|
4
4
|
export { VoiceProviderSimulationControls } from './VoiceProviderSimulationControls';
|
|
5
5
|
export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
|
|
6
|
+
export { VoiceProviderContracts } from './VoiceProviderContracts';
|
|
6
7
|
export { VoiceProviderStatus } from './VoiceProviderStatus';
|
|
7
8
|
export { VoiceRoutingStatus } from './VoiceRoutingStatus';
|
|
8
9
|
export { VoiceTurnLatency } from './VoiceTurnLatency';
|
|
@@ -15,6 +16,7 @@ export { useVoiceStream } from './useVoiceStream';
|
|
|
15
16
|
export { useVoiceController } from './useVoiceController';
|
|
16
17
|
export { useVoiceProviderStatus } from './useVoiceProviderStatus';
|
|
17
18
|
export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
|
|
19
|
+
export { useVoiceProviderContracts } from './useVoiceProviderContracts';
|
|
18
20
|
export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
|
|
19
21
|
export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
|
|
20
22
|
export { useVoiceTraceTimeline } from './useVoiceTraceTimeline';
|