@absolutejs/voice 0.0.22-beta.241 → 0.0.22-beta.243
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 +306 -181
- package/dist/angular/voice-proof-trends.service.d.ts +12 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +490 -190
- package/dist/client/proofTrends.d.ts +19 -0
- package/dist/client/proofTrendsWidget.d.ts +37 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +118 -70
- package/dist/proofTrends.d.ts +44 -0
- package/dist/react/VoiceProofTrends.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +730 -350
- package/dist/react/useVoiceProofTrends.d.ts +8 -0
- package/dist/svelte/createVoiceProofTrends.d.ts +7 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +90 -0
- package/dist/vue/VoiceProofTrends.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +704 -321
- package/dist/vue/useVoiceProofTrends.d.ts +9 -0
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -1393,6 +1393,384 @@ var VoicePlatformCoverage = ({
|
|
|
1393
1393
|
]
|
|
1394
1394
|
}, undefined, true, undefined, this);
|
|
1395
1395
|
};
|
|
1396
|
+
// src/react/useVoiceProofTrends.tsx
|
|
1397
|
+
import { useEffect as useEffect5, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
1398
|
+
|
|
1399
|
+
// src/client/proofTrends.ts
|
|
1400
|
+
var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
|
|
1401
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1402
|
+
const response = await fetchImpl(path);
|
|
1403
|
+
if (!response.ok) {
|
|
1404
|
+
throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
|
|
1405
|
+
}
|
|
1406
|
+
return await response.json();
|
|
1407
|
+
};
|
|
1408
|
+
var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
|
|
1409
|
+
const listeners = new Set;
|
|
1410
|
+
let closed = false;
|
|
1411
|
+
let timer;
|
|
1412
|
+
let snapshot = {
|
|
1413
|
+
error: null,
|
|
1414
|
+
isLoading: false
|
|
1415
|
+
};
|
|
1416
|
+
const emit = () => {
|
|
1417
|
+
for (const listener of listeners) {
|
|
1418
|
+
listener();
|
|
1419
|
+
}
|
|
1420
|
+
};
|
|
1421
|
+
const refresh = async () => {
|
|
1422
|
+
if (closed) {
|
|
1423
|
+
return snapshot.report;
|
|
1424
|
+
}
|
|
1425
|
+
snapshot = {
|
|
1426
|
+
...snapshot,
|
|
1427
|
+
error: null,
|
|
1428
|
+
isLoading: true
|
|
1429
|
+
};
|
|
1430
|
+
emit();
|
|
1431
|
+
try {
|
|
1432
|
+
const report = await fetchVoiceProofTrends(path, options);
|
|
1433
|
+
snapshot = {
|
|
1434
|
+
error: null,
|
|
1435
|
+
isLoading: false,
|
|
1436
|
+
report,
|
|
1437
|
+
updatedAt: Date.now()
|
|
1438
|
+
};
|
|
1439
|
+
emit();
|
|
1440
|
+
return report;
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
snapshot = {
|
|
1443
|
+
...snapshot,
|
|
1444
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1445
|
+
isLoading: false
|
|
1446
|
+
};
|
|
1447
|
+
emit();
|
|
1448
|
+
throw error;
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1451
|
+
const close = () => {
|
|
1452
|
+
closed = true;
|
|
1453
|
+
if (timer) {
|
|
1454
|
+
clearInterval(timer);
|
|
1455
|
+
timer = undefined;
|
|
1456
|
+
}
|
|
1457
|
+
listeners.clear();
|
|
1458
|
+
};
|
|
1459
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
1460
|
+
timer = setInterval(() => {
|
|
1461
|
+
refresh().catch(() => {});
|
|
1462
|
+
}, options.intervalMs);
|
|
1463
|
+
}
|
|
1464
|
+
return {
|
|
1465
|
+
close,
|
|
1466
|
+
getServerSnapshot: () => snapshot,
|
|
1467
|
+
getSnapshot: () => snapshot,
|
|
1468
|
+
refresh,
|
|
1469
|
+
subscribe: (listener) => {
|
|
1470
|
+
listeners.add(listener);
|
|
1471
|
+
return () => {
|
|
1472
|
+
listeners.delete(listener);
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
// src/react/useVoiceProofTrends.tsx
|
|
1479
|
+
var useVoiceProofTrends = (path = "/api/voice/proof-trends", options = {}) => {
|
|
1480
|
+
const storeRef = useRef5(null);
|
|
1481
|
+
if (!storeRef.current) {
|
|
1482
|
+
storeRef.current = createVoiceProofTrendsStore(path, options);
|
|
1483
|
+
}
|
|
1484
|
+
const store = storeRef.current;
|
|
1485
|
+
useEffect5(() => {
|
|
1486
|
+
store.refresh().catch(() => {});
|
|
1487
|
+
return () => store.close();
|
|
1488
|
+
}, [store]);
|
|
1489
|
+
return {
|
|
1490
|
+
...useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1491
|
+
refresh: store.refresh
|
|
1492
|
+
};
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
// src/proofTrends.ts
|
|
1496
|
+
import { Elysia } from "elysia";
|
|
1497
|
+
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
1498
|
+
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
1499
|
+
var toTimeMs = (value) => {
|
|
1500
|
+
if (value instanceof Date) {
|
|
1501
|
+
return value.getTime();
|
|
1502
|
+
}
|
|
1503
|
+
if (typeof value === "number") {
|
|
1504
|
+
return value;
|
|
1505
|
+
}
|
|
1506
|
+
if (typeof value === "string") {
|
|
1507
|
+
return Date.parse(value);
|
|
1508
|
+
}
|
|
1509
|
+
return Date.now();
|
|
1510
|
+
};
|
|
1511
|
+
var buildVoiceProofTrendReport = (input = {}) => {
|
|
1512
|
+
const maxAgeMs = normalizeMaxAgeMs(input.maxAgeMs);
|
|
1513
|
+
const nowMs = toTimeMs(input.now);
|
|
1514
|
+
const generatedAtMs = typeof input.generatedAt === "string" ? Date.parse(input.generatedAt) : Number.NaN;
|
|
1515
|
+
const ageMs = Number.isFinite(generatedAtMs) && Number.isFinite(nowMs) ? Math.max(0, nowMs - generatedAtMs) : undefined;
|
|
1516
|
+
const freshUntil = Number.isFinite(generatedAtMs) && Number.isFinite(maxAgeMs) ? new Date(generatedAtMs + maxAgeMs).toISOString() : undefined;
|
|
1517
|
+
const isFresh = ageMs !== undefined && ageMs <= maxAgeMs;
|
|
1518
|
+
const status = input.status === "empty" ? "empty" : !isFresh ? "stale" : input.ok === true ? "pass" : "fail";
|
|
1519
|
+
return {
|
|
1520
|
+
ageMs,
|
|
1521
|
+
baseUrl: input.baseUrl,
|
|
1522
|
+
cycles: input.cycles ?? [],
|
|
1523
|
+
freshUntil,
|
|
1524
|
+
generatedAt: input.generatedAt,
|
|
1525
|
+
maxAgeMs,
|
|
1526
|
+
ok: input.ok === true && status === "pass",
|
|
1527
|
+
outputDir: input.outputDir,
|
|
1528
|
+
runId: input.runId,
|
|
1529
|
+
source: input.source ?? "",
|
|
1530
|
+
status,
|
|
1531
|
+
summary: input.summary ?? {}
|
|
1532
|
+
};
|
|
1533
|
+
};
|
|
1534
|
+
var buildEmptyVoiceProofTrendReport = (source = "", maxAgeMs) => buildVoiceProofTrendReport({
|
|
1535
|
+
maxAgeMs,
|
|
1536
|
+
source,
|
|
1537
|
+
status: "empty"
|
|
1538
|
+
});
|
|
1539
|
+
var normalizeVoiceProofTrendReport = (value, options = {}) => {
|
|
1540
|
+
if ("status" in value && value.status === "empty") {
|
|
1541
|
+
return buildEmptyVoiceProofTrendReport(value.source || options.source || "", options.maxAgeMs ?? value.maxAgeMs);
|
|
1542
|
+
}
|
|
1543
|
+
return buildVoiceProofTrendReport({
|
|
1544
|
+
...value,
|
|
1545
|
+
maxAgeMs: options.maxAgeMs ?? value.maxAgeMs,
|
|
1546
|
+
source: value.source ?? options.source
|
|
1547
|
+
});
|
|
1548
|
+
};
|
|
1549
|
+
var readVoiceProofTrendReportFile = async (path, options = {}) => {
|
|
1550
|
+
const file = Bun.file(path);
|
|
1551
|
+
if (!await file.exists()) {
|
|
1552
|
+
return buildEmptyVoiceProofTrendReport(path, options.maxAgeMs);
|
|
1553
|
+
}
|
|
1554
|
+
try {
|
|
1555
|
+
const parsed = await file.json();
|
|
1556
|
+
return normalizeVoiceProofTrendReport(parsed, {
|
|
1557
|
+
maxAgeMs: options.maxAgeMs,
|
|
1558
|
+
source: path
|
|
1559
|
+
});
|
|
1560
|
+
} catch {
|
|
1561
|
+
return buildVoiceProofTrendReport({
|
|
1562
|
+
maxAgeMs: options.maxAgeMs,
|
|
1563
|
+
source: path
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
var createVoiceProofTrendRoutes = (options) => {
|
|
1568
|
+
const path = options.path ?? "/api/voice/proof-trends";
|
|
1569
|
+
const routes = new Elysia({
|
|
1570
|
+
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
1571
|
+
});
|
|
1572
|
+
routes.get(path, async () => {
|
|
1573
|
+
const value = options.source !== undefined ? typeof options.source === "function" ? await options.source() : options.source : options.jsonPath ? await readVoiceProofTrendReportFile(options.jsonPath, {
|
|
1574
|
+
maxAgeMs: options.maxAgeMs
|
|
1575
|
+
}) : buildEmptyVoiceProofTrendReport("", options.maxAgeMs);
|
|
1576
|
+
return Response.json(normalizeVoiceProofTrendReport(value, {
|
|
1577
|
+
maxAgeMs: options.maxAgeMs,
|
|
1578
|
+
source: options.jsonPath
|
|
1579
|
+
}), { headers: options.headers });
|
|
1580
|
+
});
|
|
1581
|
+
return routes;
|
|
1582
|
+
};
|
|
1583
|
+
var formatVoiceProofTrendAge = (ageMs) => {
|
|
1584
|
+
if (typeof ageMs !== "number" || !Number.isFinite(ageMs)) {
|
|
1585
|
+
return "unknown";
|
|
1586
|
+
}
|
|
1587
|
+
const minutes = Math.floor(ageMs / 60000);
|
|
1588
|
+
if (minutes < 1) {
|
|
1589
|
+
return "less than 1m";
|
|
1590
|
+
}
|
|
1591
|
+
if (minutes < 60) {
|
|
1592
|
+
return `${minutes}m`;
|
|
1593
|
+
}
|
|
1594
|
+
const hours = Math.floor(minutes / 60);
|
|
1595
|
+
if (hours < 48) {
|
|
1596
|
+
return `${hours}h ${minutes % 60}m`;
|
|
1597
|
+
}
|
|
1598
|
+
const days = Math.floor(hours / 24);
|
|
1599
|
+
return `${days}d ${hours % 24}h`;
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
// src/client/proofTrendsWidget.ts
|
|
1603
|
+
var DEFAULT_TITLE5 = "Sustained Proof Trends";
|
|
1604
|
+
var DEFAULT_DESCRIPTION5 = "Repeated-cycle provider, latency, recovery, and readiness evidence with freshness gating.";
|
|
1605
|
+
var DEFAULT_LINKS2 = [
|
|
1606
|
+
{ href: "/voice/proof-trends", label: "Trend page" },
|
|
1607
|
+
{ href: "/api/voice/proof-trends", label: "Trend JSON" }
|
|
1608
|
+
];
|
|
1609
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1610
|
+
var formatMs = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
1611
|
+
var statusLabel = (report) => {
|
|
1612
|
+
if (!report) {
|
|
1613
|
+
return "No trend report";
|
|
1614
|
+
}
|
|
1615
|
+
if (report.status === "pass") {
|
|
1616
|
+
return `${report.summary.cycles ?? report.cycles.length} cycles passing`;
|
|
1617
|
+
}
|
|
1618
|
+
return report.status;
|
|
1619
|
+
};
|
|
1620
|
+
var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
|
|
1621
|
+
const report = snapshot.report;
|
|
1622
|
+
const metrics = report ? [
|
|
1623
|
+
{ label: "Status", value: report.status.toUpperCase() },
|
|
1624
|
+
{
|
|
1625
|
+
label: "Cycles",
|
|
1626
|
+
value: String(report.summary.cycles ?? report.cycles.length)
|
|
1627
|
+
},
|
|
1628
|
+
{
|
|
1629
|
+
label: "Provider p95",
|
|
1630
|
+
value: formatMs(report.summary.maxProviderP95Ms)
|
|
1631
|
+
},
|
|
1632
|
+
{ label: "Turn p95", value: formatMs(report.summary.maxTurnP95Ms) },
|
|
1633
|
+
{ label: "Live p95", value: formatMs(report.summary.maxLiveP95Ms) },
|
|
1634
|
+
{
|
|
1635
|
+
label: "Artifact age",
|
|
1636
|
+
value: formatVoiceProofTrendAge(report.ageMs)
|
|
1637
|
+
},
|
|
1638
|
+
{
|
|
1639
|
+
label: "Stale after",
|
|
1640
|
+
value: formatVoiceProofTrendAge(report.maxAgeMs)
|
|
1641
|
+
}
|
|
1642
|
+
] : [];
|
|
1643
|
+
return {
|
|
1644
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1645
|
+
error: snapshot.error,
|
|
1646
|
+
isLoading: snapshot.isLoading,
|
|
1647
|
+
label: snapshot.error ? "Unavailable" : report ? statusLabel(report) : snapshot.isLoading ? "Checking" : "No trend report",
|
|
1648
|
+
links: options.links ?? DEFAULT_LINKS2,
|
|
1649
|
+
metrics,
|
|
1650
|
+
report,
|
|
1651
|
+
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
1652
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1653
|
+
updatedAt: snapshot.updatedAt
|
|
1654
|
+
};
|
|
1655
|
+
};
|
|
1656
|
+
var renderVoiceProofTrendsHTML = (snapshot, options = {}) => {
|
|
1657
|
+
const model = createVoiceProofTrendsViewModel(snapshot, options);
|
|
1658
|
+
const metrics = model.metrics.length ? `<div class="absolute-voice-proof-trends__metrics">${model.metrics.map((metric) => `<article>
|
|
1659
|
+
<span>${escapeHtml5(metric.label)}</span>
|
|
1660
|
+
<strong>${escapeHtml5(metric.value)}</strong>
|
|
1661
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml5(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
|
|
1662
|
+
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml5(link.href)}">${escapeHtml5(link.label)}</a>`).join("")}</p>` : "";
|
|
1663
|
+
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml5(model.status)}">
|
|
1664
|
+
<header class="absolute-voice-proof-trends__header">
|
|
1665
|
+
<span class="absolute-voice-proof-trends__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1666
|
+
<strong class="absolute-voice-proof-trends__label">${escapeHtml5(model.label)}</strong>
|
|
1667
|
+
</header>
|
|
1668
|
+
<p class="absolute-voice-proof-trends__description">${escapeHtml5(model.description)}</p>
|
|
1669
|
+
${metrics}
|
|
1670
|
+
${links}
|
|
1671
|
+
${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1672
|
+
</section>`;
|
|
1673
|
+
};
|
|
1674
|
+
var getVoiceProofTrendsCSS = () => `.absolute-voice-proof-trends{border:1px solid #99f6e4;border-radius:20px;background:#f0fdfa;color:#0f172a;padding:18px;box-shadow:0 18px 40px rgba(13,148,136,.12);font-family:inherit}.absolute-voice-proof-trends--warning,.absolute-voice-proof-trends--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-proof-trends__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-proof-trends__eyebrow{color:#0f766e;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-proof-trends__label{font-size:24px;line-height:1}.absolute-voice-proof-trends__description,.absolute-voice-proof-trends__empty{color:#475569}.absolute-voice-proof-trends__metrics{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));margin-top:14px}.absolute-voice-proof-trends__metrics article{background:#fff;border:1px solid #ccfbf1;border-radius:16px;padding:12px}.absolute-voice-proof-trends__metrics span{color:#64748b;display:block;font-size:12px;font-weight:800;text-transform:uppercase}.absolute-voice-proof-trends__metrics strong{display:block;font-size:20px;margin-top:4px}.absolute-voice-proof-trends__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-proof-trends__links a{border:1px solid #99f6e4;border-radius:999px;color:#0f766e;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-proof-trends__error{color:#9f1239;font-weight:700}`;
|
|
1675
|
+
var mountVoiceProofTrends = (element, path = "/api/voice/proof-trends", options = {}) => {
|
|
1676
|
+
const store = createVoiceProofTrendsStore(path, options);
|
|
1677
|
+
const render = () => {
|
|
1678
|
+
element.innerHTML = renderVoiceProofTrendsHTML(store.getSnapshot(), options);
|
|
1679
|
+
};
|
|
1680
|
+
const unsubscribe = store.subscribe(render);
|
|
1681
|
+
render();
|
|
1682
|
+
store.refresh().catch(() => {});
|
|
1683
|
+
return {
|
|
1684
|
+
close: () => {
|
|
1685
|
+
unsubscribe();
|
|
1686
|
+
store.close();
|
|
1687
|
+
},
|
|
1688
|
+
refresh: store.refresh
|
|
1689
|
+
};
|
|
1690
|
+
};
|
|
1691
|
+
var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") => {
|
|
1692
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
customElements.define(tagName, class AbsoluteVoiceProofTrendsElement extends HTMLElement {
|
|
1696
|
+
mounted;
|
|
1697
|
+
connectedCallback() {
|
|
1698
|
+
this.mounted = mountVoiceProofTrends(this, this.getAttribute("path") ?? "/api/voice/proof-trends", {
|
|
1699
|
+
description: this.getAttribute("description") ?? undefined,
|
|
1700
|
+
intervalMs: Number(this.getAttribute("interval-ms") ?? 0) || undefined,
|
|
1701
|
+
title: this.getAttribute("title") ?? undefined
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
disconnectedCallback() {
|
|
1705
|
+
this.mounted?.close();
|
|
1706
|
+
this.mounted = undefined;
|
|
1707
|
+
}
|
|
1708
|
+
});
|
|
1709
|
+
};
|
|
1710
|
+
|
|
1711
|
+
// src/react/VoiceProofTrends.tsx
|
|
1712
|
+
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
1713
|
+
var VoiceProofTrends = ({
|
|
1714
|
+
className,
|
|
1715
|
+
path = "/api/voice/proof-trends",
|
|
1716
|
+
...options
|
|
1717
|
+
}) => {
|
|
1718
|
+
const snapshot = useVoiceProofTrends(path, options);
|
|
1719
|
+
const model = createVoiceProofTrendsViewModel(snapshot, options);
|
|
1720
|
+
return /* @__PURE__ */ jsxDEV5("section", {
|
|
1721
|
+
className: [
|
|
1722
|
+
"absolute-voice-proof-trends",
|
|
1723
|
+
`absolute-voice-proof-trends--${model.status}`,
|
|
1724
|
+
className
|
|
1725
|
+
].filter(Boolean).join(" "),
|
|
1726
|
+
children: [
|
|
1727
|
+
/* @__PURE__ */ jsxDEV5("header", {
|
|
1728
|
+
className: "absolute-voice-proof-trends__header",
|
|
1729
|
+
children: [
|
|
1730
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1731
|
+
className: "absolute-voice-proof-trends__eyebrow",
|
|
1732
|
+
children: model.title
|
|
1733
|
+
}, undefined, false, undefined, this),
|
|
1734
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1735
|
+
className: "absolute-voice-proof-trends__label",
|
|
1736
|
+
children: model.label
|
|
1737
|
+
}, undefined, false, undefined, this)
|
|
1738
|
+
]
|
|
1739
|
+
}, undefined, true, undefined, this),
|
|
1740
|
+
/* @__PURE__ */ jsxDEV5("p", {
|
|
1741
|
+
className: "absolute-voice-proof-trends__description",
|
|
1742
|
+
children: model.description
|
|
1743
|
+
}, undefined, false, undefined, this),
|
|
1744
|
+
model.metrics.length ? /* @__PURE__ */ jsxDEV5("div", {
|
|
1745
|
+
className: "absolute-voice-proof-trends__metrics",
|
|
1746
|
+
children: model.metrics.map((metric) => /* @__PURE__ */ jsxDEV5("article", {
|
|
1747
|
+
children: [
|
|
1748
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1749
|
+
children: metric.label
|
|
1750
|
+
}, undefined, false, undefined, this),
|
|
1751
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1752
|
+
children: metric.value
|
|
1753
|
+
}, undefined, false, undefined, this)
|
|
1754
|
+
]
|
|
1755
|
+
}, metric.label, true, undefined, this))
|
|
1756
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5("p", {
|
|
1757
|
+
className: "absolute-voice-proof-trends__empty",
|
|
1758
|
+
children: model.error ?? "Run the sustained proof trends script to populate evidence."
|
|
1759
|
+
}, undefined, false, undefined, this),
|
|
1760
|
+
model.links.length ? /* @__PURE__ */ jsxDEV5("p", {
|
|
1761
|
+
className: "absolute-voice-proof-trends__links",
|
|
1762
|
+
children: model.links.map((link) => /* @__PURE__ */ jsxDEV5("a", {
|
|
1763
|
+
href: link.href,
|
|
1764
|
+
children: link.label
|
|
1765
|
+
}, link.href, false, undefined, this))
|
|
1766
|
+
}, undefined, false, undefined, this) : null,
|
|
1767
|
+
model.error ? /* @__PURE__ */ jsxDEV5("p", {
|
|
1768
|
+
className: "absolute-voice-proof-trends__error",
|
|
1769
|
+
children: model.error
|
|
1770
|
+
}, undefined, false, undefined, this) : null
|
|
1771
|
+
]
|
|
1772
|
+
}, undefined, true, undefined, this);
|
|
1773
|
+
};
|
|
1396
1774
|
// src/client/providerSimulationControls.ts
|
|
1397
1775
|
var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
|
|
1398
1776
|
const response = await fetchImpl(`${pathPrefix}/${mode}?provider=${encodeURIComponent(provider)}`, { method: "POST" });
|
|
@@ -1473,7 +1851,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
1473
1851
|
};
|
|
1474
1852
|
|
|
1475
1853
|
// src/client/providerSimulationControlsWidget.ts
|
|
1476
|
-
var
|
|
1854
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1477
1855
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
1478
1856
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
1479
1857
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -1493,18 +1871,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
1493
1871
|
};
|
|
1494
1872
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
1495
1873
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
1496
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
1497
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
1874
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml6(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml6(provider.provider)} ${escapeHtml6(formatKind(options.kind))} failure</button>`).join("");
|
|
1875
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml6(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml6(provider.provider)} recovered</button>`).join("");
|
|
1498
1876
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
1499
1877
|
<header class="absolute-voice-provider-simulation__header">
|
|
1500
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
1501
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1878
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1879
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml6(model.label)}</strong>
|
|
1502
1880
|
</header>
|
|
1503
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
1504
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1881
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml6(model.description)}</p>
|
|
1882
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml6(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
1505
1883
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
1506
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
1507
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
1884
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml6(snapshot.error)}</p>` : ""}
|
|
1885
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml6(model.resultText)}</pre>` : ""}
|
|
1508
1886
|
</section>`;
|
|
1509
1887
|
};
|
|
1510
1888
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -1570,22 +1948,22 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
1570
1948
|
};
|
|
1571
1949
|
|
|
1572
1950
|
// src/react/useVoiceProviderSimulationControls.tsx
|
|
1573
|
-
import { useEffect as
|
|
1951
|
+
import { useEffect as useEffect6, useRef as useRef6, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
1574
1952
|
var useVoiceProviderSimulationControls = (options) => {
|
|
1575
|
-
const storeRef =
|
|
1953
|
+
const storeRef = useRef6(null);
|
|
1576
1954
|
if (!storeRef.current) {
|
|
1577
1955
|
storeRef.current = createVoiceProviderSimulationControlsStore(options);
|
|
1578
1956
|
}
|
|
1579
1957
|
const store = storeRef.current;
|
|
1580
|
-
|
|
1958
|
+
useEffect6(() => () => store.close(), [store]);
|
|
1581
1959
|
return {
|
|
1582
|
-
...
|
|
1960
|
+
...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1583
1961
|
run: store.run
|
|
1584
1962
|
};
|
|
1585
1963
|
};
|
|
1586
1964
|
|
|
1587
1965
|
// src/react/VoiceProviderSimulationControls.tsx
|
|
1588
|
-
import { jsxDEV as
|
|
1966
|
+
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
1589
1967
|
var VoiceProviderSimulationControls = ({
|
|
1590
1968
|
className,
|
|
1591
1969
|
...options
|
|
@@ -1595,38 +1973,38 @@ var VoiceProviderSimulationControls = ({
|
|
|
1595
1973
|
const run = (provider, mode) => {
|
|
1596
1974
|
snapshot.run(provider, mode).catch(() => {});
|
|
1597
1975
|
};
|
|
1598
|
-
return /* @__PURE__ */
|
|
1976
|
+
return /* @__PURE__ */ jsxDEV6("section", {
|
|
1599
1977
|
className: [
|
|
1600
1978
|
"absolute-voice-provider-simulation",
|
|
1601
1979
|
`absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}`,
|
|
1602
1980
|
className
|
|
1603
1981
|
].filter(Boolean).join(" "),
|
|
1604
1982
|
children: [
|
|
1605
|
-
/* @__PURE__ */
|
|
1983
|
+
/* @__PURE__ */ jsxDEV6("header", {
|
|
1606
1984
|
className: "absolute-voice-provider-simulation__header",
|
|
1607
1985
|
children: [
|
|
1608
|
-
/* @__PURE__ */
|
|
1986
|
+
/* @__PURE__ */ jsxDEV6("span", {
|
|
1609
1987
|
className: "absolute-voice-provider-simulation__eyebrow",
|
|
1610
1988
|
children: model.title
|
|
1611
1989
|
}, undefined, false, undefined, this),
|
|
1612
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsxDEV6("strong", {
|
|
1613
1991
|
className: "absolute-voice-provider-simulation__label",
|
|
1614
1992
|
children: model.label
|
|
1615
1993
|
}, undefined, false, undefined, this)
|
|
1616
1994
|
]
|
|
1617
1995
|
}, undefined, true, undefined, this),
|
|
1618
|
-
/* @__PURE__ */
|
|
1996
|
+
/* @__PURE__ */ jsxDEV6("p", {
|
|
1619
1997
|
className: "absolute-voice-provider-simulation__description",
|
|
1620
1998
|
children: model.description
|
|
1621
1999
|
}, undefined, false, undefined, this),
|
|
1622
|
-
model.canSimulateFailure ? null : /* @__PURE__ */
|
|
2000
|
+
model.canSimulateFailure ? null : /* @__PURE__ */ jsxDEV6("p", {
|
|
1623
2001
|
className: "absolute-voice-provider-simulation__empty",
|
|
1624
2002
|
children: options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."
|
|
1625
2003
|
}, undefined, false, undefined, this),
|
|
1626
|
-
/* @__PURE__ */
|
|
2004
|
+
/* @__PURE__ */ jsxDEV6("div", {
|
|
1627
2005
|
className: "absolute-voice-provider-simulation__actions",
|
|
1628
2006
|
children: [
|
|
1629
|
-
model.failureProviders.map((provider) => /* @__PURE__ */
|
|
2007
|
+
model.failureProviders.map((provider) => /* @__PURE__ */ jsxDEV6("button", {
|
|
1630
2008
|
disabled: !model.canSimulateFailure || snapshot.isRunning,
|
|
1631
2009
|
onClick: () => run(provider.provider, "failure"),
|
|
1632
2010
|
type: "button",
|
|
@@ -1639,7 +2017,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1639
2017
|
"failure"
|
|
1640
2018
|
]
|
|
1641
2019
|
}, `fail-${provider.provider}`, true, undefined, this)),
|
|
1642
|
-
model.providers.map((provider) => /* @__PURE__ */
|
|
2020
|
+
model.providers.map((provider) => /* @__PURE__ */ jsxDEV6("button", {
|
|
1643
2021
|
disabled: snapshot.isRunning,
|
|
1644
2022
|
onClick: () => run(provider.provider, "recovery"),
|
|
1645
2023
|
type: "button",
|
|
@@ -1651,11 +2029,11 @@ var VoiceProviderSimulationControls = ({
|
|
|
1651
2029
|
}, `recover-${provider.provider}`, true, undefined, this))
|
|
1652
2030
|
]
|
|
1653
2031
|
}, undefined, true, undefined, this),
|
|
1654
|
-
snapshot.error ? /* @__PURE__ */
|
|
2032
|
+
snapshot.error ? /* @__PURE__ */ jsxDEV6("p", {
|
|
1655
2033
|
className: "absolute-voice-provider-simulation__error",
|
|
1656
2034
|
children: snapshot.error
|
|
1657
2035
|
}, undefined, false, undefined, this) : null,
|
|
1658
|
-
model.resultText ? /* @__PURE__ */
|
|
2036
|
+
model.resultText ? /* @__PURE__ */ jsxDEV6("pre", {
|
|
1659
2037
|
className: "absolute-voice-provider-simulation__result",
|
|
1660
2038
|
children: model.resultText
|
|
1661
2039
|
}, undefined, false, undefined, this) : null
|
|
@@ -1663,7 +2041,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1663
2041
|
}, undefined, true, undefined, this);
|
|
1664
2042
|
};
|
|
1665
2043
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1666
|
-
import { useEffect as
|
|
2044
|
+
import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
1667
2045
|
|
|
1668
2046
|
// src/client/providerCapabilities.ts
|
|
1669
2047
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1746,25 +2124,25 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1746
2124
|
|
|
1747
2125
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1748
2126
|
var useVoiceProviderCapabilities = (path = "/api/provider-capabilities", options = {}) => {
|
|
1749
|
-
const storeRef =
|
|
2127
|
+
const storeRef = useRef7(null);
|
|
1750
2128
|
if (!storeRef.current) {
|
|
1751
2129
|
storeRef.current = createVoiceProviderCapabilitiesStore(path, options);
|
|
1752
2130
|
}
|
|
1753
2131
|
const store = storeRef.current;
|
|
1754
|
-
|
|
2132
|
+
useEffect7(() => {
|
|
1755
2133
|
store.refresh().catch(() => {});
|
|
1756
2134
|
return () => store.close();
|
|
1757
2135
|
}, [store]);
|
|
1758
2136
|
return {
|
|
1759
|
-
...
|
|
2137
|
+
...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1760
2138
|
refresh: store.refresh
|
|
1761
2139
|
};
|
|
1762
2140
|
};
|
|
1763
2141
|
|
|
1764
2142
|
// src/client/providerCapabilitiesWidget.ts
|
|
1765
|
-
var
|
|
1766
|
-
var
|
|
1767
|
-
var
|
|
2143
|
+
var DEFAULT_TITLE6 = "Provider Capabilities";
|
|
2144
|
+
var DEFAULT_DESCRIPTION6 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
2145
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1768
2146
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1769
2147
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1770
2148
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -1808,36 +2186,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1808
2186
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1809
2187
|
return {
|
|
1810
2188
|
capabilities,
|
|
1811
|
-
description: options.description ??
|
|
2189
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1812
2190
|
error: snapshot.error,
|
|
1813
2191
|
isLoading: snapshot.isLoading,
|
|
1814
2192
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1815
2193
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1816
|
-
title: options.title ??
|
|
2194
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1817
2195
|
updatedAt: snapshot.updatedAt
|
|
1818
2196
|
};
|
|
1819
2197
|
};
|
|
1820
2198
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1821
2199
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1822
|
-
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--${
|
|
2200
|
+
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--${escapeHtml7(capability.status)}">
|
|
1823
2201
|
<header>
|
|
1824
|
-
<strong>${
|
|
1825
|
-
<span>${
|
|
2202
|
+
<strong>${escapeHtml7(capability.label)}</strong>
|
|
2203
|
+
<span>${escapeHtml7(formatStatus2(capability.status))}</span>
|
|
1826
2204
|
</header>
|
|
1827
|
-
<p>${
|
|
2205
|
+
<p>${escapeHtml7(capability.detail)}</p>
|
|
1828
2206
|
<dl>${capability.rows.map((row) => `<div>
|
|
1829
|
-
<dt>${
|
|
1830
|
-
<dd>${
|
|
2207
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
2208
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
1831
2209
|
</div>`).join("")}</dl>
|
|
1832
2210
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
1833
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
2211
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml7(model.status)}">
|
|
1834
2212
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1835
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1836
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
2213
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2214
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml7(model.label)}</strong>
|
|
1837
2215
|
</header>
|
|
1838
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
2216
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml7(model.description)}</p>
|
|
1839
2217
|
${capabilities}
|
|
1840
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
2218
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1841
2219
|
</section>`;
|
|
1842
2220
|
};
|
|
1843
2221
|
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}`;
|
|
@@ -1879,7 +2257,7 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1879
2257
|
};
|
|
1880
2258
|
|
|
1881
2259
|
// src/react/VoiceProviderCapabilities.tsx
|
|
1882
|
-
import { jsxDEV as
|
|
2260
|
+
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
1883
2261
|
var VoiceProviderCapabilities = ({
|
|
1884
2262
|
className,
|
|
1885
2263
|
path = "/api/provider-capabilities",
|
|
@@ -1887,58 +2265,58 @@ var VoiceProviderCapabilities = ({
|
|
|
1887
2265
|
}) => {
|
|
1888
2266
|
const snapshot = useVoiceProviderCapabilities(path, options);
|
|
1889
2267
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1890
|
-
return /* @__PURE__ */
|
|
2268
|
+
return /* @__PURE__ */ jsxDEV7("section", {
|
|
1891
2269
|
className: [
|
|
1892
2270
|
"absolute-voice-provider-capabilities",
|
|
1893
2271
|
`absolute-voice-provider-capabilities--${model.status}`,
|
|
1894
2272
|
className
|
|
1895
2273
|
].filter(Boolean).join(" "),
|
|
1896
2274
|
children: [
|
|
1897
|
-
/* @__PURE__ */
|
|
2275
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1898
2276
|
className: "absolute-voice-provider-capabilities__header",
|
|
1899
2277
|
children: [
|
|
1900
|
-
/* @__PURE__ */
|
|
2278
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1901
2279
|
className: "absolute-voice-provider-capabilities__eyebrow",
|
|
1902
2280
|
children: model.title
|
|
1903
2281
|
}, undefined, false, undefined, this),
|
|
1904
|
-
/* @__PURE__ */
|
|
2282
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1905
2283
|
className: "absolute-voice-provider-capabilities__label",
|
|
1906
2284
|
children: model.label
|
|
1907
2285
|
}, undefined, false, undefined, this)
|
|
1908
2286
|
]
|
|
1909
2287
|
}, undefined, true, undefined, this),
|
|
1910
|
-
/* @__PURE__ */
|
|
2288
|
+
/* @__PURE__ */ jsxDEV7("p", {
|
|
1911
2289
|
className: "absolute-voice-provider-capabilities__description",
|
|
1912
2290
|
children: model.description
|
|
1913
2291
|
}, undefined, false, undefined, this),
|
|
1914
|
-
model.capabilities.length ? /* @__PURE__ */
|
|
2292
|
+
model.capabilities.length ? /* @__PURE__ */ jsxDEV7("div", {
|
|
1915
2293
|
className: "absolute-voice-provider-capabilities__providers",
|
|
1916
|
-
children: model.capabilities.map((capability) => /* @__PURE__ */
|
|
2294
|
+
children: model.capabilities.map((capability) => /* @__PURE__ */ jsxDEV7("article", {
|
|
1917
2295
|
className: [
|
|
1918
2296
|
"absolute-voice-provider-capabilities__provider",
|
|
1919
2297
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1920
2298
|
].join(" "),
|
|
1921
2299
|
children: [
|
|
1922
|
-
/* @__PURE__ */
|
|
2300
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1923
2301
|
children: [
|
|
1924
|
-
/* @__PURE__ */
|
|
2302
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1925
2303
|
children: capability.label
|
|
1926
2304
|
}, undefined, false, undefined, this),
|
|
1927
|
-
/* @__PURE__ */
|
|
2305
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1928
2306
|
children: capability.status
|
|
1929
2307
|
}, undefined, false, undefined, this)
|
|
1930
2308
|
]
|
|
1931
2309
|
}, undefined, true, undefined, this),
|
|
1932
|
-
/* @__PURE__ */
|
|
2310
|
+
/* @__PURE__ */ jsxDEV7("p", {
|
|
1933
2311
|
children: capability.detail
|
|
1934
2312
|
}, undefined, false, undefined, this),
|
|
1935
|
-
/* @__PURE__ */
|
|
1936
|
-
children: capability.rows.map((row) => /* @__PURE__ */
|
|
2313
|
+
/* @__PURE__ */ jsxDEV7("dl", {
|
|
2314
|
+
children: capability.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
|
|
1937
2315
|
children: [
|
|
1938
|
-
/* @__PURE__ */
|
|
2316
|
+
/* @__PURE__ */ jsxDEV7("dt", {
|
|
1939
2317
|
children: row.label
|
|
1940
2318
|
}, undefined, false, undefined, this),
|
|
1941
|
-
/* @__PURE__ */
|
|
2319
|
+
/* @__PURE__ */ jsxDEV7("dd", {
|
|
1942
2320
|
children: row.value
|
|
1943
2321
|
}, undefined, false, undefined, this)
|
|
1944
2322
|
]
|
|
@@ -1946,11 +2324,11 @@ var VoiceProviderCapabilities = ({
|
|
|
1946
2324
|
}, undefined, false, undefined, this)
|
|
1947
2325
|
]
|
|
1948
2326
|
}, `${capability.kind}:${capability.provider}`, true, undefined, this))
|
|
1949
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2327
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
|
|
1950
2328
|
className: "absolute-voice-provider-capabilities__empty",
|
|
1951
2329
|
children: "Configure provider capabilities to see deployment coverage."
|
|
1952
2330
|
}, undefined, false, undefined, this),
|
|
1953
|
-
model.error ? /* @__PURE__ */
|
|
2331
|
+
model.error ? /* @__PURE__ */ jsxDEV7("p", {
|
|
1954
2332
|
className: "absolute-voice-provider-capabilities__error",
|
|
1955
2333
|
children: model.error
|
|
1956
2334
|
}, undefined, false, undefined, this) : null
|
|
@@ -1958,7 +2336,7 @@ var VoiceProviderCapabilities = ({
|
|
|
1958
2336
|
}, undefined, true, undefined, this);
|
|
1959
2337
|
};
|
|
1960
2338
|
// src/react/useVoiceProviderContracts.tsx
|
|
1961
|
-
import { useEffect as
|
|
2339
|
+
import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
1962
2340
|
|
|
1963
2341
|
// src/client/providerContracts.ts
|
|
1964
2342
|
var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
|
|
@@ -2037,25 +2415,25 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
|
|
|
2037
2415
|
|
|
2038
2416
|
// src/react/useVoiceProviderContracts.tsx
|
|
2039
2417
|
var useVoiceProviderContracts = (path = "/api/provider-contracts", options = {}) => {
|
|
2040
|
-
const storeRef =
|
|
2418
|
+
const storeRef = useRef8(null);
|
|
2041
2419
|
if (!storeRef.current) {
|
|
2042
2420
|
storeRef.current = createVoiceProviderContractsStore(path, options);
|
|
2043
2421
|
}
|
|
2044
2422
|
const store = storeRef.current;
|
|
2045
|
-
|
|
2423
|
+
useEffect8(() => {
|
|
2046
2424
|
store.refresh().catch(() => {});
|
|
2047
2425
|
return () => store.close();
|
|
2048
2426
|
}, [store]);
|
|
2049
2427
|
return {
|
|
2050
|
-
...
|
|
2428
|
+
...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2051
2429
|
refresh: store.refresh
|
|
2052
2430
|
};
|
|
2053
2431
|
};
|
|
2054
2432
|
|
|
2055
2433
|
// src/client/providerContractsWidget.ts
|
|
2056
|
-
var
|
|
2057
|
-
var
|
|
2058
|
-
var
|
|
2434
|
+
var DEFAULT_TITLE7 = "Provider Contracts";
|
|
2435
|
+
var DEFAULT_DESCRIPTION7 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
2436
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2059
2437
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2060
2438
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2061
2439
|
var contractDetail = (row) => {
|
|
@@ -2087,38 +2465,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
2087
2465
|
}));
|
|
2088
2466
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
2089
2467
|
return {
|
|
2090
|
-
description: options.description ??
|
|
2468
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2091
2469
|
error: snapshot.error,
|
|
2092
2470
|
isLoading: snapshot.isLoading,
|
|
2093
2471
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
2094
2472
|
rows,
|
|
2095
2473
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2096
|
-
title: options.title ??
|
|
2474
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2097
2475
|
updatedAt: snapshot.updatedAt
|
|
2098
2476
|
};
|
|
2099
2477
|
};
|
|
2100
2478
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
2101
2479
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
2102
|
-
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--${
|
|
2480
|
+
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--${escapeHtml8(row.status)}">
|
|
2103
2481
|
<header>
|
|
2104
|
-
<strong>${
|
|
2105
|
-
<span>${
|
|
2482
|
+
<strong>${escapeHtml8(row.label)}</strong>
|
|
2483
|
+
<span>${escapeHtml8(formatStatus3(row.status))}</span>
|
|
2106
2484
|
</header>
|
|
2107
|
-
<p>${
|
|
2108
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
2485
|
+
<p>${escapeHtml8(row.detail)}</p>
|
|
2486
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml8(remediation.href)}">${escapeHtml8(remediation.label)}</a>` : `<strong>${escapeHtml8(remediation.label)}</strong>`}<span>${escapeHtml8(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
2109
2487
|
<dl>${row.rows.map((item) => `<div>
|
|
2110
|
-
<dt>${
|
|
2111
|
-
<dd>${
|
|
2488
|
+
<dt>${escapeHtml8(item.label)}</dt>
|
|
2489
|
+
<dd>${escapeHtml8(item.value)}</dd>
|
|
2112
2490
|
</div>`).join("")}</dl>
|
|
2113
2491
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
2114
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
2492
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml8(model.status)}">
|
|
2115
2493
|
<header class="absolute-voice-provider-contracts__header">
|
|
2116
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
2117
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
2494
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2495
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml8(model.label)}</strong>
|
|
2118
2496
|
</header>
|
|
2119
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
2497
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml8(model.description)}</p>
|
|
2120
2498
|
${rows}
|
|
2121
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
2499
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2122
2500
|
</section>`;
|
|
2123
2501
|
};
|
|
2124
2502
|
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__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.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}`;
|
|
@@ -2160,7 +2538,7 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
2160
2538
|
};
|
|
2161
2539
|
|
|
2162
2540
|
// src/react/VoiceProviderContracts.tsx
|
|
2163
|
-
import { jsxDEV as
|
|
2541
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
2164
2542
|
var VoiceProviderContracts = ({
|
|
2165
2543
|
className,
|
|
2166
2544
|
path = "/api/provider-contracts",
|
|
@@ -2168,74 +2546,74 @@ var VoiceProviderContracts = ({
|
|
|
2168
2546
|
}) => {
|
|
2169
2547
|
const snapshot = useVoiceProviderContracts(path, options);
|
|
2170
2548
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
2171
|
-
return /* @__PURE__ */
|
|
2549
|
+
return /* @__PURE__ */ jsxDEV8("section", {
|
|
2172
2550
|
className: [
|
|
2173
2551
|
"absolute-voice-provider-contracts",
|
|
2174
2552
|
`absolute-voice-provider-contracts--${model.status}`,
|
|
2175
2553
|
className
|
|
2176
2554
|
].filter(Boolean).join(" "),
|
|
2177
2555
|
children: [
|
|
2178
|
-
/* @__PURE__ */
|
|
2556
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2179
2557
|
className: "absolute-voice-provider-contracts__header",
|
|
2180
2558
|
children: [
|
|
2181
|
-
/* @__PURE__ */
|
|
2559
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2182
2560
|
className: "absolute-voice-provider-contracts__eyebrow",
|
|
2183
2561
|
children: model.title
|
|
2184
2562
|
}, undefined, false, undefined, this),
|
|
2185
|
-
/* @__PURE__ */
|
|
2563
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2186
2564
|
className: "absolute-voice-provider-contracts__label",
|
|
2187
2565
|
children: model.label
|
|
2188
2566
|
}, undefined, false, undefined, this)
|
|
2189
2567
|
]
|
|
2190
2568
|
}, undefined, true, undefined, this),
|
|
2191
|
-
/* @__PURE__ */
|
|
2569
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2192
2570
|
className: "absolute-voice-provider-contracts__description",
|
|
2193
2571
|
children: model.description
|
|
2194
2572
|
}, undefined, false, undefined, this),
|
|
2195
|
-
model.rows.length ? /* @__PURE__ */
|
|
2573
|
+
model.rows.length ? /* @__PURE__ */ jsxDEV8("div", {
|
|
2196
2574
|
className: "absolute-voice-provider-contracts__rows",
|
|
2197
|
-
children: model.rows.map((row) => /* @__PURE__ */
|
|
2575
|
+
children: model.rows.map((row) => /* @__PURE__ */ jsxDEV8("article", {
|
|
2198
2576
|
className: [
|
|
2199
2577
|
"absolute-voice-provider-contracts__row",
|
|
2200
2578
|
`absolute-voice-provider-contracts__row--${row.status}`
|
|
2201
2579
|
].join(" "),
|
|
2202
2580
|
children: [
|
|
2203
|
-
/* @__PURE__ */
|
|
2581
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2204
2582
|
children: [
|
|
2205
|
-
/* @__PURE__ */
|
|
2583
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2206
2584
|
children: row.label
|
|
2207
2585
|
}, undefined, false, undefined, this),
|
|
2208
|
-
/* @__PURE__ */
|
|
2586
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2209
2587
|
children: row.status
|
|
2210
2588
|
}, undefined, false, undefined, this)
|
|
2211
2589
|
]
|
|
2212
2590
|
}, undefined, true, undefined, this),
|
|
2213
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2214
2592
|
children: row.detail
|
|
2215
2593
|
}, undefined, false, undefined, this),
|
|
2216
|
-
row.remediations.length ? /* @__PURE__ */
|
|
2594
|
+
row.remediations.length ? /* @__PURE__ */ jsxDEV8("ul", {
|
|
2217
2595
|
className: "absolute-voice-provider-contracts__remediations",
|
|
2218
|
-
children: row.remediations.map((remediation) => /* @__PURE__ */
|
|
2596
|
+
children: row.remediations.map((remediation) => /* @__PURE__ */ jsxDEV8("li", {
|
|
2219
2597
|
children: [
|
|
2220
|
-
remediation.href ? /* @__PURE__ */
|
|
2598
|
+
remediation.href ? /* @__PURE__ */ jsxDEV8("a", {
|
|
2221
2599
|
href: remediation.href,
|
|
2222
2600
|
children: remediation.label
|
|
2223
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2601
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("strong", {
|
|
2224
2602
|
children: remediation.label
|
|
2225
2603
|
}, undefined, false, undefined, this),
|
|
2226
|
-
/* @__PURE__ */
|
|
2604
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2227
2605
|
children: remediation.detail
|
|
2228
2606
|
}, undefined, false, undefined, this)
|
|
2229
2607
|
]
|
|
2230
2608
|
}, `${row.kind}:${row.provider}:${remediation.label}`, true, undefined, this))
|
|
2231
2609
|
}, undefined, false, undefined, this) : null,
|
|
2232
|
-
/* @__PURE__ */
|
|
2233
|
-
children: row.rows.map((item) => /* @__PURE__ */
|
|
2610
|
+
/* @__PURE__ */ jsxDEV8("dl", {
|
|
2611
|
+
children: row.rows.map((item) => /* @__PURE__ */ jsxDEV8("div", {
|
|
2234
2612
|
children: [
|
|
2235
|
-
/* @__PURE__ */
|
|
2613
|
+
/* @__PURE__ */ jsxDEV8("dt", {
|
|
2236
2614
|
children: item.label
|
|
2237
2615
|
}, undefined, false, undefined, this),
|
|
2238
|
-
/* @__PURE__ */
|
|
2616
|
+
/* @__PURE__ */ jsxDEV8("dd", {
|
|
2239
2617
|
children: item.value
|
|
2240
2618
|
}, undefined, false, undefined, this)
|
|
2241
2619
|
]
|
|
@@ -2243,11 +2621,11 @@ var VoiceProviderContracts = ({
|
|
|
2243
2621
|
}, undefined, false, undefined, this)
|
|
2244
2622
|
]
|
|
2245
2623
|
}, `${row.kind}:${row.provider}`, true, undefined, this))
|
|
2246
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2624
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
|
|
2247
2625
|
className: "absolute-voice-provider-contracts__empty",
|
|
2248
2626
|
children: "Configure provider contracts to see production coverage."
|
|
2249
2627
|
}, undefined, false, undefined, this),
|
|
2250
|
-
model.error ? /* @__PURE__ */
|
|
2628
|
+
model.error ? /* @__PURE__ */ jsxDEV8("p", {
|
|
2251
2629
|
className: "absolute-voice-provider-contracts__error",
|
|
2252
2630
|
children: model.error
|
|
2253
2631
|
}, undefined, false, undefined, this) : null
|
|
@@ -2255,7 +2633,7 @@ var VoiceProviderContracts = ({
|
|
|
2255
2633
|
}, undefined, true, undefined, this);
|
|
2256
2634
|
};
|
|
2257
2635
|
// src/react/useVoiceProviderStatus.tsx
|
|
2258
|
-
import { useEffect as
|
|
2636
|
+
import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
2259
2637
|
|
|
2260
2638
|
// src/client/providerStatus.ts
|
|
2261
2639
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -2339,25 +2717,25 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
2339
2717
|
|
|
2340
2718
|
// src/react/useVoiceProviderStatus.tsx
|
|
2341
2719
|
var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
|
|
2342
|
-
const storeRef =
|
|
2720
|
+
const storeRef = useRef9(null);
|
|
2343
2721
|
if (!storeRef.current) {
|
|
2344
2722
|
storeRef.current = createVoiceProviderStatusStore(path, options);
|
|
2345
2723
|
}
|
|
2346
2724
|
const store = storeRef.current;
|
|
2347
|
-
|
|
2725
|
+
useEffect9(() => {
|
|
2348
2726
|
store.refresh().catch(() => {});
|
|
2349
2727
|
return () => store.close();
|
|
2350
2728
|
}, [store]);
|
|
2351
2729
|
return {
|
|
2352
|
-
...
|
|
2730
|
+
...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2353
2731
|
refresh: store.refresh
|
|
2354
2732
|
};
|
|
2355
2733
|
};
|
|
2356
2734
|
|
|
2357
2735
|
// src/client/providerStatusWidget.ts
|
|
2358
|
-
var
|
|
2359
|
-
var
|
|
2360
|
-
var
|
|
2736
|
+
var DEFAULT_TITLE8 = "Voice Providers";
|
|
2737
|
+
var DEFAULT_DESCRIPTION8 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
2738
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2361
2739
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2362
2740
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2363
2741
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -2401,37 +2779,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
2401
2779
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
2402
2780
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
2403
2781
|
return {
|
|
2404
|
-
description: options.description ??
|
|
2782
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2405
2783
|
error: snapshot.error,
|
|
2406
2784
|
isLoading: snapshot.isLoading,
|
|
2407
2785
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
2408
2786
|
providers,
|
|
2409
2787
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2410
|
-
title: options.title ??
|
|
2788
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2411
2789
|
updatedAt: snapshot.updatedAt
|
|
2412
2790
|
};
|
|
2413
2791
|
};
|
|
2414
2792
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
2415
2793
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
2416
|
-
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--${
|
|
2794
|
+
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--${escapeHtml9(provider.status)}">
|
|
2417
2795
|
<header>
|
|
2418
|
-
<strong>${
|
|
2419
|
-
<span>${
|
|
2796
|
+
<strong>${escapeHtml9(provider.label)}</strong>
|
|
2797
|
+
<span>${escapeHtml9(formatStatus4(provider.status))}</span>
|
|
2420
2798
|
</header>
|
|
2421
|
-
<p>${
|
|
2799
|
+
<p>${escapeHtml9(provider.detail)}</p>
|
|
2422
2800
|
<dl>${provider.rows.map((row) => `<div>
|
|
2423
|
-
<dt>${
|
|
2424
|
-
<dd>${
|
|
2801
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2802
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2425
2803
|
</div>`).join("")}</dl>
|
|
2426
2804
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
2427
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
2805
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml9(model.status)}">
|
|
2428
2806
|
<header class="absolute-voice-provider-status__header">
|
|
2429
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
2430
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
2807
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2808
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml9(model.label)}</strong>
|
|
2431
2809
|
</header>
|
|
2432
|
-
<p class="absolute-voice-provider-status__description">${
|
|
2810
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml9(model.description)}</p>
|
|
2433
2811
|
${providers}
|
|
2434
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
2812
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2435
2813
|
</section>`;
|
|
2436
2814
|
};
|
|
2437
2815
|
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}`;
|
|
@@ -2473,7 +2851,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
2473
2851
|
};
|
|
2474
2852
|
|
|
2475
2853
|
// src/react/VoiceProviderStatus.tsx
|
|
2476
|
-
import { jsxDEV as
|
|
2854
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
2477
2855
|
var VoiceProviderStatus = ({
|
|
2478
2856
|
className,
|
|
2479
2857
|
path = "/api/provider-status",
|
|
@@ -2481,58 +2859,58 @@ var VoiceProviderStatus = ({
|
|
|
2481
2859
|
}) => {
|
|
2482
2860
|
const snapshot = useVoiceProviderStatus(path, options);
|
|
2483
2861
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
2484
|
-
return /* @__PURE__ */
|
|
2862
|
+
return /* @__PURE__ */ jsxDEV9("section", {
|
|
2485
2863
|
className: [
|
|
2486
2864
|
"absolute-voice-provider-status",
|
|
2487
2865
|
`absolute-voice-provider-status--${model.status}`,
|
|
2488
2866
|
className
|
|
2489
2867
|
].filter(Boolean).join(" "),
|
|
2490
2868
|
children: [
|
|
2491
|
-
/* @__PURE__ */
|
|
2869
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2492
2870
|
className: "absolute-voice-provider-status__header",
|
|
2493
2871
|
children: [
|
|
2494
|
-
/* @__PURE__ */
|
|
2872
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2495
2873
|
className: "absolute-voice-provider-status__eyebrow",
|
|
2496
2874
|
children: model.title
|
|
2497
2875
|
}, undefined, false, undefined, this),
|
|
2498
|
-
/* @__PURE__ */
|
|
2876
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2499
2877
|
className: "absolute-voice-provider-status__label",
|
|
2500
2878
|
children: model.label
|
|
2501
2879
|
}, undefined, false, undefined, this)
|
|
2502
2880
|
]
|
|
2503
2881
|
}, undefined, true, undefined, this),
|
|
2504
|
-
/* @__PURE__ */
|
|
2882
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2505
2883
|
className: "absolute-voice-provider-status__description",
|
|
2506
2884
|
children: model.description
|
|
2507
2885
|
}, undefined, false, undefined, this),
|
|
2508
|
-
model.providers.length ? /* @__PURE__ */
|
|
2886
|
+
model.providers.length ? /* @__PURE__ */ jsxDEV9("div", {
|
|
2509
2887
|
className: "absolute-voice-provider-status__providers",
|
|
2510
|
-
children: model.providers.map((provider) => /* @__PURE__ */
|
|
2888
|
+
children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV9("article", {
|
|
2511
2889
|
className: [
|
|
2512
2890
|
"absolute-voice-provider-status__provider",
|
|
2513
2891
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
2514
2892
|
].join(" "),
|
|
2515
2893
|
children: [
|
|
2516
|
-
/* @__PURE__ */
|
|
2894
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2517
2895
|
children: [
|
|
2518
|
-
/* @__PURE__ */
|
|
2896
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2519
2897
|
children: provider.label
|
|
2520
2898
|
}, undefined, false, undefined, this),
|
|
2521
|
-
/* @__PURE__ */
|
|
2899
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2522
2900
|
children: provider.status
|
|
2523
2901
|
}, undefined, false, undefined, this)
|
|
2524
2902
|
]
|
|
2525
2903
|
}, undefined, true, undefined, this),
|
|
2526
|
-
/* @__PURE__ */
|
|
2904
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2527
2905
|
children: provider.detail
|
|
2528
2906
|
}, undefined, false, undefined, this),
|
|
2529
|
-
/* @__PURE__ */
|
|
2530
|
-
children: provider.rows.map((row) => /* @__PURE__ */
|
|
2907
|
+
/* @__PURE__ */ jsxDEV9("dl", {
|
|
2908
|
+
children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV9("div", {
|
|
2531
2909
|
children: [
|
|
2532
|
-
/* @__PURE__ */
|
|
2910
|
+
/* @__PURE__ */ jsxDEV9("dt", {
|
|
2533
2911
|
children: row.label
|
|
2534
2912
|
}, undefined, false, undefined, this),
|
|
2535
|
-
/* @__PURE__ */
|
|
2913
|
+
/* @__PURE__ */ jsxDEV9("dd", {
|
|
2536
2914
|
children: row.value
|
|
2537
2915
|
}, undefined, false, undefined, this)
|
|
2538
2916
|
]
|
|
@@ -2540,11 +2918,11 @@ var VoiceProviderStatus = ({
|
|
|
2540
2918
|
}, undefined, false, undefined, this)
|
|
2541
2919
|
]
|
|
2542
2920
|
}, provider.provider, true, undefined, this))
|
|
2543
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2921
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
|
|
2544
2922
|
className: "absolute-voice-provider-status__empty",
|
|
2545
2923
|
children: "Run voice traffic to see provider health."
|
|
2546
2924
|
}, undefined, false, undefined, this),
|
|
2547
|
-
model.error ? /* @__PURE__ */
|
|
2925
|
+
model.error ? /* @__PURE__ */ jsxDEV9("p", {
|
|
2548
2926
|
className: "absolute-voice-provider-status__error",
|
|
2549
2927
|
children: model.error
|
|
2550
2928
|
}, undefined, false, undefined, this) : null
|
|
@@ -2552,7 +2930,7 @@ var VoiceProviderStatus = ({
|
|
|
2552
2930
|
}, undefined, true, undefined, this);
|
|
2553
2931
|
};
|
|
2554
2932
|
// src/react/useVoiceRoutingStatus.tsx
|
|
2555
|
-
import { useEffect as
|
|
2933
|
+
import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
2556
2934
|
|
|
2557
2935
|
// src/client/routingStatus.ts
|
|
2558
2936
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -2636,25 +3014,25 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2636
3014
|
|
|
2637
3015
|
// src/react/useVoiceRoutingStatus.tsx
|
|
2638
3016
|
var useVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
|
|
2639
|
-
const storeRef =
|
|
3017
|
+
const storeRef = useRef10(null);
|
|
2640
3018
|
if (!storeRef.current) {
|
|
2641
3019
|
storeRef.current = createVoiceRoutingStatusStore(path, options);
|
|
2642
3020
|
}
|
|
2643
3021
|
const store = storeRef.current;
|
|
2644
|
-
|
|
3022
|
+
useEffect10(() => {
|
|
2645
3023
|
store.refresh().catch(() => {});
|
|
2646
3024
|
return () => store.close();
|
|
2647
3025
|
}, [store]);
|
|
2648
3026
|
return {
|
|
2649
|
-
...
|
|
3027
|
+
...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2650
3028
|
refresh: store.refresh
|
|
2651
3029
|
};
|
|
2652
3030
|
};
|
|
2653
3031
|
|
|
2654
3032
|
// src/client/routingStatusWidget.ts
|
|
2655
|
-
var
|
|
2656
|
-
var
|
|
2657
|
-
var
|
|
3033
|
+
var DEFAULT_TITLE9 = "Voice Routing";
|
|
3034
|
+
var DEFAULT_DESCRIPTION9 = "Latest provider routing decision from the self-hosted trace store.";
|
|
3035
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2658
3036
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2659
3037
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2660
3038
|
const decision = snapshot.decision;
|
|
@@ -2678,30 +3056,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2678
3056
|
] : [];
|
|
2679
3057
|
return {
|
|
2680
3058
|
decision,
|
|
2681
|
-
description: options.description ??
|
|
3059
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
2682
3060
|
error: snapshot.error,
|
|
2683
3061
|
isLoading: snapshot.isLoading,
|
|
2684
3062
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2685
3063
|
rows,
|
|
2686
3064
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2687
|
-
title: options.title ??
|
|
3065
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
2688
3066
|
updatedAt: snapshot.updatedAt
|
|
2689
3067
|
};
|
|
2690
3068
|
};
|
|
2691
3069
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2692
3070
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2693
3071
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2694
|
-
<span>${
|
|
2695
|
-
<strong>${
|
|
3072
|
+
<span>${escapeHtml10(row.label)}</span>
|
|
3073
|
+
<strong>${escapeHtml10(row.value)}</strong>
|
|
2696
3074
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2697
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
3075
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml10(model.status)}">
|
|
2698
3076
|
<header class="absolute-voice-routing-status__header">
|
|
2699
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2700
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
3077
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml10(model.title)}</span>
|
|
3078
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml10(model.label)}</strong>
|
|
2701
3079
|
</header>
|
|
2702
|
-
<p class="absolute-voice-routing-status__description">${
|
|
3080
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml10(model.description)}</p>
|
|
2703
3081
|
${rows}
|
|
2704
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
3082
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2705
3083
|
</section>`;
|
|
2706
3084
|
};
|
|
2707
3085
|
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}`;
|
|
@@ -2743,7 +3121,7 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
2743
3121
|
};
|
|
2744
3122
|
|
|
2745
3123
|
// src/react/VoiceRoutingStatus.tsx
|
|
2746
|
-
import { jsxDEV as
|
|
3124
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
2747
3125
|
var VoiceRoutingStatus = ({
|
|
2748
3126
|
className,
|
|
2749
3127
|
path = "/api/routing/latest",
|
|
@@ -2751,47 +3129,47 @@ var VoiceRoutingStatus = ({
|
|
|
2751
3129
|
}) => {
|
|
2752
3130
|
const snapshot = useVoiceRoutingStatus(path, options);
|
|
2753
3131
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2754
|
-
return /* @__PURE__ */
|
|
3132
|
+
return /* @__PURE__ */ jsxDEV10("section", {
|
|
2755
3133
|
className: [
|
|
2756
3134
|
"absolute-voice-routing-status",
|
|
2757
3135
|
`absolute-voice-routing-status--${model.status}`,
|
|
2758
3136
|
className
|
|
2759
3137
|
].filter(Boolean).join(" "),
|
|
2760
3138
|
children: [
|
|
2761
|
-
/* @__PURE__ */
|
|
3139
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2762
3140
|
className: "absolute-voice-routing-status__header",
|
|
2763
3141
|
children: [
|
|
2764
|
-
/* @__PURE__ */
|
|
3142
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2765
3143
|
className: "absolute-voice-routing-status__eyebrow",
|
|
2766
3144
|
children: model.title
|
|
2767
3145
|
}, undefined, false, undefined, this),
|
|
2768
|
-
/* @__PURE__ */
|
|
3146
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2769
3147
|
className: "absolute-voice-routing-status__label",
|
|
2770
3148
|
children: model.label
|
|
2771
3149
|
}, undefined, false, undefined, this)
|
|
2772
3150
|
]
|
|
2773
3151
|
}, undefined, true, undefined, this),
|
|
2774
|
-
/* @__PURE__ */
|
|
3152
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2775
3153
|
className: "absolute-voice-routing-status__description",
|
|
2776
3154
|
children: model.description
|
|
2777
3155
|
}, undefined, false, undefined, this),
|
|
2778
|
-
model.rows.length ? /* @__PURE__ */
|
|
3156
|
+
model.rows.length ? /* @__PURE__ */ jsxDEV10("div", {
|
|
2779
3157
|
className: "absolute-voice-routing-status__grid",
|
|
2780
|
-
children: model.rows.map((row) => /* @__PURE__ */
|
|
3158
|
+
children: model.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
|
|
2781
3159
|
children: [
|
|
2782
|
-
/* @__PURE__ */
|
|
3160
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2783
3161
|
children: row.label
|
|
2784
3162
|
}, undefined, false, undefined, this),
|
|
2785
|
-
/* @__PURE__ */
|
|
3163
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2786
3164
|
children: row.value
|
|
2787
3165
|
}, undefined, false, undefined, this)
|
|
2788
3166
|
]
|
|
2789
3167
|
}, row.label, true, undefined, this))
|
|
2790
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
3168
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
|
|
2791
3169
|
className: "absolute-voice-routing-status__empty",
|
|
2792
3170
|
children: "Start a voice session to see the selected provider."
|
|
2793
3171
|
}, undefined, false, undefined, this),
|
|
2794
|
-
model.error ? /* @__PURE__ */
|
|
3172
|
+
model.error ? /* @__PURE__ */ jsxDEV10("p", {
|
|
2795
3173
|
className: "absolute-voice-routing-status__error",
|
|
2796
3174
|
children: model.error
|
|
2797
3175
|
}, undefined, false, undefined, this) : null
|
|
@@ -2879,16 +3257,16 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
2879
3257
|
};
|
|
2880
3258
|
|
|
2881
3259
|
// src/client/traceTimelineWidget.ts
|
|
2882
|
-
var
|
|
2883
|
-
var
|
|
2884
|
-
var
|
|
2885
|
-
var
|
|
3260
|
+
var DEFAULT_TITLE10 = "Voice Traces";
|
|
3261
|
+
var DEFAULT_DESCRIPTION10 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
3262
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3263
|
+
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
2886
3264
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
2887
3265
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
2888
3266
|
const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
|
|
2889
3267
|
...session,
|
|
2890
3268
|
detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
|
|
2891
|
-
durationLabel:
|
|
3269
|
+
durationLabel: formatMs2(session.summary.callDurationMs),
|
|
2892
3270
|
incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
|
|
2893
3271
|
label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
|
|
2894
3272
|
operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
|
|
@@ -2897,13 +3275,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
2897
3275
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
2898
3276
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
2899
3277
|
return {
|
|
2900
|
-
description: options.description ??
|
|
3278
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
2901
3279
|
error: snapshot.error,
|
|
2902
3280
|
isLoading: snapshot.isLoading,
|
|
2903
3281
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
2904
3282
|
sessions,
|
|
2905
3283
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2906
|
-
title: options.title ??
|
|
3284
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
2907
3285
|
updatedAt: snapshot.updatedAt
|
|
2908
3286
|
};
|
|
2909
3287
|
};
|
|
@@ -2911,27 +3289,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
2911
3289
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
2912
3290
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
2913
3291
|
const supportLinks = [
|
|
2914
|
-
`<a href="${
|
|
2915
|
-
session.operationsRecordHref ? `<a href="${
|
|
2916
|
-
session.incidentBundleHref ? `<a href="${
|
|
3292
|
+
`<a href="${escapeHtml11(session.detailHref)}">Open timeline</a>`,
|
|
3293
|
+
session.operationsRecordHref ? `<a href="${escapeHtml11(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
3294
|
+
session.incidentBundleHref ? `<a href="${escapeHtml11(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
2917
3295
|
].filter(Boolean).join("");
|
|
2918
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
3296
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml11(session.status)}">
|
|
2919
3297
|
<header>
|
|
2920
|
-
<strong>${
|
|
2921
|
-
<span>${
|
|
3298
|
+
<strong>${escapeHtml11(session.sessionId)}</strong>
|
|
3299
|
+
<span>${escapeHtml11(session.status)}</span>
|
|
2922
3300
|
</header>
|
|
2923
|
-
<p>${
|
|
3301
|
+
<p>${escapeHtml11(session.label)} \xB7 ${escapeHtml11(session.durationLabel)} \xB7 ${escapeHtml11(session.providerLabel)}</p>
|
|
2924
3302
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
2925
3303
|
</article>`;
|
|
2926
3304
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
2927
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
3305
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml11(model.status)}">
|
|
2928
3306
|
<header class="absolute-voice-trace-timeline__header">
|
|
2929
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
2930
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
3307
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml11(model.title)}</span>
|
|
3308
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml11(model.label)}</strong>
|
|
2931
3309
|
</header>
|
|
2932
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
3310
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml11(model.description)}</p>
|
|
2933
3311
|
${sessions}
|
|
2934
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
3312
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
2935
3313
|
</section>`;
|
|
2936
3314
|
};
|
|
2937
3315
|
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__actions{display:flex;flex-wrap:wrap;gap:10px}.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}`;
|
|
@@ -2978,25 +3356,25 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
2978
3356
|
};
|
|
2979
3357
|
|
|
2980
3358
|
// src/react/useVoiceTraceTimeline.tsx
|
|
2981
|
-
import { useEffect as
|
|
3359
|
+
import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
2982
3360
|
var useVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
|
|
2983
|
-
const storeRef =
|
|
3361
|
+
const storeRef = useRef11(null);
|
|
2984
3362
|
if (!storeRef.current) {
|
|
2985
3363
|
storeRef.current = createVoiceTraceTimelineStore(path, options);
|
|
2986
3364
|
}
|
|
2987
3365
|
const store = storeRef.current;
|
|
2988
|
-
|
|
3366
|
+
useEffect11(() => {
|
|
2989
3367
|
store.refresh().catch(() => {});
|
|
2990
3368
|
return () => store.close();
|
|
2991
3369
|
}, [store]);
|
|
2992
3370
|
return {
|
|
2993
|
-
...
|
|
3371
|
+
...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2994
3372
|
refresh: store.refresh
|
|
2995
3373
|
};
|
|
2996
3374
|
};
|
|
2997
3375
|
|
|
2998
3376
|
// src/react/VoiceTraceTimeline.tsx
|
|
2999
|
-
import { jsxDEV as
|
|
3377
|
+
import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
|
|
3000
3378
|
var VoiceTraceTimeline = ({
|
|
3001
3379
|
className,
|
|
3002
3380
|
path = "/api/voice-traces",
|
|
@@ -3004,49 +3382,49 @@ var VoiceTraceTimeline = ({
|
|
|
3004
3382
|
}) => {
|
|
3005
3383
|
const snapshot = useVoiceTraceTimeline(path, options);
|
|
3006
3384
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
3007
|
-
return /* @__PURE__ */
|
|
3385
|
+
return /* @__PURE__ */ jsxDEV11("section", {
|
|
3008
3386
|
className: [
|
|
3009
3387
|
"absolute-voice-trace-timeline",
|
|
3010
3388
|
`absolute-voice-trace-timeline--${model.status}`,
|
|
3011
3389
|
className
|
|
3012
3390
|
].filter(Boolean).join(" "),
|
|
3013
3391
|
children: [
|
|
3014
|
-
/* @__PURE__ */
|
|
3392
|
+
/* @__PURE__ */ jsxDEV11("header", {
|
|
3015
3393
|
className: "absolute-voice-trace-timeline__header",
|
|
3016
3394
|
children: [
|
|
3017
|
-
/* @__PURE__ */
|
|
3395
|
+
/* @__PURE__ */ jsxDEV11("span", {
|
|
3018
3396
|
className: "absolute-voice-trace-timeline__eyebrow",
|
|
3019
3397
|
children: model.title
|
|
3020
3398
|
}, undefined, false, undefined, this),
|
|
3021
|
-
/* @__PURE__ */
|
|
3399
|
+
/* @__PURE__ */ jsxDEV11("strong", {
|
|
3022
3400
|
className: "absolute-voice-trace-timeline__label",
|
|
3023
3401
|
children: model.label
|
|
3024
3402
|
}, undefined, false, undefined, this)
|
|
3025
3403
|
]
|
|
3026
3404
|
}, undefined, true, undefined, this),
|
|
3027
|
-
/* @__PURE__ */
|
|
3405
|
+
/* @__PURE__ */ jsxDEV11("p", {
|
|
3028
3406
|
className: "absolute-voice-trace-timeline__description",
|
|
3029
3407
|
children: model.description
|
|
3030
3408
|
}, undefined, false, undefined, this),
|
|
3031
|
-
model.sessions.length ? /* @__PURE__ */
|
|
3409
|
+
model.sessions.length ? /* @__PURE__ */ jsxDEV11("div", {
|
|
3032
3410
|
className: "absolute-voice-trace-timeline__sessions",
|
|
3033
|
-
children: model.sessions.map((session) => /* @__PURE__ */
|
|
3411
|
+
children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV11("article", {
|
|
3034
3412
|
className: [
|
|
3035
3413
|
"absolute-voice-trace-timeline__session",
|
|
3036
3414
|
`absolute-voice-trace-timeline__session--${session.status}`
|
|
3037
3415
|
].join(" "),
|
|
3038
3416
|
children: [
|
|
3039
|
-
/* @__PURE__ */
|
|
3417
|
+
/* @__PURE__ */ jsxDEV11("header", {
|
|
3040
3418
|
children: [
|
|
3041
|
-
/* @__PURE__ */
|
|
3419
|
+
/* @__PURE__ */ jsxDEV11("strong", {
|
|
3042
3420
|
children: session.sessionId
|
|
3043
3421
|
}, undefined, false, undefined, this),
|
|
3044
|
-
/* @__PURE__ */
|
|
3422
|
+
/* @__PURE__ */ jsxDEV11("span", {
|
|
3045
3423
|
children: session.status
|
|
3046
3424
|
}, undefined, false, undefined, this)
|
|
3047
3425
|
]
|
|
3048
3426
|
}, undefined, true, undefined, this),
|
|
3049
|
-
/* @__PURE__ */
|
|
3427
|
+
/* @__PURE__ */ jsxDEV11("p", {
|
|
3050
3428
|
children: [
|
|
3051
3429
|
session.label,
|
|
3052
3430
|
" \xB7 ",
|
|
@@ -3056,18 +3434,18 @@ var VoiceTraceTimeline = ({
|
|
|
3056
3434
|
session.providerLabel
|
|
3057
3435
|
]
|
|
3058
3436
|
}, undefined, true, undefined, this),
|
|
3059
|
-
/* @__PURE__ */
|
|
3437
|
+
/* @__PURE__ */ jsxDEV11("p", {
|
|
3060
3438
|
className: "absolute-voice-trace-timeline__actions",
|
|
3061
3439
|
children: [
|
|
3062
|
-
/* @__PURE__ */
|
|
3440
|
+
/* @__PURE__ */ jsxDEV11("a", {
|
|
3063
3441
|
href: session.detailHref,
|
|
3064
3442
|
children: "Open timeline"
|
|
3065
3443
|
}, undefined, false, undefined, this),
|
|
3066
|
-
session.operationsRecordHref ? /* @__PURE__ */
|
|
3444
|
+
session.operationsRecordHref ? /* @__PURE__ */ jsxDEV11("a", {
|
|
3067
3445
|
href: session.operationsRecordHref,
|
|
3068
3446
|
children: "Open operations record"
|
|
3069
3447
|
}, undefined, false, undefined, this) : null,
|
|
3070
|
-
session.incidentBundleHref ? /* @__PURE__ */
|
|
3448
|
+
session.incidentBundleHref ? /* @__PURE__ */ jsxDEV11("a", {
|
|
3071
3449
|
href: session.incidentBundleHref,
|
|
3072
3450
|
children: "Export incident bundle"
|
|
3073
3451
|
}, undefined, false, undefined, this) : null
|
|
@@ -3075,11 +3453,11 @@ var VoiceTraceTimeline = ({
|
|
|
3075
3453
|
}, undefined, true, undefined, this)
|
|
3076
3454
|
]
|
|
3077
3455
|
}, session.sessionId, true, undefined, this))
|
|
3078
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
3456
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV11("p", {
|
|
3079
3457
|
className: "absolute-voice-trace-timeline__empty",
|
|
3080
3458
|
children: "Run a voice session to see call timelines."
|
|
3081
3459
|
}, undefined, false, undefined, this),
|
|
3082
|
-
model.error ? /* @__PURE__ */
|
|
3460
|
+
model.error ? /* @__PURE__ */ jsxDEV11("p", {
|
|
3083
3461
|
className: "absolute-voice-trace-timeline__error",
|
|
3084
3462
|
children: model.error
|
|
3085
3463
|
}, undefined, false, undefined, this) : null
|
|
@@ -3087,7 +3465,7 @@ var VoiceTraceTimeline = ({
|
|
|
3087
3465
|
}, undefined, true, undefined, this);
|
|
3088
3466
|
};
|
|
3089
3467
|
// src/react/useVoiceAgentSquadStatus.tsx
|
|
3090
|
-
import { useEffect as
|
|
3468
|
+
import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
3091
3469
|
|
|
3092
3470
|
// src/client/agentSquadStatus.ts
|
|
3093
3471
|
var getString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
@@ -3165,25 +3543,25 @@ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}
|
|
|
3165
3543
|
|
|
3166
3544
|
// src/react/useVoiceAgentSquadStatus.tsx
|
|
3167
3545
|
var useVoiceAgentSquadStatus = (path = "/api/voice-traces", options = {}) => {
|
|
3168
|
-
const storeRef =
|
|
3546
|
+
const storeRef = useRef12(null);
|
|
3169
3547
|
if (!storeRef.current) {
|
|
3170
3548
|
storeRef.current = createVoiceAgentSquadStatusStore(path, options);
|
|
3171
3549
|
}
|
|
3172
3550
|
const store = storeRef.current;
|
|
3173
|
-
|
|
3551
|
+
useEffect12(() => {
|
|
3174
3552
|
store.refresh().catch(() => {});
|
|
3175
3553
|
return () => store.close();
|
|
3176
3554
|
}, [store]);
|
|
3177
3555
|
return {
|
|
3178
|
-
...
|
|
3556
|
+
...useSyncExternalStore12(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
3179
3557
|
refresh: store.refresh
|
|
3180
3558
|
};
|
|
3181
3559
|
};
|
|
3182
3560
|
|
|
3183
3561
|
// src/client/agentSquadStatusWidget.ts
|
|
3184
|
-
var
|
|
3185
|
-
var
|
|
3186
|
-
var
|
|
3562
|
+
var DEFAULT_TITLE11 = "Voice Agent Squad";
|
|
3563
|
+
var DEFAULT_DESCRIPTION11 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
3564
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3187
3565
|
var labelFor = (current) => {
|
|
3188
3566
|
if (!current)
|
|
3189
3567
|
return "Waiting for specialist activity";
|
|
@@ -3197,37 +3575,37 @@ var labelFor = (current) => {
|
|
|
3197
3575
|
};
|
|
3198
3576
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
3199
3577
|
current: snapshot.report.current,
|
|
3200
|
-
description: options.description ??
|
|
3578
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
3201
3579
|
error: snapshot.error,
|
|
3202
3580
|
isLoading: snapshot.isLoading,
|
|
3203
3581
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
3204
3582
|
sessionCount: snapshot.report.sessionCount,
|
|
3205
3583
|
sessions: snapshot.report.sessions,
|
|
3206
|
-
title: options.title ??
|
|
3584
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
3207
3585
|
updatedAt: snapshot.updatedAt
|
|
3208
3586
|
});
|
|
3209
3587
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
3210
3588
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
3211
3589
|
const current = model.current;
|
|
3212
3590
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
3213
|
-
<span>${
|
|
3214
|
-
<strong>${
|
|
3215
|
-
<em>${
|
|
3216
|
-
${session.summary || session.reason ? `<p>${
|
|
3591
|
+
<span>${escapeHtml12(session.sessionId)}</span>
|
|
3592
|
+
<strong>${escapeHtml12(session.targetAgentId ?? "none")}</strong>
|
|
3593
|
+
<em>${escapeHtml12(session.status)}</em>
|
|
3594
|
+
${session.summary || session.reason ? `<p>${escapeHtml12(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
3217
3595
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
3218
3596
|
return `<section class="absolute-voice-agent-squad-status">
|
|
3219
3597
|
<header>
|
|
3220
|
-
<span>${
|
|
3221
|
-
<strong>${
|
|
3598
|
+
<span>${escapeHtml12(model.title)}</span>
|
|
3599
|
+
<strong>${escapeHtml12(model.label)}</strong>
|
|
3222
3600
|
</header>
|
|
3223
|
-
<p>${
|
|
3601
|
+
<p>${escapeHtml12(model.description)}</p>
|
|
3224
3602
|
<div>
|
|
3225
|
-
<span>Session</span><strong>${
|
|
3226
|
-
<span>From</span><strong>${
|
|
3227
|
-
<span>Status</span><strong>${
|
|
3603
|
+
<span>Session</span><strong>${escapeHtml12(current?.sessionId ?? "n/a")}</strong>
|
|
3604
|
+
<span>From</span><strong>${escapeHtml12(current?.fromAgentId ?? "n/a")}</strong>
|
|
3605
|
+
<span>Status</span><strong>${escapeHtml12(current?.status ?? "idle")}</strong>
|
|
3228
3606
|
</div>
|
|
3229
3607
|
<ul>${rows}</ul>
|
|
3230
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
3608
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
3231
3609
|
</section>`;
|
|
3232
3610
|
};
|
|
3233
3611
|
var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
|
|
@@ -3272,7 +3650,7 @@ var defineVoiceAgentSquadStatusElement = (tagName = "absolute-voice-agent-squad-
|
|
|
3272
3650
|
};
|
|
3273
3651
|
|
|
3274
3652
|
// src/react/VoiceAgentSquadStatus.tsx
|
|
3275
|
-
import { jsxDEV as
|
|
3653
|
+
import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime";
|
|
3276
3654
|
function VoiceAgentSquadStatus({
|
|
3277
3655
|
path = "/api/voice-traces",
|
|
3278
3656
|
...options
|
|
@@ -3280,64 +3658,64 @@ function VoiceAgentSquadStatus({
|
|
|
3280
3658
|
const snapshot = useVoiceAgentSquadStatus(path, options);
|
|
3281
3659
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
3282
3660
|
const current = model.current;
|
|
3283
|
-
return /* @__PURE__ */
|
|
3661
|
+
return /* @__PURE__ */ jsxDEV12("section", {
|
|
3284
3662
|
className: "absolute-voice-agent-squad-status",
|
|
3285
3663
|
children: [
|
|
3286
|
-
/* @__PURE__ */
|
|
3664
|
+
/* @__PURE__ */ jsxDEV12("header", {
|
|
3287
3665
|
children: [
|
|
3288
|
-
/* @__PURE__ */
|
|
3666
|
+
/* @__PURE__ */ jsxDEV12("span", {
|
|
3289
3667
|
children: model.title
|
|
3290
3668
|
}, undefined, false, undefined, this),
|
|
3291
|
-
/* @__PURE__ */
|
|
3669
|
+
/* @__PURE__ */ jsxDEV12("strong", {
|
|
3292
3670
|
children: model.label
|
|
3293
3671
|
}, undefined, false, undefined, this)
|
|
3294
3672
|
]
|
|
3295
3673
|
}, undefined, true, undefined, this),
|
|
3296
|
-
/* @__PURE__ */
|
|
3674
|
+
/* @__PURE__ */ jsxDEV12("p", {
|
|
3297
3675
|
children: model.description
|
|
3298
3676
|
}, undefined, false, undefined, this),
|
|
3299
|
-
/* @__PURE__ */
|
|
3677
|
+
/* @__PURE__ */ jsxDEV12("dl", {
|
|
3300
3678
|
children: [
|
|
3301
|
-
/* @__PURE__ */
|
|
3679
|
+
/* @__PURE__ */ jsxDEV12("div", {
|
|
3302
3680
|
children: [
|
|
3303
|
-
/* @__PURE__ */
|
|
3681
|
+
/* @__PURE__ */ jsxDEV12("dt", {
|
|
3304
3682
|
children: "Session"
|
|
3305
3683
|
}, undefined, false, undefined, this),
|
|
3306
|
-
/* @__PURE__ */
|
|
3684
|
+
/* @__PURE__ */ jsxDEV12("dd", {
|
|
3307
3685
|
children: current?.sessionId ?? "n/a"
|
|
3308
3686
|
}, undefined, false, undefined, this)
|
|
3309
3687
|
]
|
|
3310
3688
|
}, undefined, true, undefined, this),
|
|
3311
|
-
/* @__PURE__ */
|
|
3689
|
+
/* @__PURE__ */ jsxDEV12("div", {
|
|
3312
3690
|
children: [
|
|
3313
|
-
/* @__PURE__ */
|
|
3691
|
+
/* @__PURE__ */ jsxDEV12("dt", {
|
|
3314
3692
|
children: "Current specialist"
|
|
3315
3693
|
}, undefined, false, undefined, this),
|
|
3316
|
-
/* @__PURE__ */
|
|
3694
|
+
/* @__PURE__ */ jsxDEV12("dd", {
|
|
3317
3695
|
children: current?.targetAgentId ?? "none"
|
|
3318
3696
|
}, undefined, false, undefined, this)
|
|
3319
3697
|
]
|
|
3320
3698
|
}, undefined, true, undefined, this),
|
|
3321
|
-
/* @__PURE__ */
|
|
3699
|
+
/* @__PURE__ */ jsxDEV12("div", {
|
|
3322
3700
|
children: [
|
|
3323
|
-
/* @__PURE__ */
|
|
3701
|
+
/* @__PURE__ */ jsxDEV12("dt", {
|
|
3324
3702
|
children: "Status"
|
|
3325
3703
|
}, undefined, false, undefined, this),
|
|
3326
|
-
/* @__PURE__ */
|
|
3704
|
+
/* @__PURE__ */ jsxDEV12("dd", {
|
|
3327
3705
|
children: current?.status ?? "idle"
|
|
3328
3706
|
}, undefined, false, undefined, this)
|
|
3329
3707
|
]
|
|
3330
3708
|
}, undefined, true, undefined, this)
|
|
3331
3709
|
]
|
|
3332
3710
|
}, undefined, true, undefined, this),
|
|
3333
|
-
model.error ? /* @__PURE__ */
|
|
3711
|
+
model.error ? /* @__PURE__ */ jsxDEV12("p", {
|
|
3334
3712
|
children: model.error
|
|
3335
3713
|
}, undefined, false, undefined, this) : null
|
|
3336
3714
|
]
|
|
3337
3715
|
}, undefined, true, undefined, this);
|
|
3338
3716
|
}
|
|
3339
3717
|
// src/react/useVoiceTurnLatency.tsx
|
|
3340
|
-
import { useEffect as
|
|
3718
|
+
import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
3341
3719
|
|
|
3342
3720
|
// src/client/turnLatency.ts
|
|
3343
3721
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -3444,73 +3822,73 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
3444
3822
|
|
|
3445
3823
|
// src/react/useVoiceTurnLatency.tsx
|
|
3446
3824
|
var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
|
|
3447
|
-
const storeRef =
|
|
3825
|
+
const storeRef = useRef13(null);
|
|
3448
3826
|
if (!storeRef.current) {
|
|
3449
3827
|
storeRef.current = createVoiceTurnLatencyStore(path, options);
|
|
3450
3828
|
}
|
|
3451
3829
|
const store = storeRef.current;
|
|
3452
|
-
|
|
3830
|
+
useEffect13(() => {
|
|
3453
3831
|
store.refresh().catch(() => {});
|
|
3454
3832
|
return () => store.close();
|
|
3455
3833
|
}, [store]);
|
|
3456
3834
|
return {
|
|
3457
|
-
...
|
|
3835
|
+
...useSyncExternalStore13(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
3458
3836
|
refresh: store.refresh,
|
|
3459
3837
|
runProof: store.runProof
|
|
3460
3838
|
};
|
|
3461
3839
|
};
|
|
3462
3840
|
|
|
3463
3841
|
// src/client/turnLatencyWidget.ts
|
|
3464
|
-
var
|
|
3465
|
-
var
|
|
3842
|
+
var DEFAULT_TITLE12 = "Turn Latency";
|
|
3843
|
+
var DEFAULT_DESCRIPTION12 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3466
3844
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3467
|
-
var
|
|
3468
|
-
var
|
|
3845
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3846
|
+
var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3469
3847
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3470
3848
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
3471
3849
|
...turn,
|
|
3472
3850
|
label: turn.text || "Empty turn",
|
|
3473
3851
|
rows: turn.stages.map((stage) => ({
|
|
3474
3852
|
label: stage.label,
|
|
3475
|
-
value:
|
|
3853
|
+
value: formatMs3(stage.valueMs)
|
|
3476
3854
|
}))
|
|
3477
3855
|
}));
|
|
3478
3856
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3479
3857
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3480
3858
|
return {
|
|
3481
|
-
description: options.description ??
|
|
3859
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
3482
3860
|
error: snapshot.error,
|
|
3483
3861
|
isLoading: snapshot.isLoading,
|
|
3484
|
-
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${
|
|
3862
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3485
3863
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
3486
3864
|
showProofAction: Boolean(options.proofPath),
|
|
3487
3865
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3488
|
-
title: options.title ??
|
|
3866
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
3489
3867
|
turns,
|
|
3490
3868
|
updatedAt: snapshot.updatedAt
|
|
3491
3869
|
};
|
|
3492
3870
|
};
|
|
3493
3871
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3494
3872
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
3495
|
-
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--${
|
|
3873
|
+
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--${escapeHtml13(turn.status)}">
|
|
3496
3874
|
<header>
|
|
3497
|
-
<strong>${
|
|
3498
|
-
<span>${
|
|
3875
|
+
<strong>${escapeHtml13(turn.label)}</strong>
|
|
3876
|
+
<span>${escapeHtml13(turn.status)}</span>
|
|
3499
3877
|
</header>
|
|
3500
3878
|
<dl>${turn.rows.map((row) => `<div>
|
|
3501
|
-
<dt>${
|
|
3502
|
-
<dd>${
|
|
3879
|
+
<dt>${escapeHtml13(row.label)}</dt>
|
|
3880
|
+
<dd>${escapeHtml13(row.value)}</dd>
|
|
3503
3881
|
</div>`).join("")}</dl>
|
|
3504
3882
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3505
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
3883
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml13(model.status)}">
|
|
3506
3884
|
<header class="absolute-voice-turn-latency__header">
|
|
3507
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3508
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
3885
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml13(model.title)}</span>
|
|
3886
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml13(model.label)}</strong>
|
|
3509
3887
|
</header>
|
|
3510
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3511
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
3888
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml13(model.description)}</p>
|
|
3889
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml13(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
3512
3890
|
${turns}
|
|
3513
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
3891
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
3514
3892
|
</section>`;
|
|
3515
3893
|
};
|
|
3516
3894
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -3561,7 +3939,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
3561
3939
|
};
|
|
3562
3940
|
|
|
3563
3941
|
// src/react/VoiceTurnLatency.tsx
|
|
3564
|
-
import { jsxDEV as
|
|
3942
|
+
import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
|
|
3565
3943
|
var VoiceTurnLatency = ({
|
|
3566
3944
|
className,
|
|
3567
3945
|
path = "/api/turn-latency",
|
|
@@ -3569,31 +3947,31 @@ var VoiceTurnLatency = ({
|
|
|
3569
3947
|
}) => {
|
|
3570
3948
|
const latency = useVoiceTurnLatency(path, options);
|
|
3571
3949
|
const model = createVoiceTurnLatencyViewModel(latency, options);
|
|
3572
|
-
return /* @__PURE__ */
|
|
3950
|
+
return /* @__PURE__ */ jsxDEV13("section", {
|
|
3573
3951
|
className: [
|
|
3574
3952
|
"absolute-voice-turn-latency",
|
|
3575
3953
|
`absolute-voice-turn-latency--${model.status}`,
|
|
3576
3954
|
className
|
|
3577
3955
|
].filter(Boolean).join(" "),
|
|
3578
3956
|
children: [
|
|
3579
|
-
/* @__PURE__ */
|
|
3957
|
+
/* @__PURE__ */ jsxDEV13("header", {
|
|
3580
3958
|
className: "absolute-voice-turn-latency__header",
|
|
3581
3959
|
children: [
|
|
3582
|
-
/* @__PURE__ */
|
|
3960
|
+
/* @__PURE__ */ jsxDEV13("span", {
|
|
3583
3961
|
className: "absolute-voice-turn-latency__eyebrow",
|
|
3584
3962
|
children: model.title
|
|
3585
3963
|
}, undefined, false, undefined, this),
|
|
3586
|
-
/* @__PURE__ */
|
|
3964
|
+
/* @__PURE__ */ jsxDEV13("strong", {
|
|
3587
3965
|
className: "absolute-voice-turn-latency__label",
|
|
3588
3966
|
children: model.label
|
|
3589
3967
|
}, undefined, false, undefined, this)
|
|
3590
3968
|
]
|
|
3591
3969
|
}, undefined, true, undefined, this),
|
|
3592
|
-
/* @__PURE__ */
|
|
3970
|
+
/* @__PURE__ */ jsxDEV13("p", {
|
|
3593
3971
|
className: "absolute-voice-turn-latency__description",
|
|
3594
3972
|
children: model.description
|
|
3595
3973
|
}, undefined, false, undefined, this),
|
|
3596
|
-
model.showProofAction ? /* @__PURE__ */
|
|
3974
|
+
model.showProofAction ? /* @__PURE__ */ jsxDEV13("button", {
|
|
3597
3975
|
className: "absolute-voice-turn-latency__proof",
|
|
3598
3976
|
onClick: () => {
|
|
3599
3977
|
latency.runProof().catch(() => {});
|
|
@@ -3601,31 +3979,31 @@ var VoiceTurnLatency = ({
|
|
|
3601
3979
|
type: "button",
|
|
3602
3980
|
children: model.proofLabel
|
|
3603
3981
|
}, undefined, false, undefined, this) : null,
|
|
3604
|
-
model.turns.length ? /* @__PURE__ */
|
|
3982
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV13("div", {
|
|
3605
3983
|
className: "absolute-voice-turn-latency__turns",
|
|
3606
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
3984
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV13("article", {
|
|
3607
3985
|
className: [
|
|
3608
3986
|
"absolute-voice-turn-latency__turn",
|
|
3609
3987
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
3610
3988
|
].join(" "),
|
|
3611
3989
|
children: [
|
|
3612
|
-
/* @__PURE__ */
|
|
3990
|
+
/* @__PURE__ */ jsxDEV13("header", {
|
|
3613
3991
|
children: [
|
|
3614
|
-
/* @__PURE__ */
|
|
3992
|
+
/* @__PURE__ */ jsxDEV13("strong", {
|
|
3615
3993
|
children: turn.label
|
|
3616
3994
|
}, undefined, false, undefined, this),
|
|
3617
|
-
/* @__PURE__ */
|
|
3995
|
+
/* @__PURE__ */ jsxDEV13("span", {
|
|
3618
3996
|
children: turn.status
|
|
3619
3997
|
}, undefined, false, undefined, this)
|
|
3620
3998
|
]
|
|
3621
3999
|
}, undefined, true, undefined, this),
|
|
3622
|
-
/* @__PURE__ */
|
|
3623
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
4000
|
+
/* @__PURE__ */ jsxDEV13("dl", {
|
|
4001
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV13("div", {
|
|
3624
4002
|
children: [
|
|
3625
|
-
/* @__PURE__ */
|
|
4003
|
+
/* @__PURE__ */ jsxDEV13("dt", {
|
|
3626
4004
|
children: row.label
|
|
3627
4005
|
}, undefined, false, undefined, this),
|
|
3628
|
-
/* @__PURE__ */
|
|
4006
|
+
/* @__PURE__ */ jsxDEV13("dd", {
|
|
3629
4007
|
children: row.value
|
|
3630
4008
|
}, undefined, false, undefined, this)
|
|
3631
4009
|
]
|
|
@@ -3633,11 +4011,11 @@ var VoiceTurnLatency = ({
|
|
|
3633
4011
|
}, undefined, false, undefined, this)
|
|
3634
4012
|
]
|
|
3635
4013
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
3636
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
4014
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13("p", {
|
|
3637
4015
|
className: "absolute-voice-turn-latency__empty",
|
|
3638
4016
|
children: "Complete a voice turn to see latency diagnostics."
|
|
3639
4017
|
}, undefined, false, undefined, this),
|
|
3640
|
-
model.error ? /* @__PURE__ */
|
|
4018
|
+
model.error ? /* @__PURE__ */ jsxDEV13("p", {
|
|
3641
4019
|
className: "absolute-voice-turn-latency__error",
|
|
3642
4020
|
children: model.error
|
|
3643
4021
|
}, undefined, false, undefined, this) : null
|
|
@@ -3645,7 +4023,7 @@ var VoiceTurnLatency = ({
|
|
|
3645
4023
|
}, undefined, true, undefined, this);
|
|
3646
4024
|
};
|
|
3647
4025
|
// src/react/useVoiceTurnQuality.tsx
|
|
3648
|
-
import { useEffect as
|
|
4026
|
+
import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
|
|
3649
4027
|
|
|
3650
4028
|
// src/client/turnQuality.ts
|
|
3651
4029
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -3728,25 +4106,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
3728
4106
|
|
|
3729
4107
|
// src/react/useVoiceTurnQuality.tsx
|
|
3730
4108
|
var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
|
|
3731
|
-
const storeRef =
|
|
4109
|
+
const storeRef = useRef14(null);
|
|
3732
4110
|
if (!storeRef.current) {
|
|
3733
4111
|
storeRef.current = createVoiceTurnQualityStore(path, options);
|
|
3734
4112
|
}
|
|
3735
4113
|
const store = storeRef.current;
|
|
3736
|
-
|
|
4114
|
+
useEffect14(() => {
|
|
3737
4115
|
store.refresh().catch(() => {});
|
|
3738
4116
|
return () => store.close();
|
|
3739
4117
|
}, [store]);
|
|
3740
4118
|
return {
|
|
3741
|
-
...
|
|
4119
|
+
...useSyncExternalStore14(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
3742
4120
|
refresh: store.refresh
|
|
3743
4121
|
};
|
|
3744
4122
|
};
|
|
3745
4123
|
|
|
3746
4124
|
// src/client/turnQualityWidget.ts
|
|
3747
|
-
var
|
|
3748
|
-
var
|
|
3749
|
-
var
|
|
4125
|
+
var DEFAULT_TITLE13 = "Turn Quality";
|
|
4126
|
+
var DEFAULT_DESCRIPTION13 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
4127
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3750
4128
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3751
4129
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3752
4130
|
var getTurnDetail = (turn) => {
|
|
@@ -3784,37 +4162,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3784
4162
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3785
4163
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3786
4164
|
return {
|
|
3787
|
-
description: options.description ??
|
|
4165
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
3788
4166
|
error: snapshot.error,
|
|
3789
4167
|
isLoading: snapshot.isLoading,
|
|
3790
4168
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3791
4169
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3792
|
-
title: options.title ??
|
|
4170
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
3793
4171
|
turns,
|
|
3794
4172
|
updatedAt: snapshot.updatedAt
|
|
3795
4173
|
};
|
|
3796
4174
|
};
|
|
3797
4175
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3798
4176
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3799
|
-
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--${
|
|
4177
|
+
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--${escapeHtml14(turn.status)}">
|
|
3800
4178
|
<header>
|
|
3801
|
-
<strong>${
|
|
3802
|
-
<span>${
|
|
4179
|
+
<strong>${escapeHtml14(turn.label)}</strong>
|
|
4180
|
+
<span>${escapeHtml14(turn.status)}</span>
|
|
3803
4181
|
</header>
|
|
3804
|
-
<p>${
|
|
4182
|
+
<p>${escapeHtml14(turn.detail)}</p>
|
|
3805
4183
|
<dl>${turn.rows.map((row) => `<div>
|
|
3806
|
-
<dt>${
|
|
3807
|
-
<dd>${
|
|
4184
|
+
<dt>${escapeHtml14(row.label)}</dt>
|
|
4185
|
+
<dd>${escapeHtml14(row.value)}</dd>
|
|
3808
4186
|
</div>`).join("")}</dl>
|
|
3809
4187
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3810
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
4188
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml14(model.status)}">
|
|
3811
4189
|
<header class="absolute-voice-turn-quality__header">
|
|
3812
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3813
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
4190
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml14(model.title)}</span>
|
|
4191
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml14(model.label)}</strong>
|
|
3814
4192
|
</header>
|
|
3815
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
4193
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml14(model.description)}</p>
|
|
3816
4194
|
${turns}
|
|
3817
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
4195
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
3818
4196
|
</section>`;
|
|
3819
4197
|
};
|
|
3820
4198
|
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}`;
|
|
@@ -3856,7 +4234,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3856
4234
|
};
|
|
3857
4235
|
|
|
3858
4236
|
// src/react/VoiceTurnQuality.tsx
|
|
3859
|
-
import { jsxDEV as
|
|
4237
|
+
import { jsxDEV as jsxDEV14 } from "react/jsx-dev-runtime";
|
|
3860
4238
|
var VoiceTurnQuality = ({
|
|
3861
4239
|
className,
|
|
3862
4240
|
path = "/api/turn-quality",
|
|
@@ -3864,58 +4242,58 @@ var VoiceTurnQuality = ({
|
|
|
3864
4242
|
}) => {
|
|
3865
4243
|
const snapshot = useVoiceTurnQuality(path, options);
|
|
3866
4244
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3867
|
-
return /* @__PURE__ */
|
|
4245
|
+
return /* @__PURE__ */ jsxDEV14("section", {
|
|
3868
4246
|
className: [
|
|
3869
4247
|
"absolute-voice-turn-quality",
|
|
3870
4248
|
`absolute-voice-turn-quality--${model.status}`,
|
|
3871
4249
|
className
|
|
3872
4250
|
].filter(Boolean).join(" "),
|
|
3873
4251
|
children: [
|
|
3874
|
-
/* @__PURE__ */
|
|
4252
|
+
/* @__PURE__ */ jsxDEV14("header", {
|
|
3875
4253
|
className: "absolute-voice-turn-quality__header",
|
|
3876
4254
|
children: [
|
|
3877
|
-
/* @__PURE__ */
|
|
4255
|
+
/* @__PURE__ */ jsxDEV14("span", {
|
|
3878
4256
|
className: "absolute-voice-turn-quality__eyebrow",
|
|
3879
4257
|
children: model.title
|
|
3880
4258
|
}, undefined, false, undefined, this),
|
|
3881
|
-
/* @__PURE__ */
|
|
4259
|
+
/* @__PURE__ */ jsxDEV14("strong", {
|
|
3882
4260
|
className: "absolute-voice-turn-quality__label",
|
|
3883
4261
|
children: model.label
|
|
3884
4262
|
}, undefined, false, undefined, this)
|
|
3885
4263
|
]
|
|
3886
4264
|
}, undefined, true, undefined, this),
|
|
3887
|
-
/* @__PURE__ */
|
|
4265
|
+
/* @__PURE__ */ jsxDEV14("p", {
|
|
3888
4266
|
className: "absolute-voice-turn-quality__description",
|
|
3889
4267
|
children: model.description
|
|
3890
4268
|
}, undefined, false, undefined, this),
|
|
3891
|
-
model.turns.length ? /* @__PURE__ */
|
|
4269
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV14("div", {
|
|
3892
4270
|
className: "absolute-voice-turn-quality__turns",
|
|
3893
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
4271
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV14("article", {
|
|
3894
4272
|
className: [
|
|
3895
4273
|
"absolute-voice-turn-quality__turn",
|
|
3896
4274
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
3897
4275
|
].join(" "),
|
|
3898
4276
|
children: [
|
|
3899
|
-
/* @__PURE__ */
|
|
4277
|
+
/* @__PURE__ */ jsxDEV14("header", {
|
|
3900
4278
|
children: [
|
|
3901
|
-
/* @__PURE__ */
|
|
4279
|
+
/* @__PURE__ */ jsxDEV14("strong", {
|
|
3902
4280
|
children: turn.label
|
|
3903
4281
|
}, undefined, false, undefined, this),
|
|
3904
|
-
/* @__PURE__ */
|
|
4282
|
+
/* @__PURE__ */ jsxDEV14("span", {
|
|
3905
4283
|
children: turn.status
|
|
3906
4284
|
}, undefined, false, undefined, this)
|
|
3907
4285
|
]
|
|
3908
4286
|
}, undefined, true, undefined, this),
|
|
3909
|
-
/* @__PURE__ */
|
|
4287
|
+
/* @__PURE__ */ jsxDEV14("p", {
|
|
3910
4288
|
children: turn.detail
|
|
3911
4289
|
}, undefined, false, undefined, this),
|
|
3912
|
-
/* @__PURE__ */
|
|
3913
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
4290
|
+
/* @__PURE__ */ jsxDEV14("dl", {
|
|
4291
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV14("div", {
|
|
3914
4292
|
children: [
|
|
3915
|
-
/* @__PURE__ */
|
|
4293
|
+
/* @__PURE__ */ jsxDEV14("dt", {
|
|
3916
4294
|
children: row.label
|
|
3917
4295
|
}, undefined, false, undefined, this),
|
|
3918
|
-
/* @__PURE__ */
|
|
4296
|
+
/* @__PURE__ */ jsxDEV14("dd", {
|
|
3919
4297
|
children: row.value
|
|
3920
4298
|
}, undefined, false, undefined, this)
|
|
3921
4299
|
]
|
|
@@ -3923,11 +4301,11 @@ var VoiceTurnQuality = ({
|
|
|
3923
4301
|
}, undefined, false, undefined, this)
|
|
3924
4302
|
]
|
|
3925
4303
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
3926
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
4304
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV14("p", {
|
|
3927
4305
|
className: "absolute-voice-turn-quality__empty",
|
|
3928
4306
|
children: "Complete a voice turn to see STT quality diagnostics."
|
|
3929
4307
|
}, undefined, false, undefined, this),
|
|
3930
|
-
model.error ? /* @__PURE__ */
|
|
4308
|
+
model.error ? /* @__PURE__ */ jsxDEV14("p", {
|
|
3931
4309
|
className: "absolute-voice-turn-quality__error",
|
|
3932
4310
|
children: model.error
|
|
3933
4311
|
}, undefined, false, undefined, this) : null
|
|
@@ -3935,7 +4313,7 @@ var VoiceTurnQuality = ({
|
|
|
3935
4313
|
}, undefined, true, undefined, this);
|
|
3936
4314
|
};
|
|
3937
4315
|
// src/react/useVoiceLiveOps.tsx
|
|
3938
|
-
import { useEffect as
|
|
4316
|
+
import { useEffect as useEffect15, useRef as useRef15, useSyncExternalStore as useSyncExternalStore15 } from "react";
|
|
3939
4317
|
|
|
3940
4318
|
// src/client/liveOps.ts
|
|
3941
4319
|
var postVoiceLiveOpsAction = async (input, options = {}) => {
|
|
@@ -4025,19 +4403,19 @@ var createVoiceLiveOpsStore = (options = {}) => {
|
|
|
4025
4403
|
|
|
4026
4404
|
// src/react/useVoiceLiveOps.tsx
|
|
4027
4405
|
var useVoiceLiveOps = (options = {}) => {
|
|
4028
|
-
const storeRef =
|
|
4406
|
+
const storeRef = useRef15(null);
|
|
4029
4407
|
if (!storeRef.current) {
|
|
4030
4408
|
storeRef.current = createVoiceLiveOpsStore(options);
|
|
4031
4409
|
}
|
|
4032
4410
|
const store = storeRef.current;
|
|
4033
|
-
|
|
4411
|
+
useEffect15(() => () => store.close(), [store]);
|
|
4034
4412
|
return {
|
|
4035
|
-
...
|
|
4413
|
+
...useSyncExternalStore15(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
4036
4414
|
run: store.run
|
|
4037
4415
|
};
|
|
4038
4416
|
};
|
|
4039
4417
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
4040
|
-
import { useEffect as
|
|
4418
|
+
import { useEffect as useEffect16, useRef as useRef16, useSyncExternalStore as useSyncExternalStore16 } from "react";
|
|
4041
4419
|
|
|
4042
4420
|
// src/client/campaignDialerProof.ts
|
|
4043
4421
|
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
@@ -4159,23 +4537,23 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
4159
4537
|
|
|
4160
4538
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
4161
4539
|
var useVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
4162
|
-
const storeRef =
|
|
4540
|
+
const storeRef = useRef16(null);
|
|
4163
4541
|
if (!storeRef.current) {
|
|
4164
4542
|
storeRef.current = createVoiceCampaignDialerProofStore(path, options);
|
|
4165
4543
|
}
|
|
4166
4544
|
const store = storeRef.current;
|
|
4167
|
-
|
|
4545
|
+
useEffect16(() => {
|
|
4168
4546
|
store.refresh().catch(() => {});
|
|
4169
4547
|
return () => store.close();
|
|
4170
4548
|
}, [store]);
|
|
4171
4549
|
return {
|
|
4172
|
-
...
|
|
4550
|
+
...useSyncExternalStore16(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
4173
4551
|
refresh: store.refresh,
|
|
4174
4552
|
runProof: store.runProof
|
|
4175
4553
|
};
|
|
4176
4554
|
};
|
|
4177
4555
|
// src/react/useVoiceStream.tsx
|
|
4178
|
-
import { useEffect as
|
|
4556
|
+
import { useEffect as useEffect17, useRef as useRef17, useSyncExternalStore as useSyncExternalStore17 } from "react";
|
|
4179
4557
|
|
|
4180
4558
|
// src/client/actions.ts
|
|
4181
4559
|
var normalizeErrorMessage = (value) => {
|
|
@@ -4835,13 +5213,13 @@ var EMPTY_SNAPSHOT = {
|
|
|
4835
5213
|
turns: []
|
|
4836
5214
|
};
|
|
4837
5215
|
var useVoiceStream = (path, options = {}) => {
|
|
4838
|
-
const streamRef =
|
|
5216
|
+
const streamRef = useRef17(null);
|
|
4839
5217
|
if (!streamRef.current) {
|
|
4840
5218
|
streamRef.current = createVoiceStream(path, options);
|
|
4841
5219
|
}
|
|
4842
5220
|
const stream = streamRef.current;
|
|
4843
|
-
|
|
4844
|
-
const snapshot =
|
|
5221
|
+
useEffect17(() => () => stream.close(), [stream]);
|
|
5222
|
+
const snapshot = useSyncExternalStore17(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
|
|
4845
5223
|
return {
|
|
4846
5224
|
...snapshot,
|
|
4847
5225
|
callControl: (message) => stream.callControl(message),
|
|
@@ -4851,7 +5229,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
4851
5229
|
};
|
|
4852
5230
|
};
|
|
4853
5231
|
// src/react/useVoiceController.tsx
|
|
4854
|
-
import { useEffect as
|
|
5232
|
+
import { useEffect as useEffect18, useRef as useRef18, useSyncExternalStore as useSyncExternalStore18 } from "react";
|
|
4855
5233
|
|
|
4856
5234
|
// src/client/htmx.ts
|
|
4857
5235
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -5514,13 +5892,13 @@ var EMPTY_SNAPSHOT2 = {
|
|
|
5514
5892
|
turns: []
|
|
5515
5893
|
};
|
|
5516
5894
|
var useVoiceController = (path, options = {}) => {
|
|
5517
|
-
const controllerRef =
|
|
5895
|
+
const controllerRef = useRef18(null);
|
|
5518
5896
|
if (!controllerRef.current) {
|
|
5519
5897
|
controllerRef.current = createVoiceController(path, options);
|
|
5520
5898
|
}
|
|
5521
5899
|
const controller = controllerRef.current;
|
|
5522
|
-
|
|
5523
|
-
const snapshot =
|
|
5900
|
+
useEffect18(() => () => controller.close(), [controller]);
|
|
5901
|
+
const snapshot = useSyncExternalStore18(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
|
|
5524
5902
|
return {
|
|
5525
5903
|
...snapshot,
|
|
5526
5904
|
bindHTMX: controller.bindHTMX,
|
|
@@ -5534,7 +5912,7 @@ var useVoiceController = (path, options = {}) => {
|
|
|
5534
5912
|
};
|
|
5535
5913
|
};
|
|
5536
5914
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
5537
|
-
import { useEffect as
|
|
5915
|
+
import { useEffect as useEffect19, useRef as useRef19, useSyncExternalStore as useSyncExternalStore19 } from "react";
|
|
5538
5916
|
|
|
5539
5917
|
// src/client/workflowStatus.ts
|
|
5540
5918
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -5617,17 +5995,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
5617
5995
|
|
|
5618
5996
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
5619
5997
|
var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
|
|
5620
|
-
const storeRef =
|
|
5998
|
+
const storeRef = useRef19(null);
|
|
5621
5999
|
if (!storeRef.current) {
|
|
5622
6000
|
storeRef.current = createVoiceWorkflowStatusStore(path, options);
|
|
5623
6001
|
}
|
|
5624
6002
|
const store = storeRef.current;
|
|
5625
|
-
|
|
6003
|
+
useEffect19(() => {
|
|
5626
6004
|
store.refresh().catch(() => {});
|
|
5627
6005
|
return () => store.close();
|
|
5628
6006
|
}, [store]);
|
|
5629
6007
|
return {
|
|
5630
|
-
...
|
|
6008
|
+
...useSyncExternalStore19(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
5631
6009
|
refresh: store.refresh
|
|
5632
6010
|
};
|
|
5633
6011
|
};
|
|
@@ -5642,6 +6020,7 @@ export {
|
|
|
5642
6020
|
useVoiceProviderSimulationControls,
|
|
5643
6021
|
useVoiceProviderContracts,
|
|
5644
6022
|
useVoiceProviderCapabilities,
|
|
6023
|
+
useVoiceProofTrends,
|
|
5645
6024
|
useVoicePlatformCoverage,
|
|
5646
6025
|
useVoiceOpsStatus,
|
|
5647
6026
|
useVoiceOpsActionCenter,
|
|
@@ -5658,6 +6037,7 @@ export {
|
|
|
5658
6037
|
VoiceProviderSimulationControls,
|
|
5659
6038
|
VoiceProviderContracts,
|
|
5660
6039
|
VoiceProviderCapabilities,
|
|
6040
|
+
VoiceProofTrends,
|
|
5661
6041
|
VoicePlatformCoverage,
|
|
5662
6042
|
VoiceOpsStatus,
|
|
5663
6043
|
VoiceOpsActionCenter,
|