@absolutejs/voice 0.0.22-beta.333 → 0.0.22-beta.334
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/client/index.js +323 -167
- package/dist/index.d.ts +2 -2
- package/dist/index.js +445 -285
- package/dist/proofTrends.d.ts +74 -0
- package/dist/react/index.js +283 -127
- package/dist/vue/index.js +258 -102
- package/package.json +1 -1
package/dist/vue/index.js
CHANGED
|
@@ -1599,6 +1599,162 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
1599
1599
|
}
|
|
1600
1600
|
return assertion;
|
|
1601
1601
|
};
|
|
1602
|
+
var DEFAULT_RECOMMENDATION_BUDGETS = {
|
|
1603
|
+
maxLiveP95Ms: 800,
|
|
1604
|
+
maxProviderP95Ms: 1000,
|
|
1605
|
+
maxRuntimeBackpressureEvents: 0,
|
|
1606
|
+
maxRuntimeFirstAudioLatencyMs: 600,
|
|
1607
|
+
maxRuntimeInterruptionP95Ms: 300,
|
|
1608
|
+
maxRuntimeJitterMs: 30,
|
|
1609
|
+
maxRuntimeTimestampDriftMs: 800,
|
|
1610
|
+
maxTurnP95Ms: 700
|
|
1611
|
+
};
|
|
1612
|
+
var withinBudget = (value, budget) => typeof value === "number" && Number.isFinite(value) && value <= budget;
|
|
1613
|
+
var recommendationStatusRank = {
|
|
1614
|
+
pass: 0,
|
|
1615
|
+
warn: 1,
|
|
1616
|
+
fail: 2
|
|
1617
|
+
};
|
|
1618
|
+
var worstRecommendationStatus = (recommendations) => recommendations.reduce((status, recommendation) => recommendationStatusRank[recommendation.status] > recommendationStatusRank[status] ? recommendation.status : status, "pass");
|
|
1619
|
+
var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
1620
|
+
const budgets = { ...DEFAULT_RECOMMENDATION_BUDGETS, ...options };
|
|
1621
|
+
const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
|
|
1622
|
+
const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
|
|
1623
|
+
const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
|
|
1624
|
+
const runtimeChannel = readProofTrendRuntimeChannel(report);
|
|
1625
|
+
const recommendations = [];
|
|
1626
|
+
const issues = [];
|
|
1627
|
+
if (report.ok !== true) {
|
|
1628
|
+
issues.push(`Proof trend report is ${report.status}; recommendations need a fresh passing trend artifact.`);
|
|
1629
|
+
}
|
|
1630
|
+
recommendations.push({
|
|
1631
|
+
evidence: {
|
|
1632
|
+
budgetMs: budgets.maxProviderP95Ms,
|
|
1633
|
+
providerP95Ms: maxProviderP95Ms
|
|
1634
|
+
},
|
|
1635
|
+
nextMove: withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep the current provider route for latency-sensitive turns and keep collecting sustained proof." : "Route latency-sensitive turns to a faster provider profile or tighten fallback/circuit-breaker budgets before promotion.",
|
|
1636
|
+
recommendation: withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
|
|
1637
|
+
status: withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
|
|
1638
|
+
surface: "provider-path"
|
|
1639
|
+
});
|
|
1640
|
+
const runtimePass = withinBudget(runtimeChannel.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) && withinBudget(runtimeChannel.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) && withinBudget(runtimeChannel.maxJitterMs, budgets.maxRuntimeJitterMs) && withinBudget(runtimeChannel.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) && withinBudget(runtimeChannel.maxBackpressureEvents, budgets.maxRuntimeBackpressureEvents);
|
|
1641
|
+
recommendations.push({
|
|
1642
|
+
evidence: {
|
|
1643
|
+
backpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
1644
|
+
firstAudioBudgetMs: budgets.maxRuntimeFirstAudioLatencyMs,
|
|
1645
|
+
firstAudioMs: runtimeChannel.maxFirstAudioLatencyMs,
|
|
1646
|
+
interruptionBudgetMs: budgets.maxRuntimeInterruptionP95Ms,
|
|
1647
|
+
interruptionP95Ms: runtimeChannel.maxInterruptionP95Ms,
|
|
1648
|
+
jitterBudgetMs: budgets.maxRuntimeJitterMs,
|
|
1649
|
+
jitterMs: runtimeChannel.maxJitterMs,
|
|
1650
|
+
samples: runtimeChannel.samples,
|
|
1651
|
+
timestampDriftMs: runtimeChannel.maxTimestampDriftMs
|
|
1652
|
+
},
|
|
1653
|
+
nextMove: runtimePass ? "Keep the current runtime-channel settings and use this artifact as the deploy gate baseline." : "Tune capture/output format, buffering, interruption threshold, or transport backpressure before promoting this runtime path.",
|
|
1654
|
+
recommendation: runtimePass ? "Keep current runtime channel" : "Tune runtime channel before promotion",
|
|
1655
|
+
status: runtimePass ? "pass" : runtimeChannel.samples === undefined ? "fail" : "warn",
|
|
1656
|
+
surface: "runtime-channel"
|
|
1657
|
+
});
|
|
1658
|
+
recommendations.push({
|
|
1659
|
+
evidence: {
|
|
1660
|
+
budgetMs: budgets.maxLiveP95Ms,
|
|
1661
|
+
liveP95Ms: maxLiveP95Ms
|
|
1662
|
+
},
|
|
1663
|
+
nextMove: withinBudget(maxLiveP95Ms, budgets.maxLiveP95Ms) ? "Keep browser live-latency defaults and continue watching long-window drift." : "Tune browser streaming, chunking, or readiness thresholds before release.",
|
|
1664
|
+
recommendation: withinBudget(maxLiveP95Ms, budgets.maxLiveP95Ms) ? "Keep live-latency settings" : "Tune live-latency path",
|
|
1665
|
+
status: withinBudget(maxLiveP95Ms, budgets.maxLiveP95Ms) ? "pass" : maxLiveP95Ms === undefined ? "fail" : "warn",
|
|
1666
|
+
surface: "live-latency"
|
|
1667
|
+
});
|
|
1668
|
+
recommendations.push({
|
|
1669
|
+
evidence: {
|
|
1670
|
+
budgetMs: budgets.maxTurnP95Ms,
|
|
1671
|
+
turnP95Ms: maxTurnP95Ms
|
|
1672
|
+
},
|
|
1673
|
+
nextMove: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "Keep current turn pipeline defaults." : "Reduce tool/provider latency or split the turn pipeline before promotion.",
|
|
1674
|
+
recommendation: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "Keep turn pipeline" : "Tune turn pipeline",
|
|
1675
|
+
status: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "pass" : maxTurnP95Ms === undefined ? "fail" : "warn",
|
|
1676
|
+
surface: "turn-latency"
|
|
1677
|
+
});
|
|
1678
|
+
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
1679
|
+
return {
|
|
1680
|
+
generatedAt: new Date().toISOString(),
|
|
1681
|
+
issues,
|
|
1682
|
+
ok: status !== "fail",
|
|
1683
|
+
recommendations,
|
|
1684
|
+
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
1685
|
+
status,
|
|
1686
|
+
summary: {
|
|
1687
|
+
keepCurrentProviderPath: recommendations.find((item) => item.surface === "provider-path")?.status === "pass",
|
|
1688
|
+
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
1689
|
+
recommendedActions: recommendations.filter((item) => item.status !== "pass").length
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
};
|
|
1693
|
+
var escapeHtml5 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1694
|
+
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
1695
|
+
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
1696
|
+
`# ${title}`,
|
|
1697
|
+
"",
|
|
1698
|
+
`- Status: ${report.status}`,
|
|
1699
|
+
`- Source: ${report.source}`,
|
|
1700
|
+
`- Recommended actions: ${String(report.summary.recommendedActions)}`,
|
|
1701
|
+
"",
|
|
1702
|
+
"| Surface | Status | Recommendation | Next move |",
|
|
1703
|
+
"| --- | --- | --- | --- |",
|
|
1704
|
+
...report.recommendations.map((recommendation) => `| ${escapeMarkdown(recommendation.surface)} | ${recommendation.status} | ${escapeMarkdown(recommendation.recommendation)} | ${escapeMarkdown(recommendation.nextMove)} |`),
|
|
1705
|
+
"",
|
|
1706
|
+
"## Issues",
|
|
1707
|
+
"",
|
|
1708
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
1709
|
+
].join(`
|
|
1710
|
+
`);
|
|
1711
|
+
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
1712
|
+
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml5(recommendation.status)}"><p class="eyebrow">${escapeHtml5(recommendation.surface)} \xB7 ${escapeHtml5(recommendation.status)}</p><h2>${escapeHtml5(recommendation.recommendation)}</h2><p>${escapeHtml5(recommendation.nextMove)}</p><pre>${escapeHtml5(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
1713
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
|
|
1714
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
1715
|
+
};
|
|
1716
|
+
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
1717
|
+
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
1718
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/proof-trend-recommendations" : options.htmlPath;
|
|
1719
|
+
const markdownPath = options.markdownPath === undefined ? "/voice/proof-trend-recommendations.md" : options.markdownPath;
|
|
1720
|
+
const title = options.title ?? "Voice Provider Runtime Recommendations";
|
|
1721
|
+
const routes = new Elysia({
|
|
1722
|
+
name: options.name ?? "absolutejs-voice-proof-trend-recommendations"
|
|
1723
|
+
});
|
|
1724
|
+
const loadReport = async () => {
|
|
1725
|
+
const value = options.source !== undefined ? typeof options.source === "function" ? await options.source() : options.source : options.jsonPath ? await readVoiceProofTrendReportFile(options.jsonPath, {
|
|
1726
|
+
maxAgeMs: options.maxAgeMs
|
|
1727
|
+
}) : buildEmptyVoiceProofTrendReport("", options.maxAgeMs);
|
|
1728
|
+
return buildVoiceProofTrendRecommendationReport(normalizeVoiceProofTrendReport(value, {
|
|
1729
|
+
maxAgeMs: options.maxAgeMs,
|
|
1730
|
+
source: options.jsonPath
|
|
1731
|
+
}), options);
|
|
1732
|
+
};
|
|
1733
|
+
routes.get(path, async () => Response.json(await loadReport(), { headers: options.headers }));
|
|
1734
|
+
if (htmlPath !== false) {
|
|
1735
|
+
routes.get(htmlPath, async () => {
|
|
1736
|
+
const report = await loadReport();
|
|
1737
|
+
return new Response(renderVoiceProofTrendRecommendationHTML(report, title), {
|
|
1738
|
+
headers: {
|
|
1739
|
+
"content-type": "text/html; charset=utf-8",
|
|
1740
|
+
...Object.fromEntries(new Headers(options.headers))
|
|
1741
|
+
}
|
|
1742
|
+
});
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
if (markdownPath !== false) {
|
|
1746
|
+
routes.get(markdownPath, async () => {
|
|
1747
|
+
const report = await loadReport();
|
|
1748
|
+
return new Response(renderVoiceProofTrendRecommendationMarkdown(report, title), {
|
|
1749
|
+
headers: {
|
|
1750
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
1751
|
+
...Object.fromEntries(new Headers(options.headers))
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
return routes;
|
|
1757
|
+
};
|
|
1602
1758
|
var createVoiceProofTrendRoutes = (options) => {
|
|
1603
1759
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
1604
1760
|
const routes = new Elysia({
|
|
@@ -1720,7 +1876,7 @@ var DEFAULT_LINKS2 = [
|
|
|
1720
1876
|
{ href: "/voice/proof-trends", label: "Trend page" },
|
|
1721
1877
|
{ href: "/api/voice/proof-trends", label: "Trend JSON" }
|
|
1722
1878
|
];
|
|
1723
|
-
var
|
|
1879
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1724
1880
|
var formatMs = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
1725
1881
|
var statusLabel = (report) => {
|
|
1726
1882
|
if (!report) {
|
|
@@ -1770,19 +1926,19 @@ var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
|
|
|
1770
1926
|
var renderVoiceProofTrendsHTML = (snapshot, options = {}) => {
|
|
1771
1927
|
const model = createVoiceProofTrendsViewModel(snapshot, options);
|
|
1772
1928
|
const metrics = model.metrics.length ? `<div class="absolute-voice-proof-trends__metrics">${model.metrics.map((metric) => `<article>
|
|
1773
|
-
<span>${
|
|
1774
|
-
<strong>${
|
|
1775
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ?
|
|
1776
|
-
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${
|
|
1777
|
-
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${
|
|
1929
|
+
<span>${escapeHtml6(metric.label)}</span>
|
|
1930
|
+
<strong>${escapeHtml6(metric.value)}</strong>
|
|
1931
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml6(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
|
|
1932
|
+
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml6(link.href)}">${escapeHtml6(link.label)}</a>`).join("")}</p>` : "";
|
|
1933
|
+
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml6(model.status)}">
|
|
1778
1934
|
<header class="absolute-voice-proof-trends__header">
|
|
1779
|
-
<span class="absolute-voice-proof-trends__eyebrow">${
|
|
1780
|
-
<strong class="absolute-voice-proof-trends__label">${
|
|
1935
|
+
<span class="absolute-voice-proof-trends__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1936
|
+
<strong class="absolute-voice-proof-trends__label">${escapeHtml6(model.label)}</strong>
|
|
1781
1937
|
</header>
|
|
1782
|
-
<p class="absolute-voice-proof-trends__description">${
|
|
1938
|
+
<p class="absolute-voice-proof-trends__description">${escapeHtml6(model.description)}</p>
|
|
1783
1939
|
${metrics}
|
|
1784
1940
|
${links}
|
|
1785
|
-
${model.error ? `<p class="absolute-voice-proof-trends__error">${
|
|
1941
|
+
${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1786
1942
|
</section>`;
|
|
1787
1943
|
};
|
|
1788
1944
|
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}`;
|
|
@@ -1990,7 +2146,7 @@ var DEFAULT_LINKS3 = [
|
|
|
1990
2146
|
{ href: "/production-readiness", label: "Readiness page" },
|
|
1991
2147
|
{ href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
|
|
1992
2148
|
];
|
|
1993
|
-
var
|
|
2149
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1994
2150
|
var formatExplanationValue = (value, unit) => {
|
|
1995
2151
|
if (value === undefined || value === null) {
|
|
1996
2152
|
return "n/a";
|
|
@@ -2031,23 +2187,23 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
|
|
|
2031
2187
|
};
|
|
2032
2188
|
var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
|
|
2033
2189
|
const model = createVoiceReadinessFailuresViewModel(snapshot, options);
|
|
2034
|
-
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${
|
|
2035
|
-
<span>${
|
|
2036
|
-
<strong>${
|
|
2037
|
-
<p>Observed ${
|
|
2038
|
-
<p>${
|
|
2039
|
-
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${
|
|
2040
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ?
|
|
2041
|
-
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${
|
|
2042
|
-
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${
|
|
2190
|
+
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${escapeHtml7(failure.status)}">
|
|
2191
|
+
<span>${escapeHtml7(failure.status.toUpperCase())}</span>
|
|
2192
|
+
<strong>${escapeHtml7(failure.label)}</strong>
|
|
2193
|
+
<p>Observed ${escapeHtml7(failure.observed)} against ${escapeHtml7(failure.thresholdLabel)} ${escapeHtml7(failure.threshold)}.</p>
|
|
2194
|
+
<p>${escapeHtml7(failure.remediation)}</p>
|
|
2195
|
+
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml7(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml7(failure.sourceHref)}">Threshold source</a>` : ""}</p>
|
|
2196
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml7(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
|
|
2197
|
+
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml7(link.href)}">${escapeHtml7(link.label)}</a>`).join("")}</p>` : "";
|
|
2198
|
+
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml7(model.status)}">
|
|
2043
2199
|
<header class="absolute-voice-readiness-failures__header">
|
|
2044
|
-
<span class="absolute-voice-readiness-failures__eyebrow">${
|
|
2045
|
-
<strong class="absolute-voice-readiness-failures__label">${
|
|
2200
|
+
<span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2201
|
+
<strong class="absolute-voice-readiness-failures__label">${escapeHtml7(model.label)}</strong>
|
|
2046
2202
|
</header>
|
|
2047
|
-
<p class="absolute-voice-readiness-failures__description">${
|
|
2203
|
+
<p class="absolute-voice-readiness-failures__description">${escapeHtml7(model.description)}</p>
|
|
2048
2204
|
${failures}
|
|
2049
2205
|
${links}
|
|
2050
|
-
${model.error ? `<p class="absolute-voice-readiness-failures__error">${
|
|
2206
|
+
${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
2051
2207
|
</section>`;
|
|
2052
2208
|
};
|
|
2053
2209
|
var getVoiceReadinessFailuresCSS = () => `.absolute-voice-readiness-failures{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-readiness-failures--ready{border-color:#86efac;background:#f0fdf4}.absolute-voice-readiness-failures--error{border-color:#fda4af;background:#fff1f2}.absolute-voice-readiness-failures__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-readiness-failures__eyebrow{color:#9a3412;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-readiness-failures__label{font-size:24px;line-height:1}.absolute-voice-readiness-failures__description,.absolute-voice-readiness-failures__empty{color:#57534e}.absolute-voice-readiness-failures__items{display:grid;gap:10px;margin-top:14px}.absolute-voice-readiness-failures__item{background:white;border:1px solid #fed7aa;border-radius:16px;padding:12px}.absolute-voice-readiness-failures__item--fail{border-color:#fb7185}.absolute-voice-readiness-failures__item span{color:#9a3412;display:block;font-size:12px;font-weight:900;text-transform:uppercase}.absolute-voice-readiness-failures__item strong{display:block;font-size:18px;margin-top:4px}.absolute-voice-readiness-failures__item p{margin:.45rem 0 0}.absolute-voice-readiness-failures__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-readiness-failures__links a{border:1px solid #fdba74;border-radius:999px;color:#9a3412;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-readiness-failures__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2264,7 +2420,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
2264
2420
|
};
|
|
2265
2421
|
|
|
2266
2422
|
// src/client/providerSimulationControlsWidget.ts
|
|
2267
|
-
var
|
|
2423
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2268
2424
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
2269
2425
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
2270
2426
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -2284,18 +2440,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
2284
2440
|
};
|
|
2285
2441
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
2286
2442
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
2287
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
2288
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
2443
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml8(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml8(provider.provider)} ${escapeHtml8(formatKind(options.kind))} failure</button>`).join("");
|
|
2444
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml8(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml8(provider.provider)} recovered</button>`).join("");
|
|
2289
2445
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
2290
2446
|
<header class="absolute-voice-provider-simulation__header">
|
|
2291
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
2292
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
2447
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2448
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml8(model.label)}</strong>
|
|
2293
2449
|
</header>
|
|
2294
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
2295
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
2450
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml8(model.description)}</p>
|
|
2451
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml8(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
2296
2452
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
2297
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
2298
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
2453
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml8(snapshot.error)}</p>` : ""}
|
|
2454
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml8(model.resultText)}</pre>` : ""}
|
|
2299
2455
|
</section>`;
|
|
2300
2456
|
};
|
|
2301
2457
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -2556,7 +2712,7 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
2556
2712
|
// src/client/providerCapabilitiesWidget.ts
|
|
2557
2713
|
var DEFAULT_TITLE7 = "Provider Capabilities";
|
|
2558
2714
|
var DEFAULT_DESCRIPTION7 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
2559
|
-
var
|
|
2715
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2560
2716
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2561
2717
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
2562
2718
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -2611,25 +2767,25 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
2611
2767
|
};
|
|
2612
2768
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
2613
2769
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
2614
|
-
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--${
|
|
2770
|
+
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--${escapeHtml9(capability.status)}">
|
|
2615
2771
|
<header>
|
|
2616
|
-
<strong>${
|
|
2617
|
-
<span>${
|
|
2772
|
+
<strong>${escapeHtml9(capability.label)}</strong>
|
|
2773
|
+
<span>${escapeHtml9(formatStatus2(capability.status))}</span>
|
|
2618
2774
|
</header>
|
|
2619
|
-
<p>${
|
|
2775
|
+
<p>${escapeHtml9(capability.detail)}</p>
|
|
2620
2776
|
<dl>${capability.rows.map((row) => `<div>
|
|
2621
|
-
<dt>${
|
|
2622
|
-
<dd>${
|
|
2777
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2778
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2623
2779
|
</div>`).join("")}</dl>
|
|
2624
2780
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
2625
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
2781
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml9(model.status)}">
|
|
2626
2782
|
<header class="absolute-voice-provider-capabilities__header">
|
|
2627
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
2628
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
2783
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2784
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml9(model.label)}</strong>
|
|
2629
2785
|
</header>
|
|
2630
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
2786
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml9(model.description)}</p>
|
|
2631
2787
|
${capabilities}
|
|
2632
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
2788
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2633
2789
|
</section>`;
|
|
2634
2790
|
};
|
|
2635
2791
|
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}`;
|
|
@@ -2886,7 +3042,7 @@ function useVoiceProviderContracts(path = "/api/provider-contracts", options = {
|
|
|
2886
3042
|
// src/client/providerContractsWidget.ts
|
|
2887
3043
|
var DEFAULT_TITLE8 = "Provider Contracts";
|
|
2888
3044
|
var DEFAULT_DESCRIPTION8 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
2889
|
-
var
|
|
3045
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2890
3046
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2891
3047
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2892
3048
|
var contractDetail = (row) => {
|
|
@@ -2930,26 +3086,26 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
2930
3086
|
};
|
|
2931
3087
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
2932
3088
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
2933
|
-
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--${
|
|
3089
|
+
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--${escapeHtml10(row.status)}">
|
|
2934
3090
|
<header>
|
|
2935
|
-
<strong>${
|
|
2936
|
-
<span>${
|
|
3091
|
+
<strong>${escapeHtml10(row.label)}</strong>
|
|
3092
|
+
<span>${escapeHtml10(formatStatus3(row.status))}</span>
|
|
2937
3093
|
</header>
|
|
2938
|
-
<p>${
|
|
2939
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
3094
|
+
<p>${escapeHtml10(row.detail)}</p>
|
|
3095
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml10(remediation.href)}">${escapeHtml10(remediation.label)}</a>` : `<strong>${escapeHtml10(remediation.label)}</strong>`}<span>${escapeHtml10(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
2940
3096
|
<dl>${row.rows.map((item) => `<div>
|
|
2941
|
-
<dt>${
|
|
2942
|
-
<dd>${
|
|
3097
|
+
<dt>${escapeHtml10(item.label)}</dt>
|
|
3098
|
+
<dd>${escapeHtml10(item.value)}</dd>
|
|
2943
3099
|
</div>`).join("")}</dl>
|
|
2944
3100
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
2945
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
3101
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml10(model.status)}">
|
|
2946
3102
|
<header class="absolute-voice-provider-contracts__header">
|
|
2947
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
2948
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
3103
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml10(model.title)}</span>
|
|
3104
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml10(model.label)}</strong>
|
|
2949
3105
|
</header>
|
|
2950
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
3106
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml10(model.description)}</p>
|
|
2951
3107
|
${rows}
|
|
2952
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
3108
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2953
3109
|
</section>`;
|
|
2954
3110
|
};
|
|
2955
3111
|
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}`;
|
|
@@ -3146,7 +3302,7 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
3146
3302
|
// src/client/providerStatusWidget.ts
|
|
3147
3303
|
var DEFAULT_TITLE9 = "Voice Providers";
|
|
3148
3304
|
var DEFAULT_DESCRIPTION9 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
3149
|
-
var
|
|
3305
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3150
3306
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3151
3307
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3152
3308
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3202,25 +3358,25 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3202
3358
|
};
|
|
3203
3359
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3204
3360
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
3205
|
-
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--${
|
|
3361
|
+
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--${escapeHtml11(provider.status)}">
|
|
3206
3362
|
<header>
|
|
3207
|
-
<strong>${
|
|
3208
|
-
<span>${
|
|
3363
|
+
<strong>${escapeHtml11(provider.label)}</strong>
|
|
3364
|
+
<span>${escapeHtml11(formatStatus4(provider.status))}</span>
|
|
3209
3365
|
</header>
|
|
3210
|
-
<p>${
|
|
3366
|
+
<p>${escapeHtml11(provider.detail)}</p>
|
|
3211
3367
|
<dl>${provider.rows.map((row) => `<div>
|
|
3212
|
-
<dt>${
|
|
3213
|
-
<dd>${
|
|
3368
|
+
<dt>${escapeHtml11(row.label)}</dt>
|
|
3369
|
+
<dd>${escapeHtml11(row.value)}</dd>
|
|
3214
3370
|
</div>`).join("")}</dl>
|
|
3215
3371
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
3216
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
3372
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml11(model.status)}">
|
|
3217
3373
|
<header class="absolute-voice-provider-status__header">
|
|
3218
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3219
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
3374
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml11(model.title)}</span>
|
|
3375
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml11(model.label)}</strong>
|
|
3220
3376
|
</header>
|
|
3221
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3377
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml11(model.description)}</p>
|
|
3222
3378
|
${providers}
|
|
3223
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3379
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
3224
3380
|
</section>`;
|
|
3225
3381
|
};
|
|
3226
3382
|
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}`;
|
|
@@ -3449,7 +3605,7 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
3449
3605
|
// src/client/routingStatusWidget.ts
|
|
3450
3606
|
var DEFAULT_TITLE10 = "Voice Routing";
|
|
3451
3607
|
var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-hosted trace store.";
|
|
3452
|
-
var
|
|
3608
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3453
3609
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
3454
3610
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
3455
3611
|
const decision = snapshot.decision;
|
|
@@ -3486,17 +3642,17 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
3486
3642
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
3487
3643
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
3488
3644
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
3489
|
-
<span>${
|
|
3490
|
-
<strong>${
|
|
3645
|
+
<span>${escapeHtml12(row.label)}</span>
|
|
3646
|
+
<strong>${escapeHtml12(row.value)}</strong>
|
|
3491
3647
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
3492
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
3648
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml12(model.status)}">
|
|
3493
3649
|
<header class="absolute-voice-routing-status__header">
|
|
3494
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
3495
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
3650
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml12(model.title)}</span>
|
|
3651
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml12(model.label)}</strong>
|
|
3496
3652
|
</header>
|
|
3497
|
-
<p class="absolute-voice-routing-status__description">${
|
|
3653
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml12(model.description)}</p>
|
|
3498
3654
|
${rows}
|
|
3499
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
3655
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
3500
3656
|
</section>`;
|
|
3501
3657
|
};
|
|
3502
3658
|
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}`;
|
|
@@ -3927,7 +4083,7 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
3927
4083
|
var DEFAULT_TITLE11 = "Turn Latency";
|
|
3928
4084
|
var DEFAULT_DESCRIPTION11 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3929
4085
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3930
|
-
var
|
|
4086
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3931
4087
|
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3932
4088
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3933
4089
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3955,25 +4111,25 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3955
4111
|
};
|
|
3956
4112
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3957
4113
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
3958
|
-
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--${
|
|
4114
|
+
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)}">
|
|
3959
4115
|
<header>
|
|
3960
|
-
<strong>${
|
|
3961
|
-
<span>${
|
|
4116
|
+
<strong>${escapeHtml13(turn.label)}</strong>
|
|
4117
|
+
<span>${escapeHtml13(turn.status)}</span>
|
|
3962
4118
|
</header>
|
|
3963
4119
|
<dl>${turn.rows.map((row) => `<div>
|
|
3964
|
-
<dt>${
|
|
3965
|
-
<dd>${
|
|
4120
|
+
<dt>${escapeHtml13(row.label)}</dt>
|
|
4121
|
+
<dd>${escapeHtml13(row.value)}</dd>
|
|
3966
4122
|
</div>`).join("")}</dl>
|
|
3967
4123
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3968
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
4124
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml13(model.status)}">
|
|
3969
4125
|
<header class="absolute-voice-turn-latency__header">
|
|
3970
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3971
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
4126
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml13(model.title)}</span>
|
|
4127
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml13(model.label)}</strong>
|
|
3972
4128
|
</header>
|
|
3973
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3974
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
4129
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml13(model.description)}</p>
|
|
4130
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml13(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
3975
4131
|
${turns}
|
|
3976
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
4132
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
3977
4133
|
</section>`;
|
|
3978
4134
|
};
|
|
3979
4135
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -4206,7 +4362,7 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
4206
4362
|
// src/client/turnQualityWidget.ts
|
|
4207
4363
|
var DEFAULT_TITLE12 = "Turn Quality";
|
|
4208
4364
|
var DEFAULT_DESCRIPTION12 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
4209
|
-
var
|
|
4365
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4210
4366
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
4211
4367
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
4212
4368
|
var getTurnDetail = (turn) => {
|
|
@@ -4256,25 +4412,25 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
4256
4412
|
};
|
|
4257
4413
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
4258
4414
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
4259
|
-
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--${
|
|
4415
|
+
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)}">
|
|
4260
4416
|
<header>
|
|
4261
|
-
<strong>${
|
|
4262
|
-
<span>${
|
|
4417
|
+
<strong>${escapeHtml14(turn.label)}</strong>
|
|
4418
|
+
<span>${escapeHtml14(turn.status)}</span>
|
|
4263
4419
|
</header>
|
|
4264
|
-
<p>${
|
|
4420
|
+
<p>${escapeHtml14(turn.detail)}</p>
|
|
4265
4421
|
<dl>${turn.rows.map((row) => `<div>
|
|
4266
|
-
<dt>${
|
|
4267
|
-
<dd>${
|
|
4422
|
+
<dt>${escapeHtml14(row.label)}</dt>
|
|
4423
|
+
<dd>${escapeHtml14(row.value)}</dd>
|
|
4268
4424
|
</div>`).join("")}</dl>
|
|
4269
4425
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
4270
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
4426
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml14(model.status)}">
|
|
4271
4427
|
<header class="absolute-voice-turn-quality__header">
|
|
4272
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
4273
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
4428
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml14(model.title)}</span>
|
|
4429
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml14(model.label)}</strong>
|
|
4274
4430
|
</header>
|
|
4275
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
4431
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml14(model.description)}</p>
|
|
4276
4432
|
${turns}
|
|
4277
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
4433
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
4278
4434
|
</section>`;
|
|
4279
4435
|
};
|
|
4280
4436
|
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}`;
|