@absolutejs/voice 0.0.22-beta.310 → 0.0.22-beta.311
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/index.d.ts +2 -0
- package/dist/index.js +588 -413
- package/dist/mediaPipelineRoutes.d.ts +93 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11818,9 +11818,178 @@ var buildVoiceMediaPipelineCalibrationReport = (input = {}) => {
|
|
|
11818
11818
|
turnCommitFrames: turnCommitFrames.length
|
|
11819
11819
|
};
|
|
11820
11820
|
};
|
|
11821
|
-
// src/
|
|
11821
|
+
// src/mediaPipelineRoutes.ts
|
|
11822
11822
|
import { Elysia as Elysia12 } from "elysia";
|
|
11823
|
-
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11823
|
+
var escapeHtml15 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11824
|
+
var statusRank2 = {
|
|
11825
|
+
pass: 0,
|
|
11826
|
+
warn: 1,
|
|
11827
|
+
fail: 2
|
|
11828
|
+
};
|
|
11829
|
+
var worstStatus = (statuses) => statuses.reduce((worst, status) => statusRank2[status] > statusRank2[worst] ? status : worst, "pass");
|
|
11830
|
+
var buildVoiceMediaPipelineReport = (options = {}) => {
|
|
11831
|
+
const frames = options.frames ?? [];
|
|
11832
|
+
const calibration = buildVoiceMediaPipelineCalibrationReport(options);
|
|
11833
|
+
const vad = buildVoiceMediaVadReport({
|
|
11834
|
+
frames,
|
|
11835
|
+
maxSilenceFrames: options.maxSilenceFrames,
|
|
11836
|
+
minSpeechFrames: options.minSpeechFrames,
|
|
11837
|
+
speechEndThreshold: options.speechEndThreshold,
|
|
11838
|
+
speechStartThreshold: options.speechStartThreshold
|
|
11839
|
+
});
|
|
11840
|
+
const interruption = buildVoiceMediaInterruptionReport({
|
|
11841
|
+
frames,
|
|
11842
|
+
maxInterruptionLatencyMs: options.maxInterruptionLatencyMs
|
|
11843
|
+
});
|
|
11844
|
+
const resampling = calibration.inputFormat && calibration.outputFormat ? buildVoiceMediaResamplingPlan({
|
|
11845
|
+
inputFormat: calibration.inputFormat,
|
|
11846
|
+
outputFormat: calibration.outputFormat
|
|
11847
|
+
}) : undefined;
|
|
11848
|
+
const status = worstStatus([
|
|
11849
|
+
calibration.status,
|
|
11850
|
+
vad.status,
|
|
11851
|
+
interruption.status,
|
|
11852
|
+
resampling?.status ?? "pass"
|
|
11853
|
+
]);
|
|
11854
|
+
return {
|
|
11855
|
+
calibration,
|
|
11856
|
+
checkedAt: Date.now(),
|
|
11857
|
+
frames: frames.length,
|
|
11858
|
+
interruption,
|
|
11859
|
+
ok: status === "pass",
|
|
11860
|
+
resampling,
|
|
11861
|
+
status,
|
|
11862
|
+
surface: options.surface ?? "voice-media-pipeline",
|
|
11863
|
+
vad
|
|
11864
|
+
};
|
|
11865
|
+
};
|
|
11866
|
+
var evaluateVoiceMediaPipelineEvidence = (report, input = {}) => {
|
|
11867
|
+
const issues = [];
|
|
11868
|
+
if ((input.requirePass ?? false) && report.status !== "pass") {
|
|
11869
|
+
issues.push(`Expected media pipeline proof to pass, found ${report.status}.`);
|
|
11870
|
+
}
|
|
11871
|
+
if (input.minInputAudioFrames !== undefined && report.calibration.inputAudioFrames < input.minInputAudioFrames) {
|
|
11872
|
+
issues.push(`Expected at least ${String(input.minInputAudioFrames)} input audio frame(s), found ${String(report.calibration.inputAudioFrames)}.`);
|
|
11873
|
+
}
|
|
11874
|
+
if (input.minAssistantAudioFrames !== undefined && report.calibration.assistantAudioFrames < input.minAssistantAudioFrames) {
|
|
11875
|
+
issues.push(`Expected at least ${String(input.minAssistantAudioFrames)} assistant audio frame(s), found ${String(report.calibration.assistantAudioFrames)}.`);
|
|
11876
|
+
}
|
|
11877
|
+
if (input.minTraceLinkedFrames !== undefined && report.calibration.traceLinkedFrames < input.minTraceLinkedFrames) {
|
|
11878
|
+
issues.push(`Expected at least ${String(input.minTraceLinkedFrames)} trace-linked frame(s), found ${String(report.calibration.traceLinkedFrames)}.`);
|
|
11879
|
+
}
|
|
11880
|
+
if (input.maxFirstAudioLatencyMs !== undefined && (report.calibration.firstAudioLatencyMs === undefined || report.calibration.firstAudioLatencyMs > input.maxFirstAudioLatencyMs)) {
|
|
11881
|
+
issues.push(`Expected first assistant audio at or below ${String(input.maxFirstAudioLatencyMs)}ms, found ${String(report.calibration.firstAudioLatencyMs ?? "missing")}ms.`);
|
|
11882
|
+
}
|
|
11883
|
+
if (input.minVadSegments !== undefined && report.vad.segments.length < input.minVadSegments) {
|
|
11884
|
+
issues.push(`Expected at least ${String(input.minVadSegments)} VAD segment(s), found ${String(report.vad.segments.length)}.`);
|
|
11885
|
+
}
|
|
11886
|
+
if (input.requireInterruptionFrame && report.interruption.interruptionFrames < 1) {
|
|
11887
|
+
issues.push("Expected at least one interruption frame.");
|
|
11888
|
+
}
|
|
11889
|
+
if (input.maxInterruptionLatencyMs !== undefined && report.interruption.latenciesMs.some((latency) => latency > input.maxInterruptionLatencyMs)) {
|
|
11890
|
+
issues.push(`Expected interruption latency at or below ${String(input.maxInterruptionLatencyMs)}ms.`);
|
|
11891
|
+
}
|
|
11892
|
+
if (input.requireResamplingReady && report.calibration.resamplingRequired && !report.resampling) {
|
|
11893
|
+
issues.push("Expected resampling plan when calibration requires resampling.");
|
|
11894
|
+
}
|
|
11895
|
+
return {
|
|
11896
|
+
issues,
|
|
11897
|
+
ok: issues.length === 0,
|
|
11898
|
+
status: report.status,
|
|
11899
|
+
surface: report.surface
|
|
11900
|
+
};
|
|
11901
|
+
};
|
|
11902
|
+
var assertVoiceMediaPipelineEvidence = (report, input = {}) => {
|
|
11903
|
+
const assertion = evaluateVoiceMediaPipelineEvidence(report, input);
|
|
11904
|
+
if (!assertion.ok) {
|
|
11905
|
+
throw new Error(`Voice media pipeline assertion failed: ${assertion.issues.join(" ")}`);
|
|
11906
|
+
}
|
|
11907
|
+
return assertion;
|
|
11908
|
+
};
|
|
11909
|
+
var renderVoiceMediaPipelineMarkdown = (report) => [
|
|
11910
|
+
"# Voice Media Pipeline Proof",
|
|
11911
|
+
"",
|
|
11912
|
+
`- Status: ${report.status}`,
|
|
11913
|
+
`- Surface: ${report.surface}`,
|
|
11914
|
+
`- Frames: ${String(report.frames)}`,
|
|
11915
|
+
`- Input audio frames: ${String(report.calibration.inputAudioFrames)}`,
|
|
11916
|
+
`- Assistant audio frames: ${String(report.calibration.assistantAudioFrames)}`,
|
|
11917
|
+
`- Trace-linked frames: ${String(report.calibration.traceLinkedFrames)}`,
|
|
11918
|
+
`- First audio latency: ${String(report.calibration.firstAudioLatencyMs ?? "n/a")}ms`,
|
|
11919
|
+
`- Resampling required: ${report.calibration.resamplingRequired ? "yes" : "no"}`,
|
|
11920
|
+
`- VAD segments: ${String(report.vad.segments.length)}`,
|
|
11921
|
+
`- Interruption frames: ${String(report.interruption.interruptionFrames)}`,
|
|
11922
|
+
"",
|
|
11923
|
+
"## Issues",
|
|
11924
|
+
"",
|
|
11925
|
+
...[
|
|
11926
|
+
...report.calibration.issues,
|
|
11927
|
+
...report.interruption.issues
|
|
11928
|
+
].map((issue) => `- ${issue.severity.toUpperCase()} ${issue.code}: ${issue.message}`),
|
|
11929
|
+
...report.calibration.issues.length + report.interruption.issues.length === 0 ? ["- None"] : []
|
|
11930
|
+
].join(`
|
|
11931
|
+
`);
|
|
11932
|
+
var renderVoiceMediaPipelineHTML = (report, title = "Voice Media Pipeline Proof") => {
|
|
11933
|
+
const issues = [...report.calibration.issues, ...report.interruption.issues].map((issue) => `<li class="${escapeHtml15(issue.severity)}"><strong>${escapeHtml15(issue.code)}</strong>: ${escapeHtml15(issue.message)}</li>`).join("");
|
|
11934
|
+
const segments = report.vad.segments.map((segment) => `<tr><td>${escapeHtml15(segment.segmentId)}</td><td>${escapeHtml15(segment.frameCount)}</td><td>${escapeHtml15(segment.durationMs ?? "n/a")}</td><td>${escapeHtml15(segment.turnId ?? "n/a")}</td></tr>`).join("");
|
|
11935
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml15(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}.metric{background:#101814;border:1px solid #2e3d36;border-radius:18px;padding:14px}.metric span{color:#a8b5ad;display:block;font-size:.78rem;text-transform:uppercase}.metric strong{display:block;font-size:1.65rem;margin-top:5px}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:7px 11px}.pass{color:#86efac}.warn,.warning{color:#fde68a}.fail,.error{color:#fecaca}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3d36;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Native media pipeline</p><h1>${escapeHtml15(title)}</h1><p class="status ${escapeHtml15(report.status)}">${escapeHtml15(report.status)}</p><p>${escapeHtml15(report.surface)}</p><section class="summary"><div class="metric"><span>Frames</span><strong>${String(report.frames)}</strong></div><div class="metric"><span>Input audio</span><strong>${String(report.calibration.inputAudioFrames)}</strong></div><div class="metric"><span>Assistant audio</span><strong>${String(report.calibration.assistantAudioFrames)}</strong></div><div class="metric"><span>Trace linked</span><strong>${String(report.calibration.traceLinkedFrames)}</strong></div><div class="metric"><span>First audio</span><strong>${escapeHtml15(report.calibration.firstAudioLatencyMs ?? "n/a")}ms</strong></div><div class="metric"><span>VAD segments</span><strong>${String(report.vad.segments.length)}</strong></div><div class="metric"><span>Interruptions</span><strong>${String(report.interruption.interruptionFrames)}</strong></div><div class="metric"><span>Resampling</span><strong>${report.calibration.resamplingRequired ? "required" : "not required"}</strong></div></section></section><section class="card"><h2>Issues</h2><ul>${issues || '<li class="pass">No media pipeline issues.</li>'}</ul></section><section class="card"><h2>VAD Segments</h2><table><thead><tr><th>Segment</th><th>Frames</th><th>Duration ms</th><th>Turn</th></tr></thead><tbody>${segments || '<tr><td colspan="4">No VAD segments.</td></tr>'}</tbody></table></section></main></body></html>`;
|
|
11936
|
+
};
|
|
11937
|
+
var createVoiceMediaPipelineRoutes = (options = {}) => {
|
|
11938
|
+
const path = options.path ?? "/api/voice/media-pipeline";
|
|
11939
|
+
const htmlPath = options.htmlPath ?? "/voice/media-pipeline";
|
|
11940
|
+
const markdownPath = options.markdownPath ?? "/voice/media-pipeline.md";
|
|
11941
|
+
const headers = options.headers ?? {};
|
|
11942
|
+
const title = options.title ?? "Voice Media Pipeline Proof";
|
|
11943
|
+
const resolveOptions = async () => {
|
|
11944
|
+
const source = typeof options.source === "function" ? await options.source() : options.source ?? options;
|
|
11945
|
+
const {
|
|
11946
|
+
headers: _headers,
|
|
11947
|
+
htmlPath: _htmlPath,
|
|
11948
|
+
markdownPath: _markdownPath,
|
|
11949
|
+
name: _name,
|
|
11950
|
+
path: _path,
|
|
11951
|
+
render: _render,
|
|
11952
|
+
source: _source,
|
|
11953
|
+
title: _title,
|
|
11954
|
+
...reportOptions
|
|
11955
|
+
} = {
|
|
11956
|
+
...options,
|
|
11957
|
+
...source
|
|
11958
|
+
};
|
|
11959
|
+
return reportOptions;
|
|
11960
|
+
};
|
|
11961
|
+
const report = async () => buildVoiceMediaPipelineReport(await resolveOptions());
|
|
11962
|
+
const app = new Elysia12({ name: options.name ?? "voice-media-pipeline" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
11963
|
+
headers: {
|
|
11964
|
+
"content-type": "application/json; charset=utf-8",
|
|
11965
|
+
...headers
|
|
11966
|
+
}
|
|
11967
|
+
}));
|
|
11968
|
+
if (htmlPath !== false) {
|
|
11969
|
+
app.get(htmlPath, async () => {
|
|
11970
|
+
const current = await report();
|
|
11971
|
+
const body = options.render ? await options.render(current) : renderVoiceMediaPipelineHTML(current, title);
|
|
11972
|
+
return new Response(body, {
|
|
11973
|
+
headers: {
|
|
11974
|
+
"content-type": "text/html; charset=utf-8",
|
|
11975
|
+
...headers
|
|
11976
|
+
}
|
|
11977
|
+
});
|
|
11978
|
+
});
|
|
11979
|
+
}
|
|
11980
|
+
if (markdownPath !== false) {
|
|
11981
|
+
app.get(markdownPath, async () => new Response(renderVoiceMediaPipelineMarkdown(await report()), {
|
|
11982
|
+
headers: {
|
|
11983
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
11984
|
+
...headers
|
|
11985
|
+
}
|
|
11986
|
+
}));
|
|
11987
|
+
}
|
|
11988
|
+
return app;
|
|
11989
|
+
};
|
|
11990
|
+
// src/demoReadyRoutes.ts
|
|
11991
|
+
import { Elysia as Elysia13 } from "elysia";
|
|
11992
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11824
11993
|
var rollupStatus2 = (sections) => sections.some((section) => section.status === "fail") ? "fail" : sections.some((section) => section.status === "warn") ? "warn" : "pass";
|
|
11825
11994
|
var resolveLoader = async (loader, input) => typeof loader === "function" ? await loader(input) : loader;
|
|
11826
11995
|
var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
@@ -11904,17 +12073,17 @@ var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
|
11904
12073
|
};
|
|
11905
12074
|
};
|
|
11906
12075
|
var renderVoiceDemoReadyHTML = (report) => {
|
|
11907
|
-
const sections = report.sections.map((section) => `<article class="section ${
|
|
11908
|
-
<div><span>${
|
|
11909
|
-
<strong>${
|
|
11910
|
-
${section.href ? `<a href="${
|
|
12076
|
+
const sections = report.sections.map((section) => `<article class="section ${escapeHtml16(section.status)}">
|
|
12077
|
+
<div><span>${escapeHtml16(section.status.toUpperCase())}</span><h2>${escapeHtml16(section.label)}</h2>${section.description ? `<p>${escapeHtml16(section.description)}</p>` : ""}</div>
|
|
12078
|
+
<strong>${escapeHtml16(String(section.value ?? section.status))}</strong>
|
|
12079
|
+
${section.href ? `<a href="${escapeHtml16(section.href)}">Open</a>` : ""}
|
|
11911
12080
|
</article>`).join("");
|
|
11912
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
12081
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml16(report.title)}</title><style>body{background:#0d141b;color:#f8f3e7;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(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}.sections{display:grid;gap:14px}.section{align-items:center;background:#151d26;border:1px solid #283544;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.section span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.section h2{margin:.2rem 0}.section p{color:#b9c0c8;margin:.2rem 0 0}.section strong{font-size:1.4rem}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.65)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}@media(max-width:760px){main{padding:20px}.section{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Demo readiness</p><h1>${escapeHtml16(report.title)}</h1><p>One customer-facing checklist for the self-hosted voice proof surfaces: ops status, production readiness, phone setup, and phone smoke traces.</p><p class="status ${escapeHtml16(report.status)}">Overall: ${escapeHtml16(report.status.toUpperCase())}</p><p>Checked ${escapeHtml16(new Date(report.checkedAt).toLocaleString())}</p></section><section class="sections">${sections || '<article class="section warn"><div><span>WARN</span><h2>No checks configured</h2><p>Add ops status, production readiness, phone setup, or phone smoke loaders.</p></div><strong>warn</strong></article>'}</section></main></body></html>`;
|
|
11913
12082
|
};
|
|
11914
12083
|
var createVoiceDemoReadyRoutes = (options) => {
|
|
11915
12084
|
const path = options.path ?? "/api/demo-ready";
|
|
11916
12085
|
const htmlPath = options.htmlPath ?? "/demo-ready";
|
|
11917
|
-
const routes = new
|
|
12086
|
+
const routes = new Elysia13({
|
|
11918
12087
|
name: options.name ?? "absolutejs-voice-demo-ready"
|
|
11919
12088
|
});
|
|
11920
12089
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
@@ -11933,7 +12102,7 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
11933
12102
|
return routes;
|
|
11934
12103
|
};
|
|
11935
12104
|
// src/deliverySinkRoutes.ts
|
|
11936
|
-
import { Elysia as
|
|
12105
|
+
import { Elysia as Elysia14 } from "elysia";
|
|
11937
12106
|
|
|
11938
12107
|
// src/queue.ts
|
|
11939
12108
|
var releaseLeaseScript = `
|
|
@@ -12876,7 +13045,7 @@ var createVoiceOpsTaskProcessorWorkerLoop = (options) => {
|
|
|
12876
13045
|
};
|
|
12877
13046
|
|
|
12878
13047
|
// src/deliverySinkRoutes.ts
|
|
12879
|
-
var
|
|
13048
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12880
13049
|
var deliveryStatus = (summary) => {
|
|
12881
13050
|
if (!summary) {
|
|
12882
13051
|
return "warn";
|
|
@@ -12975,13 +13144,13 @@ var renderSurfaceCard = (surface) => {
|
|
|
12975
13144
|
return "";
|
|
12976
13145
|
}
|
|
12977
13146
|
const value = `${surface.summary.delivered}/${surface.summary.total}`;
|
|
12978
|
-
const body = `<span>${
|
|
12979
|
-
return `<article>${surface.href ? `<a href="${
|
|
13147
|
+
const body = `<span>${escapeHtml17(surface.label)}</span><strong>${escapeHtml17(value)}</strong><p class="muted">Delivered export records.</p>`;
|
|
13148
|
+
return `<article>${surface.href ? `<a href="${escapeHtml17(surface.href)}">${body}</a>` : body}</article>`;
|
|
12980
13149
|
};
|
|
12981
13150
|
var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
12982
13151
|
const title = options.title ?? "AbsoluteJS Voice Delivery Sinks";
|
|
12983
|
-
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${
|
|
12984
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13152
|
+
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${escapeHtml17(sink.kind)}</span><strong style="font-size:1.5rem">${escapeHtml17(sink.label)}</strong>${sink.description ? `<p class="muted">${escapeHtml17(sink.description)}</p>` : ""}${sink.mode ? `<p class="muted">Mode: ${escapeHtml17(sink.mode)}</p>` : ""}${sink.target ? `<p class="muted">Target: <code>${escapeHtml17(sink.target)}</code></p>` : ""}${sink.href ? `<p><a href="${escapeHtml17(sink.href)}">Open sink</a></p>` : ""}</article>`).join("") : '<article><span>Sink</span><strong style="font-size:1.5rem">Not described</strong><p class="muted">Pass sink descriptors to document your file, webhook, S3, SQLite, or Postgres targets.</p></article>';
|
|
13153
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml17(title)}</title><style>body{background:#11120d;color:#fbf7e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{max-width:1120px;margin:auto;padding:32px}a{color:#fde68a;text-decoration:none}.hero{background:linear-gradient(135deg,rgba(253,230,138,.2),rgba(34,197,94,.14));border:1px solid #3a3420;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fde68a;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.65)}.status.fail{border-color:rgba(239,68,68,.75)}.muted{color:#b8b093}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin:18px 0}article,.card{background:#191a13;border:1px solid #33311f;border-radius:22px;padding:18px}article span{color:#b8b093;display:block;font-weight:800}article strong{display:block;font-size:2.4rem;margin-top:8px}pre{background:#0c0d09;border:1px solid #33311f;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}code{color:#fef3c7}</style></head><body><main><p><a href="/production-readiness">Production readiness</a></p><section class="hero"><p class="eyebrow">Composable sink primitive</p><h1>${escapeHtml17(title)}</h1><p class="muted">Delivery queues prove audit and trace exports without owning your infrastructure. Swap file, webhook, S3, SQLite, or Postgres sinks behind the same readiness surface.</p><p class="status ${escapeHtml17(report.status)}">Overall: ${escapeHtml17(report.status.toUpperCase())}</p><p class="muted">Checked ${escapeHtml17(new Date(report.checkedAt).toLocaleString())}</p></section><section class="grid">${renderSurfaceCard(report.auditDeliveries)}${renderSurfaceCard(report.traceDeliveries)}${sinks}</section><section class="card"><h2>Primitive shape</h2><p class="muted">Mount delivery sink routes beside audit and trace delivery queues. Production readiness can consume the same stores for pass/fail evidence.</p><pre>createVoiceDeliverySinkRoutes({
|
|
12985
13154
|
auditDeliveries: { store: runtimeStorage.auditDeliveries },
|
|
12986
13155
|
traceDeliveries: { store: runtimeStorage.traceDeliveries },
|
|
12987
13156
|
sinks: createVoiceDeliverySinkPair({
|
|
@@ -12993,7 +13162,7 @@ var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
|
12993
13162
|
var createVoiceDeliverySinkRoutes = (options) => {
|
|
12994
13163
|
const path = options.path ?? "/api/voice-delivery-sinks";
|
|
12995
13164
|
const htmlPath = options.htmlPath === undefined ? "/delivery-sinks" : options.htmlPath;
|
|
12996
|
-
const routes = new
|
|
13165
|
+
const routes = new Elysia14({
|
|
12997
13166
|
name: options.name ?? "absolutejs-voice-delivery-sinks"
|
|
12998
13167
|
}).get(path, () => buildVoiceDeliverySinkReport(options));
|
|
12999
13168
|
if (htmlPath !== false) {
|
|
@@ -13011,7 +13180,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
|
|
|
13011
13180
|
return routes;
|
|
13012
13181
|
};
|
|
13013
13182
|
// src/opsActionAuditRoutes.ts
|
|
13014
|
-
import { Elysia as
|
|
13183
|
+
import { Elysia as Elysia15 } from "elysia";
|
|
13015
13184
|
var readRecordBody = (body) => {
|
|
13016
13185
|
if (!body || typeof body !== "object") {
|
|
13017
13186
|
throw new Error("Voice ops action audit requires a JSON body.");
|
|
@@ -13086,7 +13255,7 @@ var createVoiceOpsActionAuditRoutes = (options) => {
|
|
|
13086
13255
|
const path = options.path ?? "/api/voice/ops-actions/audit";
|
|
13087
13256
|
const historyPath = options.historyPath === undefined ? "/api/voice/ops-actions/history" : options.historyPath;
|
|
13088
13257
|
const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
|
|
13089
|
-
const routes = new
|
|
13258
|
+
const routes = new Elysia15({
|
|
13090
13259
|
name: options.name ?? "absolutejs-voice-ops-action-audit"
|
|
13091
13260
|
}).post(path, async ({ body, request, set }) => {
|
|
13092
13261
|
try {
|
|
@@ -13136,13 +13305,13 @@ var buildVoiceOpsActionHistoryReport = async (options) => {
|
|
|
13136
13305
|
total: entries.length
|
|
13137
13306
|
};
|
|
13138
13307
|
};
|
|
13139
|
-
var
|
|
13308
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13140
13309
|
var renderVoiceOpsActionHistoryHTML = (report) => {
|
|
13141
|
-
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${
|
|
13310
|
+
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${escapeHtml18(entry.ok ? "success" : "error")}</span><strong>${escapeHtml18(entry.actionId)}</strong><p>${escapeHtml18(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</p>${entry.error ? `<p>${escapeHtml18(entry.error)}</p>` : ""}</article>`).join("");
|
|
13142
13311
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Voice Ops Action History</title><style>body{background:#11140f;color:#f7f1df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181d15;border:1px solid #2c3327;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4rem);line-height:.95}section{display:grid;gap:12px}article.ok{border-color:rgba(34,197,94,.55)}article.fail{border-color:rgba(239,68,68,.75)}span{color:#facc15;font-weight:900;text-transform:uppercase}p{color:#c8ccb8}</style></head><body><main><section class="hero"><span>Operator proof</span><h1>Voice Ops Action History</h1><p>${String(report.total)} action(s), ${String(report.failed)} failed.</p></section><section>${rows || "<p>No operator actions have been recorded.</p>"}</section></main></body></html>`;
|
|
13143
13312
|
};
|
|
13144
13313
|
// src/platformCoverage.ts
|
|
13145
|
-
import { Elysia as
|
|
13314
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
13146
13315
|
var buildVoicePlatformCoverageSummary = (input) => {
|
|
13147
13316
|
const coverage = input.coverage ?? [];
|
|
13148
13317
|
const ok = input.ok ?? (coverage.length > 0 && coverage.every((surface) => surface.status === "pass"));
|
|
@@ -13203,7 +13372,7 @@ var assertVoicePlatformCoverage = (summary, input = {}) => {
|
|
|
13203
13372
|
var normalizeCoverageSummary = (value) => ("status" in value) && ("total" in value) && ("coverage" in value) ? value : buildVoicePlatformCoverageSummary(value);
|
|
13204
13373
|
var createVoicePlatformCoverageRoutes = (options) => {
|
|
13205
13374
|
const path = options.path ?? "/api/voice/platform-coverage";
|
|
13206
|
-
const routes = new
|
|
13375
|
+
const routes = new Elysia16({
|
|
13207
13376
|
name: options.name ?? "absolutejs-voice-platform-coverage"
|
|
13208
13377
|
});
|
|
13209
13378
|
routes.get(path, async () => {
|
|
@@ -13215,8 +13384,8 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
13215
13384
|
return routes;
|
|
13216
13385
|
};
|
|
13217
13386
|
// src/competitiveCoverage.ts
|
|
13218
|
-
import { Elysia as
|
|
13219
|
-
var
|
|
13387
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
13388
|
+
var escapeHtml19 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13220
13389
|
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
13221
13390
|
var resolveSurfaceStatus = (surface) => {
|
|
13222
13391
|
if (surface.status)
|
|
@@ -13384,24 +13553,24 @@ var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive
|
|
|
13384
13553
|
`);
|
|
13385
13554
|
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
13386
13555
|
const surfaceCards = report.surfaces.map((surface) => {
|
|
13387
|
-
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${
|
|
13388
|
-
return `<article class="surface ${
|
|
13389
|
-
<header><div><p class="eyebrow">${
|
|
13390
|
-
<p>${
|
|
13556
|
+
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${escapeHtml19(item.name)}</strong>${item.kind ? ` <span>${escapeHtml19(item.kind)}</span>` : ""}${item.status ? ` <em>${escapeHtml19(item.status)}</em>` : ""}${item.href ? ` <a href="${escapeHtml19(item.href)}">open</a>` : ""}</li>`).join("");
|
|
13557
|
+
return `<article class="surface ${escapeHtml19(surface.status)} ${escapeHtml19(surface.depth)}">
|
|
13558
|
+
<header><div><p class="eyebrow">${escapeHtml19(surface.coverage)} \xB7 ${escapeHtml19(surface.depth)}</p><h2>${escapeHtml19(surface.surface)}</h2></div><strong>${escapeHtml19(surface.status)}</strong></header>
|
|
13559
|
+
<p>${escapeHtml19(surface.why)}</p>
|
|
13391
13560
|
<dl>
|
|
13392
|
-
<div><dt>Competitors</dt><dd>${
|
|
13393
|
-
<div><dt>Operations record</dt><dd>${
|
|
13394
|
-
<div><dt>Readiness gate</dt><dd>${
|
|
13395
|
-
<div><dt>Frameworks</dt><dd>${
|
|
13561
|
+
<div><dt>Competitors</dt><dd>${escapeHtml19((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
13562
|
+
<div><dt>Operations record</dt><dd>${escapeHtml19(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
13563
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml19(surface.readinessGate ?? "unknown")}</dd></div>
|
|
13564
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml19((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
13396
13565
|
</dl>
|
|
13397
|
-
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${
|
|
13398
|
-
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${
|
|
13566
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml19(surface.remainingGap)}</p>` : ""}
|
|
13567
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml19(surface.nextMove)}</p>` : ""}
|
|
13399
13568
|
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
13400
13569
|
</article>`;
|
|
13401
13570
|
}).join(`
|
|
13402
13571
|
`);
|
|
13403
|
-
const issueList = report.issues.map((issue) => `<li class="${
|
|
13404
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13572
|
+
const issueList = report.issues.map((issue) => `<li class="${escapeHtml19(issue.severity)}"><strong>${escapeHtml19(issue.code)}</strong>${issue.surface ? ` ${escapeHtml19(issue.surface)}` : ""}: ${escapeHtml19(issue.message)}</li>`).join("");
|
|
13573
|
+
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:#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>${escapeHtml19(title)}</h1><p>Generated ${escapeHtml19(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 ${escapeHtml19(report.status)}</span><span class="pill">Vapi-style ${escapeHtml19(report.vapiCoverageEstimate)}</span><span class="pill">Market ${escapeHtml19(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>`;
|
|
13405
13574
|
};
|
|
13406
13575
|
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
13407
13576
|
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
@@ -13414,7 +13583,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
13414
13583
|
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
13415
13584
|
return normalizeCompetitiveCoverageReport(value);
|
|
13416
13585
|
};
|
|
13417
|
-
const app = new
|
|
13586
|
+
const app = new Elysia17({
|
|
13418
13587
|
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
13419
13588
|
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
13420
13589
|
headers: {
|
|
@@ -13445,7 +13614,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
13445
13614
|
return app;
|
|
13446
13615
|
};
|
|
13447
13616
|
// src/proofTrends.ts
|
|
13448
|
-
import { Elysia as
|
|
13617
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
13449
13618
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
13450
13619
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
13451
13620
|
var toTimeMs = (value) => {
|
|
@@ -13596,7 +13765,7 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
13596
13765
|
};
|
|
13597
13766
|
var createVoiceProofTrendRoutes = (options) => {
|
|
13598
13767
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
13599
|
-
const routes = new
|
|
13768
|
+
const routes = new Elysia18({
|
|
13600
13769
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
13601
13770
|
});
|
|
13602
13771
|
routes.get(path, async () => {
|
|
@@ -13629,11 +13798,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
13629
13798
|
return `${days}d ${hours % 24}h`;
|
|
13630
13799
|
};
|
|
13631
13800
|
// src/providerDecisionTraces.ts
|
|
13632
|
-
import { Elysia as
|
|
13801
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
13633
13802
|
|
|
13634
13803
|
// src/resilienceRoutes.ts
|
|
13635
|
-
import { Elysia as
|
|
13636
|
-
var
|
|
13804
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
13805
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13637
13806
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
13638
13807
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
13639
13808
|
var getBoolean2 = (value) => value === true;
|
|
@@ -13781,13 +13950,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
13781
13950
|
};
|
|
13782
13951
|
var renderProviderCards = (title, providers) => {
|
|
13783
13952
|
if (providers.length === 0) {
|
|
13784
|
-
return `<p class="muted">No ${
|
|
13953
|
+
return `<p class="muted">No ${escapeHtml20(title)} provider health yet.</p>`;
|
|
13785
13954
|
}
|
|
13786
13955
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
13787
|
-
<article class="card provider ${
|
|
13956
|
+
<article class="card provider ${escapeHtml20(provider.status)}">
|
|
13788
13957
|
<div class="card-header">
|
|
13789
|
-
<strong>${
|
|
13790
|
-
<span>${
|
|
13958
|
+
<strong>${escapeHtml20(provider.provider)}</strong>
|
|
13959
|
+
<span>${escapeHtml20(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
13791
13960
|
</div>
|
|
13792
13961
|
<dl>
|
|
13793
13962
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -13796,7 +13965,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
13796
13965
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
13797
13966
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
13798
13967
|
</dl>
|
|
13799
|
-
${provider.lastError ? `<p class="muted">${
|
|
13968
|
+
${provider.lastError ? `<p class="muted">${escapeHtml20(provider.lastError)}</p>` : ""}
|
|
13800
13969
|
</article>
|
|
13801
13970
|
`).join("")}</div>`;
|
|
13802
13971
|
};
|
|
@@ -13805,24 +13974,24 @@ var renderTimeline2 = (events) => {
|
|
|
13805
13974
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
13806
13975
|
}
|
|
13807
13976
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
13808
|
-
<article class="card event ${
|
|
13977
|
+
<article class="card event ${escapeHtml20(event.status ?? "unknown")}">
|
|
13809
13978
|
<div class="card-header">
|
|
13810
|
-
<strong>${
|
|
13979
|
+
<strong>${escapeHtml20(event.kind.toUpperCase())} ${escapeHtml20(event.operation ?? "generate")}</strong>
|
|
13811
13980
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
13812
13981
|
</div>
|
|
13813
13982
|
<p>
|
|
13814
|
-
<span class="pill">${
|
|
13815
|
-
<span class="pill">provider: ${
|
|
13816
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
13983
|
+
<span class="pill">${escapeHtml20(event.status ?? "unknown")}</span>
|
|
13984
|
+
<span class="pill">provider: ${escapeHtml20(event.provider ?? "unknown")}</span>
|
|
13985
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml20(event.fallbackProvider)}</span>` : ""}
|
|
13817
13986
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
13818
13987
|
</p>
|
|
13819
13988
|
<dl>
|
|
13820
13989
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
13821
13990
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
13822
13991
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
13823
|
-
<div><dt>Session</dt><dd>${
|
|
13992
|
+
<div><dt>Session</dt><dd>${escapeHtml20(event.sessionId)}</dd></div>
|
|
13824
13993
|
</dl>
|
|
13825
|
-
${event.error ? `<p class="muted">${
|
|
13994
|
+
${event.error ? `<p class="muted">${escapeHtml20(event.error)}</p>` : ""}
|
|
13826
13995
|
</article>
|
|
13827
13996
|
`).join("")}</div>`;
|
|
13828
13997
|
};
|
|
@@ -13832,9 +14001,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
13832
14001
|
const status = latest?.status ?? "idle";
|
|
13833
14002
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
13834
14003
|
return `<div>
|
|
13835
|
-
<dt>${
|
|
13836
|
-
<dd>${
|
|
13837
|
-
<small>${
|
|
14004
|
+
<dt>${escapeHtml20(kind.toUpperCase())}</dt>
|
|
14005
|
+
<dd>${escapeHtml20(provider)}${escapeHtml20(fallback)}</dd>
|
|
14006
|
+
<small>${escapeHtml20(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>
|
|
13838
14007
|
</div>`;
|
|
13839
14008
|
};
|
|
13840
14009
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -13842,10 +14011,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
13842
14011
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
13843
14012
|
}
|
|
13844
14013
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
13845
|
-
<article class="card session ${
|
|
14014
|
+
<article class="card session ${escapeHtml20(session.status)}">
|
|
13846
14015
|
<div class="card-header">
|
|
13847
|
-
<strong>${
|
|
13848
|
-
<span>${
|
|
14016
|
+
<strong>${escapeHtml20(session.sessionId)}</strong>
|
|
14017
|
+
<span>${escapeHtml20(session.status)}</span>
|
|
13849
14018
|
</div>
|
|
13850
14019
|
<p>
|
|
13851
14020
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -13872,21 +14041,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
13872
14041
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
13873
14042
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
13874
14043
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
13875
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
13876
|
-
<p class="muted">${
|
|
14044
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml20(pathPrefix)}">
|
|
14045
|
+
<p class="muted">${escapeHtml20(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
13877
14046
|
<div class="simulate-actions">
|
|
13878
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
13879
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
14047
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml20(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml20(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
14048
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml20(provider.provider)}">Mark ${escapeHtml20(provider.provider)} recovered</button>`).join("")}
|
|
13880
14049
|
</div>
|
|
13881
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
14050
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml20(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
13882
14051
|
<pre class="simulate-output" hidden></pre>
|
|
13883
14052
|
</div>`;
|
|
13884
14053
|
};
|
|
13885
14054
|
var renderVoiceResilienceHTML = (input) => {
|
|
13886
14055
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
13887
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
13888
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
13889
|
-
const snippet =
|
|
14056
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml20(kind)}: ${String(count)}</span>`).join("");
|
|
14057
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join(" \xB7 ") : "";
|
|
14058
|
+
const snippet = escapeHtml20(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
13890
14059
|
kind: 'stt',
|
|
13891
14060
|
providers: ['deepgram', 'assemblyai'],
|
|
13892
14061
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -13924,7 +14093,7 @@ app.use(
|
|
|
13924
14093
|
<head>
|
|
13925
14094
|
<meta charset="utf-8" />
|
|
13926
14095
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
13927
|
-
<title>${
|
|
14096
|
+
<title>${escapeHtml20(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
13928
14097
|
<style>
|
|
13929
14098
|
:root { color-scheme: dark; }
|
|
13930
14099
|
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; }
|
|
@@ -14076,7 +14245,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
14076
14245
|
};
|
|
14077
14246
|
var createVoiceResilienceRoutes = (options) => {
|
|
14078
14247
|
const path = options.path ?? "/resilience";
|
|
14079
|
-
const routes = new
|
|
14248
|
+
const routes = new Elysia19({
|
|
14080
14249
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
14081
14250
|
}).get(path, async () => {
|
|
14082
14251
|
const events = await options.store.list();
|
|
@@ -14117,7 +14286,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
14117
14286
|
};
|
|
14118
14287
|
|
|
14119
14288
|
// src/providerDecisionTraces.ts
|
|
14120
|
-
var
|
|
14289
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14121
14290
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
14122
14291
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
14123
14292
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -14132,8 +14301,8 @@ var surfaceForKind = (kind) => {
|
|
|
14132
14301
|
return "live-call";
|
|
14133
14302
|
}
|
|
14134
14303
|
};
|
|
14135
|
-
var
|
|
14136
|
-
var reportStatus = (issues) => issues.reduce((status, issue) =>
|
|
14304
|
+
var statusRank3 = { fail: 2, pass: 0, warn: 1 };
|
|
14305
|
+
var reportStatus = (issues) => issues.reduce((status, issue) => statusRank3[issue.status] > statusRank3[status] ? issue.status : status, "pass");
|
|
14137
14306
|
var uniqueSorted = (values) => [
|
|
14138
14307
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
14139
14308
|
].sort();
|
|
@@ -14358,7 +14527,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
14358
14527
|
<head>
|
|
14359
14528
|
<meta charset="utf-8" />
|
|
14360
14529
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
14361
|
-
<title>${
|
|
14530
|
+
<title>${escapeHtml21(title)}</title>
|
|
14362
14531
|
<style>
|
|
14363
14532
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
14364
14533
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -14372,8 +14541,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
14372
14541
|
</head>
|
|
14373
14542
|
<body>
|
|
14374
14543
|
<main>
|
|
14375
|
-
<p class="status ${report.status}">${
|
|
14376
|
-
<h1>${
|
|
14544
|
+
<p class="status ${report.status}">${escapeHtml21(report.status)}</p>
|
|
14545
|
+
<h1>${escapeHtml21(title)}</h1>
|
|
14377
14546
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
14378
14547
|
<section class="grid">
|
|
14379
14548
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -14384,10 +14553,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
14384
14553
|
</section>
|
|
14385
14554
|
<section class="surfaces">
|
|
14386
14555
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
14387
|
-
<header><strong>${
|
|
14556
|
+
<header><strong>${escapeHtml21(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml21(surface.status)}</span></header>
|
|
14388
14557
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
14389
|
-
<p class="muted">Providers: ${
|
|
14390
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
14558
|
+
<p class="muted">Providers: ${escapeHtml21(surface.providers.join(", ") || "none")}</p>
|
|
14559
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml21(reason)}</code>`).join(" ")}</p>
|
|
14391
14560
|
</article>`).join(`
|
|
14392
14561
|
`)}
|
|
14393
14562
|
</section>
|
|
@@ -14401,7 +14570,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
14401
14570
|
const headers = options.headers ?? {};
|
|
14402
14571
|
const title = options.title ?? "Provider Decision Traces";
|
|
14403
14572
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
14404
|
-
const app = new
|
|
14573
|
+
const app = new Elysia20({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
14405
14574
|
headers: {
|
|
14406
14575
|
"content-type": "application/json; charset=utf-8",
|
|
14407
14576
|
...headers
|
|
@@ -14429,7 +14598,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
14429
14598
|
return app;
|
|
14430
14599
|
};
|
|
14431
14600
|
// src/sloCalibration.ts
|
|
14432
|
-
import { Elysia as
|
|
14601
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14433
14602
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
14434
14603
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
14435
14604
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -14609,7 +14778,7 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
14609
14778
|
};
|
|
14610
14779
|
};
|
|
14611
14780
|
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
14612
|
-
var
|
|
14781
|
+
var escapeHtml22 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14613
14782
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
14614
14783
|
var readinessThresholdRows = (report) => [
|
|
14615
14784
|
{
|
|
@@ -14700,15 +14869,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
14700
14869
|
};
|
|
14701
14870
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
14702
14871
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
14703
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
14704
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
14705
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
14706
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
14872
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml22(row.control)}</td><td>${escapeHtml22(formatMs(row.value))}</td><td>${escapeHtml22(row.usedBy)}</td></tr>`).join("");
|
|
14873
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
|
|
14874
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml22(source)}</code></li>`).join("");
|
|
14875
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml22(title)}</title><style>body{background:#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>${escapeHtml22(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">${escapeHtml22(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml22(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml22(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml22(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>`;
|
|
14707
14876
|
};
|
|
14708
14877
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
14709
14878
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
14710
14879
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
14711
|
-
const routes = new
|
|
14880
|
+
const routes = new Elysia21({
|
|
14712
14881
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
14713
14882
|
});
|
|
14714
14883
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -14732,7 +14901,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
14732
14901
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
14733
14902
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
14734
14903
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
14735
|
-
const routes = new
|
|
14904
|
+
const routes = new Elysia21({
|
|
14736
14905
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
14737
14906
|
});
|
|
14738
14907
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -14766,7 +14935,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
14766
14935
|
return routes;
|
|
14767
14936
|
};
|
|
14768
14937
|
// src/liveOps.ts
|
|
14769
|
-
import { Elysia as
|
|
14938
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
14770
14939
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
14771
14940
|
"assign",
|
|
14772
14941
|
"create-task",
|
|
@@ -15076,7 +15245,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
15076
15245
|
const controller = createVoiceLiveOpsController(options);
|
|
15077
15246
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
15078
15247
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
15079
|
-
return new
|
|
15248
|
+
return new Elysia22({
|
|
15080
15249
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
15081
15250
|
}).post(path, async ({ request, set }) => {
|
|
15082
15251
|
try {
|
|
@@ -15098,15 +15267,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
15098
15267
|
});
|
|
15099
15268
|
};
|
|
15100
15269
|
// src/deliveryRuntime.ts
|
|
15101
|
-
import { Elysia as
|
|
15270
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15102
15271
|
import { mkdir } from "fs/promises";
|
|
15103
15272
|
import { dirname, join } from "path";
|
|
15104
|
-
var
|
|
15273
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15105
15274
|
var renderSummaryCard = (label, summary) => {
|
|
15106
15275
|
if (!summary) {
|
|
15107
|
-
return `<article><span>${
|
|
15276
|
+
return `<article><span>${escapeHtml23(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
15108
15277
|
}
|
|
15109
|
-
return `<article><span>${
|
|
15278
|
+
return `<article><span>${escapeHtml23(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>`;
|
|
15110
15279
|
};
|
|
15111
15280
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
15112
15281
|
audit: leases,
|
|
@@ -15317,9 +15486,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
15317
15486
|
});
|
|
15318
15487
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
15319
15488
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
15320
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
15321
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
15322
|
-
const snippet =
|
|
15489
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml23(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
15490
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml23(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
15491
|
+
const snippet = escapeHtml23(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
15323
15492
|
createVoiceDeliveryRuntimePresetConfig({
|
|
15324
15493
|
audit: {
|
|
15325
15494
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -15345,14 +15514,14 @@ app.use(
|
|
|
15345
15514
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
15346
15515
|
})
|
|
15347
15516
|
);`);
|
|
15348
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15517
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml23(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>${escapeHtml23(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 ${escapeHtml23(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>`;
|
|
15349
15518
|
};
|
|
15350
15519
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
15351
15520
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
15352
15521
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
15353
15522
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
15354
15523
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
15355
|
-
const routes = new
|
|
15524
|
+
const routes = new Elysia23({
|
|
15356
15525
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
15357
15526
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
15358
15527
|
if (tickPath !== false) {
|
|
@@ -15388,7 +15557,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
15388
15557
|
return routes;
|
|
15389
15558
|
};
|
|
15390
15559
|
// src/dataControl.ts
|
|
15391
|
-
import { Elysia as
|
|
15560
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
15392
15561
|
var voiceComplianceRedactionDefaults = {
|
|
15393
15562
|
keys: [
|
|
15394
15563
|
"apiKey",
|
|
@@ -15627,7 +15796,7 @@ var parseRetentionScopes = (value) => {
|
|
|
15627
15796
|
const allowed = new Set(allRetentionScopes);
|
|
15628
15797
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
15629
15798
|
};
|
|
15630
|
-
var
|
|
15799
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15631
15800
|
var buildStorageSurfaces = (options) => [
|
|
15632
15801
|
{
|
|
15633
15802
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -15864,12 +16033,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
15864
16033
|
zeroRetentionAvailable: true
|
|
15865
16034
|
};
|
|
15866
16035
|
};
|
|
15867
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
16036
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml24(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml24(scope.skippedReason ?? "")}</td><td><code>${escapeHtml24(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
15868
16037
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
15869
16038
|
const title = options.title ?? "Voice Data Control";
|
|
15870
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
15871
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
15872
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
16039
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml24(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml24(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
16040
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml24(key.name)}</td><td><code>${escapeHtml24(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml24(key.recommendation)}</td></tr>`).join("");
|
|
16041
|
+
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{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>${escapeHtml24(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>`;
|
|
15873
16042
|
};
|
|
15874
16043
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
15875
16044
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -15927,7 +16096,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
15927
16096
|
var createVoiceDataControlRoutes = (options) => {
|
|
15928
16097
|
const path = options.path ?? "/data-control";
|
|
15929
16098
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
15930
|
-
const routes = new
|
|
16099
|
+
const routes = new Elysia24({
|
|
15931
16100
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
15932
16101
|
});
|
|
15933
16102
|
routes.get(path, async ({ query }) => {
|
|
@@ -16003,16 +16172,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
16003
16172
|
return routes;
|
|
16004
16173
|
};
|
|
16005
16174
|
// src/evalRoutes.ts
|
|
16006
|
-
import { Elysia as
|
|
16175
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
16007
16176
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
16008
16177
|
import { dirname as dirname2 } from "path";
|
|
16009
16178
|
|
|
16010
16179
|
// src/qualityRoutes.ts
|
|
16011
|
-
import { Elysia as
|
|
16180
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16012
16181
|
|
|
16013
16182
|
// src/handoffHealth.ts
|
|
16014
|
-
import { Elysia as
|
|
16015
|
-
var
|
|
16183
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16184
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16016
16185
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
16017
16186
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
16018
16187
|
var increment3 = (record, key) => {
|
|
@@ -16130,10 +16299,10 @@ var renderActionSummary = (summary) => {
|
|
|
16130
16299
|
return [
|
|
16131
16300
|
'<section class="voice-handoff-health-columns">',
|
|
16132
16301
|
"<article><h3>Actions</h3>",
|
|
16133
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
16302
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml25(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
16134
16303
|
"</article>",
|
|
16135
16304
|
"<article><h3>Adapters</h3>",
|
|
16136
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
16305
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml25(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
16137
16306
|
"</article>",
|
|
16138
16307
|
"</section>"
|
|
16139
16308
|
].join("");
|
|
@@ -16147,22 +16316,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
16147
16316
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
16148
16317
|
'<div class="voice-handoff-health-events">',
|
|
16149
16318
|
...summary.events.map((event) => [
|
|
16150
|
-
`<article class="${
|
|
16319
|
+
`<article class="${escapeHtml25(event.status)}">`,
|
|
16151
16320
|
'<div class="voice-handoff-health-event-header">',
|
|
16152
|
-
`<strong>${
|
|
16153
|
-
`<span>${
|
|
16321
|
+
`<strong>${escapeHtml25(event.action ?? "handoff")}</strong>`,
|
|
16322
|
+
`<span>${escapeHtml25(event.status)}</span>`,
|
|
16154
16323
|
"</div>",
|
|
16155
|
-
`<p><small>${
|
|
16156
|
-
event.target ? `<p>Target: ${
|
|
16157
|
-
event.reason ? `<p>Reason: ${
|
|
16324
|
+
`<p><small>${escapeHtml25(event.sessionId)}</small></p>`,
|
|
16325
|
+
event.target ? `<p>Target: ${escapeHtml25(event.target)}</p>` : "",
|
|
16326
|
+
event.reason ? `<p>Reason: ${escapeHtml25(event.reason)}</p>` : "",
|
|
16158
16327
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
16159
16328
|
"<li>",
|
|
16160
|
-
`${
|
|
16161
|
-
delivery.deliveredTo ? ` to ${
|
|
16162
|
-
delivery.error ? ` (${
|
|
16329
|
+
`${escapeHtml25(delivery.adapterId)}: ${escapeHtml25(delivery.status)}`,
|
|
16330
|
+
delivery.deliveredTo ? ` to ${escapeHtml25(delivery.deliveredTo)}` : "",
|
|
16331
|
+
delivery.error ? ` (${escapeHtml25(delivery.error)})` : "",
|
|
16163
16332
|
"</li>"
|
|
16164
16333
|
].join("")).join("")}</ul>` : "",
|
|
16165
|
-
event.replayHref ? `<p><a href="${
|
|
16334
|
+
event.replayHref ? `<p><a href="${escapeHtml25(event.replayHref)}">Open replay</a></p>` : "",
|
|
16166
16335
|
"</article>"
|
|
16167
16336
|
].join("")),
|
|
16168
16337
|
"</div>"
|
|
@@ -16194,7 +16363,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
16194
16363
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
16195
16364
|
const path = options.path ?? "/api/voice-handoffs";
|
|
16196
16365
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16197
|
-
const routes = new
|
|
16366
|
+
const routes = new Elysia25({
|
|
16198
16367
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
16199
16368
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
16200
16369
|
if (htmlPath) {
|
|
@@ -16315,17 +16484,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
16315
16484
|
thresholds
|
|
16316
16485
|
};
|
|
16317
16486
|
};
|
|
16318
|
-
var
|
|
16487
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16319
16488
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
16320
16489
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
16321
16490
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
16322
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
16323
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16491
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml26(metric.label)}</td><td>${escapeHtml26(formatMetricValue(metric))}</td><td>${escapeHtml26(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml26(key)}</code></td></tr>`).join("");
|
|
16492
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml26(link.href)}">${escapeHtml26(link.label)}</a>`).join("")}</nav>` : "";
|
|
16324
16493
|
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>`;
|
|
16325
16494
|
};
|
|
16326
16495
|
var createVoiceQualityRoutes = (options) => {
|
|
16327
16496
|
const path = options.path ?? "/quality";
|
|
16328
|
-
const routes = new
|
|
16497
|
+
const routes = new Elysia26({
|
|
16329
16498
|
name: options.name ?? "absolutejs-voice-quality"
|
|
16330
16499
|
});
|
|
16331
16500
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -16354,7 +16523,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
16354
16523
|
};
|
|
16355
16524
|
|
|
16356
16525
|
// src/evalRoutes.ts
|
|
16357
|
-
var
|
|
16526
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16358
16527
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
16359
16528
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
16360
16529
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -16676,7 +16845,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
16676
16845
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
16677
16846
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
16678
16847
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
16679
|
-
const snippet =
|
|
16848
|
+
const snippet = escapeHtml27(`app.use(
|
|
16680
16849
|
createVoiceEvalRoutes({
|
|
16681
16850
|
path: '/evals',
|
|
16682
16851
|
store: traceStore,
|
|
@@ -16697,48 +16866,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
16697
16866
|
};
|
|
16698
16867
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
16699
16868
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
16700
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16701
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
16869
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16870
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml27(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>';
|
|
16702
16871
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
16703
16872
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
16704
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
16705
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
16873
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml27(session.operationsRecordHref)}">${escapeHtml27(session.sessionId)}</a>` : escapeHtml27(session.sessionId);
|
|
16874
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml27(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml27(formatTime(session.endedAt))}</td><td>${escapeHtml27(failedMetrics || "none")}</td></tr>`;
|
|
16706
16875
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
16707
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16876
|
+
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{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>${escapeHtml27(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>`;
|
|
16708
16877
|
};
|
|
16709
16878
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
16710
16879
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
16711
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16712
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
16713
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
16714
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
16715
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16880
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16881
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml27(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
16882
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml27(id)}</li>`).join("") : "<li>none</li>";
|
|
16883
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml27(id)}</li>`).join("") : "<li>none</li>";
|
|
16884
|
+
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{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>${escapeHtml27(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml27(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml27(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>${escapeHtml27(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>`;
|
|
16716
16885
|
};
|
|
16717
16886
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
16718
16887
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
16719
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16888
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16720
16889
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
16721
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
16890
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml27(issue)}</li>`).join("")}</ul>` : "";
|
|
16722
16891
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
16723
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
16724
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
16892
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml27(session.operationsRecordHref)}">${escapeHtml27(session.sessionId)}</a>` : escapeHtml27(session.sessionId);
|
|
16893
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml27(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml27(session.issues.join(", ") || "none")}</td></tr>`;
|
|
16725
16894
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
16726
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
16895
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml27(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml27(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>`;
|
|
16727
16896
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
16728
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16897
|
+
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{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>${escapeHtml27(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>`;
|
|
16729
16898
|
};
|
|
16730
16899
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
16731
16900
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
16732
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16901
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16733
16902
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
16734
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
16735
|
-
return `<section class="${fixture.status}"><h2>${
|
|
16903
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml27(scenario.label)}</td><td>${escapeHtml27(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml27([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
16904
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml27(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml27(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>`;
|
|
16736
16905
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
16737
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16906
|
+
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{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>${escapeHtml27(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>`;
|
|
16738
16907
|
};
|
|
16739
16908
|
var createVoiceEvalRoutes = (options) => {
|
|
16740
16909
|
const path = options.path ?? "/evals";
|
|
16741
|
-
const routes = new
|
|
16910
|
+
const routes = new Elysia27({
|
|
16742
16911
|
name: options.name ?? "absolutejs-voice-evals"
|
|
16743
16912
|
});
|
|
16744
16913
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -16875,11 +17044,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
16875
17044
|
return routes;
|
|
16876
17045
|
};
|
|
16877
17046
|
// src/simulationSuite.ts
|
|
16878
|
-
import { Elysia as
|
|
17047
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
16879
17048
|
|
|
16880
17049
|
// src/outcomeContract.ts
|
|
16881
|
-
import { Elysia as
|
|
16882
|
-
var
|
|
17050
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17051
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16883
17052
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
16884
17053
|
if (value === false) {
|
|
16885
17054
|
return;
|
|
@@ -17090,13 +17259,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
17090
17259
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
17091
17260
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
17092
17261
|
const contracts = report.contracts.map((contract) => {
|
|
17093
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
17262
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml28(href)}">${escapeHtml28(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
17094
17263
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
17095
17264
|
<div class="contract-header">
|
|
17096
17265
|
<div>
|
|
17097
|
-
<p class="eyebrow">${
|
|
17098
|
-
<h2>${
|
|
17099
|
-
${contract.description ? `<p>${
|
|
17266
|
+
<p class="eyebrow">${escapeHtml28(contract.contractId)}</p>
|
|
17267
|
+
<h2>${escapeHtml28(contract.label ?? contract.contractId)}</h2>
|
|
17268
|
+
${contract.description ? `<p>${escapeHtml28(contract.description)}</p>` : ""}
|
|
17100
17269
|
${sessionLinks}
|
|
17101
17270
|
</div>
|
|
17102
17271
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -17108,10 +17277,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
17108
17277
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
17109
17278
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
17110
17279
|
</div>
|
|
17111
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
17280
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml28(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
17112
17281
|
</section>`;
|
|
17113
17282
|
}).join("");
|
|
17114
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17283
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml28(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>${escapeHtml28(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>`;
|
|
17115
17284
|
};
|
|
17116
17285
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
17117
17286
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -17127,7 +17296,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
17127
17296
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
17128
17297
|
const path = options.path ?? "/api/outcome-contracts";
|
|
17129
17298
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17130
|
-
const routes = new
|
|
17299
|
+
const routes = new Elysia28({
|
|
17131
17300
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
17132
17301
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
17133
17302
|
if (htmlPath) {
|
|
@@ -17137,7 +17306,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
17137
17306
|
};
|
|
17138
17307
|
|
|
17139
17308
|
// src/toolContract.ts
|
|
17140
|
-
import { Elysia as
|
|
17309
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17141
17310
|
|
|
17142
17311
|
// src/toolRuntime.ts
|
|
17143
17312
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -17346,7 +17515,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
17346
17515
|
});
|
|
17347
17516
|
var defaultApi = {};
|
|
17348
17517
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
17349
|
-
var
|
|
17518
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17350
17519
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
17351
17520
|
if (value === false) {
|
|
17352
17521
|
return;
|
|
@@ -17595,7 +17764,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
17595
17764
|
};
|
|
17596
17765
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
17597
17766
|
const title = options.title ?? "Voice Tool Contracts";
|
|
17598
|
-
const snippet =
|
|
17767
|
+
const snippet = escapeHtml29(`app.use(
|
|
17599
17768
|
createVoiceToolContractRoutes({
|
|
17600
17769
|
htmlPath: '/tool-contracts',
|
|
17601
17770
|
path: '/api/tool-contracts',
|
|
@@ -17621,20 +17790,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
17621
17790
|
);`);
|
|
17622
17791
|
const contracts = report.contracts.map((contract) => {
|
|
17623
17792
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
17624
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
17793
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml29(testCase.operationsRecordHref)}">${escapeHtml29(testCase.label ?? testCase.caseId)}</a>` : escapeHtml29(testCase.label ?? testCase.caseId)}</td>
|
|
17625
17794
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
17626
|
-
<td>${
|
|
17627
|
-
<td>${
|
|
17795
|
+
<td>${escapeHtml29(testCase.status)}</td>
|
|
17796
|
+
<td>${escapeHtml29(testCase.sessionId)}</td>
|
|
17628
17797
|
<td>${String(testCase.attempts)}</td>
|
|
17629
17798
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
17630
17799
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
17631
|
-
<td>${
|
|
17800
|
+
<td>${escapeHtml29(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
17632
17801
|
</tr>`).join("");
|
|
17633
17802
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
17634
17803
|
<div class="contract-header">
|
|
17635
17804
|
<div>
|
|
17636
|
-
<p class="eyebrow">${
|
|
17637
|
-
<h2>${
|
|
17805
|
+
<p class="eyebrow">${escapeHtml29(contract.toolName)}</p>
|
|
17806
|
+
<h2>${escapeHtml29(contract.label ?? contract.contractId)}</h2>
|
|
17638
17807
|
</div>
|
|
17639
17808
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
17640
17809
|
</div>
|
|
@@ -17644,7 +17813,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
17644
17813
|
</table>
|
|
17645
17814
|
</section>`;
|
|
17646
17815
|
}).join("");
|
|
17647
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17816
|
+
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,.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>${escapeHtml29(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml29(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>`;
|
|
17648
17817
|
};
|
|
17649
17818
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
17650
17819
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -17661,7 +17830,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
17661
17830
|
var createVoiceToolContractRoutes = (options) => {
|
|
17662
17831
|
const path = options.path ?? "/api/tool-contracts";
|
|
17663
17832
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17664
|
-
const routes = new
|
|
17833
|
+
const routes = new Elysia29({
|
|
17665
17834
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
17666
17835
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
17667
17836
|
if (htmlPath) {
|
|
@@ -17671,7 +17840,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
17671
17840
|
};
|
|
17672
17841
|
|
|
17673
17842
|
// src/simulationSuite.ts
|
|
17674
|
-
var
|
|
17843
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17675
17844
|
var summarizeSection = (report) => ({
|
|
17676
17845
|
failed: report.failed,
|
|
17677
17846
|
passed: report.passed,
|
|
@@ -17867,15 +18036,15 @@ var renderSection = (label, summary) => {
|
|
|
17867
18036
|
if (!summary) {
|
|
17868
18037
|
return "";
|
|
17869
18038
|
}
|
|
17870
|
-
return `<article class="${
|
|
18039
|
+
return `<article class="${escapeHtml30(summary.status)}"><span>${escapeHtml30(label)}</span><strong>${escapeHtml30(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
17871
18040
|
};
|
|
17872
18041
|
var renderAction = (action) => {
|
|
17873
|
-
const content = `<strong>${
|
|
17874
|
-
return action.href ? `<a class="action" href="${
|
|
18042
|
+
const content = `<strong>${escapeHtml30(action.label)}</strong><p>${escapeHtml30(action.description)}</p><span>${escapeHtml30(action.section)} / ${escapeHtml30(action.severity)}</span>`;
|
|
18043
|
+
return action.href ? `<a class="action" href="${escapeHtml30(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
17875
18044
|
};
|
|
17876
18045
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
17877
18046
|
const title = options.title ?? "Voice Simulation Suite";
|
|
17878
|
-
const snippet =
|
|
18047
|
+
const snippet = escapeHtml30(`app.use(
|
|
17879
18048
|
createVoiceSimulationSuiteRoutes({
|
|
17880
18049
|
htmlPath: '/voice/simulations',
|
|
17881
18050
|
path: '/api/voice/simulations',
|
|
@@ -17908,12 +18077,12 @@ app.use(
|
|
|
17908
18077
|
store: traceStore
|
|
17909
18078
|
})
|
|
17910
18079
|
);`);
|
|
17911
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18080
|
+
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:#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>${escapeHtml30(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml30(report.status)}">Status: ${escapeHtml30(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>${escapeHtml30(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
17912
18081
|
};
|
|
17913
18082
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
17914
18083
|
const path = options.path ?? "/api/voice/simulations";
|
|
17915
18084
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
17916
|
-
const app = new
|
|
18085
|
+
const app = new Elysia30({
|
|
17917
18086
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
17918
18087
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
17919
18088
|
if (htmlPath) {
|
|
@@ -18225,9 +18394,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
18225
18394
|
};
|
|
18226
18395
|
};
|
|
18227
18396
|
// src/sessionReplay.ts
|
|
18228
|
-
import { Elysia as
|
|
18397
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18229
18398
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
18230
|
-
var
|
|
18399
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18231
18400
|
var increment4 = (record, key) => {
|
|
18232
18401
|
record[key] = (record[key] ?? 0) + 1;
|
|
18233
18402
|
};
|
|
@@ -18421,10 +18590,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
18421
18590
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
18422
18591
|
'<div class="voice-sessions-list">',
|
|
18423
18592
|
...sessions.map((session) => [
|
|
18424
|
-
`<article class="voice-session-card ${
|
|
18593
|
+
`<article class="voice-session-card ${escapeHtml31(session.status)}">`,
|
|
18425
18594
|
'<div class="voice-session-card-header">',
|
|
18426
|
-
`<strong>${
|
|
18427
|
-
`<span>${
|
|
18595
|
+
`<strong>${escapeHtml31(session.sessionId)}</strong>`,
|
|
18596
|
+
`<span>${escapeHtml31(session.status)}</span>`,
|
|
18428
18597
|
"</div>",
|
|
18429
18598
|
"<dl>",
|
|
18430
18599
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -18432,9 +18601,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
18432
18601
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
18433
18602
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
18434
18603
|
"</dl>",
|
|
18435
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
18436
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
18437
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
18604
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml31(session.latestOutcome)}</p>` : "",
|
|
18605
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml31).join(", ")}</p>` : "",
|
|
18606
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml31(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml31(session.replayHref)}">Open replay</a></p>` : "",
|
|
18438
18607
|
"</article>"
|
|
18439
18608
|
].join("")),
|
|
18440
18609
|
"</div>"
|
|
@@ -18465,7 +18634,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
18465
18634
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
18466
18635
|
const path = options.path ?? "/api/voice-sessions";
|
|
18467
18636
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18468
|
-
const routes = new
|
|
18637
|
+
const routes = new Elysia31({
|
|
18469
18638
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
18470
18639
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
18471
18640
|
if (htmlPath) {
|
|
@@ -18493,7 +18662,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
18493
18662
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
18494
18663
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
18495
18664
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18496
|
-
const routes = new
|
|
18665
|
+
const routes = new Elysia31({
|
|
18497
18666
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
18498
18667
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
18499
18668
|
if (htmlPath) {
|
|
@@ -18807,10 +18976,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
18807
18976
|
return report;
|
|
18808
18977
|
};
|
|
18809
18978
|
// src/turnLatency.ts
|
|
18810
|
-
import { Elysia as
|
|
18979
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18811
18980
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
18812
18981
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
18813
|
-
var
|
|
18982
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18814
18983
|
var firstNumber = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
18815
18984
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
18816
18985
|
var createTraceStageIndex = (events) => {
|
|
@@ -18942,11 +19111,11 @@ await traceStore.append({
|
|
|
18942
19111
|
turnId,
|
|
18943
19112
|
type: 'turn_latency.stage'
|
|
18944
19113
|
});`;
|
|
18945
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
18946
|
-
<header><div><p class="eyebrow">${
|
|
18947
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
19114
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml32(turn.status)}">
|
|
19115
|
+
<header><div><p class="eyebrow">${escapeHtml32(turn.sessionId)} \xB7 ${escapeHtml32(turn.turnId)}</p><h2>${escapeHtml32(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml32(turn.status)}</strong></header>
|
|
19116
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml32(stage.label)}</dt><dd>${escapeHtml32(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
18948
19117
|
</article>`).join("");
|
|
18949
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19118
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml32(title)}</h1><div class="summary"><span class="pill ${escapeHtml32(report.status)}">${escapeHtml32(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml32(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>${escapeHtml32(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
18950
19119
|
};
|
|
18951
19120
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
18952
19121
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -18963,7 +19132,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
18963
19132
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
18964
19133
|
const path = options.path ?? "/api/turn-latency";
|
|
18965
19134
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18966
|
-
const routes = new
|
|
19135
|
+
const routes = new Elysia32({
|
|
18967
19136
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
18968
19137
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
18969
19138
|
if (htmlPath) {
|
|
@@ -18972,8 +19141,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
18972
19141
|
return routes;
|
|
18973
19142
|
};
|
|
18974
19143
|
// src/liveLatency.ts
|
|
18975
|
-
import { Elysia as
|
|
18976
|
-
var
|
|
19144
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
19145
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18977
19146
|
var percentile3 = (values, percentileValue) => {
|
|
18978
19147
|
if (values.length === 0) {
|
|
18979
19148
|
return;
|
|
@@ -19040,13 +19209,13 @@ await traceStore.append({
|
|
|
19040
19209
|
sessionId,
|
|
19041
19210
|
type: 'client.live_latency'
|
|
19042
19211
|
});`;
|
|
19043
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
19044
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19212
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml33(sample.sessionId)}</td><td>${escapeHtml33(formatMs3(sample.latencyMs))}</td><td>${escapeHtml33(sample.status ?? "unknown")}</td><td>${escapeHtml33(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
19213
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml33(title)}</title><style>body{background:#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>${escapeHtml33(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml33(report.status)}">Status: ${escapeHtml33(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml33(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml33(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml33(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>${escapeHtml33(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>`;
|
|
19045
19214
|
};
|
|
19046
19215
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
19047
19216
|
const path = options.path ?? "/api/live-latency";
|
|
19048
19217
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
19049
|
-
const routes = new
|
|
19218
|
+
const routes = new Elysia33({
|
|
19050
19219
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
19051
19220
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
19052
19221
|
if (htmlPath) {
|
|
@@ -19365,9 +19534,9 @@ None.
|
|
|
19365
19534
|
`}`;
|
|
19366
19535
|
};
|
|
19367
19536
|
// src/turnQuality.ts
|
|
19368
|
-
import { Elysia as
|
|
19537
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19369
19538
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
19370
|
-
var
|
|
19539
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19371
19540
|
var getTurnLatencyMs = (turn) => {
|
|
19372
19541
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
19373
19542
|
if (firstTranscriptAt === undefined) {
|
|
@@ -19438,24 +19607,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
19438
19607
|
};
|
|
19439
19608
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
19440
19609
|
const title = options.title ?? "Voice Turn Quality";
|
|
19441
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
19610
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml34(turn.status)}">
|
|
19442
19611
|
<div class="turn-header">
|
|
19443
19612
|
<div>
|
|
19444
|
-
<p class="eyebrow">${
|
|
19445
|
-
<h2>${
|
|
19613
|
+
<p class="eyebrow">${escapeHtml34(turn.sessionId)} \xB7 ${escapeHtml34(turn.turnId)}</p>
|
|
19614
|
+
<h2>${escapeHtml34(turn.text || "Empty turn")}</h2>
|
|
19446
19615
|
</div>
|
|
19447
|
-
<strong>${
|
|
19616
|
+
<strong>${escapeHtml34(turn.status)}</strong>
|
|
19448
19617
|
</div>
|
|
19449
19618
|
<dl>
|
|
19450
|
-
<div><dt>Source</dt><dd>${
|
|
19619
|
+
<div><dt>Source</dt><dd>${escapeHtml34(turn.source ?? "unknown")}</dd></div>
|
|
19451
19620
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
19452
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
19453
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
19621
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml34(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
19622
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml34(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
19454
19623
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
19455
19624
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
19456
19625
|
</dl>
|
|
19457
19626
|
</article>`).join("");
|
|
19458
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19627
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml34(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>${escapeHtml34(title)}</h1><div class="summary"><span class="pill ${escapeHtml34(report.status)}">${escapeHtml34(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>`;
|
|
19459
19628
|
};
|
|
19460
19629
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
19461
19630
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -19472,7 +19641,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
19472
19641
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
19473
19642
|
const path = options.path ?? "/api/turn-quality";
|
|
19474
19643
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19475
|
-
const routes = new
|
|
19644
|
+
const routes = new Elysia34({
|
|
19476
19645
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
19477
19646
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
19478
19647
|
if (htmlPath) {
|
|
@@ -19481,7 +19650,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
19481
19650
|
return routes;
|
|
19482
19651
|
};
|
|
19483
19652
|
// src/telephonyOutcome.ts
|
|
19484
|
-
import { Elysia as
|
|
19653
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
19485
19654
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
19486
19655
|
"answered",
|
|
19487
19656
|
"completed",
|
|
@@ -20242,7 +20411,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
20242
20411
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
20243
20412
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
20244
20413
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
20245
|
-
return new
|
|
20414
|
+
return new Elysia35({
|
|
20246
20415
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
20247
20416
|
}).post(path, async ({ query, request }) => {
|
|
20248
20417
|
try {
|
|
@@ -20263,12 +20432,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
20263
20432
|
});
|
|
20264
20433
|
};
|
|
20265
20434
|
// src/phoneAgent.ts
|
|
20266
|
-
import { Elysia as
|
|
20435
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
20267
20436
|
|
|
20268
20437
|
// src/telephony/plivo.ts
|
|
20269
20438
|
import { Buffer as Buffer5 } from "buffer";
|
|
20270
20439
|
import { Database } from "bun:sqlite";
|
|
20271
|
-
import { Elysia as
|
|
20440
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
20272
20441
|
|
|
20273
20442
|
// src/telephony/contract.ts
|
|
20274
20443
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -20352,7 +20521,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
20352
20521
|
|
|
20353
20522
|
// src/telephony/twilio.ts
|
|
20354
20523
|
import { Buffer as Buffer4 } from "buffer";
|
|
20355
|
-
import { Elysia as
|
|
20524
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
20356
20525
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
20357
20526
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
20358
20527
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -20382,7 +20551,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
20382
20551
|
return parameters;
|
|
20383
20552
|
};
|
|
20384
20553
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20385
|
-
var
|
|
20554
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20386
20555
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
20387
20556
|
if (!webhook?.verificationUrl) {
|
|
20388
20557
|
return;
|
|
@@ -20425,23 +20594,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
20425
20594
|
};
|
|
20426
20595
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20427
20596
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
20428
|
-
<h1>${
|
|
20597
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
20429
20598
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
20430
20599
|
<section>
|
|
20431
20600
|
<h2>URLs</h2>
|
|
20432
20601
|
<ul>
|
|
20433
|
-
<li><strong>TwiML:</strong> <code>${
|
|
20434
|
-
<li><strong>Media stream:</strong> <code>${
|
|
20435
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
20602
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml35(status.urls.twiml)}</code></li>
|
|
20603
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml35(status.urls.stream)}</code></li>
|
|
20604
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml35(status.urls.webhook)}</code></li>
|
|
20436
20605
|
</ul>
|
|
20437
20606
|
</section>
|
|
20438
20607
|
<section>
|
|
20439
20608
|
<h2>Signing</h2>
|
|
20440
20609
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
20441
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
20610
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml35(status.signing.verificationUrl)}</code></p>` : ""}
|
|
20442
20611
|
</section>
|
|
20443
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
20444
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
20612
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml35(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
20613
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml35(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
20445
20614
|
</main>`;
|
|
20446
20615
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
20447
20616
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -20452,20 +20621,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
20452
20621
|
});
|
|
20453
20622
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20454
20623
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
20455
|
-
<h1>${
|
|
20624
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
20456
20625
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
20457
20626
|
<section>
|
|
20458
20627
|
<h2>Checks</h2>
|
|
20459
20628
|
<ul>
|
|
20460
|
-
${report.checks.map((check) => `<li><strong>${
|
|
20629
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml35(check.name)}</strong>: ${escapeHtml35(check.status)}${check.message ? ` - ${escapeHtml35(check.message)}` : ""}</li>`).join("")}
|
|
20461
20630
|
</ul>
|
|
20462
20631
|
</section>
|
|
20463
20632
|
<section>
|
|
20464
20633
|
<h2>Observed URLs</h2>
|
|
20465
20634
|
<ul>
|
|
20466
|
-
<li><strong>TwiML:</strong> <code>${
|
|
20467
|
-
<li><strong>Stream:</strong> <code>${
|
|
20468
|
-
<li><strong>Webhook:</strong> <code>${
|
|
20635
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml35(report.setup.urls.twiml)}</code></li>
|
|
20636
|
+
<li><strong>Stream:</strong> <code>${escapeHtml35(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
20637
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml35(report.setup.urls.webhook)}</code></li>
|
|
20469
20638
|
</ul>
|
|
20470
20639
|
</section>
|
|
20471
20640
|
</main>`;
|
|
@@ -20925,7 +21094,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
20925
21094
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
20926
21095
|
const bridges = new WeakMap;
|
|
20927
21096
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
20928
|
-
const app = new
|
|
21097
|
+
const app = new Elysia36({
|
|
20929
21098
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
20930
21099
|
}).get(twimlPath, async ({ query, request }) => {
|
|
20931
21100
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -21062,7 +21231,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
21062
21231
|
|
|
21063
21232
|
// src/telephony/plivo.ts
|
|
21064
21233
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21065
|
-
var
|
|
21234
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21066
21235
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
21067
21236
|
var resolveRequestOrigin2 = (request) => {
|
|
21068
21237
|
const url = new URL(request.url);
|
|
@@ -21492,21 +21661,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
21492
21661
|
};
|
|
21493
21662
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21494
21663
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
21495
|
-
<h1>${
|
|
21664
|
+
<h1>${escapeHtml36(title)}</h1>
|
|
21496
21665
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
21497
21666
|
<ul>
|
|
21498
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
21499
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
21500
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
21667
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml36(status.urls.answer)}</code></li>
|
|
21668
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml36(status.urls.stream)}</code></li>
|
|
21669
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml36(status.urls.webhook)}</code></li>
|
|
21501
21670
|
</ul>
|
|
21502
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
21503
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
21671
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml36(name)}</code></li>`).join("")}</ul>` : ""}
|
|
21672
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml36(warning)}</li>`).join("")}</ul>` : ""}
|
|
21504
21673
|
</main>`;
|
|
21505
21674
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21506
21675
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
21507
|
-
<h1>${
|
|
21676
|
+
<h1>${escapeHtml36(title)}</h1>
|
|
21508
21677
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
21509
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
21678
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml36(check.name)}</strong>: ${escapeHtml36(check.status)}${check.message ? ` - ${escapeHtml36(check.message)}` : ""}</li>`).join("")}</ul>
|
|
21510
21679
|
</main>`;
|
|
21511
21680
|
var runPlivoSmokeTest = async (input) => {
|
|
21512
21681
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -21596,7 +21765,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
21596
21765
|
nonceStore: options.webhook.nonceStore,
|
|
21597
21766
|
verificationUrl: options.webhook.verificationUrl
|
|
21598
21767
|
}) : undefined);
|
|
21599
|
-
const app = new
|
|
21768
|
+
const app = new Elysia37({
|
|
21600
21769
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
21601
21770
|
}).get(answerPath, async ({ query, request }) => {
|
|
21602
21771
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -21708,9 +21877,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
21708
21877
|
// src/telephony/telnyx.ts
|
|
21709
21878
|
import { Buffer as Buffer6 } from "buffer";
|
|
21710
21879
|
import { Database as Database2 } from "bun:sqlite";
|
|
21711
|
-
import { Elysia as
|
|
21880
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21712
21881
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21713
|
-
var
|
|
21882
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21714
21883
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
21715
21884
|
var resolveRequestOrigin3 = (request) => {
|
|
21716
21885
|
const url = new URL(request.url);
|
|
@@ -22103,21 +22272,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
22103
22272
|
};
|
|
22104
22273
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22105
22274
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
22106
|
-
<h1>${
|
|
22275
|
+
<h1>${escapeHtml37(title)}</h1>
|
|
22107
22276
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22108
22277
|
<ul>
|
|
22109
|
-
<li><strong>TeXML:</strong> <code>${
|
|
22110
|
-
<li><strong>Media stream:</strong> <code>${
|
|
22111
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
22278
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml37(status.urls.texml)}</code></li>
|
|
22279
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml37(status.urls.stream)}</code></li>
|
|
22280
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml37(status.urls.webhook)}</code></li>
|
|
22112
22281
|
</ul>
|
|
22113
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
22114
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
22282
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml37(name)}</code></li>`).join("")}</ul>` : ""}
|
|
22283
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml37(warning)}</li>`).join("")}</ul>` : ""}
|
|
22115
22284
|
</main>`;
|
|
22116
22285
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22117
22286
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
22118
|
-
<h1>${
|
|
22287
|
+
<h1>${escapeHtml37(title)}</h1>
|
|
22119
22288
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22120
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
22289
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml37(check.name)}</strong>: ${escapeHtml37(check.status)}${check.message ? ` - ${escapeHtml37(check.message)}` : ""}</li>`).join("")}</ul>
|
|
22121
22290
|
</main>`;
|
|
22122
22291
|
var runTelnyxSmokeTest = async (input) => {
|
|
22123
22292
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -22210,7 +22379,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
22210
22379
|
publicKey: options.webhook.publicKey,
|
|
22211
22380
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
22212
22381
|
}) : undefined);
|
|
22213
|
-
const app = new
|
|
22382
|
+
const app = new Elysia38({
|
|
22214
22383
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
22215
22384
|
}).get(texmlPath, async ({ query, request }) => {
|
|
22216
22385
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -22320,8 +22489,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
22320
22489
|
};
|
|
22321
22490
|
|
|
22322
22491
|
// src/telephony/matrix.ts
|
|
22323
|
-
import { Elysia as
|
|
22324
|
-
var
|
|
22492
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
22493
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22325
22494
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
22326
22495
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
22327
22496
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -22382,13 +22551,13 @@ var badgeStyles = {
|
|
|
22382
22551
|
};
|
|
22383
22552
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
22384
22553
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
22385
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
22554
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml38(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
22386
22555
|
<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>
|
|
22387
22556
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
22388
22557
|
${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);">
|
|
22389
22558
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
22390
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
22391
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
22559
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml38(entry.name)}</h2>
|
|
22560
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml38(entry.status.toUpperCase())}</span>
|
|
22392
22561
|
</div>
|
|
22393
22562
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
22394
22563
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -22396,15 +22565,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
22396
22565
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
22397
22566
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
22398
22567
|
</dl>
|
|
22399
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
22400
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
22401
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
22568
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml38(entry.setup.urls.stream || "missing")}</code></p>
|
|
22569
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml38(entry.setup.urls.webhook || "missing")}</code></p>
|
|
22570
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml38(issue.severity)}: ${escapeHtml38(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
22402
22571
|
</article>`).join("")}
|
|
22403
22572
|
</section>
|
|
22404
22573
|
</main>`;
|
|
22405
22574
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
22406
22575
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
22407
|
-
return new
|
|
22576
|
+
return new Elysia39({
|
|
22408
22577
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
22409
22578
|
}).get(path, async ({ query, request }) => {
|
|
22410
22579
|
const providers = await options.load({ query, request });
|
|
@@ -22426,7 +22595,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
22426
22595
|
};
|
|
22427
22596
|
|
|
22428
22597
|
// src/phoneAgentProductionSmoke.ts
|
|
22429
|
-
import { Elysia as
|
|
22598
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
22430
22599
|
var defaultRequirements = [
|
|
22431
22600
|
"media-started",
|
|
22432
22601
|
"transcript",
|
|
@@ -22434,7 +22603,7 @@ var defaultRequirements = [
|
|
|
22434
22603
|
"lifecycle-outcome",
|
|
22435
22604
|
"no-session-error"
|
|
22436
22605
|
];
|
|
22437
|
-
var
|
|
22606
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
22438
22607
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
22439
22608
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
22440
22609
|
const value = event.payload[key];
|
|
@@ -22543,10 +22712,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
22543
22712
|
});
|
|
22544
22713
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
22545
22714
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
22546
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
22547
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
22548
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
22549
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22715
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml39(issue.requirement)}</strong>: ${escapeHtml39(issue.message)}</li>`).join("");
|
|
22716
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml39(outcome)}</span>`).join("");
|
|
22717
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml39(requirement)}</span>`).join("");
|
|
22718
|
+
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:#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>${escapeHtml39(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml39(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml39(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml39(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>`;
|
|
22550
22719
|
};
|
|
22551
22720
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
22552
22721
|
query,
|
|
@@ -22569,7 +22738,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
22569
22738
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
22570
22739
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
22571
22740
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
22572
|
-
const routes = new
|
|
22741
|
+
const routes = new Elysia40({
|
|
22573
22742
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
22574
22743
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
22575
22744
|
if (htmlPath) {
|
|
@@ -22612,7 +22781,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
22612
22781
|
"completed",
|
|
22613
22782
|
"failed"
|
|
22614
22783
|
];
|
|
22615
|
-
var
|
|
22784
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22616
22785
|
var loadRouteJson = async (input) => {
|
|
22617
22786
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
22618
22787
|
headers: {
|
|
@@ -22850,10 +23019,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
22850
23019
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
22851
23020
|
const urls = entry?.setup.urls;
|
|
22852
23021
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
22853
|
-
return `<tr><td>${
|
|
23022
|
+
return `<tr><td>${escapeHtml40(carrier.name ?? carrier.provider)}</td><td>${escapeHtml40(carrier.provider)}</td><td><code>${escapeHtml40(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml40(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml40(entry.status)}">${escapeHtml40(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml40(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml40(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml40(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
22854
23023
|
}).join("");
|
|
22855
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
22856
|
-
const snippet =
|
|
23024
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml40(stage)}</code></li>`).join("");
|
|
23025
|
+
const snippet = escapeHtml40(`const phoneAgent = createVoicePhoneAgent({
|
|
22857
23026
|
carriers: [
|
|
22858
23027
|
{
|
|
22859
23028
|
provider: 'twilio',
|
|
@@ -22887,11 +23056,11 @@ app.use(
|
|
|
22887
23056
|
);`);
|
|
22888
23057
|
const checklist = report.carriers.map((carrier) => {
|
|
22889
23058
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
22890
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
22891
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
22892
|
-
return `<article><h3>${
|
|
23059
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml40(issue)}</li>`).join("") ?? "";
|
|
23060
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml40(step)}</li>`).join("") ?? "";
|
|
23061
|
+
return `<article><h3>${escapeHtml40(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
22893
23062
|
}).join("");
|
|
22894
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
23063
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(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>${escapeHtml40(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="${escapeHtml40(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>`;
|
|
22895
23064
|
};
|
|
22896
23065
|
var createVoicePhoneAgent = (options) => {
|
|
22897
23066
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -22900,7 +23069,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
22900
23069
|
setupPath: resolveSetupPath(carrier),
|
|
22901
23070
|
smokePath: resolveSmokePath(carrier)
|
|
22902
23071
|
}));
|
|
22903
|
-
const app = new
|
|
23072
|
+
const app = new Elysia41({
|
|
22904
23073
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
22905
23074
|
});
|
|
22906
23075
|
for (const carrier of options.carriers) {
|
|
@@ -24530,8 +24699,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
24530
24699
|
};
|
|
24531
24700
|
};
|
|
24532
24701
|
// src/providerCapabilities.ts
|
|
24533
|
-
import { Elysia as
|
|
24534
|
-
var
|
|
24702
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24703
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24535
24704
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
24536
24705
|
configured: true,
|
|
24537
24706
|
features: options.features?.[provider],
|
|
@@ -24594,27 +24763,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
24594
24763
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
24595
24764
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
24596
24765
|
const cards = report.capabilities.map((capability) => {
|
|
24597
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
24598
|
-
return `<article class="card ${
|
|
24766
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml41(feature)}</span>`).join("");
|
|
24767
|
+
return `<article class="card ${escapeHtml41(capability.status)}">
|
|
24599
24768
|
<div class="card-header">
|
|
24600
24769
|
<div>
|
|
24601
|
-
<p class="eyebrow">${
|
|
24602
|
-
<h2>${
|
|
24770
|
+
<p class="eyebrow">${escapeHtml41(capability.kind)}</p>
|
|
24771
|
+
<h2>${escapeHtml41(capability.label ?? capability.provider)}</h2>
|
|
24603
24772
|
</div>
|
|
24604
|
-
<strong>${
|
|
24773
|
+
<strong>${escapeHtml41(capability.status)}</strong>
|
|
24605
24774
|
</div>
|
|
24606
|
-
${capability.description ? `<p>${
|
|
24775
|
+
${capability.description ? `<p>${escapeHtml41(capability.description)}</p>` : ""}
|
|
24607
24776
|
<dl>
|
|
24608
24777
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
24609
24778
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
24610
|
-
<div><dt>Model</dt><dd>${
|
|
24779
|
+
<div><dt>Model</dt><dd>${escapeHtml41(capability.model ?? "default")}</dd></div>
|
|
24611
24780
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
24612
24781
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
24613
24782
|
</dl>
|
|
24614
24783
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
24615
24784
|
</article>`;
|
|
24616
24785
|
}).join("");
|
|
24617
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24786
|
+
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{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>${escapeHtml41(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>`;
|
|
24618
24787
|
};
|
|
24619
24788
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
24620
24789
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -24631,7 +24800,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
24631
24800
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
24632
24801
|
const path = options.path ?? "/api/provider-capabilities";
|
|
24633
24802
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
24634
|
-
const routes = new
|
|
24803
|
+
const routes = new Elysia42({
|
|
24635
24804
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
24636
24805
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
24637
24806
|
if (htmlPath) {
|
|
@@ -24640,7 +24809,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
24640
24809
|
return routes;
|
|
24641
24810
|
};
|
|
24642
24811
|
// src/providerOrchestration.ts
|
|
24643
|
-
import { Elysia as
|
|
24812
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24644
24813
|
var defaultRequirement = {
|
|
24645
24814
|
minProviders: 1,
|
|
24646
24815
|
requireBudgetPolicy: false,
|
|
@@ -24648,12 +24817,12 @@ var defaultRequirement = {
|
|
|
24648
24817
|
requireFallback: false,
|
|
24649
24818
|
requireTimeoutBudget: false
|
|
24650
24819
|
};
|
|
24651
|
-
var
|
|
24820
|
+
var statusRank4 = {
|
|
24652
24821
|
pass: 0,
|
|
24653
24822
|
warn: 1,
|
|
24654
24823
|
fail: 2
|
|
24655
24824
|
};
|
|
24656
|
-
var
|
|
24825
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24657
24826
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
24658
24827
|
var uniqueSorted6 = (values) => [
|
|
24659
24828
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -24664,7 +24833,7 @@ var surfaceProviderNames = (surface) => uniqueSorted6([
|
|
|
24664
24833
|
...isProviderList(surface.fallback) ? surface.fallback : [],
|
|
24665
24834
|
...isProviderList(surface.allowProviders) ? surface.allowProviders : []
|
|
24666
24835
|
]);
|
|
24667
|
-
var surfaceStatus = (issues) => issues.reduce((status, issue) =>
|
|
24836
|
+
var surfaceStatus = (issues) => issues.reduce((status, issue) => statusRank4[issue.status] > statusRank4[status] ? issue.status : status, "pass");
|
|
24668
24837
|
var resolvedRequirement = (surface, options) => ({
|
|
24669
24838
|
...defaultRequirement,
|
|
24670
24839
|
...options.defaultRequirement ?? {},
|
|
@@ -24796,27 +24965,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
24796
24965
|
};
|
|
24797
24966
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
24798
24967
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
24799
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
24800
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
24968
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml42(surface.status)}">
|
|
24969
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml42(surface.surface)}</p><h2>${escapeHtml42(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml42(surface.status)}</strong></div>
|
|
24801
24970
|
<dl>
|
|
24802
|
-
<div><dt>Providers</dt><dd>${
|
|
24803
|
-
<div><dt>Fallback</dt><dd>${
|
|
24971
|
+
<div><dt>Providers</dt><dd>${escapeHtml42(surface.providers.join(", ") || "none")}</dd></div>
|
|
24972
|
+
<div><dt>Fallback</dt><dd>${escapeHtml42(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
24804
24973
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
24805
24974
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
24806
24975
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
24807
24976
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
24808
24977
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
24809
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
24978
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml42(surface.fallbackMode || "default")}</dd></div>
|
|
24810
24979
|
</dl>
|
|
24811
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
24980
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml42(issue.status)}</strong> ${escapeHtml42(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
24812
24981
|
</article>`).join("");
|
|
24813
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24982
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#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>${escapeHtml42(title)}</h1><div class="summary"><span class="pill">${escapeHtml42(report.profileId)}</span><span class="pill">${escapeHtml42(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>`;
|
|
24814
24983
|
};
|
|
24815
24984
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
24816
24985
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
24817
24986
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
24818
24987
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
24819
|
-
const routes = new
|
|
24988
|
+
const routes = new Elysia43({
|
|
24820
24989
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
24821
24990
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
24822
24991
|
if (htmlPath) {
|
|
@@ -24987,7 +25156,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
24987
25156
|
return report;
|
|
24988
25157
|
};
|
|
24989
25158
|
// src/providerSlo.ts
|
|
24990
|
-
import { Elysia as
|
|
25159
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
24991
25160
|
var defaultThresholds = {
|
|
24992
25161
|
llm: {
|
|
24993
25162
|
maxAverageElapsedMs: 2500,
|
|
@@ -25015,12 +25184,12 @@ var defaultThresholds = {
|
|
|
25015
25184
|
}
|
|
25016
25185
|
};
|
|
25017
25186
|
var providerKinds = ["llm", "stt", "tts"];
|
|
25018
|
-
var
|
|
25187
|
+
var statusRank5 = {
|
|
25019
25188
|
pass: 0,
|
|
25020
25189
|
warn: 1,
|
|
25021
25190
|
fail: 2
|
|
25022
25191
|
};
|
|
25023
|
-
var
|
|
25192
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25024
25193
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
25025
25194
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
25026
25195
|
var uniqueSorted7 = (values) => [
|
|
@@ -25212,7 +25381,7 @@ var evaluateVoiceProviderSloEvidence = (report, input = {}) => {
|
|
|
25212
25381
|
const timeouts = kindReports.reduce((total, kind) => total + kind.timeouts, 0);
|
|
25213
25382
|
const unresolvedErrors = kindReports.reduce((total, kind) => total + kind.unresolvedErrors, 0);
|
|
25214
25383
|
const maxStatus = input.maxStatus ?? "pass";
|
|
25215
|
-
if (
|
|
25384
|
+
if (statusRank5[report.status] > statusRank5[maxStatus]) {
|
|
25216
25385
|
issues.push(`Expected provider SLO status at most ${maxStatus}, found ${report.status}.`);
|
|
25217
25386
|
}
|
|
25218
25387
|
if (input.minEvents !== undefined && report.events < input.minEvents) {
|
|
@@ -25316,11 +25485,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
25316
25485
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
25317
25486
|
const kindCards = providerKinds.map((kind) => {
|
|
25318
25487
|
const kindReport = report.kinds[kind];
|
|
25319
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
25488
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml43(metric.label)}</dt><dd>${escapeHtml43(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml43(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
25320
25489
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
25321
|
-
return `<article class="${
|
|
25490
|
+
return `<article class="${escapeHtml43(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml43(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml43(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
25322
25491
|
}).join("");
|
|
25323
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
25492
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml43(issue.status)}"><strong>${escapeHtml43(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml43(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
25324
25493
|
const snippet = `createVoiceProviderSloRoutes({
|
|
25325
25494
|
store: runtimeStorage.traces,
|
|
25326
25495
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -25330,7 +25499,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
25330
25499
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
25331
25500
|
}
|
|
25332
25501
|
})`;
|
|
25333
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25502
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(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>${escapeHtml43(title)}</h1><p class="status ${escapeHtml43(report.status)}">${escapeHtml43(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>${escapeHtml43(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
25334
25503
|
};
|
|
25335
25504
|
var createVoiceProviderSloRoutes = (options) => {
|
|
25336
25505
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -25341,7 +25510,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
25341
25510
|
...options.headers ?? {}
|
|
25342
25511
|
};
|
|
25343
25512
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
25344
|
-
const app = new
|
|
25513
|
+
const app = new Elysia44({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
25345
25514
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
25346
25515
|
if (markdownPath !== false) {
|
|
25347
25516
|
app.get(markdownPath, async () => {
|
|
@@ -25371,10 +25540,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
25371
25540
|
return app;
|
|
25372
25541
|
};
|
|
25373
25542
|
// src/productionReadiness.ts
|
|
25374
|
-
import { Elysia as
|
|
25543
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
25375
25544
|
|
|
25376
25545
|
// src/telephony/security.ts
|
|
25377
|
-
import { Elysia as
|
|
25546
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
25378
25547
|
|
|
25379
25548
|
// src/postgresStore.ts
|
|
25380
25549
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -26112,7 +26281,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
26112
26281
|
};
|
|
26113
26282
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
26114
26283
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
26115
|
-
return new
|
|
26284
|
+
return new Elysia45({
|
|
26116
26285
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
26117
26286
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
26118
26287
|
};
|
|
@@ -26169,8 +26338,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
26169
26338
|
};
|
|
26170
26339
|
|
|
26171
26340
|
// src/opsRecovery.ts
|
|
26172
|
-
import { Elysia as
|
|
26173
|
-
var
|
|
26341
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
26342
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26174
26343
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
26175
26344
|
var hrefForSession = (value, sessionId) => {
|
|
26176
26345
|
if (typeof value === "function") {
|
|
@@ -26384,19 +26553,19 @@ ${failedSessions || "None."}
|
|
|
26384
26553
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
26385
26554
|
`;
|
|
26386
26555
|
};
|
|
26387
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
26556
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml44(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>${escapeHtml44(label)}</span><strong>not configured</strong></article>`;
|
|
26388
26557
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
26389
26558
|
const title = options.title ?? "Voice Ops Recovery";
|
|
26390
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
26391
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
26392
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
26393
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26559
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml44(issue.severity)}</td><td><code>${escapeHtml44(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml44(issue.href)}">${escapeHtml44(issue.label)}</a>` : escapeHtml44(issue.label)}</td><td>${escapeHtml44(String(issue.value ?? ""))}</td><td>${escapeHtml44(issue.detail ?? "")}</td></tr>`).join("");
|
|
26560
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml44(provider.provider)}</td><td>${escapeHtml44(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml44(provider.lastError ?? "")}</td></tr>`).join("");
|
|
26561
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml44(session.operationsRecordHref)}">${escapeHtml44(session.sessionId)}</a>` : escapeHtml44(session.sessionId)}${session.provider ? ` via ${escapeHtml44(session.provider)}` : ""}${session.error ? `: ${escapeHtml44(session.error)}` : ""}</li>`).join("");
|
|
26562
|
+
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{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>${escapeHtml44(title)}</h1><p><span class="status">${escapeHtml44(report.status)}</span> Checked ${escapeHtml44(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>${escapeHtml44(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>`;
|
|
26394
26563
|
};
|
|
26395
26564
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
26396
26565
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
26397
26566
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
26398
26567
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
26399
|
-
const routes = new
|
|
26568
|
+
const routes = new Elysia46({
|
|
26400
26569
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
26401
26570
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
26402
26571
|
if (htmlPath) {
|
|
@@ -26426,18 +26595,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
26426
26595
|
};
|
|
26427
26596
|
|
|
26428
26597
|
// src/observabilityExport.ts
|
|
26429
|
-
import { Elysia as
|
|
26598
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
26430
26599
|
import { Database as Database4 } from "bun:sqlite";
|
|
26431
26600
|
import { createHash } from "crypto";
|
|
26432
26601
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
26433
26602
|
import { join as join3 } from "path";
|
|
26434
26603
|
|
|
26435
26604
|
// src/operationsRecord.ts
|
|
26436
|
-
import { Elysia as
|
|
26605
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
26437
26606
|
|
|
26438
26607
|
// src/traceTimeline.ts
|
|
26439
|
-
import { Elysia as
|
|
26440
|
-
var
|
|
26608
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
26609
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26441
26610
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
26442
26611
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
26443
26612
|
var firstString3 = (payload, keys) => {
|
|
@@ -26620,17 +26789,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
26620
26789
|
};
|
|
26621
26790
|
};
|
|
26622
26791
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
26623
|
-
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>${
|
|
26792
|
+
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>${escapeHtml45(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>`;
|
|
26624
26793
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
26625
|
-
const events = session.events.map((event) => `<tr class="${
|
|
26626
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
26627
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
26628
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26794
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml45(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml45(event.type)}</td><td>${escapeHtml45(event.label)}</td><td>${escapeHtml45(event.provider ?? "")}</td><td>${escapeHtml45(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
26795
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml45(issue.severity)}">${escapeHtml45(issue.code)}: ${escapeHtml45(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
26796
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml45(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
26797
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(session.sessionId)}</h1><p class="status ${escapeHtml45(session.status)}">${escapeHtml45(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>`;
|
|
26629
26798
|
};
|
|
26630
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
26799
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml45(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml45(session.sessionId)}</a>`}</td><td>${escapeHtml45(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) => escapeHtml45(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
26631
26800
|
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}}";
|
|
26632
26801
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
26633
|
-
const snippet =
|
|
26802
|
+
const snippet = escapeHtml45(`const traceStore = createVoiceTraceSinkStore({
|
|
26634
26803
|
store: runtimeStorage.traces,
|
|
26635
26804
|
sinks: [
|
|
26636
26805
|
createVoiceTraceHTTPSink({
|
|
@@ -26656,13 +26825,13 @@ app.use(
|
|
|
26656
26825
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
26657
26826
|
})
|
|
26658
26827
|
);`);
|
|
26659
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26828
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(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>`;
|
|
26660
26829
|
};
|
|
26661
26830
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
26662
26831
|
const path = options.path ?? "/api/voice-traces";
|
|
26663
26832
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
26664
26833
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
26665
|
-
const routes = new
|
|
26834
|
+
const routes = new Elysia47({
|
|
26666
26835
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
26667
26836
|
});
|
|
26668
26837
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -27091,7 +27260,7 @@ var assertVoiceOperationsRecordProviderRecovery = (record, input = {}) => {
|
|
|
27091
27260
|
}
|
|
27092
27261
|
return report;
|
|
27093
27262
|
};
|
|
27094
|
-
var
|
|
27263
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27095
27264
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
27096
27265
|
var outcomeLabels = (outcome) => [
|
|
27097
27266
|
outcome.complete ? "complete" : undefined,
|
|
@@ -27171,20 +27340,20 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
27171
27340
|
`);
|
|
27172
27341
|
};
|
|
27173
27342
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
27174
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
27175
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
27176
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
27343
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml46(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>';
|
|
27344
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml46(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml46(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml46(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml46(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
27345
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml46(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml46(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml46(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml46(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml46(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml46(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml46(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml46(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
27177
27346
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
27178
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
27179
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
27180
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
27181
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
27182
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
27347
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml46(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml46(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml46(handoff.status ?? "")}</span><p>${escapeHtml46(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
27348
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml46(tool.toolName ?? "tool")}</strong> <span>${escapeHtml46(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml46(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
27349
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml46(review.title)}</strong> <span>${escapeHtml46(review.summary.outcome ?? "")}</span><p>${escapeHtml46(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
27350
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml46(task.title)}</strong> <span>${escapeHtml46(task.status)}</span><p>${escapeHtml46(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
27351
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml46(event.type)}</strong> <span>${escapeHtml46(event.deliveryStatus ?? "local")}</span><p>${escapeHtml46(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
27183
27352
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
27184
27353
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
27185
|
-
return `<li><strong>assistant.guardrail ${
|
|
27354
|
+
return `<li><strong>assistant.guardrail ${escapeHtml46(decision.stage ?? "unknown")}</strong> <span>${escapeHtml46(decision.status ?? "")}</span><p>Allowed: ${escapeHtml46(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml46(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml46(decision.turnId)}` : ""}</p><p>${escapeHtml46(findings)}</p></li>`;
|
|
27186
27355
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
27187
|
-
const snippet =
|
|
27356
|
+
const snippet = escapeHtml46(`app.use(
|
|
27188
27357
|
createVoiceOperationsRecordRoutes({
|
|
27189
27358
|
audit: auditStore,
|
|
27190
27359
|
integrationEvents: opsEvents,
|
|
@@ -27198,16 +27367,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
27198
27367
|
tasks: opsTasks
|
|
27199
27368
|
})
|
|
27200
27369
|
);`);
|
|
27201
|
-
const incidentMarkdown =
|
|
27202
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
27203
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27370
|
+
const incidentMarkdown = escapeHtml46(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
27371
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml46(options.incidentHref)}">Download incident.md</a>` : "";
|
|
27372
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(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>${escapeHtml46(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml46(record.status)}">${escapeHtml46(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>${escapeHtml46(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>`;
|
|
27204
27373
|
};
|
|
27205
27374
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
27206
27375
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
27207
27376
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
27208
27377
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
27209
27378
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
27210
|
-
const routes = new
|
|
27379
|
+
const routes = new Elysia48({
|
|
27211
27380
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
27212
27381
|
});
|
|
27213
27382
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -27858,7 +28027,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
27858
28027
|
...options.headers ?? {}
|
|
27859
28028
|
};
|
|
27860
28029
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
27861
|
-
const app = new
|
|
28030
|
+
const app = new Elysia49({
|
|
27862
28031
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
27863
28032
|
});
|
|
27864
28033
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28667,7 +28836,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28667
28836
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
28668
28837
|
}
|
|
28669
28838
|
});
|
|
28670
|
-
const app = new
|
|
28839
|
+
const app = new Elysia49({
|
|
28671
28840
|
name: options.name ?? "absolute-voice-observability-export"
|
|
28672
28841
|
});
|
|
28673
28842
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28744,7 +28913,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28744
28913
|
};
|
|
28745
28914
|
|
|
28746
28915
|
// src/productionReadiness.ts
|
|
28747
|
-
var
|
|
28916
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28748
28917
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
28749
28918
|
var readinessGateCodes = {
|
|
28750
28919
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -30199,25 +30368,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30199
30368
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
30200
30369
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
30201
30370
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
30202
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
30203
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
30371
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml47(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
30372
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml47(report.profile.name)}</h2><p>${escapeHtml47(report.profile.description)}</p><p>${escapeHtml47(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="${escapeHtml47(surface.href)}">${escapeHtml47(surface.label)}</a>` : escapeHtml47(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
30204
30373
|
const checks = report.checks.map((check, index) => {
|
|
30205
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
30206
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
30207
|
-
return `<article class="check ${
|
|
30374
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml47(action.href)}">${escapeHtml47(action.label)}</button>` : `<a href="${escapeHtml47(action.href)}">${escapeHtml47(action.label)}</a>`).join("");
|
|
30375
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml47(check.status)}: observed ${escapeHtml47(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml47(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml47(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml47(check.gateExplanation.unit)}` : ""}. ${escapeHtml47(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml47(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
30376
|
+
return `<article class="check ${escapeHtml47(check.status)}">
|
|
30208
30377
|
<div>
|
|
30209
|
-
<span>${
|
|
30210
|
-
<h2>${
|
|
30211
|
-
${check.detail ? `<p>${
|
|
30378
|
+
<span>${escapeHtml47(check.status.toUpperCase())}</span>
|
|
30379
|
+
<h2>${escapeHtml47(check.label)}</h2>
|
|
30380
|
+
${check.detail ? `<p>${escapeHtml47(check.detail)}</p>` : ""}
|
|
30212
30381
|
${explanation}
|
|
30213
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
30382
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml47(check.proofSource.href)}">${escapeHtml47(check.proofSource.sourceLabel)}</a>` : escapeHtml47(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml47(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
30214
30383
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
30215
30384
|
</div>
|
|
30216
|
-
<strong>${
|
|
30217
|
-
${check.href ? `<a href="${
|
|
30385
|
+
<strong>${escapeHtml47(String(check.value ?? check.status))}</strong>
|
|
30386
|
+
${check.href ? `<a href="${escapeHtml47(check.href)}">Open surface</a>` : ""}
|
|
30218
30387
|
</article>`;
|
|
30219
30388
|
}).join("");
|
|
30220
|
-
const snippet =
|
|
30389
|
+
const snippet = escapeHtml47(`createVoiceProductionReadinessRoutes({
|
|
30221
30390
|
htmlPath: '/production-readiness',
|
|
30222
30391
|
path: '/api/production-readiness',
|
|
30223
30392
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -30233,13 +30402,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
30233
30402
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
30234
30403
|
store: traceStore
|
|
30235
30404
|
});`);
|
|
30236
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30405
|
+
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{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>${escapeHtml47(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 ${escapeHtml47(report.status)}">Overall: ${escapeHtml47(report.status.toUpperCase())}</p><p>Checked ${escapeHtml47(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>`;
|
|
30237
30406
|
};
|
|
30238
30407
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
30239
30408
|
const path = options.path ?? "/api/production-readiness";
|
|
30240
30409
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
30241
30410
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
30242
|
-
const routes = new
|
|
30411
|
+
const routes = new Elysia50({
|
|
30243
30412
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
30244
30413
|
});
|
|
30245
30414
|
const resolveOptions = async (input) => {
|
|
@@ -30287,8 +30456,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
30287
30456
|
return routes;
|
|
30288
30457
|
};
|
|
30289
30458
|
// src/voiceMonitoring.ts
|
|
30290
|
-
import { Elysia as
|
|
30291
|
-
var
|
|
30459
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
30460
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30292
30461
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
30293
30462
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
30294
30463
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -30541,14 +30710,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
30541
30710
|
};
|
|
30542
30711
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
30543
30712
|
const title = options.title ?? "Voice Monitors";
|
|
30544
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
30545
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
30546
|
-
const snippet =
|
|
30713
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml48(run.label)}</td><td class="${escapeHtml48(run.status)}">${escapeHtml48(run.status)}</td><td>${escapeHtml48(run.severity)}</td><td>${escapeHtml48(String(run.value ?? ""))}</td><td>${escapeHtml48(String(run.threshold ?? ""))}</td><td>${escapeHtml48(run.detail ?? "")}</td></tr>`).join("");
|
|
30714
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml48(issue.label)}</strong> <span class="${escapeHtml48(issue.status)}">${escapeHtml48(issue.status)}</span> ${escapeHtml48(issue.detail ?? "")}</li>`).join("");
|
|
30715
|
+
const snippet = escapeHtml48(`app.use(createVoiceMonitorRoutes({
|
|
30547
30716
|
evidence,
|
|
30548
30717
|
issueStore,
|
|
30549
30718
|
monitors: [defineVoiceMonitor(...)]
|
|
30550
30719
|
}));`);
|
|
30551
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30720
|
+
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:#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>${escapeHtml48(title)}</h1><p class="pill ${escapeHtml48(report.status)}">Status: ${escapeHtml48(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>`;
|
|
30552
30721
|
};
|
|
30553
30722
|
var actorFromRequest = async (request) => {
|
|
30554
30723
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -30572,7 +30741,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30572
30741
|
monitors: options.monitors,
|
|
30573
30742
|
now: options.now
|
|
30574
30743
|
});
|
|
30575
|
-
const routes = new
|
|
30744
|
+
const routes = new Elysia51({
|
|
30576
30745
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
30577
30746
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
30578
30747
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -30619,7 +30788,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30619
30788
|
};
|
|
30620
30789
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
30621
30790
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
30622
|
-
return new
|
|
30791
|
+
return new Elysia51({
|
|
30623
30792
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
30624
30793
|
}).get(path, () => ({
|
|
30625
30794
|
isRunning: options.runner.isRunning()
|
|
@@ -30995,8 +31164,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
30995
31164
|
};
|
|
30996
31165
|
};
|
|
30997
31166
|
// src/providerStackRecommendations.ts
|
|
30998
|
-
import { Elysia as
|
|
30999
|
-
var
|
|
31167
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
31168
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31000
31169
|
var profileProviderPriorities = {
|
|
31001
31170
|
"meeting-recorder": {
|
|
31002
31171
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -31108,12 +31277,12 @@ var recommendVoiceProviderStack = (input) => {
|
|
|
31108
31277
|
};
|
|
31109
31278
|
};
|
|
31110
31279
|
var rollupContractStatus = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
31111
|
-
var
|
|
31280
|
+
var statusRank6 = {
|
|
31112
31281
|
pass: 0,
|
|
31113
31282
|
warn: 1,
|
|
31114
31283
|
fail: 2
|
|
31115
31284
|
};
|
|
31116
|
-
var statusExceeds2 = (actual, max) =>
|
|
31285
|
+
var statusExceeds2 = (actual, max) => statusRank6[actual] > statusRank6[max];
|
|
31117
31286
|
var buildVoiceProviderContractMatrix = (input) => {
|
|
31118
31287
|
const rows = input.contracts.map((contract) => {
|
|
31119
31288
|
const configured = contract.configured !== false;
|
|
@@ -31315,17 +31484,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
31315
31484
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
31316
31485
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
31317
31486
|
const rows = report.rows.map((row) => {
|
|
31318
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
31319
|
-
return `<article class="row ${
|
|
31487
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml49(check.status)}"><strong>${escapeHtml49(check.label)}</strong><span>${escapeHtml49(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml49(check.remediation.href)}">${escapeHtml49(check.remediation.label)}</a>` : escapeHtml49(check.remediation.label)}: ${escapeHtml49(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
31488
|
+
return `<article class="row ${escapeHtml49(row.status)}">
|
|
31320
31489
|
<div>
|
|
31321
|
-
<p class="eyebrow">${
|
|
31322
|
-
<h2>${
|
|
31323
|
-
<p class="status ${
|
|
31490
|
+
<p class="eyebrow">${escapeHtml49(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
31491
|
+
<h2>${escapeHtml49(row.provider)}</h2>
|
|
31492
|
+
<p class="status ${escapeHtml49(row.status)}">${escapeHtml49(row.status.toUpperCase())}</p>
|
|
31324
31493
|
</div>
|
|
31325
31494
|
<ul>${checks}</ul>
|
|
31326
31495
|
</article>`;
|
|
31327
31496
|
}).join("");
|
|
31328
|
-
const snippet =
|
|
31497
|
+
const snippet = escapeHtml49(`const providerContracts = () =>
|
|
31329
31498
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
31330
31499
|
env: process.env,
|
|
31331
31500
|
providers: {
|
|
@@ -31346,7 +31515,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
31346
31515
|
providerContractMatrix: () =>
|
|
31347
31516
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
31348
31517
|
});`);
|
|
31349
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31518
|
+
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:#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>${escapeHtml49(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>`;
|
|
31350
31519
|
};
|
|
31351
31520
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
31352
31521
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -31361,7 +31530,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
31361
31530
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
31362
31531
|
const path = options.path ?? "/api/provider-contracts";
|
|
31363
31532
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
31364
|
-
const routes = new
|
|
31533
|
+
const routes = new Elysia52({
|
|
31365
31534
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
31366
31535
|
});
|
|
31367
31536
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -31479,7 +31648,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
31479
31648
|
return assertion;
|
|
31480
31649
|
};
|
|
31481
31650
|
// src/opsConsoleRoutes.ts
|
|
31482
|
-
import { Elysia as
|
|
31651
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
31483
31652
|
var DEFAULT_LINKS = [
|
|
31484
31653
|
{
|
|
31485
31654
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -31514,7 +31683,7 @@ var DEFAULT_LINKS = [
|
|
|
31514
31683
|
label: "Handoffs"
|
|
31515
31684
|
}
|
|
31516
31685
|
];
|
|
31517
|
-
var
|
|
31686
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31518
31687
|
var countProviderStatuses = (providers) => {
|
|
31519
31688
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
31520
31689
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -31583,20 +31752,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
31583
31752
|
trace
|
|
31584
31753
|
};
|
|
31585
31754
|
};
|
|
31586
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
31755
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml50(input.label)}</span><strong>${escapeHtml50(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml50(input.status)}">${escapeHtml50(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml50(input.href)}">Open</a>` : ""}</article>`;
|
|
31587
31756
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
31588
31757
|
const links = report.links.map((link) => `<article class="surface">
|
|
31589
|
-
<div><h2>${
|
|
31590
|
-
<p><a href="${
|
|
31758
|
+
<div><h2>${escapeHtml50(link.label)}</h2>${link.description ? `<p>${escapeHtml50(link.description)}</p>` : ""}</div>
|
|
31759
|
+
<p><a href="${escapeHtml50(link.href)}">Open ${escapeHtml50(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml50(link.statusHref)}">Status</a>` : ""}</p>
|
|
31591
31760
|
</article>`).join("");
|
|
31592
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
31593
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
31761
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml50(session.sessionId)}</td><td>${escapeHtml50(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml50(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
31762
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml50(event.kind)}</td><td>${escapeHtml50(event.provider ?? "unknown")}</td><td>${escapeHtml50(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml50(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
31594
31763
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
31595
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31764
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{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>${escapeHtml50(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 ${escapeHtml50(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>`;
|
|
31596
31765
|
};
|
|
31597
31766
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
31598
31767
|
const path = options.path ?? "/ops-console";
|
|
31599
|
-
const routes = new
|
|
31768
|
+
const routes = new Elysia53({
|
|
31600
31769
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
31601
31770
|
});
|
|
31602
31771
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -31613,7 +31782,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
31613
31782
|
return routes;
|
|
31614
31783
|
};
|
|
31615
31784
|
// src/incidentBundle.ts
|
|
31616
|
-
import { Elysia as
|
|
31785
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
31617
31786
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
31618
31787
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
31619
31788
|
return false;
|
|
@@ -31814,7 +31983,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
31814
31983
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
31815
31984
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
31816
31985
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
31817
|
-
const routes = new
|
|
31986
|
+
const routes = new Elysia54({
|
|
31818
31987
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
31819
31988
|
});
|
|
31820
31989
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -32015,19 +32184,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
32015
32184
|
};
|
|
32016
32185
|
};
|
|
32017
32186
|
// src/opsStatusRoutes.ts
|
|
32018
|
-
import { Elysia as
|
|
32019
|
-
var
|
|
32187
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
32188
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32020
32189
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
32021
32190
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
32022
32191
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
32023
32192
|
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;
|
|
32024
|
-
return `<article class="surface ${
|
|
32193
|
+
return `<article class="surface ${escapeHtml51(surface.status)}"><span>${escapeHtml51(surface.status.toUpperCase())}</span><h2>${escapeHtml51(key)}</h2><strong>${escapeHtml51(value)}</strong></article>`;
|
|
32025
32194
|
}).join("");
|
|
32026
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32195
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#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>${escapeHtml51(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml51(report.status)}">Overall: ${escapeHtml51(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>`;
|
|
32027
32196
|
};
|
|
32028
32197
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
32029
32198
|
const path = options.path ?? "/api/voice/ops-status";
|
|
32030
|
-
const routes = new
|
|
32199
|
+
const routes = new Elysia55({
|
|
32031
32200
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
32032
32201
|
});
|
|
32033
32202
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -32460,8 +32629,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
32460
32629
|
};
|
|
32461
32630
|
};
|
|
32462
32631
|
// src/traceDeliveryRoutes.ts
|
|
32463
|
-
import { Elysia as
|
|
32464
|
-
var
|
|
32632
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
32633
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32465
32634
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
32466
32635
|
var getNumber12 = (value) => {
|
|
32467
32636
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -32542,14 +32711,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
32542
32711
|
if (entries.length === 0) {
|
|
32543
32712
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
32544
32713
|
}
|
|
32545
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
32714
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml52(sinkId)}</strong>: ${escapeHtml52(result.status)}${result.deliveredTo ? ` to ${escapeHtml52(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml52(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
32546
32715
|
};
|
|
32547
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
32716
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml52(event.type)} <small>${escapeHtml52(event.id)}</small>${event.sessionId ? ` session=${escapeHtml52(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
32548
32717
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
32549
32718
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
32550
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
32551
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
32552
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32719
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml52(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
32720
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml52(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml52(delivery.deliveryStatus)}</span><h2>${escapeHtml52(delivery.id)}</h2><p>${escapeHtml52(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml52(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml52(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
32721
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#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>${escapeHtml52(title)}</h1><p>Checked ${escapeHtml52(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>`;
|
|
32553
32722
|
};
|
|
32554
32723
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
32555
32724
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -32569,7 +32738,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
32569
32738
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
32570
32739
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
32571
32740
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
32572
|
-
const routes = new
|
|
32741
|
+
const routes = new Elysia56({
|
|
32573
32742
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
32574
32743
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
32575
32744
|
if (htmlPath !== false) {
|
|
@@ -32666,7 +32835,7 @@ var createVoiceMemoryStore = () => {
|
|
|
32666
32835
|
return { get, getOrCreate, list, remove, set };
|
|
32667
32836
|
};
|
|
32668
32837
|
// src/opsWebhook.ts
|
|
32669
|
-
import { Elysia as
|
|
32838
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
32670
32839
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
32671
32840
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
32672
32841
|
const encoder = new TextEncoder;
|
|
@@ -32796,7 +32965,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
32796
32965
|
};
|
|
32797
32966
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
32798
32967
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
32799
|
-
return new
|
|
32968
|
+
return new Elysia57().post(path, async ({ body, request, set }) => {
|
|
32800
32969
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
32801
32970
|
if (options.signingSecret) {
|
|
32802
32971
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -33251,7 +33420,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
33251
33420
|
};
|
|
33252
33421
|
};
|
|
33253
33422
|
// src/postCallAnalysis.ts
|
|
33254
|
-
import { Elysia as
|
|
33423
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
33255
33424
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
33256
33425
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
33257
33426
|
var getPathValue3 = (source, path) => {
|
|
@@ -33430,7 +33599,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
33430
33599
|
};
|
|
33431
33600
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
33432
33601
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
33433
|
-
const routes = new
|
|
33602
|
+
const routes = new Elysia58({
|
|
33434
33603
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
33435
33604
|
});
|
|
33436
33605
|
routes.get(path, async ({ query }) => {
|
|
@@ -33455,7 +33624,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
33455
33624
|
return routes;
|
|
33456
33625
|
};
|
|
33457
33626
|
// src/guardrails.ts
|
|
33458
|
-
import { Elysia as
|
|
33627
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
33459
33628
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
33460
33629
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
33461
33630
|
var matchesRule = async (rule, input) => {
|
|
@@ -33757,7 +33926,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
33757
33926
|
};
|
|
33758
33927
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
33759
33928
|
const path = options.path ?? "/api/voice/guardrails";
|
|
33760
|
-
const routes = new
|
|
33929
|
+
const routes = new Elysia59({
|
|
33761
33930
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
33762
33931
|
});
|
|
33763
33932
|
routes.all(path, async ({ request }) => {
|
|
@@ -34310,6 +34479,8 @@ export {
|
|
|
34310
34479
|
renderVoiceObservabilityExportMarkdown,
|
|
34311
34480
|
renderVoiceMonitorMarkdown,
|
|
34312
34481
|
renderVoiceMonitorHTML,
|
|
34482
|
+
renderVoiceMediaPipelineMarkdown,
|
|
34483
|
+
renderVoiceMediaPipelineHTML,
|
|
34313
34484
|
renderVoiceLiveLatencyHTML,
|
|
34314
34485
|
renderVoiceLatencySLOMarkdown,
|
|
34315
34486
|
renderVoiceHandoffHealthHTML,
|
|
@@ -34397,6 +34568,7 @@ export {
|
|
|
34397
34568
|
evaluateVoiceOperationsRecordGuardrails,
|
|
34398
34569
|
evaluateVoiceObservabilityExportReplayEvidence,
|
|
34399
34570
|
evaluateVoiceObservabilityExportDeliveryEvidence,
|
|
34571
|
+
evaluateVoiceMediaPipelineEvidence,
|
|
34400
34572
|
evaluateVoiceLiveOpsEvidence,
|
|
34401
34573
|
evaluateVoiceLiveOpsControlEvidence,
|
|
34402
34574
|
evaluateVoiceGuardrailPolicy,
|
|
@@ -34591,6 +34763,7 @@ export {
|
|
|
34591
34763
|
createVoiceMemoryAuditSinkDeliveryStore,
|
|
34592
34764
|
createVoiceMemoryAuditEventStore,
|
|
34593
34765
|
createVoiceMemoryAssistantMemoryStore,
|
|
34766
|
+
createVoiceMediaPipelineRoutes,
|
|
34594
34767
|
createVoiceMediaFrameTransformPipeline,
|
|
34595
34768
|
createVoiceMediaFrame,
|
|
34596
34769
|
createVoiceLiveOpsRoutes,
|
|
@@ -34743,6 +34916,7 @@ export {
|
|
|
34743
34916
|
buildVoiceMonitorRunReport,
|
|
34744
34917
|
buildVoiceMediaVadReport,
|
|
34745
34918
|
buildVoiceMediaResamplingPlan,
|
|
34919
|
+
buildVoiceMediaPipelineReport,
|
|
34746
34920
|
buildVoiceMediaPipelineCalibrationReport,
|
|
34747
34921
|
buildVoiceMediaInterruptionReport,
|
|
34748
34922
|
buildVoiceLiveOpsControlState,
|
|
@@ -34786,6 +34960,7 @@ export {
|
|
|
34786
34960
|
assertVoiceObservabilityExportReplayEvidence,
|
|
34787
34961
|
assertVoiceObservabilityExportRecord,
|
|
34788
34962
|
assertVoiceObservabilityExportDeliveryEvidence,
|
|
34963
|
+
assertVoiceMediaPipelineEvidence,
|
|
34789
34964
|
assertVoiceLiveOpsEvidence,
|
|
34790
34965
|
assertVoiceLiveOpsControlEvidence,
|
|
34791
34966
|
assertVoiceLatencySLOGate,
|