@absolutejs/voice 0.0.22-beta.332 → 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 +359 -167
- package/dist/index.d.ts +2 -2
- package/dist/index.js +482 -285
- package/dist/proofTrends.d.ts +92 -0
- package/dist/react/index.js +319 -127
- package/dist/vue/index.js +294 -102
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14540,6 +14540,22 @@ var maxNumber = (values) => {
|
|
|
14540
14540
|
var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
|
|
14541
14541
|
var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms;
|
|
14542
14542
|
var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
|
|
14543
|
+
var readRuntimeChannelMetric = (report, key) => {
|
|
14544
|
+
const summaryValue = report.summary.runtimeChannel?.[key];
|
|
14545
|
+
return typeof summaryValue === "number" ? summaryValue : maxNumber(report.cycles.map((cycle) => {
|
|
14546
|
+
const value = cycle.runtimeChannel?.[key];
|
|
14547
|
+
return typeof value === "number" ? value : undefined;
|
|
14548
|
+
}));
|
|
14549
|
+
};
|
|
14550
|
+
var readProofTrendRuntimeChannel = (report) => ({
|
|
14551
|
+
maxBackpressureEvents: readRuntimeChannelMetric(report, "maxBackpressureEvents"),
|
|
14552
|
+
maxFirstAudioLatencyMs: readRuntimeChannelMetric(report, "maxFirstAudioLatencyMs"),
|
|
14553
|
+
maxInterruptionP95Ms: readRuntimeChannelMetric(report, "maxInterruptionP95Ms"),
|
|
14554
|
+
maxJitterMs: readRuntimeChannelMetric(report, "maxJitterMs"),
|
|
14555
|
+
maxTimestampDriftMs: readRuntimeChannelMetric(report, "maxTimestampDriftMs"),
|
|
14556
|
+
samples: report.summary.runtimeChannel?.samples ?? maxNumber(report.cycles.map((cycle) => cycle.runtimeChannel?.samples)),
|
|
14557
|
+
status: report.summary.runtimeChannel?.status
|
|
14558
|
+
});
|
|
14543
14559
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
14544
14560
|
const issues = [];
|
|
14545
14561
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -14549,6 +14565,7 @@ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
14549
14565
|
const failedCycles = report.cycles.filter((cycle) => cycle.ok !== true).length;
|
|
14550
14566
|
const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
|
|
14551
14567
|
const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
|
|
14568
|
+
const runtimeChannel = readProofTrendRuntimeChannel(report);
|
|
14552
14569
|
const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
|
|
14553
14570
|
if (report.status !== requiredStatus) {
|
|
14554
14571
|
issues.push(`Expected proof trends status ${requiredStatus}, found ${report.status}.`);
|
|
@@ -14574,6 +14591,21 @@ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
14574
14591
|
if (input.maxTurnP95Ms !== undefined && (maxTurnP95Ms === undefined || maxTurnP95Ms > input.maxTurnP95Ms)) {
|
|
14575
14592
|
issues.push(maxTurnP95Ms === undefined ? "Missing proof trends turn latency p95." : `Expected proof trends turn latency p95 at most ${String(input.maxTurnP95Ms)}ms, found ${String(maxTurnP95Ms)}ms.`);
|
|
14576
14593
|
}
|
|
14594
|
+
if (input.maxRuntimeFirstAudioLatencyMs !== undefined && (runtimeChannel.maxFirstAudioLatencyMs === undefined || runtimeChannel.maxFirstAudioLatencyMs > input.maxRuntimeFirstAudioLatencyMs)) {
|
|
14595
|
+
issues.push(runtimeChannel.maxFirstAudioLatencyMs === undefined ? "Missing proof trends runtime-channel first audio latency." : `Expected proof trends runtime-channel first audio latency at most ${String(input.maxRuntimeFirstAudioLatencyMs)}ms, found ${String(runtimeChannel.maxFirstAudioLatencyMs)}ms.`);
|
|
14596
|
+
}
|
|
14597
|
+
if (input.maxRuntimeInterruptionP95Ms !== undefined && (runtimeChannel.maxInterruptionP95Ms === undefined || runtimeChannel.maxInterruptionP95Ms > input.maxRuntimeInterruptionP95Ms)) {
|
|
14598
|
+
issues.push(runtimeChannel.maxInterruptionP95Ms === undefined ? "Missing proof trends runtime-channel interruption p95." : `Expected proof trends runtime-channel interruption p95 at most ${String(input.maxRuntimeInterruptionP95Ms)}ms, found ${String(runtimeChannel.maxInterruptionP95Ms)}ms.`);
|
|
14599
|
+
}
|
|
14600
|
+
if (input.maxRuntimeJitterMs !== undefined && (runtimeChannel.maxJitterMs === undefined || runtimeChannel.maxJitterMs > input.maxRuntimeJitterMs)) {
|
|
14601
|
+
issues.push(runtimeChannel.maxJitterMs === undefined ? "Missing proof trends runtime-channel jitter." : `Expected proof trends runtime-channel jitter at most ${String(input.maxRuntimeJitterMs)}ms, found ${String(runtimeChannel.maxJitterMs)}ms.`);
|
|
14602
|
+
}
|
|
14603
|
+
if (input.maxRuntimeTimestampDriftMs !== undefined && (runtimeChannel.maxTimestampDriftMs === undefined || runtimeChannel.maxTimestampDriftMs > input.maxRuntimeTimestampDriftMs)) {
|
|
14604
|
+
issues.push(runtimeChannel.maxTimestampDriftMs === undefined ? "Missing proof trends runtime-channel timestamp drift." : `Expected proof trends runtime-channel timestamp drift at most ${String(input.maxRuntimeTimestampDriftMs)}ms, found ${String(runtimeChannel.maxTimestampDriftMs)}ms.`);
|
|
14605
|
+
}
|
|
14606
|
+
if (input.maxRuntimeBackpressureEvents !== undefined && (runtimeChannel.maxBackpressureEvents === undefined || runtimeChannel.maxBackpressureEvents > input.maxRuntimeBackpressureEvents)) {
|
|
14607
|
+
issues.push(runtimeChannel.maxBackpressureEvents === undefined ? "Missing proof trends runtime-channel backpressure events." : `Expected proof trends runtime-channel backpressure events at most ${String(input.maxRuntimeBackpressureEvents)}, found ${String(runtimeChannel.maxBackpressureEvents)}.`);
|
|
14608
|
+
}
|
|
14577
14609
|
if (input.minLiveLatencySamples !== undefined) {
|
|
14578
14610
|
const lowSamples = report.cycles.filter((cycle) => (cycle.liveLatency?.samples ?? 0) < input.minLiveLatencySamples).length;
|
|
14579
14611
|
if (lowSamples > 0) {
|
|
@@ -14592,6 +14624,9 @@ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
14592
14624
|
issues.push(`Expected every proof trend cycle to have at least ${String(input.minTurnLatencySamples)} turn latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
|
|
14593
14625
|
}
|
|
14594
14626
|
}
|
|
14627
|
+
if (input.minRuntimeChannelSamples !== undefined && (runtimeChannel.samples === undefined || runtimeChannel.samples < input.minRuntimeChannelSamples)) {
|
|
14628
|
+
issues.push(runtimeChannel.samples === undefined ? "Missing proof trends runtime-channel samples." : `Expected proof trends runtime-channel samples at least ${String(input.minRuntimeChannelSamples)}, found ${String(runtimeChannel.samples)}.`);
|
|
14629
|
+
}
|
|
14595
14630
|
return {
|
|
14596
14631
|
ageMs: report.ageMs,
|
|
14597
14632
|
cycles,
|
|
@@ -14599,6 +14634,7 @@ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
14599
14634
|
issues,
|
|
14600
14635
|
maxLiveP95Ms,
|
|
14601
14636
|
maxProviderP95Ms,
|
|
14637
|
+
runtimeChannel,
|
|
14602
14638
|
maxTurnP95Ms,
|
|
14603
14639
|
ok: issues.length === 0,
|
|
14604
14640
|
status: report.status
|
|
@@ -14611,6 +14647,162 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
14611
14647
|
}
|
|
14612
14648
|
return assertion;
|
|
14613
14649
|
};
|
|
14650
|
+
var DEFAULT_RECOMMENDATION_BUDGETS = {
|
|
14651
|
+
maxLiveP95Ms: 800,
|
|
14652
|
+
maxProviderP95Ms: 1000,
|
|
14653
|
+
maxRuntimeBackpressureEvents: 0,
|
|
14654
|
+
maxRuntimeFirstAudioLatencyMs: 600,
|
|
14655
|
+
maxRuntimeInterruptionP95Ms: 300,
|
|
14656
|
+
maxRuntimeJitterMs: 30,
|
|
14657
|
+
maxRuntimeTimestampDriftMs: 800,
|
|
14658
|
+
maxTurnP95Ms: 700
|
|
14659
|
+
};
|
|
14660
|
+
var withinBudget = (value, budget) => typeof value === "number" && Number.isFinite(value) && value <= budget;
|
|
14661
|
+
var recommendationStatusRank = {
|
|
14662
|
+
pass: 0,
|
|
14663
|
+
warn: 1,
|
|
14664
|
+
fail: 2
|
|
14665
|
+
};
|
|
14666
|
+
var worstRecommendationStatus = (recommendations) => recommendations.reduce((status, recommendation) => recommendationStatusRank[recommendation.status] > recommendationStatusRank[status] ? recommendation.status : status, "pass");
|
|
14667
|
+
var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
14668
|
+
const budgets = { ...DEFAULT_RECOMMENDATION_BUDGETS, ...options };
|
|
14669
|
+
const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
|
|
14670
|
+
const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
|
|
14671
|
+
const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
|
|
14672
|
+
const runtimeChannel = readProofTrendRuntimeChannel(report);
|
|
14673
|
+
const recommendations = [];
|
|
14674
|
+
const issues = [];
|
|
14675
|
+
if (report.ok !== true) {
|
|
14676
|
+
issues.push(`Proof trend report is ${report.status}; recommendations need a fresh passing trend artifact.`);
|
|
14677
|
+
}
|
|
14678
|
+
recommendations.push({
|
|
14679
|
+
evidence: {
|
|
14680
|
+
budgetMs: budgets.maxProviderP95Ms,
|
|
14681
|
+
providerP95Ms: maxProviderP95Ms
|
|
14682
|
+
},
|
|
14683
|
+
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.",
|
|
14684
|
+
recommendation: withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
|
|
14685
|
+
status: withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
|
|
14686
|
+
surface: "provider-path"
|
|
14687
|
+
});
|
|
14688
|
+
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);
|
|
14689
|
+
recommendations.push({
|
|
14690
|
+
evidence: {
|
|
14691
|
+
backpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
14692
|
+
firstAudioBudgetMs: budgets.maxRuntimeFirstAudioLatencyMs,
|
|
14693
|
+
firstAudioMs: runtimeChannel.maxFirstAudioLatencyMs,
|
|
14694
|
+
interruptionBudgetMs: budgets.maxRuntimeInterruptionP95Ms,
|
|
14695
|
+
interruptionP95Ms: runtimeChannel.maxInterruptionP95Ms,
|
|
14696
|
+
jitterBudgetMs: budgets.maxRuntimeJitterMs,
|
|
14697
|
+
jitterMs: runtimeChannel.maxJitterMs,
|
|
14698
|
+
samples: runtimeChannel.samples,
|
|
14699
|
+
timestampDriftMs: runtimeChannel.maxTimestampDriftMs
|
|
14700
|
+
},
|
|
14701
|
+
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.",
|
|
14702
|
+
recommendation: runtimePass ? "Keep current runtime channel" : "Tune runtime channel before promotion",
|
|
14703
|
+
status: runtimePass ? "pass" : runtimeChannel.samples === undefined ? "fail" : "warn",
|
|
14704
|
+
surface: "runtime-channel"
|
|
14705
|
+
});
|
|
14706
|
+
recommendations.push({
|
|
14707
|
+
evidence: {
|
|
14708
|
+
budgetMs: budgets.maxLiveP95Ms,
|
|
14709
|
+
liveP95Ms: maxLiveP95Ms
|
|
14710
|
+
},
|
|
14711
|
+
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.",
|
|
14712
|
+
recommendation: withinBudget(maxLiveP95Ms, budgets.maxLiveP95Ms) ? "Keep live-latency settings" : "Tune live-latency path",
|
|
14713
|
+
status: withinBudget(maxLiveP95Ms, budgets.maxLiveP95Ms) ? "pass" : maxLiveP95Ms === undefined ? "fail" : "warn",
|
|
14714
|
+
surface: "live-latency"
|
|
14715
|
+
});
|
|
14716
|
+
recommendations.push({
|
|
14717
|
+
evidence: {
|
|
14718
|
+
budgetMs: budgets.maxTurnP95Ms,
|
|
14719
|
+
turnP95Ms: maxTurnP95Ms
|
|
14720
|
+
},
|
|
14721
|
+
nextMove: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "Keep current turn pipeline defaults." : "Reduce tool/provider latency or split the turn pipeline before promotion.",
|
|
14722
|
+
recommendation: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "Keep turn pipeline" : "Tune turn pipeline",
|
|
14723
|
+
status: withinBudget(maxTurnP95Ms, budgets.maxTurnP95Ms) ? "pass" : maxTurnP95Ms === undefined ? "fail" : "warn",
|
|
14724
|
+
surface: "turn-latency"
|
|
14725
|
+
});
|
|
14726
|
+
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
14727
|
+
return {
|
|
14728
|
+
generatedAt: new Date().toISOString(),
|
|
14729
|
+
issues,
|
|
14730
|
+
ok: status !== "fail",
|
|
14731
|
+
recommendations,
|
|
14732
|
+
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
14733
|
+
status,
|
|
14734
|
+
summary: {
|
|
14735
|
+
keepCurrentProviderPath: recommendations.find((item) => item.surface === "provider-path")?.status === "pass",
|
|
14736
|
+
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
14737
|
+
recommendedActions: recommendations.filter((item) => item.status !== "pass").length
|
|
14738
|
+
}
|
|
14739
|
+
};
|
|
14740
|
+
};
|
|
14741
|
+
var escapeHtml22 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14742
|
+
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
14743
|
+
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
14744
|
+
`# ${title}`,
|
|
14745
|
+
"",
|
|
14746
|
+
`- Status: ${report.status}`,
|
|
14747
|
+
`- Source: ${report.source}`,
|
|
14748
|
+
`- Recommended actions: ${String(report.summary.recommendedActions)}`,
|
|
14749
|
+
"",
|
|
14750
|
+
"| Surface | Status | Recommendation | Next move |",
|
|
14751
|
+
"| --- | --- | --- | --- |",
|
|
14752
|
+
...report.recommendations.map((recommendation) => `| ${escapeMarkdown2(recommendation.surface)} | ${recommendation.status} | ${escapeMarkdown2(recommendation.recommendation)} | ${escapeMarkdown2(recommendation.nextMove)} |`),
|
|
14753
|
+
"",
|
|
14754
|
+
"## Issues",
|
|
14755
|
+
"",
|
|
14756
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
14757
|
+
].join(`
|
|
14758
|
+
`);
|
|
14759
|
+
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
14760
|
+
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml22(recommendation.status)}"><p class="eyebrow">${escapeHtml22(recommendation.surface)} \xB7 ${escapeHtml22(recommendation.status)}</p><h2>${escapeHtml22(recommendation.recommendation)}</h2><p>${escapeHtml22(recommendation.nextMove)}</p><pre>${escapeHtml22(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
14761
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
|
|
14762
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml22(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>${escapeHtml22(title)}</h1><p>Generated ${escapeHtml22(report.generatedAt)} from ${escapeHtml22(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml22(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>`;
|
|
14763
|
+
};
|
|
14764
|
+
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
14765
|
+
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
14766
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/proof-trend-recommendations" : options.htmlPath;
|
|
14767
|
+
const markdownPath = options.markdownPath === undefined ? "/voice/proof-trend-recommendations.md" : options.markdownPath;
|
|
14768
|
+
const title = options.title ?? "Voice Provider Runtime Recommendations";
|
|
14769
|
+
const routes = new Elysia20({
|
|
14770
|
+
name: options.name ?? "absolutejs-voice-proof-trend-recommendations"
|
|
14771
|
+
});
|
|
14772
|
+
const loadReport = async () => {
|
|
14773
|
+
const value = options.source !== undefined ? typeof options.source === "function" ? await options.source() : options.source : options.jsonPath ? await readVoiceProofTrendReportFile(options.jsonPath, {
|
|
14774
|
+
maxAgeMs: options.maxAgeMs
|
|
14775
|
+
}) : buildEmptyVoiceProofTrendReport("", options.maxAgeMs);
|
|
14776
|
+
return buildVoiceProofTrendRecommendationReport(normalizeVoiceProofTrendReport(value, {
|
|
14777
|
+
maxAgeMs: options.maxAgeMs,
|
|
14778
|
+
source: options.jsonPath
|
|
14779
|
+
}), options);
|
|
14780
|
+
};
|
|
14781
|
+
routes.get(path, async () => Response.json(await loadReport(), { headers: options.headers }));
|
|
14782
|
+
if (htmlPath !== false) {
|
|
14783
|
+
routes.get(htmlPath, async () => {
|
|
14784
|
+
const report = await loadReport();
|
|
14785
|
+
return new Response(renderVoiceProofTrendRecommendationHTML(report, title), {
|
|
14786
|
+
headers: {
|
|
14787
|
+
"content-type": "text/html; charset=utf-8",
|
|
14788
|
+
...Object.fromEntries(new Headers(options.headers))
|
|
14789
|
+
}
|
|
14790
|
+
});
|
|
14791
|
+
});
|
|
14792
|
+
}
|
|
14793
|
+
if (markdownPath !== false) {
|
|
14794
|
+
routes.get(markdownPath, async () => {
|
|
14795
|
+
const report = await loadReport();
|
|
14796
|
+
return new Response(renderVoiceProofTrendRecommendationMarkdown(report, title), {
|
|
14797
|
+
headers: {
|
|
14798
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
14799
|
+
...Object.fromEntries(new Headers(options.headers))
|
|
14800
|
+
}
|
|
14801
|
+
});
|
|
14802
|
+
});
|
|
14803
|
+
}
|
|
14804
|
+
return routes;
|
|
14805
|
+
};
|
|
14614
14806
|
var createVoiceProofTrendRoutes = (options) => {
|
|
14615
14807
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
14616
14808
|
const routes = new Elysia20({
|
|
@@ -14650,7 +14842,7 @@ import { Elysia as Elysia22 } from "elysia";
|
|
|
14650
14842
|
|
|
14651
14843
|
// src/resilienceRoutes.ts
|
|
14652
14844
|
import { Elysia as Elysia21 } from "elysia";
|
|
14653
|
-
var
|
|
14845
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14654
14846
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
14655
14847
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
14656
14848
|
var getBoolean2 = (value) => value === true;
|
|
@@ -14798,13 +14990,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
14798
14990
|
};
|
|
14799
14991
|
var renderProviderCards = (title, providers) => {
|
|
14800
14992
|
if (providers.length === 0) {
|
|
14801
|
-
return `<p class="muted">No ${
|
|
14993
|
+
return `<p class="muted">No ${escapeHtml23(title)} provider health yet.</p>`;
|
|
14802
14994
|
}
|
|
14803
14995
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
14804
|
-
<article class="card provider ${
|
|
14996
|
+
<article class="card provider ${escapeHtml23(provider.status)}">
|
|
14805
14997
|
<div class="card-header">
|
|
14806
|
-
<strong>${
|
|
14807
|
-
<span>${
|
|
14998
|
+
<strong>${escapeHtml23(provider.provider)}</strong>
|
|
14999
|
+
<span>${escapeHtml23(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
14808
15000
|
</div>
|
|
14809
15001
|
<dl>
|
|
14810
15002
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -14813,7 +15005,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
14813
15005
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
14814
15006
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
14815
15007
|
</dl>
|
|
14816
|
-
${provider.lastError ? `<p class="muted">${
|
|
15008
|
+
${provider.lastError ? `<p class="muted">${escapeHtml23(provider.lastError)}</p>` : ""}
|
|
14817
15009
|
</article>
|
|
14818
15010
|
`).join("")}</div>`;
|
|
14819
15011
|
};
|
|
@@ -14822,24 +15014,24 @@ var renderTimeline2 = (events) => {
|
|
|
14822
15014
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
14823
15015
|
}
|
|
14824
15016
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
14825
|
-
<article class="card event ${
|
|
15017
|
+
<article class="card event ${escapeHtml23(event.status ?? "unknown")}">
|
|
14826
15018
|
<div class="card-header">
|
|
14827
|
-
<strong>${
|
|
15019
|
+
<strong>${escapeHtml23(event.kind.toUpperCase())} ${escapeHtml23(event.operation ?? "generate")}</strong>
|
|
14828
15020
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
14829
15021
|
</div>
|
|
14830
15022
|
<p>
|
|
14831
|
-
<span class="pill">${
|
|
14832
|
-
<span class="pill">provider: ${
|
|
14833
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
15023
|
+
<span class="pill">${escapeHtml23(event.status ?? "unknown")}</span>
|
|
15024
|
+
<span class="pill">provider: ${escapeHtml23(event.provider ?? "unknown")}</span>
|
|
15025
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml23(event.fallbackProvider)}</span>` : ""}
|
|
14834
15026
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
14835
15027
|
</p>
|
|
14836
15028
|
<dl>
|
|
14837
15029
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
14838
15030
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
14839
15031
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
14840
|
-
<div><dt>Session</dt><dd>${
|
|
15032
|
+
<div><dt>Session</dt><dd>${escapeHtml23(event.sessionId)}</dd></div>
|
|
14841
15033
|
</dl>
|
|
14842
|
-
${event.error ? `<p class="muted">${
|
|
15034
|
+
${event.error ? `<p class="muted">${escapeHtml23(event.error)}</p>` : ""}
|
|
14843
15035
|
</article>
|
|
14844
15036
|
`).join("")}</div>`;
|
|
14845
15037
|
};
|
|
@@ -14849,9 +15041,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
14849
15041
|
const status = latest?.status ?? "idle";
|
|
14850
15042
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
14851
15043
|
return `<div>
|
|
14852
|
-
<dt>${
|
|
14853
|
-
<dd>${
|
|
14854
|
-
<small>${
|
|
15044
|
+
<dt>${escapeHtml23(kind.toUpperCase())}</dt>
|
|
15045
|
+
<dd>${escapeHtml23(provider)}${escapeHtml23(fallback)}</dd>
|
|
15046
|
+
<small>${escapeHtml23(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
|
|
14855
15047
|
</div>`;
|
|
14856
15048
|
};
|
|
14857
15049
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -14859,10 +15051,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
14859
15051
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
14860
15052
|
}
|
|
14861
15053
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
14862
|
-
<article class="card session ${
|
|
15054
|
+
<article class="card session ${escapeHtml23(session.status)}">
|
|
14863
15055
|
<div class="card-header">
|
|
14864
|
-
<strong>${
|
|
14865
|
-
<span>${
|
|
15056
|
+
<strong>${escapeHtml23(session.sessionId)}</strong>
|
|
15057
|
+
<span>${escapeHtml23(session.status)}</span>
|
|
14866
15058
|
</div>
|
|
14867
15059
|
<p>
|
|
14868
15060
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -14889,21 +15081,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
14889
15081
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
14890
15082
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
14891
15083
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
14892
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
14893
|
-
<p class="muted">${
|
|
15084
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml23(pathPrefix)}">
|
|
15085
|
+
<p class="muted">${escapeHtml23(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
14894
15086
|
<div class="simulate-actions">
|
|
14895
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
14896
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
15087
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml23(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml23(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
15088
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml23(provider.provider)}">Mark ${escapeHtml23(provider.provider)} recovered</button>`).join("")}
|
|
14897
15089
|
</div>
|
|
14898
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
15090
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml23(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
14899
15091
|
<pre class="simulate-output" hidden></pre>
|
|
14900
15092
|
</div>`;
|
|
14901
15093
|
};
|
|
14902
15094
|
var renderVoiceResilienceHTML = (input) => {
|
|
14903
15095
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
14904
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
14905
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
14906
|
-
const snippet =
|
|
15096
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml23(kind)}: ${String(count)}</span>`).join("");
|
|
15097
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml23(link.href)}">${escapeHtml23(link.label)}</a>`).join(" \xB7 ") : "";
|
|
15098
|
+
const snippet = escapeHtml23(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
14907
15099
|
kind: 'stt',
|
|
14908
15100
|
providers: ['deepgram', 'assemblyai'],
|
|
14909
15101
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -14941,7 +15133,7 @@ app.use(
|
|
|
14941
15133
|
<head>
|
|
14942
15134
|
<meta charset="utf-8" />
|
|
14943
15135
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
14944
|
-
<title>${
|
|
15136
|
+
<title>${escapeHtml23(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
14945
15137
|
<style>
|
|
14946
15138
|
:root { color-scheme: dark; }
|
|
14947
15139
|
body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
|
|
@@ -15134,7 +15326,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
15134
15326
|
};
|
|
15135
15327
|
|
|
15136
15328
|
// src/providerDecisionTraces.ts
|
|
15137
|
-
var
|
|
15329
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15138
15330
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
15139
15331
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15140
15332
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -15375,7 +15567,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
15375
15567
|
<head>
|
|
15376
15568
|
<meta charset="utf-8" />
|
|
15377
15569
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15378
|
-
<title>${
|
|
15570
|
+
<title>${escapeHtml24(title)}</title>
|
|
15379
15571
|
<style>
|
|
15380
15572
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
15381
15573
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -15389,8 +15581,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
15389
15581
|
</head>
|
|
15390
15582
|
<body>
|
|
15391
15583
|
<main>
|
|
15392
|
-
<p class="status ${report.status}">${
|
|
15393
|
-
<h1>${
|
|
15584
|
+
<p class="status ${report.status}">${escapeHtml24(report.status)}</p>
|
|
15585
|
+
<h1>${escapeHtml24(title)}</h1>
|
|
15394
15586
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
15395
15587
|
<section class="grid">
|
|
15396
15588
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -15401,10 +15593,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
15401
15593
|
</section>
|
|
15402
15594
|
<section class="surfaces">
|
|
15403
15595
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
15404
|
-
<header><strong>${
|
|
15596
|
+
<header><strong>${escapeHtml24(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml24(surface.status)}</span></header>
|
|
15405
15597
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
15406
|
-
<p class="muted">Providers: ${
|
|
15407
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
15598
|
+
<p class="muted">Providers: ${escapeHtml24(surface.providers.join(", ") || "none")}</p>
|
|
15599
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml24(reason)}</code>`).join(" ")}</p>
|
|
15408
15600
|
</article>`).join(`
|
|
15409
15601
|
`)}
|
|
15410
15602
|
</section>
|
|
@@ -15465,6 +15657,7 @@ var normalizeSample = (input) => {
|
|
|
15465
15657
|
return {
|
|
15466
15658
|
generatedAt: input.generatedAt,
|
|
15467
15659
|
liveP95Ms: input.summary.maxLiveP95Ms,
|
|
15660
|
+
interruptionP95Ms: input.summary.runtimeChannel?.maxInterruptionP95Ms,
|
|
15468
15661
|
ok: input.ok,
|
|
15469
15662
|
providerP95Ms: input.summary.maxProviderP95Ms,
|
|
15470
15663
|
runId: input.runId,
|
|
@@ -15625,8 +15818,8 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
15625
15818
|
status: profile.status
|
|
15626
15819
|
};
|
|
15627
15820
|
};
|
|
15628
|
-
var
|
|
15629
|
-
var
|
|
15821
|
+
var escapeMarkdown3 = (value) => value.replaceAll("|", "\\|");
|
|
15822
|
+
var escapeHtml25 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15630
15823
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
15631
15824
|
var readinessThresholdRows = (report) => [
|
|
15632
15825
|
{
|
|
@@ -15671,7 +15864,7 @@ var readinessThresholdRows = (report) => [
|
|
|
15671
15864
|
}
|
|
15672
15865
|
];
|
|
15673
15866
|
var renderVoiceSloCalibrationMarkdown = (report, options = {}) => {
|
|
15674
|
-
const rows = Object.values(report.thresholds).map((threshold) => `| ${
|
|
15867
|
+
const rows = Object.values(report.thresholds).map((threshold) => `| ${escapeMarkdown3(threshold.metric)} | ${threshold.status} | ${threshold.samples} | ${threshold.baselineP95Ms ?? "n/a"} | ${threshold.warnAfterMs ?? "n/a"} | ${threshold.failAfterMs ?? "n/a"} |`).join(`
|
|
15675
15868
|
`);
|
|
15676
15869
|
return `# ${options.title ?? "Voice SLO Calibration"}
|
|
15677
15870
|
|
|
@@ -15692,7 +15885,7 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
15692
15885
|
`;
|
|
15693
15886
|
};
|
|
15694
15887
|
var renderVoiceSloReadinessThresholdMarkdown = (report, options = {}) => {
|
|
15695
|
-
const rows = readinessThresholdRows(report).map((row) => `| ${
|
|
15888
|
+
const rows = readinessThresholdRows(report).map((row) => `| ${escapeMarkdown3(row.control)} | ${formatMs(row.value)} | ${escapeMarkdown3(row.usedBy)} |`).join(`
|
|
15696
15889
|
`);
|
|
15697
15890
|
return `# ${options.title ?? "Calibration -> Active Readiness Gate"}
|
|
15698
15891
|
|
|
@@ -15717,10 +15910,10 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
15717
15910
|
};
|
|
15718
15911
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
15719
15912
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
15720
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
15721
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
15722
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
15723
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15913
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml25(row.control)}</td><td>${escapeHtml25(formatMs(row.value))}</td><td>${escapeHtml25(row.usedBy)}</td></tr>`).join("");
|
|
15914
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml25(issue)}</li>`).join("");
|
|
15915
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml25(source)}</code></li>`).join("");
|
|
15916
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1040px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}.status{font-size:1.6rem;font-weight:800;text-transform:uppercase}</style></head><body><main><h1>${escapeHtml25(title)}</h1><p>This page shows the calibrated thresholds currently driving production readiness gates.</p><section class="summary"><div class="card"><strong>Status</strong><br><span class="status">${escapeHtml25(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml25(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml25(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml25(formatMs(report.bargeIn.thresholdMs))}</div></section><h2>Active Readiness Thresholds</h2><table><thead><tr><th>Threshold</th><th>Active value</th><th>Used by</th></tr></thead><tbody>${rows}</tbody></table><h2>Sources</h2><ul>${sources}</ul><h2>Issues</h2><ul>${issues}</ul></main></body></html>`;
|
|
15724
15917
|
};
|
|
15725
15918
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
15726
15919
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
@@ -16118,12 +16311,12 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
16118
16311
|
import { Elysia as Elysia25 } from "elysia";
|
|
16119
16312
|
import { mkdir } from "fs/promises";
|
|
16120
16313
|
import { dirname, join } from "path";
|
|
16121
|
-
var
|
|
16314
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16122
16315
|
var renderSummaryCard = (label, summary) => {
|
|
16123
16316
|
if (!summary) {
|
|
16124
|
-
return `<article><span>${
|
|
16317
|
+
return `<article><span>${escapeHtml26(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
16125
16318
|
}
|
|
16126
|
-
return `<article><span>${
|
|
16319
|
+
return `<article><span>${escapeHtml26(label)}</span><strong>${String(summary.delivered)}/${String(summary.total)}</strong><p class="muted">${String(summary.pending)} pending · ${String(summary.failed)} failed · ${String(summary.deadLettered)} dead-lettered</p></article>`;
|
|
16127
16320
|
};
|
|
16128
16321
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
16129
16322
|
audit: leases,
|
|
@@ -16334,9 +16527,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
16334
16527
|
});
|
|
16335
16528
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
16336
16529
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
16337
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
16338
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
16339
|
-
const snippet =
|
|
16530
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml26(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
16531
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml26(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
16532
|
+
const snippet = escapeHtml26(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
16340
16533
|
createVoiceDeliveryRuntimePresetConfig({
|
|
16341
16534
|
audit: {
|
|
16342
16535
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -16362,7 +16555,7 @@ app.use(
|
|
|
16362
16555
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
16363
16556
|
})
|
|
16364
16557
|
);`);
|
|
16365
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16558
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml26(title)}</title><style>body{background:#0f1411;color:#f7f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}a{color:#86efac;text-decoration:none}.hero{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(14,165,233,.13));border:1px solid #263a30;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#86efac;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.running{border-color:rgba(34,197,94,.7);color:#bbf7d0}.muted{color:#b9c3b4}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin:18px 0}article,.card{background:#151d18;border:1px solid #263a30;border-radius:22px;padding:18px}.primitive{background:#111a15;border-color:#41604a}article span{color:#b9c3b4;display:block;font-weight:800}article strong{display:block;font-size:2.3rem;margin-top:8px}.actions{display:flex;flex-wrap:wrap;gap:10px}button{background:#86efac;border:0;border-radius:999px;color:#07120b;cursor:pointer;font-weight:900;margin-top:12px;padding:10px 14px}pre{background:#09100c;border:1px solid #263a30;border-radius:18px;color:#dcfce7;overflow:auto;padding:16px}.primitive p{color:#c8d8ca;line-height:1.55}.primitive code{color:#bbf7d0}</style></head><body><main><p><a href="/delivery-sinks">Delivery sinks</a></p><section class="hero"><p class="eyebrow">Worker control plane</p><h1>${escapeHtml26(title)}</h1><p class="muted">Inspect queue summaries, manually tick failed/pending audit and trace deliveries, and requeue dead letters after operator review.</p><p class="status ${report.isRunning ? "running" : ""}">${report.isRunning ? "Running" : "Stopped"}</p><p class="muted">Checked ${escapeHtml26(new Date(report.checkedAt).toLocaleString())}</p><div class="actions">${tickForm}${requeueForm}</div></section><section class="grid">${renderSummaryCard("Audit", report.summary.audit)}${renderSummaryCard("Trace", report.summary.trace)}</section><section class="card primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceDeliveryRuntimeRoutes(...)</code> builds this control plane</h2><p>Own the audit and trace delivery queues in your app, mount one runtime route group, and pass the same runtime into production readiness so failed or dead-lettered exports block deploys.</p><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
16366
16559
|
};
|
|
16367
16560
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
16368
16561
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
@@ -16644,7 +16837,7 @@ var parseRetentionScopes = (value) => {
|
|
|
16644
16837
|
const allowed = new Set(allRetentionScopes);
|
|
16645
16838
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
16646
16839
|
};
|
|
16647
|
-
var
|
|
16840
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16648
16841
|
var buildStorageSurfaces = (options) => [
|
|
16649
16842
|
{
|
|
16650
16843
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -16881,12 +17074,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
16881
17074
|
zeroRetentionAvailable: true
|
|
16882
17075
|
};
|
|
16883
17076
|
};
|
|
16884
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
17077
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml27(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml27(scope.skippedReason ?? "")}</td><td><code>${escapeHtml27(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
16885
17078
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
16886
17079
|
const title = options.title ?? "Voice Data Control";
|
|
16887
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
16888
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
16889
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
17080
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml27(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml27(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
17081
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml27(key.name)}</td><td><code>${escapeHtml27(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml27(key.recommendation)}</td></tr>`).join("");
|
|
17082
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml27(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml27(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
|
|
16890
17083
|
};
|
|
16891
17084
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
16892
17085
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -17029,7 +17222,7 @@ import { Elysia as Elysia28 } from "elysia";
|
|
|
17029
17222
|
|
|
17030
17223
|
// src/handoffHealth.ts
|
|
17031
17224
|
import { Elysia as Elysia27 } from "elysia";
|
|
17032
|
-
var
|
|
17225
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17033
17226
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
17034
17227
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
17035
17228
|
var increment3 = (record, key) => {
|
|
@@ -17147,10 +17340,10 @@ var renderActionSummary = (summary) => {
|
|
|
17147
17340
|
return [
|
|
17148
17341
|
'<section class="voice-handoff-health-columns">',
|
|
17149
17342
|
"<article><h3>Actions</h3>",
|
|
17150
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
17343
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml28(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
17151
17344
|
"</article>",
|
|
17152
17345
|
"<article><h3>Adapters</h3>",
|
|
17153
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
17346
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml28(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
17154
17347
|
"</article>",
|
|
17155
17348
|
"</section>"
|
|
17156
17349
|
].join("");
|
|
@@ -17164,22 +17357,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
17164
17357
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
17165
17358
|
'<div class="voice-handoff-health-events">',
|
|
17166
17359
|
...summary.events.map((event) => [
|
|
17167
|
-
`<article class="${
|
|
17360
|
+
`<article class="${escapeHtml28(event.status)}">`,
|
|
17168
17361
|
'<div class="voice-handoff-health-event-header">',
|
|
17169
|
-
`<strong>${
|
|
17170
|
-
`<span>${
|
|
17362
|
+
`<strong>${escapeHtml28(event.action ?? "handoff")}</strong>`,
|
|
17363
|
+
`<span>${escapeHtml28(event.status)}</span>`,
|
|
17171
17364
|
"</div>",
|
|
17172
|
-
`<p><small>${
|
|
17173
|
-
event.target ? `<p>Target: ${
|
|
17174
|
-
event.reason ? `<p>Reason: ${
|
|
17365
|
+
`<p><small>${escapeHtml28(event.sessionId)}</small></p>`,
|
|
17366
|
+
event.target ? `<p>Target: ${escapeHtml28(event.target)}</p>` : "",
|
|
17367
|
+
event.reason ? `<p>Reason: ${escapeHtml28(event.reason)}</p>` : "",
|
|
17175
17368
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
17176
17369
|
"<li>",
|
|
17177
|
-
`${
|
|
17178
|
-
delivery.deliveredTo ? ` to ${
|
|
17179
|
-
delivery.error ? ` (${
|
|
17370
|
+
`${escapeHtml28(delivery.adapterId)}: ${escapeHtml28(delivery.status)}`,
|
|
17371
|
+
delivery.deliveredTo ? ` to ${escapeHtml28(delivery.deliveredTo)}` : "",
|
|
17372
|
+
delivery.error ? ` (${escapeHtml28(delivery.error)})` : "",
|
|
17180
17373
|
"</li>"
|
|
17181
17374
|
].join("")).join("")}</ul>` : "",
|
|
17182
|
-
event.replayHref ? `<p><a href="${
|
|
17375
|
+
event.replayHref ? `<p><a href="${escapeHtml28(event.replayHref)}">Open replay</a></p>` : "",
|
|
17183
17376
|
"</article>"
|
|
17184
17377
|
].join("")),
|
|
17185
17378
|
"</div>"
|
|
@@ -17332,12 +17525,12 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
17332
17525
|
thresholds
|
|
17333
17526
|
};
|
|
17334
17527
|
};
|
|
17335
|
-
var
|
|
17528
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17336
17529
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
17337
17530
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
17338
17531
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
17339
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
17340
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17532
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml29(metric.label)}</td><td>${escapeHtml29(formatMetricValue(metric))}</td><td>${escapeHtml29(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml29(key)}</code></td></tr>`).join("");
|
|
17533
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml29(link.href)}">${escapeHtml29(link.label)}</a>`).join("")}</nav>` : "";
|
|
17341
17534
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>AbsoluteJS Voice Quality</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}nav{display:flex;flex-wrap:wrap;gap:.5rem;margin:0 0 1.25rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;padding:.35rem .75rem;font-weight:800}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}table{border-collapse:collapse;width:100%;background:white;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}.pass td{border-left:4px solid #16a34a}.fail td{border-left:4px solid #dc2626}code{background:#f3f4f6;padding:.15rem .3rem;border-radius:.3rem}</style></head><body><main>${links}<h1>Voice quality gates</h1><p class="status ${report.status}">${report.status}</p><p>${report.eventCount} event(s) checked.</p><table><thead><tr><th>Metric</th><th>Actual</th><th>Threshold</th><th>Status</th><th>Key</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
17342
17535
|
};
|
|
17343
17536
|
var createVoiceQualityRoutes = (options) => {
|
|
@@ -17371,7 +17564,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
17371
17564
|
};
|
|
17372
17565
|
|
|
17373
17566
|
// src/evalRoutes.ts
|
|
17374
|
-
var
|
|
17567
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17375
17568
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
17376
17569
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
17377
17570
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -17693,7 +17886,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
17693
17886
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
17694
17887
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
17695
17888
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
17696
|
-
const snippet =
|
|
17889
|
+
const snippet = escapeHtml30(`app.use(
|
|
17697
17890
|
createVoiceEvalRoutes({
|
|
17698
17891
|
path: '/evals',
|
|
17699
17892
|
store: traceStore,
|
|
@@ -17714,44 +17907,44 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
17714
17907
|
};
|
|
17715
17908
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
17716
17909
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
17717
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17718
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
17910
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml30(link.href)}">${escapeHtml30(link.label)}</a>`).join("")}</nav>` : "";
|
|
17911
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml30(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
|
|
17719
17912
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
17720
17913
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
17721
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
17722
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
17914
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml30(session.operationsRecordHref)}">${escapeHtml30(session.sessionId)}</a>` : escapeHtml30(session.sessionId);
|
|
17915
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml30(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml30(formatTime(session.endedAt))}</td><td>${escapeHtml30(failedMetrics || "none")}</td></tr>`;
|
|
17723
17916
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
17724
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17917
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml30(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml30(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
|
|
17725
17918
|
};
|
|
17726
17919
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
17727
17920
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
17728
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17729
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
17730
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
17731
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
17732
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17921
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml30(link.href)}">${escapeHtml30(link.label)}</a>`).join("")}</nav>` : "";
|
|
17922
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml30(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
17923
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml30(id)}</li>`).join("") : "<li>none</li>";
|
|
17924
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml30(id)}</li>`).join("") : "<li>none</li>";
|
|
17925
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml30(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml30(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml30(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml30(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml30(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
|
|
17733
17926
|
};
|
|
17734
17927
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
17735
17928
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
17736
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17929
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml30(link.href)}">${escapeHtml30(link.label)}</a>`).join("")}</nav>` : "";
|
|
17737
17930
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
17738
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
17931
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml30(issue)}</li>`).join("")}</ul>` : "";
|
|
17739
17932
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
17740
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
17741
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
17933
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml30(session.operationsRecordHref)}">${escapeHtml30(session.sessionId)}</a>` : escapeHtml30(session.sessionId);
|
|
17934
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml30(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml30(session.issues.join(", ") || "none")}</td></tr>`;
|
|
17742
17935
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
17743
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
17936
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml30(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml30(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
|
|
17744
17937
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
17745
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17938
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml30(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml30(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
|
|
17746
17939
|
};
|
|
17747
17940
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
17748
17941
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
17749
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17942
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml30(link.href)}">${escapeHtml30(link.label)}</a>`).join("")}</nav>` : "";
|
|
17750
17943
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
17751
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
17752
|
-
return `<section class="${fixture.status}"><h2>${
|
|
17944
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml30(scenario.label)}</td><td>${escapeHtml30(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml30([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
17945
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml30(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml30(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
|
|
17753
17946
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
17754
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17947
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml30(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml30(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
|
|
17755
17948
|
};
|
|
17756
17949
|
var createVoiceEvalRoutes = (options) => {
|
|
17757
17950
|
const path = options.path ?? "/evals";
|
|
@@ -17896,7 +18089,7 @@ import { Elysia as Elysia32 } from "elysia";
|
|
|
17896
18089
|
|
|
17897
18090
|
// src/outcomeContract.ts
|
|
17898
18091
|
import { Elysia as Elysia30 } from "elysia";
|
|
17899
|
-
var
|
|
18092
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17900
18093
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
17901
18094
|
if (value === false) {
|
|
17902
18095
|
return;
|
|
@@ -18107,13 +18300,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
18107
18300
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
18108
18301
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
18109
18302
|
const contracts = report.contracts.map((contract) => {
|
|
18110
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
18303
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml31(href)}">${escapeHtml31(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
18111
18304
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
18112
18305
|
<div class="contract-header">
|
|
18113
18306
|
<div>
|
|
18114
|
-
<p class="eyebrow">${
|
|
18115
|
-
<h2>${
|
|
18116
|
-
${contract.description ? `<p>${
|
|
18307
|
+
<p class="eyebrow">${escapeHtml31(contract.contractId)}</p>
|
|
18308
|
+
<h2>${escapeHtml31(contract.label ?? contract.contractId)}</h2>
|
|
18309
|
+
${contract.description ? `<p>${escapeHtml31(contract.description)}</p>` : ""}
|
|
18117
18310
|
${sessionLinks}
|
|
18118
18311
|
</div>
|
|
18119
18312
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -18125,10 +18318,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
18125
18318
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
18126
18319
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
18127
18320
|
</div>
|
|
18128
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
18321
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml31(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
18129
18322
|
</section>`;
|
|
18130
18323
|
}).join("");
|
|
18131
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18324
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml31(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml31(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
|
|
18132
18325
|
};
|
|
18133
18326
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
18134
18327
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -18363,7 +18556,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
18363
18556
|
});
|
|
18364
18557
|
var defaultApi = {};
|
|
18365
18558
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
18366
|
-
var
|
|
18559
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18367
18560
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
18368
18561
|
if (value === false) {
|
|
18369
18562
|
return;
|
|
@@ -18612,7 +18805,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
18612
18805
|
};
|
|
18613
18806
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
18614
18807
|
const title = options.title ?? "Voice Tool Contracts";
|
|
18615
|
-
const snippet =
|
|
18808
|
+
const snippet = escapeHtml32(`app.use(
|
|
18616
18809
|
createVoiceToolContractRoutes({
|
|
18617
18810
|
htmlPath: '/tool-contracts',
|
|
18618
18811
|
path: '/api/tool-contracts',
|
|
@@ -18638,20 +18831,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
18638
18831
|
);`);
|
|
18639
18832
|
const contracts = report.contracts.map((contract) => {
|
|
18640
18833
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
18641
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
18834
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml32(testCase.operationsRecordHref)}">${escapeHtml32(testCase.label ?? testCase.caseId)}</a>` : escapeHtml32(testCase.label ?? testCase.caseId)}</td>
|
|
18642
18835
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
18643
|
-
<td>${
|
|
18644
|
-
<td>${
|
|
18836
|
+
<td>${escapeHtml32(testCase.status)}</td>
|
|
18837
|
+
<td>${escapeHtml32(testCase.sessionId)}</td>
|
|
18645
18838
|
<td>${String(testCase.attempts)}</td>
|
|
18646
18839
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
18647
18840
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
18648
|
-
<td>${
|
|
18841
|
+
<td>${escapeHtml32(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
18649
18842
|
</tr>`).join("");
|
|
18650
18843
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
18651
18844
|
<div class="contract-header">
|
|
18652
18845
|
<div>
|
|
18653
|
-
<p class="eyebrow">${
|
|
18654
|
-
<h2>${
|
|
18846
|
+
<p class="eyebrow">${escapeHtml32(contract.toolName)}</p>
|
|
18847
|
+
<h2>${escapeHtml32(contract.label ?? contract.contractId)}</h2>
|
|
18655
18848
|
</div>
|
|
18656
18849
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
18657
18850
|
</div>
|
|
@@ -18661,7 +18854,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
18661
18854
|
</table>
|
|
18662
18855
|
</section>`;
|
|
18663
18856
|
}).join("");
|
|
18664
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18857
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml32(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml32(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
|
|
18665
18858
|
};
|
|
18666
18859
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
18667
18860
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -18688,7 +18881,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
18688
18881
|
};
|
|
18689
18882
|
|
|
18690
18883
|
// src/simulationSuite.ts
|
|
18691
|
-
var
|
|
18884
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18692
18885
|
var summarizeSection = (report) => ({
|
|
18693
18886
|
failed: report.failed,
|
|
18694
18887
|
passed: report.passed,
|
|
@@ -18884,15 +19077,15 @@ var renderSection = (label, summary) => {
|
|
|
18884
19077
|
if (!summary) {
|
|
18885
19078
|
return "";
|
|
18886
19079
|
}
|
|
18887
|
-
return `<article class="${
|
|
19080
|
+
return `<article class="${escapeHtml33(summary.status)}"><span>${escapeHtml33(label)}</span><strong>${escapeHtml33(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
18888
19081
|
};
|
|
18889
19082
|
var renderAction = (action) => {
|
|
18890
|
-
const content = `<strong>${
|
|
18891
|
-
return action.href ? `<a class="action" href="${
|
|
19083
|
+
const content = `<strong>${escapeHtml33(action.label)}</strong><p>${escapeHtml33(action.description)}</p><span>${escapeHtml33(action.section)} / ${escapeHtml33(action.severity)}</span>`;
|
|
19084
|
+
return action.href ? `<a class="action" href="${escapeHtml33(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
18892
19085
|
};
|
|
18893
19086
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
18894
19087
|
const title = options.title ?? "Voice Simulation Suite";
|
|
18895
|
-
const snippet =
|
|
19088
|
+
const snippet = escapeHtml33(`app.use(
|
|
18896
19089
|
createVoiceSimulationSuiteRoutes({
|
|
18897
19090
|
htmlPath: '/voice/simulations',
|
|
18898
19091
|
path: '/api/voice/simulations',
|
|
@@ -18925,7 +19118,7 @@ app.use(
|
|
|
18925
19118
|
store: traceStore
|
|
18926
19119
|
})
|
|
18927
19120
|
);`);
|
|
18928
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19121
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml33(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml33(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml33(report.status)}">Status: ${escapeHtml33(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml33(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
18929
19122
|
};
|
|
18930
19123
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
18931
19124
|
const path = options.path ?? "/api/voice/simulations";
|
|
@@ -19244,7 +19437,7 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
19244
19437
|
// src/sessionReplay.ts
|
|
19245
19438
|
import { Elysia as Elysia33 } from "elysia";
|
|
19246
19439
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
19247
|
-
var
|
|
19440
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19248
19441
|
var increment4 = (record, key) => {
|
|
19249
19442
|
record[key] = (record[key] ?? 0) + 1;
|
|
19250
19443
|
};
|
|
@@ -19438,10 +19631,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
19438
19631
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
19439
19632
|
'<div class="voice-sessions-list">',
|
|
19440
19633
|
...sessions.map((session) => [
|
|
19441
|
-
`<article class="voice-session-card ${
|
|
19634
|
+
`<article class="voice-session-card ${escapeHtml34(session.status)}">`,
|
|
19442
19635
|
'<div class="voice-session-card-header">',
|
|
19443
|
-
`<strong>${
|
|
19444
|
-
`<span>${
|
|
19636
|
+
`<strong>${escapeHtml34(session.sessionId)}</strong>`,
|
|
19637
|
+
`<span>${escapeHtml34(session.status)}</span>`,
|
|
19445
19638
|
"</div>",
|
|
19446
19639
|
"<dl>",
|
|
19447
19640
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -19449,9 +19642,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
19449
19642
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
19450
19643
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
19451
19644
|
"</dl>",
|
|
19452
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
19453
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
19454
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
19645
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml34(session.latestOutcome)}</p>` : "",
|
|
19646
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml34).join(", ")}</p>` : "",
|
|
19647
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml34(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml34(session.replayHref)}">Open replay</a></p>` : "",
|
|
19455
19648
|
"</article>"
|
|
19456
19649
|
].join("")),
|
|
19457
19650
|
"</div>"
|
|
@@ -19827,7 +20020,7 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
19827
20020
|
import { Elysia as Elysia34 } from "elysia";
|
|
19828
20021
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
19829
20022
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
19830
|
-
var
|
|
20023
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19831
20024
|
var firstNumber2 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
19832
20025
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
19833
20026
|
var createTraceStageIndex = (events) => {
|
|
@@ -19959,11 +20152,11 @@ await traceStore.append({
|
|
|
19959
20152
|
turnId,
|
|
19960
20153
|
type: 'turn_latency.stage'
|
|
19961
20154
|
});`;
|
|
19962
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
19963
|
-
<header><div><p class="eyebrow">${
|
|
19964
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
20155
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml35(turn.status)}">
|
|
20156
|
+
<header><div><p class="eyebrow">${escapeHtml35(turn.sessionId)} \xB7 ${escapeHtml35(turn.turnId)}</p><h2>${escapeHtml35(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml35(turn.status)}</strong></header>
|
|
20157
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml35(stage.label)}</dt><dd>${escapeHtml35(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
19965
20158
|
</article>`).join("");
|
|
19966
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20159
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml35(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml35(title)}</h1><div class="summary"><span class="pill ${escapeHtml35(report.status)}">${escapeHtml35(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml35(formatMs2(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml35(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
19967
20160
|
};
|
|
19968
20161
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
19969
20162
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -19990,7 +20183,7 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
19990
20183
|
};
|
|
19991
20184
|
// src/liveLatency.ts
|
|
19992
20185
|
import { Elysia as Elysia35 } from "elysia";
|
|
19993
|
-
var
|
|
20186
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19994
20187
|
var percentile3 = (values, percentileValue) => {
|
|
19995
20188
|
if (values.length === 0) {
|
|
19996
20189
|
return;
|
|
@@ -20057,8 +20250,8 @@ await traceStore.append({
|
|
|
20057
20250
|
sessionId,
|
|
20058
20251
|
type: 'client.live_latency'
|
|
20059
20252
|
});`;
|
|
20060
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
20061
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20253
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml36(sample.sessionId)}</td><td>${escapeHtml36(formatMs3(sample.latencyMs))}</td><td>${escapeHtml36(sample.status ?? "unknown")}</td><td>${escapeHtml36(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
20254
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml36(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml36(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml36(report.status)}">Status: ${escapeHtml36(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml36(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml36(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml36(formatMs3(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml36(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
20062
20255
|
};
|
|
20063
20256
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
20064
20257
|
const path = options.path ?? "/api/live-latency";
|
|
@@ -20384,7 +20577,7 @@ None.
|
|
|
20384
20577
|
// src/turnQuality.ts
|
|
20385
20578
|
import { Elysia as Elysia36 } from "elysia";
|
|
20386
20579
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
20387
|
-
var
|
|
20580
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20388
20581
|
var getTurnLatencyMs = (turn) => {
|
|
20389
20582
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
20390
20583
|
if (firstTranscriptAt === undefined) {
|
|
@@ -20455,24 +20648,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
20455
20648
|
};
|
|
20456
20649
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
20457
20650
|
const title = options.title ?? "Voice Turn Quality";
|
|
20458
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
20651
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml37(turn.status)}">
|
|
20459
20652
|
<div class="turn-header">
|
|
20460
20653
|
<div>
|
|
20461
|
-
<p class="eyebrow">${
|
|
20462
|
-
<h2>${
|
|
20654
|
+
<p class="eyebrow">${escapeHtml37(turn.sessionId)} \xB7 ${escapeHtml37(turn.turnId)}</p>
|
|
20655
|
+
<h2>${escapeHtml37(turn.text || "Empty turn")}</h2>
|
|
20463
20656
|
</div>
|
|
20464
|
-
<strong>${
|
|
20657
|
+
<strong>${escapeHtml37(turn.status)}</strong>
|
|
20465
20658
|
</div>
|
|
20466
20659
|
<dl>
|
|
20467
|
-
<div><dt>Source</dt><dd>${
|
|
20660
|
+
<div><dt>Source</dt><dd>${escapeHtml37(turn.source ?? "unknown")}</dd></div>
|
|
20468
20661
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
20469
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
20470
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
20662
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml37(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
20663
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml37(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
20471
20664
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
20472
20665
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
20473
20666
|
</dl>
|
|
20474
20667
|
</article>`).join("");
|
|
20475
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20668
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml37(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml37(title)}</h1><div class="summary"><span class="pill ${escapeHtml37(report.status)}">${escapeHtml37(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
20476
20669
|
};
|
|
20477
20670
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
20478
20671
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -21399,7 +21592,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
21399
21592
|
return parameters;
|
|
21400
21593
|
};
|
|
21401
21594
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
21402
|
-
var
|
|
21595
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21403
21596
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
21404
21597
|
if (!webhook?.verificationUrl) {
|
|
21405
21598
|
return;
|
|
@@ -21442,23 +21635,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
21442
21635
|
};
|
|
21443
21636
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21444
21637
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
21445
|
-
<h1>${
|
|
21638
|
+
<h1>${escapeHtml38(title)}</h1>
|
|
21446
21639
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
21447
21640
|
<section>
|
|
21448
21641
|
<h2>URLs</h2>
|
|
21449
21642
|
<ul>
|
|
21450
|
-
<li><strong>TwiML:</strong> <code>${
|
|
21451
|
-
<li><strong>Media stream:</strong> <code>${
|
|
21452
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
21643
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml38(status.urls.twiml)}</code></li>
|
|
21644
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml38(status.urls.stream)}</code></li>
|
|
21645
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml38(status.urls.webhook)}</code></li>
|
|
21453
21646
|
</ul>
|
|
21454
21647
|
</section>
|
|
21455
21648
|
<section>
|
|
21456
21649
|
<h2>Signing</h2>
|
|
21457
21650
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
21458
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
21651
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml38(status.signing.verificationUrl)}</code></p>` : ""}
|
|
21459
21652
|
</section>
|
|
21460
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
21461
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
21653
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml38(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
21654
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml38(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
21462
21655
|
</main>`;
|
|
21463
21656
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
21464
21657
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -21469,20 +21662,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
21469
21662
|
});
|
|
21470
21663
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21471
21664
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
21472
|
-
<h1>${
|
|
21665
|
+
<h1>${escapeHtml38(title)}</h1>
|
|
21473
21666
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
21474
21667
|
<section>
|
|
21475
21668
|
<h2>Checks</h2>
|
|
21476
21669
|
<ul>
|
|
21477
|
-
${report.checks.map((check) => `<li><strong>${
|
|
21670
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml38(check.name)}</strong>: ${escapeHtml38(check.status)}${check.message ? ` - ${escapeHtml38(check.message)}` : ""}</li>`).join("")}
|
|
21478
21671
|
</ul>
|
|
21479
21672
|
</section>
|
|
21480
21673
|
<section>
|
|
21481
21674
|
<h2>Observed URLs</h2>
|
|
21482
21675
|
<ul>
|
|
21483
|
-
<li><strong>TwiML:</strong> <code>${
|
|
21484
|
-
<li><strong>Stream:</strong> <code>${
|
|
21485
|
-
<li><strong>Webhook:</strong> <code>${
|
|
21676
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml38(report.setup.urls.twiml)}</code></li>
|
|
21677
|
+
<li><strong>Stream:</strong> <code>${escapeHtml38(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
21678
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml38(report.setup.urls.webhook)}</code></li>
|
|
21486
21679
|
</ul>
|
|
21487
21680
|
</section>
|
|
21488
21681
|
</main>`;
|
|
@@ -22165,7 +22358,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
22165
22358
|
|
|
22166
22359
|
// src/telephony/plivo.ts
|
|
22167
22360
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22168
|
-
var
|
|
22361
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22169
22362
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22170
22363
|
var resolveRequestOrigin2 = (request) => {
|
|
22171
22364
|
const url = new URL(request.url);
|
|
@@ -22596,21 +22789,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
22596
22789
|
};
|
|
22597
22790
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22598
22791
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
22599
|
-
<h1>${
|
|
22792
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22600
22793
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22601
22794
|
<ul>
|
|
22602
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
22603
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
22604
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
22795
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml39(status.urls.answer)}</code></li>
|
|
22796
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml39(status.urls.stream)}</code></li>
|
|
22797
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml39(status.urls.webhook)}</code></li>
|
|
22605
22798
|
</ul>
|
|
22606
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
22607
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
22799
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml39(name)}</code></li>`).join("")}</ul>` : ""}
|
|
22800
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml39(warning)}</li>`).join("")}</ul>` : ""}
|
|
22608
22801
|
</main>`;
|
|
22609
22802
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22610
22803
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
22611
|
-
<h1>${
|
|
22804
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22612
22805
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22613
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
22806
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml39(check.name)}</strong>: ${escapeHtml39(check.status)}${check.message ? ` - ${escapeHtml39(check.message)}` : ""}</li>`).join("")}</ul>
|
|
22614
22807
|
</main>`;
|
|
22615
22808
|
var runPlivoSmokeTest = async (input) => {
|
|
22616
22809
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -22814,7 +23007,7 @@ import { Buffer as Buffer6 } from "buffer";
|
|
|
22814
23007
|
import { Database as Database2 } from "bun:sqlite";
|
|
22815
23008
|
import { Elysia as Elysia40 } from "elysia";
|
|
22816
23009
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22817
|
-
var
|
|
23010
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22818
23011
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22819
23012
|
var resolveRequestOrigin3 = (request) => {
|
|
22820
23013
|
const url = new URL(request.url);
|
|
@@ -23208,21 +23401,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
23208
23401
|
};
|
|
23209
23402
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23210
23403
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
23211
|
-
<h1>${
|
|
23404
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23212
23405
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23213
23406
|
<ul>
|
|
23214
|
-
<li><strong>TeXML:</strong> <code>${
|
|
23215
|
-
<li><strong>Media stream:</strong> <code>${
|
|
23216
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
23407
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml40(status.urls.texml)}</code></li>
|
|
23408
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml40(status.urls.stream)}</code></li>
|
|
23409
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml40(status.urls.webhook)}</code></li>
|
|
23217
23410
|
</ul>
|
|
23218
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23219
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
23411
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml40(name)}</code></li>`).join("")}</ul>` : ""}
|
|
23412
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml40(warning)}</li>`).join("")}</ul>` : ""}
|
|
23220
23413
|
</main>`;
|
|
23221
23414
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23222
23415
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
23223
|
-
<h1>${
|
|
23416
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23224
23417
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23225
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
23418
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml40(check.name)}</strong>: ${escapeHtml40(check.status)}${check.message ? ` - ${escapeHtml40(check.message)}` : ""}</li>`).join("")}</ul>
|
|
23226
23419
|
</main>`;
|
|
23227
23420
|
var runTelnyxSmokeTest = async (input) => {
|
|
23228
23421
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -23426,7 +23619,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
23426
23619
|
|
|
23427
23620
|
// src/telephony/matrix.ts
|
|
23428
23621
|
import { Elysia as Elysia41 } from "elysia";
|
|
23429
|
-
var
|
|
23622
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23430
23623
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
23431
23624
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
23432
23625
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -23487,13 +23680,13 @@ var badgeStyles = {
|
|
|
23487
23680
|
};
|
|
23488
23681
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
23489
23682
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
23490
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
23683
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml41(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
23491
23684
|
<p style="color:#52606d; margin: 0 0 24px;">${matrix.summary.ready}/${matrix.summary.providers} ready, ${matrix.summary.contractsPassing}/${matrix.summary.providers} contract passing, ${matrix.summary.smokePassing}/${matrix.summary.providers} smoke passing.</p>
|
|
23492
23685
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
23493
23686
|
${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; border-radius:18px; padding:18px; background:#fff; box-shadow:0 18px 48px rgba(15,23,42,.08);">
|
|
23494
23687
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
23495
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
23496
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
23688
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml41(entry.name)}</h2>
|
|
23689
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml41(entry.status.toUpperCase())}</span>
|
|
23497
23690
|
</div>
|
|
23498
23691
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
23499
23692
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -23501,9 +23694,9 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
23501
23694
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
23502
23695
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
23503
23696
|
</dl>
|
|
23504
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
23505
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
23506
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
23697
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml41(entry.setup.urls.stream || "missing")}</code></p>
|
|
23698
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml41(entry.setup.urls.webhook || "missing")}</code></p>
|
|
23699
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml41(issue.severity)}: ${escapeHtml41(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
23507
23700
|
</article>`).join("")}
|
|
23508
23701
|
</section>
|
|
23509
23702
|
</main>`;
|
|
@@ -23539,7 +23732,7 @@ var defaultRequirements = [
|
|
|
23539
23732
|
"lifecycle-outcome",
|
|
23540
23733
|
"no-session-error"
|
|
23541
23734
|
];
|
|
23542
|
-
var
|
|
23735
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
23543
23736
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
23544
23737
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
23545
23738
|
const value = event.payload[key];
|
|
@@ -23648,10 +23841,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
23648
23841
|
});
|
|
23649
23842
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
23650
23843
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
23651
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
23652
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
23653
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
23654
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
23844
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml42(issue.requirement)}</strong>: ${escapeHtml42(issue.message)}</li>`).join("");
|
|
23845
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml42(outcome)}</span>`).join("");
|
|
23846
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml42(requirement)}</span>`).join("");
|
|
23847
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;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:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml42(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml42(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml42(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml42(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
|
|
23655
23848
|
};
|
|
23656
23849
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
23657
23850
|
query,
|
|
@@ -23717,7 +23910,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
23717
23910
|
"completed",
|
|
23718
23911
|
"failed"
|
|
23719
23912
|
];
|
|
23720
|
-
var
|
|
23913
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23721
23914
|
var loadRouteJson = async (input) => {
|
|
23722
23915
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
23723
23916
|
headers: {
|
|
@@ -23955,10 +24148,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
23955
24148
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
23956
24149
|
const urls = entry?.setup.urls;
|
|
23957
24150
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
23958
|
-
return `<tr><td>${
|
|
24151
|
+
return `<tr><td>${escapeHtml43(carrier.name ?? carrier.provider)}</td><td>${escapeHtml43(carrier.provider)}</td><td><code>${escapeHtml43(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml43(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml43(entry.status)}">${escapeHtml43(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml43(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml43(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml43(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
23959
24152
|
}).join("");
|
|
23960
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
23961
|
-
const snippet =
|
|
24153
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml43(stage)}</code></li>`).join("");
|
|
24154
|
+
const snippet = escapeHtml43(`const phoneAgent = createVoicePhoneAgent({
|
|
23962
24155
|
carriers: [
|
|
23963
24156
|
{
|
|
23964
24157
|
provider: 'twilio',
|
|
@@ -23992,11 +24185,11 @@ app.use(
|
|
|
23992
24185
|
);`);
|
|
23993
24186
|
const checklist = report.carriers.map((carrier) => {
|
|
23994
24187
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
23995
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
23996
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
23997
|
-
return `<article><h3>${
|
|
24188
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml43(issue)}</li>`).join("") ?? "";
|
|
24189
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml43(step)}</li>`).join("") ?? "";
|
|
24190
|
+
return `<article><h3>${escapeHtml43(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
23998
24191
|
}).join("");
|
|
23999
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24192
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml43(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml43(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
|
|
24000
24193
|
};
|
|
24001
24194
|
var createVoicePhoneAgent = (options) => {
|
|
24002
24195
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -25636,7 +25829,7 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
25636
25829
|
};
|
|
25637
25830
|
// src/providerCapabilities.ts
|
|
25638
25831
|
import { Elysia as Elysia44 } from "elysia";
|
|
25639
|
-
var
|
|
25832
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25640
25833
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
25641
25834
|
configured: true,
|
|
25642
25835
|
features: options.features?.[provider],
|
|
@@ -25699,27 +25892,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
25699
25892
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
25700
25893
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
25701
25894
|
const cards = report.capabilities.map((capability) => {
|
|
25702
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
25703
|
-
return `<article class="card ${
|
|
25895
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml44(feature)}</span>`).join("");
|
|
25896
|
+
return `<article class="card ${escapeHtml44(capability.status)}">
|
|
25704
25897
|
<div class="card-header">
|
|
25705
25898
|
<div>
|
|
25706
|
-
<p class="eyebrow">${
|
|
25707
|
-
<h2>${
|
|
25899
|
+
<p class="eyebrow">${escapeHtml44(capability.kind)}</p>
|
|
25900
|
+
<h2>${escapeHtml44(capability.label ?? capability.provider)}</h2>
|
|
25708
25901
|
</div>
|
|
25709
|
-
<strong>${
|
|
25902
|
+
<strong>${escapeHtml44(capability.status)}</strong>
|
|
25710
25903
|
</div>
|
|
25711
|
-
${capability.description ? `<p>${
|
|
25904
|
+
${capability.description ? `<p>${escapeHtml44(capability.description)}</p>` : ""}
|
|
25712
25905
|
<dl>
|
|
25713
25906
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
25714
25907
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
25715
|
-
<div><dt>Model</dt><dd>${
|
|
25908
|
+
<div><dt>Model</dt><dd>${escapeHtml44(capability.model ?? "default")}</dd></div>
|
|
25716
25909
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
25717
25910
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
25718
25911
|
</dl>
|
|
25719
25912
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
25720
25913
|
</article>`;
|
|
25721
25914
|
}).join("");
|
|
25722
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25915
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml44(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
|
|
25723
25916
|
};
|
|
25724
25917
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
25725
25918
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -25758,7 +25951,7 @@ var statusRank4 = {
|
|
|
25758
25951
|
warn: 1,
|
|
25759
25952
|
fail: 2
|
|
25760
25953
|
};
|
|
25761
|
-
var
|
|
25954
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25762
25955
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
25763
25956
|
var uniqueSorted6 = (values) => [
|
|
25764
25957
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -25901,21 +26094,21 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
25901
26094
|
};
|
|
25902
26095
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
25903
26096
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
25904
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
25905
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
26097
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml45(surface.status)}">
|
|
26098
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml45(surface.surface)}</p><h2>${escapeHtml45(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml45(surface.status)}</strong></div>
|
|
25906
26099
|
<dl>
|
|
25907
|
-
<div><dt>Providers</dt><dd>${
|
|
25908
|
-
<div><dt>Fallback</dt><dd>${
|
|
26100
|
+
<div><dt>Providers</dt><dd>${escapeHtml45(surface.providers.join(", ") || "none")}</dd></div>
|
|
26101
|
+
<div><dt>Fallback</dt><dd>${escapeHtml45(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
25909
26102
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
25910
26103
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
25911
26104
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
25912
26105
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
25913
26106
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
25914
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
26107
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml45(surface.fallbackMode || "default")}</dd></div>
|
|
25915
26108
|
</dl>
|
|
25916
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
26109
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml45(issue.status)}</strong> ${escapeHtml45(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
25917
26110
|
</article>`).join("");
|
|
25918
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26111
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml45(title)}</h1><div class="summary"><span class="pill">${escapeHtml45(report.profileId)}</span><span class="pill">${escapeHtml45(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
|
|
25919
26112
|
};
|
|
25920
26113
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
25921
26114
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
@@ -26125,7 +26318,7 @@ var statusRank5 = {
|
|
|
26125
26318
|
warn: 1,
|
|
26126
26319
|
fail: 2
|
|
26127
26320
|
};
|
|
26128
|
-
var
|
|
26321
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26129
26322
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
26130
26323
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
26131
26324
|
var uniqueSorted7 = (values) => [
|
|
@@ -26421,11 +26614,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
26421
26614
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
26422
26615
|
const kindCards = providerKinds.map((kind) => {
|
|
26423
26616
|
const kindReport = report.kinds[kind];
|
|
26424
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
26617
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml46(metric.label)}</dt><dd>${escapeHtml46(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml46(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
26425
26618
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
26426
|
-
return `<article class="${
|
|
26619
|
+
return `<article class="${escapeHtml46(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml46(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml46(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
26427
26620
|
}).join("");
|
|
26428
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
26621
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml46(issue.status)}"><strong>${escapeHtml46(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml46(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
26429
26622
|
const snippet = `createVoiceProviderSloRoutes({
|
|
26430
26623
|
store: runtimeStorage.traces,
|
|
26431
26624
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -26435,7 +26628,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
26435
26628
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
26436
26629
|
}
|
|
26437
26630
|
})`;
|
|
26438
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26631
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{background:#101318;color:#f8f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,article,.primitive{background:#171b22;border:1px solid #2c3340;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.2),rgba(245,158,11,.12))}.eyebrow{color:#7dd3fc;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.9rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status,article h2 span{border:1px solid #475569;border-radius:999px;display:inline-flex;font-size:.85rem;padding:6px 10px}.pass{border-color:rgba(34,197,94,.65)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}dt{color:#cbd5e1;font-size:.78rem;text-transform:uppercase}dd{font-size:1.7rem;font-weight:900;margin:0}small{color:#a8b3c2}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#101318;border:1px solid #2c3340;border-radius:16px;padding:12px}li span{color:#cbd5e1;display:block;margin-top:4px}.primitive{background:#11161d}.primitive code{color:#bae6fd}.primitive pre{background:#070b10;border:1px solid #243041;border-radius:16px;color:#e0f2fe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Provider latency and fallback proof</p><h1>${escapeHtml46(title)}</h1><p class="status ${escapeHtml46(report.status)}">${escapeHtml46(report.status)}</p><p>${report.events} provider routing event(s), ${report.eventsWithLatency} latency sample(s).</p></section><section class="grid">${kindCards}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderSloRoutes(...)</code> turns provider speed into release evidence</h2><p>Pair this report with production readiness so LLM/STT/TTS latency, timeout, fallback, and unresolved error regressions block deploys.</p><pre><code>${escapeHtml46(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
26439
26632
|
};
|
|
26440
26633
|
var createVoiceProviderSloRoutes = (options) => {
|
|
26441
26634
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -27275,7 +27468,7 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
27275
27468
|
|
|
27276
27469
|
// src/opsRecovery.ts
|
|
27277
27470
|
import { Elysia as Elysia48 } from "elysia";
|
|
27278
|
-
var
|
|
27471
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27279
27472
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
27280
27473
|
var hrefForSession = (value, sessionId) => {
|
|
27281
27474
|
if (typeof value === "function") {
|
|
@@ -27489,13 +27682,13 @@ ${failedSessions || "None."}
|
|
|
27489
27682
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
27490
27683
|
`;
|
|
27491
27684
|
};
|
|
27492
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
27685
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml47(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml47(label)}</span><strong>not configured</strong></article>`;
|
|
27493
27686
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
27494
27687
|
const title = options.title ?? "Voice Ops Recovery";
|
|
27495
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
27496
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
27497
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
27498
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27688
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml47(issue.severity)}</td><td><code>${escapeHtml47(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml47(issue.href)}">${escapeHtml47(issue.label)}</a>` : escapeHtml47(issue.label)}</td><td>${escapeHtml47(String(issue.value ?? ""))}</td><td>${escapeHtml47(issue.detail ?? "")}</td></tr>`).join("");
|
|
27689
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml47(provider.provider)}</td><td>${escapeHtml47(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml47(provider.lastError ?? "")}</td></tr>`).join("");
|
|
27690
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml47(session.operationsRecordHref)}">${escapeHtml47(session.sessionId)}</a>` : escapeHtml47(session.sessionId)}${session.provider ? ` via ${escapeHtml47(session.provider)}` : ""}${session.error ? `: ${escapeHtml47(session.error)}` : ""}</li>`).join("");
|
|
27691
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml47(title)}</h1><p><span class="status">${escapeHtml47(report.status)}</span> Checked ${escapeHtml47(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml47(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
|
|
27499
27692
|
};
|
|
27500
27693
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
27501
27694
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
@@ -27542,7 +27735,7 @@ import { Elysia as Elysia50 } from "elysia";
|
|
|
27542
27735
|
|
|
27543
27736
|
// src/traceTimeline.ts
|
|
27544
27737
|
import { Elysia as Elysia49 } from "elysia";
|
|
27545
|
-
var
|
|
27738
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27546
27739
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
27547
27740
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
27548
27741
|
var firstString4 = (payload, keys) => {
|
|
@@ -27725,17 +27918,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
27725
27918
|
};
|
|
27726
27919
|
};
|
|
27727
27920
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
27728
|
-
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${
|
|
27921
|
+
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${escapeHtml48(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs4(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs4(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
27729
27922
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
27730
|
-
const events = session.events.map((event) => `<tr class="${
|
|
27731
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
27732
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
27733
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27923
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml48(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml48(event.type)}</td><td>${escapeHtml48(event.label)}</td><td>${escapeHtml48(event.provider ?? "")}</td><td>${escapeHtml48(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
27924
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml48(issue.severity)}">${escapeHtml48(issue.code)}: ${escapeHtml48(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
27925
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml48(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
27926
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml48(session.sessionId)}</h1><p class="status ${escapeHtml48(session.status)}">${escapeHtml48(session.status)}</p>${supportLinks}</header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs4(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards2(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
27734
27927
|
};
|
|
27735
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
27928
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml48(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml48(session.operationsRecordHref)}">${escapeHtml48(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml48(session.sessionId)}</a>`}</td><td>${escapeHtml48(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs4(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml48(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
27736
27929
|
var timelineCSS = "body{background:#0f1318;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}a{color:#fbbf24}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.metrics,.providers{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.providers article{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span,dt,.muted{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 0}dd{font-weight:800;margin:4px 0 0}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}section{margin-top:28px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}";
|
|
27737
27930
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
27738
|
-
const snippet =
|
|
27931
|
+
const snippet = escapeHtml48(`const traceStore = createVoiceTraceSinkStore({
|
|
27739
27932
|
store: runtimeStorage.traces,
|
|
27740
27933
|
sinks: [
|
|
27741
27934
|
createVoiceTraceHTTPSink({
|
|
@@ -27761,7 +27954,7 @@ app.use(
|
|
|
27761
27954
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
27762
27955
|
})
|
|
27763
27956
|
);`);
|
|
27764
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27957
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(options.title ?? "Voice Trace Timelines")}</title><style>${timelineCSS}.primitive{background:#181f27;border:1px solid #334155;border-radius:20px;margin:20px 0;padding:18px}.primitive p{line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #2b3642;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.primitive code{color:#bfdbfe}</style></head><body><main><header><p class="eyebrow">Self-hosted voice debugging</p><h1>${escapeHtml48(options.title ?? "Voice Trace Timelines")}</h1><p class="muted">Per-call event timelines with provider latency, fallback, timeout, handoff, and error context.</p></header><section class="metrics"><article><span>Sessions</span><strong>${String(report.total)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article><article><span>Warnings</span><strong>${String(report.warnings)}</strong></article></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTraceTimelineRoutes(...)</code> makes traces the proof backbone</h2><p class="muted">Mount trace timelines from the same trace store used by readiness, simulations, provider recovery, delivery sinks, and phone-agent smoke proof.</p><pre><code>${snippet}</code></pre></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
27765
27958
|
};
|
|
27766
27959
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
27767
27960
|
const path = options.path ?? "/api/voice-traces";
|
|
@@ -28397,7 +28590,7 @@ var renderVoiceFailureReplayMarkdown = (report) => {
|
|
|
28397
28590
|
].join(`
|
|
28398
28591
|
`);
|
|
28399
28592
|
};
|
|
28400
|
-
var
|
|
28593
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28401
28594
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
28402
28595
|
var outcomeLabels = (outcome) => [
|
|
28403
28596
|
outcome.complete ? "complete" : undefined,
|
|
@@ -28507,18 +28700,18 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
28507
28700
|
`);
|
|
28508
28701
|
};
|
|
28509
28702
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
28510
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
28511
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
28512
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
28703
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml49(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs5(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
|
|
28704
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml49(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml49(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml49(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml49(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
28705
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml49(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml49(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml49(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml49(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml49(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml49(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml49(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml49(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
28513
28706
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
28514
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
28515
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
28516
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
28517
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
28518
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
28707
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml49(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml49(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml49(handoff.status ?? "")}</span><p>${escapeHtml49(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
28708
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml49(tool.toolName ?? "tool")}</strong> <span>${escapeHtml49(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml49(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
28709
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml49(review.title)}</strong> <span>${escapeHtml49(review.summary.outcome ?? "")}</span><p>${escapeHtml49(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
28710
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml49(task.title)}</strong> <span>${escapeHtml49(task.status)}</span><p>${escapeHtml49(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
28711
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml49(event.type)}</strong> <span>${escapeHtml49(event.deliveryStatus ?? "local")}</span><p>${escapeHtml49(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
28519
28712
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
28520
28713
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
28521
|
-
return `<li><strong>assistant.guardrail ${
|
|
28714
|
+
return `<li><strong>assistant.guardrail ${escapeHtml49(decision.stage ?? "unknown")}</strong> <span>${escapeHtml49(decision.status ?? "")}</span><p>Allowed: ${escapeHtml49(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml49(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml49(decision.turnId)}` : ""}</p><p>${escapeHtml49(findings)}</p></li>`;
|
|
28522
28715
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
28523
28716
|
const telephonyMedia = record.telephonyMedia.events.length ? record.telephonyMedia.events.slice(0, 50).map((event) => {
|
|
28524
28717
|
const details = [
|
|
@@ -28529,9 +28722,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
28529
28722
|
event.sequenceNumber ? `Seq: ${event.sequenceNumber}` : undefined,
|
|
28530
28723
|
`Audio bytes: ${String(event.audioBytes)}`
|
|
28531
28724
|
].filter((detail) => typeof detail === "string");
|
|
28532
|
-
return `<li><strong>${
|
|
28725
|
+
return `<li><strong>${escapeHtml49(event.event)}</strong> <span>${escapeHtml49(new Date(event.at).toLocaleString())}</span><p>${escapeHtml49(details.join(" \xB7 "))}</p></li>`;
|
|
28533
28726
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
28534
|
-
const snippet =
|
|
28727
|
+
const snippet = escapeHtml49(`app.use(
|
|
28535
28728
|
createVoiceOperationsRecordRoutes({
|
|
28536
28729
|
audit: auditStore,
|
|
28537
28730
|
integrationEvents: opsEvents,
|
|
@@ -28545,9 +28738,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
28545
28738
|
tasks: opsTasks
|
|
28546
28739
|
})
|
|
28547
28740
|
);`);
|
|
28548
|
-
const incidentMarkdown =
|
|
28549
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
28550
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
28741
|
+
const incidentMarkdown = escapeHtml49(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
28742
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml49(options.incidentHref)}">Download incident.md</a>` : "";
|
|
28743
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(options.title ?? "Voice Operations Record")}</title><style>body{background:#101417;color:#f9f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.eyebrow{color:#fbbf24;font-size:.8rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.card,.primitive{background:#182025;border:1px solid #2d3a43;border-radius:20px;padding:16px}.card span,.muted,.label{color:#a9b4bd}.label{display:block;font-size:.72rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.card strong{display:block;font-size:2rem}section{margin-top:28px}article{display:grid;gap:8px}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#182025;border:1px solid #2d3a43;border-radius:16px;padding:14px}pre{background:#080d10;border:1px solid #2d3a43;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}.hero-actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.two-column{display:grid;gap:18px;grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr)}@media(max-width:860px){main{padding:20px}.two-column{grid-template-columns:1fr}}</style></head><body><main><p class="eyebrow">Call log replacement</p><h1>${escapeHtml49(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml49(record.status)}">${escapeHtml49(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</a><a href="#telephony-media">Telephony media</a><a href="#guardrails">Guardrails</a><a href="#incident-handoff">Incident handoff</a>${incidentLink}</div><section class="grid"><div class="card"><span>Events</span><strong>${String(record.summary.eventCount)}</strong></div><div class="card"><span>Turns</span><strong>${String(record.summary.turnCount)}</strong></div><div class="card"><span>Errors</span><strong>${String(record.summary.errorCount)}</strong></div><div class="card"><span>Duration</span><strong>${formatMs5(record.summary.callDurationMs)}</strong></div><div class="card"><span>Provider recovery</span><strong>${escapeHtml49(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</span></div><div class="card"><span>Telephony media</span><strong>${String(record.telephonyMedia.media)}</strong><span>${String(record.telephonyMedia.inbound)} inbound / ${String(record.telephonyMedia.outbound)} outbound / ${String(record.telephonyMedia.clears)} clears</span></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div></section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="telephony-media"><h2>Telephony Media</h2><p class="muted">Live <code>client.telephony_media</code> stream lifecycle evidence attached to this session. Carriers: ${escapeHtml49(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml49(record.telephonyMedia.streamIds.join(", ") || "none")}. Inbound: ${String(record.telephonyMedia.inbound)}. Outbound: ${String(record.telephonyMedia.outbound)}. Marks: ${String(record.telephonyMedia.marks)}. Clears: ${String(record.telephonyMedia.clears)}.</p><ul>${telephonyMedia}</ul></section><section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, media streams, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
28551
28744
|
};
|
|
28552
28745
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
28553
28746
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
@@ -30091,7 +30284,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
30091
30284
|
};
|
|
30092
30285
|
|
|
30093
30286
|
// src/productionReadiness.ts
|
|
30094
|
-
var
|
|
30287
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30095
30288
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
30096
30289
|
var readinessGateCodes = {
|
|
30097
30290
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -31729,25 +31922,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
31729
31922
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
31730
31923
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
31731
31924
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
31732
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
31733
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
31925
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml50(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
31926
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml50(report.profile.name)}</h2><p>${escapeHtml50(report.profile.description)}</p><p>${escapeHtml50(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml50(surface.href)}">${escapeHtml50(surface.label)}</a>` : escapeHtml50(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
31734
31927
|
const checks = report.checks.map((check, index) => {
|
|
31735
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
31736
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
31737
|
-
return `<article class="check ${
|
|
31928
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml50(action.href)}">${escapeHtml50(action.label)}</button>` : `<a href="${escapeHtml50(action.href)}">${escapeHtml50(action.label)}</a>`).join("");
|
|
31929
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml50(check.status)}: observed ${escapeHtml50(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml50(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml50(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml50(check.gateExplanation.unit)}` : ""}. ${escapeHtml50(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml50(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
31930
|
+
return `<article class="check ${escapeHtml50(check.status)}">
|
|
31738
31931
|
<div>
|
|
31739
|
-
<span>${
|
|
31740
|
-
<h2>${
|
|
31741
|
-
${check.detail ? `<p>${
|
|
31932
|
+
<span>${escapeHtml50(check.status.toUpperCase())}</span>
|
|
31933
|
+
<h2>${escapeHtml50(check.label)}</h2>
|
|
31934
|
+
${check.detail ? `<p>${escapeHtml50(check.detail)}</p>` : ""}
|
|
31742
31935
|
${explanation}
|
|
31743
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
31936
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml50(check.proofSource.href)}">${escapeHtml50(check.proofSource.sourceLabel)}</a>` : escapeHtml50(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml50(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
31744
31937
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
31745
31938
|
</div>
|
|
31746
|
-
<strong>${
|
|
31747
|
-
${check.href ? `<a href="${
|
|
31939
|
+
<strong>${escapeHtml50(String(check.value ?? check.status))}</strong>
|
|
31940
|
+
${check.href ? `<a href="${escapeHtml50(check.href)}">Open surface</a>` : ""}
|
|
31748
31941
|
</article>`;
|
|
31749
31942
|
}).join("");
|
|
31750
|
-
const snippet =
|
|
31943
|
+
const snippet = escapeHtml50(`createVoiceProductionReadinessRoutes({
|
|
31751
31944
|
htmlPath: '/production-readiness',
|
|
31752
31945
|
path: '/api/production-readiness',
|
|
31753
31946
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -31763,7 +31956,7 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
31763
31956
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
31764
31957
|
store: traceStore
|
|
31765
31958
|
});`);
|
|
31766
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31959
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml50(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml50(report.status)}">Overall: ${escapeHtml50(report.status.toUpperCase())}</p><p>Checked ${escapeHtml50(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
|
|
31767
31960
|
};
|
|
31768
31961
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
31769
31962
|
const path = options.path ?? "/api/production-readiness";
|
|
@@ -31818,7 +32011,7 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
31818
32011
|
};
|
|
31819
32012
|
// src/voiceMonitoring.ts
|
|
31820
32013
|
import { Elysia as Elysia53 } from "elysia";
|
|
31821
|
-
var
|
|
32014
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31822
32015
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
31823
32016
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
31824
32017
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -32071,14 +32264,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
32071
32264
|
};
|
|
32072
32265
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
32073
32266
|
const title = options.title ?? "Voice Monitors";
|
|
32074
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
32075
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
32076
|
-
const snippet =
|
|
32267
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml51(run.label)}</td><td class="${escapeHtml51(run.status)}">${escapeHtml51(run.status)}</td><td>${escapeHtml51(run.severity)}</td><td>${escapeHtml51(String(run.value ?? ""))}</td><td>${escapeHtml51(String(run.threshold ?? ""))}</td><td>${escapeHtml51(run.detail ?? "")}</td></tr>`).join("");
|
|
32268
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml51(issue.label)}</strong> <span class="${escapeHtml51(issue.status)}">${escapeHtml51(issue.status)}</span> ${escapeHtml51(issue.detail ?? "")}</li>`).join("");
|
|
32269
|
+
const snippet = escapeHtml51(`app.use(createVoiceMonitorRoutes({
|
|
32077
32270
|
evidence,
|
|
32078
32271
|
issueStore,
|
|
32079
32272
|
monitors: [defineVoiceMonitor(...)]
|
|
32080
32273
|
}));`);
|
|
32081
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32274
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml51(title)}</h1><p class="pill ${escapeHtml51(report.status)}">Status: ${escapeHtml51(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
32082
32275
|
};
|
|
32083
32276
|
var actorFromRequest = async (request) => {
|
|
32084
32277
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -32526,7 +32719,7 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
32526
32719
|
};
|
|
32527
32720
|
// src/providerStackRecommendations.ts
|
|
32528
32721
|
import { Elysia as Elysia54 } from "elysia";
|
|
32529
|
-
var
|
|
32722
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32530
32723
|
var profileProviderPriorities = {
|
|
32531
32724
|
"meeting-recorder": {
|
|
32532
32725
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -32845,17 +33038,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
32845
33038
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
32846
33039
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
32847
33040
|
const rows = report.rows.map((row) => {
|
|
32848
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
32849
|
-
return `<article class="row ${
|
|
33041
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml52(check.status)}"><strong>${escapeHtml52(check.label)}</strong><span>${escapeHtml52(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml52(check.remediation.href)}">${escapeHtml52(check.remediation.label)}</a>` : escapeHtml52(check.remediation.label)}: ${escapeHtml52(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
33042
|
+
return `<article class="row ${escapeHtml52(row.status)}">
|
|
32850
33043
|
<div>
|
|
32851
|
-
<p class="eyebrow">${
|
|
32852
|
-
<h2>${
|
|
32853
|
-
<p class="status ${
|
|
33044
|
+
<p class="eyebrow">${escapeHtml52(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
33045
|
+
<h2>${escapeHtml52(row.provider)}</h2>
|
|
33046
|
+
<p class="status ${escapeHtml52(row.status)}">${escapeHtml52(row.status.toUpperCase())}</p>
|
|
32854
33047
|
</div>
|
|
32855
33048
|
<ul>${checks}</ul>
|
|
32856
33049
|
</article>`;
|
|
32857
33050
|
}).join("");
|
|
32858
|
-
const snippet =
|
|
33051
|
+
const snippet = escapeHtml52(`const providerContracts = () =>
|
|
32859
33052
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
32860
33053
|
env: process.env,
|
|
32861
33054
|
providers: {
|
|
@@ -32876,7 +33069,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
32876
33069
|
providerContractMatrix: () =>
|
|
32877
33070
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
32878
33071
|
});`);
|
|
32879
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33072
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml52(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
|
|
32880
33073
|
};
|
|
32881
33074
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
32882
33075
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -33044,7 +33237,7 @@ var DEFAULT_LINKS = [
|
|
|
33044
33237
|
label: "Handoffs"
|
|
33045
33238
|
}
|
|
33046
33239
|
];
|
|
33047
|
-
var
|
|
33240
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33048
33241
|
var countProviderStatuses = (providers) => {
|
|
33049
33242
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
33050
33243
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -33113,16 +33306,16 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
33113
33306
|
trace
|
|
33114
33307
|
};
|
|
33115
33308
|
};
|
|
33116
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
33309
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml53(input.label)}</span><strong>${escapeHtml53(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml53(input.status)}">${escapeHtml53(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml53(input.href)}">Open</a>` : ""}</article>`;
|
|
33117
33310
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
33118
33311
|
const links = report.links.map((link) => `<article class="surface">
|
|
33119
|
-
<div><h2>${
|
|
33120
|
-
<p><a href="${
|
|
33312
|
+
<div><h2>${escapeHtml53(link.label)}</h2>${link.description ? `<p>${escapeHtml53(link.description)}</p>` : ""}</div>
|
|
33313
|
+
<p><a href="${escapeHtml53(link.href)}">Open ${escapeHtml53(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml53(link.statusHref)}">Status</a>` : ""}</p>
|
|
33121
33314
|
</article>`).join("");
|
|
33122
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
33123
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
33315
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml53(session.sessionId)}</td><td>${escapeHtml53(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml53(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
33316
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml53(event.kind)}</td><td>${escapeHtml53(event.provider ?? "unknown")}</td><td>${escapeHtml53(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml53(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
33124
33317
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
33125
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33318
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml53(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml53(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
|
|
33126
33319
|
};
|
|
33127
33320
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
33128
33321
|
const path = options.path ?? "/ops-console";
|
|
@@ -33546,14 +33739,14 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
33546
33739
|
};
|
|
33547
33740
|
// src/opsStatusRoutes.ts
|
|
33548
33741
|
import { Elysia as Elysia57 } from "elysia";
|
|
33549
|
-
var
|
|
33742
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33550
33743
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
33551
33744
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
33552
33745
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
33553
33746
|
const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("auditTotal" in surface) ? `${surface.auditTotal + surface.traceTotal} deliveries` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
|
|
33554
|
-
return `<article class="surface ${
|
|
33747
|
+
return `<article class="surface ${escapeHtml54(surface.status)}"><span>${escapeHtml54(surface.status.toUpperCase())}</span><h2>${escapeHtml54(key)}</h2><strong>${escapeHtml54(value)}</strong></article>`;
|
|
33555
33748
|
}).join("");
|
|
33556
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33749
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(title)}</title><style>body{background:#0d141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.surfaces{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.surface{background:#151d26;border:1px solid #283544;border-radius:20px;padding:18px}.surface span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.surface strong{font-size:1.5rem}.pass{border-color:rgba(34,197,94,.55)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Ops status</p><h1>${escapeHtml54(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml54(report.status)}">Overall: ${escapeHtml54(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
|
|
33557
33750
|
};
|
|
33558
33751
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
33559
33752
|
const path = options.path ?? "/api/voice/ops-status";
|
|
@@ -33991,7 +34184,7 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
33991
34184
|
};
|
|
33992
34185
|
// src/traceDeliveryRoutes.ts
|
|
33993
34186
|
import { Elysia as Elysia58 } from "elysia";
|
|
33994
|
-
var
|
|
34187
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33995
34188
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
33996
34189
|
var getNumber12 = (value) => {
|
|
33997
34190
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -34072,14 +34265,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
34072
34265
|
if (entries.length === 0) {
|
|
34073
34266
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
34074
34267
|
}
|
|
34075
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
34268
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml55(sinkId)}</strong>: ${escapeHtml55(result.status)}${result.deliveredTo ? ` to ${escapeHtml55(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml55(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
34076
34269
|
};
|
|
34077
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
34270
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml55(event.type)} <small>${escapeHtml55(event.id)}</small>${event.sessionId ? ` session=${escapeHtml55(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
34078
34271
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
34079
34272
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
34080
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
34081
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
34082
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34273
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml55(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
34274
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml55(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml55(delivery.deliveryStatus)}</span><h2>${escapeHtml55(delivery.id)}</h2><p>${escapeHtml55(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml55(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml55(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
34275
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#0f1318;color:#f4efe1;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(14,165,233,.14));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#86efac;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.grid{display:grid;gap:12px;grid-template-columns:repeat(4,1fr);margin-bottom:16px}.grid article,.delivery{background:#151b22;border:1px solid #26313d;border-radius:22px;padding:18px}.grid span,.delivery span{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.grid strong{display:block;font-size:2rem}.deliveries{display:grid;gap:14px}.delivery.failed{border-color:rgba(239,68,68,.75)}.delivery.pending{border-color:rgba(245,158,11,.7)}.delivery.delivered{border-color:rgba(34,197,94,.55)}.delivery.skipped{border-color:rgba(148,163,184,.6)}.head{align-items:start;display:flex;gap:14px;justify-content:space-between}.delivery h2{font-size:1.05rem;margin:.3rem 0;overflow-wrap:anywhere}.delivery h3{margin:1rem 0 .3rem}.delivery p,.delivery li{color:#c8d0d8}.error{color:#fecaca!important}button{background:#86efac;border:0;border-radius:999px;color:#07111f;cursor:pointer;font-weight:900;margin-top:12px;padding:10px 14px}@media(max-width:760px){main{padding:20px}.grid{grid-template-columns:1fr 1fr}.head{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Trace export health</p><h1>${escapeHtml55(title)}</h1><p>Checked ${escapeHtml55(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid3(report)}<section class="deliveries">${rows || "<p>No trace deliveries match this filter.</p>"}</section></main></body></html>`;
|
|
34083
34276
|
};
|
|
34084
34277
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
34085
34278
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -36191,6 +36384,8 @@ export {
|
|
|
36191
36384
|
renderVoiceProviderDecisionTraceHTML,
|
|
36192
36385
|
renderVoiceProviderContractMatrixHTML,
|
|
36193
36386
|
renderVoiceProviderCapabilityHTML,
|
|
36387
|
+
renderVoiceProofTrendRecommendationMarkdown,
|
|
36388
|
+
renderVoiceProofTrendRecommendationHTML,
|
|
36194
36389
|
renderVoiceProductionReadinessHTML,
|
|
36195
36390
|
renderVoicePostCallAnalysisMarkdown,
|
|
36196
36391
|
renderVoicePhoneAgentProductionSmokeHTML,
|
|
@@ -36438,6 +36633,7 @@ export {
|
|
|
36438
36633
|
createVoiceProviderCapabilityJSONHandler,
|
|
36439
36634
|
createVoiceProviderCapabilityHTMLHandler,
|
|
36440
36635
|
createVoiceProofTrendRoutes,
|
|
36636
|
+
createVoiceProofTrendRecommendationRoutes,
|
|
36441
36637
|
createVoiceProductionReadinessRoutes,
|
|
36442
36638
|
createVoicePostgresTraceSinkDeliveryStore,
|
|
36443
36639
|
createVoicePostgresTraceEventStore,
|
|
@@ -36632,6 +36828,7 @@ export {
|
|
|
36632
36828
|
buildVoiceProviderDecisionTraceReport,
|
|
36633
36829
|
buildVoiceProviderContractMatrix,
|
|
36634
36830
|
buildVoiceProofTrendReport,
|
|
36831
|
+
buildVoiceProofTrendRecommendationReport,
|
|
36635
36832
|
buildVoiceProductionReadinessReport,
|
|
36636
36833
|
buildVoiceProductionReadinessGate,
|
|
36637
36834
|
buildVoicePostCallAnalysisReport,
|