@absolutejs/voice 0.0.22-beta.300 → 0.0.22-beta.301
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/competitiveCoverage.d.ts +141 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +608 -372
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12451,8 +12451,238 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
12451
12451
|
});
|
|
12452
12452
|
return routes;
|
|
12453
12453
|
};
|
|
12454
|
-
// src/
|
|
12454
|
+
// src/competitiveCoverage.ts
|
|
12455
12455
|
import { Elysia as Elysia14 } from "elysia";
|
|
12456
|
+
var escapeHtml16 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12457
|
+
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
12458
|
+
var resolveSurfaceStatus = (surface) => {
|
|
12459
|
+
if (surface.status)
|
|
12460
|
+
return surface.status;
|
|
12461
|
+
if (surface.coverage === "missing")
|
|
12462
|
+
return "fail";
|
|
12463
|
+
if (surface.coverage === "partial")
|
|
12464
|
+
return "warn";
|
|
12465
|
+
if (surface.depth === "lag" && surface.coverage !== "intentional-gap")
|
|
12466
|
+
return "warn";
|
|
12467
|
+
if ((surface.evidence ?? []).some((evidence) => evidence.status === "fail")) {
|
|
12468
|
+
return "fail";
|
|
12469
|
+
}
|
|
12470
|
+
if ((surface.evidence ?? []).some((evidence) => evidence.status === "warn")) {
|
|
12471
|
+
return "warn";
|
|
12472
|
+
}
|
|
12473
|
+
return "pass";
|
|
12474
|
+
};
|
|
12475
|
+
var buildVoiceCompetitiveCoverageReport = (input) => {
|
|
12476
|
+
const surfaces = input.surfaces.map((surface) => ({
|
|
12477
|
+
...surface,
|
|
12478
|
+
status: resolveSurfaceStatus(surface)
|
|
12479
|
+
}));
|
|
12480
|
+
const issues = [];
|
|
12481
|
+
for (const surface of surfaces) {
|
|
12482
|
+
const evidence = surface.evidence ?? [];
|
|
12483
|
+
const missingRequiredEvidence = evidence.filter((item) => item.required && item.status !== "pass");
|
|
12484
|
+
for (const item of missingRequiredEvidence) {
|
|
12485
|
+
issues.push({
|
|
12486
|
+
code: "required-evidence-not-passing",
|
|
12487
|
+
message: `Required evidence is not passing: ${item.name}.`,
|
|
12488
|
+
severity: "error",
|
|
12489
|
+
surface: surface.surface
|
|
12490
|
+
});
|
|
12491
|
+
}
|
|
12492
|
+
if (surface.coverage === "missing") {
|
|
12493
|
+
issues.push({
|
|
12494
|
+
code: "surface-missing",
|
|
12495
|
+
message: `Competitive surface is missing: ${surface.surface}.`,
|
|
12496
|
+
severity: "error",
|
|
12497
|
+
surface: surface.surface
|
|
12498
|
+
});
|
|
12499
|
+
}
|
|
12500
|
+
if (surface.status === "warn") {
|
|
12501
|
+
issues.push({
|
|
12502
|
+
code: "surface-warning",
|
|
12503
|
+
message: `Competitive surface needs depth work: ${surface.surface}.`,
|
|
12504
|
+
severity: "warning",
|
|
12505
|
+
surface: surface.surface
|
|
12506
|
+
});
|
|
12507
|
+
}
|
|
12508
|
+
}
|
|
12509
|
+
const failed = surfaces.filter((surface) => surface.status === "fail").length;
|
|
12510
|
+
const warned = surfaces.filter((surface) => surface.status === "warn").length;
|
|
12511
|
+
const status = failed > 0 ? "fail" : warned > 0 ? "warn" : "pass";
|
|
12512
|
+
return {
|
|
12513
|
+
generatedAt: input.generatedAt ?? new Date().toISOString(),
|
|
12514
|
+
issues,
|
|
12515
|
+
marketCoverageEstimate: input.marketCoverageEstimate ?? "93-95%",
|
|
12516
|
+
notes: input.notes ?? [],
|
|
12517
|
+
ok: status !== "fail",
|
|
12518
|
+
source: input.source,
|
|
12519
|
+
status,
|
|
12520
|
+
summary: {
|
|
12521
|
+
advantage: surfaces.filter((surface) => surface.depth === "advantage").length,
|
|
12522
|
+
covered: surfaces.filter((surface) => surface.coverage === "covered").length,
|
|
12523
|
+
failed,
|
|
12524
|
+
intentionalGaps: surfaces.filter((surface) => surface.coverage === "intentional-gap").length,
|
|
12525
|
+
missing: surfaces.filter((surface) => surface.coverage === "missing").length,
|
|
12526
|
+
parity: surfaces.filter((surface) => surface.depth === "parity").length,
|
|
12527
|
+
passed: surfaces.filter((surface) => surface.status === "pass").length,
|
|
12528
|
+
surfaces: surfaces.length,
|
|
12529
|
+
warned
|
|
12530
|
+
},
|
|
12531
|
+
surfaces,
|
|
12532
|
+
vapiCoverageEstimate: input.vapiCoverageEstimate ?? "99.8%"
|
|
12533
|
+
};
|
|
12534
|
+
};
|
|
12535
|
+
var evaluateVoiceCompetitiveCoverage = (report, input = {}) => {
|
|
12536
|
+
const issues = [];
|
|
12537
|
+
const surfaces = report.surfaces.map((surface) => surface.surface).sort();
|
|
12538
|
+
const missing = report.summary.missing;
|
|
12539
|
+
const failed = report.summary.failed;
|
|
12540
|
+
const evidenceNames = new Set(report.surfaces.flatMap((surface) => (surface.evidence ?? []).map((evidence) => evidence.name)));
|
|
12541
|
+
if ((input.requirePass ?? false) && report.status !== "pass") {
|
|
12542
|
+
issues.push(`Expected competitive coverage to pass, found ${report.status}.`);
|
|
12543
|
+
}
|
|
12544
|
+
if (input.minSurfaces !== undefined && report.summary.surfaces < input.minSurfaces) {
|
|
12545
|
+
issues.push(`Expected at least ${String(input.minSurfaces)} competitive surfaces, found ${String(report.summary.surfaces)}.`);
|
|
12546
|
+
}
|
|
12547
|
+
if (input.minAdvantageSurfaces !== undefined && report.summary.advantage < input.minAdvantageSurfaces) {
|
|
12548
|
+
issues.push(`Expected at least ${String(input.minAdvantageSurfaces)} advantage surfaces, found ${String(report.summary.advantage)}.`);
|
|
12549
|
+
}
|
|
12550
|
+
if (input.maxFailedSurfaces !== undefined && failed > input.maxFailedSurfaces) {
|
|
12551
|
+
issues.push(`Expected at most ${String(input.maxFailedSurfaces)} failing competitive surfaces, found ${String(failed)}.`);
|
|
12552
|
+
}
|
|
12553
|
+
if (input.maxMissingSurfaces !== undefined && missing > input.maxMissingSurfaces) {
|
|
12554
|
+
issues.push(`Expected at most ${String(input.maxMissingSurfaces)} missing competitive surfaces, found ${String(missing)}.`);
|
|
12555
|
+
}
|
|
12556
|
+
for (const surface of input.requiredSurfaces ?? []) {
|
|
12557
|
+
if (!surfaces.includes(surface)) {
|
|
12558
|
+
issues.push(`Missing competitive surface: ${surface}.`);
|
|
12559
|
+
}
|
|
12560
|
+
}
|
|
12561
|
+
for (const evidence of input.requiredEvidence ?? []) {
|
|
12562
|
+
if (!evidenceNames.has(evidence)) {
|
|
12563
|
+
issues.push(`Missing competitive evidence: ${evidence}.`);
|
|
12564
|
+
}
|
|
12565
|
+
}
|
|
12566
|
+
if (input.requireOperationsRecordLinks) {
|
|
12567
|
+
for (const surface of report.surfaces) {
|
|
12568
|
+
if (surface.coverage !== "intentional-gap" && surface.operationsRecord !== "linked" && surface.operationsRecord !== "not-applicable") {
|
|
12569
|
+
issues.push(`Competitive surface does not have operations-record proof: ${surface.surface}.`);
|
|
12570
|
+
}
|
|
12571
|
+
}
|
|
12572
|
+
}
|
|
12573
|
+
if (input.requireReadinessGates) {
|
|
12574
|
+
for (const surface of report.surfaces) {
|
|
12575
|
+
if (surface.coverage !== "intentional-gap" && surface.readinessGate !== "present" && surface.readinessGate !== "not-applicable") {
|
|
12576
|
+
issues.push(`Competitive surface does not have readiness-gate proof: ${surface.surface}.`);
|
|
12577
|
+
}
|
|
12578
|
+
}
|
|
12579
|
+
}
|
|
12580
|
+
return {
|
|
12581
|
+
advantage: report.summary.advantage,
|
|
12582
|
+
failed,
|
|
12583
|
+
issues,
|
|
12584
|
+
missing,
|
|
12585
|
+
ok: issues.length === 0,
|
|
12586
|
+
status: report.status,
|
|
12587
|
+
surfaces,
|
|
12588
|
+
total: report.summary.surfaces
|
|
12589
|
+
};
|
|
12590
|
+
};
|
|
12591
|
+
var assertVoiceCompetitiveCoverage = (report, input = {}) => {
|
|
12592
|
+
const assertion = evaluateVoiceCompetitiveCoverage(report, input);
|
|
12593
|
+
if (!assertion.ok) {
|
|
12594
|
+
throw new Error(`Voice competitive coverage assertion failed: ${assertion.issues.join(" ")}`);
|
|
12595
|
+
}
|
|
12596
|
+
return assertion;
|
|
12597
|
+
};
|
|
12598
|
+
var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive Coverage") => [
|
|
12599
|
+
`# ${title}`,
|
|
12600
|
+
"",
|
|
12601
|
+
`- Status: ${report.status}`,
|
|
12602
|
+
`- Vapi-style coverage: ${report.vapiCoverageEstimate}`,
|
|
12603
|
+
`- Broader market coverage: ${report.marketCoverageEstimate}`,
|
|
12604
|
+
`- Surfaces: ${String(report.summary.surfaces)}`,
|
|
12605
|
+
`- Advantage surfaces: ${String(report.summary.advantage)}`,
|
|
12606
|
+
`- Parity surfaces: ${String(report.summary.parity)}`,
|
|
12607
|
+
`- Intentional gaps: ${String(report.summary.intentionalGaps)}`,
|
|
12608
|
+
"",
|
|
12609
|
+
"| Surface | Coverage | Depth | Status | Operations record | Readiness gate | Competitors | Next move |",
|
|
12610
|
+
"| --- | --- | --- | --- | --- | --- | --- | --- |",
|
|
12611
|
+
...report.surfaces.map((surface) => `| ${escapeMarkdown(surface.surface)} | ${surface.coverage} | ${surface.depth} | ${surface.status} | ${surface.operationsRecord ?? "unknown"} | ${surface.readinessGate ?? "unknown"} | ${escapeMarkdown((surface.competitors ?? []).join(", ") || "n/a")} | ${escapeMarkdown(surface.nextMove ?? surface.remainingGap ?? "none")} |`),
|
|
12612
|
+
"",
|
|
12613
|
+
"## Issues",
|
|
12614
|
+
"",
|
|
12615
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue.severity.toUpperCase()} ${issue.code}${issue.surface ? ` (${issue.surface})` : ""}: ${issue.message}`) : ["- None"],
|
|
12616
|
+
"",
|
|
12617
|
+
"## Notes",
|
|
12618
|
+
"",
|
|
12619
|
+
...report.notes.length ? report.notes.map((note) => `- ${note}`) : ["- None"]
|
|
12620
|
+
].join(`
|
|
12621
|
+
`);
|
|
12622
|
+
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
12623
|
+
const surfaceCards = report.surfaces.map((surface) => {
|
|
12624
|
+
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${escapeHtml16(item.name)}</strong>${item.kind ? ` <span>${escapeHtml16(item.kind)}</span>` : ""}${item.status ? ` <em>${escapeHtml16(item.status)}</em>` : ""}${item.href ? ` <a href="${escapeHtml16(item.href)}">open</a>` : ""}</li>`).join("");
|
|
12625
|
+
return `<article class="surface ${escapeHtml16(surface.status)} ${escapeHtml16(surface.depth)}">
|
|
12626
|
+
<header><div><p class="eyebrow">${escapeHtml16(surface.coverage)} \xB7 ${escapeHtml16(surface.depth)}</p><h2>${escapeHtml16(surface.surface)}</h2></div><strong>${escapeHtml16(surface.status)}</strong></header>
|
|
12627
|
+
<p>${escapeHtml16(surface.why)}</p>
|
|
12628
|
+
<dl>
|
|
12629
|
+
<div><dt>Competitors</dt><dd>${escapeHtml16((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
12630
|
+
<div><dt>Operations record</dt><dd>${escapeHtml16(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
12631
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml16(surface.readinessGate ?? "unknown")}</dd></div>
|
|
12632
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml16((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
12633
|
+
</dl>
|
|
12634
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml16(surface.remainingGap)}</p>` : ""}
|
|
12635
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml16(surface.nextMove)}</p>` : ""}
|
|
12636
|
+
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
12637
|
+
</article>`;
|
|
12638
|
+
}).join(`
|
|
12639
|
+
`);
|
|
12640
|
+
const issueList = report.issues.map((issue) => `<li class="${escapeHtml16(issue.severity)}"><strong>${escapeHtml16(issue.code)}</strong>${issue.surface ? ` ${escapeHtml16(issue.surface)}` : ""}: ${escapeHtml16(issue.message)}</li>`).join("");
|
|
12641
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml16(title)}</title><style>body{background:#0e1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.surface,.issues{background:#17201c;border:1px solid #2e3c35;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.16),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;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{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.surfaces{display:grid;gap:14px}.surface header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.surface.pass{border-color:rgba(34,197,94,.55)}.surface.warn{border-color:rgba(245,158,11,.72)}.surface.fail{border-color:rgba(239,68,68,.75)}.surface.advantage h2{color:#bbf7d0}.surface.intentional-gap h2{color:#cbd5e1}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}dt{color:#9fb0a8;font-size:.8rem;font-weight:800}dd{margin:0;overflow-wrap:anywhere}.gap{color:#fde68a}.next{color:#bfdbfe}.muted{color:#a8b5ad}a{color:#5eead4}.issues li{margin:.4rem 0}.issues .error{color:#fecaca}.issues .warning{color:#fde68a}@media(max-width:760px){main{padding:18px}.surface header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted market proof</p><h1>${escapeHtml16(title)}</h1><p>Generated ${escapeHtml16(report.generatedAt)}. This report scores whether AbsoluteJS Voice merely covers a hosted-platform buyer surface or beats it for a code-owned/self-hosted buyer.</p><div class="summary"><span class="pill">Status ${escapeHtml16(report.status)}</span><span class="pill">Vapi-style ${escapeHtml16(report.vapiCoverageEstimate)}</span><span class="pill">Market ${escapeHtml16(report.marketCoverageEstimate)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.advantage)} advantage</span><span class="pill">${String(report.summary.intentionalGaps)} intentional gaps</span></div></section><section class="issues"><h2>Issues</h2><ul>${issueList || "<li>No issues.</li>"}</ul></section><section class="surfaces">${surfaceCards || '<article class="surface"><p>No competitive surfaces configured.</p></article>'}</section></main></body></html>`;
|
|
12642
|
+
};
|
|
12643
|
+
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
12644
|
+
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
12645
|
+
const path = options.path ?? "/api/voice/competitive-coverage";
|
|
12646
|
+
const htmlPath = options.htmlPath ?? "/voice/competitive-coverage";
|
|
12647
|
+
const markdownPath = options.markdownPath ?? "/voice/competitive-coverage.md";
|
|
12648
|
+
const headers = options.headers ?? {};
|
|
12649
|
+
const title = options.title ?? "Voice Competitive Coverage";
|
|
12650
|
+
const report = async () => {
|
|
12651
|
+
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
12652
|
+
return normalizeCompetitiveCoverageReport(value);
|
|
12653
|
+
};
|
|
12654
|
+
const app = new Elysia14({
|
|
12655
|
+
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
12656
|
+
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
12657
|
+
headers: {
|
|
12658
|
+
"content-type": "application/json; charset=utf-8",
|
|
12659
|
+
...headers
|
|
12660
|
+
}
|
|
12661
|
+
}));
|
|
12662
|
+
if (htmlPath !== false) {
|
|
12663
|
+
app.get(htmlPath, async () => {
|
|
12664
|
+
const current = await report();
|
|
12665
|
+
const body = options.render ? await options.render(current) : renderVoiceCompetitiveCoverageHTML(current, title);
|
|
12666
|
+
return new Response(body, {
|
|
12667
|
+
headers: {
|
|
12668
|
+
"content-type": "text/html; charset=utf-8",
|
|
12669
|
+
...headers
|
|
12670
|
+
}
|
|
12671
|
+
});
|
|
12672
|
+
});
|
|
12673
|
+
}
|
|
12674
|
+
if (markdownPath !== false) {
|
|
12675
|
+
app.get(markdownPath, async () => new Response(renderVoiceCompetitiveCoverageMarkdown(await report(), title), {
|
|
12676
|
+
headers: {
|
|
12677
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
12678
|
+
...headers
|
|
12679
|
+
}
|
|
12680
|
+
}));
|
|
12681
|
+
}
|
|
12682
|
+
return app;
|
|
12683
|
+
};
|
|
12684
|
+
// src/proofTrends.ts
|
|
12685
|
+
import { Elysia as Elysia15 } from "elysia";
|
|
12456
12686
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
12457
12687
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
12458
12688
|
var toTimeMs = (value) => {
|
|
@@ -12603,7 +12833,7 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
12603
12833
|
};
|
|
12604
12834
|
var createVoiceProofTrendRoutes = (options) => {
|
|
12605
12835
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
12606
|
-
const routes = new
|
|
12836
|
+
const routes = new Elysia15({
|
|
12607
12837
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
12608
12838
|
});
|
|
12609
12839
|
routes.get(path, async () => {
|
|
@@ -12636,11 +12866,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
12636
12866
|
return `${days}d ${hours % 24}h`;
|
|
12637
12867
|
};
|
|
12638
12868
|
// src/providerDecisionTraces.ts
|
|
12639
|
-
import { Elysia as
|
|
12869
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
12640
12870
|
|
|
12641
12871
|
// src/resilienceRoutes.ts
|
|
12642
|
-
import { Elysia as
|
|
12643
|
-
var
|
|
12872
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
12873
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12644
12874
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
12645
12875
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
12646
12876
|
var getBoolean2 = (value) => value === true;
|
|
@@ -12788,13 +13018,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
12788
13018
|
};
|
|
12789
13019
|
var renderProviderCards = (title, providers) => {
|
|
12790
13020
|
if (providers.length === 0) {
|
|
12791
|
-
return `<p class="muted">No ${
|
|
13021
|
+
return `<p class="muted">No ${escapeHtml17(title)} provider health yet.</p>`;
|
|
12792
13022
|
}
|
|
12793
13023
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
12794
|
-
<article class="card provider ${
|
|
13024
|
+
<article class="card provider ${escapeHtml17(provider.status)}">
|
|
12795
13025
|
<div class="card-header">
|
|
12796
|
-
<strong>${
|
|
12797
|
-
<span>${
|
|
13026
|
+
<strong>${escapeHtml17(provider.provider)}</strong>
|
|
13027
|
+
<span>${escapeHtml17(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
12798
13028
|
</div>
|
|
12799
13029
|
<dl>
|
|
12800
13030
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -12803,7 +13033,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
12803
13033
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
12804
13034
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
12805
13035
|
</dl>
|
|
12806
|
-
${provider.lastError ? `<p class="muted">${
|
|
13036
|
+
${provider.lastError ? `<p class="muted">${escapeHtml17(provider.lastError)}</p>` : ""}
|
|
12807
13037
|
</article>
|
|
12808
13038
|
`).join("")}</div>`;
|
|
12809
13039
|
};
|
|
@@ -12812,24 +13042,24 @@ var renderTimeline2 = (events) => {
|
|
|
12812
13042
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
12813
13043
|
}
|
|
12814
13044
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
12815
|
-
<article class="card event ${
|
|
13045
|
+
<article class="card event ${escapeHtml17(event.status ?? "unknown")}">
|
|
12816
13046
|
<div class="card-header">
|
|
12817
|
-
<strong>${
|
|
13047
|
+
<strong>${escapeHtml17(event.kind.toUpperCase())} ${escapeHtml17(event.operation ?? "generate")}</strong>
|
|
12818
13048
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
12819
13049
|
</div>
|
|
12820
13050
|
<p>
|
|
12821
|
-
<span class="pill">${
|
|
12822
|
-
<span class="pill">provider: ${
|
|
12823
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
13051
|
+
<span class="pill">${escapeHtml17(event.status ?? "unknown")}</span>
|
|
13052
|
+
<span class="pill">provider: ${escapeHtml17(event.provider ?? "unknown")}</span>
|
|
13053
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml17(event.fallbackProvider)}</span>` : ""}
|
|
12824
13054
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
12825
13055
|
</p>
|
|
12826
13056
|
<dl>
|
|
12827
13057
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
12828
13058
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
12829
13059
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
12830
|
-
<div><dt>Session</dt><dd>${
|
|
13060
|
+
<div><dt>Session</dt><dd>${escapeHtml17(event.sessionId)}</dd></div>
|
|
12831
13061
|
</dl>
|
|
12832
|
-
${event.error ? `<p class="muted">${
|
|
13062
|
+
${event.error ? `<p class="muted">${escapeHtml17(event.error)}</p>` : ""}
|
|
12833
13063
|
</article>
|
|
12834
13064
|
`).join("")}</div>`;
|
|
12835
13065
|
};
|
|
@@ -12839,9 +13069,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
12839
13069
|
const status = latest?.status ?? "idle";
|
|
12840
13070
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
12841
13071
|
return `<div>
|
|
12842
|
-
<dt>${
|
|
12843
|
-
<dd>${
|
|
12844
|
-
<small>${
|
|
13072
|
+
<dt>${escapeHtml17(kind.toUpperCase())}</dt>
|
|
13073
|
+
<dd>${escapeHtml17(provider)}${escapeHtml17(fallback)}</dd>
|
|
13074
|
+
<small>${escapeHtml17(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>
|
|
12845
13075
|
</div>`;
|
|
12846
13076
|
};
|
|
12847
13077
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -12849,10 +13079,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
12849
13079
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
12850
13080
|
}
|
|
12851
13081
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
12852
|
-
<article class="card session ${
|
|
13082
|
+
<article class="card session ${escapeHtml17(session.status)}">
|
|
12853
13083
|
<div class="card-header">
|
|
12854
|
-
<strong>${
|
|
12855
|
-
<span>${
|
|
13084
|
+
<strong>${escapeHtml17(session.sessionId)}</strong>
|
|
13085
|
+
<span>${escapeHtml17(session.status)}</span>
|
|
12856
13086
|
</div>
|
|
12857
13087
|
<p>
|
|
12858
13088
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -12879,21 +13109,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
12879
13109
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
12880
13110
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
12881
13111
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
12882
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
12883
|
-
<p class="muted">${
|
|
13112
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml17(pathPrefix)}">
|
|
13113
|
+
<p class="muted">${escapeHtml17(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
12884
13114
|
<div class="simulate-actions">
|
|
12885
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
12886
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
13115
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml17(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml17(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
13116
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml17(provider.provider)}">Mark ${escapeHtml17(provider.provider)} recovered</button>`).join("")}
|
|
12887
13117
|
</div>
|
|
12888
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
13118
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml17(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
12889
13119
|
<pre class="simulate-output" hidden></pre>
|
|
12890
13120
|
</div>`;
|
|
12891
13121
|
};
|
|
12892
13122
|
var renderVoiceResilienceHTML = (input) => {
|
|
12893
13123
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
12894
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
12895
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
12896
|
-
const snippet =
|
|
13124
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml17(kind)}: ${String(count)}</span>`).join("");
|
|
13125
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml17(link.href)}">${escapeHtml17(link.label)}</a>`).join(" \xB7 ") : "";
|
|
13126
|
+
const snippet = escapeHtml17(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
12897
13127
|
kind: 'stt',
|
|
12898
13128
|
providers: ['deepgram', 'assemblyai'],
|
|
12899
13129
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -12931,7 +13161,7 @@ app.use(
|
|
|
12931
13161
|
<head>
|
|
12932
13162
|
<meta charset="utf-8" />
|
|
12933
13163
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12934
|
-
<title>${
|
|
13164
|
+
<title>${escapeHtml17(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
12935
13165
|
<style>
|
|
12936
13166
|
:root { color-scheme: dark; }
|
|
12937
13167
|
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; }
|
|
@@ -13083,7 +13313,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
13083
13313
|
};
|
|
13084
13314
|
var createVoiceResilienceRoutes = (options) => {
|
|
13085
13315
|
const path = options.path ?? "/resilience";
|
|
13086
|
-
const routes = new
|
|
13316
|
+
const routes = new Elysia16({
|
|
13087
13317
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
13088
13318
|
}).get(path, async () => {
|
|
13089
13319
|
const events = await options.store.list();
|
|
@@ -13124,7 +13354,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
13124
13354
|
};
|
|
13125
13355
|
|
|
13126
13356
|
// src/providerDecisionTraces.ts
|
|
13127
|
-
var
|
|
13357
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13128
13358
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
13129
13359
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
13130
13360
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -13365,7 +13595,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
13365
13595
|
<head>
|
|
13366
13596
|
<meta charset="utf-8" />
|
|
13367
13597
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
13368
|
-
<title>${
|
|
13598
|
+
<title>${escapeHtml18(title)}</title>
|
|
13369
13599
|
<style>
|
|
13370
13600
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
13371
13601
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -13379,8 +13609,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
13379
13609
|
</head>
|
|
13380
13610
|
<body>
|
|
13381
13611
|
<main>
|
|
13382
|
-
<p class="status ${report.status}">${
|
|
13383
|
-
<h1>${
|
|
13612
|
+
<p class="status ${report.status}">${escapeHtml18(report.status)}</p>
|
|
13613
|
+
<h1>${escapeHtml18(title)}</h1>
|
|
13384
13614
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
13385
13615
|
<section class="grid">
|
|
13386
13616
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -13391,10 +13621,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
13391
13621
|
</section>
|
|
13392
13622
|
<section class="surfaces">
|
|
13393
13623
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
13394
|
-
<header><strong>${
|
|
13624
|
+
<header><strong>${escapeHtml18(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml18(surface.status)}</span></header>
|
|
13395
13625
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
13396
|
-
<p class="muted">Providers: ${
|
|
13397
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
13626
|
+
<p class="muted">Providers: ${escapeHtml18(surface.providers.join(", ") || "none")}</p>
|
|
13627
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml18(reason)}</code>`).join(" ")}</p>
|
|
13398
13628
|
</article>`).join(`
|
|
13399
13629
|
`)}
|
|
13400
13630
|
</section>
|
|
@@ -13408,7 +13638,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
13408
13638
|
const headers = options.headers ?? {};
|
|
13409
13639
|
const title = options.title ?? "Provider Decision Traces";
|
|
13410
13640
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
13411
|
-
const app = new
|
|
13641
|
+
const app = new Elysia17({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
13412
13642
|
headers: {
|
|
13413
13643
|
"content-type": "application/json; charset=utf-8",
|
|
13414
13644
|
...headers
|
|
@@ -13436,7 +13666,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
13436
13666
|
return app;
|
|
13437
13667
|
};
|
|
13438
13668
|
// src/sloCalibration.ts
|
|
13439
|
-
import { Elysia as
|
|
13669
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
13440
13670
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
13441
13671
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
13442
13672
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -13615,8 +13845,8 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
13615
13845
|
status: profile.status
|
|
13616
13846
|
};
|
|
13617
13847
|
};
|
|
13618
|
-
var
|
|
13619
|
-
var
|
|
13848
|
+
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
13849
|
+
var escapeHtml19 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13620
13850
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
13621
13851
|
var readinessThresholdRows = (report) => [
|
|
13622
13852
|
{
|
|
@@ -13661,7 +13891,7 @@ var readinessThresholdRows = (report) => [
|
|
|
13661
13891
|
}
|
|
13662
13892
|
];
|
|
13663
13893
|
var renderVoiceSloCalibrationMarkdown = (report, options = {}) => {
|
|
13664
|
-
const rows = Object.values(report.thresholds).map((threshold) => `| ${
|
|
13894
|
+
const rows = Object.values(report.thresholds).map((threshold) => `| ${escapeMarkdown2(threshold.metric)} | ${threshold.status} | ${threshold.samples} | ${threshold.baselineP95Ms ?? "n/a"} | ${threshold.warnAfterMs ?? "n/a"} | ${threshold.failAfterMs ?? "n/a"} |`).join(`
|
|
13665
13895
|
`);
|
|
13666
13896
|
return `# ${options.title ?? "Voice SLO Calibration"}
|
|
13667
13897
|
|
|
@@ -13682,7 +13912,7 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
13682
13912
|
`;
|
|
13683
13913
|
};
|
|
13684
13914
|
var renderVoiceSloReadinessThresholdMarkdown = (report, options = {}) => {
|
|
13685
|
-
const rows = readinessThresholdRows(report).map((row) => `| ${
|
|
13915
|
+
const rows = readinessThresholdRows(report).map((row) => `| ${escapeMarkdown2(row.control)} | ${formatMs(row.value)} | ${escapeMarkdown2(row.usedBy)} |`).join(`
|
|
13686
13916
|
`);
|
|
13687
13917
|
return `# ${options.title ?? "Calibration -> Active Readiness Gate"}
|
|
13688
13918
|
|
|
@@ -13707,15 +13937,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
13707
13937
|
};
|
|
13708
13938
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
13709
13939
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
13710
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
13711
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
13712
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
13713
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
13940
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml19(row.control)}</td><td>${escapeHtml19(formatMs(row.value))}</td><td>${escapeHtml19(row.usedBy)}</td></tr>`).join("");
|
|
13941
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml19(issue)}</li>`).join("");
|
|
13942
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml19(source)}</code></li>`).join("");
|
|
13943
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml19(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>${escapeHtml19(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">${escapeHtml19(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml19(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml19(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml19(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>`;
|
|
13714
13944
|
};
|
|
13715
13945
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
13716
13946
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
13717
13947
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
13718
|
-
const routes = new
|
|
13948
|
+
const routes = new Elysia18({
|
|
13719
13949
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
13720
13950
|
});
|
|
13721
13951
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -13739,7 +13969,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
13739
13969
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
13740
13970
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
13741
13971
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
13742
|
-
const routes = new
|
|
13972
|
+
const routes = new Elysia18({
|
|
13743
13973
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
13744
13974
|
});
|
|
13745
13975
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -13773,7 +14003,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
13773
14003
|
return routes;
|
|
13774
14004
|
};
|
|
13775
14005
|
// src/liveOps.ts
|
|
13776
|
-
import { Elysia as
|
|
14006
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
13777
14007
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
13778
14008
|
"assign",
|
|
13779
14009
|
"create-task",
|
|
@@ -14083,7 +14313,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
14083
14313
|
const controller = createVoiceLiveOpsController(options);
|
|
14084
14314
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
14085
14315
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
14086
|
-
return new
|
|
14316
|
+
return new Elysia19({
|
|
14087
14317
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
14088
14318
|
}).post(path, async ({ request, set }) => {
|
|
14089
14319
|
try {
|
|
@@ -14105,15 +14335,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
14105
14335
|
});
|
|
14106
14336
|
};
|
|
14107
14337
|
// src/deliveryRuntime.ts
|
|
14108
|
-
import { Elysia as
|
|
14338
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
14109
14339
|
import { mkdir } from "fs/promises";
|
|
14110
14340
|
import { dirname, join } from "path";
|
|
14111
|
-
var
|
|
14341
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14112
14342
|
var renderSummaryCard = (label, summary) => {
|
|
14113
14343
|
if (!summary) {
|
|
14114
|
-
return `<article><span>${
|
|
14344
|
+
return `<article><span>${escapeHtml20(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
14115
14345
|
}
|
|
14116
|
-
return `<article><span>${
|
|
14346
|
+
return `<article><span>${escapeHtml20(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>`;
|
|
14117
14347
|
};
|
|
14118
14348
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
14119
14349
|
audit: leases,
|
|
@@ -14324,9 +14554,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
14324
14554
|
});
|
|
14325
14555
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
14326
14556
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
14327
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
14328
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
14329
|
-
const snippet =
|
|
14557
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml20(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
14558
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml20(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
14559
|
+
const snippet = escapeHtml20(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
14330
14560
|
createVoiceDeliveryRuntimePresetConfig({
|
|
14331
14561
|
audit: {
|
|
14332
14562
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -14352,14 +14582,14 @@ app.use(
|
|
|
14352
14582
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
14353
14583
|
})
|
|
14354
14584
|
);`);
|
|
14355
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
14585
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml20(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>${escapeHtml20(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 ${escapeHtml20(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>`;
|
|
14356
14586
|
};
|
|
14357
14587
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
14358
14588
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
14359
14589
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
14360
14590
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
14361
14591
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
14362
|
-
const routes = new
|
|
14592
|
+
const routes = new Elysia20({
|
|
14363
14593
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
14364
14594
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
14365
14595
|
if (tickPath !== false) {
|
|
@@ -14395,7 +14625,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
14395
14625
|
return routes;
|
|
14396
14626
|
};
|
|
14397
14627
|
// src/dataControl.ts
|
|
14398
|
-
import { Elysia as
|
|
14628
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14399
14629
|
var voiceComplianceRedactionDefaults = {
|
|
14400
14630
|
keys: [
|
|
14401
14631
|
"apiKey",
|
|
@@ -14634,7 +14864,7 @@ var parseRetentionScopes = (value) => {
|
|
|
14634
14864
|
const allowed = new Set(allRetentionScopes);
|
|
14635
14865
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
14636
14866
|
};
|
|
14637
|
-
var
|
|
14867
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14638
14868
|
var buildStorageSurfaces = (options) => [
|
|
14639
14869
|
{
|
|
14640
14870
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -14871,12 +15101,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
14871
15101
|
zeroRetentionAvailable: true
|
|
14872
15102
|
};
|
|
14873
15103
|
};
|
|
14874
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
15104
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml21(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml21(scope.skippedReason ?? "")}</td><td><code>${escapeHtml21(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
14875
15105
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
14876
15106
|
const title = options.title ?? "Voice Data Control";
|
|
14877
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
14878
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
14879
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15107
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml21(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml21(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
15108
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml21(key.name)}</td><td><code>${escapeHtml21(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml21(key.recommendation)}</td></tr>`).join("");
|
|
15109
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml21(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>${escapeHtml21(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>`;
|
|
14880
15110
|
};
|
|
14881
15111
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
14882
15112
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -14934,7 +15164,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
14934
15164
|
var createVoiceDataControlRoutes = (options) => {
|
|
14935
15165
|
const path = options.path ?? "/data-control";
|
|
14936
15166
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
14937
|
-
const routes = new
|
|
15167
|
+
const routes = new Elysia21({
|
|
14938
15168
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
14939
15169
|
});
|
|
14940
15170
|
routes.get(path, async ({ query }) => {
|
|
@@ -15010,16 +15240,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
15010
15240
|
return routes;
|
|
15011
15241
|
};
|
|
15012
15242
|
// src/evalRoutes.ts
|
|
15013
|
-
import { Elysia as
|
|
15243
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
15014
15244
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
15015
15245
|
import { dirname as dirname2 } from "path";
|
|
15016
15246
|
|
|
15017
15247
|
// src/qualityRoutes.ts
|
|
15018
|
-
import { Elysia as
|
|
15248
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15019
15249
|
|
|
15020
15250
|
// src/handoffHealth.ts
|
|
15021
|
-
import { Elysia as
|
|
15022
|
-
var
|
|
15251
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
15252
|
+
var escapeHtml22 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15023
15253
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
15024
15254
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
15025
15255
|
var increment3 = (record, key) => {
|
|
@@ -15137,10 +15367,10 @@ var renderActionSummary = (summary) => {
|
|
|
15137
15367
|
return [
|
|
15138
15368
|
'<section class="voice-handoff-health-columns">',
|
|
15139
15369
|
"<article><h3>Actions</h3>",
|
|
15140
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
15370
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml22(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
15141
15371
|
"</article>",
|
|
15142
15372
|
"<article><h3>Adapters</h3>",
|
|
15143
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
15373
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml22(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
15144
15374
|
"</article>",
|
|
15145
15375
|
"</section>"
|
|
15146
15376
|
].join("");
|
|
@@ -15154,22 +15384,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
15154
15384
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
15155
15385
|
'<div class="voice-handoff-health-events">',
|
|
15156
15386
|
...summary.events.map((event) => [
|
|
15157
|
-
`<article class="${
|
|
15387
|
+
`<article class="${escapeHtml22(event.status)}">`,
|
|
15158
15388
|
'<div class="voice-handoff-health-event-header">',
|
|
15159
|
-
`<strong>${
|
|
15160
|
-
`<span>${
|
|
15389
|
+
`<strong>${escapeHtml22(event.action ?? "handoff")}</strong>`,
|
|
15390
|
+
`<span>${escapeHtml22(event.status)}</span>`,
|
|
15161
15391
|
"</div>",
|
|
15162
|
-
`<p><small>${
|
|
15163
|
-
event.target ? `<p>Target: ${
|
|
15164
|
-
event.reason ? `<p>Reason: ${
|
|
15392
|
+
`<p><small>${escapeHtml22(event.sessionId)}</small></p>`,
|
|
15393
|
+
event.target ? `<p>Target: ${escapeHtml22(event.target)}</p>` : "",
|
|
15394
|
+
event.reason ? `<p>Reason: ${escapeHtml22(event.reason)}</p>` : "",
|
|
15165
15395
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
15166
15396
|
"<li>",
|
|
15167
|
-
`${
|
|
15168
|
-
delivery.deliveredTo ? ` to ${
|
|
15169
|
-
delivery.error ? ` (${
|
|
15397
|
+
`${escapeHtml22(delivery.adapterId)}: ${escapeHtml22(delivery.status)}`,
|
|
15398
|
+
delivery.deliveredTo ? ` to ${escapeHtml22(delivery.deliveredTo)}` : "",
|
|
15399
|
+
delivery.error ? ` (${escapeHtml22(delivery.error)})` : "",
|
|
15170
15400
|
"</li>"
|
|
15171
15401
|
].join("")).join("")}</ul>` : "",
|
|
15172
|
-
event.replayHref ? `<p><a href="${
|
|
15402
|
+
event.replayHref ? `<p><a href="${escapeHtml22(event.replayHref)}">Open replay</a></p>` : "",
|
|
15173
15403
|
"</article>"
|
|
15174
15404
|
].join("")),
|
|
15175
15405
|
"</div>"
|
|
@@ -15201,7 +15431,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
15201
15431
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
15202
15432
|
const path = options.path ?? "/api/voice-handoffs";
|
|
15203
15433
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
15204
|
-
const routes = new
|
|
15434
|
+
const routes = new Elysia22({
|
|
15205
15435
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
15206
15436
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
15207
15437
|
if (htmlPath) {
|
|
@@ -15322,17 +15552,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
15322
15552
|
thresholds
|
|
15323
15553
|
};
|
|
15324
15554
|
};
|
|
15325
|
-
var
|
|
15555
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15326
15556
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
15327
15557
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
15328
15558
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
15329
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
15330
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15559
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml23(metric.label)}</td><td>${escapeHtml23(formatMetricValue(metric))}</td><td>${escapeHtml23(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml23(key)}</code></td></tr>`).join("");
|
|
15560
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml23(link.href)}">${escapeHtml23(link.label)}</a>`).join("")}</nav>` : "";
|
|
15331
15561
|
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>`;
|
|
15332
15562
|
};
|
|
15333
15563
|
var createVoiceQualityRoutes = (options) => {
|
|
15334
15564
|
const path = options.path ?? "/quality";
|
|
15335
|
-
const routes = new
|
|
15565
|
+
const routes = new Elysia23({
|
|
15336
15566
|
name: options.name ?? "absolutejs-voice-quality"
|
|
15337
15567
|
});
|
|
15338
15568
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -15361,7 +15591,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
15361
15591
|
};
|
|
15362
15592
|
|
|
15363
15593
|
// src/evalRoutes.ts
|
|
15364
|
-
var
|
|
15594
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15365
15595
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
15366
15596
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
15367
15597
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -15683,7 +15913,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
15683
15913
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
15684
15914
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
15685
15915
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
15686
|
-
const snippet =
|
|
15916
|
+
const snippet = escapeHtml24(`app.use(
|
|
15687
15917
|
createVoiceEvalRoutes({
|
|
15688
15918
|
path: '/evals',
|
|
15689
15919
|
store: traceStore,
|
|
@@ -15704,48 +15934,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
15704
15934
|
};
|
|
15705
15935
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
15706
15936
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
15707
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15708
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
15937
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join("")}</nav>` : "";
|
|
15938
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml24(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>';
|
|
15709
15939
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
15710
15940
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
15711
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
15712
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
15941
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml24(session.operationsRecordHref)}">${escapeHtml24(session.sessionId)}</a>` : escapeHtml24(session.sessionId);
|
|
15942
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml24(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml24(formatTime(session.endedAt))}</td><td>${escapeHtml24(failedMetrics || "none")}</td></tr>`;
|
|
15713
15943
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
15714
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15944
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml24(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>${escapeHtml24(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>`;
|
|
15715
15945
|
};
|
|
15716
15946
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
15717
15947
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
15718
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15719
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
15720
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
15721
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
15722
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15948
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join("")}</nav>` : "";
|
|
15949
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml24(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
15950
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml24(id)}</li>`).join("") : "<li>none</li>";
|
|
15951
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml24(id)}</li>`).join("") : "<li>none</li>";
|
|
15952
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml24(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>${escapeHtml24(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml24(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml24(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>${escapeHtml24(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>`;
|
|
15723
15953
|
};
|
|
15724
15954
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
15725
15955
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
15726
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15956
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join("")}</nav>` : "";
|
|
15727
15957
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
15728
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
15958
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml24(issue)}</li>`).join("")}</ul>` : "";
|
|
15729
15959
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
15730
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
15731
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
15960
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml24(session.operationsRecordHref)}">${escapeHtml24(session.sessionId)}</a>` : escapeHtml24(session.sessionId);
|
|
15961
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml24(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml24(session.issues.join(", ") || "none")}</td></tr>`;
|
|
15732
15962
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
15733
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
15963
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml24(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml24(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>`;
|
|
15734
15964
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
15735
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15965
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml24(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>${escapeHtml24(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>`;
|
|
15736
15966
|
};
|
|
15737
15967
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
15738
15968
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
15739
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15969
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join("")}</nav>` : "";
|
|
15740
15970
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
15741
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
15742
|
-
return `<section class="${fixture.status}"><h2>${
|
|
15971
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml24(scenario.label)}</td><td>${escapeHtml24(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml24([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
15972
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml24(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml24(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>`;
|
|
15743
15973
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
15744
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15974
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml24(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>${escapeHtml24(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>`;
|
|
15745
15975
|
};
|
|
15746
15976
|
var createVoiceEvalRoutes = (options) => {
|
|
15747
15977
|
const path = options.path ?? "/evals";
|
|
15748
|
-
const routes = new
|
|
15978
|
+
const routes = new Elysia24({
|
|
15749
15979
|
name: options.name ?? "absolutejs-voice-evals"
|
|
15750
15980
|
});
|
|
15751
15981
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -15882,11 +16112,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
15882
16112
|
return routes;
|
|
15883
16113
|
};
|
|
15884
16114
|
// src/simulationSuite.ts
|
|
15885
|
-
import { Elysia as
|
|
16115
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
15886
16116
|
|
|
15887
16117
|
// src/outcomeContract.ts
|
|
15888
|
-
import { Elysia as
|
|
15889
|
-
var
|
|
16118
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16119
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15890
16120
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
15891
16121
|
if (value === false) {
|
|
15892
16122
|
return;
|
|
@@ -16097,13 +16327,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
16097
16327
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
16098
16328
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
16099
16329
|
const contracts = report.contracts.map((contract) => {
|
|
16100
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
16330
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml25(href)}">${escapeHtml25(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
16101
16331
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
16102
16332
|
<div class="contract-header">
|
|
16103
16333
|
<div>
|
|
16104
|
-
<p class="eyebrow">${
|
|
16105
|
-
<h2>${
|
|
16106
|
-
${contract.description ? `<p>${
|
|
16334
|
+
<p class="eyebrow">${escapeHtml25(contract.contractId)}</p>
|
|
16335
|
+
<h2>${escapeHtml25(contract.label ?? contract.contractId)}</h2>
|
|
16336
|
+
${contract.description ? `<p>${escapeHtml25(contract.description)}</p>` : ""}
|
|
16107
16337
|
${sessionLinks}
|
|
16108
16338
|
</div>
|
|
16109
16339
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -16115,10 +16345,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
16115
16345
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
16116
16346
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
16117
16347
|
</div>
|
|
16118
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
16348
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml25(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
16119
16349
|
</section>`;
|
|
16120
16350
|
}).join("");
|
|
16121
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16351
|
+
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:#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>${escapeHtml25(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>`;
|
|
16122
16352
|
};
|
|
16123
16353
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
16124
16354
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -16134,7 +16364,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
16134
16364
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
16135
16365
|
const path = options.path ?? "/api/outcome-contracts";
|
|
16136
16366
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16137
|
-
const routes = new
|
|
16367
|
+
const routes = new Elysia25({
|
|
16138
16368
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
16139
16369
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
16140
16370
|
if (htmlPath) {
|
|
@@ -16144,7 +16374,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
16144
16374
|
};
|
|
16145
16375
|
|
|
16146
16376
|
// src/toolContract.ts
|
|
16147
|
-
import { Elysia as
|
|
16377
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16148
16378
|
|
|
16149
16379
|
// src/toolRuntime.ts
|
|
16150
16380
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -16353,7 +16583,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
16353
16583
|
});
|
|
16354
16584
|
var defaultApi = {};
|
|
16355
16585
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
16356
|
-
var
|
|
16586
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16357
16587
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
16358
16588
|
if (value === false) {
|
|
16359
16589
|
return;
|
|
@@ -16602,7 +16832,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
16602
16832
|
};
|
|
16603
16833
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
16604
16834
|
const title = options.title ?? "Voice Tool Contracts";
|
|
16605
|
-
const snippet =
|
|
16835
|
+
const snippet = escapeHtml26(`app.use(
|
|
16606
16836
|
createVoiceToolContractRoutes({
|
|
16607
16837
|
htmlPath: '/tool-contracts',
|
|
16608
16838
|
path: '/api/tool-contracts',
|
|
@@ -16628,20 +16858,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
16628
16858
|
);`);
|
|
16629
16859
|
const contracts = report.contracts.map((contract) => {
|
|
16630
16860
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
16631
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
16861
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml26(testCase.operationsRecordHref)}">${escapeHtml26(testCase.label ?? testCase.caseId)}</a>` : escapeHtml26(testCase.label ?? testCase.caseId)}</td>
|
|
16632
16862
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
16633
|
-
<td>${
|
|
16634
|
-
<td>${
|
|
16863
|
+
<td>${escapeHtml26(testCase.status)}</td>
|
|
16864
|
+
<td>${escapeHtml26(testCase.sessionId)}</td>
|
|
16635
16865
|
<td>${String(testCase.attempts)}</td>
|
|
16636
16866
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
16637
16867
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
16638
|
-
<td>${
|
|
16868
|
+
<td>${escapeHtml26(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
16639
16869
|
</tr>`).join("");
|
|
16640
16870
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
16641
16871
|
<div class="contract-header">
|
|
16642
16872
|
<div>
|
|
16643
|
-
<p class="eyebrow">${
|
|
16644
|
-
<h2>${
|
|
16873
|
+
<p class="eyebrow">${escapeHtml26(contract.toolName)}</p>
|
|
16874
|
+
<h2>${escapeHtml26(contract.label ?? contract.contractId)}</h2>
|
|
16645
16875
|
</div>
|
|
16646
16876
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
16647
16877
|
</div>
|
|
@@ -16651,7 +16881,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
16651
16881
|
</table>
|
|
16652
16882
|
</section>`;
|
|
16653
16883
|
}).join("");
|
|
16654
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16884
|
+
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:#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>${escapeHtml26(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml26(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>`;
|
|
16655
16885
|
};
|
|
16656
16886
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
16657
16887
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -16668,7 +16898,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
16668
16898
|
var createVoiceToolContractRoutes = (options) => {
|
|
16669
16899
|
const path = options.path ?? "/api/tool-contracts";
|
|
16670
16900
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16671
|
-
const routes = new
|
|
16901
|
+
const routes = new Elysia26({
|
|
16672
16902
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
16673
16903
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
16674
16904
|
if (htmlPath) {
|
|
@@ -16678,7 +16908,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
16678
16908
|
};
|
|
16679
16909
|
|
|
16680
16910
|
// src/simulationSuite.ts
|
|
16681
|
-
var
|
|
16911
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16682
16912
|
var summarizeSection = (report) => ({
|
|
16683
16913
|
failed: report.failed,
|
|
16684
16914
|
passed: report.passed,
|
|
@@ -16874,15 +17104,15 @@ var renderSection = (label, summary) => {
|
|
|
16874
17104
|
if (!summary) {
|
|
16875
17105
|
return "";
|
|
16876
17106
|
}
|
|
16877
|
-
return `<article class="${
|
|
17107
|
+
return `<article class="${escapeHtml27(summary.status)}"><span>${escapeHtml27(label)}</span><strong>${escapeHtml27(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
16878
17108
|
};
|
|
16879
17109
|
var renderAction = (action) => {
|
|
16880
|
-
const content = `<strong>${
|
|
16881
|
-
return action.href ? `<a class="action" href="${
|
|
17110
|
+
const content = `<strong>${escapeHtml27(action.label)}</strong><p>${escapeHtml27(action.description)}</p><span>${escapeHtml27(action.section)} / ${escapeHtml27(action.severity)}</span>`;
|
|
17111
|
+
return action.href ? `<a class="action" href="${escapeHtml27(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
16882
17112
|
};
|
|
16883
17113
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
16884
17114
|
const title = options.title ?? "Voice Simulation Suite";
|
|
16885
|
-
const snippet =
|
|
17115
|
+
const snippet = escapeHtml27(`app.use(
|
|
16886
17116
|
createVoiceSimulationSuiteRoutes({
|
|
16887
17117
|
htmlPath: '/voice/simulations',
|
|
16888
17118
|
path: '/api/voice/simulations',
|
|
@@ -16915,12 +17145,12 @@ app.use(
|
|
|
16915
17145
|
store: traceStore
|
|
16916
17146
|
})
|
|
16917
17147
|
);`);
|
|
16918
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17148
|
+
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:#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>${escapeHtml27(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml27(report.status)}">Status: ${escapeHtml27(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>${escapeHtml27(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
16919
17149
|
};
|
|
16920
17150
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
16921
17151
|
const path = options.path ?? "/api/voice/simulations";
|
|
16922
17152
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
16923
|
-
const app = new
|
|
17153
|
+
const app = new Elysia27({
|
|
16924
17154
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
16925
17155
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
16926
17156
|
if (htmlPath) {
|
|
@@ -17232,9 +17462,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
17232
17462
|
};
|
|
17233
17463
|
};
|
|
17234
17464
|
// src/sessionReplay.ts
|
|
17235
|
-
import { Elysia as
|
|
17465
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17236
17466
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
17237
|
-
var
|
|
17467
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17238
17468
|
var increment4 = (record, key) => {
|
|
17239
17469
|
record[key] = (record[key] ?? 0) + 1;
|
|
17240
17470
|
};
|
|
@@ -17428,10 +17658,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
17428
17658
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
17429
17659
|
'<div class="voice-sessions-list">',
|
|
17430
17660
|
...sessions.map((session) => [
|
|
17431
|
-
`<article class="voice-session-card ${
|
|
17661
|
+
`<article class="voice-session-card ${escapeHtml28(session.status)}">`,
|
|
17432
17662
|
'<div class="voice-session-card-header">',
|
|
17433
|
-
`<strong>${
|
|
17434
|
-
`<span>${
|
|
17663
|
+
`<strong>${escapeHtml28(session.sessionId)}</strong>`,
|
|
17664
|
+
`<span>${escapeHtml28(session.status)}</span>`,
|
|
17435
17665
|
"</div>",
|
|
17436
17666
|
"<dl>",
|
|
17437
17667
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -17439,9 +17669,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
17439
17669
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
17440
17670
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
17441
17671
|
"</dl>",
|
|
17442
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
17443
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
17444
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
17672
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml28(session.latestOutcome)}</p>` : "",
|
|
17673
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml28).join(", ")}</p>` : "",
|
|
17674
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml28(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml28(session.replayHref)}">Open replay</a></p>` : "",
|
|
17445
17675
|
"</article>"
|
|
17446
17676
|
].join("")),
|
|
17447
17677
|
"</div>"
|
|
@@ -17472,7 +17702,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
17472
17702
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
17473
17703
|
const path = options.path ?? "/api/voice-sessions";
|
|
17474
17704
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17475
|
-
const routes = new
|
|
17705
|
+
const routes = new Elysia28({
|
|
17476
17706
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
17477
17707
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
17478
17708
|
if (htmlPath) {
|
|
@@ -17500,7 +17730,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
17500
17730
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
17501
17731
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
17502
17732
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17503
|
-
const routes = new
|
|
17733
|
+
const routes = new Elysia28({
|
|
17504
17734
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
17505
17735
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
17506
17736
|
if (htmlPath) {
|
|
@@ -17814,10 +18044,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
17814
18044
|
return report;
|
|
17815
18045
|
};
|
|
17816
18046
|
// src/turnLatency.ts
|
|
17817
|
-
import { Elysia as
|
|
18047
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17818
18048
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
17819
18049
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
17820
|
-
var
|
|
18050
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17821
18051
|
var firstNumber = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
17822
18052
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
17823
18053
|
var createTraceStageIndex = (events) => {
|
|
@@ -17949,11 +18179,11 @@ await traceStore.append({
|
|
|
17949
18179
|
turnId,
|
|
17950
18180
|
type: 'turn_latency.stage'
|
|
17951
18181
|
});`;
|
|
17952
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
17953
|
-
<header><div><p class="eyebrow">${
|
|
17954
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
18182
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml29(turn.status)}">
|
|
18183
|
+
<header><div><p class="eyebrow">${escapeHtml29(turn.sessionId)} \xB7 ${escapeHtml29(turn.turnId)}</p><h2>${escapeHtml29(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml29(turn.status)}</strong></header>
|
|
18184
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml29(stage.label)}</dt><dd>${escapeHtml29(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
17955
18185
|
</article>`).join("");
|
|
17956
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18186
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml29(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>${escapeHtml29(title)}</h1><div class="summary"><span class="pill ${escapeHtml29(report.status)}">${escapeHtml29(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml29(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>${escapeHtml29(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
17957
18187
|
};
|
|
17958
18188
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
17959
18189
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -17970,7 +18200,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
17970
18200
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
17971
18201
|
const path = options.path ?? "/api/turn-latency";
|
|
17972
18202
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17973
|
-
const routes = new
|
|
18203
|
+
const routes = new Elysia29({
|
|
17974
18204
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
17975
18205
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
17976
18206
|
if (htmlPath) {
|
|
@@ -17979,8 +18209,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
17979
18209
|
return routes;
|
|
17980
18210
|
};
|
|
17981
18211
|
// src/liveLatency.ts
|
|
17982
|
-
import { Elysia as
|
|
17983
|
-
var
|
|
18212
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
18213
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17984
18214
|
var percentile3 = (values, percentileValue) => {
|
|
17985
18215
|
if (values.length === 0) {
|
|
17986
18216
|
return;
|
|
@@ -18047,13 +18277,13 @@ await traceStore.append({
|
|
|
18047
18277
|
sessionId,
|
|
18048
18278
|
type: 'client.live_latency'
|
|
18049
18279
|
});`;
|
|
18050
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
18051
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18280
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml30(sample.sessionId)}</td><td>${escapeHtml30(formatMs3(sample.latencyMs))}</td><td>${escapeHtml30(sample.status ?? "unknown")}</td><td>${escapeHtml30(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
18281
|
+
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{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>${escapeHtml30(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml30(report.status)}">Status: ${escapeHtml30(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml30(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml30(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml30(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>${escapeHtml30(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>`;
|
|
18052
18282
|
};
|
|
18053
18283
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
18054
18284
|
const path = options.path ?? "/api/live-latency";
|
|
18055
18285
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
18056
|
-
const routes = new
|
|
18286
|
+
const routes = new Elysia30({
|
|
18057
18287
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
18058
18288
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
18059
18289
|
if (htmlPath) {
|
|
@@ -18372,9 +18602,9 @@ None.
|
|
|
18372
18602
|
`}`;
|
|
18373
18603
|
};
|
|
18374
18604
|
// src/turnQuality.ts
|
|
18375
|
-
import { Elysia as
|
|
18605
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18376
18606
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
18377
|
-
var
|
|
18607
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18378
18608
|
var getTurnLatencyMs = (turn) => {
|
|
18379
18609
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
18380
18610
|
if (firstTranscriptAt === undefined) {
|
|
@@ -18445,24 +18675,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
18445
18675
|
};
|
|
18446
18676
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
18447
18677
|
const title = options.title ?? "Voice Turn Quality";
|
|
18448
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
18678
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml31(turn.status)}">
|
|
18449
18679
|
<div class="turn-header">
|
|
18450
18680
|
<div>
|
|
18451
|
-
<p class="eyebrow">${
|
|
18452
|
-
<h2>${
|
|
18681
|
+
<p class="eyebrow">${escapeHtml31(turn.sessionId)} \xB7 ${escapeHtml31(turn.turnId)}</p>
|
|
18682
|
+
<h2>${escapeHtml31(turn.text || "Empty turn")}</h2>
|
|
18453
18683
|
</div>
|
|
18454
|
-
<strong>${
|
|
18684
|
+
<strong>${escapeHtml31(turn.status)}</strong>
|
|
18455
18685
|
</div>
|
|
18456
18686
|
<dl>
|
|
18457
|
-
<div><dt>Source</dt><dd>${
|
|
18687
|
+
<div><dt>Source</dt><dd>${escapeHtml31(turn.source ?? "unknown")}</dd></div>
|
|
18458
18688
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
18459
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
18460
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
18689
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml31(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
18690
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml31(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
18461
18691
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
18462
18692
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
18463
18693
|
</dl>
|
|
18464
18694
|
</article>`).join("");
|
|
18465
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18695
|
+
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,.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>${escapeHtml31(title)}</h1><div class="summary"><span class="pill ${escapeHtml31(report.status)}">${escapeHtml31(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>`;
|
|
18466
18696
|
};
|
|
18467
18697
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
18468
18698
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -18479,7 +18709,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
18479
18709
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
18480
18710
|
const path = options.path ?? "/api/turn-quality";
|
|
18481
18711
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18482
|
-
const routes = new
|
|
18712
|
+
const routes = new Elysia31({
|
|
18483
18713
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
18484
18714
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
18485
18715
|
if (htmlPath) {
|
|
@@ -18488,7 +18718,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
18488
18718
|
return routes;
|
|
18489
18719
|
};
|
|
18490
18720
|
// src/telephonyOutcome.ts
|
|
18491
|
-
import { Elysia as
|
|
18721
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18492
18722
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
18493
18723
|
"answered",
|
|
18494
18724
|
"completed",
|
|
@@ -19249,7 +19479,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
19249
19479
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
19250
19480
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
19251
19481
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
19252
|
-
return new
|
|
19482
|
+
return new Elysia32({
|
|
19253
19483
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
19254
19484
|
}).post(path, async ({ query, request }) => {
|
|
19255
19485
|
try {
|
|
@@ -19270,12 +19500,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
19270
19500
|
});
|
|
19271
19501
|
};
|
|
19272
19502
|
// src/phoneAgent.ts
|
|
19273
|
-
import { Elysia as
|
|
19503
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
19274
19504
|
|
|
19275
19505
|
// src/telephony/plivo.ts
|
|
19276
19506
|
import { Buffer as Buffer5 } from "buffer";
|
|
19277
19507
|
import { Database } from "bun:sqlite";
|
|
19278
|
-
import { Elysia as
|
|
19508
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19279
19509
|
|
|
19280
19510
|
// src/telephony/contract.ts
|
|
19281
19511
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -19359,7 +19589,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
19359
19589
|
|
|
19360
19590
|
// src/telephony/twilio.ts
|
|
19361
19591
|
import { Buffer as Buffer4 } from "buffer";
|
|
19362
|
-
import { Elysia as
|
|
19592
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
19363
19593
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
19364
19594
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
19365
19595
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -19389,7 +19619,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
19389
19619
|
return parameters;
|
|
19390
19620
|
};
|
|
19391
19621
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
19392
|
-
var
|
|
19622
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
19393
19623
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
19394
19624
|
if (!webhook?.verificationUrl) {
|
|
19395
19625
|
return;
|
|
@@ -19432,23 +19662,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
19432
19662
|
};
|
|
19433
19663
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
19434
19664
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
19435
|
-
<h1>${
|
|
19665
|
+
<h1>${escapeHtml32(title)}</h1>
|
|
19436
19666
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
19437
19667
|
<section>
|
|
19438
19668
|
<h2>URLs</h2>
|
|
19439
19669
|
<ul>
|
|
19440
|
-
<li><strong>TwiML:</strong> <code>${
|
|
19441
|
-
<li><strong>Media stream:</strong> <code>${
|
|
19442
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
19670
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml32(status.urls.twiml)}</code></li>
|
|
19671
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml32(status.urls.stream)}</code></li>
|
|
19672
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml32(status.urls.webhook)}</code></li>
|
|
19443
19673
|
</ul>
|
|
19444
19674
|
</section>
|
|
19445
19675
|
<section>
|
|
19446
19676
|
<h2>Signing</h2>
|
|
19447
19677
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
19448
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
19678
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml32(status.signing.verificationUrl)}</code></p>` : ""}
|
|
19449
19679
|
</section>
|
|
19450
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
19451
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
19680
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml32(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
19681
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml32(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
19452
19682
|
</main>`;
|
|
19453
19683
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
19454
19684
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -19459,20 +19689,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
19459
19689
|
});
|
|
19460
19690
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
19461
19691
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
19462
|
-
<h1>${
|
|
19692
|
+
<h1>${escapeHtml32(title)}</h1>
|
|
19463
19693
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
19464
19694
|
<section>
|
|
19465
19695
|
<h2>Checks</h2>
|
|
19466
19696
|
<ul>
|
|
19467
|
-
${report.checks.map((check) => `<li><strong>${
|
|
19697
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml32(check.name)}</strong>: ${escapeHtml32(check.status)}${check.message ? ` - ${escapeHtml32(check.message)}` : ""}</li>`).join("")}
|
|
19468
19698
|
</ul>
|
|
19469
19699
|
</section>
|
|
19470
19700
|
<section>
|
|
19471
19701
|
<h2>Observed URLs</h2>
|
|
19472
19702
|
<ul>
|
|
19473
|
-
<li><strong>TwiML:</strong> <code>${
|
|
19474
|
-
<li><strong>Stream:</strong> <code>${
|
|
19475
|
-
<li><strong>Webhook:</strong> <code>${
|
|
19703
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml32(report.setup.urls.twiml)}</code></li>
|
|
19704
|
+
<li><strong>Stream:</strong> <code>${escapeHtml32(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
19705
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml32(report.setup.urls.webhook)}</code></li>
|
|
19476
19706
|
</ul>
|
|
19477
19707
|
</section>
|
|
19478
19708
|
</main>`;
|
|
@@ -19932,7 +20162,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
19932
20162
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
19933
20163
|
const bridges = new WeakMap;
|
|
19934
20164
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
19935
|
-
const app = new
|
|
20165
|
+
const app = new Elysia33({
|
|
19936
20166
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
19937
20167
|
}).get(twimlPath, async ({ query, request }) => {
|
|
19938
20168
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -20069,7 +20299,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
20069
20299
|
|
|
20070
20300
|
// src/telephony/plivo.ts
|
|
20071
20301
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20072
|
-
var
|
|
20302
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20073
20303
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20074
20304
|
var resolveRequestOrigin2 = (request) => {
|
|
20075
20305
|
const url = new URL(request.url);
|
|
@@ -20499,21 +20729,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
20499
20729
|
};
|
|
20500
20730
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20501
20731
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
20502
|
-
<h1>${
|
|
20732
|
+
<h1>${escapeHtml33(title)}</h1>
|
|
20503
20733
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
20504
20734
|
<ul>
|
|
20505
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
20506
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
20507
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
20735
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml33(status.urls.answer)}</code></li>
|
|
20736
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml33(status.urls.stream)}</code></li>
|
|
20737
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml33(status.urls.webhook)}</code></li>
|
|
20508
20738
|
</ul>
|
|
20509
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
20510
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
20739
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml33(name)}</code></li>`).join("")}</ul>` : ""}
|
|
20740
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml33(warning)}</li>`).join("")}</ul>` : ""}
|
|
20511
20741
|
</main>`;
|
|
20512
20742
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20513
20743
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
20514
|
-
<h1>${
|
|
20744
|
+
<h1>${escapeHtml33(title)}</h1>
|
|
20515
20745
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
20516
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
20746
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml33(check.name)}</strong>: ${escapeHtml33(check.status)}${check.message ? ` - ${escapeHtml33(check.message)}` : ""}</li>`).join("")}</ul>
|
|
20517
20747
|
</main>`;
|
|
20518
20748
|
var runPlivoSmokeTest = async (input) => {
|
|
20519
20749
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -20603,7 +20833,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
20603
20833
|
nonceStore: options.webhook.nonceStore,
|
|
20604
20834
|
verificationUrl: options.webhook.verificationUrl
|
|
20605
20835
|
}) : undefined);
|
|
20606
|
-
const app = new
|
|
20836
|
+
const app = new Elysia34({
|
|
20607
20837
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
20608
20838
|
}).get(answerPath, async ({ query, request }) => {
|
|
20609
20839
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -20715,9 +20945,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
20715
20945
|
// src/telephony/telnyx.ts
|
|
20716
20946
|
import { Buffer as Buffer6 } from "buffer";
|
|
20717
20947
|
import { Database as Database2 } from "bun:sqlite";
|
|
20718
|
-
import { Elysia as
|
|
20948
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
20719
20949
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20720
|
-
var
|
|
20950
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20721
20951
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20722
20952
|
var resolveRequestOrigin3 = (request) => {
|
|
20723
20953
|
const url = new URL(request.url);
|
|
@@ -21110,21 +21340,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
21110
21340
|
};
|
|
21111
21341
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21112
21342
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
21113
|
-
<h1>${
|
|
21343
|
+
<h1>${escapeHtml34(title)}</h1>
|
|
21114
21344
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
21115
21345
|
<ul>
|
|
21116
|
-
<li><strong>TeXML:</strong> <code>${
|
|
21117
|
-
<li><strong>Media stream:</strong> <code>${
|
|
21118
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
21346
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml34(status.urls.texml)}</code></li>
|
|
21347
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml34(status.urls.stream)}</code></li>
|
|
21348
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml34(status.urls.webhook)}</code></li>
|
|
21119
21349
|
</ul>
|
|
21120
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
21121
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
21350
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml34(name)}</code></li>`).join("")}</ul>` : ""}
|
|
21351
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml34(warning)}</li>`).join("")}</ul>` : ""}
|
|
21122
21352
|
</main>`;
|
|
21123
21353
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21124
21354
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
21125
|
-
<h1>${
|
|
21355
|
+
<h1>${escapeHtml34(title)}</h1>
|
|
21126
21356
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
21127
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
21357
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml34(check.name)}</strong>: ${escapeHtml34(check.status)}${check.message ? ` - ${escapeHtml34(check.message)}` : ""}</li>`).join("")}</ul>
|
|
21128
21358
|
</main>`;
|
|
21129
21359
|
var runTelnyxSmokeTest = async (input) => {
|
|
21130
21360
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -21217,7 +21447,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
21217
21447
|
publicKey: options.webhook.publicKey,
|
|
21218
21448
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
21219
21449
|
}) : undefined);
|
|
21220
|
-
const app = new
|
|
21450
|
+
const app = new Elysia35({
|
|
21221
21451
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
21222
21452
|
}).get(texmlPath, async ({ query, request }) => {
|
|
21223
21453
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -21327,8 +21557,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
21327
21557
|
};
|
|
21328
21558
|
|
|
21329
21559
|
// src/telephony/matrix.ts
|
|
21330
|
-
import { Elysia as
|
|
21331
|
-
var
|
|
21560
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
21561
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21332
21562
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
21333
21563
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
21334
21564
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -21389,13 +21619,13 @@ var badgeStyles = {
|
|
|
21389
21619
|
};
|
|
21390
21620
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
21391
21621
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
21392
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
21622
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml35(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
21393
21623
|
<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>
|
|
21394
21624
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
21395
21625
|
${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);">
|
|
21396
21626
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
21397
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
21398
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
21627
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml35(entry.name)}</h2>
|
|
21628
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml35(entry.status.toUpperCase())}</span>
|
|
21399
21629
|
</div>
|
|
21400
21630
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
21401
21631
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -21403,15 +21633,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
21403
21633
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
21404
21634
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
21405
21635
|
</dl>
|
|
21406
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
21407
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
21408
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
21636
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml35(entry.setup.urls.stream || "missing")}</code></p>
|
|
21637
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml35(entry.setup.urls.webhook || "missing")}</code></p>
|
|
21638
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml35(issue.severity)}: ${escapeHtml35(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
21409
21639
|
</article>`).join("")}
|
|
21410
21640
|
</section>
|
|
21411
21641
|
</main>`;
|
|
21412
21642
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
21413
21643
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
21414
|
-
return new
|
|
21644
|
+
return new Elysia36({
|
|
21415
21645
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
21416
21646
|
}).get(path, async ({ query, request }) => {
|
|
21417
21647
|
const providers = await options.load({ query, request });
|
|
@@ -21433,7 +21663,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
21433
21663
|
};
|
|
21434
21664
|
|
|
21435
21665
|
// src/phoneAgentProductionSmoke.ts
|
|
21436
|
-
import { Elysia as
|
|
21666
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
21437
21667
|
var defaultRequirements = [
|
|
21438
21668
|
"media-started",
|
|
21439
21669
|
"transcript",
|
|
@@ -21441,7 +21671,7 @@ var defaultRequirements = [
|
|
|
21441
21671
|
"lifecycle-outcome",
|
|
21442
21672
|
"no-session-error"
|
|
21443
21673
|
];
|
|
21444
|
-
var
|
|
21674
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21445
21675
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
21446
21676
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
21447
21677
|
const value = event.payload[key];
|
|
@@ -21550,10 +21780,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
21550
21780
|
});
|
|
21551
21781
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
21552
21782
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
21553
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
21554
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
21555
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
21556
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21783
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml36(issue.requirement)}</strong>: ${escapeHtml36(issue.message)}</li>`).join("");
|
|
21784
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml36(outcome)}</span>`).join("");
|
|
21785
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml36(requirement)}</span>`).join("");
|
|
21786
|
+
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:#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>${escapeHtml36(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml36(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml36(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml36(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>`;
|
|
21557
21787
|
};
|
|
21558
21788
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
21559
21789
|
query,
|
|
@@ -21576,7 +21806,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
21576
21806
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
21577
21807
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
21578
21808
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
21579
|
-
const routes = new
|
|
21809
|
+
const routes = new Elysia37({
|
|
21580
21810
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
21581
21811
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
21582
21812
|
if (htmlPath) {
|
|
@@ -21619,7 +21849,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
21619
21849
|
"completed",
|
|
21620
21850
|
"failed"
|
|
21621
21851
|
];
|
|
21622
|
-
var
|
|
21852
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21623
21853
|
var loadRouteJson = async (input) => {
|
|
21624
21854
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
21625
21855
|
headers: {
|
|
@@ -21857,10 +22087,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
21857
22087
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
21858
22088
|
const urls = entry?.setup.urls;
|
|
21859
22089
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
21860
|
-
return `<tr><td>${
|
|
22090
|
+
return `<tr><td>${escapeHtml37(carrier.name ?? carrier.provider)}</td><td>${escapeHtml37(carrier.provider)}</td><td><code>${escapeHtml37(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml37(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml37(entry.status)}">${escapeHtml37(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml37(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml37(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml37(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
21861
22091
|
}).join("");
|
|
21862
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
21863
|
-
const snippet =
|
|
22092
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml37(stage)}</code></li>`).join("");
|
|
22093
|
+
const snippet = escapeHtml37(`const phoneAgent = createVoicePhoneAgent({
|
|
21864
22094
|
carriers: [
|
|
21865
22095
|
{
|
|
21866
22096
|
provider: 'twilio',
|
|
@@ -21894,11 +22124,11 @@ app.use(
|
|
|
21894
22124
|
);`);
|
|
21895
22125
|
const checklist = report.carriers.map((carrier) => {
|
|
21896
22126
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
21897
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
21898
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
21899
|
-
return `<article><h3>${
|
|
22127
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml37(issue)}</li>`).join("") ?? "";
|
|
22128
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml37(step)}</li>`).join("") ?? "";
|
|
22129
|
+
return `<article><h3>${escapeHtml37(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
21900
22130
|
}).join("");
|
|
21901
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22131
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml37(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>${escapeHtml37(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="${escapeHtml37(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>`;
|
|
21902
22132
|
};
|
|
21903
22133
|
var createVoicePhoneAgent = (options) => {
|
|
21904
22134
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -21907,7 +22137,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
21907
22137
|
setupPath: resolveSetupPath(carrier),
|
|
21908
22138
|
smokePath: resolveSmokePath(carrier)
|
|
21909
22139
|
}));
|
|
21910
|
-
const app = new
|
|
22140
|
+
const app = new Elysia38({
|
|
21911
22141
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
21912
22142
|
});
|
|
21913
22143
|
for (const carrier of options.carriers) {
|
|
@@ -24041,8 +24271,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
24041
24271
|
};
|
|
24042
24272
|
};
|
|
24043
24273
|
// src/providerCapabilities.ts
|
|
24044
|
-
import { Elysia as
|
|
24045
|
-
var
|
|
24274
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
24275
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24046
24276
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
24047
24277
|
configured: true,
|
|
24048
24278
|
features: options.features?.[provider],
|
|
@@ -24105,27 +24335,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
24105
24335
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
24106
24336
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
24107
24337
|
const cards = report.capabilities.map((capability) => {
|
|
24108
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
24109
|
-
return `<article class="card ${
|
|
24338
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml38(feature)}</span>`).join("");
|
|
24339
|
+
return `<article class="card ${escapeHtml38(capability.status)}">
|
|
24110
24340
|
<div class="card-header">
|
|
24111
24341
|
<div>
|
|
24112
|
-
<p class="eyebrow">${
|
|
24113
|
-
<h2>${
|
|
24342
|
+
<p class="eyebrow">${escapeHtml38(capability.kind)}</p>
|
|
24343
|
+
<h2>${escapeHtml38(capability.label ?? capability.provider)}</h2>
|
|
24114
24344
|
</div>
|
|
24115
|
-
<strong>${
|
|
24345
|
+
<strong>${escapeHtml38(capability.status)}</strong>
|
|
24116
24346
|
</div>
|
|
24117
|
-
${capability.description ? `<p>${
|
|
24347
|
+
${capability.description ? `<p>${escapeHtml38(capability.description)}</p>` : ""}
|
|
24118
24348
|
<dl>
|
|
24119
24349
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
24120
24350
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
24121
|
-
<div><dt>Model</dt><dd>${
|
|
24351
|
+
<div><dt>Model</dt><dd>${escapeHtml38(capability.model ?? "default")}</dd></div>
|
|
24122
24352
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
24123
24353
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
24124
24354
|
</dl>
|
|
24125
24355
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
24126
24356
|
</article>`;
|
|
24127
24357
|
}).join("");
|
|
24128
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24358
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(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>${escapeHtml38(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>`;
|
|
24129
24359
|
};
|
|
24130
24360
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
24131
24361
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -24142,7 +24372,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
24142
24372
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
24143
24373
|
const path = options.path ?? "/api/provider-capabilities";
|
|
24144
24374
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
24145
|
-
const routes = new
|
|
24375
|
+
const routes = new Elysia39({
|
|
24146
24376
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
24147
24377
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
24148
24378
|
if (htmlPath) {
|
|
@@ -24151,7 +24381,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
24151
24381
|
return routes;
|
|
24152
24382
|
};
|
|
24153
24383
|
// src/providerOrchestration.ts
|
|
24154
|
-
import { Elysia as
|
|
24384
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
24155
24385
|
var defaultRequirement = {
|
|
24156
24386
|
minProviders: 1,
|
|
24157
24387
|
requireBudgetPolicy: false,
|
|
@@ -24164,7 +24394,7 @@ var statusRank2 = {
|
|
|
24164
24394
|
warn: 1,
|
|
24165
24395
|
fail: 2
|
|
24166
24396
|
};
|
|
24167
|
-
var
|
|
24397
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24168
24398
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
24169
24399
|
var uniqueSorted6 = (values) => [
|
|
24170
24400
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -24307,27 +24537,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
24307
24537
|
};
|
|
24308
24538
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
24309
24539
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
24310
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
24311
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
24540
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml39(surface.status)}">
|
|
24541
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml39(surface.surface)}</p><h2>${escapeHtml39(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml39(surface.status)}</strong></div>
|
|
24312
24542
|
<dl>
|
|
24313
|
-
<div><dt>Providers</dt><dd>${
|
|
24314
|
-
<div><dt>Fallback</dt><dd>${
|
|
24543
|
+
<div><dt>Providers</dt><dd>${escapeHtml39(surface.providers.join(", ") || "none")}</dd></div>
|
|
24544
|
+
<div><dt>Fallback</dt><dd>${escapeHtml39(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
24315
24545
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
24316
24546
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
24317
24547
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
24318
24548
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
24319
24549
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
24320
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
24550
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml39(surface.fallbackMode || "default")}</dd></div>
|
|
24321
24551
|
</dl>
|
|
24322
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
24552
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml39(issue.status)}</strong> ${escapeHtml39(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
24323
24553
|
</article>`).join("");
|
|
24324
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24554
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(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>${escapeHtml39(title)}</h1><div class="summary"><span class="pill">${escapeHtml39(report.profileId)}</span><span class="pill">${escapeHtml39(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>`;
|
|
24325
24555
|
};
|
|
24326
24556
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
24327
24557
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
24328
24558
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
24329
24559
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
24330
|
-
const routes = new
|
|
24560
|
+
const routes = new Elysia40({
|
|
24331
24561
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
24332
24562
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
24333
24563
|
if (htmlPath) {
|
|
@@ -24498,7 +24728,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
24498
24728
|
return report;
|
|
24499
24729
|
};
|
|
24500
24730
|
// src/providerSlo.ts
|
|
24501
|
-
import { Elysia as
|
|
24731
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
24502
24732
|
var defaultThresholds = {
|
|
24503
24733
|
llm: {
|
|
24504
24734
|
maxAverageElapsedMs: 2500,
|
|
@@ -24531,7 +24761,7 @@ var statusRank3 = {
|
|
|
24531
24761
|
warn: 1,
|
|
24532
24762
|
fail: 2
|
|
24533
24763
|
};
|
|
24534
|
-
var
|
|
24764
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24535
24765
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
24536
24766
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
24537
24767
|
var uniqueSorted7 = (values) => [
|
|
@@ -24827,11 +25057,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24827
25057
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
24828
25058
|
const kindCards = providerKinds.map((kind) => {
|
|
24829
25059
|
const kindReport = report.kinds[kind];
|
|
24830
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
25060
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml40(metric.label)}</dt><dd>${escapeHtml40(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml40(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
24831
25061
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
24832
|
-
return `<article class="${
|
|
25062
|
+
return `<article class="${escapeHtml40(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml40(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml40(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
24833
25063
|
}).join("");
|
|
24834
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
25064
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml40(issue.status)}"><strong>${escapeHtml40(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml40(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
24835
25065
|
const snippet = `createVoiceProviderSloRoutes({
|
|
24836
25066
|
store: runtimeStorage.traces,
|
|
24837
25067
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -24841,7 +25071,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24841
25071
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
24842
25072
|
}
|
|
24843
25073
|
})`;
|
|
24844
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25074
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(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>${escapeHtml40(title)}</h1><p class="status ${escapeHtml40(report.status)}">${escapeHtml40(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>${escapeHtml40(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
24845
25075
|
};
|
|
24846
25076
|
var createVoiceProviderSloRoutes = (options) => {
|
|
24847
25077
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -24852,7 +25082,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24852
25082
|
...options.headers ?? {}
|
|
24853
25083
|
};
|
|
24854
25084
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
24855
|
-
const app = new
|
|
25085
|
+
const app = new Elysia41({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
24856
25086
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
24857
25087
|
if (markdownPath !== false) {
|
|
24858
25088
|
app.get(markdownPath, async () => {
|
|
@@ -24882,10 +25112,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24882
25112
|
return app;
|
|
24883
25113
|
};
|
|
24884
25114
|
// src/productionReadiness.ts
|
|
24885
|
-
import { Elysia as
|
|
25115
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
24886
25116
|
|
|
24887
25117
|
// src/telephony/security.ts
|
|
24888
|
-
import { Elysia as
|
|
25118
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24889
25119
|
|
|
24890
25120
|
// src/postgresStore.ts
|
|
24891
25121
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -25623,7 +25853,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
25623
25853
|
};
|
|
25624
25854
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
25625
25855
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
25626
|
-
return new
|
|
25856
|
+
return new Elysia42({
|
|
25627
25857
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
25628
25858
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
25629
25859
|
};
|
|
@@ -25680,8 +25910,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
25680
25910
|
};
|
|
25681
25911
|
|
|
25682
25912
|
// src/opsRecovery.ts
|
|
25683
|
-
import { Elysia as
|
|
25684
|
-
var
|
|
25913
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
25914
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25685
25915
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
25686
25916
|
var hrefForSession = (value, sessionId) => {
|
|
25687
25917
|
if (typeof value === "function") {
|
|
@@ -25895,19 +26125,19 @@ ${failedSessions || "None."}
|
|
|
25895
26125
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
25896
26126
|
`;
|
|
25897
26127
|
};
|
|
25898
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
26128
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml41(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>${escapeHtml41(label)}</span><strong>not configured</strong></article>`;
|
|
25899
26129
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
25900
26130
|
const title = options.title ?? "Voice Ops Recovery";
|
|
25901
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
25902
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
25903
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
25904
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26131
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml41(issue.severity)}</td><td><code>${escapeHtml41(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml41(issue.href)}">${escapeHtml41(issue.label)}</a>` : escapeHtml41(issue.label)}</td><td>${escapeHtml41(String(issue.value ?? ""))}</td><td>${escapeHtml41(issue.detail ?? "")}</td></tr>`).join("");
|
|
26132
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml41(provider.provider)}</td><td>${escapeHtml41(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml41(provider.lastError ?? "")}</td></tr>`).join("");
|
|
26133
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml41(session.operationsRecordHref)}">${escapeHtml41(session.sessionId)}</a>` : escapeHtml41(session.sessionId)}${session.provider ? ` via ${escapeHtml41(session.provider)}` : ""}${session.error ? `: ${escapeHtml41(session.error)}` : ""}</li>`).join("");
|
|
26134
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(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>${escapeHtml41(title)}</h1><p><span class="status">${escapeHtml41(report.status)}</span> Checked ${escapeHtml41(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>${escapeHtml41(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>`;
|
|
25905
26135
|
};
|
|
25906
26136
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
25907
26137
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
25908
26138
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
25909
26139
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
25910
|
-
const routes = new
|
|
26140
|
+
const routes = new Elysia43({
|
|
25911
26141
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
25912
26142
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
25913
26143
|
if (htmlPath) {
|
|
@@ -25937,18 +26167,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
25937
26167
|
};
|
|
25938
26168
|
|
|
25939
26169
|
// src/observabilityExport.ts
|
|
25940
|
-
import { Elysia as
|
|
26170
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
25941
26171
|
import { Database as Database4 } from "bun:sqlite";
|
|
25942
26172
|
import { createHash } from "crypto";
|
|
25943
26173
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
25944
26174
|
import { join as join3 } from "path";
|
|
25945
26175
|
|
|
25946
26176
|
// src/operationsRecord.ts
|
|
25947
|
-
import { Elysia as
|
|
26177
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
25948
26178
|
|
|
25949
26179
|
// src/traceTimeline.ts
|
|
25950
|
-
import { Elysia as
|
|
25951
|
-
var
|
|
26180
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
26181
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25952
26182
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
25953
26183
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
25954
26184
|
var firstString3 = (payload, keys) => {
|
|
@@ -26131,17 +26361,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
26131
26361
|
};
|
|
26132
26362
|
};
|
|
26133
26363
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
26134
|
-
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>${
|
|
26364
|
+
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>${escapeHtml42(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>`;
|
|
26135
26365
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
26136
|
-
const events = session.events.map((event) => `<tr class="${
|
|
26137
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
26138
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
26139
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26366
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml42(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml42(event.type)}</td><td>${escapeHtml42(event.label)}</td><td>${escapeHtml42(event.provider ?? "")}</td><td>${escapeHtml42(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
26367
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml42(issue.severity)}">${escapeHtml42(issue.code)}: ${escapeHtml42(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
26368
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml42(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
26369
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(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>${escapeHtml42(session.sessionId)}</h1><p class="status ${escapeHtml42(session.status)}">${escapeHtml42(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>`;
|
|
26140
26370
|
};
|
|
26141
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
26371
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml42(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml42(session.operationsRecordHref)}">${escapeHtml42(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml42(session.sessionId)}</a>`}</td><td>${escapeHtml42(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) => escapeHtml42(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
26142
26372
|
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}}";
|
|
26143
26373
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
26144
|
-
const snippet =
|
|
26374
|
+
const snippet = escapeHtml42(`const traceStore = createVoiceTraceSinkStore({
|
|
26145
26375
|
store: runtimeStorage.traces,
|
|
26146
26376
|
sinks: [
|
|
26147
26377
|
createVoiceTraceHTTPSink({
|
|
@@ -26167,13 +26397,13 @@ app.use(
|
|
|
26167
26397
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
26168
26398
|
})
|
|
26169
26399
|
);`);
|
|
26170
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26400
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(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>${escapeHtml42(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>`;
|
|
26171
26401
|
};
|
|
26172
26402
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
26173
26403
|
const path = options.path ?? "/api/voice-traces";
|
|
26174
26404
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
26175
26405
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
26176
|
-
const routes = new
|
|
26406
|
+
const routes = new Elysia44({
|
|
26177
26407
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
26178
26408
|
});
|
|
26179
26409
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -26602,7 +26832,7 @@ var assertVoiceOperationsRecordProviderRecovery = (record, input = {}) => {
|
|
|
26602
26832
|
}
|
|
26603
26833
|
return report;
|
|
26604
26834
|
};
|
|
26605
|
-
var
|
|
26835
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26606
26836
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
26607
26837
|
var outcomeLabels = (outcome) => [
|
|
26608
26838
|
outcome.complete ? "complete" : undefined,
|
|
@@ -26682,20 +26912,20 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
26682
26912
|
`);
|
|
26683
26913
|
};
|
|
26684
26914
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
26685
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
26686
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
26687
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
26915
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml43(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>';
|
|
26916
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml43(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml43(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml43(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml43(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
26917
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml43(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml43(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml43(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml43(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml43(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml43(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml43(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml43(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
26688
26918
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
26689
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
26690
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
26691
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
26692
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
26693
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
26919
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml43(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml43(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml43(handoff.status ?? "")}</span><p>${escapeHtml43(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
26920
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml43(tool.toolName ?? "tool")}</strong> <span>${escapeHtml43(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml43(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
26921
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml43(review.title)}</strong> <span>${escapeHtml43(review.summary.outcome ?? "")}</span><p>${escapeHtml43(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
26922
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml43(task.title)}</strong> <span>${escapeHtml43(task.status)}</span><p>${escapeHtml43(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
26923
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml43(event.type)}</strong> <span>${escapeHtml43(event.deliveryStatus ?? "local")}</span><p>${escapeHtml43(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
26694
26924
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
26695
26925
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
26696
|
-
return `<li><strong>assistant.guardrail ${
|
|
26926
|
+
return `<li><strong>assistant.guardrail ${escapeHtml43(decision.stage ?? "unknown")}</strong> <span>${escapeHtml43(decision.status ?? "")}</span><p>Allowed: ${escapeHtml43(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml43(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml43(decision.turnId)}` : ""}</p><p>${escapeHtml43(findings)}</p></li>`;
|
|
26697
26927
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
26698
|
-
const snippet =
|
|
26928
|
+
const snippet = escapeHtml43(`app.use(
|
|
26699
26929
|
createVoiceOperationsRecordRoutes({
|
|
26700
26930
|
audit: auditStore,
|
|
26701
26931
|
integrationEvents: opsEvents,
|
|
@@ -26709,16 +26939,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
26709
26939
|
tasks: opsTasks
|
|
26710
26940
|
})
|
|
26711
26941
|
);`);
|
|
26712
|
-
const incidentMarkdown =
|
|
26713
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
26714
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26942
|
+
const incidentMarkdown = escapeHtml43(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
26943
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml43(options.incidentHref)}">Download incident.md</a>` : "";
|
|
26944
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(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>${escapeHtml43(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml43(record.status)}">${escapeHtml43(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</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>${escapeHtml43(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</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="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, 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>`;
|
|
26715
26945
|
};
|
|
26716
26946
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
26717
26947
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
26718
26948
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
26719
26949
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
26720
26950
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
26721
|
-
const routes = new
|
|
26951
|
+
const routes = new Elysia45({
|
|
26722
26952
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
26723
26953
|
});
|
|
26724
26954
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -27369,7 +27599,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
27369
27599
|
...options.headers ?? {}
|
|
27370
27600
|
};
|
|
27371
27601
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
27372
|
-
const app = new
|
|
27602
|
+
const app = new Elysia46({
|
|
27373
27603
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
27374
27604
|
});
|
|
27375
27605
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28178,7 +28408,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28178
28408
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
28179
28409
|
}
|
|
28180
28410
|
});
|
|
28181
|
-
const app = new
|
|
28411
|
+
const app = new Elysia46({
|
|
28182
28412
|
name: options.name ?? "absolute-voice-observability-export"
|
|
28183
28413
|
});
|
|
28184
28414
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28255,7 +28485,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28255
28485
|
};
|
|
28256
28486
|
|
|
28257
28487
|
// src/productionReadiness.ts
|
|
28258
|
-
var
|
|
28488
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28259
28489
|
var rollupStatus3 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
28260
28490
|
var readinessGateCodes = {
|
|
28261
28491
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -29710,25 +29940,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29710
29940
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
29711
29941
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
29712
29942
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
29713
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
29714
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
29943
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml44(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
29944
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml44(report.profile.name)}</h2><p>${escapeHtml44(report.profile.description)}</p><p>${escapeHtml44(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="${escapeHtml44(surface.href)}">${escapeHtml44(surface.label)}</a>` : escapeHtml44(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
29715
29945
|
const checks = report.checks.map((check, index) => {
|
|
29716
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
29717
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
29718
|
-
return `<article class="check ${
|
|
29946
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml44(action.href)}">${escapeHtml44(action.label)}</button>` : `<a href="${escapeHtml44(action.href)}">${escapeHtml44(action.label)}</a>`).join("");
|
|
29947
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml44(check.status)}: observed ${escapeHtml44(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml44(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml44(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml44(check.gateExplanation.unit)}` : ""}. ${escapeHtml44(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml44(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
29948
|
+
return `<article class="check ${escapeHtml44(check.status)}">
|
|
29719
29949
|
<div>
|
|
29720
|
-
<span>${
|
|
29721
|
-
<h2>${
|
|
29722
|
-
${check.detail ? `<p>${
|
|
29950
|
+
<span>${escapeHtml44(check.status.toUpperCase())}</span>
|
|
29951
|
+
<h2>${escapeHtml44(check.label)}</h2>
|
|
29952
|
+
${check.detail ? `<p>${escapeHtml44(check.detail)}</p>` : ""}
|
|
29723
29953
|
${explanation}
|
|
29724
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
29954
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml44(check.proofSource.href)}">${escapeHtml44(check.proofSource.sourceLabel)}</a>` : escapeHtml44(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml44(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
29725
29955
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
29726
29956
|
</div>
|
|
29727
|
-
<strong>${
|
|
29728
|
-
${check.href ? `<a href="${
|
|
29957
|
+
<strong>${escapeHtml44(String(check.value ?? check.status))}</strong>
|
|
29958
|
+
${check.href ? `<a href="${escapeHtml44(check.href)}">Open surface</a>` : ""}
|
|
29729
29959
|
</article>`;
|
|
29730
29960
|
}).join("");
|
|
29731
|
-
const snippet =
|
|
29961
|
+
const snippet = escapeHtml44(`createVoiceProductionReadinessRoutes({
|
|
29732
29962
|
htmlPath: '/production-readiness',
|
|
29733
29963
|
path: '/api/production-readiness',
|
|
29734
29964
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -29744,13 +29974,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
29744
29974
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
29745
29975
|
store: traceStore
|
|
29746
29976
|
});`);
|
|
29747
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29977
|
+
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:#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>${escapeHtml44(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 ${escapeHtml44(report.status)}">Overall: ${escapeHtml44(report.status.toUpperCase())}</p><p>Checked ${escapeHtml44(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>`;
|
|
29748
29978
|
};
|
|
29749
29979
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
29750
29980
|
const path = options.path ?? "/api/production-readiness";
|
|
29751
29981
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
29752
29982
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
29753
|
-
const routes = new
|
|
29983
|
+
const routes = new Elysia47({
|
|
29754
29984
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
29755
29985
|
});
|
|
29756
29986
|
const resolveOptions = async (input) => {
|
|
@@ -29798,8 +30028,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
29798
30028
|
return routes;
|
|
29799
30029
|
};
|
|
29800
30030
|
// src/voiceMonitoring.ts
|
|
29801
|
-
import { Elysia as
|
|
29802
|
-
var
|
|
30031
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
30032
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29803
30033
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
29804
30034
|
var rollupStatus4 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
29805
30035
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -30052,14 +30282,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
30052
30282
|
};
|
|
30053
30283
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
30054
30284
|
const title = options.title ?? "Voice Monitors";
|
|
30055
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
30056
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
30057
|
-
const snippet =
|
|
30285
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml45(run.label)}</td><td class="${escapeHtml45(run.status)}">${escapeHtml45(run.status)}</td><td>${escapeHtml45(run.severity)}</td><td>${escapeHtml45(String(run.value ?? ""))}</td><td>${escapeHtml45(String(run.threshold ?? ""))}</td><td>${escapeHtml45(run.detail ?? "")}</td></tr>`).join("");
|
|
30286
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml45(issue.label)}</strong> <span class="${escapeHtml45(issue.status)}">${escapeHtml45(issue.status)}</span> ${escapeHtml45(issue.detail ?? "")}</li>`).join("");
|
|
30287
|
+
const snippet = escapeHtml45(`app.use(createVoiceMonitorRoutes({
|
|
30058
30288
|
evidence,
|
|
30059
30289
|
issueStore,
|
|
30060
30290
|
monitors: [defineVoiceMonitor(...)]
|
|
30061
30291
|
}));`);
|
|
30062
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30292
|
+
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:#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>${escapeHtml45(title)}</h1><p class="pill ${escapeHtml45(report.status)}">Status: ${escapeHtml45(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>`;
|
|
30063
30293
|
};
|
|
30064
30294
|
var actorFromRequest = async (request) => {
|
|
30065
30295
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -30083,7 +30313,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30083
30313
|
monitors: options.monitors,
|
|
30084
30314
|
now: options.now
|
|
30085
30315
|
});
|
|
30086
|
-
const routes = new
|
|
30316
|
+
const routes = new Elysia48({
|
|
30087
30317
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
30088
30318
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
30089
30319
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -30130,7 +30360,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30130
30360
|
};
|
|
30131
30361
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
30132
30362
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
30133
|
-
return new
|
|
30363
|
+
return new Elysia48({
|
|
30134
30364
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
30135
30365
|
}).get(path, () => ({
|
|
30136
30366
|
isRunning: options.runner.isRunning()
|
|
@@ -30506,8 +30736,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
30506
30736
|
};
|
|
30507
30737
|
};
|
|
30508
30738
|
// src/providerStackRecommendations.ts
|
|
30509
|
-
import { Elysia as
|
|
30510
|
-
var
|
|
30739
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
30740
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30511
30741
|
var profileProviderPriorities = {
|
|
30512
30742
|
"meeting-recorder": {
|
|
30513
30743
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -30826,17 +31056,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
30826
31056
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
30827
31057
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
30828
31058
|
const rows = report.rows.map((row) => {
|
|
30829
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
30830
|
-
return `<article class="row ${
|
|
31059
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml46(check.status)}"><strong>${escapeHtml46(check.label)}</strong><span>${escapeHtml46(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml46(check.remediation.href)}">${escapeHtml46(check.remediation.label)}</a>` : escapeHtml46(check.remediation.label)}: ${escapeHtml46(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
31060
|
+
return `<article class="row ${escapeHtml46(row.status)}">
|
|
30831
31061
|
<div>
|
|
30832
|
-
<p class="eyebrow">${
|
|
30833
|
-
<h2>${
|
|
30834
|
-
<p class="status ${
|
|
31062
|
+
<p class="eyebrow">${escapeHtml46(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
31063
|
+
<h2>${escapeHtml46(row.provider)}</h2>
|
|
31064
|
+
<p class="status ${escapeHtml46(row.status)}">${escapeHtml46(row.status.toUpperCase())}</p>
|
|
30835
31065
|
</div>
|
|
30836
31066
|
<ul>${checks}</ul>
|
|
30837
31067
|
</article>`;
|
|
30838
31068
|
}).join("");
|
|
30839
|
-
const snippet =
|
|
31069
|
+
const snippet = escapeHtml46(`const providerContracts = () =>
|
|
30840
31070
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
30841
31071
|
env: process.env,
|
|
30842
31072
|
providers: {
|
|
@@ -30857,7 +31087,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
30857
31087
|
providerContractMatrix: () =>
|
|
30858
31088
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
30859
31089
|
});`);
|
|
30860
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31090
|
+
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:#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>${escapeHtml46(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>`;
|
|
30861
31091
|
};
|
|
30862
31092
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
30863
31093
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -30872,7 +31102,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
30872
31102
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
30873
31103
|
const path = options.path ?? "/api/provider-contracts";
|
|
30874
31104
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
30875
|
-
const routes = new
|
|
31105
|
+
const routes = new Elysia49({
|
|
30876
31106
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
30877
31107
|
});
|
|
30878
31108
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -30990,7 +31220,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
30990
31220
|
return assertion;
|
|
30991
31221
|
};
|
|
30992
31222
|
// src/opsConsoleRoutes.ts
|
|
30993
|
-
import { Elysia as
|
|
31223
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
30994
31224
|
var DEFAULT_LINKS = [
|
|
30995
31225
|
{
|
|
30996
31226
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -31025,7 +31255,7 @@ var DEFAULT_LINKS = [
|
|
|
31025
31255
|
label: "Handoffs"
|
|
31026
31256
|
}
|
|
31027
31257
|
];
|
|
31028
|
-
var
|
|
31258
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31029
31259
|
var countProviderStatuses = (providers) => {
|
|
31030
31260
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
31031
31261
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -31094,20 +31324,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
31094
31324
|
trace
|
|
31095
31325
|
};
|
|
31096
31326
|
};
|
|
31097
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
31327
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml47(input.label)}</span><strong>${escapeHtml47(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml47(input.status)}">${escapeHtml47(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml47(input.href)}">Open</a>` : ""}</article>`;
|
|
31098
31328
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
31099
31329
|
const links = report.links.map((link) => `<article class="surface">
|
|
31100
|
-
<div><h2>${
|
|
31101
|
-
<p><a href="${
|
|
31330
|
+
<div><h2>${escapeHtml47(link.label)}</h2>${link.description ? `<p>${escapeHtml47(link.description)}</p>` : ""}</div>
|
|
31331
|
+
<p><a href="${escapeHtml47(link.href)}">Open ${escapeHtml47(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml47(link.statusHref)}">Status</a>` : ""}</p>
|
|
31102
31332
|
</article>`).join("");
|
|
31103
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
31104
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
31333
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml47(session.sessionId)}</td><td>${escapeHtml47(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml47(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
31334
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml47(event.kind)}</td><td>${escapeHtml47(event.provider ?? "unknown")}</td><td>${escapeHtml47(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml47(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
31105
31335
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
31106
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31336
|
+
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:#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>${escapeHtml47(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 ${escapeHtml47(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>`;
|
|
31107
31337
|
};
|
|
31108
31338
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
31109
31339
|
const path = options.path ?? "/ops-console";
|
|
31110
|
-
const routes = new
|
|
31340
|
+
const routes = new Elysia50({
|
|
31111
31341
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
31112
31342
|
});
|
|
31113
31343
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -31124,7 +31354,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
31124
31354
|
return routes;
|
|
31125
31355
|
};
|
|
31126
31356
|
// src/incidentBundle.ts
|
|
31127
|
-
import { Elysia as
|
|
31357
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
31128
31358
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
31129
31359
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
31130
31360
|
return false;
|
|
@@ -31325,7 +31555,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
31325
31555
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
31326
31556
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
31327
31557
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
31328
|
-
const routes = new
|
|
31558
|
+
const routes = new Elysia51({
|
|
31329
31559
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
31330
31560
|
});
|
|
31331
31561
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -31526,19 +31756,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
31526
31756
|
};
|
|
31527
31757
|
};
|
|
31528
31758
|
// src/opsStatusRoutes.ts
|
|
31529
|
-
import { Elysia as
|
|
31530
|
-
var
|
|
31759
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
31760
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31531
31761
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
31532
31762
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
31533
31763
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
31534
31764
|
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;
|
|
31535
|
-
return `<article class="surface ${
|
|
31765
|
+
return `<article class="surface ${escapeHtml48(surface.status)}"><span>${escapeHtml48(surface.status.toUpperCase())}</span><h2>${escapeHtml48(key)}</h2><strong>${escapeHtml48(value)}</strong></article>`;
|
|
31536
31766
|
}).join("");
|
|
31537
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31767
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(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>${escapeHtml48(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml48(report.status)}">Overall: ${escapeHtml48(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>`;
|
|
31538
31768
|
};
|
|
31539
31769
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
31540
31770
|
const path = options.path ?? "/api/voice/ops-status";
|
|
31541
|
-
const routes = new
|
|
31771
|
+
const routes = new Elysia52({
|
|
31542
31772
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
31543
31773
|
});
|
|
31544
31774
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -31971,8 +32201,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
31971
32201
|
};
|
|
31972
32202
|
};
|
|
31973
32203
|
// src/traceDeliveryRoutes.ts
|
|
31974
|
-
import { Elysia as
|
|
31975
|
-
var
|
|
32204
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
32205
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31976
32206
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
31977
32207
|
var getNumber12 = (value) => {
|
|
31978
32208
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -32053,14 +32283,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
32053
32283
|
if (entries.length === 0) {
|
|
32054
32284
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
32055
32285
|
}
|
|
32056
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
32286
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml49(sinkId)}</strong>: ${escapeHtml49(result.status)}${result.deliveredTo ? ` to ${escapeHtml49(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml49(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
32057
32287
|
};
|
|
32058
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
32288
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml49(event.type)} <small>${escapeHtml49(event.id)}</small>${event.sessionId ? ` session=${escapeHtml49(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
32059
32289
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
32060
32290
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
32061
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
32062
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
32063
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32291
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml49(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
32292
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml49(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml49(delivery.deliveryStatus)}</span><h2>${escapeHtml49(delivery.id)}</h2><p>${escapeHtml49(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml49(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml49(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
32293
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(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>${escapeHtml49(title)}</h1><p>Checked ${escapeHtml49(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>`;
|
|
32064
32294
|
};
|
|
32065
32295
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
32066
32296
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -32080,7 +32310,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
32080
32310
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
32081
32311
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
32082
32312
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
32083
|
-
const routes = new
|
|
32313
|
+
const routes = new Elysia53({
|
|
32084
32314
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
32085
32315
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
32086
32316
|
if (htmlPath !== false) {
|
|
@@ -32177,7 +32407,7 @@ var createVoiceMemoryStore = () => {
|
|
|
32177
32407
|
return { get, getOrCreate, list, remove, set };
|
|
32178
32408
|
};
|
|
32179
32409
|
// src/opsWebhook.ts
|
|
32180
|
-
import { Elysia as
|
|
32410
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
32181
32411
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
32182
32412
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
32183
32413
|
const encoder = new TextEncoder;
|
|
@@ -32307,7 +32537,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
32307
32537
|
};
|
|
32308
32538
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
32309
32539
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
32310
|
-
return new
|
|
32540
|
+
return new Elysia54().post(path, async ({ body, request, set }) => {
|
|
32311
32541
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
32312
32542
|
if (options.signingSecret) {
|
|
32313
32543
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -32762,7 +32992,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
32762
32992
|
};
|
|
32763
32993
|
};
|
|
32764
32994
|
// src/postCallAnalysis.ts
|
|
32765
|
-
import { Elysia as
|
|
32995
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
32766
32996
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
32767
32997
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
32768
32998
|
var getPathValue3 = (source, path) => {
|
|
@@ -32941,7 +33171,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
32941
33171
|
};
|
|
32942
33172
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
32943
33173
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
32944
|
-
const routes = new
|
|
33174
|
+
const routes = new Elysia55({
|
|
32945
33175
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
32946
33176
|
});
|
|
32947
33177
|
routes.get(path, async ({ query }) => {
|
|
@@ -32966,7 +33196,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
32966
33196
|
return routes;
|
|
32967
33197
|
};
|
|
32968
33198
|
// src/guardrails.ts
|
|
32969
|
-
import { Elysia as
|
|
33199
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
32970
33200
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
32971
33201
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
32972
33202
|
var matchesRule = async (rule, input) => {
|
|
@@ -33268,7 +33498,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
33268
33498
|
};
|
|
33269
33499
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
33270
33500
|
const path = options.path ?? "/api/voice/guardrails";
|
|
33271
|
-
const routes = new
|
|
33501
|
+
const routes = new Elysia56({
|
|
33272
33502
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
33273
33503
|
});
|
|
33274
33504
|
routes.all(path, async ({ request }) => {
|
|
@@ -33829,6 +34059,8 @@ export {
|
|
|
33829
34059
|
renderVoiceDeliveryRuntimeHTML,
|
|
33830
34060
|
renderVoiceDataControlMarkdown,
|
|
33831
34061
|
renderVoiceDataControlHTML,
|
|
34062
|
+
renderVoiceCompetitiveCoverageMarkdown,
|
|
34063
|
+
renderVoiceCompetitiveCoverageHTML,
|
|
33832
34064
|
renderVoiceCampaignsHTML,
|
|
33833
34065
|
renderVoiceCampaignObservabilityHTML,
|
|
33834
34066
|
renderVoiceCallReviewMarkdown,
|
|
@@ -33905,6 +34137,7 @@ export {
|
|
|
33905
34137
|
evaluateVoiceLiveOpsControlEvidence,
|
|
33906
34138
|
evaluateVoiceGuardrailPolicy,
|
|
33907
34139
|
evaluateVoiceDataControlEvidence,
|
|
34140
|
+
evaluateVoiceCompetitiveCoverage,
|
|
33908
34141
|
evaluateVoiceCampaignReadinessEvidence,
|
|
33909
34142
|
evaluateVoiceCampaignDialerProofEvidence,
|
|
33910
34143
|
evaluateVoiceAgentSquadContractEvidence,
|
|
@@ -34145,6 +34378,7 @@ export {
|
|
|
34145
34378
|
createVoiceDeliveryRuntimePresetConfig,
|
|
34146
34379
|
createVoiceDeliveryRuntime,
|
|
34147
34380
|
createVoiceDataControlRoutes,
|
|
34381
|
+
createVoiceCompetitiveCoverageRoutes,
|
|
34148
34382
|
createVoiceCampaignWorkerLoop,
|
|
34149
34383
|
createVoiceCampaignWorker,
|
|
34150
34384
|
createVoiceCampaignTelephonyOutcomeHandler,
|
|
@@ -34246,6 +34480,7 @@ export {
|
|
|
34246
34480
|
buildVoiceDeliveryRuntimeReport,
|
|
34247
34481
|
buildVoiceDataRetentionPlan,
|
|
34248
34482
|
buildVoiceDataControlReport,
|
|
34483
|
+
buildVoiceCompetitiveCoverageReport,
|
|
34249
34484
|
buildVoiceCampaignObservabilityReport,
|
|
34250
34485
|
buildVoiceAuditTrailReport,
|
|
34251
34486
|
buildVoiceAuditExport,
|
|
@@ -34278,6 +34513,7 @@ export {
|
|
|
34278
34513
|
assertVoiceLiveOpsControlEvidence,
|
|
34279
34514
|
assertVoiceLatencySLOGate,
|
|
34280
34515
|
assertVoiceDataControlEvidence,
|
|
34516
|
+
assertVoiceCompetitiveCoverage,
|
|
34281
34517
|
assertVoiceCampaignReadinessEvidence,
|
|
34282
34518
|
assertVoiceCampaignDialerProofEvidence,
|
|
34283
34519
|
assertVoiceAgentSquadContractEvidence,
|