@absolutejs/voice 0.0.22-beta.310 → 0.0.22-beta.312
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 +4 -2
- package/dist/index.js +697 -413
- package/dist/mediaPipeline.d.ts +44 -0
- package/dist/mediaPipelineRoutes.d.ts +99 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11620,6 +11620,95 @@ var numericMetadata = (frame, key) => {
|
|
|
11620
11620
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
11621
11621
|
};
|
|
11622
11622
|
var createVoiceMediaFrame = (frame) => frame;
|
|
11623
|
+
var buildVoiceMediaTransportReport = (input) => {
|
|
11624
|
+
const events = input.events ?? [];
|
|
11625
|
+
const state = input.state ?? events.at(-1)?.state ?? "idle";
|
|
11626
|
+
const backpressureEvents = events.filter((event) => event.kind === "backpressure").length;
|
|
11627
|
+
const failed = state === "failed" || events.some((event) => event.kind === "error");
|
|
11628
|
+
return {
|
|
11629
|
+
backpressureEvents,
|
|
11630
|
+
checkedAt: Date.now(),
|
|
11631
|
+
closed: state === "closed",
|
|
11632
|
+
connected: state === "open",
|
|
11633
|
+
events,
|
|
11634
|
+
failed,
|
|
11635
|
+
inputFrames: events.filter((event) => event.kind === "frame-in").length,
|
|
11636
|
+
name: input.name,
|
|
11637
|
+
outputFrames: events.filter((event) => event.kind === "frame-out").length,
|
|
11638
|
+
state,
|
|
11639
|
+
status: failed ? "fail" : backpressureEvents > 0 ? "warn" : "pass"
|
|
11640
|
+
};
|
|
11641
|
+
};
|
|
11642
|
+
var createVoiceMediaTransport = (options) => {
|
|
11643
|
+
let state = "idle";
|
|
11644
|
+
const events = [];
|
|
11645
|
+
const frameHandlers = new Set;
|
|
11646
|
+
const record = (event) => {
|
|
11647
|
+
events.push({ ...event, at: Date.now(), state });
|
|
11648
|
+
};
|
|
11649
|
+
return {
|
|
11650
|
+
close: async () => {
|
|
11651
|
+
state = "closing";
|
|
11652
|
+
await options.onClose?.();
|
|
11653
|
+
state = "closed";
|
|
11654
|
+
record({ kind: "close" });
|
|
11655
|
+
},
|
|
11656
|
+
connect: async () => {
|
|
11657
|
+
try {
|
|
11658
|
+
await options.onConnect?.();
|
|
11659
|
+
state = "open";
|
|
11660
|
+
record({ kind: "connect" });
|
|
11661
|
+
} catch (error) {
|
|
11662
|
+
state = "failed";
|
|
11663
|
+
record({
|
|
11664
|
+
error: error instanceof Error ? error.message : String(error),
|
|
11665
|
+
kind: "error"
|
|
11666
|
+
});
|
|
11667
|
+
throw error;
|
|
11668
|
+
}
|
|
11669
|
+
},
|
|
11670
|
+
events: () => [...events],
|
|
11671
|
+
inputFormat: options.inputFormat,
|
|
11672
|
+
name: options.name,
|
|
11673
|
+
onFrame: (handler) => {
|
|
11674
|
+
frameHandlers.add(handler);
|
|
11675
|
+
return () => frameHandlers.delete(handler);
|
|
11676
|
+
},
|
|
11677
|
+
outputFormat: options.outputFormat,
|
|
11678
|
+
receive: async (frame) => {
|
|
11679
|
+
record({ frameId: frame.id, kind: "frame-in" });
|
|
11680
|
+
if (options.maxBufferedFrames !== undefined && events.filter((event) => event.kind === "frame-in").length > options.maxBufferedFrames) {
|
|
11681
|
+
record({
|
|
11682
|
+
bufferedFrames: events.filter((event) => event.kind === "frame-in").length,
|
|
11683
|
+
kind: "backpressure"
|
|
11684
|
+
});
|
|
11685
|
+
}
|
|
11686
|
+
for (const handler of frameHandlers) {
|
|
11687
|
+
await handler(frame);
|
|
11688
|
+
}
|
|
11689
|
+
},
|
|
11690
|
+
report: () => buildVoiceMediaTransportReport({
|
|
11691
|
+
events,
|
|
11692
|
+
name: options.name,
|
|
11693
|
+
state
|
|
11694
|
+
}),
|
|
11695
|
+
send: async (frame) => {
|
|
11696
|
+
try {
|
|
11697
|
+
await options.onSend?.(frame);
|
|
11698
|
+
record({ frameId: frame.id, kind: "frame-out" });
|
|
11699
|
+
} catch (error) {
|
|
11700
|
+
state = "failed";
|
|
11701
|
+
record({
|
|
11702
|
+
error: error instanceof Error ? error.message : String(error),
|
|
11703
|
+
frameId: frame.id,
|
|
11704
|
+
kind: "error"
|
|
11705
|
+
});
|
|
11706
|
+
throw error;
|
|
11707
|
+
}
|
|
11708
|
+
},
|
|
11709
|
+
state: () => state
|
|
11710
|
+
};
|
|
11711
|
+
};
|
|
11623
11712
|
var buildVoiceMediaResamplingPlan = (input) => {
|
|
11624
11713
|
const required = !formatMatches2(input.inputFormat, input.outputFormat);
|
|
11625
11714
|
return {
|
|
@@ -11818,9 +11907,196 @@ var buildVoiceMediaPipelineCalibrationReport = (input = {}) => {
|
|
|
11818
11907
|
turnCommitFrames: turnCommitFrames.length
|
|
11819
11908
|
};
|
|
11820
11909
|
};
|
|
11821
|
-
// src/
|
|
11910
|
+
// src/mediaPipelineRoutes.ts
|
|
11822
11911
|
import { Elysia as Elysia12 } from "elysia";
|
|
11823
|
-
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11912
|
+
var escapeHtml15 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11913
|
+
var statusRank2 = {
|
|
11914
|
+
pass: 0,
|
|
11915
|
+
warn: 1,
|
|
11916
|
+
fail: 2
|
|
11917
|
+
};
|
|
11918
|
+
var worstStatus = (statuses) => statuses.reduce((worst, status) => statusRank2[status] > statusRank2[worst] ? status : worst, "pass");
|
|
11919
|
+
var buildVoiceMediaPipelineReport = (options = {}) => {
|
|
11920
|
+
const frames = options.frames ?? [];
|
|
11921
|
+
const calibration = buildVoiceMediaPipelineCalibrationReport(options);
|
|
11922
|
+
const vad = buildVoiceMediaVadReport({
|
|
11923
|
+
frames,
|
|
11924
|
+
maxSilenceFrames: options.maxSilenceFrames,
|
|
11925
|
+
minSpeechFrames: options.minSpeechFrames,
|
|
11926
|
+
speechEndThreshold: options.speechEndThreshold,
|
|
11927
|
+
speechStartThreshold: options.speechStartThreshold
|
|
11928
|
+
});
|
|
11929
|
+
const interruption = buildVoiceMediaInterruptionReport({
|
|
11930
|
+
frames,
|
|
11931
|
+
maxInterruptionLatencyMs: options.maxInterruptionLatencyMs
|
|
11932
|
+
});
|
|
11933
|
+
const resampling = calibration.inputFormat && calibration.outputFormat ? buildVoiceMediaResamplingPlan({
|
|
11934
|
+
inputFormat: calibration.inputFormat,
|
|
11935
|
+
outputFormat: calibration.outputFormat
|
|
11936
|
+
}) : undefined;
|
|
11937
|
+
const status = worstStatus([
|
|
11938
|
+
calibration.status,
|
|
11939
|
+
vad.status,
|
|
11940
|
+
interruption.status,
|
|
11941
|
+
resampling?.status ?? "pass",
|
|
11942
|
+
options.transport?.status ?? "pass"
|
|
11943
|
+
]);
|
|
11944
|
+
return {
|
|
11945
|
+
calibration,
|
|
11946
|
+
checkedAt: Date.now(),
|
|
11947
|
+
frames: frames.length,
|
|
11948
|
+
interruption,
|
|
11949
|
+
ok: status === "pass",
|
|
11950
|
+
resampling,
|
|
11951
|
+
status,
|
|
11952
|
+
surface: options.surface ?? "voice-media-pipeline",
|
|
11953
|
+
transport: options.transport,
|
|
11954
|
+
vad
|
|
11955
|
+
};
|
|
11956
|
+
};
|
|
11957
|
+
var evaluateVoiceMediaPipelineEvidence = (report, input = {}) => {
|
|
11958
|
+
const issues = [];
|
|
11959
|
+
if ((input.requirePass ?? false) && report.status !== "pass") {
|
|
11960
|
+
issues.push(`Expected media pipeline proof to pass, found ${report.status}.`);
|
|
11961
|
+
}
|
|
11962
|
+
if (input.minInputAudioFrames !== undefined && report.calibration.inputAudioFrames < input.minInputAudioFrames) {
|
|
11963
|
+
issues.push(`Expected at least ${String(input.minInputAudioFrames)} input audio frame(s), found ${String(report.calibration.inputAudioFrames)}.`);
|
|
11964
|
+
}
|
|
11965
|
+
if (input.minAssistantAudioFrames !== undefined && report.calibration.assistantAudioFrames < input.minAssistantAudioFrames) {
|
|
11966
|
+
issues.push(`Expected at least ${String(input.minAssistantAudioFrames)} assistant audio frame(s), found ${String(report.calibration.assistantAudioFrames)}.`);
|
|
11967
|
+
}
|
|
11968
|
+
if (input.minTraceLinkedFrames !== undefined && report.calibration.traceLinkedFrames < input.minTraceLinkedFrames) {
|
|
11969
|
+
issues.push(`Expected at least ${String(input.minTraceLinkedFrames)} trace-linked frame(s), found ${String(report.calibration.traceLinkedFrames)}.`);
|
|
11970
|
+
}
|
|
11971
|
+
if (input.maxFirstAudioLatencyMs !== undefined && (report.calibration.firstAudioLatencyMs === undefined || report.calibration.firstAudioLatencyMs > input.maxFirstAudioLatencyMs)) {
|
|
11972
|
+
issues.push(`Expected first assistant audio at or below ${String(input.maxFirstAudioLatencyMs)}ms, found ${String(report.calibration.firstAudioLatencyMs ?? "missing")}ms.`);
|
|
11973
|
+
}
|
|
11974
|
+
if (input.minVadSegments !== undefined && report.vad.segments.length < input.minVadSegments) {
|
|
11975
|
+
issues.push(`Expected at least ${String(input.minVadSegments)} VAD segment(s), found ${String(report.vad.segments.length)}.`);
|
|
11976
|
+
}
|
|
11977
|
+
if (input.requireInterruptionFrame && report.interruption.interruptionFrames < 1) {
|
|
11978
|
+
issues.push("Expected at least one interruption frame.");
|
|
11979
|
+
}
|
|
11980
|
+
if (input.maxInterruptionLatencyMs !== undefined && report.interruption.latenciesMs.some((latency) => latency > input.maxInterruptionLatencyMs)) {
|
|
11981
|
+
issues.push(`Expected interruption latency at or below ${String(input.maxInterruptionLatencyMs)}ms.`);
|
|
11982
|
+
}
|
|
11983
|
+
if (input.requireResamplingReady && report.calibration.resamplingRequired && !report.resampling) {
|
|
11984
|
+
issues.push("Expected resampling plan when calibration requires resampling.");
|
|
11985
|
+
}
|
|
11986
|
+
if (input.requireTransportConnected && !report.transport?.connected) {
|
|
11987
|
+
issues.push("Expected connected media transport evidence.");
|
|
11988
|
+
}
|
|
11989
|
+
if (input.minTransportInputFrames !== undefined && (report.transport?.inputFrames ?? 0) < input.minTransportInputFrames) {
|
|
11990
|
+
issues.push(`Expected at least ${String(input.minTransportInputFrames)} transport input frame(s), found ${String(report.transport?.inputFrames ?? 0)}.`);
|
|
11991
|
+
}
|
|
11992
|
+
if (input.minTransportOutputFrames !== undefined && (report.transport?.outputFrames ?? 0) < input.minTransportOutputFrames) {
|
|
11993
|
+
issues.push(`Expected at least ${String(input.minTransportOutputFrames)} transport output frame(s), found ${String(report.transport?.outputFrames ?? 0)}.`);
|
|
11994
|
+
}
|
|
11995
|
+
if (input.maxTransportBackpressureEvents !== undefined && (report.transport?.backpressureEvents ?? 0) > input.maxTransportBackpressureEvents) {
|
|
11996
|
+
issues.push(`Expected at most ${String(input.maxTransportBackpressureEvents)} transport backpressure event(s), found ${String(report.transport?.backpressureEvents ?? 0)}.`);
|
|
11997
|
+
}
|
|
11998
|
+
return {
|
|
11999
|
+
issues,
|
|
12000
|
+
ok: issues.length === 0,
|
|
12001
|
+
status: report.status,
|
|
12002
|
+
surface: report.surface
|
|
12003
|
+
};
|
|
12004
|
+
};
|
|
12005
|
+
var assertVoiceMediaPipelineEvidence = (report, input = {}) => {
|
|
12006
|
+
const assertion = evaluateVoiceMediaPipelineEvidence(report, input);
|
|
12007
|
+
if (!assertion.ok) {
|
|
12008
|
+
throw new Error(`Voice media pipeline assertion failed: ${assertion.issues.join(" ")}`);
|
|
12009
|
+
}
|
|
12010
|
+
return assertion;
|
|
12011
|
+
};
|
|
12012
|
+
var renderVoiceMediaPipelineMarkdown = (report) => [
|
|
12013
|
+
"# Voice Media Pipeline Proof",
|
|
12014
|
+
"",
|
|
12015
|
+
`- Status: ${report.status}`,
|
|
12016
|
+
`- Surface: ${report.surface}`,
|
|
12017
|
+
`- Frames: ${String(report.frames)}`,
|
|
12018
|
+
`- Input audio frames: ${String(report.calibration.inputAudioFrames)}`,
|
|
12019
|
+
`- Assistant audio frames: ${String(report.calibration.assistantAudioFrames)}`,
|
|
12020
|
+
`- Trace-linked frames: ${String(report.calibration.traceLinkedFrames)}`,
|
|
12021
|
+
`- First audio latency: ${String(report.calibration.firstAudioLatencyMs ?? "n/a")}ms`,
|
|
12022
|
+
`- Resampling required: ${report.calibration.resamplingRequired ? "yes" : "no"}`,
|
|
12023
|
+
`- VAD segments: ${String(report.vad.segments.length)}`,
|
|
12024
|
+
`- Interruption frames: ${String(report.interruption.interruptionFrames)}`,
|
|
12025
|
+
`- Transport: ${report.transport ? `${report.transport.name} (${report.transport.state})` : "n/a"}`,
|
|
12026
|
+
`- Transport input frames: ${String(report.transport?.inputFrames ?? 0)}`,
|
|
12027
|
+
`- Transport output frames: ${String(report.transport?.outputFrames ?? 0)}`,
|
|
12028
|
+
`- Transport backpressure events: ${String(report.transport?.backpressureEvents ?? 0)}`,
|
|
12029
|
+
"",
|
|
12030
|
+
"## Issues",
|
|
12031
|
+
"",
|
|
12032
|
+
...[
|
|
12033
|
+
...report.calibration.issues,
|
|
12034
|
+
...report.interruption.issues
|
|
12035
|
+
].map((issue) => `- ${issue.severity.toUpperCase()} ${issue.code}: ${issue.message}`),
|
|
12036
|
+
...report.calibration.issues.length + report.interruption.issues.length === 0 ? ["- None"] : []
|
|
12037
|
+
].join(`
|
|
12038
|
+
`);
|
|
12039
|
+
var renderVoiceMediaPipelineHTML = (report, title = "Voice Media Pipeline Proof") => {
|
|
12040
|
+
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("");
|
|
12041
|
+
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("");
|
|
12042
|
+
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><div class="metric"><span>Transport</span><strong>${escapeHtml15(report.transport?.state ?? "n/a")}</strong></div><div class="metric"><span>Transport in/out</span><strong>${String(report.transport?.inputFrames ?? 0)}/${String(report.transport?.outputFrames ?? 0)}</strong></div><div class="metric"><span>Backpressure</span><strong>${String(report.transport?.backpressureEvents ?? 0)}</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>`;
|
|
12043
|
+
};
|
|
12044
|
+
var createVoiceMediaPipelineRoutes = (options = {}) => {
|
|
12045
|
+
const path = options.path ?? "/api/voice/media-pipeline";
|
|
12046
|
+
const htmlPath = options.htmlPath ?? "/voice/media-pipeline";
|
|
12047
|
+
const markdownPath = options.markdownPath ?? "/voice/media-pipeline.md";
|
|
12048
|
+
const headers = options.headers ?? {};
|
|
12049
|
+
const title = options.title ?? "Voice Media Pipeline Proof";
|
|
12050
|
+
const resolveOptions = async () => {
|
|
12051
|
+
const source = typeof options.source === "function" ? await options.source() : options.source ?? options;
|
|
12052
|
+
const {
|
|
12053
|
+
headers: _headers,
|
|
12054
|
+
htmlPath: _htmlPath,
|
|
12055
|
+
markdownPath: _markdownPath,
|
|
12056
|
+
name: _name,
|
|
12057
|
+
path: _path,
|
|
12058
|
+
render: _render,
|
|
12059
|
+
source: _source,
|
|
12060
|
+
title: _title,
|
|
12061
|
+
...reportOptions
|
|
12062
|
+
} = {
|
|
12063
|
+
...options,
|
|
12064
|
+
...source
|
|
12065
|
+
};
|
|
12066
|
+
return reportOptions;
|
|
12067
|
+
};
|
|
12068
|
+
const report = async () => buildVoiceMediaPipelineReport(await resolveOptions());
|
|
12069
|
+
const app = new Elysia12({ name: options.name ?? "voice-media-pipeline" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
12070
|
+
headers: {
|
|
12071
|
+
"content-type": "application/json; charset=utf-8",
|
|
12072
|
+
...headers
|
|
12073
|
+
}
|
|
12074
|
+
}));
|
|
12075
|
+
if (htmlPath !== false) {
|
|
12076
|
+
app.get(htmlPath, async () => {
|
|
12077
|
+
const current = await report();
|
|
12078
|
+
const body = options.render ? await options.render(current) : renderVoiceMediaPipelineHTML(current, title);
|
|
12079
|
+
return new Response(body, {
|
|
12080
|
+
headers: {
|
|
12081
|
+
"content-type": "text/html; charset=utf-8",
|
|
12082
|
+
...headers
|
|
12083
|
+
}
|
|
12084
|
+
});
|
|
12085
|
+
});
|
|
12086
|
+
}
|
|
12087
|
+
if (markdownPath !== false) {
|
|
12088
|
+
app.get(markdownPath, async () => new Response(renderVoiceMediaPipelineMarkdown(await report()), {
|
|
12089
|
+
headers: {
|
|
12090
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
12091
|
+
...headers
|
|
12092
|
+
}
|
|
12093
|
+
}));
|
|
12094
|
+
}
|
|
12095
|
+
return app;
|
|
12096
|
+
};
|
|
12097
|
+
// src/demoReadyRoutes.ts
|
|
12098
|
+
import { Elysia as Elysia13 } from "elysia";
|
|
12099
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11824
12100
|
var rollupStatus2 = (sections) => sections.some((section) => section.status === "fail") ? "fail" : sections.some((section) => section.status === "warn") ? "warn" : "pass";
|
|
11825
12101
|
var resolveLoader = async (loader, input) => typeof loader === "function" ? await loader(input) : loader;
|
|
11826
12102
|
var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
@@ -11904,17 +12180,17 @@ var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
|
11904
12180
|
};
|
|
11905
12181
|
};
|
|
11906
12182
|
var renderVoiceDemoReadyHTML = (report) => {
|
|
11907
|
-
const sections = report.sections.map((section) => `<article class="section ${
|
|
11908
|
-
<div><span>${
|
|
11909
|
-
<strong>${
|
|
11910
|
-
${section.href ? `<a href="${
|
|
12183
|
+
const sections = report.sections.map((section) => `<article class="section ${escapeHtml16(section.status)}">
|
|
12184
|
+
<div><span>${escapeHtml16(section.status.toUpperCase())}</span><h2>${escapeHtml16(section.label)}</h2>${section.description ? `<p>${escapeHtml16(section.description)}</p>` : ""}</div>
|
|
12185
|
+
<strong>${escapeHtml16(String(section.value ?? section.status))}</strong>
|
|
12186
|
+
${section.href ? `<a href="${escapeHtml16(section.href)}">Open</a>` : ""}
|
|
11911
12187
|
</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>${
|
|
12188
|
+
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
12189
|
};
|
|
11914
12190
|
var createVoiceDemoReadyRoutes = (options) => {
|
|
11915
12191
|
const path = options.path ?? "/api/demo-ready";
|
|
11916
12192
|
const htmlPath = options.htmlPath ?? "/demo-ready";
|
|
11917
|
-
const routes = new
|
|
12193
|
+
const routes = new Elysia13({
|
|
11918
12194
|
name: options.name ?? "absolutejs-voice-demo-ready"
|
|
11919
12195
|
});
|
|
11920
12196
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
@@ -11933,7 +12209,7 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
11933
12209
|
return routes;
|
|
11934
12210
|
};
|
|
11935
12211
|
// src/deliverySinkRoutes.ts
|
|
11936
|
-
import { Elysia as
|
|
12212
|
+
import { Elysia as Elysia14 } from "elysia";
|
|
11937
12213
|
|
|
11938
12214
|
// src/queue.ts
|
|
11939
12215
|
var releaseLeaseScript = `
|
|
@@ -12876,7 +13152,7 @@ var createVoiceOpsTaskProcessorWorkerLoop = (options) => {
|
|
|
12876
13152
|
};
|
|
12877
13153
|
|
|
12878
13154
|
// src/deliverySinkRoutes.ts
|
|
12879
|
-
var
|
|
13155
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12880
13156
|
var deliveryStatus = (summary) => {
|
|
12881
13157
|
if (!summary) {
|
|
12882
13158
|
return "warn";
|
|
@@ -12975,13 +13251,13 @@ var renderSurfaceCard = (surface) => {
|
|
|
12975
13251
|
return "";
|
|
12976
13252
|
}
|
|
12977
13253
|
const value = `${surface.summary.delivered}/${surface.summary.total}`;
|
|
12978
|
-
const body = `<span>${
|
|
12979
|
-
return `<article>${surface.href ? `<a href="${
|
|
13254
|
+
const body = `<span>${escapeHtml17(surface.label)}</span><strong>${escapeHtml17(value)}</strong><p class="muted">Delivered export records.</p>`;
|
|
13255
|
+
return `<article>${surface.href ? `<a href="${escapeHtml17(surface.href)}">${body}</a>` : body}</article>`;
|
|
12980
13256
|
};
|
|
12981
13257
|
var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
12982
13258
|
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>${
|
|
13259
|
+
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>';
|
|
13260
|
+
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
13261
|
auditDeliveries: { store: runtimeStorage.auditDeliveries },
|
|
12986
13262
|
traceDeliveries: { store: runtimeStorage.traceDeliveries },
|
|
12987
13263
|
sinks: createVoiceDeliverySinkPair({
|
|
@@ -12993,7 +13269,7 @@ var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
|
12993
13269
|
var createVoiceDeliverySinkRoutes = (options) => {
|
|
12994
13270
|
const path = options.path ?? "/api/voice-delivery-sinks";
|
|
12995
13271
|
const htmlPath = options.htmlPath === undefined ? "/delivery-sinks" : options.htmlPath;
|
|
12996
|
-
const routes = new
|
|
13272
|
+
const routes = new Elysia14({
|
|
12997
13273
|
name: options.name ?? "absolutejs-voice-delivery-sinks"
|
|
12998
13274
|
}).get(path, () => buildVoiceDeliverySinkReport(options));
|
|
12999
13275
|
if (htmlPath !== false) {
|
|
@@ -13011,7 +13287,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
|
|
|
13011
13287
|
return routes;
|
|
13012
13288
|
};
|
|
13013
13289
|
// src/opsActionAuditRoutes.ts
|
|
13014
|
-
import { Elysia as
|
|
13290
|
+
import { Elysia as Elysia15 } from "elysia";
|
|
13015
13291
|
var readRecordBody = (body) => {
|
|
13016
13292
|
if (!body || typeof body !== "object") {
|
|
13017
13293
|
throw new Error("Voice ops action audit requires a JSON body.");
|
|
@@ -13086,7 +13362,7 @@ var createVoiceOpsActionAuditRoutes = (options) => {
|
|
|
13086
13362
|
const path = options.path ?? "/api/voice/ops-actions/audit";
|
|
13087
13363
|
const historyPath = options.historyPath === undefined ? "/api/voice/ops-actions/history" : options.historyPath;
|
|
13088
13364
|
const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
|
|
13089
|
-
const routes = new
|
|
13365
|
+
const routes = new Elysia15({
|
|
13090
13366
|
name: options.name ?? "absolutejs-voice-ops-action-audit"
|
|
13091
13367
|
}).post(path, async ({ body, request, set }) => {
|
|
13092
13368
|
try {
|
|
@@ -13136,13 +13412,13 @@ var buildVoiceOpsActionHistoryReport = async (options) => {
|
|
|
13136
13412
|
total: entries.length
|
|
13137
13413
|
};
|
|
13138
13414
|
};
|
|
13139
|
-
var
|
|
13415
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13140
13416
|
var renderVoiceOpsActionHistoryHTML = (report) => {
|
|
13141
|
-
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${
|
|
13417
|
+
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
13418
|
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
13419
|
};
|
|
13144
13420
|
// src/platformCoverage.ts
|
|
13145
|
-
import { Elysia as
|
|
13421
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
13146
13422
|
var buildVoicePlatformCoverageSummary = (input) => {
|
|
13147
13423
|
const coverage = input.coverage ?? [];
|
|
13148
13424
|
const ok = input.ok ?? (coverage.length > 0 && coverage.every((surface) => surface.status === "pass"));
|
|
@@ -13203,7 +13479,7 @@ var assertVoicePlatformCoverage = (summary, input = {}) => {
|
|
|
13203
13479
|
var normalizeCoverageSummary = (value) => ("status" in value) && ("total" in value) && ("coverage" in value) ? value : buildVoicePlatformCoverageSummary(value);
|
|
13204
13480
|
var createVoicePlatformCoverageRoutes = (options) => {
|
|
13205
13481
|
const path = options.path ?? "/api/voice/platform-coverage";
|
|
13206
|
-
const routes = new
|
|
13482
|
+
const routes = new Elysia16({
|
|
13207
13483
|
name: options.name ?? "absolutejs-voice-platform-coverage"
|
|
13208
13484
|
});
|
|
13209
13485
|
routes.get(path, async () => {
|
|
@@ -13215,8 +13491,8 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
13215
13491
|
return routes;
|
|
13216
13492
|
};
|
|
13217
13493
|
// src/competitiveCoverage.ts
|
|
13218
|
-
import { Elysia as
|
|
13219
|
-
var
|
|
13494
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
13495
|
+
var escapeHtml19 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13220
13496
|
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
13221
13497
|
var resolveSurfaceStatus = (surface) => {
|
|
13222
13498
|
if (surface.status)
|
|
@@ -13384,24 +13660,24 @@ var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive
|
|
|
13384
13660
|
`);
|
|
13385
13661
|
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
13386
13662
|
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>${
|
|
13663
|
+
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("");
|
|
13664
|
+
return `<article class="surface ${escapeHtml19(surface.status)} ${escapeHtml19(surface.depth)}">
|
|
13665
|
+
<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>
|
|
13666
|
+
<p>${escapeHtml19(surface.why)}</p>
|
|
13391
13667
|
<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>${
|
|
13668
|
+
<div><dt>Competitors</dt><dd>${escapeHtml19((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
13669
|
+
<div><dt>Operations record</dt><dd>${escapeHtml19(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
13670
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml19(surface.readinessGate ?? "unknown")}</dd></div>
|
|
13671
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml19((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
13396
13672
|
</dl>
|
|
13397
|
-
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${
|
|
13398
|
-
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${
|
|
13673
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml19(surface.remainingGap)}</p>` : ""}
|
|
13674
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml19(surface.nextMove)}</p>` : ""}
|
|
13399
13675
|
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
13400
13676
|
</article>`;
|
|
13401
13677
|
}).join(`
|
|
13402
13678
|
`);
|
|
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>${
|
|
13679
|
+
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("");
|
|
13680
|
+
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
13681
|
};
|
|
13406
13682
|
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
13407
13683
|
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
@@ -13414,7 +13690,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
13414
13690
|
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
13415
13691
|
return normalizeCompetitiveCoverageReport(value);
|
|
13416
13692
|
};
|
|
13417
|
-
const app = new
|
|
13693
|
+
const app = new Elysia17({
|
|
13418
13694
|
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
13419
13695
|
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
13420
13696
|
headers: {
|
|
@@ -13445,7 +13721,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
13445
13721
|
return app;
|
|
13446
13722
|
};
|
|
13447
13723
|
// src/proofTrends.ts
|
|
13448
|
-
import { Elysia as
|
|
13724
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
13449
13725
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
13450
13726
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
13451
13727
|
var toTimeMs = (value) => {
|
|
@@ -13596,7 +13872,7 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
13596
13872
|
};
|
|
13597
13873
|
var createVoiceProofTrendRoutes = (options) => {
|
|
13598
13874
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
13599
|
-
const routes = new
|
|
13875
|
+
const routes = new Elysia18({
|
|
13600
13876
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
13601
13877
|
});
|
|
13602
13878
|
routes.get(path, async () => {
|
|
@@ -13629,11 +13905,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
13629
13905
|
return `${days}d ${hours % 24}h`;
|
|
13630
13906
|
};
|
|
13631
13907
|
// src/providerDecisionTraces.ts
|
|
13632
|
-
import { Elysia as
|
|
13908
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
13633
13909
|
|
|
13634
13910
|
// src/resilienceRoutes.ts
|
|
13635
|
-
import { Elysia as
|
|
13636
|
-
var
|
|
13911
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
13912
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13637
13913
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
13638
13914
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
13639
13915
|
var getBoolean2 = (value) => value === true;
|
|
@@ -13781,13 +14057,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
13781
14057
|
};
|
|
13782
14058
|
var renderProviderCards = (title, providers) => {
|
|
13783
14059
|
if (providers.length === 0) {
|
|
13784
|
-
return `<p class="muted">No ${
|
|
14060
|
+
return `<p class="muted">No ${escapeHtml20(title)} provider health yet.</p>`;
|
|
13785
14061
|
}
|
|
13786
14062
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
13787
|
-
<article class="card provider ${
|
|
14063
|
+
<article class="card provider ${escapeHtml20(provider.status)}">
|
|
13788
14064
|
<div class="card-header">
|
|
13789
|
-
<strong>${
|
|
13790
|
-
<span>${
|
|
14065
|
+
<strong>${escapeHtml20(provider.provider)}</strong>
|
|
14066
|
+
<span>${escapeHtml20(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
13791
14067
|
</div>
|
|
13792
14068
|
<dl>
|
|
13793
14069
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -13796,7 +14072,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
13796
14072
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
13797
14073
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
13798
14074
|
</dl>
|
|
13799
|
-
${provider.lastError ? `<p class="muted">${
|
|
14075
|
+
${provider.lastError ? `<p class="muted">${escapeHtml20(provider.lastError)}</p>` : ""}
|
|
13800
14076
|
</article>
|
|
13801
14077
|
`).join("")}</div>`;
|
|
13802
14078
|
};
|
|
@@ -13805,24 +14081,24 @@ var renderTimeline2 = (events) => {
|
|
|
13805
14081
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
13806
14082
|
}
|
|
13807
14083
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
13808
|
-
<article class="card event ${
|
|
14084
|
+
<article class="card event ${escapeHtml20(event.status ?? "unknown")}">
|
|
13809
14085
|
<div class="card-header">
|
|
13810
|
-
<strong>${
|
|
14086
|
+
<strong>${escapeHtml20(event.kind.toUpperCase())} ${escapeHtml20(event.operation ?? "generate")}</strong>
|
|
13811
14087
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
13812
14088
|
</div>
|
|
13813
14089
|
<p>
|
|
13814
|
-
<span class="pill">${
|
|
13815
|
-
<span class="pill">provider: ${
|
|
13816
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
14090
|
+
<span class="pill">${escapeHtml20(event.status ?? "unknown")}</span>
|
|
14091
|
+
<span class="pill">provider: ${escapeHtml20(event.provider ?? "unknown")}</span>
|
|
14092
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml20(event.fallbackProvider)}</span>` : ""}
|
|
13817
14093
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
13818
14094
|
</p>
|
|
13819
14095
|
<dl>
|
|
13820
14096
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
13821
14097
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
13822
14098
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
13823
|
-
<div><dt>Session</dt><dd>${
|
|
14099
|
+
<div><dt>Session</dt><dd>${escapeHtml20(event.sessionId)}</dd></div>
|
|
13824
14100
|
</dl>
|
|
13825
|
-
${event.error ? `<p class="muted">${
|
|
14101
|
+
${event.error ? `<p class="muted">${escapeHtml20(event.error)}</p>` : ""}
|
|
13826
14102
|
</article>
|
|
13827
14103
|
`).join("")}</div>`;
|
|
13828
14104
|
};
|
|
@@ -13832,9 +14108,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
13832
14108
|
const status = latest?.status ?? "idle";
|
|
13833
14109
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
13834
14110
|
return `<div>
|
|
13835
|
-
<dt>${
|
|
13836
|
-
<dd>${
|
|
13837
|
-
<small>${
|
|
14111
|
+
<dt>${escapeHtml20(kind.toUpperCase())}</dt>
|
|
14112
|
+
<dd>${escapeHtml20(provider)}${escapeHtml20(fallback)}</dd>
|
|
14113
|
+
<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
14114
|
</div>`;
|
|
13839
14115
|
};
|
|
13840
14116
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -13842,10 +14118,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
13842
14118
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
13843
14119
|
}
|
|
13844
14120
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
13845
|
-
<article class="card session ${
|
|
14121
|
+
<article class="card session ${escapeHtml20(session.status)}">
|
|
13846
14122
|
<div class="card-header">
|
|
13847
|
-
<strong>${
|
|
13848
|
-
<span>${
|
|
14123
|
+
<strong>${escapeHtml20(session.sessionId)}</strong>
|
|
14124
|
+
<span>${escapeHtml20(session.status)}</span>
|
|
13849
14125
|
</div>
|
|
13850
14126
|
<p>
|
|
13851
14127
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -13872,21 +14148,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
13872
14148
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
13873
14149
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
13874
14150
|
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">${
|
|
14151
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml20(pathPrefix)}">
|
|
14152
|
+
<p class="muted">${escapeHtml20(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
13877
14153
|
<div class="simulate-actions">
|
|
13878
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
13879
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
14154
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml20(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml20(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
14155
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml20(provider.provider)}">Mark ${escapeHtml20(provider.provider)} recovered</button>`).join("")}
|
|
13880
14156
|
</div>
|
|
13881
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
14157
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml20(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
13882
14158
|
<pre class="simulate-output" hidden></pre>
|
|
13883
14159
|
</div>`;
|
|
13884
14160
|
};
|
|
13885
14161
|
var renderVoiceResilienceHTML = (input) => {
|
|
13886
14162
|
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 =
|
|
14163
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml20(kind)}: ${String(count)}</span>`).join("");
|
|
14164
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join(" \xB7 ") : "";
|
|
14165
|
+
const snippet = escapeHtml20(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
13890
14166
|
kind: 'stt',
|
|
13891
14167
|
providers: ['deepgram', 'assemblyai'],
|
|
13892
14168
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -13924,7 +14200,7 @@ app.use(
|
|
|
13924
14200
|
<head>
|
|
13925
14201
|
<meta charset="utf-8" />
|
|
13926
14202
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
13927
|
-
<title>${
|
|
14203
|
+
<title>${escapeHtml20(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
13928
14204
|
<style>
|
|
13929
14205
|
:root { color-scheme: dark; }
|
|
13930
14206
|
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 +14352,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
14076
14352
|
};
|
|
14077
14353
|
var createVoiceResilienceRoutes = (options) => {
|
|
14078
14354
|
const path = options.path ?? "/resilience";
|
|
14079
|
-
const routes = new
|
|
14355
|
+
const routes = new Elysia19({
|
|
14080
14356
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
14081
14357
|
}).get(path, async () => {
|
|
14082
14358
|
const events = await options.store.list();
|
|
@@ -14117,7 +14393,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
14117
14393
|
};
|
|
14118
14394
|
|
|
14119
14395
|
// src/providerDecisionTraces.ts
|
|
14120
|
-
var
|
|
14396
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14121
14397
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
14122
14398
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
14123
14399
|
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 +14408,8 @@ var surfaceForKind = (kind) => {
|
|
|
14132
14408
|
return "live-call";
|
|
14133
14409
|
}
|
|
14134
14410
|
};
|
|
14135
|
-
var
|
|
14136
|
-
var reportStatus = (issues) => issues.reduce((status, issue) =>
|
|
14411
|
+
var statusRank3 = { fail: 2, pass: 0, warn: 1 };
|
|
14412
|
+
var reportStatus = (issues) => issues.reduce((status, issue) => statusRank3[issue.status] > statusRank3[status] ? issue.status : status, "pass");
|
|
14137
14413
|
var uniqueSorted = (values) => [
|
|
14138
14414
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
14139
14415
|
].sort();
|
|
@@ -14358,7 +14634,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
14358
14634
|
<head>
|
|
14359
14635
|
<meta charset="utf-8" />
|
|
14360
14636
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
14361
|
-
<title>${
|
|
14637
|
+
<title>${escapeHtml21(title)}</title>
|
|
14362
14638
|
<style>
|
|
14363
14639
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
14364
14640
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -14372,8 +14648,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
14372
14648
|
</head>
|
|
14373
14649
|
<body>
|
|
14374
14650
|
<main>
|
|
14375
|
-
<p class="status ${report.status}">${
|
|
14376
|
-
<h1>${
|
|
14651
|
+
<p class="status ${report.status}">${escapeHtml21(report.status)}</p>
|
|
14652
|
+
<h1>${escapeHtml21(title)}</h1>
|
|
14377
14653
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
14378
14654
|
<section class="grid">
|
|
14379
14655
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -14384,10 +14660,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
14384
14660
|
</section>
|
|
14385
14661
|
<section class="surfaces">
|
|
14386
14662
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
14387
|
-
<header><strong>${
|
|
14663
|
+
<header><strong>${escapeHtml21(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml21(surface.status)}</span></header>
|
|
14388
14664
|
<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>${
|
|
14665
|
+
<p class="muted">Providers: ${escapeHtml21(surface.providers.join(", ") || "none")}</p>
|
|
14666
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml21(reason)}</code>`).join(" ")}</p>
|
|
14391
14667
|
</article>`).join(`
|
|
14392
14668
|
`)}
|
|
14393
14669
|
</section>
|
|
@@ -14401,7 +14677,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
14401
14677
|
const headers = options.headers ?? {};
|
|
14402
14678
|
const title = options.title ?? "Provider Decision Traces";
|
|
14403
14679
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
14404
|
-
const app = new
|
|
14680
|
+
const app = new Elysia20({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
14405
14681
|
headers: {
|
|
14406
14682
|
"content-type": "application/json; charset=utf-8",
|
|
14407
14683
|
...headers
|
|
@@ -14429,7 +14705,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
14429
14705
|
return app;
|
|
14430
14706
|
};
|
|
14431
14707
|
// src/sloCalibration.ts
|
|
14432
|
-
import { Elysia as
|
|
14708
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14433
14709
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
14434
14710
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
14435
14711
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -14609,7 +14885,7 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
14609
14885
|
};
|
|
14610
14886
|
};
|
|
14611
14887
|
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
14612
|
-
var
|
|
14888
|
+
var escapeHtml22 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14613
14889
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
14614
14890
|
var readinessThresholdRows = (report) => [
|
|
14615
14891
|
{
|
|
@@ -14700,15 +14976,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
14700
14976
|
};
|
|
14701
14977
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
14702
14978
|
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>${
|
|
14979
|
+
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("");
|
|
14980
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
|
|
14981
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml22(source)}</code></li>`).join("");
|
|
14982
|
+
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
14983
|
};
|
|
14708
14984
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
14709
14985
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
14710
14986
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
14711
|
-
const routes = new
|
|
14987
|
+
const routes = new Elysia21({
|
|
14712
14988
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
14713
14989
|
});
|
|
14714
14990
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -14732,7 +15008,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
14732
15008
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
14733
15009
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
14734
15010
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
14735
|
-
const routes = new
|
|
15011
|
+
const routes = new Elysia21({
|
|
14736
15012
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
14737
15013
|
});
|
|
14738
15014
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -14766,7 +15042,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
14766
15042
|
return routes;
|
|
14767
15043
|
};
|
|
14768
15044
|
// src/liveOps.ts
|
|
14769
|
-
import { Elysia as
|
|
15045
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
14770
15046
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
14771
15047
|
"assign",
|
|
14772
15048
|
"create-task",
|
|
@@ -15076,7 +15352,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
15076
15352
|
const controller = createVoiceLiveOpsController(options);
|
|
15077
15353
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
15078
15354
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
15079
|
-
return new
|
|
15355
|
+
return new Elysia22({
|
|
15080
15356
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
15081
15357
|
}).post(path, async ({ request, set }) => {
|
|
15082
15358
|
try {
|
|
@@ -15098,15 +15374,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
15098
15374
|
});
|
|
15099
15375
|
};
|
|
15100
15376
|
// src/deliveryRuntime.ts
|
|
15101
|
-
import { Elysia as
|
|
15377
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15102
15378
|
import { mkdir } from "fs/promises";
|
|
15103
15379
|
import { dirname, join } from "path";
|
|
15104
|
-
var
|
|
15380
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15105
15381
|
var renderSummaryCard = (label, summary) => {
|
|
15106
15382
|
if (!summary) {
|
|
15107
|
-
return `<article><span>${
|
|
15383
|
+
return `<article><span>${escapeHtml23(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
15108
15384
|
}
|
|
15109
|
-
return `<article><span>${
|
|
15385
|
+
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
15386
|
};
|
|
15111
15387
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
15112
15388
|
audit: leases,
|
|
@@ -15317,9 +15593,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
15317
15593
|
});
|
|
15318
15594
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
15319
15595
|
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 =
|
|
15596
|
+
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>`;
|
|
15597
|
+
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>`;
|
|
15598
|
+
const snippet = escapeHtml23(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
15323
15599
|
createVoiceDeliveryRuntimePresetConfig({
|
|
15324
15600
|
audit: {
|
|
15325
15601
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -15345,14 +15621,14 @@ app.use(
|
|
|
15345
15621
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
15346
15622
|
})
|
|
15347
15623
|
);`);
|
|
15348
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15624
|
+
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
15625
|
};
|
|
15350
15626
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
15351
15627
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
15352
15628
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
15353
15629
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
15354
15630
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
15355
|
-
const routes = new
|
|
15631
|
+
const routes = new Elysia23({
|
|
15356
15632
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
15357
15633
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
15358
15634
|
if (tickPath !== false) {
|
|
@@ -15388,7 +15664,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
15388
15664
|
return routes;
|
|
15389
15665
|
};
|
|
15390
15666
|
// src/dataControl.ts
|
|
15391
|
-
import { Elysia as
|
|
15667
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
15392
15668
|
var voiceComplianceRedactionDefaults = {
|
|
15393
15669
|
keys: [
|
|
15394
15670
|
"apiKey",
|
|
@@ -15627,7 +15903,7 @@ var parseRetentionScopes = (value) => {
|
|
|
15627
15903
|
const allowed = new Set(allRetentionScopes);
|
|
15628
15904
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
15629
15905
|
};
|
|
15630
|
-
var
|
|
15906
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15631
15907
|
var buildStorageSurfaces = (options) => [
|
|
15632
15908
|
{
|
|
15633
15909
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -15864,12 +16140,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
15864
16140
|
zeroRetentionAvailable: true
|
|
15865
16141
|
};
|
|
15866
16142
|
};
|
|
15867
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
16143
|
+
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
16144
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
15869
16145
|
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>${
|
|
16146
|
+
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("");
|
|
16147
|
+
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("");
|
|
16148
|
+
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
16149
|
};
|
|
15874
16150
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
15875
16151
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -15927,7 +16203,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
15927
16203
|
var createVoiceDataControlRoutes = (options) => {
|
|
15928
16204
|
const path = options.path ?? "/data-control";
|
|
15929
16205
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
15930
|
-
const routes = new
|
|
16206
|
+
const routes = new Elysia24({
|
|
15931
16207
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
15932
16208
|
});
|
|
15933
16209
|
routes.get(path, async ({ query }) => {
|
|
@@ -16003,16 +16279,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
16003
16279
|
return routes;
|
|
16004
16280
|
};
|
|
16005
16281
|
// src/evalRoutes.ts
|
|
16006
|
-
import { Elysia as
|
|
16282
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
16007
16283
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
16008
16284
|
import { dirname as dirname2 } from "path";
|
|
16009
16285
|
|
|
16010
16286
|
// src/qualityRoutes.ts
|
|
16011
|
-
import { Elysia as
|
|
16287
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16012
16288
|
|
|
16013
16289
|
// src/handoffHealth.ts
|
|
16014
|
-
import { Elysia as
|
|
16015
|
-
var
|
|
16290
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16291
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16016
16292
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
16017
16293
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
16018
16294
|
var increment3 = (record, key) => {
|
|
@@ -16130,10 +16406,10 @@ var renderActionSummary = (summary) => {
|
|
|
16130
16406
|
return [
|
|
16131
16407
|
'<section class="voice-handoff-health-columns">',
|
|
16132
16408
|
"<article><h3>Actions</h3>",
|
|
16133
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
16409
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml25(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
16134
16410
|
"</article>",
|
|
16135
16411
|
"<article><h3>Adapters</h3>",
|
|
16136
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
16412
|
+
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
16413
|
"</article>",
|
|
16138
16414
|
"</section>"
|
|
16139
16415
|
].join("");
|
|
@@ -16147,22 +16423,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
16147
16423
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
16148
16424
|
'<div class="voice-handoff-health-events">',
|
|
16149
16425
|
...summary.events.map((event) => [
|
|
16150
|
-
`<article class="${
|
|
16426
|
+
`<article class="${escapeHtml25(event.status)}">`,
|
|
16151
16427
|
'<div class="voice-handoff-health-event-header">',
|
|
16152
|
-
`<strong>${
|
|
16153
|
-
`<span>${
|
|
16428
|
+
`<strong>${escapeHtml25(event.action ?? "handoff")}</strong>`,
|
|
16429
|
+
`<span>${escapeHtml25(event.status)}</span>`,
|
|
16154
16430
|
"</div>",
|
|
16155
|
-
`<p><small>${
|
|
16156
|
-
event.target ? `<p>Target: ${
|
|
16157
|
-
event.reason ? `<p>Reason: ${
|
|
16431
|
+
`<p><small>${escapeHtml25(event.sessionId)}</small></p>`,
|
|
16432
|
+
event.target ? `<p>Target: ${escapeHtml25(event.target)}</p>` : "",
|
|
16433
|
+
event.reason ? `<p>Reason: ${escapeHtml25(event.reason)}</p>` : "",
|
|
16158
16434
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
16159
16435
|
"<li>",
|
|
16160
|
-
`${
|
|
16161
|
-
delivery.deliveredTo ? ` to ${
|
|
16162
|
-
delivery.error ? ` (${
|
|
16436
|
+
`${escapeHtml25(delivery.adapterId)}: ${escapeHtml25(delivery.status)}`,
|
|
16437
|
+
delivery.deliveredTo ? ` to ${escapeHtml25(delivery.deliveredTo)}` : "",
|
|
16438
|
+
delivery.error ? ` (${escapeHtml25(delivery.error)})` : "",
|
|
16163
16439
|
"</li>"
|
|
16164
16440
|
].join("")).join("")}</ul>` : "",
|
|
16165
|
-
event.replayHref ? `<p><a href="${
|
|
16441
|
+
event.replayHref ? `<p><a href="${escapeHtml25(event.replayHref)}">Open replay</a></p>` : "",
|
|
16166
16442
|
"</article>"
|
|
16167
16443
|
].join("")),
|
|
16168
16444
|
"</div>"
|
|
@@ -16194,7 +16470,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
16194
16470
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
16195
16471
|
const path = options.path ?? "/api/voice-handoffs";
|
|
16196
16472
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16197
|
-
const routes = new
|
|
16473
|
+
const routes = new Elysia25({
|
|
16198
16474
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
16199
16475
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
16200
16476
|
if (htmlPath) {
|
|
@@ -16315,17 +16591,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
16315
16591
|
thresholds
|
|
16316
16592
|
};
|
|
16317
16593
|
};
|
|
16318
|
-
var
|
|
16594
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16319
16595
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
16320
16596
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
16321
16597
|
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="${
|
|
16598
|
+
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("");
|
|
16599
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml26(link.href)}">${escapeHtml26(link.label)}</a>`).join("")}</nav>` : "";
|
|
16324
16600
|
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
16601
|
};
|
|
16326
16602
|
var createVoiceQualityRoutes = (options) => {
|
|
16327
16603
|
const path = options.path ?? "/quality";
|
|
16328
|
-
const routes = new
|
|
16604
|
+
const routes = new Elysia26({
|
|
16329
16605
|
name: options.name ?? "absolutejs-voice-quality"
|
|
16330
16606
|
});
|
|
16331
16607
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -16354,7 +16630,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
16354
16630
|
};
|
|
16355
16631
|
|
|
16356
16632
|
// src/evalRoutes.ts
|
|
16357
|
-
var
|
|
16633
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16358
16634
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
16359
16635
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
16360
16636
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -16676,7 +16952,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
16676
16952
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
16677
16953
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
16678
16954
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
16679
|
-
const snippet =
|
|
16955
|
+
const snippet = escapeHtml27(`app.use(
|
|
16680
16956
|
createVoiceEvalRoutes({
|
|
16681
16957
|
path: '/evals',
|
|
16682
16958
|
store: traceStore,
|
|
@@ -16697,48 +16973,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
16697
16973
|
};
|
|
16698
16974
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
16699
16975
|
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>${
|
|
16976
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16977
|
+
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
16978
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
16703
16979
|
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>${
|
|
16980
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml27(session.operationsRecordHref)}">${escapeHtml27(session.sessionId)}</a>` : escapeHtml27(session.sessionId);
|
|
16981
|
+
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
16982
|
}).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>${
|
|
16983
|
+
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
16984
|
};
|
|
16709
16985
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
16710
16986
|
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>${
|
|
16987
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16988
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml27(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
16989
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml27(id)}</li>`).join("") : "<li>none</li>";
|
|
16990
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml27(id)}</li>`).join("") : "<li>none</li>";
|
|
16991
|
+
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
16992
|
};
|
|
16717
16993
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
16718
16994
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
16719
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16995
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16720
16996
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
16721
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
16997
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml27(issue)}</li>`).join("")}</ul>` : "";
|
|
16722
16998
|
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>${
|
|
16999
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml27(session.operationsRecordHref)}">${escapeHtml27(session.sessionId)}</a>` : escapeHtml27(session.sessionId);
|
|
17000
|
+
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
17001
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
16726
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
17002
|
+
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
17003
|
}).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>${
|
|
17004
|
+
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
17005
|
};
|
|
16730
17006
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
16731
17007
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
16732
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
17008
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml27(link.href)}">${escapeHtml27(link.label)}</a>`).join("")}</nav>` : "";
|
|
16733
17009
|
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>${
|
|
17010
|
+
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("");
|
|
17011
|
+
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
17012
|
}).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>${
|
|
17013
|
+
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
17014
|
};
|
|
16739
17015
|
var createVoiceEvalRoutes = (options) => {
|
|
16740
17016
|
const path = options.path ?? "/evals";
|
|
16741
|
-
const routes = new
|
|
17017
|
+
const routes = new Elysia27({
|
|
16742
17018
|
name: options.name ?? "absolutejs-voice-evals"
|
|
16743
17019
|
});
|
|
16744
17020
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -16875,11 +17151,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
16875
17151
|
return routes;
|
|
16876
17152
|
};
|
|
16877
17153
|
// src/simulationSuite.ts
|
|
16878
|
-
import { Elysia as
|
|
17154
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
16879
17155
|
|
|
16880
17156
|
// src/outcomeContract.ts
|
|
16881
|
-
import { Elysia as
|
|
16882
|
-
var
|
|
17157
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17158
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16883
17159
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
16884
17160
|
if (value === false) {
|
|
16885
17161
|
return;
|
|
@@ -17090,13 +17366,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
17090
17366
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
17091
17367
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
17092
17368
|
const contracts = report.contracts.map((contract) => {
|
|
17093
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
17369
|
+
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
17370
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
17095
17371
|
<div class="contract-header">
|
|
17096
17372
|
<div>
|
|
17097
|
-
<p class="eyebrow">${
|
|
17098
|
-
<h2>${
|
|
17099
|
-
${contract.description ? `<p>${
|
|
17373
|
+
<p class="eyebrow">${escapeHtml28(contract.contractId)}</p>
|
|
17374
|
+
<h2>${escapeHtml28(contract.label ?? contract.contractId)}</h2>
|
|
17375
|
+
${contract.description ? `<p>${escapeHtml28(contract.description)}</p>` : ""}
|
|
17100
17376
|
${sessionLinks}
|
|
17101
17377
|
</div>
|
|
17102
17378
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -17108,10 +17384,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
17108
17384
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
17109
17385
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
17110
17386
|
</div>
|
|
17111
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
17387
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml28(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
17112
17388
|
</section>`;
|
|
17113
17389
|
}).join("");
|
|
17114
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17390
|
+
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
17391
|
};
|
|
17116
17392
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
17117
17393
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -17127,7 +17403,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
17127
17403
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
17128
17404
|
const path = options.path ?? "/api/outcome-contracts";
|
|
17129
17405
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17130
|
-
const routes = new
|
|
17406
|
+
const routes = new Elysia28({
|
|
17131
17407
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
17132
17408
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
17133
17409
|
if (htmlPath) {
|
|
@@ -17137,7 +17413,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
17137
17413
|
};
|
|
17138
17414
|
|
|
17139
17415
|
// src/toolContract.ts
|
|
17140
|
-
import { Elysia as
|
|
17416
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17141
17417
|
|
|
17142
17418
|
// src/toolRuntime.ts
|
|
17143
17419
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -17346,7 +17622,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
17346
17622
|
});
|
|
17347
17623
|
var defaultApi = {};
|
|
17348
17624
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
17349
|
-
var
|
|
17625
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17350
17626
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
17351
17627
|
if (value === false) {
|
|
17352
17628
|
return;
|
|
@@ -17595,7 +17871,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
17595
17871
|
};
|
|
17596
17872
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
17597
17873
|
const title = options.title ?? "Voice Tool Contracts";
|
|
17598
|
-
const snippet =
|
|
17874
|
+
const snippet = escapeHtml29(`app.use(
|
|
17599
17875
|
createVoiceToolContractRoutes({
|
|
17600
17876
|
htmlPath: '/tool-contracts',
|
|
17601
17877
|
path: '/api/tool-contracts',
|
|
@@ -17621,20 +17897,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
17621
17897
|
);`);
|
|
17622
17898
|
const contracts = report.contracts.map((contract) => {
|
|
17623
17899
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
17624
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
17900
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml29(testCase.operationsRecordHref)}">${escapeHtml29(testCase.label ?? testCase.caseId)}</a>` : escapeHtml29(testCase.label ?? testCase.caseId)}</td>
|
|
17625
17901
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
17626
|
-
<td>${
|
|
17627
|
-
<td>${
|
|
17902
|
+
<td>${escapeHtml29(testCase.status)}</td>
|
|
17903
|
+
<td>${escapeHtml29(testCase.sessionId)}</td>
|
|
17628
17904
|
<td>${String(testCase.attempts)}</td>
|
|
17629
17905
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
17630
17906
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
17631
|
-
<td>${
|
|
17907
|
+
<td>${escapeHtml29(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
17632
17908
|
</tr>`).join("");
|
|
17633
17909
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
17634
17910
|
<div class="contract-header">
|
|
17635
17911
|
<div>
|
|
17636
|
-
<p class="eyebrow">${
|
|
17637
|
-
<h2>${
|
|
17912
|
+
<p class="eyebrow">${escapeHtml29(contract.toolName)}</p>
|
|
17913
|
+
<h2>${escapeHtml29(contract.label ?? contract.contractId)}</h2>
|
|
17638
17914
|
</div>
|
|
17639
17915
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
17640
17916
|
</div>
|
|
@@ -17644,7 +17920,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
17644
17920
|
</table>
|
|
17645
17921
|
</section>`;
|
|
17646
17922
|
}).join("");
|
|
17647
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17923
|
+
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
17924
|
};
|
|
17649
17925
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
17650
17926
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -17661,7 +17937,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
17661
17937
|
var createVoiceToolContractRoutes = (options) => {
|
|
17662
17938
|
const path = options.path ?? "/api/tool-contracts";
|
|
17663
17939
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17664
|
-
const routes = new
|
|
17940
|
+
const routes = new Elysia29({
|
|
17665
17941
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
17666
17942
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
17667
17943
|
if (htmlPath) {
|
|
@@ -17671,7 +17947,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
17671
17947
|
};
|
|
17672
17948
|
|
|
17673
17949
|
// src/simulationSuite.ts
|
|
17674
|
-
var
|
|
17950
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17675
17951
|
var summarizeSection = (report) => ({
|
|
17676
17952
|
failed: report.failed,
|
|
17677
17953
|
passed: report.passed,
|
|
@@ -17867,15 +18143,15 @@ var renderSection = (label, summary) => {
|
|
|
17867
18143
|
if (!summary) {
|
|
17868
18144
|
return "";
|
|
17869
18145
|
}
|
|
17870
|
-
return `<article class="${
|
|
18146
|
+
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
18147
|
};
|
|
17872
18148
|
var renderAction = (action) => {
|
|
17873
|
-
const content = `<strong>${
|
|
17874
|
-
return action.href ? `<a class="action" href="${
|
|
18149
|
+
const content = `<strong>${escapeHtml30(action.label)}</strong><p>${escapeHtml30(action.description)}</p><span>${escapeHtml30(action.section)} / ${escapeHtml30(action.severity)}</span>`;
|
|
18150
|
+
return action.href ? `<a class="action" href="${escapeHtml30(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
17875
18151
|
};
|
|
17876
18152
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
17877
18153
|
const title = options.title ?? "Voice Simulation Suite";
|
|
17878
|
-
const snippet =
|
|
18154
|
+
const snippet = escapeHtml30(`app.use(
|
|
17879
18155
|
createVoiceSimulationSuiteRoutes({
|
|
17880
18156
|
htmlPath: '/voice/simulations',
|
|
17881
18157
|
path: '/api/voice/simulations',
|
|
@@ -17908,12 +18184,12 @@ app.use(
|
|
|
17908
18184
|
store: traceStore
|
|
17909
18185
|
})
|
|
17910
18186
|
);`);
|
|
17911
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18187
|
+
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
18188
|
};
|
|
17913
18189
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
17914
18190
|
const path = options.path ?? "/api/voice/simulations";
|
|
17915
18191
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
17916
|
-
const app = new
|
|
18192
|
+
const app = new Elysia30({
|
|
17917
18193
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
17918
18194
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
17919
18195
|
if (htmlPath) {
|
|
@@ -18225,9 +18501,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
18225
18501
|
};
|
|
18226
18502
|
};
|
|
18227
18503
|
// src/sessionReplay.ts
|
|
18228
|
-
import { Elysia as
|
|
18504
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18229
18505
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
18230
|
-
var
|
|
18506
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18231
18507
|
var increment4 = (record, key) => {
|
|
18232
18508
|
record[key] = (record[key] ?? 0) + 1;
|
|
18233
18509
|
};
|
|
@@ -18421,10 +18697,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
18421
18697
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
18422
18698
|
'<div class="voice-sessions-list">',
|
|
18423
18699
|
...sessions.map((session) => [
|
|
18424
|
-
`<article class="voice-session-card ${
|
|
18700
|
+
`<article class="voice-session-card ${escapeHtml31(session.status)}">`,
|
|
18425
18701
|
'<div class="voice-session-card-header">',
|
|
18426
|
-
`<strong>${
|
|
18427
|
-
`<span>${
|
|
18702
|
+
`<strong>${escapeHtml31(session.sessionId)}</strong>`,
|
|
18703
|
+
`<span>${escapeHtml31(session.status)}</span>`,
|
|
18428
18704
|
"</div>",
|
|
18429
18705
|
"<dl>",
|
|
18430
18706
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -18432,9 +18708,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
18432
18708
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
18433
18709
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
18434
18710
|
"</dl>",
|
|
18435
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
18436
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
18437
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
18711
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml31(session.latestOutcome)}</p>` : "",
|
|
18712
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml31).join(", ")}</p>` : "",
|
|
18713
|
+
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
18714
|
"</article>"
|
|
18439
18715
|
].join("")),
|
|
18440
18716
|
"</div>"
|
|
@@ -18465,7 +18741,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
18465
18741
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
18466
18742
|
const path = options.path ?? "/api/voice-sessions";
|
|
18467
18743
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18468
|
-
const routes = new
|
|
18744
|
+
const routes = new Elysia31({
|
|
18469
18745
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
18470
18746
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
18471
18747
|
if (htmlPath) {
|
|
@@ -18493,7 +18769,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
18493
18769
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
18494
18770
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
18495
18771
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18496
|
-
const routes = new
|
|
18772
|
+
const routes = new Elysia31({
|
|
18497
18773
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
18498
18774
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
18499
18775
|
if (htmlPath) {
|
|
@@ -18807,10 +19083,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
18807
19083
|
return report;
|
|
18808
19084
|
};
|
|
18809
19085
|
// src/turnLatency.ts
|
|
18810
|
-
import { Elysia as
|
|
19086
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18811
19087
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
18812
19088
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
18813
|
-
var
|
|
19089
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18814
19090
|
var firstNumber = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
18815
19091
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
18816
19092
|
var createTraceStageIndex = (events) => {
|
|
@@ -18942,11 +19218,11 @@ await traceStore.append({
|
|
|
18942
19218
|
turnId,
|
|
18943
19219
|
type: 'turn_latency.stage'
|
|
18944
19220
|
});`;
|
|
18945
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
18946
|
-
<header><div><p class="eyebrow">${
|
|
18947
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
19221
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml32(turn.status)}">
|
|
19222
|
+
<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>
|
|
19223
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml32(stage.label)}</dt><dd>${escapeHtml32(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
18948
19224
|
</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>${
|
|
19225
|
+
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
19226
|
};
|
|
18951
19227
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
18952
19228
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -18963,7 +19239,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
18963
19239
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
18964
19240
|
const path = options.path ?? "/api/turn-latency";
|
|
18965
19241
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18966
|
-
const routes = new
|
|
19242
|
+
const routes = new Elysia32({
|
|
18967
19243
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
18968
19244
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
18969
19245
|
if (htmlPath) {
|
|
@@ -18972,8 +19248,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
18972
19248
|
return routes;
|
|
18973
19249
|
};
|
|
18974
19250
|
// src/liveLatency.ts
|
|
18975
|
-
import { Elysia as
|
|
18976
|
-
var
|
|
19251
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
19252
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18977
19253
|
var percentile3 = (values, percentileValue) => {
|
|
18978
19254
|
if (values.length === 0) {
|
|
18979
19255
|
return;
|
|
@@ -19040,13 +19316,13 @@ await traceStore.append({
|
|
|
19040
19316
|
sessionId,
|
|
19041
19317
|
type: 'client.live_latency'
|
|
19042
19318
|
});`;
|
|
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>${
|
|
19319
|
+
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("");
|
|
19320
|
+
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
19321
|
};
|
|
19046
19322
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
19047
19323
|
const path = options.path ?? "/api/live-latency";
|
|
19048
19324
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
19049
|
-
const routes = new
|
|
19325
|
+
const routes = new Elysia33({
|
|
19050
19326
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
19051
19327
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
19052
19328
|
if (htmlPath) {
|
|
@@ -19365,9 +19641,9 @@ None.
|
|
|
19365
19641
|
`}`;
|
|
19366
19642
|
};
|
|
19367
19643
|
// src/turnQuality.ts
|
|
19368
|
-
import { Elysia as
|
|
19644
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19369
19645
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
19370
|
-
var
|
|
19646
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19371
19647
|
var getTurnLatencyMs = (turn) => {
|
|
19372
19648
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
19373
19649
|
if (firstTranscriptAt === undefined) {
|
|
@@ -19438,24 +19714,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
19438
19714
|
};
|
|
19439
19715
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
19440
19716
|
const title = options.title ?? "Voice Turn Quality";
|
|
19441
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
19717
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml34(turn.status)}">
|
|
19442
19718
|
<div class="turn-header">
|
|
19443
19719
|
<div>
|
|
19444
|
-
<p class="eyebrow">${
|
|
19445
|
-
<h2>${
|
|
19720
|
+
<p class="eyebrow">${escapeHtml34(turn.sessionId)} \xB7 ${escapeHtml34(turn.turnId)}</p>
|
|
19721
|
+
<h2>${escapeHtml34(turn.text || "Empty turn")}</h2>
|
|
19446
19722
|
</div>
|
|
19447
|
-
<strong>${
|
|
19723
|
+
<strong>${escapeHtml34(turn.status)}</strong>
|
|
19448
19724
|
</div>
|
|
19449
19725
|
<dl>
|
|
19450
|
-
<div><dt>Source</dt><dd>${
|
|
19726
|
+
<div><dt>Source</dt><dd>${escapeHtml34(turn.source ?? "unknown")}</dd></div>
|
|
19451
19727
|
<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 ${
|
|
19728
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml34(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
19729
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml34(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
19454
19730
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
19455
19731
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
19456
19732
|
</dl>
|
|
19457
19733
|
</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>${
|
|
19734
|
+
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
19735
|
};
|
|
19460
19736
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
19461
19737
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -19472,7 +19748,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
19472
19748
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
19473
19749
|
const path = options.path ?? "/api/turn-quality";
|
|
19474
19750
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19475
|
-
const routes = new
|
|
19751
|
+
const routes = new Elysia34({
|
|
19476
19752
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
19477
19753
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
19478
19754
|
if (htmlPath) {
|
|
@@ -19481,7 +19757,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
19481
19757
|
return routes;
|
|
19482
19758
|
};
|
|
19483
19759
|
// src/telephonyOutcome.ts
|
|
19484
|
-
import { Elysia as
|
|
19760
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
19485
19761
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
19486
19762
|
"answered",
|
|
19487
19763
|
"completed",
|
|
@@ -20242,7 +20518,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
20242
20518
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
20243
20519
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
20244
20520
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
20245
|
-
return new
|
|
20521
|
+
return new Elysia35({
|
|
20246
20522
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
20247
20523
|
}).post(path, async ({ query, request }) => {
|
|
20248
20524
|
try {
|
|
@@ -20263,12 +20539,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
20263
20539
|
});
|
|
20264
20540
|
};
|
|
20265
20541
|
// src/phoneAgent.ts
|
|
20266
|
-
import { Elysia as
|
|
20542
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
20267
20543
|
|
|
20268
20544
|
// src/telephony/plivo.ts
|
|
20269
20545
|
import { Buffer as Buffer5 } from "buffer";
|
|
20270
20546
|
import { Database } from "bun:sqlite";
|
|
20271
|
-
import { Elysia as
|
|
20547
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
20272
20548
|
|
|
20273
20549
|
// src/telephony/contract.ts
|
|
20274
20550
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -20352,7 +20628,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
20352
20628
|
|
|
20353
20629
|
// src/telephony/twilio.ts
|
|
20354
20630
|
import { Buffer as Buffer4 } from "buffer";
|
|
20355
|
-
import { Elysia as
|
|
20631
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
20356
20632
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
20357
20633
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
20358
20634
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -20382,7 +20658,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
20382
20658
|
return parameters;
|
|
20383
20659
|
};
|
|
20384
20660
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20385
|
-
var
|
|
20661
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20386
20662
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
20387
20663
|
if (!webhook?.verificationUrl) {
|
|
20388
20664
|
return;
|
|
@@ -20425,23 +20701,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
20425
20701
|
};
|
|
20426
20702
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20427
20703
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
20428
|
-
<h1>${
|
|
20704
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
20429
20705
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
20430
20706
|
<section>
|
|
20431
20707
|
<h2>URLs</h2>
|
|
20432
20708
|
<ul>
|
|
20433
|
-
<li><strong>TwiML:</strong> <code>${
|
|
20434
|
-
<li><strong>Media stream:</strong> <code>${
|
|
20435
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
20709
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml35(status.urls.twiml)}</code></li>
|
|
20710
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml35(status.urls.stream)}</code></li>
|
|
20711
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml35(status.urls.webhook)}</code></li>
|
|
20436
20712
|
</ul>
|
|
20437
20713
|
</section>
|
|
20438
20714
|
<section>
|
|
20439
20715
|
<h2>Signing</h2>
|
|
20440
20716
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
20441
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
20717
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml35(status.signing.verificationUrl)}</code></p>` : ""}
|
|
20442
20718
|
</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>${
|
|
20719
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml35(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
20720
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml35(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
20445
20721
|
</main>`;
|
|
20446
20722
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
20447
20723
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -20452,20 +20728,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
20452
20728
|
});
|
|
20453
20729
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20454
20730
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
20455
|
-
<h1>${
|
|
20731
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
20456
20732
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
20457
20733
|
<section>
|
|
20458
20734
|
<h2>Checks</h2>
|
|
20459
20735
|
<ul>
|
|
20460
|
-
${report.checks.map((check) => `<li><strong>${
|
|
20736
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml35(check.name)}</strong>: ${escapeHtml35(check.status)}${check.message ? ` - ${escapeHtml35(check.message)}` : ""}</li>`).join("")}
|
|
20461
20737
|
</ul>
|
|
20462
20738
|
</section>
|
|
20463
20739
|
<section>
|
|
20464
20740
|
<h2>Observed URLs</h2>
|
|
20465
20741
|
<ul>
|
|
20466
|
-
<li><strong>TwiML:</strong> <code>${
|
|
20467
|
-
<li><strong>Stream:</strong> <code>${
|
|
20468
|
-
<li><strong>Webhook:</strong> <code>${
|
|
20742
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml35(report.setup.urls.twiml)}</code></li>
|
|
20743
|
+
<li><strong>Stream:</strong> <code>${escapeHtml35(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
20744
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml35(report.setup.urls.webhook)}</code></li>
|
|
20469
20745
|
</ul>
|
|
20470
20746
|
</section>
|
|
20471
20747
|
</main>`;
|
|
@@ -20925,7 +21201,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
20925
21201
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
20926
21202
|
const bridges = new WeakMap;
|
|
20927
21203
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
20928
|
-
const app = new
|
|
21204
|
+
const app = new Elysia36({
|
|
20929
21205
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
20930
21206
|
}).get(twimlPath, async ({ query, request }) => {
|
|
20931
21207
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -21062,7 +21338,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
21062
21338
|
|
|
21063
21339
|
// src/telephony/plivo.ts
|
|
21064
21340
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21065
|
-
var
|
|
21341
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21066
21342
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
21067
21343
|
var resolveRequestOrigin2 = (request) => {
|
|
21068
21344
|
const url = new URL(request.url);
|
|
@@ -21492,21 +21768,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
21492
21768
|
};
|
|
21493
21769
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21494
21770
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
21495
|
-
<h1>${
|
|
21771
|
+
<h1>${escapeHtml36(title)}</h1>
|
|
21496
21772
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
21497
21773
|
<ul>
|
|
21498
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
21499
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
21500
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
21774
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml36(status.urls.answer)}</code></li>
|
|
21775
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml36(status.urls.stream)}</code></li>
|
|
21776
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml36(status.urls.webhook)}</code></li>
|
|
21501
21777
|
</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>${
|
|
21778
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml36(name)}</code></li>`).join("")}</ul>` : ""}
|
|
21779
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml36(warning)}</li>`).join("")}</ul>` : ""}
|
|
21504
21780
|
</main>`;
|
|
21505
21781
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21506
21782
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
21507
|
-
<h1>${
|
|
21783
|
+
<h1>${escapeHtml36(title)}</h1>
|
|
21508
21784
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
21509
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
21785
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml36(check.name)}</strong>: ${escapeHtml36(check.status)}${check.message ? ` - ${escapeHtml36(check.message)}` : ""}</li>`).join("")}</ul>
|
|
21510
21786
|
</main>`;
|
|
21511
21787
|
var runPlivoSmokeTest = async (input) => {
|
|
21512
21788
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -21596,7 +21872,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
21596
21872
|
nonceStore: options.webhook.nonceStore,
|
|
21597
21873
|
verificationUrl: options.webhook.verificationUrl
|
|
21598
21874
|
}) : undefined);
|
|
21599
|
-
const app = new
|
|
21875
|
+
const app = new Elysia37({
|
|
21600
21876
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
21601
21877
|
}).get(answerPath, async ({ query, request }) => {
|
|
21602
21878
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -21708,9 +21984,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
21708
21984
|
// src/telephony/telnyx.ts
|
|
21709
21985
|
import { Buffer as Buffer6 } from "buffer";
|
|
21710
21986
|
import { Database as Database2 } from "bun:sqlite";
|
|
21711
|
-
import { Elysia as
|
|
21987
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21712
21988
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21713
|
-
var
|
|
21989
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21714
21990
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
21715
21991
|
var resolveRequestOrigin3 = (request) => {
|
|
21716
21992
|
const url = new URL(request.url);
|
|
@@ -22103,21 +22379,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
22103
22379
|
};
|
|
22104
22380
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22105
22381
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
22106
|
-
<h1>${
|
|
22382
|
+
<h1>${escapeHtml37(title)}</h1>
|
|
22107
22383
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22108
22384
|
<ul>
|
|
22109
|
-
<li><strong>TeXML:</strong> <code>${
|
|
22110
|
-
<li><strong>Media stream:</strong> <code>${
|
|
22111
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
22385
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml37(status.urls.texml)}</code></li>
|
|
22386
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml37(status.urls.stream)}</code></li>
|
|
22387
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml37(status.urls.webhook)}</code></li>
|
|
22112
22388
|
</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>${
|
|
22389
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml37(name)}</code></li>`).join("")}</ul>` : ""}
|
|
22390
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml37(warning)}</li>`).join("")}</ul>` : ""}
|
|
22115
22391
|
</main>`;
|
|
22116
22392
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22117
22393
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
22118
|
-
<h1>${
|
|
22394
|
+
<h1>${escapeHtml37(title)}</h1>
|
|
22119
22395
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22120
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
22396
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml37(check.name)}</strong>: ${escapeHtml37(check.status)}${check.message ? ` - ${escapeHtml37(check.message)}` : ""}</li>`).join("")}</ul>
|
|
22121
22397
|
</main>`;
|
|
22122
22398
|
var runTelnyxSmokeTest = async (input) => {
|
|
22123
22399
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -22210,7 +22486,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
22210
22486
|
publicKey: options.webhook.publicKey,
|
|
22211
22487
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
22212
22488
|
}) : undefined);
|
|
22213
|
-
const app = new
|
|
22489
|
+
const app = new Elysia38({
|
|
22214
22490
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
22215
22491
|
}).get(texmlPath, async ({ query, request }) => {
|
|
22216
22492
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -22320,8 +22596,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
22320
22596
|
};
|
|
22321
22597
|
|
|
22322
22598
|
// src/telephony/matrix.ts
|
|
22323
|
-
import { Elysia as
|
|
22324
|
-
var
|
|
22599
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
22600
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22325
22601
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
22326
22602
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
22327
22603
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -22382,13 +22658,13 @@ var badgeStyles = {
|
|
|
22382
22658
|
};
|
|
22383
22659
|
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
22660
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
22385
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
22661
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml38(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
22386
22662
|
<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
22663
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
22388
22664
|
${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
22665
|
<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]}">${
|
|
22666
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml38(entry.name)}</h2>
|
|
22667
|
+
<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
22668
|
</div>
|
|
22393
22669
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
22394
22670
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -22396,15 +22672,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
22396
22672
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
22397
22673
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
22398
22674
|
</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>${
|
|
22675
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml38(entry.setup.urls.stream || "missing")}</code></p>
|
|
22676
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml38(entry.setup.urls.webhook || "missing")}</code></p>
|
|
22677
|
+
${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
22678
|
</article>`).join("")}
|
|
22403
22679
|
</section>
|
|
22404
22680
|
</main>`;
|
|
22405
22681
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
22406
22682
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
22407
|
-
return new
|
|
22683
|
+
return new Elysia39({
|
|
22408
22684
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
22409
22685
|
}).get(path, async ({ query, request }) => {
|
|
22410
22686
|
const providers = await options.load({ query, request });
|
|
@@ -22426,7 +22702,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
22426
22702
|
};
|
|
22427
22703
|
|
|
22428
22704
|
// src/phoneAgentProductionSmoke.ts
|
|
22429
|
-
import { Elysia as
|
|
22705
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
22430
22706
|
var defaultRequirements = [
|
|
22431
22707
|
"media-started",
|
|
22432
22708
|
"transcript",
|
|
@@ -22434,7 +22710,7 @@ var defaultRequirements = [
|
|
|
22434
22710
|
"lifecycle-outcome",
|
|
22435
22711
|
"no-session-error"
|
|
22436
22712
|
];
|
|
22437
|
-
var
|
|
22713
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
22438
22714
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
22439
22715
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
22440
22716
|
const value = event.payload[key];
|
|
@@ -22543,10 +22819,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
22543
22819
|
});
|
|
22544
22820
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
22545
22821
|
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>${
|
|
22822
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml39(issue.requirement)}</strong>: ${escapeHtml39(issue.message)}</li>`).join("");
|
|
22823
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml39(outcome)}</span>`).join("");
|
|
22824
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml39(requirement)}</span>`).join("");
|
|
22825
|
+
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
22826
|
};
|
|
22551
22827
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
22552
22828
|
query,
|
|
@@ -22569,7 +22845,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
22569
22845
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
22570
22846
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
22571
22847
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
22572
|
-
const routes = new
|
|
22848
|
+
const routes = new Elysia40({
|
|
22573
22849
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
22574
22850
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
22575
22851
|
if (htmlPath) {
|
|
@@ -22612,7 +22888,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
22612
22888
|
"completed",
|
|
22613
22889
|
"failed"
|
|
22614
22890
|
];
|
|
22615
|
-
var
|
|
22891
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22616
22892
|
var loadRouteJson = async (input) => {
|
|
22617
22893
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
22618
22894
|
headers: {
|
|
@@ -22850,10 +23126,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
22850
23126
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
22851
23127
|
const urls = entry?.setup.urls;
|
|
22852
23128
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
22853
|
-
return `<tr><td>${
|
|
23129
|
+
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
23130
|
}).join("");
|
|
22855
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
22856
|
-
const snippet =
|
|
23131
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml40(stage)}</code></li>`).join("");
|
|
23132
|
+
const snippet = escapeHtml40(`const phoneAgent = createVoicePhoneAgent({
|
|
22857
23133
|
carriers: [
|
|
22858
23134
|
{
|
|
22859
23135
|
provider: 'twilio',
|
|
@@ -22887,11 +23163,11 @@ app.use(
|
|
|
22887
23163
|
);`);
|
|
22888
23164
|
const checklist = report.carriers.map((carrier) => {
|
|
22889
23165
|
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>${
|
|
23166
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml40(issue)}</li>`).join("") ?? "";
|
|
23167
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml40(step)}</li>`).join("") ?? "";
|
|
23168
|
+
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
23169
|
}).join("");
|
|
22894
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
23170
|
+
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
23171
|
};
|
|
22896
23172
|
var createVoicePhoneAgent = (options) => {
|
|
22897
23173
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -22900,7 +23176,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
22900
23176
|
setupPath: resolveSetupPath(carrier),
|
|
22901
23177
|
smokePath: resolveSmokePath(carrier)
|
|
22902
23178
|
}));
|
|
22903
|
-
const app = new
|
|
23179
|
+
const app = new Elysia41({
|
|
22904
23180
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
22905
23181
|
});
|
|
22906
23182
|
for (const carrier of options.carriers) {
|
|
@@ -24530,8 +24806,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
24530
24806
|
};
|
|
24531
24807
|
};
|
|
24532
24808
|
// src/providerCapabilities.ts
|
|
24533
|
-
import { Elysia as
|
|
24534
|
-
var
|
|
24809
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24810
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24535
24811
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
24536
24812
|
configured: true,
|
|
24537
24813
|
features: options.features?.[provider],
|
|
@@ -24594,27 +24870,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
24594
24870
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
24595
24871
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
24596
24872
|
const cards = report.capabilities.map((capability) => {
|
|
24597
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
24598
|
-
return `<article class="card ${
|
|
24873
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml41(feature)}</span>`).join("");
|
|
24874
|
+
return `<article class="card ${escapeHtml41(capability.status)}">
|
|
24599
24875
|
<div class="card-header">
|
|
24600
24876
|
<div>
|
|
24601
|
-
<p class="eyebrow">${
|
|
24602
|
-
<h2>${
|
|
24877
|
+
<p class="eyebrow">${escapeHtml41(capability.kind)}</p>
|
|
24878
|
+
<h2>${escapeHtml41(capability.label ?? capability.provider)}</h2>
|
|
24603
24879
|
</div>
|
|
24604
|
-
<strong>${
|
|
24880
|
+
<strong>${escapeHtml41(capability.status)}</strong>
|
|
24605
24881
|
</div>
|
|
24606
|
-
${capability.description ? `<p>${
|
|
24882
|
+
${capability.description ? `<p>${escapeHtml41(capability.description)}</p>` : ""}
|
|
24607
24883
|
<dl>
|
|
24608
24884
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
24609
24885
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
24610
|
-
<div><dt>Model</dt><dd>${
|
|
24886
|
+
<div><dt>Model</dt><dd>${escapeHtml41(capability.model ?? "default")}</dd></div>
|
|
24611
24887
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
24612
24888
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
24613
24889
|
</dl>
|
|
24614
24890
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
24615
24891
|
</article>`;
|
|
24616
24892
|
}).join("");
|
|
24617
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24893
|
+
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
24894
|
};
|
|
24619
24895
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
24620
24896
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -24631,7 +24907,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
24631
24907
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
24632
24908
|
const path = options.path ?? "/api/provider-capabilities";
|
|
24633
24909
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
24634
|
-
const routes = new
|
|
24910
|
+
const routes = new Elysia42({
|
|
24635
24911
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
24636
24912
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
24637
24913
|
if (htmlPath) {
|
|
@@ -24640,7 +24916,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
24640
24916
|
return routes;
|
|
24641
24917
|
};
|
|
24642
24918
|
// src/providerOrchestration.ts
|
|
24643
|
-
import { Elysia as
|
|
24919
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24644
24920
|
var defaultRequirement = {
|
|
24645
24921
|
minProviders: 1,
|
|
24646
24922
|
requireBudgetPolicy: false,
|
|
@@ -24648,12 +24924,12 @@ var defaultRequirement = {
|
|
|
24648
24924
|
requireFallback: false,
|
|
24649
24925
|
requireTimeoutBudget: false
|
|
24650
24926
|
};
|
|
24651
|
-
var
|
|
24927
|
+
var statusRank4 = {
|
|
24652
24928
|
pass: 0,
|
|
24653
24929
|
warn: 1,
|
|
24654
24930
|
fail: 2
|
|
24655
24931
|
};
|
|
24656
|
-
var
|
|
24932
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24657
24933
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
24658
24934
|
var uniqueSorted6 = (values) => [
|
|
24659
24935
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -24664,7 +24940,7 @@ var surfaceProviderNames = (surface) => uniqueSorted6([
|
|
|
24664
24940
|
...isProviderList(surface.fallback) ? surface.fallback : [],
|
|
24665
24941
|
...isProviderList(surface.allowProviders) ? surface.allowProviders : []
|
|
24666
24942
|
]);
|
|
24667
|
-
var surfaceStatus = (issues) => issues.reduce((status, issue) =>
|
|
24943
|
+
var surfaceStatus = (issues) => issues.reduce((status, issue) => statusRank4[issue.status] > statusRank4[status] ? issue.status : status, "pass");
|
|
24668
24944
|
var resolvedRequirement = (surface, options) => ({
|
|
24669
24945
|
...defaultRequirement,
|
|
24670
24946
|
...options.defaultRequirement ?? {},
|
|
@@ -24796,27 +25072,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
24796
25072
|
};
|
|
24797
25073
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
24798
25074
|
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">${
|
|
25075
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml42(surface.status)}">
|
|
25076
|
+
<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
25077
|
<dl>
|
|
24802
|
-
<div><dt>Providers</dt><dd>${
|
|
24803
|
-
<div><dt>Fallback</dt><dd>${
|
|
25078
|
+
<div><dt>Providers</dt><dd>${escapeHtml42(surface.providers.join(", ") || "none")}</dd></div>
|
|
25079
|
+
<div><dt>Fallback</dt><dd>${escapeHtml42(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
24804
25080
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
24805
25081
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
24806
25082
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
24807
25083
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
24808
25084
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
24809
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
25085
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml42(surface.fallbackMode || "default")}</dd></div>
|
|
24810
25086
|
</dl>
|
|
24811
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
25087
|
+
${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
25088
|
</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>${
|
|
25089
|
+
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
25090
|
};
|
|
24815
25091
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
24816
25092
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
24817
25093
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
24818
25094
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
24819
|
-
const routes = new
|
|
25095
|
+
const routes = new Elysia43({
|
|
24820
25096
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
24821
25097
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
24822
25098
|
if (htmlPath) {
|
|
@@ -24987,7 +25263,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
24987
25263
|
return report;
|
|
24988
25264
|
};
|
|
24989
25265
|
// src/providerSlo.ts
|
|
24990
|
-
import { Elysia as
|
|
25266
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
24991
25267
|
var defaultThresholds = {
|
|
24992
25268
|
llm: {
|
|
24993
25269
|
maxAverageElapsedMs: 2500,
|
|
@@ -25015,12 +25291,12 @@ var defaultThresholds = {
|
|
|
25015
25291
|
}
|
|
25016
25292
|
};
|
|
25017
25293
|
var providerKinds = ["llm", "stt", "tts"];
|
|
25018
|
-
var
|
|
25294
|
+
var statusRank5 = {
|
|
25019
25295
|
pass: 0,
|
|
25020
25296
|
warn: 1,
|
|
25021
25297
|
fail: 2
|
|
25022
25298
|
};
|
|
25023
|
-
var
|
|
25299
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25024
25300
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
25025
25301
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
25026
25302
|
var uniqueSorted7 = (values) => [
|
|
@@ -25212,7 +25488,7 @@ var evaluateVoiceProviderSloEvidence = (report, input = {}) => {
|
|
|
25212
25488
|
const timeouts = kindReports.reduce((total, kind) => total + kind.timeouts, 0);
|
|
25213
25489
|
const unresolvedErrors = kindReports.reduce((total, kind) => total + kind.unresolvedErrors, 0);
|
|
25214
25490
|
const maxStatus = input.maxStatus ?? "pass";
|
|
25215
|
-
if (
|
|
25491
|
+
if (statusRank5[report.status] > statusRank5[maxStatus]) {
|
|
25216
25492
|
issues.push(`Expected provider SLO status at most ${maxStatus}, found ${report.status}.`);
|
|
25217
25493
|
}
|
|
25218
25494
|
if (input.minEvents !== undefined && report.events < input.minEvents) {
|
|
@@ -25316,11 +25592,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
25316
25592
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
25317
25593
|
const kindCards = providerKinds.map((kind) => {
|
|
25318
25594
|
const kindReport = report.kinds[kind];
|
|
25319
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
25595
|
+
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
25596
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
25321
|
-
return `<article class="${
|
|
25597
|
+
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
25598
|
}).join("");
|
|
25323
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
25599
|
+
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
25600
|
const snippet = `createVoiceProviderSloRoutes({
|
|
25325
25601
|
store: runtimeStorage.traces,
|
|
25326
25602
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -25330,7 +25606,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
25330
25606
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
25331
25607
|
}
|
|
25332
25608
|
})`;
|
|
25333
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25609
|
+
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
25610
|
};
|
|
25335
25611
|
var createVoiceProviderSloRoutes = (options) => {
|
|
25336
25612
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -25341,7 +25617,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
25341
25617
|
...options.headers ?? {}
|
|
25342
25618
|
};
|
|
25343
25619
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
25344
|
-
const app = new
|
|
25620
|
+
const app = new Elysia44({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
25345
25621
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
25346
25622
|
if (markdownPath !== false) {
|
|
25347
25623
|
app.get(markdownPath, async () => {
|
|
@@ -25371,10 +25647,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
25371
25647
|
return app;
|
|
25372
25648
|
};
|
|
25373
25649
|
// src/productionReadiness.ts
|
|
25374
|
-
import { Elysia as
|
|
25650
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
25375
25651
|
|
|
25376
25652
|
// src/telephony/security.ts
|
|
25377
|
-
import { Elysia as
|
|
25653
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
25378
25654
|
|
|
25379
25655
|
// src/postgresStore.ts
|
|
25380
25656
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -26112,7 +26388,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
26112
26388
|
};
|
|
26113
26389
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
26114
26390
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
26115
|
-
return new
|
|
26391
|
+
return new Elysia45({
|
|
26116
26392
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
26117
26393
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
26118
26394
|
};
|
|
@@ -26169,8 +26445,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
26169
26445
|
};
|
|
26170
26446
|
|
|
26171
26447
|
// src/opsRecovery.ts
|
|
26172
|
-
import { Elysia as
|
|
26173
|
-
var
|
|
26448
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
26449
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26174
26450
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
26175
26451
|
var hrefForSession = (value, sessionId) => {
|
|
26176
26452
|
if (typeof value === "function") {
|
|
@@ -26384,19 +26660,19 @@ ${failedSessions || "None."}
|
|
|
26384
26660
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
26385
26661
|
`;
|
|
26386
26662
|
};
|
|
26387
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
26663
|
+
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
26664
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
26389
26665
|
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>${
|
|
26666
|
+
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("");
|
|
26667
|
+
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("");
|
|
26668
|
+
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("");
|
|
26669
|
+
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
26670
|
};
|
|
26395
26671
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
26396
26672
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
26397
26673
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
26398
26674
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
26399
|
-
const routes = new
|
|
26675
|
+
const routes = new Elysia46({
|
|
26400
26676
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
26401
26677
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
26402
26678
|
if (htmlPath) {
|
|
@@ -26426,18 +26702,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
26426
26702
|
};
|
|
26427
26703
|
|
|
26428
26704
|
// src/observabilityExport.ts
|
|
26429
|
-
import { Elysia as
|
|
26705
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
26430
26706
|
import { Database as Database4 } from "bun:sqlite";
|
|
26431
26707
|
import { createHash } from "crypto";
|
|
26432
26708
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
26433
26709
|
import { join as join3 } from "path";
|
|
26434
26710
|
|
|
26435
26711
|
// src/operationsRecord.ts
|
|
26436
|
-
import { Elysia as
|
|
26712
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
26437
26713
|
|
|
26438
26714
|
// src/traceTimeline.ts
|
|
26439
|
-
import { Elysia as
|
|
26440
|
-
var
|
|
26715
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
26716
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26441
26717
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
26442
26718
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
26443
26719
|
var firstString3 = (payload, keys) => {
|
|
@@ -26620,17 +26896,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
26620
26896
|
};
|
|
26621
26897
|
};
|
|
26622
26898
|
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>${
|
|
26899
|
+
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
26900
|
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>${
|
|
26901
|
+
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("");
|
|
26902
|
+
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>";
|
|
26903
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml45(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
26904
|
+
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
26905
|
};
|
|
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="${
|
|
26906
|
+
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
26907
|
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
26908
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
26633
|
-
const snippet =
|
|
26909
|
+
const snippet = escapeHtml45(`const traceStore = createVoiceTraceSinkStore({
|
|
26634
26910
|
store: runtimeStorage.traces,
|
|
26635
26911
|
sinks: [
|
|
26636
26912
|
createVoiceTraceHTTPSink({
|
|
@@ -26656,13 +26932,13 @@ app.use(
|
|
|
26656
26932
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
26657
26933
|
})
|
|
26658
26934
|
);`);
|
|
26659
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26935
|
+
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
26936
|
};
|
|
26661
26937
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
26662
26938
|
const path = options.path ?? "/api/voice-traces";
|
|
26663
26939
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
26664
26940
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
26665
|
-
const routes = new
|
|
26941
|
+
const routes = new Elysia47({
|
|
26666
26942
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
26667
26943
|
});
|
|
26668
26944
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -27091,7 +27367,7 @@ var assertVoiceOperationsRecordProviderRecovery = (record, input = {}) => {
|
|
|
27091
27367
|
}
|
|
27092
27368
|
return report;
|
|
27093
27369
|
};
|
|
27094
|
-
var
|
|
27370
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27095
27371
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
27096
27372
|
var outcomeLabels = (outcome) => [
|
|
27097
27373
|
outcome.complete ? "complete" : undefined,
|
|
@@ -27171,20 +27447,20 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
27171
27447
|
`);
|
|
27172
27448
|
};
|
|
27173
27449
|
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>${
|
|
27450
|
+
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>';
|
|
27451
|
+
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>";
|
|
27452
|
+
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
27453
|
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>${
|
|
27454
|
+
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>";
|
|
27455
|
+
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>";
|
|
27456
|
+
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>";
|
|
27457
|
+
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>";
|
|
27458
|
+
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
27459
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
27184
27460
|
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 ${
|
|
27461
|
+
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
27462
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
27187
|
-
const snippet =
|
|
27463
|
+
const snippet = escapeHtml46(`app.use(
|
|
27188
27464
|
createVoiceOperationsRecordRoutes({
|
|
27189
27465
|
audit: auditStore,
|
|
27190
27466
|
integrationEvents: opsEvents,
|
|
@@ -27198,16 +27474,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
27198
27474
|
tasks: opsTasks
|
|
27199
27475
|
})
|
|
27200
27476
|
);`);
|
|
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>${
|
|
27477
|
+
const incidentMarkdown = escapeHtml46(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
27478
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml46(options.incidentHref)}">Download incident.md</a>` : "";
|
|
27479
|
+
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
27480
|
};
|
|
27205
27481
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
27206
27482
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
27207
27483
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
27208
27484
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
27209
27485
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
27210
|
-
const routes = new
|
|
27486
|
+
const routes = new Elysia48({
|
|
27211
27487
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
27212
27488
|
});
|
|
27213
27489
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -27858,7 +28134,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
27858
28134
|
...options.headers ?? {}
|
|
27859
28135
|
};
|
|
27860
28136
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
27861
|
-
const app = new
|
|
28137
|
+
const app = new Elysia49({
|
|
27862
28138
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
27863
28139
|
});
|
|
27864
28140
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28667,7 +28943,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28667
28943
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
28668
28944
|
}
|
|
28669
28945
|
});
|
|
28670
|
-
const app = new
|
|
28946
|
+
const app = new Elysia49({
|
|
28671
28947
|
name: options.name ?? "absolute-voice-observability-export"
|
|
28672
28948
|
});
|
|
28673
28949
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28744,7 +29020,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28744
29020
|
};
|
|
28745
29021
|
|
|
28746
29022
|
// src/productionReadiness.ts
|
|
28747
|
-
var
|
|
29023
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28748
29024
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
28749
29025
|
var readinessGateCodes = {
|
|
28750
29026
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -30199,25 +30475,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30199
30475
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
30200
30476
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
30201
30477
|
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>${
|
|
30478
|
+
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>` : "";
|
|
30479
|
+
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
30480
|
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 ${
|
|
30481
|
+
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("");
|
|
30482
|
+
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>` : "";
|
|
30483
|
+
return `<article class="check ${escapeHtml47(check.status)}">
|
|
30208
30484
|
<div>
|
|
30209
|
-
<span>${
|
|
30210
|
-
<h2>${
|
|
30211
|
-
${check.detail ? `<p>${
|
|
30485
|
+
<span>${escapeHtml47(check.status.toUpperCase())}</span>
|
|
30486
|
+
<h2>${escapeHtml47(check.label)}</h2>
|
|
30487
|
+
${check.detail ? `<p>${escapeHtml47(check.detail)}</p>` : ""}
|
|
30212
30488
|
${explanation}
|
|
30213
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
30489
|
+
${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
30490
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
30215
30491
|
</div>
|
|
30216
|
-
<strong>${
|
|
30217
|
-
${check.href ? `<a href="${
|
|
30492
|
+
<strong>${escapeHtml47(String(check.value ?? check.status))}</strong>
|
|
30493
|
+
${check.href ? `<a href="${escapeHtml47(check.href)}">Open surface</a>` : ""}
|
|
30218
30494
|
</article>`;
|
|
30219
30495
|
}).join("");
|
|
30220
|
-
const snippet =
|
|
30496
|
+
const snippet = escapeHtml47(`createVoiceProductionReadinessRoutes({
|
|
30221
30497
|
htmlPath: '/production-readiness',
|
|
30222
30498
|
path: '/api/production-readiness',
|
|
30223
30499
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -30233,13 +30509,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
30233
30509
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
30234
30510
|
store: traceStore
|
|
30235
30511
|
});`);
|
|
30236
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30512
|
+
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
30513
|
};
|
|
30238
30514
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
30239
30515
|
const path = options.path ?? "/api/production-readiness";
|
|
30240
30516
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
30241
30517
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
30242
|
-
const routes = new
|
|
30518
|
+
const routes = new Elysia50({
|
|
30243
30519
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
30244
30520
|
});
|
|
30245
30521
|
const resolveOptions = async (input) => {
|
|
@@ -30287,8 +30563,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
30287
30563
|
return routes;
|
|
30288
30564
|
};
|
|
30289
30565
|
// src/voiceMonitoring.ts
|
|
30290
|
-
import { Elysia as
|
|
30291
|
-
var
|
|
30566
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
30567
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30292
30568
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
30293
30569
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
30294
30570
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -30541,14 +30817,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
30541
30817
|
};
|
|
30542
30818
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
30543
30819
|
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 =
|
|
30820
|
+
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("");
|
|
30821
|
+
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("");
|
|
30822
|
+
const snippet = escapeHtml48(`app.use(createVoiceMonitorRoutes({
|
|
30547
30823
|
evidence,
|
|
30548
30824
|
issueStore,
|
|
30549
30825
|
monitors: [defineVoiceMonitor(...)]
|
|
30550
30826
|
}));`);
|
|
30551
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30827
|
+
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
30828
|
};
|
|
30553
30829
|
var actorFromRequest = async (request) => {
|
|
30554
30830
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -30572,7 +30848,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30572
30848
|
monitors: options.monitors,
|
|
30573
30849
|
now: options.now
|
|
30574
30850
|
});
|
|
30575
|
-
const routes = new
|
|
30851
|
+
const routes = new Elysia51({
|
|
30576
30852
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
30577
30853
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
30578
30854
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -30619,7 +30895,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30619
30895
|
};
|
|
30620
30896
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
30621
30897
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
30622
|
-
return new
|
|
30898
|
+
return new Elysia51({
|
|
30623
30899
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
30624
30900
|
}).get(path, () => ({
|
|
30625
30901
|
isRunning: options.runner.isRunning()
|
|
@@ -30995,8 +31271,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
30995
31271
|
};
|
|
30996
31272
|
};
|
|
30997
31273
|
// src/providerStackRecommendations.ts
|
|
30998
|
-
import { Elysia as
|
|
30999
|
-
var
|
|
31274
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
31275
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31000
31276
|
var profileProviderPriorities = {
|
|
31001
31277
|
"meeting-recorder": {
|
|
31002
31278
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -31108,12 +31384,12 @@ var recommendVoiceProviderStack = (input) => {
|
|
|
31108
31384
|
};
|
|
31109
31385
|
};
|
|
31110
31386
|
var rollupContractStatus = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
31111
|
-
var
|
|
31387
|
+
var statusRank6 = {
|
|
31112
31388
|
pass: 0,
|
|
31113
31389
|
warn: 1,
|
|
31114
31390
|
fail: 2
|
|
31115
31391
|
};
|
|
31116
|
-
var statusExceeds2 = (actual, max) =>
|
|
31392
|
+
var statusExceeds2 = (actual, max) => statusRank6[actual] > statusRank6[max];
|
|
31117
31393
|
var buildVoiceProviderContractMatrix = (input) => {
|
|
31118
31394
|
const rows = input.contracts.map((contract) => {
|
|
31119
31395
|
const configured = contract.configured !== false;
|
|
@@ -31315,17 +31591,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
31315
31591
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
31316
31592
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
31317
31593
|
const rows = report.rows.map((row) => {
|
|
31318
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
31319
|
-
return `<article class="row ${
|
|
31594
|
+
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("");
|
|
31595
|
+
return `<article class="row ${escapeHtml49(row.status)}">
|
|
31320
31596
|
<div>
|
|
31321
|
-
<p class="eyebrow">${
|
|
31322
|
-
<h2>${
|
|
31323
|
-
<p class="status ${
|
|
31597
|
+
<p class="eyebrow">${escapeHtml49(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
31598
|
+
<h2>${escapeHtml49(row.provider)}</h2>
|
|
31599
|
+
<p class="status ${escapeHtml49(row.status)}">${escapeHtml49(row.status.toUpperCase())}</p>
|
|
31324
31600
|
</div>
|
|
31325
31601
|
<ul>${checks}</ul>
|
|
31326
31602
|
</article>`;
|
|
31327
31603
|
}).join("");
|
|
31328
|
-
const snippet =
|
|
31604
|
+
const snippet = escapeHtml49(`const providerContracts = () =>
|
|
31329
31605
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
31330
31606
|
env: process.env,
|
|
31331
31607
|
providers: {
|
|
@@ -31346,7 +31622,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
31346
31622
|
providerContractMatrix: () =>
|
|
31347
31623
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
31348
31624
|
});`);
|
|
31349
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31625
|
+
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
31626
|
};
|
|
31351
31627
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
31352
31628
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -31361,7 +31637,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
31361
31637
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
31362
31638
|
const path = options.path ?? "/api/provider-contracts";
|
|
31363
31639
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
31364
|
-
const routes = new
|
|
31640
|
+
const routes = new Elysia52({
|
|
31365
31641
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
31366
31642
|
});
|
|
31367
31643
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -31479,7 +31755,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
31479
31755
|
return assertion;
|
|
31480
31756
|
};
|
|
31481
31757
|
// src/opsConsoleRoutes.ts
|
|
31482
|
-
import { Elysia as
|
|
31758
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
31483
31759
|
var DEFAULT_LINKS = [
|
|
31484
31760
|
{
|
|
31485
31761
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -31514,7 +31790,7 @@ var DEFAULT_LINKS = [
|
|
|
31514
31790
|
label: "Handoffs"
|
|
31515
31791
|
}
|
|
31516
31792
|
];
|
|
31517
|
-
var
|
|
31793
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31518
31794
|
var countProviderStatuses = (providers) => {
|
|
31519
31795
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
31520
31796
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -31583,20 +31859,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
31583
31859
|
trace
|
|
31584
31860
|
};
|
|
31585
31861
|
};
|
|
31586
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
31862
|
+
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
31863
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
31588
31864
|
const links = report.links.map((link) => `<article class="surface">
|
|
31589
|
-
<div><h2>${
|
|
31590
|
-
<p><a href="${
|
|
31865
|
+
<div><h2>${escapeHtml50(link.label)}</h2>${link.description ? `<p>${escapeHtml50(link.description)}</p>` : ""}</div>
|
|
31866
|
+
<p><a href="${escapeHtml50(link.href)}">Open ${escapeHtml50(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml50(link.statusHref)}">Status</a>` : ""}</p>
|
|
31591
31867
|
</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>${
|
|
31868
|
+
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>';
|
|
31869
|
+
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
31870
|
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>${
|
|
31871
|
+
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
31872
|
};
|
|
31597
31873
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
31598
31874
|
const path = options.path ?? "/ops-console";
|
|
31599
|
-
const routes = new
|
|
31875
|
+
const routes = new Elysia53({
|
|
31600
31876
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
31601
31877
|
});
|
|
31602
31878
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -31613,7 +31889,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
31613
31889
|
return routes;
|
|
31614
31890
|
};
|
|
31615
31891
|
// src/incidentBundle.ts
|
|
31616
|
-
import { Elysia as
|
|
31892
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
31617
31893
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
31618
31894
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
31619
31895
|
return false;
|
|
@@ -31814,7 +32090,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
31814
32090
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
31815
32091
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
31816
32092
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
31817
|
-
const routes = new
|
|
32093
|
+
const routes = new Elysia54({
|
|
31818
32094
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
31819
32095
|
});
|
|
31820
32096
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -32015,19 +32291,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
32015
32291
|
};
|
|
32016
32292
|
};
|
|
32017
32293
|
// src/opsStatusRoutes.ts
|
|
32018
|
-
import { Elysia as
|
|
32019
|
-
var
|
|
32294
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
32295
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32020
32296
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
32021
32297
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
32022
32298
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
32023
32299
|
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 ${
|
|
32300
|
+
return `<article class="surface ${escapeHtml51(surface.status)}"><span>${escapeHtml51(surface.status.toUpperCase())}</span><h2>${escapeHtml51(key)}</h2><strong>${escapeHtml51(value)}</strong></article>`;
|
|
32025
32301
|
}).join("");
|
|
32026
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32302
|
+
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
32303
|
};
|
|
32028
32304
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
32029
32305
|
const path = options.path ?? "/api/voice/ops-status";
|
|
32030
|
-
const routes = new
|
|
32306
|
+
const routes = new Elysia55({
|
|
32031
32307
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
32032
32308
|
});
|
|
32033
32309
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -32460,8 +32736,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
32460
32736
|
};
|
|
32461
32737
|
};
|
|
32462
32738
|
// src/traceDeliveryRoutes.ts
|
|
32463
|
-
import { Elysia as
|
|
32464
|
-
var
|
|
32739
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
32740
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32465
32741
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
32466
32742
|
var getNumber12 = (value) => {
|
|
32467
32743
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -32542,14 +32818,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
32542
32818
|
if (entries.length === 0) {
|
|
32543
32819
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
32544
32820
|
}
|
|
32545
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
32821
|
+
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
32822
|
};
|
|
32547
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
32823
|
+
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
32824
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
32549
32825
|
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>${
|
|
32826
|
+
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>`;
|
|
32827
|
+
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("");
|
|
32828
|
+
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
32829
|
};
|
|
32554
32830
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
32555
32831
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -32569,7 +32845,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
32569
32845
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
32570
32846
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
32571
32847
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
32572
|
-
const routes = new
|
|
32848
|
+
const routes = new Elysia56({
|
|
32573
32849
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
32574
32850
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
32575
32851
|
if (htmlPath !== false) {
|
|
@@ -32666,7 +32942,7 @@ var createVoiceMemoryStore = () => {
|
|
|
32666
32942
|
return { get, getOrCreate, list, remove, set };
|
|
32667
32943
|
};
|
|
32668
32944
|
// src/opsWebhook.ts
|
|
32669
|
-
import { Elysia as
|
|
32945
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
32670
32946
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
32671
32947
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
32672
32948
|
const encoder = new TextEncoder;
|
|
@@ -32796,7 +33072,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
32796
33072
|
};
|
|
32797
33073
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
32798
33074
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
32799
|
-
return new
|
|
33075
|
+
return new Elysia57().post(path, async ({ body, request, set }) => {
|
|
32800
33076
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
32801
33077
|
if (options.signingSecret) {
|
|
32802
33078
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -33251,7 +33527,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
33251
33527
|
};
|
|
33252
33528
|
};
|
|
33253
33529
|
// src/postCallAnalysis.ts
|
|
33254
|
-
import { Elysia as
|
|
33530
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
33255
33531
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
33256
33532
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
33257
33533
|
var getPathValue3 = (source, path) => {
|
|
@@ -33430,7 +33706,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
33430
33706
|
};
|
|
33431
33707
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
33432
33708
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
33433
|
-
const routes = new
|
|
33709
|
+
const routes = new Elysia58({
|
|
33434
33710
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
33435
33711
|
});
|
|
33436
33712
|
routes.get(path, async ({ query }) => {
|
|
@@ -33455,7 +33731,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
33455
33731
|
return routes;
|
|
33456
33732
|
};
|
|
33457
33733
|
// src/guardrails.ts
|
|
33458
|
-
import { Elysia as
|
|
33734
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
33459
33735
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
33460
33736
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
33461
33737
|
var matchesRule = async (rule, input) => {
|
|
@@ -33757,7 +34033,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
33757
34033
|
};
|
|
33758
34034
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
33759
34035
|
const path = options.path ?? "/api/voice/guardrails";
|
|
33760
|
-
const routes = new
|
|
34036
|
+
const routes = new Elysia59({
|
|
33761
34037
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
33762
34038
|
});
|
|
33763
34039
|
routes.all(path, async ({ request }) => {
|
|
@@ -34310,6 +34586,8 @@ export {
|
|
|
34310
34586
|
renderVoiceObservabilityExportMarkdown,
|
|
34311
34587
|
renderVoiceMonitorMarkdown,
|
|
34312
34588
|
renderVoiceMonitorHTML,
|
|
34589
|
+
renderVoiceMediaPipelineMarkdown,
|
|
34590
|
+
renderVoiceMediaPipelineHTML,
|
|
34313
34591
|
renderVoiceLiveLatencyHTML,
|
|
34314
34592
|
renderVoiceLatencySLOMarkdown,
|
|
34315
34593
|
renderVoiceHandoffHealthHTML,
|
|
@@ -34397,6 +34675,7 @@ export {
|
|
|
34397
34675
|
evaluateVoiceOperationsRecordGuardrails,
|
|
34398
34676
|
evaluateVoiceObservabilityExportReplayEvidence,
|
|
34399
34677
|
evaluateVoiceObservabilityExportDeliveryEvidence,
|
|
34678
|
+
evaluateVoiceMediaPipelineEvidence,
|
|
34400
34679
|
evaluateVoiceLiveOpsEvidence,
|
|
34401
34680
|
evaluateVoiceLiveOpsControlEvidence,
|
|
34402
34681
|
evaluateVoiceGuardrailPolicy,
|
|
@@ -34591,6 +34870,8 @@ export {
|
|
|
34591
34870
|
createVoiceMemoryAuditSinkDeliveryStore,
|
|
34592
34871
|
createVoiceMemoryAuditEventStore,
|
|
34593
34872
|
createVoiceMemoryAssistantMemoryStore,
|
|
34873
|
+
createVoiceMediaTransport,
|
|
34874
|
+
createVoiceMediaPipelineRoutes,
|
|
34594
34875
|
createVoiceMediaFrameTransformPipeline,
|
|
34595
34876
|
createVoiceMediaFrame,
|
|
34596
34877
|
createVoiceLiveOpsRoutes,
|
|
@@ -34742,7 +35023,9 @@ export {
|
|
|
34742
35023
|
buildVoiceObservabilityArtifactIndex,
|
|
34743
35024
|
buildVoiceMonitorRunReport,
|
|
34744
35025
|
buildVoiceMediaVadReport,
|
|
35026
|
+
buildVoiceMediaTransportReport,
|
|
34745
35027
|
buildVoiceMediaResamplingPlan,
|
|
35028
|
+
buildVoiceMediaPipelineReport,
|
|
34746
35029
|
buildVoiceMediaPipelineCalibrationReport,
|
|
34747
35030
|
buildVoiceMediaInterruptionReport,
|
|
34748
35031
|
buildVoiceLiveOpsControlState,
|
|
@@ -34786,6 +35069,7 @@ export {
|
|
|
34786
35069
|
assertVoiceObservabilityExportReplayEvidence,
|
|
34787
35070
|
assertVoiceObservabilityExportRecord,
|
|
34788
35071
|
assertVoiceObservabilityExportDeliveryEvidence,
|
|
35072
|
+
assertVoiceMediaPipelineEvidence,
|
|
34789
35073
|
assertVoiceLiveOpsEvidence,
|
|
34790
35074
|
assertVoiceLiveOpsControlEvidence,
|
|
34791
35075
|
assertVoiceLatencySLOGate,
|