@absolutejs/voice 0.0.22-beta.300 → 0.0.22-beta.302
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/competitiveCoverage.d.ts +141 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +870 -398
- package/dist/realtimeChannel.d.ts +127 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10920,9 +10920,239 @@ var createVoiceReconnectContractRoutes = (options) => {
|
|
|
10920
10920
|
}
|
|
10921
10921
|
return app;
|
|
10922
10922
|
};
|
|
10923
|
-
// src/
|
|
10923
|
+
// src/realtimeChannel.ts
|
|
10924
10924
|
import { Elysia as Elysia9 } from "elysia";
|
|
10925
|
-
var
|
|
10925
|
+
var DEFAULT_REALTIME_FORMAT2 = {
|
|
10926
|
+
channels: 1,
|
|
10927
|
+
container: "raw",
|
|
10928
|
+
encoding: "pcm_s16le",
|
|
10929
|
+
sampleRateHz: 24000
|
|
10930
|
+
};
|
|
10931
|
+
var escapeHtml12 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10932
|
+
var formatLabel = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
|
|
10933
|
+
var formatMatches = (actual, expected) => actual.container === expected.container && actual.encoding === expected.encoding && actual.sampleRateHz === expected.sampleRateHz && actual.channels === expected.channels;
|
|
10934
|
+
var validateFormat = (label, actual, expected, issues) => {
|
|
10935
|
+
if (!formatMatches(actual, expected)) {
|
|
10936
|
+
issues.push({
|
|
10937
|
+
code: `${label}-format-mismatch`,
|
|
10938
|
+
message: `${label} format ${formatLabel(actual)} does not match expected ${formatLabel(expected)}.`,
|
|
10939
|
+
severity: "error"
|
|
10940
|
+
});
|
|
10941
|
+
}
|
|
10942
|
+
if (actual.container !== "raw" || actual.encoding !== "pcm_s16le") {
|
|
10943
|
+
issues.push({
|
|
10944
|
+
code: `${label}-unsupported-encoding`,
|
|
10945
|
+
message: `${label} must use raw pcm_s16le audio for realtime proof.`,
|
|
10946
|
+
severity: "error"
|
|
10947
|
+
});
|
|
10948
|
+
}
|
|
10949
|
+
if (actual.channels !== 1) {
|
|
10950
|
+
issues.push({
|
|
10951
|
+
code: `${label}-not-mono`,
|
|
10952
|
+
message: `${label} should be mono for realtime provider input/output.`,
|
|
10953
|
+
severity: "error"
|
|
10954
|
+
});
|
|
10955
|
+
}
|
|
10956
|
+
};
|
|
10957
|
+
var buildVoiceRealtimeChannelReport = (options) => {
|
|
10958
|
+
const expectedInputFormat = options.expectedInputFormat ?? DEFAULT_REALTIME_FORMAT2;
|
|
10959
|
+
const expectedOutputFormat = options.expectedOutputFormat ?? expectedInputFormat;
|
|
10960
|
+
const inputFormat = options.inputFormat ?? expectedInputFormat;
|
|
10961
|
+
const outputFormat = options.outputFormat ?? expectedOutputFormat;
|
|
10962
|
+
const runtimeSamples = options.runtimeSamples ?? [];
|
|
10963
|
+
const issues = [];
|
|
10964
|
+
validateFormat("input", inputFormat, expectedInputFormat, issues);
|
|
10965
|
+
validateFormat("output", outputFormat, expectedOutputFormat, issues);
|
|
10966
|
+
const browserCapture = options.browserCapture ? {
|
|
10967
|
+
...options.browserCapture,
|
|
10968
|
+
resamplingRequired: options.browserCapture.audioContextSampleRateHz !== undefined && options.browserCapture.audioContextSampleRateHz !== inputFormat.sampleRateHz,
|
|
10969
|
+
resamplingTargetHz: inputFormat.sampleRateHz
|
|
10970
|
+
} : undefined;
|
|
10971
|
+
if (!browserCapture) {
|
|
10972
|
+
issues.push({
|
|
10973
|
+
code: "browser-capture-missing",
|
|
10974
|
+
message: "Browser capture settings are missing; realtime proof cannot show capture-to-provider format negotiation.",
|
|
10975
|
+
severity: "warning"
|
|
10976
|
+
});
|
|
10977
|
+
} else {
|
|
10978
|
+
if (browserCapture.sampleRateHz !== inputFormat.sampleRateHz) {
|
|
10979
|
+
issues.push({
|
|
10980
|
+
code: "browser-capture-target-mismatch",
|
|
10981
|
+
message: `Browser capture target ${String(browserCapture.sampleRateHz ?? "unknown")}hz does not match realtime input ${String(inputFormat.sampleRateHz)}hz.`,
|
|
10982
|
+
severity: "error"
|
|
10983
|
+
});
|
|
10984
|
+
}
|
|
10985
|
+
if ((browserCapture.channelCount ?? 1) !== inputFormat.channels) {
|
|
10986
|
+
issues.push({
|
|
10987
|
+
code: "browser-capture-channel-mismatch",
|
|
10988
|
+
message: `Browser capture channel count ${String(browserCapture.channelCount ?? "unknown")} does not match realtime input ${String(inputFormat.channels)}.`,
|
|
10989
|
+
severity: "error"
|
|
10990
|
+
});
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
for (const sample of runtimeSamples) {
|
|
10994
|
+
if (sample.ok === false) {
|
|
10995
|
+
issues.push({
|
|
10996
|
+
code: "runtime-sample-failed",
|
|
10997
|
+
message: `Realtime runtime sample failed: ${sample.kind}.`,
|
|
10998
|
+
severity: "error"
|
|
10999
|
+
});
|
|
11000
|
+
}
|
|
11001
|
+
if (sample.format && !formatMatches(sample.format, inputFormat)) {
|
|
11002
|
+
issues.push({
|
|
11003
|
+
code: "runtime-format-mismatch",
|
|
11004
|
+
message: `Runtime sample ${sample.kind} used ${formatLabel(sample.format)} instead of ${formatLabel(inputFormat)}.`,
|
|
11005
|
+
severity: "error"
|
|
11006
|
+
});
|
|
11007
|
+
}
|
|
11008
|
+
}
|
|
11009
|
+
const inputAudioSamples = runtimeSamples.filter((sample) => sample.kind === "input-audio").length;
|
|
11010
|
+
const assistantAudioSamples = runtimeSamples.filter((sample) => sample.kind === "assistant-audio").length;
|
|
11011
|
+
const firstAudioLatencyMs = runtimeSamples.filter((sample) => sample.kind === "assistant-audio" && typeof sample.latencyMs === "number" && Number.isFinite(sample.latencyMs)).map((sample) => sample.latencyMs).sort((a, b) => a - b)[0];
|
|
11012
|
+
const minInputAudioSamples = options.minInputAudioSamples ?? 1;
|
|
11013
|
+
const minAssistantAudioSamples = options.minAssistantAudioSamples ?? 1;
|
|
11014
|
+
const maxFirstAudioLatencyMs = options.maxFirstAudioLatencyMs;
|
|
11015
|
+
if (inputAudioSamples < minInputAudioSamples) {
|
|
11016
|
+
issues.push({
|
|
11017
|
+
code: "runtime-input-audio-missing",
|
|
11018
|
+
message: `Expected at least ${String(minInputAudioSamples)} realtime input audio sample(s), found ${String(inputAudioSamples)}.`,
|
|
11019
|
+
severity: "warning"
|
|
11020
|
+
});
|
|
11021
|
+
}
|
|
11022
|
+
if (assistantAudioSamples < minAssistantAudioSamples) {
|
|
11023
|
+
issues.push({
|
|
11024
|
+
code: "runtime-assistant-audio-missing",
|
|
11025
|
+
message: `Expected at least ${String(minAssistantAudioSamples)} realtime assistant audio sample(s), found ${String(assistantAudioSamples)}.`,
|
|
11026
|
+
severity: "warning"
|
|
11027
|
+
});
|
|
11028
|
+
}
|
|
11029
|
+
if (maxFirstAudioLatencyMs !== undefined && (firstAudioLatencyMs === undefined || firstAudioLatencyMs > maxFirstAudioLatencyMs)) {
|
|
11030
|
+
issues.push({
|
|
11031
|
+
code: "first-audio-latency-over-budget",
|
|
11032
|
+
message: `Expected first realtime assistant audio at or below ${String(maxFirstAudioLatencyMs)}ms, found ${String(firstAudioLatencyMs ?? "missing")}ms.`,
|
|
11033
|
+
severity: "warning"
|
|
11034
|
+
});
|
|
11035
|
+
}
|
|
11036
|
+
const status = issues.some((issue) => issue.severity === "error") ? "fail" : issues.length > 0 ? "warn" : "pass";
|
|
11037
|
+
return {
|
|
11038
|
+
browserCapture,
|
|
11039
|
+
checkedAt: Date.now(),
|
|
11040
|
+
inputFormat,
|
|
11041
|
+
issues,
|
|
11042
|
+
operationsRecordHref: options.operationsRecordHref,
|
|
11043
|
+
outputFormat,
|
|
11044
|
+
provider: options.provider,
|
|
11045
|
+
readinessHref: options.readinessHref,
|
|
11046
|
+
runtime: {
|
|
11047
|
+
assistantAudioSamples,
|
|
11048
|
+
firstAudioLatencyMs,
|
|
11049
|
+
inputAudioSamples,
|
|
11050
|
+
samples: runtimeSamples
|
|
11051
|
+
},
|
|
11052
|
+
status,
|
|
11053
|
+
surface: options.surface ?? "Direct realtime/duplex providers"
|
|
11054
|
+
};
|
|
11055
|
+
};
|
|
11056
|
+
var evaluateVoiceRealtimeChannelEvidence = (report, input = {}) => {
|
|
11057
|
+
const issues = [];
|
|
11058
|
+
if ((input.requirePass ?? false) && report.status !== "pass") {
|
|
11059
|
+
issues.push(`Expected realtime channel proof to pass, found ${report.status}.`);
|
|
11060
|
+
}
|
|
11061
|
+
if (input.requireBrowserCapture && !report.browserCapture) {
|
|
11062
|
+
issues.push("Missing browser capture negotiation proof.");
|
|
11063
|
+
}
|
|
11064
|
+
if (input.requireOperationsRecordHref && !report.operationsRecordHref) {
|
|
11065
|
+
issues.push("Missing operations-record link for realtime channel proof.");
|
|
11066
|
+
}
|
|
11067
|
+
if (input.requireReadinessHref && !report.readinessHref) {
|
|
11068
|
+
issues.push("Missing readiness link for realtime channel proof.");
|
|
11069
|
+
}
|
|
11070
|
+
if (input.minInputAudioSamples !== undefined && report.runtime.inputAudioSamples < input.minInputAudioSamples) {
|
|
11071
|
+
issues.push(`Expected at least ${String(input.minInputAudioSamples)} realtime input audio samples, found ${String(report.runtime.inputAudioSamples)}.`);
|
|
11072
|
+
}
|
|
11073
|
+
if (input.minAssistantAudioSamples !== undefined && report.runtime.assistantAudioSamples < input.minAssistantAudioSamples) {
|
|
11074
|
+
issues.push(`Expected at least ${String(input.minAssistantAudioSamples)} realtime assistant audio samples, found ${String(report.runtime.assistantAudioSamples)}.`);
|
|
11075
|
+
}
|
|
11076
|
+
if (input.maxFirstAudioLatencyMs !== undefined && (report.runtime.firstAudioLatencyMs === undefined || report.runtime.firstAudioLatencyMs > input.maxFirstAudioLatencyMs)) {
|
|
11077
|
+
issues.push(`Expected first realtime assistant audio at or below ${String(input.maxFirstAudioLatencyMs)}ms, found ${String(report.runtime.firstAudioLatencyMs ?? "missing")}ms.`);
|
|
11078
|
+
}
|
|
11079
|
+
return {
|
|
11080
|
+
issues,
|
|
11081
|
+
ok: issues.length === 0,
|
|
11082
|
+
provider: report.provider,
|
|
11083
|
+
status: report.status,
|
|
11084
|
+
surface: report.surface
|
|
11085
|
+
};
|
|
11086
|
+
};
|
|
11087
|
+
var assertVoiceRealtimeChannelEvidence = (report, input = {}) => {
|
|
11088
|
+
const assertion = evaluateVoiceRealtimeChannelEvidence(report, input);
|
|
11089
|
+
if (!assertion.ok) {
|
|
11090
|
+
throw new Error(`Voice realtime channel assertion failed: ${assertion.issues.join(" ")}`);
|
|
11091
|
+
}
|
|
11092
|
+
return assertion;
|
|
11093
|
+
};
|
|
11094
|
+
var renderVoiceRealtimeChannelMarkdown = (report) => [
|
|
11095
|
+
"# Voice Realtime Channel Proof",
|
|
11096
|
+
"",
|
|
11097
|
+
`- Status: ${report.status}`,
|
|
11098
|
+
`- Provider: ${report.provider}`,
|
|
11099
|
+
`- Surface: ${report.surface}`,
|
|
11100
|
+
`- Input format: ${formatLabel(report.inputFormat)}`,
|
|
11101
|
+
`- Output format: ${formatLabel(report.outputFormat)}`,
|
|
11102
|
+
`- Browser capture: ${report.browserCapture ? `${String(report.browserCapture.sampleRateHz)}hz target, ${String(report.browserCapture.channelCount ?? 1)}ch` : "missing"}`,
|
|
11103
|
+
`- Resampling required: ${report.browserCapture?.resamplingRequired ? "yes" : "no"}`,
|
|
11104
|
+
`- Input audio samples: ${String(report.runtime.inputAudioSamples)}`,
|
|
11105
|
+
`- Assistant audio samples: ${String(report.runtime.assistantAudioSamples)}`,
|
|
11106
|
+
`- First audio latency: ${String(report.runtime.firstAudioLatencyMs ?? "n/a")}ms`,
|
|
11107
|
+
"",
|
|
11108
|
+
"## Issues",
|
|
11109
|
+
"",
|
|
11110
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue.severity.toUpperCase()} ${issue.code}: ${issue.message}`) : ["- None"]
|
|
11111
|
+
].join(`
|
|
11112
|
+
`);
|
|
11113
|
+
var renderVoiceRealtimeChannelHTML = (report, title = "Voice Realtime Channel Proof") => {
|
|
11114
|
+
const issues = report.issues.map((issue) => `<li class="${escapeHtml12(issue.severity)}"><strong>${escapeHtml12(issue.code)}</strong>: ${escapeHtml12(issue.message)}</li>`).join("");
|
|
11115
|
+
const rows = report.runtime.samples.map((sample) => `<tr><td>${escapeHtml12(sample.kind)}</td><td>${escapeHtml12(sample.source ?? "runtime")}</td><td>${escapeHtml12(sample.format ? formatLabel(sample.format) : "n/a")}</td><td>${escapeHtml12(sample.latencyMs ?? "n/a")}</td><td>${escapeHtml12(sample.ok ?? true)}</td></tr>`).join("");
|
|
11116
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml12(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;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(59,130,246,.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{color:#fde68a}.fail,.error{color:#fecaca}.warning{color:#fde68a}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3d36;padding:10px;text-align:left}.links a{color:#5eead4;margin-right:12px}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime / duplex readiness</p><h1>${escapeHtml12(title)}</h1><p class="status ${escapeHtml12(report.status)}">${escapeHtml12(report.status)}</p><p>Provider <strong>${escapeHtml12(report.provider)}</strong> \xB7 ${escapeHtml12(report.surface)}</p><p class="links">${report.readinessHref ? `<a href="${escapeHtml12(report.readinessHref)}">Readiness</a>` : ""}${report.operationsRecordHref ? `<a href="${escapeHtml12(report.operationsRecordHref)}">Operations record</a>` : ""}</p><section class="summary"><div class="metric"><span>Input</span><strong>${escapeHtml12(formatLabel(report.inputFormat))}</strong></div><div class="metric"><span>Output</span><strong>${escapeHtml12(formatLabel(report.outputFormat))}</strong></div><div class="metric"><span>Browser capture</span><strong>${escapeHtml12(report.browserCapture ? `${String(report.browserCapture.sampleRateHz)}hz` : "missing")}</strong></div><div class="metric"><span>Resampling</span><strong>${report.browserCapture?.resamplingRequired ? "required" : "not required"}</strong></div><div class="metric"><span>Input samples</span><strong>${String(report.runtime.inputAudioSamples)}</strong></div><div class="metric"><span>Assistant samples</span><strong>${String(report.runtime.assistantAudioSamples)}</strong></div></section></section><section class="card"><h2>Issues</h2><ul>${issues || '<li class="pass">No realtime channel issues.</li>'}</ul></section><section class="card"><h2>Runtime Samples</h2><table><thead><tr><th>Kind</th><th>Source</th><th>Format</th><th>Latency ms</th><th>OK</th></tr></thead><tbody>${rows || '<tr><td colspan="5">No runtime samples configured.</td></tr>'}</tbody></table></section></main></body></html>`;
|
|
11117
|
+
};
|
|
11118
|
+
var createVoiceRealtimeChannelRoutes = (options) => {
|
|
11119
|
+
const path = options.path ?? "/api/voice/realtime-channel";
|
|
11120
|
+
const htmlPath = options.htmlPath ?? "/voice/realtime-channel";
|
|
11121
|
+
const markdownPath = options.markdownPath ?? "/voice/realtime-channel.md";
|
|
11122
|
+
const headers = options.headers ?? {};
|
|
11123
|
+
const title = options.title ?? "Voice Realtime Channel Proof";
|
|
11124
|
+
const report = () => buildVoiceRealtimeChannelReport(options);
|
|
11125
|
+
const app = new Elysia9({ name: options.name ?? "voice-realtime-channel" }).get(path, () => new Response(JSON.stringify(report(), null, 2), {
|
|
11126
|
+
headers: {
|
|
11127
|
+
"content-type": "application/json; charset=utf-8",
|
|
11128
|
+
...headers
|
|
11129
|
+
}
|
|
11130
|
+
}));
|
|
11131
|
+
if (htmlPath !== false) {
|
|
11132
|
+
app.get(htmlPath, async () => {
|
|
11133
|
+
const current = report();
|
|
11134
|
+
const body = options.render ? await options.render(current) : renderVoiceRealtimeChannelHTML(current, title);
|
|
11135
|
+
return new Response(body, {
|
|
11136
|
+
headers: {
|
|
11137
|
+
"content-type": "text/html; charset=utf-8",
|
|
11138
|
+
...headers
|
|
11139
|
+
}
|
|
11140
|
+
});
|
|
11141
|
+
});
|
|
11142
|
+
}
|
|
11143
|
+
if (markdownPath !== false) {
|
|
11144
|
+
app.get(markdownPath, () => new Response(renderVoiceRealtimeChannelMarkdown(report()), {
|
|
11145
|
+
headers: {
|
|
11146
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
11147
|
+
...headers
|
|
11148
|
+
}
|
|
11149
|
+
}));
|
|
11150
|
+
}
|
|
11151
|
+
return app;
|
|
11152
|
+
};
|
|
11153
|
+
// src/diagnosticsRoutes.ts
|
|
11154
|
+
import { Elysia as Elysia10 } from "elysia";
|
|
11155
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10926
11156
|
var getString6 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
10927
11157
|
var getNumber4 = (value) => {
|
|
10928
11158
|
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : undefined;
|
|
@@ -10988,9 +11218,9 @@ var renderDiagnosticsIndex = (input) => {
|
|
|
10988
11218
|
const rows = [...sessions.entries()].sort(([, left], [, right]) => (right.at(-1)?.at ?? 0) - (left.at(-1)?.at ?? 0)).slice(0, 50).map(([sessionId, events]) => {
|
|
10989
11219
|
const summary = summarizeVoiceTrace(events);
|
|
10990
11220
|
const encoded = encodeURIComponent(sessionId);
|
|
10991
|
-
return `<tr><td>${
|
|
11221
|
+
return `<tr><td>${escapeHtml13(sessionId)}</td><td>${summary.eventCount}</td><td>${summary.turnCount}</td><td>${summary.errorCount}</td><td><a href="${input.basePath}/html?sessionId=${encoded}&redact=true">HTML</a> \xB7 <a href="${input.basePath}/markdown?sessionId=${encoded}&redact=true">Markdown</a> \xB7 <a href="${input.basePath}/json?sessionId=${encoded}&redact=true">JSON</a></td></tr>`;
|
|
10992
11222
|
}).join("");
|
|
10993
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11223
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml13(input.title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}table{width:100%;border-collapse:collapse;background:white}td,th{border-bottom:1px solid #eee;padding:.7rem;text-align:left}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml13(input.title)}</h1><p>Recent voice trace diagnostics. Exports support filters: sessionId, traceId, turnId, scenarioId, type, provider, status, since, until, limit, redact.</p><table><thead><tr><th>Session</th><th>Events</th><th>Turns</th><th>Errors</th><th>Exports</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
10994
11224
|
};
|
|
10995
11225
|
var withRedaction = (events, query, defaultRedact) => {
|
|
10996
11226
|
const shouldRedact = query.redact === undefined ? defaultRedact : getBoolean(query.redact);
|
|
@@ -10999,7 +11229,7 @@ var withRedaction = (events, query, defaultRedact) => {
|
|
|
10999
11229
|
var createVoiceDiagnosticsRoutes = (options) => {
|
|
11000
11230
|
const path = options.path ?? "/diagnostics";
|
|
11001
11231
|
const title = options.title ?? "AbsoluteJS Voice Diagnostics";
|
|
11002
|
-
const routes = new
|
|
11232
|
+
const routes = new Elysia10({
|
|
11003
11233
|
name: options.name ?? "absolutejs-voice-diagnostics"
|
|
11004
11234
|
});
|
|
11005
11235
|
routes.get(path, async () => {
|
|
@@ -11056,8 +11286,8 @@ var createVoiceDiagnosticsRoutes = (options) => {
|
|
|
11056
11286
|
return routes;
|
|
11057
11287
|
};
|
|
11058
11288
|
// src/demoReadyRoutes.ts
|
|
11059
|
-
import { Elysia as
|
|
11060
|
-
var
|
|
11289
|
+
import { Elysia as Elysia11 } from "elysia";
|
|
11290
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11061
11291
|
var rollupStatus = (sections) => sections.some((section) => section.status === "fail") ? "fail" : sections.some((section) => section.status === "warn") ? "warn" : "pass";
|
|
11062
11292
|
var resolveLoader = async (loader, input) => typeof loader === "function" ? await loader(input) : loader;
|
|
11063
11293
|
var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
@@ -11141,17 +11371,17 @@ var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
|
11141
11371
|
};
|
|
11142
11372
|
};
|
|
11143
11373
|
var renderVoiceDemoReadyHTML = (report) => {
|
|
11144
|
-
const sections = report.sections.map((section) => `<article class="section ${
|
|
11145
|
-
<div><span>${
|
|
11146
|
-
<strong>${
|
|
11147
|
-
${section.href ? `<a href="${
|
|
11374
|
+
const sections = report.sections.map((section) => `<article class="section ${escapeHtml14(section.status)}">
|
|
11375
|
+
<div><span>${escapeHtml14(section.status.toUpperCase())}</span><h2>${escapeHtml14(section.label)}</h2>${section.description ? `<p>${escapeHtml14(section.description)}</p>` : ""}</div>
|
|
11376
|
+
<strong>${escapeHtml14(String(section.value ?? section.status))}</strong>
|
|
11377
|
+
${section.href ? `<a href="${escapeHtml14(section.href)}">Open</a>` : ""}
|
|
11148
11378
|
</article>`).join("");
|
|
11149
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11379
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml14(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>${escapeHtml14(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 ${escapeHtml14(report.status)}">Overall: ${escapeHtml14(report.status.toUpperCase())}</p><p>Checked ${escapeHtml14(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>`;
|
|
11150
11380
|
};
|
|
11151
11381
|
var createVoiceDemoReadyRoutes = (options) => {
|
|
11152
11382
|
const path = options.path ?? "/api/demo-ready";
|
|
11153
11383
|
const htmlPath = options.htmlPath ?? "/demo-ready";
|
|
11154
|
-
const routes = new
|
|
11384
|
+
const routes = new Elysia11({
|
|
11155
11385
|
name: options.name ?? "absolutejs-voice-demo-ready"
|
|
11156
11386
|
});
|
|
11157
11387
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
@@ -11170,7 +11400,7 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
11170
11400
|
return routes;
|
|
11171
11401
|
};
|
|
11172
11402
|
// src/deliverySinkRoutes.ts
|
|
11173
|
-
import { Elysia as
|
|
11403
|
+
import { Elysia as Elysia12 } from "elysia";
|
|
11174
11404
|
|
|
11175
11405
|
// src/queue.ts
|
|
11176
11406
|
var releaseLeaseScript = `
|
|
@@ -12113,7 +12343,7 @@ var createVoiceOpsTaskProcessorWorkerLoop = (options) => {
|
|
|
12113
12343
|
};
|
|
12114
12344
|
|
|
12115
12345
|
// src/deliverySinkRoutes.ts
|
|
12116
|
-
var
|
|
12346
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12117
12347
|
var deliveryStatus = (summary) => {
|
|
12118
12348
|
if (!summary) {
|
|
12119
12349
|
return "warn";
|
|
@@ -12212,13 +12442,13 @@ var renderSurfaceCard = (surface) => {
|
|
|
12212
12442
|
return "";
|
|
12213
12443
|
}
|
|
12214
12444
|
const value = `${surface.summary.delivered}/${surface.summary.total}`;
|
|
12215
|
-
const body = `<span>${
|
|
12216
|
-
return `<article>${surface.href ? `<a href="${
|
|
12445
|
+
const body = `<span>${escapeHtml15(surface.label)}</span><strong>${escapeHtml15(value)}</strong><p class="muted">Delivered export records.</p>`;
|
|
12446
|
+
return `<article>${surface.href ? `<a href="${escapeHtml15(surface.href)}">${body}</a>` : body}</article>`;
|
|
12217
12447
|
};
|
|
12218
12448
|
var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
12219
12449
|
const title = options.title ?? "AbsoluteJS Voice Delivery Sinks";
|
|
12220
|
-
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${
|
|
12221
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
12450
|
+
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${escapeHtml15(sink.kind)}</span><strong style="font-size:1.5rem">${escapeHtml15(sink.label)}</strong>${sink.description ? `<p class="muted">${escapeHtml15(sink.description)}</p>` : ""}${sink.mode ? `<p class="muted">Mode: ${escapeHtml15(sink.mode)}</p>` : ""}${sink.target ? `<p class="muted">Target: <code>${escapeHtml15(sink.target)}</code></p>` : ""}${sink.href ? `<p><a href="${escapeHtml15(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>';
|
|
12451
|
+
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:#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>${escapeHtml15(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 ${escapeHtml15(report.status)}">Overall: ${escapeHtml15(report.status.toUpperCase())}</p><p class="muted">Checked ${escapeHtml15(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({
|
|
12222
12452
|
auditDeliveries: { store: runtimeStorage.auditDeliveries },
|
|
12223
12453
|
traceDeliveries: { store: runtimeStorage.traceDeliveries },
|
|
12224
12454
|
sinks: createVoiceDeliverySinkPair({
|
|
@@ -12230,7 +12460,7 @@ var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
|
12230
12460
|
var createVoiceDeliverySinkRoutes = (options) => {
|
|
12231
12461
|
const path = options.path ?? "/api/voice-delivery-sinks";
|
|
12232
12462
|
const htmlPath = options.htmlPath === undefined ? "/delivery-sinks" : options.htmlPath;
|
|
12233
|
-
const routes = new
|
|
12463
|
+
const routes = new Elysia12({
|
|
12234
12464
|
name: options.name ?? "absolutejs-voice-delivery-sinks"
|
|
12235
12465
|
}).get(path, () => buildVoiceDeliverySinkReport(options));
|
|
12236
12466
|
if (htmlPath !== false) {
|
|
@@ -12248,7 +12478,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
|
|
|
12248
12478
|
return routes;
|
|
12249
12479
|
};
|
|
12250
12480
|
// src/opsActionAuditRoutes.ts
|
|
12251
|
-
import { Elysia as
|
|
12481
|
+
import { Elysia as Elysia13 } from "elysia";
|
|
12252
12482
|
var readRecordBody = (body) => {
|
|
12253
12483
|
if (!body || typeof body !== "object") {
|
|
12254
12484
|
throw new Error("Voice ops action audit requires a JSON body.");
|
|
@@ -12323,7 +12553,7 @@ var createVoiceOpsActionAuditRoutes = (options) => {
|
|
|
12323
12553
|
const path = options.path ?? "/api/voice/ops-actions/audit";
|
|
12324
12554
|
const historyPath = options.historyPath === undefined ? "/api/voice/ops-actions/history" : options.historyPath;
|
|
12325
12555
|
const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
|
|
12326
|
-
const routes = new
|
|
12556
|
+
const routes = new Elysia13({
|
|
12327
12557
|
name: options.name ?? "absolutejs-voice-ops-action-audit"
|
|
12328
12558
|
}).post(path, async ({ body, request, set }) => {
|
|
12329
12559
|
try {
|
|
@@ -12373,13 +12603,13 @@ var buildVoiceOpsActionHistoryReport = async (options) => {
|
|
|
12373
12603
|
total: entries.length
|
|
12374
12604
|
};
|
|
12375
12605
|
};
|
|
12376
|
-
var
|
|
12606
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12377
12607
|
var renderVoiceOpsActionHistoryHTML = (report) => {
|
|
12378
|
-
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${
|
|
12608
|
+
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${escapeHtml16(entry.ok ? "success" : "error")}</span><strong>${escapeHtml16(entry.actionId)}</strong><p>${escapeHtml16(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</p>${entry.error ? `<p>${escapeHtml16(entry.error)}</p>` : ""}</article>`).join("");
|
|
12379
12609
|
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>`;
|
|
12380
12610
|
};
|
|
12381
12611
|
// src/platformCoverage.ts
|
|
12382
|
-
import { Elysia as
|
|
12612
|
+
import { Elysia as Elysia14 } from "elysia";
|
|
12383
12613
|
var buildVoicePlatformCoverageSummary = (input) => {
|
|
12384
12614
|
const coverage = input.coverage ?? [];
|
|
12385
12615
|
const ok = input.ok ?? (coverage.length > 0 && coverage.every((surface) => surface.status === "pass"));
|
|
@@ -12440,7 +12670,7 @@ var assertVoicePlatformCoverage = (summary, input = {}) => {
|
|
|
12440
12670
|
var normalizeCoverageSummary = (value) => ("status" in value) && ("total" in value) && ("coverage" in value) ? value : buildVoicePlatformCoverageSummary(value);
|
|
12441
12671
|
var createVoicePlatformCoverageRoutes = (options) => {
|
|
12442
12672
|
const path = options.path ?? "/api/voice/platform-coverage";
|
|
12443
|
-
const routes = new
|
|
12673
|
+
const routes = new Elysia14({
|
|
12444
12674
|
name: options.name ?? "absolutejs-voice-platform-coverage"
|
|
12445
12675
|
});
|
|
12446
12676
|
routes.get(path, async () => {
|
|
@@ -12451,8 +12681,238 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
12451
12681
|
});
|
|
12452
12682
|
return routes;
|
|
12453
12683
|
};
|
|
12684
|
+
// src/competitiveCoverage.ts
|
|
12685
|
+
import { Elysia as Elysia15 } from "elysia";
|
|
12686
|
+
var escapeHtml17 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12687
|
+
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
12688
|
+
var resolveSurfaceStatus = (surface) => {
|
|
12689
|
+
if (surface.status)
|
|
12690
|
+
return surface.status;
|
|
12691
|
+
if (surface.coverage === "missing")
|
|
12692
|
+
return "fail";
|
|
12693
|
+
if (surface.coverage === "partial")
|
|
12694
|
+
return "warn";
|
|
12695
|
+
if (surface.depth === "lag" && surface.coverage !== "intentional-gap")
|
|
12696
|
+
return "warn";
|
|
12697
|
+
if ((surface.evidence ?? []).some((evidence) => evidence.status === "fail")) {
|
|
12698
|
+
return "fail";
|
|
12699
|
+
}
|
|
12700
|
+
if ((surface.evidence ?? []).some((evidence) => evidence.status === "warn")) {
|
|
12701
|
+
return "warn";
|
|
12702
|
+
}
|
|
12703
|
+
return "pass";
|
|
12704
|
+
};
|
|
12705
|
+
var buildVoiceCompetitiveCoverageReport = (input) => {
|
|
12706
|
+
const surfaces = input.surfaces.map((surface) => ({
|
|
12707
|
+
...surface,
|
|
12708
|
+
status: resolveSurfaceStatus(surface)
|
|
12709
|
+
}));
|
|
12710
|
+
const issues = [];
|
|
12711
|
+
for (const surface of surfaces) {
|
|
12712
|
+
const evidence = surface.evidence ?? [];
|
|
12713
|
+
const missingRequiredEvidence = evidence.filter((item) => item.required && item.status !== "pass");
|
|
12714
|
+
for (const item of missingRequiredEvidence) {
|
|
12715
|
+
issues.push({
|
|
12716
|
+
code: "required-evidence-not-passing",
|
|
12717
|
+
message: `Required evidence is not passing: ${item.name}.`,
|
|
12718
|
+
severity: "error",
|
|
12719
|
+
surface: surface.surface
|
|
12720
|
+
});
|
|
12721
|
+
}
|
|
12722
|
+
if (surface.coverage === "missing") {
|
|
12723
|
+
issues.push({
|
|
12724
|
+
code: "surface-missing",
|
|
12725
|
+
message: `Competitive surface is missing: ${surface.surface}.`,
|
|
12726
|
+
severity: "error",
|
|
12727
|
+
surface: surface.surface
|
|
12728
|
+
});
|
|
12729
|
+
}
|
|
12730
|
+
if (surface.status === "warn") {
|
|
12731
|
+
issues.push({
|
|
12732
|
+
code: "surface-warning",
|
|
12733
|
+
message: `Competitive surface needs depth work: ${surface.surface}.`,
|
|
12734
|
+
severity: "warning",
|
|
12735
|
+
surface: surface.surface
|
|
12736
|
+
});
|
|
12737
|
+
}
|
|
12738
|
+
}
|
|
12739
|
+
const failed = surfaces.filter((surface) => surface.status === "fail").length;
|
|
12740
|
+
const warned = surfaces.filter((surface) => surface.status === "warn").length;
|
|
12741
|
+
const status = failed > 0 ? "fail" : warned > 0 ? "warn" : "pass";
|
|
12742
|
+
return {
|
|
12743
|
+
generatedAt: input.generatedAt ?? new Date().toISOString(),
|
|
12744
|
+
issues,
|
|
12745
|
+
marketCoverageEstimate: input.marketCoverageEstimate ?? "93-95%",
|
|
12746
|
+
notes: input.notes ?? [],
|
|
12747
|
+
ok: status !== "fail",
|
|
12748
|
+
source: input.source,
|
|
12749
|
+
status,
|
|
12750
|
+
summary: {
|
|
12751
|
+
advantage: surfaces.filter((surface) => surface.depth === "advantage").length,
|
|
12752
|
+
covered: surfaces.filter((surface) => surface.coverage === "covered").length,
|
|
12753
|
+
failed,
|
|
12754
|
+
intentionalGaps: surfaces.filter((surface) => surface.coverage === "intentional-gap").length,
|
|
12755
|
+
missing: surfaces.filter((surface) => surface.coverage === "missing").length,
|
|
12756
|
+
parity: surfaces.filter((surface) => surface.depth === "parity").length,
|
|
12757
|
+
passed: surfaces.filter((surface) => surface.status === "pass").length,
|
|
12758
|
+
surfaces: surfaces.length,
|
|
12759
|
+
warned
|
|
12760
|
+
},
|
|
12761
|
+
surfaces,
|
|
12762
|
+
vapiCoverageEstimate: input.vapiCoverageEstimate ?? "99.8%"
|
|
12763
|
+
};
|
|
12764
|
+
};
|
|
12765
|
+
var evaluateVoiceCompetitiveCoverage = (report, input = {}) => {
|
|
12766
|
+
const issues = [];
|
|
12767
|
+
const surfaces = report.surfaces.map((surface) => surface.surface).sort();
|
|
12768
|
+
const missing = report.summary.missing;
|
|
12769
|
+
const failed = report.summary.failed;
|
|
12770
|
+
const evidenceNames = new Set(report.surfaces.flatMap((surface) => (surface.evidence ?? []).map((evidence) => evidence.name)));
|
|
12771
|
+
if ((input.requirePass ?? false) && report.status !== "pass") {
|
|
12772
|
+
issues.push(`Expected competitive coverage to pass, found ${report.status}.`);
|
|
12773
|
+
}
|
|
12774
|
+
if (input.minSurfaces !== undefined && report.summary.surfaces < input.minSurfaces) {
|
|
12775
|
+
issues.push(`Expected at least ${String(input.minSurfaces)} competitive surfaces, found ${String(report.summary.surfaces)}.`);
|
|
12776
|
+
}
|
|
12777
|
+
if (input.minAdvantageSurfaces !== undefined && report.summary.advantage < input.minAdvantageSurfaces) {
|
|
12778
|
+
issues.push(`Expected at least ${String(input.minAdvantageSurfaces)} advantage surfaces, found ${String(report.summary.advantage)}.`);
|
|
12779
|
+
}
|
|
12780
|
+
if (input.maxFailedSurfaces !== undefined && failed > input.maxFailedSurfaces) {
|
|
12781
|
+
issues.push(`Expected at most ${String(input.maxFailedSurfaces)} failing competitive surfaces, found ${String(failed)}.`);
|
|
12782
|
+
}
|
|
12783
|
+
if (input.maxMissingSurfaces !== undefined && missing > input.maxMissingSurfaces) {
|
|
12784
|
+
issues.push(`Expected at most ${String(input.maxMissingSurfaces)} missing competitive surfaces, found ${String(missing)}.`);
|
|
12785
|
+
}
|
|
12786
|
+
for (const surface of input.requiredSurfaces ?? []) {
|
|
12787
|
+
if (!surfaces.includes(surface)) {
|
|
12788
|
+
issues.push(`Missing competitive surface: ${surface}.`);
|
|
12789
|
+
}
|
|
12790
|
+
}
|
|
12791
|
+
for (const evidence of input.requiredEvidence ?? []) {
|
|
12792
|
+
if (!evidenceNames.has(evidence)) {
|
|
12793
|
+
issues.push(`Missing competitive evidence: ${evidence}.`);
|
|
12794
|
+
}
|
|
12795
|
+
}
|
|
12796
|
+
if (input.requireOperationsRecordLinks) {
|
|
12797
|
+
for (const surface of report.surfaces) {
|
|
12798
|
+
if (surface.coverage !== "intentional-gap" && surface.operationsRecord !== "linked" && surface.operationsRecord !== "not-applicable") {
|
|
12799
|
+
issues.push(`Competitive surface does not have operations-record proof: ${surface.surface}.`);
|
|
12800
|
+
}
|
|
12801
|
+
}
|
|
12802
|
+
}
|
|
12803
|
+
if (input.requireReadinessGates) {
|
|
12804
|
+
for (const surface of report.surfaces) {
|
|
12805
|
+
if (surface.coverage !== "intentional-gap" && surface.readinessGate !== "present" && surface.readinessGate !== "not-applicable") {
|
|
12806
|
+
issues.push(`Competitive surface does not have readiness-gate proof: ${surface.surface}.`);
|
|
12807
|
+
}
|
|
12808
|
+
}
|
|
12809
|
+
}
|
|
12810
|
+
return {
|
|
12811
|
+
advantage: report.summary.advantage,
|
|
12812
|
+
failed,
|
|
12813
|
+
issues,
|
|
12814
|
+
missing,
|
|
12815
|
+
ok: issues.length === 0,
|
|
12816
|
+
status: report.status,
|
|
12817
|
+
surfaces,
|
|
12818
|
+
total: report.summary.surfaces
|
|
12819
|
+
};
|
|
12820
|
+
};
|
|
12821
|
+
var assertVoiceCompetitiveCoverage = (report, input = {}) => {
|
|
12822
|
+
const assertion = evaluateVoiceCompetitiveCoverage(report, input);
|
|
12823
|
+
if (!assertion.ok) {
|
|
12824
|
+
throw new Error(`Voice competitive coverage assertion failed: ${assertion.issues.join(" ")}`);
|
|
12825
|
+
}
|
|
12826
|
+
return assertion;
|
|
12827
|
+
};
|
|
12828
|
+
var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive Coverage") => [
|
|
12829
|
+
`# ${title}`,
|
|
12830
|
+
"",
|
|
12831
|
+
`- Status: ${report.status}`,
|
|
12832
|
+
`- Vapi-style coverage: ${report.vapiCoverageEstimate}`,
|
|
12833
|
+
`- Broader market coverage: ${report.marketCoverageEstimate}`,
|
|
12834
|
+
`- Surfaces: ${String(report.summary.surfaces)}`,
|
|
12835
|
+
`- Advantage surfaces: ${String(report.summary.advantage)}`,
|
|
12836
|
+
`- Parity surfaces: ${String(report.summary.parity)}`,
|
|
12837
|
+
`- Intentional gaps: ${String(report.summary.intentionalGaps)}`,
|
|
12838
|
+
"",
|
|
12839
|
+
"| Surface | Coverage | Depth | Status | Operations record | Readiness gate | Competitors | Next move |",
|
|
12840
|
+
"| --- | --- | --- | --- | --- | --- | --- | --- |",
|
|
12841
|
+
...report.surfaces.map((surface) => `| ${escapeMarkdown(surface.surface)} | ${surface.coverage} | ${surface.depth} | ${surface.status} | ${surface.operationsRecord ?? "unknown"} | ${surface.readinessGate ?? "unknown"} | ${escapeMarkdown((surface.competitors ?? []).join(", ") || "n/a")} | ${escapeMarkdown(surface.nextMove ?? surface.remainingGap ?? "none")} |`),
|
|
12842
|
+
"",
|
|
12843
|
+
"## Issues",
|
|
12844
|
+
"",
|
|
12845
|
+
...report.issues.length ? report.issues.map((issue) => `- ${issue.severity.toUpperCase()} ${issue.code}${issue.surface ? ` (${issue.surface})` : ""}: ${issue.message}`) : ["- None"],
|
|
12846
|
+
"",
|
|
12847
|
+
"## Notes",
|
|
12848
|
+
"",
|
|
12849
|
+
...report.notes.length ? report.notes.map((note) => `- ${note}`) : ["- None"]
|
|
12850
|
+
].join(`
|
|
12851
|
+
`);
|
|
12852
|
+
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
12853
|
+
const surfaceCards = report.surfaces.map((surface) => {
|
|
12854
|
+
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${escapeHtml17(item.name)}</strong>${item.kind ? ` <span>${escapeHtml17(item.kind)}</span>` : ""}${item.status ? ` <em>${escapeHtml17(item.status)}</em>` : ""}${item.href ? ` <a href="${escapeHtml17(item.href)}">open</a>` : ""}</li>`).join("");
|
|
12855
|
+
return `<article class="surface ${escapeHtml17(surface.status)} ${escapeHtml17(surface.depth)}">
|
|
12856
|
+
<header><div><p class="eyebrow">${escapeHtml17(surface.coverage)} \xB7 ${escapeHtml17(surface.depth)}</p><h2>${escapeHtml17(surface.surface)}</h2></div><strong>${escapeHtml17(surface.status)}</strong></header>
|
|
12857
|
+
<p>${escapeHtml17(surface.why)}</p>
|
|
12858
|
+
<dl>
|
|
12859
|
+
<div><dt>Competitors</dt><dd>${escapeHtml17((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
12860
|
+
<div><dt>Operations record</dt><dd>${escapeHtml17(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
12861
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml17(surface.readinessGate ?? "unknown")}</dd></div>
|
|
12862
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml17((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
12863
|
+
</dl>
|
|
12864
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml17(surface.remainingGap)}</p>` : ""}
|
|
12865
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml17(surface.nextMove)}</p>` : ""}
|
|
12866
|
+
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
12867
|
+
</article>`;
|
|
12868
|
+
}).join(`
|
|
12869
|
+
`);
|
|
12870
|
+
const issueList = report.issues.map((issue) => `<li class="${escapeHtml17(issue.severity)}"><strong>${escapeHtml17(issue.code)}</strong>${issue.surface ? ` ${escapeHtml17(issue.surface)}` : ""}: ${escapeHtml17(issue.message)}</li>`).join("");
|
|
12871
|
+
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:#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>${escapeHtml17(title)}</h1><p>Generated ${escapeHtml17(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 ${escapeHtml17(report.status)}</span><span class="pill">Vapi-style ${escapeHtml17(report.vapiCoverageEstimate)}</span><span class="pill">Market ${escapeHtml17(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>`;
|
|
12872
|
+
};
|
|
12873
|
+
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
12874
|
+
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
12875
|
+
const path = options.path ?? "/api/voice/competitive-coverage";
|
|
12876
|
+
const htmlPath = options.htmlPath ?? "/voice/competitive-coverage";
|
|
12877
|
+
const markdownPath = options.markdownPath ?? "/voice/competitive-coverage.md";
|
|
12878
|
+
const headers = options.headers ?? {};
|
|
12879
|
+
const title = options.title ?? "Voice Competitive Coverage";
|
|
12880
|
+
const report = async () => {
|
|
12881
|
+
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
12882
|
+
return normalizeCompetitiveCoverageReport(value);
|
|
12883
|
+
};
|
|
12884
|
+
const app = new Elysia15({
|
|
12885
|
+
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
12886
|
+
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
12887
|
+
headers: {
|
|
12888
|
+
"content-type": "application/json; charset=utf-8",
|
|
12889
|
+
...headers
|
|
12890
|
+
}
|
|
12891
|
+
}));
|
|
12892
|
+
if (htmlPath !== false) {
|
|
12893
|
+
app.get(htmlPath, async () => {
|
|
12894
|
+
const current = await report();
|
|
12895
|
+
const body = options.render ? await options.render(current) : renderVoiceCompetitiveCoverageHTML(current, title);
|
|
12896
|
+
return new Response(body, {
|
|
12897
|
+
headers: {
|
|
12898
|
+
"content-type": "text/html; charset=utf-8",
|
|
12899
|
+
...headers
|
|
12900
|
+
}
|
|
12901
|
+
});
|
|
12902
|
+
});
|
|
12903
|
+
}
|
|
12904
|
+
if (markdownPath !== false) {
|
|
12905
|
+
app.get(markdownPath, async () => new Response(renderVoiceCompetitiveCoverageMarkdown(await report(), title), {
|
|
12906
|
+
headers: {
|
|
12907
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
12908
|
+
...headers
|
|
12909
|
+
}
|
|
12910
|
+
}));
|
|
12911
|
+
}
|
|
12912
|
+
return app;
|
|
12913
|
+
};
|
|
12454
12914
|
// src/proofTrends.ts
|
|
12455
|
-
import { Elysia as
|
|
12915
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
12456
12916
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
12457
12917
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
12458
12918
|
var toTimeMs = (value) => {
|
|
@@ -12603,7 +13063,7 @@ var assertVoiceProofTrendEvidence = (report, input = {}) => {
|
|
|
12603
13063
|
};
|
|
12604
13064
|
var createVoiceProofTrendRoutes = (options) => {
|
|
12605
13065
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
12606
|
-
const routes = new
|
|
13066
|
+
const routes = new Elysia16({
|
|
12607
13067
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
12608
13068
|
});
|
|
12609
13069
|
routes.get(path, async () => {
|
|
@@ -12636,11 +13096,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
12636
13096
|
return `${days}d ${hours % 24}h`;
|
|
12637
13097
|
};
|
|
12638
13098
|
// src/providerDecisionTraces.ts
|
|
12639
|
-
import { Elysia as
|
|
13099
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
12640
13100
|
|
|
12641
13101
|
// src/resilienceRoutes.ts
|
|
12642
|
-
import { Elysia as
|
|
12643
|
-
var
|
|
13102
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
13103
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12644
13104
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
12645
13105
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
12646
13106
|
var getBoolean2 = (value) => value === true;
|
|
@@ -12788,13 +13248,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
12788
13248
|
};
|
|
12789
13249
|
var renderProviderCards = (title, providers) => {
|
|
12790
13250
|
if (providers.length === 0) {
|
|
12791
|
-
return `<p class="muted">No ${
|
|
13251
|
+
return `<p class="muted">No ${escapeHtml18(title)} provider health yet.</p>`;
|
|
12792
13252
|
}
|
|
12793
13253
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
12794
|
-
<article class="card provider ${
|
|
13254
|
+
<article class="card provider ${escapeHtml18(provider.status)}">
|
|
12795
13255
|
<div class="card-header">
|
|
12796
|
-
<strong>${
|
|
12797
|
-
<span>${
|
|
13256
|
+
<strong>${escapeHtml18(provider.provider)}</strong>
|
|
13257
|
+
<span>${escapeHtml18(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
12798
13258
|
</div>
|
|
12799
13259
|
<dl>
|
|
12800
13260
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -12803,7 +13263,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
12803
13263
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
12804
13264
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
12805
13265
|
</dl>
|
|
12806
|
-
${provider.lastError ? `<p class="muted">${
|
|
13266
|
+
${provider.lastError ? `<p class="muted">${escapeHtml18(provider.lastError)}</p>` : ""}
|
|
12807
13267
|
</article>
|
|
12808
13268
|
`).join("")}</div>`;
|
|
12809
13269
|
};
|
|
@@ -12812,24 +13272,24 @@ var renderTimeline2 = (events) => {
|
|
|
12812
13272
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
12813
13273
|
}
|
|
12814
13274
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
12815
|
-
<article class="card event ${
|
|
13275
|
+
<article class="card event ${escapeHtml18(event.status ?? "unknown")}">
|
|
12816
13276
|
<div class="card-header">
|
|
12817
|
-
<strong>${
|
|
13277
|
+
<strong>${escapeHtml18(event.kind.toUpperCase())} ${escapeHtml18(event.operation ?? "generate")}</strong>
|
|
12818
13278
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
12819
13279
|
</div>
|
|
12820
13280
|
<p>
|
|
12821
|
-
<span class="pill">${
|
|
12822
|
-
<span class="pill">provider: ${
|
|
12823
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
13281
|
+
<span class="pill">${escapeHtml18(event.status ?? "unknown")}</span>
|
|
13282
|
+
<span class="pill">provider: ${escapeHtml18(event.provider ?? "unknown")}</span>
|
|
13283
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml18(event.fallbackProvider)}</span>` : ""}
|
|
12824
13284
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
12825
13285
|
</p>
|
|
12826
13286
|
<dl>
|
|
12827
13287
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
12828
13288
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
12829
13289
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
12830
|
-
<div><dt>Session</dt><dd>${
|
|
13290
|
+
<div><dt>Session</dt><dd>${escapeHtml18(event.sessionId)}</dd></div>
|
|
12831
13291
|
</dl>
|
|
12832
|
-
${event.error ? `<p class="muted">${
|
|
13292
|
+
${event.error ? `<p class="muted">${escapeHtml18(event.error)}</p>` : ""}
|
|
12833
13293
|
</article>
|
|
12834
13294
|
`).join("")}</div>`;
|
|
12835
13295
|
};
|
|
@@ -12839,9 +13299,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
12839
13299
|
const status = latest?.status ?? "idle";
|
|
12840
13300
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
12841
13301
|
return `<div>
|
|
12842
|
-
<dt>${
|
|
12843
|
-
<dd>${
|
|
12844
|
-
<small>${
|
|
13302
|
+
<dt>${escapeHtml18(kind.toUpperCase())}</dt>
|
|
13303
|
+
<dd>${escapeHtml18(provider)}${escapeHtml18(fallback)}</dd>
|
|
13304
|
+
<small>${escapeHtml18(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
|
|
12845
13305
|
</div>`;
|
|
12846
13306
|
};
|
|
12847
13307
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -12849,10 +13309,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
12849
13309
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
12850
13310
|
}
|
|
12851
13311
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
12852
|
-
<article class="card session ${
|
|
13312
|
+
<article class="card session ${escapeHtml18(session.status)}">
|
|
12853
13313
|
<div class="card-header">
|
|
12854
|
-
<strong>${
|
|
12855
|
-
<span>${
|
|
13314
|
+
<strong>${escapeHtml18(session.sessionId)}</strong>
|
|
13315
|
+
<span>${escapeHtml18(session.status)}</span>
|
|
12856
13316
|
</div>
|
|
12857
13317
|
<p>
|
|
12858
13318
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -12879,21 +13339,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
12879
13339
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
12880
13340
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
12881
13341
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
12882
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
12883
|
-
<p class="muted">${
|
|
13342
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml18(pathPrefix)}">
|
|
13343
|
+
<p class="muted">${escapeHtml18(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
12884
13344
|
<div class="simulate-actions">
|
|
12885
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
12886
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
13345
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml18(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml18(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
13346
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml18(provider.provider)}">Mark ${escapeHtml18(provider.provider)} recovered</button>`).join("")}
|
|
12887
13347
|
</div>
|
|
12888
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
13348
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml18(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
12889
13349
|
<pre class="simulate-output" hidden></pre>
|
|
12890
13350
|
</div>`;
|
|
12891
13351
|
};
|
|
12892
13352
|
var renderVoiceResilienceHTML = (input) => {
|
|
12893
13353
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
12894
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
12895
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
12896
|
-
const snippet =
|
|
13354
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml18(kind)}: ${String(count)}</span>`).join("");
|
|
13355
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml18(link.href)}">${escapeHtml18(link.label)}</a>`).join(" \xB7 ") : "";
|
|
13356
|
+
const snippet = escapeHtml18(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
12897
13357
|
kind: 'stt',
|
|
12898
13358
|
providers: ['deepgram', 'assemblyai'],
|
|
12899
13359
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -12931,7 +13391,7 @@ app.use(
|
|
|
12931
13391
|
<head>
|
|
12932
13392
|
<meta charset="utf-8" />
|
|
12933
13393
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12934
|
-
<title>${
|
|
13394
|
+
<title>${escapeHtml18(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
12935
13395
|
<style>
|
|
12936
13396
|
:root { color-scheme: dark; }
|
|
12937
13397
|
body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
|
|
@@ -13083,7 +13543,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
13083
13543
|
};
|
|
13084
13544
|
var createVoiceResilienceRoutes = (options) => {
|
|
13085
13545
|
const path = options.path ?? "/resilience";
|
|
13086
|
-
const routes = new
|
|
13546
|
+
const routes = new Elysia17({
|
|
13087
13547
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
13088
13548
|
}).get(path, async () => {
|
|
13089
13549
|
const events = await options.store.list();
|
|
@@ -13124,7 +13584,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
13124
13584
|
};
|
|
13125
13585
|
|
|
13126
13586
|
// src/providerDecisionTraces.ts
|
|
13127
|
-
var
|
|
13587
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13128
13588
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
13129
13589
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
13130
13590
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -13365,7 +13825,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
13365
13825
|
<head>
|
|
13366
13826
|
<meta charset="utf-8" />
|
|
13367
13827
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
13368
|
-
<title>${
|
|
13828
|
+
<title>${escapeHtml19(title)}</title>
|
|
13369
13829
|
<style>
|
|
13370
13830
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
13371
13831
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -13379,8 +13839,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
13379
13839
|
</head>
|
|
13380
13840
|
<body>
|
|
13381
13841
|
<main>
|
|
13382
|
-
<p class="status ${report.status}">${
|
|
13383
|
-
<h1>${
|
|
13842
|
+
<p class="status ${report.status}">${escapeHtml19(report.status)}</p>
|
|
13843
|
+
<h1>${escapeHtml19(title)}</h1>
|
|
13384
13844
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
13385
13845
|
<section class="grid">
|
|
13386
13846
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -13391,10 +13851,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
13391
13851
|
</section>
|
|
13392
13852
|
<section class="surfaces">
|
|
13393
13853
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
13394
|
-
<header><strong>${
|
|
13854
|
+
<header><strong>${escapeHtml19(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml19(surface.status)}</span></header>
|
|
13395
13855
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
13396
|
-
<p class="muted">Providers: ${
|
|
13397
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
13856
|
+
<p class="muted">Providers: ${escapeHtml19(surface.providers.join(", ") || "none")}</p>
|
|
13857
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml19(reason)}</code>`).join(" ")}</p>
|
|
13398
13858
|
</article>`).join(`
|
|
13399
13859
|
`)}
|
|
13400
13860
|
</section>
|
|
@@ -13408,7 +13868,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
13408
13868
|
const headers = options.headers ?? {};
|
|
13409
13869
|
const title = options.title ?? "Provider Decision Traces";
|
|
13410
13870
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
13411
|
-
const app = new
|
|
13871
|
+
const app = new Elysia18({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
13412
13872
|
headers: {
|
|
13413
13873
|
"content-type": "application/json; charset=utf-8",
|
|
13414
13874
|
...headers
|
|
@@ -13436,7 +13896,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
13436
13896
|
return app;
|
|
13437
13897
|
};
|
|
13438
13898
|
// src/sloCalibration.ts
|
|
13439
|
-
import { Elysia as
|
|
13899
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
13440
13900
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
13441
13901
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
13442
13902
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -13615,8 +14075,8 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
13615
14075
|
status: profile.status
|
|
13616
14076
|
};
|
|
13617
14077
|
};
|
|
13618
|
-
var
|
|
13619
|
-
var
|
|
14078
|
+
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
14079
|
+
var escapeHtml20 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13620
14080
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
13621
14081
|
var readinessThresholdRows = (report) => [
|
|
13622
14082
|
{
|
|
@@ -13661,7 +14121,7 @@ var readinessThresholdRows = (report) => [
|
|
|
13661
14121
|
}
|
|
13662
14122
|
];
|
|
13663
14123
|
var renderVoiceSloCalibrationMarkdown = (report, options = {}) => {
|
|
13664
|
-
const rows = Object.values(report.thresholds).map((threshold) => `| ${
|
|
14124
|
+
const rows = Object.values(report.thresholds).map((threshold) => `| ${escapeMarkdown2(threshold.metric)} | ${threshold.status} | ${threshold.samples} | ${threshold.baselineP95Ms ?? "n/a"} | ${threshold.warnAfterMs ?? "n/a"} | ${threshold.failAfterMs ?? "n/a"} |`).join(`
|
|
13665
14125
|
`);
|
|
13666
14126
|
return `# ${options.title ?? "Voice SLO Calibration"}
|
|
13667
14127
|
|
|
@@ -13682,7 +14142,7 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
13682
14142
|
`;
|
|
13683
14143
|
};
|
|
13684
14144
|
var renderVoiceSloReadinessThresholdMarkdown = (report, options = {}) => {
|
|
13685
|
-
const rows = readinessThresholdRows(report).map((row) => `| ${
|
|
14145
|
+
const rows = readinessThresholdRows(report).map((row) => `| ${escapeMarkdown2(row.control)} | ${formatMs(row.value)} | ${escapeMarkdown2(row.usedBy)} |`).join(`
|
|
13686
14146
|
`);
|
|
13687
14147
|
return `# ${options.title ?? "Calibration -> Active Readiness Gate"}
|
|
13688
14148
|
|
|
@@ -13707,15 +14167,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
13707
14167
|
};
|
|
13708
14168
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
13709
14169
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
13710
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
13711
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
13712
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
13713
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
14170
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml20(row.control)}</td><td>${escapeHtml20(formatMs(row.value))}</td><td>${escapeHtml20(row.usedBy)}</td></tr>`).join("");
|
|
14171
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml20(issue)}</li>`).join("");
|
|
14172
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml20(source)}</code></li>`).join("");
|
|
14173
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml20(title)}</title><style>body{background:#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>${escapeHtml20(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">${escapeHtml20(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml20(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml20(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml20(formatMs(report.bargeIn.thresholdMs))}</div></section><h2>Active Readiness Thresholds</h2><table><thead><tr><th>Threshold</th><th>Active value</th><th>Used by</th></tr></thead><tbody>${rows}</tbody></table><h2>Sources</h2><ul>${sources}</ul><h2>Issues</h2><ul>${issues}</ul></main></body></html>`;
|
|
13714
14174
|
};
|
|
13715
14175
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
13716
14176
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
13717
14177
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
13718
|
-
const routes = new
|
|
14178
|
+
const routes = new Elysia19({
|
|
13719
14179
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
13720
14180
|
});
|
|
13721
14181
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -13739,7 +14199,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
13739
14199
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
13740
14200
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
13741
14201
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
13742
|
-
const routes = new
|
|
14202
|
+
const routes = new Elysia19({
|
|
13743
14203
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
13744
14204
|
});
|
|
13745
14205
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -13773,7 +14233,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
13773
14233
|
return routes;
|
|
13774
14234
|
};
|
|
13775
14235
|
// src/liveOps.ts
|
|
13776
|
-
import { Elysia as
|
|
14236
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
13777
14237
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
13778
14238
|
"assign",
|
|
13779
14239
|
"create-task",
|
|
@@ -14083,7 +14543,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
14083
14543
|
const controller = createVoiceLiveOpsController(options);
|
|
14084
14544
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
14085
14545
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
14086
|
-
return new
|
|
14546
|
+
return new Elysia20({
|
|
14087
14547
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
14088
14548
|
}).post(path, async ({ request, set }) => {
|
|
14089
14549
|
try {
|
|
@@ -14105,15 +14565,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
14105
14565
|
});
|
|
14106
14566
|
};
|
|
14107
14567
|
// src/deliveryRuntime.ts
|
|
14108
|
-
import { Elysia as
|
|
14568
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14109
14569
|
import { mkdir } from "fs/promises";
|
|
14110
14570
|
import { dirname, join } from "path";
|
|
14111
|
-
var
|
|
14571
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14112
14572
|
var renderSummaryCard = (label, summary) => {
|
|
14113
14573
|
if (!summary) {
|
|
14114
|
-
return `<article><span>${
|
|
14574
|
+
return `<article><span>${escapeHtml21(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
14115
14575
|
}
|
|
14116
|
-
return `<article><span>${
|
|
14576
|
+
return `<article><span>${escapeHtml21(label)}</span><strong>${String(summary.delivered)}/${String(summary.total)}</strong><p class="muted">${String(summary.pending)} pending · ${String(summary.failed)} failed · ${String(summary.deadLettered)} dead-lettered</p></article>`;
|
|
14117
14577
|
};
|
|
14118
14578
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
14119
14579
|
audit: leases,
|
|
@@ -14324,9 +14784,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
14324
14784
|
});
|
|
14325
14785
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
14326
14786
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
14327
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
14328
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
14329
|
-
const snippet =
|
|
14787
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml21(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
14788
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml21(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
14789
|
+
const snippet = escapeHtml21(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
14330
14790
|
createVoiceDeliveryRuntimePresetConfig({
|
|
14331
14791
|
audit: {
|
|
14332
14792
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -14352,14 +14812,14 @@ app.use(
|
|
|
14352
14812
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
14353
14813
|
})
|
|
14354
14814
|
);`);
|
|
14355
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
14815
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml21(title)}</title><style>body{background:#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>${escapeHtml21(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 ${escapeHtml21(new Date(report.checkedAt).toLocaleString())}</p><div class="actions">${tickForm}${requeueForm}</div></section><section class="grid">${renderSummaryCard("Audit", report.summary.audit)}${renderSummaryCard("Trace", report.summary.trace)}</section><section class="card primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceDeliveryRuntimeRoutes(...)</code> builds this control plane</h2><p>Own the audit and trace delivery queues in your app, mount one runtime route group, and pass the same runtime into production readiness so failed or dead-lettered exports block deploys.</p><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
14356
14816
|
};
|
|
14357
14817
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
14358
14818
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
14359
14819
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
14360
14820
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
14361
14821
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
14362
|
-
const routes = new
|
|
14822
|
+
const routes = new Elysia21({
|
|
14363
14823
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
14364
14824
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
14365
14825
|
if (tickPath !== false) {
|
|
@@ -14395,7 +14855,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
14395
14855
|
return routes;
|
|
14396
14856
|
};
|
|
14397
14857
|
// src/dataControl.ts
|
|
14398
|
-
import { Elysia as
|
|
14858
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
14399
14859
|
var voiceComplianceRedactionDefaults = {
|
|
14400
14860
|
keys: [
|
|
14401
14861
|
"apiKey",
|
|
@@ -14634,7 +15094,7 @@ var parseRetentionScopes = (value) => {
|
|
|
14634
15094
|
const allowed = new Set(allRetentionScopes);
|
|
14635
15095
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
14636
15096
|
};
|
|
14637
|
-
var
|
|
15097
|
+
var escapeHtml22 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14638
15098
|
var buildStorageSurfaces = (options) => [
|
|
14639
15099
|
{
|
|
14640
15100
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -14871,12 +15331,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
14871
15331
|
zeroRetentionAvailable: true
|
|
14872
15332
|
};
|
|
14873
15333
|
};
|
|
14874
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
15334
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml22(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml22(scope.skippedReason ?? "")}</td><td><code>${escapeHtml22(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
14875
15335
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
14876
15336
|
const title = options.title ?? "Voice Data Control";
|
|
14877
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
14878
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
14879
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15337
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml22(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml22(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
15338
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml22(key.name)}</td><td><code>${escapeHtml22(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml22(key.recommendation)}</td></tr>`).join("");
|
|
15339
|
+
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: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>${escapeHtml22(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
|
|
14880
15340
|
};
|
|
14881
15341
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
14882
15342
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -14934,7 +15394,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
14934
15394
|
var createVoiceDataControlRoutes = (options) => {
|
|
14935
15395
|
const path = options.path ?? "/data-control";
|
|
14936
15396
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
14937
|
-
const routes = new
|
|
15397
|
+
const routes = new Elysia22({
|
|
14938
15398
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
14939
15399
|
});
|
|
14940
15400
|
routes.get(path, async ({ query }) => {
|
|
@@ -15010,16 +15470,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
15010
15470
|
return routes;
|
|
15011
15471
|
};
|
|
15012
15472
|
// src/evalRoutes.ts
|
|
15013
|
-
import { Elysia as
|
|
15473
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
15014
15474
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
15015
15475
|
import { dirname as dirname2 } from "path";
|
|
15016
15476
|
|
|
15017
15477
|
// src/qualityRoutes.ts
|
|
15018
|
-
import { Elysia as
|
|
15478
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
15019
15479
|
|
|
15020
15480
|
// src/handoffHealth.ts
|
|
15021
|
-
import { Elysia as
|
|
15022
|
-
var
|
|
15481
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15482
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15023
15483
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
15024
15484
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
15025
15485
|
var increment3 = (record, key) => {
|
|
@@ -15137,10 +15597,10 @@ var renderActionSummary = (summary) => {
|
|
|
15137
15597
|
return [
|
|
15138
15598
|
'<section class="voice-handoff-health-columns">',
|
|
15139
15599
|
"<article><h3>Actions</h3>",
|
|
15140
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
15600
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml23(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
15141
15601
|
"</article>",
|
|
15142
15602
|
"<article><h3>Adapters</h3>",
|
|
15143
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
15603
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml23(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
15144
15604
|
"</article>",
|
|
15145
15605
|
"</section>"
|
|
15146
15606
|
].join("");
|
|
@@ -15154,22 +15614,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
15154
15614
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
15155
15615
|
'<div class="voice-handoff-health-events">',
|
|
15156
15616
|
...summary.events.map((event) => [
|
|
15157
|
-
`<article class="${
|
|
15617
|
+
`<article class="${escapeHtml23(event.status)}">`,
|
|
15158
15618
|
'<div class="voice-handoff-health-event-header">',
|
|
15159
|
-
`<strong>${
|
|
15160
|
-
`<span>${
|
|
15619
|
+
`<strong>${escapeHtml23(event.action ?? "handoff")}</strong>`,
|
|
15620
|
+
`<span>${escapeHtml23(event.status)}</span>`,
|
|
15161
15621
|
"</div>",
|
|
15162
|
-
`<p><small>${
|
|
15163
|
-
event.target ? `<p>Target: ${
|
|
15164
|
-
event.reason ? `<p>Reason: ${
|
|
15622
|
+
`<p><small>${escapeHtml23(event.sessionId)}</small></p>`,
|
|
15623
|
+
event.target ? `<p>Target: ${escapeHtml23(event.target)}</p>` : "",
|
|
15624
|
+
event.reason ? `<p>Reason: ${escapeHtml23(event.reason)}</p>` : "",
|
|
15165
15625
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
15166
15626
|
"<li>",
|
|
15167
|
-
`${
|
|
15168
|
-
delivery.deliveredTo ? ` to ${
|
|
15169
|
-
delivery.error ? ` (${
|
|
15627
|
+
`${escapeHtml23(delivery.adapterId)}: ${escapeHtml23(delivery.status)}`,
|
|
15628
|
+
delivery.deliveredTo ? ` to ${escapeHtml23(delivery.deliveredTo)}` : "",
|
|
15629
|
+
delivery.error ? ` (${escapeHtml23(delivery.error)})` : "",
|
|
15170
15630
|
"</li>"
|
|
15171
15631
|
].join("")).join("")}</ul>` : "",
|
|
15172
|
-
event.replayHref ? `<p><a href="${
|
|
15632
|
+
event.replayHref ? `<p><a href="${escapeHtml23(event.replayHref)}">Open replay</a></p>` : "",
|
|
15173
15633
|
"</article>"
|
|
15174
15634
|
].join("")),
|
|
15175
15635
|
"</div>"
|
|
@@ -15201,7 +15661,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
15201
15661
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
15202
15662
|
const path = options.path ?? "/api/voice-handoffs";
|
|
15203
15663
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
15204
|
-
const routes = new
|
|
15664
|
+
const routes = new Elysia23({
|
|
15205
15665
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
15206
15666
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
15207
15667
|
if (htmlPath) {
|
|
@@ -15322,17 +15782,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
15322
15782
|
thresholds
|
|
15323
15783
|
};
|
|
15324
15784
|
};
|
|
15325
|
-
var
|
|
15785
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15326
15786
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
15327
15787
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
15328
15788
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
15329
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
15330
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15789
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml24(metric.label)}</td><td>${escapeHtml24(formatMetricValue(metric))}</td><td>${escapeHtml24(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml24(key)}</code></td></tr>`).join("");
|
|
15790
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join("")}</nav>` : "";
|
|
15331
15791
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>AbsoluteJS Voice Quality</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}nav{display:flex;flex-wrap:wrap;gap:.5rem;margin:0 0 1.25rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;padding:.35rem .75rem;font-weight:800}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}table{border-collapse:collapse;width:100%;background:white;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}.pass td{border-left:4px solid #16a34a}.fail td{border-left:4px solid #dc2626}code{background:#f3f4f6;padding:.15rem .3rem;border-radius:.3rem}</style></head><body><main>${links}<h1>Voice quality gates</h1><p class="status ${report.status}">${report.status}</p><p>${report.eventCount} event(s) checked.</p><table><thead><tr><th>Metric</th><th>Actual</th><th>Threshold</th><th>Status</th><th>Key</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
15332
15792
|
};
|
|
15333
15793
|
var createVoiceQualityRoutes = (options) => {
|
|
15334
15794
|
const path = options.path ?? "/quality";
|
|
15335
|
-
const routes = new
|
|
15795
|
+
const routes = new Elysia24({
|
|
15336
15796
|
name: options.name ?? "absolutejs-voice-quality"
|
|
15337
15797
|
});
|
|
15338
15798
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -15361,7 +15821,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
15361
15821
|
};
|
|
15362
15822
|
|
|
15363
15823
|
// src/evalRoutes.ts
|
|
15364
|
-
var
|
|
15824
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15365
15825
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
15366
15826
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
15367
15827
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -15683,7 +16143,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
15683
16143
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
15684
16144
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
15685
16145
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
15686
|
-
const snippet =
|
|
16146
|
+
const snippet = escapeHtml25(`app.use(
|
|
15687
16147
|
createVoiceEvalRoutes({
|
|
15688
16148
|
path: '/evals',
|
|
15689
16149
|
store: traceStore,
|
|
@@ -15704,48 +16164,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
15704
16164
|
};
|
|
15705
16165
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
15706
16166
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
15707
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15708
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
16167
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml25(link.href)}">${escapeHtml25(link.label)}</a>`).join("")}</nav>` : "";
|
|
16168
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml25(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
|
|
15709
16169
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
15710
16170
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
15711
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
15712
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
16171
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml25(session.operationsRecordHref)}">${escapeHtml25(session.sessionId)}</a>` : escapeHtml25(session.sessionId);
|
|
16172
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml25(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml25(formatTime(session.endedAt))}</td><td>${escapeHtml25(failedMetrics || "none")}</td></tr>`;
|
|
15713
16173
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
15714
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16174
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
|
|
15715
16175
|
};
|
|
15716
16176
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
15717
16177
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
15718
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
15719
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
15720
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
15721
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
15722
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16178
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml25(link.href)}">${escapeHtml25(link.label)}</a>`).join("")}</nav>` : "";
|
|
16179
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml25(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
16180
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml25(id)}</li>`).join("") : "<li>none</li>";
|
|
16181
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml25(id)}</li>`).join("") : "<li>none</li>";
|
|
16182
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml25(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml25(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>${escapeHtml25(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
|
|
15723
16183
|
};
|
|
15724
16184
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
15725
16185
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
15726
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16186
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml25(link.href)}">${escapeHtml25(link.label)}</a>`).join("")}</nav>` : "";
|
|
15727
16187
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
15728
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
16188
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml25(issue)}</li>`).join("")}</ul>` : "";
|
|
15729
16189
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
15730
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
15731
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
16190
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml25(session.operationsRecordHref)}">${escapeHtml25(session.sessionId)}</a>` : escapeHtml25(session.sessionId);
|
|
16191
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml25(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml25(session.issues.join(", ") || "none")}</td></tr>`;
|
|
15732
16192
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
15733
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
16193
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml25(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml25(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
|
|
15734
16194
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
15735
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16195
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
|
|
15736
16196
|
};
|
|
15737
16197
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
15738
16198
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
15739
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
16199
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml25(link.href)}">${escapeHtml25(link.label)}</a>`).join("")}</nav>` : "";
|
|
15740
16200
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
15741
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
15742
|
-
return `<section class="${fixture.status}"><h2>${
|
|
16201
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml25(scenario.label)}</td><td>${escapeHtml25(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml25([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
16202
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml25(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml25(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
|
|
15743
16203
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
15744
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16204
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
|
|
15745
16205
|
};
|
|
15746
16206
|
var createVoiceEvalRoutes = (options) => {
|
|
15747
16207
|
const path = options.path ?? "/evals";
|
|
15748
|
-
const routes = new
|
|
16208
|
+
const routes = new Elysia25({
|
|
15749
16209
|
name: options.name ?? "absolutejs-voice-evals"
|
|
15750
16210
|
});
|
|
15751
16211
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -15882,11 +16342,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
15882
16342
|
return routes;
|
|
15883
16343
|
};
|
|
15884
16344
|
// src/simulationSuite.ts
|
|
15885
|
-
import { Elysia as
|
|
16345
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
15886
16346
|
|
|
15887
16347
|
// src/outcomeContract.ts
|
|
15888
|
-
import { Elysia as
|
|
15889
|
-
var
|
|
16348
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16349
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15890
16350
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
15891
16351
|
if (value === false) {
|
|
15892
16352
|
return;
|
|
@@ -16097,13 +16557,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
16097
16557
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
16098
16558
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
16099
16559
|
const contracts = report.contracts.map((contract) => {
|
|
16100
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
16560
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml26(href)}">${escapeHtml26(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
16101
16561
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
16102
16562
|
<div class="contract-header">
|
|
16103
16563
|
<div>
|
|
16104
|
-
<p class="eyebrow">${
|
|
16105
|
-
<h2>${
|
|
16106
|
-
${contract.description ? `<p>${
|
|
16564
|
+
<p class="eyebrow">${escapeHtml26(contract.contractId)}</p>
|
|
16565
|
+
<h2>${escapeHtml26(contract.label ?? contract.contractId)}</h2>
|
|
16566
|
+
${contract.description ? `<p>${escapeHtml26(contract.description)}</p>` : ""}
|
|
16107
16567
|
${sessionLinks}
|
|
16108
16568
|
</div>
|
|
16109
16569
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -16115,10 +16575,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
16115
16575
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
16116
16576
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
16117
16577
|
</div>
|
|
16118
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
16578
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml26(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
16119
16579
|
</section>`;
|
|
16120
16580
|
}).join("");
|
|
16121
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
16581
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml26(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml26(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
|
|
16122
16582
|
};
|
|
16123
16583
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
16124
16584
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -16134,7 +16594,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
16134
16594
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
16135
16595
|
const path = options.path ?? "/api/outcome-contracts";
|
|
16136
16596
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16137
|
-
const routes = new
|
|
16597
|
+
const routes = new Elysia26({
|
|
16138
16598
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
16139
16599
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
16140
16600
|
if (htmlPath) {
|
|
@@ -16144,7 +16604,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
16144
16604
|
};
|
|
16145
16605
|
|
|
16146
16606
|
// src/toolContract.ts
|
|
16147
|
-
import { Elysia as
|
|
16607
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
16148
16608
|
|
|
16149
16609
|
// src/toolRuntime.ts
|
|
16150
16610
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -16353,7 +16813,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
16353
16813
|
});
|
|
16354
16814
|
var defaultApi = {};
|
|
16355
16815
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
16356
|
-
var
|
|
16816
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16357
16817
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
16358
16818
|
if (value === false) {
|
|
16359
16819
|
return;
|
|
@@ -16602,7 +17062,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
16602
17062
|
};
|
|
16603
17063
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
16604
17064
|
const title = options.title ?? "Voice Tool Contracts";
|
|
16605
|
-
const snippet =
|
|
17065
|
+
const snippet = escapeHtml27(`app.use(
|
|
16606
17066
|
createVoiceToolContractRoutes({
|
|
16607
17067
|
htmlPath: '/tool-contracts',
|
|
16608
17068
|
path: '/api/tool-contracts',
|
|
@@ -16628,20 +17088,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
16628
17088
|
);`);
|
|
16629
17089
|
const contracts = report.contracts.map((contract) => {
|
|
16630
17090
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
16631
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
17091
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml27(testCase.operationsRecordHref)}">${escapeHtml27(testCase.label ?? testCase.caseId)}</a>` : escapeHtml27(testCase.label ?? testCase.caseId)}</td>
|
|
16632
17092
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
16633
|
-
<td>${
|
|
16634
|
-
<td>${
|
|
17093
|
+
<td>${escapeHtml27(testCase.status)}</td>
|
|
17094
|
+
<td>${escapeHtml27(testCase.sessionId)}</td>
|
|
16635
17095
|
<td>${String(testCase.attempts)}</td>
|
|
16636
17096
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
16637
17097
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
16638
|
-
<td>${
|
|
17098
|
+
<td>${escapeHtml27(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
16639
17099
|
</tr>`).join("");
|
|
16640
17100
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
16641
17101
|
<div class="contract-header">
|
|
16642
17102
|
<div>
|
|
16643
|
-
<p class="eyebrow">${
|
|
16644
|
-
<h2>${
|
|
17103
|
+
<p class="eyebrow">${escapeHtml27(contract.toolName)}</p>
|
|
17104
|
+
<h2>${escapeHtml27(contract.label ?? contract.contractId)}</h2>
|
|
16645
17105
|
</div>
|
|
16646
17106
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
16647
17107
|
</div>
|
|
@@ -16651,7 +17111,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
16651
17111
|
</table>
|
|
16652
17112
|
</section>`;
|
|
16653
17113
|
}).join("");
|
|
16654
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17114
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml27(title)}</title><style>body{background:#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>${escapeHtml27(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml27(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
|
|
16655
17115
|
};
|
|
16656
17116
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
16657
17117
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -16668,7 +17128,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
16668
17128
|
var createVoiceToolContractRoutes = (options) => {
|
|
16669
17129
|
const path = options.path ?? "/api/tool-contracts";
|
|
16670
17130
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
16671
|
-
const routes = new
|
|
17131
|
+
const routes = new Elysia27({
|
|
16672
17132
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
16673
17133
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
16674
17134
|
if (htmlPath) {
|
|
@@ -16678,7 +17138,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
16678
17138
|
};
|
|
16679
17139
|
|
|
16680
17140
|
// src/simulationSuite.ts
|
|
16681
|
-
var
|
|
17141
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16682
17142
|
var summarizeSection = (report) => ({
|
|
16683
17143
|
failed: report.failed,
|
|
16684
17144
|
passed: report.passed,
|
|
@@ -16874,15 +17334,15 @@ var renderSection = (label, summary) => {
|
|
|
16874
17334
|
if (!summary) {
|
|
16875
17335
|
return "";
|
|
16876
17336
|
}
|
|
16877
|
-
return `<article class="${
|
|
17337
|
+
return `<article class="${escapeHtml28(summary.status)}"><span>${escapeHtml28(label)}</span><strong>${escapeHtml28(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
16878
17338
|
};
|
|
16879
17339
|
var renderAction = (action) => {
|
|
16880
|
-
const content = `<strong>${
|
|
16881
|
-
return action.href ? `<a class="action" href="${
|
|
17340
|
+
const content = `<strong>${escapeHtml28(action.label)}</strong><p>${escapeHtml28(action.description)}</p><span>${escapeHtml28(action.section)} / ${escapeHtml28(action.severity)}</span>`;
|
|
17341
|
+
return action.href ? `<a class="action" href="${escapeHtml28(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
16882
17342
|
};
|
|
16883
17343
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
16884
17344
|
const title = options.title ?? "Voice Simulation Suite";
|
|
16885
|
-
const snippet =
|
|
17345
|
+
const snippet = escapeHtml28(`app.use(
|
|
16886
17346
|
createVoiceSimulationSuiteRoutes({
|
|
16887
17347
|
htmlPath: '/voice/simulations',
|
|
16888
17348
|
path: '/api/voice/simulations',
|
|
@@ -16915,12 +17375,12 @@ app.use(
|
|
|
16915
17375
|
store: traceStore
|
|
16916
17376
|
})
|
|
16917
17377
|
);`);
|
|
16918
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17378
|
+
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:#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>${escapeHtml28(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml28(report.status)}">Status: ${escapeHtml28(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>${escapeHtml28(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
16919
17379
|
};
|
|
16920
17380
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
16921
17381
|
const path = options.path ?? "/api/voice/simulations";
|
|
16922
17382
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
16923
|
-
const app = new
|
|
17383
|
+
const app = new Elysia28({
|
|
16924
17384
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
16925
17385
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
16926
17386
|
if (htmlPath) {
|
|
@@ -17232,9 +17692,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
17232
17692
|
};
|
|
17233
17693
|
};
|
|
17234
17694
|
// src/sessionReplay.ts
|
|
17235
|
-
import { Elysia as
|
|
17695
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17236
17696
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
17237
|
-
var
|
|
17697
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17238
17698
|
var increment4 = (record, key) => {
|
|
17239
17699
|
record[key] = (record[key] ?? 0) + 1;
|
|
17240
17700
|
};
|
|
@@ -17428,10 +17888,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
17428
17888
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
17429
17889
|
'<div class="voice-sessions-list">',
|
|
17430
17890
|
...sessions.map((session) => [
|
|
17431
|
-
`<article class="voice-session-card ${
|
|
17891
|
+
`<article class="voice-session-card ${escapeHtml29(session.status)}">`,
|
|
17432
17892
|
'<div class="voice-session-card-header">',
|
|
17433
|
-
`<strong>${
|
|
17434
|
-
`<span>${
|
|
17893
|
+
`<strong>${escapeHtml29(session.sessionId)}</strong>`,
|
|
17894
|
+
`<span>${escapeHtml29(session.status)}</span>`,
|
|
17435
17895
|
"</div>",
|
|
17436
17896
|
"<dl>",
|
|
17437
17897
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -17439,9 +17899,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
17439
17899
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
17440
17900
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
17441
17901
|
"</dl>",
|
|
17442
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
17443
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
17444
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
17902
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml29(session.latestOutcome)}</p>` : "",
|
|
17903
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml29).join(", ")}</p>` : "",
|
|
17904
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml29(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml29(session.replayHref)}">Open replay</a></p>` : "",
|
|
17445
17905
|
"</article>"
|
|
17446
17906
|
].join("")),
|
|
17447
17907
|
"</div>"
|
|
@@ -17472,7 +17932,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
17472
17932
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
17473
17933
|
const path = options.path ?? "/api/voice-sessions";
|
|
17474
17934
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17475
|
-
const routes = new
|
|
17935
|
+
const routes = new Elysia29({
|
|
17476
17936
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
17477
17937
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
17478
17938
|
if (htmlPath) {
|
|
@@ -17500,7 +17960,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
17500
17960
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
17501
17961
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
17502
17962
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17503
|
-
const routes = new
|
|
17963
|
+
const routes = new Elysia29({
|
|
17504
17964
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
17505
17965
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
17506
17966
|
if (htmlPath) {
|
|
@@ -17814,10 +18274,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
17814
18274
|
return report;
|
|
17815
18275
|
};
|
|
17816
18276
|
// src/turnLatency.ts
|
|
17817
|
-
import { Elysia as
|
|
18277
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
17818
18278
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
17819
18279
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
17820
|
-
var
|
|
18280
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17821
18281
|
var firstNumber = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
17822
18282
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
17823
18283
|
var createTraceStageIndex = (events) => {
|
|
@@ -17949,11 +18409,11 @@ await traceStore.append({
|
|
|
17949
18409
|
turnId,
|
|
17950
18410
|
type: 'turn_latency.stage'
|
|
17951
18411
|
});`;
|
|
17952
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
17953
|
-
<header><div><p class="eyebrow">${
|
|
17954
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
18412
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml30(turn.status)}">
|
|
18413
|
+
<header><div><p class="eyebrow">${escapeHtml30(turn.sessionId)} \xB7 ${escapeHtml30(turn.turnId)}</p><h2>${escapeHtml30(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml30(turn.status)}</strong></header>
|
|
18414
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml30(stage.label)}</dt><dd>${escapeHtml30(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
17955
18415
|
</article>`).join("");
|
|
17956
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18416
|
+
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:#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>${escapeHtml30(title)}</h1><div class="summary"><span class="pill ${escapeHtml30(report.status)}">${escapeHtml30(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml30(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>${escapeHtml30(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
17957
18417
|
};
|
|
17958
18418
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
17959
18419
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -17970,7 +18430,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
17970
18430
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
17971
18431
|
const path = options.path ?? "/api/turn-latency";
|
|
17972
18432
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17973
|
-
const routes = new
|
|
18433
|
+
const routes = new Elysia30({
|
|
17974
18434
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
17975
18435
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
17976
18436
|
if (htmlPath) {
|
|
@@ -17979,8 +18439,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
17979
18439
|
return routes;
|
|
17980
18440
|
};
|
|
17981
18441
|
// src/liveLatency.ts
|
|
17982
|
-
import { Elysia as
|
|
17983
|
-
var
|
|
18442
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18443
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17984
18444
|
var percentile3 = (values, percentileValue) => {
|
|
17985
18445
|
if (values.length === 0) {
|
|
17986
18446
|
return;
|
|
@@ -18047,13 +18507,13 @@ await traceStore.append({
|
|
|
18047
18507
|
sessionId,
|
|
18048
18508
|
type: 'client.live_latency'
|
|
18049
18509
|
});`;
|
|
18050
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
18051
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18510
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml31(sample.sessionId)}</td><td>${escapeHtml31(formatMs3(sample.latencyMs))}</td><td>${escapeHtml31(sample.status ?? "unknown")}</td><td>${escapeHtml31(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
18511
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml31(title)}</title><style>body{background:#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>${escapeHtml31(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml31(report.status)}">Status: ${escapeHtml31(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml31(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml31(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml31(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>${escapeHtml31(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
18052
18512
|
};
|
|
18053
18513
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
18054
18514
|
const path = options.path ?? "/api/live-latency";
|
|
18055
18515
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
18056
|
-
const routes = new
|
|
18516
|
+
const routes = new Elysia31({
|
|
18057
18517
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
18058
18518
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
18059
18519
|
if (htmlPath) {
|
|
@@ -18372,9 +18832,9 @@ None.
|
|
|
18372
18832
|
`}`;
|
|
18373
18833
|
};
|
|
18374
18834
|
// src/turnQuality.ts
|
|
18375
|
-
import { Elysia as
|
|
18835
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18376
18836
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
18377
|
-
var
|
|
18837
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18378
18838
|
var getTurnLatencyMs = (turn) => {
|
|
18379
18839
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
18380
18840
|
if (firstTranscriptAt === undefined) {
|
|
@@ -18445,24 +18905,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
18445
18905
|
};
|
|
18446
18906
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
18447
18907
|
const title = options.title ?? "Voice Turn Quality";
|
|
18448
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
18908
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml32(turn.status)}">
|
|
18449
18909
|
<div class="turn-header">
|
|
18450
18910
|
<div>
|
|
18451
|
-
<p class="eyebrow">${
|
|
18452
|
-
<h2>${
|
|
18911
|
+
<p class="eyebrow">${escapeHtml32(turn.sessionId)} \xB7 ${escapeHtml32(turn.turnId)}</p>
|
|
18912
|
+
<h2>${escapeHtml32(turn.text || "Empty turn")}</h2>
|
|
18453
18913
|
</div>
|
|
18454
|
-
<strong>${
|
|
18914
|
+
<strong>${escapeHtml32(turn.status)}</strong>
|
|
18455
18915
|
</div>
|
|
18456
18916
|
<dl>
|
|
18457
|
-
<div><dt>Source</dt><dd>${
|
|
18917
|
+
<div><dt>Source</dt><dd>${escapeHtml32(turn.source ?? "unknown")}</dd></div>
|
|
18458
18918
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
18459
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
18460
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
18919
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml32(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
18920
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml32(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
18461
18921
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
18462
18922
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
18463
18923
|
</dl>
|
|
18464
18924
|
</article>`).join("");
|
|
18465
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18925
|
+
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{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>${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">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
18466
18926
|
};
|
|
18467
18927
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
18468
18928
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -18479,7 +18939,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
18479
18939
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
18480
18940
|
const path = options.path ?? "/api/turn-quality";
|
|
18481
18941
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18482
|
-
const routes = new
|
|
18942
|
+
const routes = new Elysia32({
|
|
18483
18943
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
18484
18944
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
18485
18945
|
if (htmlPath) {
|
|
@@ -18488,7 +18948,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
18488
18948
|
return routes;
|
|
18489
18949
|
};
|
|
18490
18950
|
// src/telephonyOutcome.ts
|
|
18491
|
-
import { Elysia as
|
|
18951
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
18492
18952
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
18493
18953
|
"answered",
|
|
18494
18954
|
"completed",
|
|
@@ -19249,7 +19709,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
19249
19709
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
19250
19710
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
19251
19711
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
19252
|
-
return new
|
|
19712
|
+
return new Elysia33({
|
|
19253
19713
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
19254
19714
|
}).post(path, async ({ query, request }) => {
|
|
19255
19715
|
try {
|
|
@@ -19270,12 +19730,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
19270
19730
|
});
|
|
19271
19731
|
};
|
|
19272
19732
|
// src/phoneAgent.ts
|
|
19273
|
-
import { Elysia as
|
|
19733
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
19274
19734
|
|
|
19275
19735
|
// src/telephony/plivo.ts
|
|
19276
19736
|
import { Buffer as Buffer5 } from "buffer";
|
|
19277
19737
|
import { Database } from "bun:sqlite";
|
|
19278
|
-
import { Elysia as
|
|
19738
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
19279
19739
|
|
|
19280
19740
|
// src/telephony/contract.ts
|
|
19281
19741
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -19359,7 +19819,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
19359
19819
|
|
|
19360
19820
|
// src/telephony/twilio.ts
|
|
19361
19821
|
import { Buffer as Buffer4 } from "buffer";
|
|
19362
|
-
import { Elysia as
|
|
19822
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19363
19823
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
19364
19824
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
19365
19825
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -19389,7 +19849,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
19389
19849
|
return parameters;
|
|
19390
19850
|
};
|
|
19391
19851
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
19392
|
-
var
|
|
19852
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
19393
19853
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
19394
19854
|
if (!webhook?.verificationUrl) {
|
|
19395
19855
|
return;
|
|
@@ -19432,23 +19892,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
19432
19892
|
};
|
|
19433
19893
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
19434
19894
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
19435
|
-
<h1>${
|
|
19895
|
+
<h1>${escapeHtml33(title)}</h1>
|
|
19436
19896
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
19437
19897
|
<section>
|
|
19438
19898
|
<h2>URLs</h2>
|
|
19439
19899
|
<ul>
|
|
19440
|
-
<li><strong>TwiML:</strong> <code>${
|
|
19441
|
-
<li><strong>Media stream:</strong> <code>${
|
|
19442
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
19900
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml33(status.urls.twiml)}</code></li>
|
|
19901
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml33(status.urls.stream)}</code></li>
|
|
19902
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml33(status.urls.webhook)}</code></li>
|
|
19443
19903
|
</ul>
|
|
19444
19904
|
</section>
|
|
19445
19905
|
<section>
|
|
19446
19906
|
<h2>Signing</h2>
|
|
19447
19907
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
19448
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
19908
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml33(status.signing.verificationUrl)}</code></p>` : ""}
|
|
19449
19909
|
</section>
|
|
19450
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
19451
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
19910
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml33(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
19911
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml33(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
19452
19912
|
</main>`;
|
|
19453
19913
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
19454
19914
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -19459,20 +19919,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
19459
19919
|
});
|
|
19460
19920
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
19461
19921
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
19462
|
-
<h1>${
|
|
19922
|
+
<h1>${escapeHtml33(title)}</h1>
|
|
19463
19923
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
19464
19924
|
<section>
|
|
19465
19925
|
<h2>Checks</h2>
|
|
19466
19926
|
<ul>
|
|
19467
|
-
${report.checks.map((check) => `<li><strong>${
|
|
19927
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml33(check.name)}</strong>: ${escapeHtml33(check.status)}${check.message ? ` - ${escapeHtml33(check.message)}` : ""}</li>`).join("")}
|
|
19468
19928
|
</ul>
|
|
19469
19929
|
</section>
|
|
19470
19930
|
<section>
|
|
19471
19931
|
<h2>Observed URLs</h2>
|
|
19472
19932
|
<ul>
|
|
19473
|
-
<li><strong>TwiML:</strong> <code>${
|
|
19474
|
-
<li><strong>Stream:</strong> <code>${
|
|
19475
|
-
<li><strong>Webhook:</strong> <code>${
|
|
19933
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml33(report.setup.urls.twiml)}</code></li>
|
|
19934
|
+
<li><strong>Stream:</strong> <code>${escapeHtml33(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
19935
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml33(report.setup.urls.webhook)}</code></li>
|
|
19476
19936
|
</ul>
|
|
19477
19937
|
</section>
|
|
19478
19938
|
</main>`;
|
|
@@ -19932,7 +20392,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
19932
20392
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
19933
20393
|
const bridges = new WeakMap;
|
|
19934
20394
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
19935
|
-
const app = new
|
|
20395
|
+
const app = new Elysia34({
|
|
19936
20396
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
19937
20397
|
}).get(twimlPath, async ({ query, request }) => {
|
|
19938
20398
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -20069,7 +20529,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
20069
20529
|
|
|
20070
20530
|
// src/telephony/plivo.ts
|
|
20071
20531
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20072
|
-
var
|
|
20532
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20073
20533
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20074
20534
|
var resolveRequestOrigin2 = (request) => {
|
|
20075
20535
|
const url = new URL(request.url);
|
|
@@ -20499,21 +20959,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
20499
20959
|
};
|
|
20500
20960
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20501
20961
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
20502
|
-
<h1>${
|
|
20962
|
+
<h1>${escapeHtml34(title)}</h1>
|
|
20503
20963
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
20504
20964
|
<ul>
|
|
20505
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
20506
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
20507
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
20965
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml34(status.urls.answer)}</code></li>
|
|
20966
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml34(status.urls.stream)}</code></li>
|
|
20967
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml34(status.urls.webhook)}</code></li>
|
|
20508
20968
|
</ul>
|
|
20509
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
20510
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
20969
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml34(name)}</code></li>`).join("")}</ul>` : ""}
|
|
20970
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml34(warning)}</li>`).join("")}</ul>` : ""}
|
|
20511
20971
|
</main>`;
|
|
20512
20972
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
20513
20973
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
20514
|
-
<h1>${
|
|
20974
|
+
<h1>${escapeHtml34(title)}</h1>
|
|
20515
20975
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
20516
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
20976
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml34(check.name)}</strong>: ${escapeHtml34(check.status)}${check.message ? ` - ${escapeHtml34(check.message)}` : ""}</li>`).join("")}</ul>
|
|
20517
20977
|
</main>`;
|
|
20518
20978
|
var runPlivoSmokeTest = async (input) => {
|
|
20519
20979
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -20603,7 +21063,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
20603
21063
|
nonceStore: options.webhook.nonceStore,
|
|
20604
21064
|
verificationUrl: options.webhook.verificationUrl
|
|
20605
21065
|
}) : undefined);
|
|
20606
|
-
const app = new
|
|
21066
|
+
const app = new Elysia35({
|
|
20607
21067
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
20608
21068
|
}).get(answerPath, async ({ query, request }) => {
|
|
20609
21069
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -20715,9 +21175,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
20715
21175
|
// src/telephony/telnyx.ts
|
|
20716
21176
|
import { Buffer as Buffer6 } from "buffer";
|
|
20717
21177
|
import { Database as Database2 } from "bun:sqlite";
|
|
20718
|
-
import { Elysia as
|
|
21178
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
20719
21179
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20720
|
-
var
|
|
21180
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
20721
21181
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
20722
21182
|
var resolveRequestOrigin3 = (request) => {
|
|
20723
21183
|
const url = new URL(request.url);
|
|
@@ -21110,21 +21570,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
21110
21570
|
};
|
|
21111
21571
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21112
21572
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
21113
|
-
<h1>${
|
|
21573
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
21114
21574
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
21115
21575
|
<ul>
|
|
21116
|
-
<li><strong>TeXML:</strong> <code>${
|
|
21117
|
-
<li><strong>Media stream:</strong> <code>${
|
|
21118
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
21576
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml35(status.urls.texml)}</code></li>
|
|
21577
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml35(status.urls.stream)}</code></li>
|
|
21578
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml35(status.urls.webhook)}</code></li>
|
|
21119
21579
|
</ul>
|
|
21120
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
21121
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
21580
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml35(name)}</code></li>`).join("")}</ul>` : ""}
|
|
21581
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml35(warning)}</li>`).join("")}</ul>` : ""}
|
|
21122
21582
|
</main>`;
|
|
21123
21583
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
21124
21584
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
21125
|
-
<h1>${
|
|
21585
|
+
<h1>${escapeHtml35(title)}</h1>
|
|
21126
21586
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
21127
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
21587
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml35(check.name)}</strong>: ${escapeHtml35(check.status)}${check.message ? ` - ${escapeHtml35(check.message)}` : ""}</li>`).join("")}</ul>
|
|
21128
21588
|
</main>`;
|
|
21129
21589
|
var runTelnyxSmokeTest = async (input) => {
|
|
21130
21590
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -21217,7 +21677,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
21217
21677
|
publicKey: options.webhook.publicKey,
|
|
21218
21678
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
21219
21679
|
}) : undefined);
|
|
21220
|
-
const app = new
|
|
21680
|
+
const app = new Elysia36({
|
|
21221
21681
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
21222
21682
|
}).get(texmlPath, async ({ query, request }) => {
|
|
21223
21683
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -21327,8 +21787,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
21327
21787
|
};
|
|
21328
21788
|
|
|
21329
21789
|
// src/telephony/matrix.ts
|
|
21330
|
-
import { Elysia as
|
|
21331
|
-
var
|
|
21790
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
21791
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21332
21792
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
21333
21793
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
21334
21794
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -21389,13 +21849,13 @@ var badgeStyles = {
|
|
|
21389
21849
|
};
|
|
21390
21850
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
21391
21851
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
21392
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
21852
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml36(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
21393
21853
|
<p style="color:#52606d; margin: 0 0 24px;">${matrix.summary.ready}/${matrix.summary.providers} ready, ${matrix.summary.contractsPassing}/${matrix.summary.providers} contract passing, ${matrix.summary.smokePassing}/${matrix.summary.providers} smoke passing.</p>
|
|
21394
21854
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
21395
21855
|
${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; border-radius:18px; padding:18px; background:#fff; box-shadow:0 18px 48px rgba(15,23,42,.08);">
|
|
21396
21856
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
21397
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
21398
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
21857
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml36(entry.name)}</h2>
|
|
21858
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml36(entry.status.toUpperCase())}</span>
|
|
21399
21859
|
</div>
|
|
21400
21860
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
21401
21861
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -21403,15 +21863,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
21403
21863
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
21404
21864
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
21405
21865
|
</dl>
|
|
21406
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
21407
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
21408
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
21866
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml36(entry.setup.urls.stream || "missing")}</code></p>
|
|
21867
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml36(entry.setup.urls.webhook || "missing")}</code></p>
|
|
21868
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml36(issue.severity)}: ${escapeHtml36(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
21409
21869
|
</article>`).join("")}
|
|
21410
21870
|
</section>
|
|
21411
21871
|
</main>`;
|
|
21412
21872
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
21413
21873
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
21414
|
-
return new
|
|
21874
|
+
return new Elysia37({
|
|
21415
21875
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
21416
21876
|
}).get(path, async ({ query, request }) => {
|
|
21417
21877
|
const providers = await options.load({ query, request });
|
|
@@ -21433,7 +21893,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
21433
21893
|
};
|
|
21434
21894
|
|
|
21435
21895
|
// src/phoneAgentProductionSmoke.ts
|
|
21436
|
-
import { Elysia as
|
|
21896
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21437
21897
|
var defaultRequirements = [
|
|
21438
21898
|
"media-started",
|
|
21439
21899
|
"transcript",
|
|
@@ -21441,7 +21901,7 @@ var defaultRequirements = [
|
|
|
21441
21901
|
"lifecycle-outcome",
|
|
21442
21902
|
"no-session-error"
|
|
21443
21903
|
];
|
|
21444
|
-
var
|
|
21904
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21445
21905
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
21446
21906
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
21447
21907
|
const value = event.payload[key];
|
|
@@ -21550,10 +22010,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
21550
22010
|
});
|
|
21551
22011
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
21552
22012
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
21553
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
21554
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
21555
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
21556
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22013
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml37(issue.requirement)}</strong>: ${escapeHtml37(issue.message)}</li>`).join("");
|
|
22014
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml37(outcome)}</span>`).join("");
|
|
22015
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml37(requirement)}</span>`).join("");
|
|
22016
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml37(title)}</title><style>body{background:#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>${escapeHtml37(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml37(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml37(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml37(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
|
|
21557
22017
|
};
|
|
21558
22018
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
21559
22019
|
query,
|
|
@@ -21576,7 +22036,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
21576
22036
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
21577
22037
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
21578
22038
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
21579
|
-
const routes = new
|
|
22039
|
+
const routes = new Elysia38({
|
|
21580
22040
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
21581
22041
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
21582
22042
|
if (htmlPath) {
|
|
@@ -21619,7 +22079,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
21619
22079
|
"completed",
|
|
21620
22080
|
"failed"
|
|
21621
22081
|
];
|
|
21622
|
-
var
|
|
22082
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
21623
22083
|
var loadRouteJson = async (input) => {
|
|
21624
22084
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
21625
22085
|
headers: {
|
|
@@ -21857,10 +22317,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
21857
22317
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
21858
22318
|
const urls = entry?.setup.urls;
|
|
21859
22319
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
21860
|
-
return `<tr><td>${
|
|
22320
|
+
return `<tr><td>${escapeHtml38(carrier.name ?? carrier.provider)}</td><td>${escapeHtml38(carrier.provider)}</td><td><code>${escapeHtml38(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml38(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml38(entry.status)}">${escapeHtml38(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml38(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml38(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml38(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
21861
22321
|
}).join("");
|
|
21862
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
21863
|
-
const snippet =
|
|
22322
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml38(stage)}</code></li>`).join("");
|
|
22323
|
+
const snippet = escapeHtml38(`const phoneAgent = createVoicePhoneAgent({
|
|
21864
22324
|
carriers: [
|
|
21865
22325
|
{
|
|
21866
22326
|
provider: 'twilio',
|
|
@@ -21894,11 +22354,11 @@ app.use(
|
|
|
21894
22354
|
);`);
|
|
21895
22355
|
const checklist = report.carriers.map((carrier) => {
|
|
21896
22356
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
21897
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
21898
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
21899
|
-
return `<article><h3>${
|
|
22357
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml38(issue)}</li>`).join("") ?? "";
|
|
22358
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml38(step)}</li>`).join("") ?? "";
|
|
22359
|
+
return `<article><h3>${escapeHtml38(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
21900
22360
|
}).join("");
|
|
21901
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22361
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(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>${escapeHtml38(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="${escapeHtml38(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
|
|
21902
22362
|
};
|
|
21903
22363
|
var createVoicePhoneAgent = (options) => {
|
|
21904
22364
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -21907,7 +22367,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
21907
22367
|
setupPath: resolveSetupPath(carrier),
|
|
21908
22368
|
smokePath: resolveSmokePath(carrier)
|
|
21909
22369
|
}));
|
|
21910
|
-
const app = new
|
|
22370
|
+
const app = new Elysia39({
|
|
21911
22371
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
21912
22372
|
});
|
|
21913
22373
|
for (const carrier of options.carriers) {
|
|
@@ -24041,8 +24501,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
24041
24501
|
};
|
|
24042
24502
|
};
|
|
24043
24503
|
// src/providerCapabilities.ts
|
|
24044
|
-
import { Elysia as
|
|
24045
|
-
var
|
|
24504
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
24505
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24046
24506
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
24047
24507
|
configured: true,
|
|
24048
24508
|
features: options.features?.[provider],
|
|
@@ -24105,27 +24565,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
24105
24565
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
24106
24566
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
24107
24567
|
const cards = report.capabilities.map((capability) => {
|
|
24108
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
24109
|
-
return `<article class="card ${
|
|
24568
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml39(feature)}</span>`).join("");
|
|
24569
|
+
return `<article class="card ${escapeHtml39(capability.status)}">
|
|
24110
24570
|
<div class="card-header">
|
|
24111
24571
|
<div>
|
|
24112
|
-
<p class="eyebrow">${
|
|
24113
|
-
<h2>${
|
|
24572
|
+
<p class="eyebrow">${escapeHtml39(capability.kind)}</p>
|
|
24573
|
+
<h2>${escapeHtml39(capability.label ?? capability.provider)}</h2>
|
|
24114
24574
|
</div>
|
|
24115
|
-
<strong>${
|
|
24575
|
+
<strong>${escapeHtml39(capability.status)}</strong>
|
|
24116
24576
|
</div>
|
|
24117
|
-
${capability.description ? `<p>${
|
|
24577
|
+
${capability.description ? `<p>${escapeHtml39(capability.description)}</p>` : ""}
|
|
24118
24578
|
<dl>
|
|
24119
24579
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
24120
24580
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
24121
|
-
<div><dt>Model</dt><dd>${
|
|
24581
|
+
<div><dt>Model</dt><dd>${escapeHtml39(capability.model ?? "default")}</dd></div>
|
|
24122
24582
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
24123
24583
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
24124
24584
|
</dl>
|
|
24125
24585
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
24126
24586
|
</article>`;
|
|
24127
24587
|
}).join("");
|
|
24128
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24588
|
+
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:#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>${escapeHtml39(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
|
|
24129
24589
|
};
|
|
24130
24590
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
24131
24591
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -24142,7 +24602,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
24142
24602
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
24143
24603
|
const path = options.path ?? "/api/provider-capabilities";
|
|
24144
24604
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
24145
|
-
const routes = new
|
|
24605
|
+
const routes = new Elysia40({
|
|
24146
24606
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
24147
24607
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
24148
24608
|
if (htmlPath) {
|
|
@@ -24151,7 +24611,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
24151
24611
|
return routes;
|
|
24152
24612
|
};
|
|
24153
24613
|
// src/providerOrchestration.ts
|
|
24154
|
-
import { Elysia as
|
|
24614
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
24155
24615
|
var defaultRequirement = {
|
|
24156
24616
|
minProviders: 1,
|
|
24157
24617
|
requireBudgetPolicy: false,
|
|
@@ -24164,7 +24624,7 @@ var statusRank2 = {
|
|
|
24164
24624
|
warn: 1,
|
|
24165
24625
|
fail: 2
|
|
24166
24626
|
};
|
|
24167
|
-
var
|
|
24627
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24168
24628
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
24169
24629
|
var uniqueSorted6 = (values) => [
|
|
24170
24630
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -24307,27 +24767,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
24307
24767
|
};
|
|
24308
24768
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
24309
24769
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
24310
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
24311
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
24770
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml40(surface.status)}">
|
|
24771
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml40(surface.surface)}</p><h2>${escapeHtml40(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml40(surface.status)}</strong></div>
|
|
24312
24772
|
<dl>
|
|
24313
|
-
<div><dt>Providers</dt><dd>${
|
|
24314
|
-
<div><dt>Fallback</dt><dd>${
|
|
24773
|
+
<div><dt>Providers</dt><dd>${escapeHtml40(surface.providers.join(", ") || "none")}</dd></div>
|
|
24774
|
+
<div><dt>Fallback</dt><dd>${escapeHtml40(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
24315
24775
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
24316
24776
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
24317
24777
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
24318
24778
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
24319
24779
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
24320
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
24780
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml40(surface.fallbackMode || "default")}</dd></div>
|
|
24321
24781
|
</dl>
|
|
24322
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
24782
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml40(issue.status)}</strong> ${escapeHtml40(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
24323
24783
|
</article>`).join("");
|
|
24324
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24784
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(title)}</title><style>body{background:#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>${escapeHtml40(title)}</h1><div class="summary"><span class="pill">${escapeHtml40(report.profileId)}</span><span class="pill">${escapeHtml40(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
|
|
24325
24785
|
};
|
|
24326
24786
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
24327
24787
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
24328
24788
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
24329
24789
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
24330
|
-
const routes = new
|
|
24790
|
+
const routes = new Elysia41({
|
|
24331
24791
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
24332
24792
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
24333
24793
|
if (htmlPath) {
|
|
@@ -24498,7 +24958,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
24498
24958
|
return report;
|
|
24499
24959
|
};
|
|
24500
24960
|
// src/providerSlo.ts
|
|
24501
|
-
import { Elysia as
|
|
24961
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24502
24962
|
var defaultThresholds = {
|
|
24503
24963
|
llm: {
|
|
24504
24964
|
maxAverageElapsedMs: 2500,
|
|
@@ -24531,7 +24991,7 @@ var statusRank3 = {
|
|
|
24531
24991
|
warn: 1,
|
|
24532
24992
|
fail: 2
|
|
24533
24993
|
};
|
|
24534
|
-
var
|
|
24994
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24535
24995
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
24536
24996
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
24537
24997
|
var uniqueSorted7 = (values) => [
|
|
@@ -24827,11 +25287,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24827
25287
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
24828
25288
|
const kindCards = providerKinds.map((kind) => {
|
|
24829
25289
|
const kindReport = report.kinds[kind];
|
|
24830
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
25290
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml41(metric.label)}</dt><dd>${escapeHtml41(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml41(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
24831
25291
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
24832
|
-
return `<article class="${
|
|
25292
|
+
return `<article class="${escapeHtml41(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml41(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml41(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
24833
25293
|
}).join("");
|
|
24834
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
25294
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml41(issue.status)}"><strong>${escapeHtml41(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml41(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
24835
25295
|
const snippet = `createVoiceProviderSloRoutes({
|
|
24836
25296
|
store: runtimeStorage.traces,
|
|
24837
25297
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -24841,7 +25301,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24841
25301
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
24842
25302
|
}
|
|
24843
25303
|
})`;
|
|
24844
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25304
|
+
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:#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>${escapeHtml41(title)}</h1><p class="status ${escapeHtml41(report.status)}">${escapeHtml41(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>${escapeHtml41(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
24845
25305
|
};
|
|
24846
25306
|
var createVoiceProviderSloRoutes = (options) => {
|
|
24847
25307
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -24852,7 +25312,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24852
25312
|
...options.headers ?? {}
|
|
24853
25313
|
};
|
|
24854
25314
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
24855
|
-
const app = new
|
|
25315
|
+
const app = new Elysia42({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
24856
25316
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
24857
25317
|
if (markdownPath !== false) {
|
|
24858
25318
|
app.get(markdownPath, async () => {
|
|
@@ -24882,10 +25342,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24882
25342
|
return app;
|
|
24883
25343
|
};
|
|
24884
25344
|
// src/productionReadiness.ts
|
|
24885
|
-
import { Elysia as
|
|
25345
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
24886
25346
|
|
|
24887
25347
|
// src/telephony/security.ts
|
|
24888
|
-
import { Elysia as
|
|
25348
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24889
25349
|
|
|
24890
25350
|
// src/postgresStore.ts
|
|
24891
25351
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -25623,7 +26083,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
25623
26083
|
};
|
|
25624
26084
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
25625
26085
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
25626
|
-
return new
|
|
26086
|
+
return new Elysia43({
|
|
25627
26087
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
25628
26088
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
25629
26089
|
};
|
|
@@ -25680,8 +26140,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
25680
26140
|
};
|
|
25681
26141
|
|
|
25682
26142
|
// src/opsRecovery.ts
|
|
25683
|
-
import { Elysia as
|
|
25684
|
-
var
|
|
26143
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
26144
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25685
26145
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
25686
26146
|
var hrefForSession = (value, sessionId) => {
|
|
25687
26147
|
if (typeof value === "function") {
|
|
@@ -25895,19 +26355,19 @@ ${failedSessions || "None."}
|
|
|
25895
26355
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
25896
26356
|
`;
|
|
25897
26357
|
};
|
|
25898
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
26358
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml42(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>${escapeHtml42(label)}</span><strong>not configured</strong></article>`;
|
|
25899
26359
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
25900
26360
|
const title = options.title ?? "Voice Ops Recovery";
|
|
25901
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
25902
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
25903
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
25904
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26361
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml42(issue.severity)}</td><td><code>${escapeHtml42(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml42(issue.href)}">${escapeHtml42(issue.label)}</a>` : escapeHtml42(issue.label)}</td><td>${escapeHtml42(String(issue.value ?? ""))}</td><td>${escapeHtml42(issue.detail ?? "")}</td></tr>`).join("");
|
|
26362
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml42(provider.provider)}</td><td>${escapeHtml42(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml42(provider.lastError ?? "")}</td></tr>`).join("");
|
|
26363
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml42(session.operationsRecordHref)}">${escapeHtml42(session.sessionId)}</a>` : escapeHtml42(session.sessionId)}${session.provider ? ` via ${escapeHtml42(session.provider)}` : ""}${session.error ? `: ${escapeHtml42(session.error)}` : ""}</li>`).join("");
|
|
26364
|
+
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{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>${escapeHtml42(title)}</h1><p><span class="status">${escapeHtml42(report.status)}</span> Checked ${escapeHtml42(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>${escapeHtml42(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
|
|
25905
26365
|
};
|
|
25906
26366
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
25907
26367
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
25908
26368
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
25909
26369
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
25910
|
-
const routes = new
|
|
26370
|
+
const routes = new Elysia44({
|
|
25911
26371
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
25912
26372
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
25913
26373
|
if (htmlPath) {
|
|
@@ -25937,18 +26397,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
25937
26397
|
};
|
|
25938
26398
|
|
|
25939
26399
|
// src/observabilityExport.ts
|
|
25940
|
-
import { Elysia as
|
|
26400
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
25941
26401
|
import { Database as Database4 } from "bun:sqlite";
|
|
25942
26402
|
import { createHash } from "crypto";
|
|
25943
26403
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
25944
26404
|
import { join as join3 } from "path";
|
|
25945
26405
|
|
|
25946
26406
|
// src/operationsRecord.ts
|
|
25947
|
-
import { Elysia as
|
|
26407
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
25948
26408
|
|
|
25949
26409
|
// src/traceTimeline.ts
|
|
25950
|
-
import { Elysia as
|
|
25951
|
-
var
|
|
26410
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
26411
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25952
26412
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
25953
26413
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
25954
26414
|
var firstString3 = (payload, keys) => {
|
|
@@ -26131,17 +26591,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
26131
26591
|
};
|
|
26132
26592
|
};
|
|
26133
26593
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
26134
|
-
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${
|
|
26594
|
+
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>${escapeHtml43(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs4(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs4(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
26135
26595
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
26136
|
-
const events = session.events.map((event) => `<tr class="${
|
|
26137
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
26138
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
26139
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26596
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml43(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml43(event.type)}</td><td>${escapeHtml43(event.label)}</td><td>${escapeHtml43(event.provider ?? "")}</td><td>${escapeHtml43(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
26597
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml43(issue.severity)}">${escapeHtml43(issue.code)}: ${escapeHtml43(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
26598
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml43(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
26599
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml43(session.sessionId)}</h1><p class="status ${escapeHtml43(session.status)}">${escapeHtml43(session.status)}</p>${supportLinks}</header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs4(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards2(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
26140
26600
|
};
|
|
26141
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
26601
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml43(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml43(session.operationsRecordHref)}">${escapeHtml43(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml43(session.sessionId)}</a>`}</td><td>${escapeHtml43(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) => escapeHtml43(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
26142
26602
|
var timelineCSS = "body{background:#0f1318;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}a{color:#fbbf24}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.metrics,.providers{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.providers article{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span,dt,.muted{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 0}dd{font-weight:800;margin:4px 0 0}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}section{margin-top:28px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}";
|
|
26143
26603
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
26144
|
-
const snippet =
|
|
26604
|
+
const snippet = escapeHtml43(`const traceStore = createVoiceTraceSinkStore({
|
|
26145
26605
|
store: runtimeStorage.traces,
|
|
26146
26606
|
sinks: [
|
|
26147
26607
|
createVoiceTraceHTTPSink({
|
|
@@ -26167,13 +26627,13 @@ app.use(
|
|
|
26167
26627
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
26168
26628
|
})
|
|
26169
26629
|
);`);
|
|
26170
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26630
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(options.title ?? "Voice 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>${escapeHtml43(options.title ?? "Voice Trace Timelines")}</h1><p class="muted">Per-call event timelines with provider latency, fallback, timeout, handoff, and error context.</p></header><section class="metrics"><article><span>Sessions</span><strong>${String(report.total)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article><article><span>Warnings</span><strong>${String(report.warnings)}</strong></article></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTraceTimelineRoutes(...)</code> makes traces the proof backbone</h2><p class="muted">Mount trace timelines from the same trace store used by readiness, simulations, provider recovery, delivery sinks, and phone-agent smoke proof.</p><pre><code>${snippet}</code></pre></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
26171
26631
|
};
|
|
26172
26632
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
26173
26633
|
const path = options.path ?? "/api/voice-traces";
|
|
26174
26634
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
26175
26635
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
26176
|
-
const routes = new
|
|
26636
|
+
const routes = new Elysia45({
|
|
26177
26637
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
26178
26638
|
});
|
|
26179
26639
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -26602,7 +27062,7 @@ var assertVoiceOperationsRecordProviderRecovery = (record, input = {}) => {
|
|
|
26602
27062
|
}
|
|
26603
27063
|
return report;
|
|
26604
27064
|
};
|
|
26605
|
-
var
|
|
27065
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26606
27066
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
26607
27067
|
var outcomeLabels = (outcome) => [
|
|
26608
27068
|
outcome.complete ? "complete" : undefined,
|
|
@@ -26682,20 +27142,20 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
26682
27142
|
`);
|
|
26683
27143
|
};
|
|
26684
27144
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
26685
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
26686
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
26687
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
27145
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml44(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>';
|
|
27146
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml44(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml44(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml44(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml44(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
27147
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml44(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml44(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml44(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml44(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml44(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml44(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml44(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml44(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
26688
27148
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
26689
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
26690
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
26691
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
26692
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
26693
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
27149
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml44(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml44(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml44(handoff.status ?? "")}</span><p>${escapeHtml44(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
27150
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml44(tool.toolName ?? "tool")}</strong> <span>${escapeHtml44(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml44(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
27151
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml44(review.title)}</strong> <span>${escapeHtml44(review.summary.outcome ?? "")}</span><p>${escapeHtml44(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
27152
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml44(task.title)}</strong> <span>${escapeHtml44(task.status)}</span><p>${escapeHtml44(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
27153
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml44(event.type)}</strong> <span>${escapeHtml44(event.deliveryStatus ?? "local")}</span><p>${escapeHtml44(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
26694
27154
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
26695
27155
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
26696
|
-
return `<li><strong>assistant.guardrail ${
|
|
27156
|
+
return `<li><strong>assistant.guardrail ${escapeHtml44(decision.stage ?? "unknown")}</strong> <span>${escapeHtml44(decision.status ?? "")}</span><p>Allowed: ${escapeHtml44(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml44(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml44(decision.turnId)}` : ""}</p><p>${escapeHtml44(findings)}</p></li>`;
|
|
26697
27157
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
26698
|
-
const snippet =
|
|
27158
|
+
const snippet = escapeHtml44(`app.use(
|
|
26699
27159
|
createVoiceOperationsRecordRoutes({
|
|
26700
27160
|
audit: auditStore,
|
|
26701
27161
|
integrationEvents: opsEvents,
|
|
@@ -26709,16 +27169,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
26709
27169
|
tasks: opsTasks
|
|
26710
27170
|
})
|
|
26711
27171
|
);`);
|
|
26712
|
-
const incidentMarkdown =
|
|
26713
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
26714
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27172
|
+
const incidentMarkdown = escapeHtml44(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
27173
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml44(options.incidentHref)}">Download incident.md</a>` : "";
|
|
27174
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(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>${escapeHtml44(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml44(record.status)}">${escapeHtml44(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>${escapeHtml44(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</span></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div></section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
26715
27175
|
};
|
|
26716
27176
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
26717
27177
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
26718
27178
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
26719
27179
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
26720
27180
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
26721
|
-
const routes = new
|
|
27181
|
+
const routes = new Elysia46({
|
|
26722
27182
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
26723
27183
|
});
|
|
26724
27184
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -27369,7 +27829,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
27369
27829
|
...options.headers ?? {}
|
|
27370
27830
|
};
|
|
27371
27831
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
27372
|
-
const app = new
|
|
27832
|
+
const app = new Elysia47({
|
|
27373
27833
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
27374
27834
|
});
|
|
27375
27835
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28178,7 +28638,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28178
28638
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
28179
28639
|
}
|
|
28180
28640
|
});
|
|
28181
|
-
const app = new
|
|
28641
|
+
const app = new Elysia47({
|
|
28182
28642
|
name: options.name ?? "absolute-voice-observability-export"
|
|
28183
28643
|
});
|
|
28184
28644
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -28255,7 +28715,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
28255
28715
|
};
|
|
28256
28716
|
|
|
28257
28717
|
// src/productionReadiness.ts
|
|
28258
|
-
var
|
|
28718
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28259
28719
|
var rollupStatus3 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
28260
28720
|
var readinessGateCodes = {
|
|
28261
28721
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -29710,25 +30170,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29710
30170
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
29711
30171
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
29712
30172
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
29713
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
29714
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
30173
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml45(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
30174
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml45(report.profile.name)}</h2><p>${escapeHtml45(report.profile.description)}</p><p>${escapeHtml45(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="${escapeHtml45(surface.href)}">${escapeHtml45(surface.label)}</a>` : escapeHtml45(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
29715
30175
|
const checks = report.checks.map((check, index) => {
|
|
29716
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
29717
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
29718
|
-
return `<article class="check ${
|
|
30176
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml45(action.href)}">${escapeHtml45(action.label)}</button>` : `<a href="${escapeHtml45(action.href)}">${escapeHtml45(action.label)}</a>`).join("");
|
|
30177
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml45(check.status)}: observed ${escapeHtml45(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml45(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml45(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml45(check.gateExplanation.unit)}` : ""}. ${escapeHtml45(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml45(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
30178
|
+
return `<article class="check ${escapeHtml45(check.status)}">
|
|
29719
30179
|
<div>
|
|
29720
|
-
<span>${
|
|
29721
|
-
<h2>${
|
|
29722
|
-
${check.detail ? `<p>${
|
|
30180
|
+
<span>${escapeHtml45(check.status.toUpperCase())}</span>
|
|
30181
|
+
<h2>${escapeHtml45(check.label)}</h2>
|
|
30182
|
+
${check.detail ? `<p>${escapeHtml45(check.detail)}</p>` : ""}
|
|
29723
30183
|
${explanation}
|
|
29724
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
30184
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml45(check.proofSource.href)}">${escapeHtml45(check.proofSource.sourceLabel)}</a>` : escapeHtml45(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml45(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
29725
30185
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
29726
30186
|
</div>
|
|
29727
|
-
<strong>${
|
|
29728
|
-
${check.href ? `<a href="${
|
|
30187
|
+
<strong>${escapeHtml45(String(check.value ?? check.status))}</strong>
|
|
30188
|
+
${check.href ? `<a href="${escapeHtml45(check.href)}">Open surface</a>` : ""}
|
|
29729
30189
|
</article>`;
|
|
29730
30190
|
}).join("");
|
|
29731
|
-
const snippet =
|
|
30191
|
+
const snippet = escapeHtml45(`createVoiceProductionReadinessRoutes({
|
|
29732
30192
|
htmlPath: '/production-readiness',
|
|
29733
30193
|
path: '/api/production-readiness',
|
|
29734
30194
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -29744,13 +30204,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
29744
30204
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
29745
30205
|
store: traceStore
|
|
29746
30206
|
});`);
|
|
29747
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30207
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{background:#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>${escapeHtml45(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 ${escapeHtml45(report.status)}">Overall: ${escapeHtml45(report.status.toUpperCase())}</p><p>Checked ${escapeHtml45(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
|
|
29748
30208
|
};
|
|
29749
30209
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
29750
30210
|
const path = options.path ?? "/api/production-readiness";
|
|
29751
30211
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
29752
30212
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
29753
|
-
const routes = new
|
|
30213
|
+
const routes = new Elysia48({
|
|
29754
30214
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
29755
30215
|
});
|
|
29756
30216
|
const resolveOptions = async (input) => {
|
|
@@ -29798,8 +30258,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
29798
30258
|
return routes;
|
|
29799
30259
|
};
|
|
29800
30260
|
// src/voiceMonitoring.ts
|
|
29801
|
-
import { Elysia as
|
|
29802
|
-
var
|
|
30261
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
30262
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29803
30263
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
29804
30264
|
var rollupStatus4 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
29805
30265
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -30052,14 +30512,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
30052
30512
|
};
|
|
30053
30513
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
30054
30514
|
const title = options.title ?? "Voice Monitors";
|
|
30055
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
30056
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
30057
|
-
const snippet =
|
|
30515
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml46(run.label)}</td><td class="${escapeHtml46(run.status)}">${escapeHtml46(run.status)}</td><td>${escapeHtml46(run.severity)}</td><td>${escapeHtml46(String(run.value ?? ""))}</td><td>${escapeHtml46(String(run.threshold ?? ""))}</td><td>${escapeHtml46(run.detail ?? "")}</td></tr>`).join("");
|
|
30516
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml46(issue.label)}</strong> <span class="${escapeHtml46(issue.status)}">${escapeHtml46(issue.status)}</span> ${escapeHtml46(issue.detail ?? "")}</li>`).join("");
|
|
30517
|
+
const snippet = escapeHtml46(`app.use(createVoiceMonitorRoutes({
|
|
30058
30518
|
evidence,
|
|
30059
30519
|
issueStore,
|
|
30060
30520
|
monitors: [defineVoiceMonitor(...)]
|
|
30061
30521
|
}));`);
|
|
30062
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30522
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{background:#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>${escapeHtml46(title)}</h1><p class="pill ${escapeHtml46(report.status)}">Status: ${escapeHtml46(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
30063
30523
|
};
|
|
30064
30524
|
var actorFromRequest = async (request) => {
|
|
30065
30525
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -30083,7 +30543,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30083
30543
|
monitors: options.monitors,
|
|
30084
30544
|
now: options.now
|
|
30085
30545
|
});
|
|
30086
|
-
const routes = new
|
|
30546
|
+
const routes = new Elysia49({
|
|
30087
30547
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
30088
30548
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
30089
30549
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -30130,7 +30590,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
30130
30590
|
};
|
|
30131
30591
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
30132
30592
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
30133
|
-
return new
|
|
30593
|
+
return new Elysia49({
|
|
30134
30594
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
30135
30595
|
}).get(path, () => ({
|
|
30136
30596
|
isRunning: options.runner.isRunning()
|
|
@@ -30506,8 +30966,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
30506
30966
|
};
|
|
30507
30967
|
};
|
|
30508
30968
|
// src/providerStackRecommendations.ts
|
|
30509
|
-
import { Elysia as
|
|
30510
|
-
var
|
|
30969
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
30970
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30511
30971
|
var profileProviderPriorities = {
|
|
30512
30972
|
"meeting-recorder": {
|
|
30513
30973
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -30826,17 +31286,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
30826
31286
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
30827
31287
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
30828
31288
|
const rows = report.rows.map((row) => {
|
|
30829
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
30830
|
-
return `<article class="row ${
|
|
31289
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml47(check.status)}"><strong>${escapeHtml47(check.label)}</strong><span>${escapeHtml47(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml47(check.remediation.href)}">${escapeHtml47(check.remediation.label)}</a>` : escapeHtml47(check.remediation.label)}: ${escapeHtml47(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
31290
|
+
return `<article class="row ${escapeHtml47(row.status)}">
|
|
30831
31291
|
<div>
|
|
30832
|
-
<p class="eyebrow">${
|
|
30833
|
-
<h2>${
|
|
30834
|
-
<p class="status ${
|
|
31292
|
+
<p class="eyebrow">${escapeHtml47(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
31293
|
+
<h2>${escapeHtml47(row.provider)}</h2>
|
|
31294
|
+
<p class="status ${escapeHtml47(row.status)}">${escapeHtml47(row.status.toUpperCase())}</p>
|
|
30835
31295
|
</div>
|
|
30836
31296
|
<ul>${checks}</ul>
|
|
30837
31297
|
</article>`;
|
|
30838
31298
|
}).join("");
|
|
30839
|
-
const snippet =
|
|
31299
|
+
const snippet = escapeHtml47(`const providerContracts = () =>
|
|
30840
31300
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
30841
31301
|
env: process.env,
|
|
30842
31302
|
providers: {
|
|
@@ -30857,7 +31317,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
30857
31317
|
providerContractMatrix: () =>
|
|
30858
31318
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
30859
31319
|
});`);
|
|
30860
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31320
|
+
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:#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>${escapeHtml47(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
|
|
30861
31321
|
};
|
|
30862
31322
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
30863
31323
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -30872,7 +31332,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
30872
31332
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
30873
31333
|
const path = options.path ?? "/api/provider-contracts";
|
|
30874
31334
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
30875
|
-
const routes = new
|
|
31335
|
+
const routes = new Elysia50({
|
|
30876
31336
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
30877
31337
|
});
|
|
30878
31338
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -30990,7 +31450,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
30990
31450
|
return assertion;
|
|
30991
31451
|
};
|
|
30992
31452
|
// src/opsConsoleRoutes.ts
|
|
30993
|
-
import { Elysia as
|
|
31453
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
30994
31454
|
var DEFAULT_LINKS = [
|
|
30995
31455
|
{
|
|
30996
31456
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -31025,7 +31485,7 @@ var DEFAULT_LINKS = [
|
|
|
31025
31485
|
label: "Handoffs"
|
|
31026
31486
|
}
|
|
31027
31487
|
];
|
|
31028
|
-
var
|
|
31488
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31029
31489
|
var countProviderStatuses = (providers) => {
|
|
31030
31490
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
31031
31491
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -31094,20 +31554,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
31094
31554
|
trace
|
|
31095
31555
|
};
|
|
31096
31556
|
};
|
|
31097
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
31557
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml48(input.label)}</span><strong>${escapeHtml48(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml48(input.status)}">${escapeHtml48(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml48(input.href)}">Open</a>` : ""}</article>`;
|
|
31098
31558
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
31099
31559
|
const links = report.links.map((link) => `<article class="surface">
|
|
31100
|
-
<div><h2>${
|
|
31101
|
-
<p><a href="${
|
|
31560
|
+
<div><h2>${escapeHtml48(link.label)}</h2>${link.description ? `<p>${escapeHtml48(link.description)}</p>` : ""}</div>
|
|
31561
|
+
<p><a href="${escapeHtml48(link.href)}">Open ${escapeHtml48(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml48(link.statusHref)}">Status</a>` : ""}</p>
|
|
31102
31562
|
</article>`).join("");
|
|
31103
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
31104
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
31563
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml48(session.sessionId)}</td><td>${escapeHtml48(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml48(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
31564
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml48(event.kind)}</td><td>${escapeHtml48(event.provider ?? "unknown")}</td><td>${escapeHtml48(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml48(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
31105
31565
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
31106
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31566
|
+
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{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>${escapeHtml48(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 ${escapeHtml48(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
|
|
31107
31567
|
};
|
|
31108
31568
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
31109
31569
|
const path = options.path ?? "/ops-console";
|
|
31110
|
-
const routes = new
|
|
31570
|
+
const routes = new Elysia51({
|
|
31111
31571
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
31112
31572
|
});
|
|
31113
31573
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -31124,7 +31584,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
31124
31584
|
return routes;
|
|
31125
31585
|
};
|
|
31126
31586
|
// src/incidentBundle.ts
|
|
31127
|
-
import { Elysia as
|
|
31587
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
31128
31588
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
31129
31589
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
31130
31590
|
return false;
|
|
@@ -31325,7 +31785,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
31325
31785
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
31326
31786
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
31327
31787
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
31328
|
-
const routes = new
|
|
31788
|
+
const routes = new Elysia52({
|
|
31329
31789
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
31330
31790
|
});
|
|
31331
31791
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -31526,19 +31986,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
31526
31986
|
};
|
|
31527
31987
|
};
|
|
31528
31988
|
// src/opsStatusRoutes.ts
|
|
31529
|
-
import { Elysia as
|
|
31530
|
-
var
|
|
31989
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
31990
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31531
31991
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
31532
31992
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
31533
31993
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
31534
31994
|
const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("auditTotal" in surface) ? `${surface.auditTotal + surface.traceTotal} deliveries` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
|
|
31535
|
-
return `<article class="surface ${
|
|
31995
|
+
return `<article class="surface ${escapeHtml49(surface.status)}"><span>${escapeHtml49(surface.status.toUpperCase())}</span><h2>${escapeHtml49(key)}</h2><strong>${escapeHtml49(value)}</strong></article>`;
|
|
31536
31996
|
}).join("");
|
|
31537
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31997
|
+
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:#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>${escapeHtml49(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml49(report.status)}">Overall: ${escapeHtml49(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
|
|
31538
31998
|
};
|
|
31539
31999
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
31540
32000
|
const path = options.path ?? "/api/voice/ops-status";
|
|
31541
|
-
const routes = new
|
|
32001
|
+
const routes = new Elysia53({
|
|
31542
32002
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
31543
32003
|
});
|
|
31544
32004
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -31971,8 +32431,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
31971
32431
|
};
|
|
31972
32432
|
};
|
|
31973
32433
|
// src/traceDeliveryRoutes.ts
|
|
31974
|
-
import { Elysia as
|
|
31975
|
-
var
|
|
32434
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
32435
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31976
32436
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
31977
32437
|
var getNumber12 = (value) => {
|
|
31978
32438
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -32053,14 +32513,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
32053
32513
|
if (entries.length === 0) {
|
|
32054
32514
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
32055
32515
|
}
|
|
32056
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
32516
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml50(sinkId)}</strong>: ${escapeHtml50(result.status)}${result.deliveredTo ? ` to ${escapeHtml50(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml50(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
32057
32517
|
};
|
|
32058
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
32518
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml50(event.type)} <small>${escapeHtml50(event.id)}</small>${event.sessionId ? ` session=${escapeHtml50(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
32059
32519
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
32060
32520
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
32061
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
32062
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
32063
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32521
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml50(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
32522
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml50(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml50(delivery.deliveryStatus)}</span><h2>${escapeHtml50(delivery.id)}</h2><p>${escapeHtml50(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml50(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml50(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
32523
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#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>${escapeHtml50(title)}</h1><p>Checked ${escapeHtml50(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid3(report)}<section class="deliveries">${rows || "<p>No trace deliveries match this filter.</p>"}</section></main></body></html>`;
|
|
32064
32524
|
};
|
|
32065
32525
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
32066
32526
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -32080,7 +32540,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
32080
32540
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
32081
32541
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
32082
32542
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
32083
|
-
const routes = new
|
|
32543
|
+
const routes = new Elysia54({
|
|
32084
32544
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
32085
32545
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
32086
32546
|
if (htmlPath !== false) {
|
|
@@ -32177,7 +32637,7 @@ var createVoiceMemoryStore = () => {
|
|
|
32177
32637
|
return { get, getOrCreate, list, remove, set };
|
|
32178
32638
|
};
|
|
32179
32639
|
// src/opsWebhook.ts
|
|
32180
|
-
import { Elysia as
|
|
32640
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
32181
32641
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
32182
32642
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
32183
32643
|
const encoder = new TextEncoder;
|
|
@@ -32307,7 +32767,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
32307
32767
|
};
|
|
32308
32768
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
32309
32769
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
32310
|
-
return new
|
|
32770
|
+
return new Elysia55().post(path, async ({ body, request, set }) => {
|
|
32311
32771
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
32312
32772
|
if (options.signingSecret) {
|
|
32313
32773
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -32762,7 +33222,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
32762
33222
|
};
|
|
32763
33223
|
};
|
|
32764
33224
|
// src/postCallAnalysis.ts
|
|
32765
|
-
import { Elysia as
|
|
33225
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
32766
33226
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
32767
33227
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
32768
33228
|
var getPathValue3 = (source, path) => {
|
|
@@ -32941,7 +33401,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
32941
33401
|
};
|
|
32942
33402
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
32943
33403
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
32944
|
-
const routes = new
|
|
33404
|
+
const routes = new Elysia56({
|
|
32945
33405
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
32946
33406
|
});
|
|
32947
33407
|
routes.get(path, async ({ query }) => {
|
|
@@ -32966,7 +33426,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
32966
33426
|
return routes;
|
|
32967
33427
|
};
|
|
32968
33428
|
// src/guardrails.ts
|
|
32969
|
-
import { Elysia as
|
|
33429
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
32970
33430
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
32971
33431
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
32972
33432
|
var matchesRule = async (rule, input) => {
|
|
@@ -33268,7 +33728,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
33268
33728
|
};
|
|
33269
33729
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
33270
33730
|
const path = options.path ?? "/api/voice/guardrails";
|
|
33271
|
-
const routes = new
|
|
33731
|
+
const routes = new Elysia57({
|
|
33272
33732
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
33273
33733
|
});
|
|
33274
33734
|
routes.all(path, async ({ request }) => {
|
|
@@ -33792,6 +34252,8 @@ export {
|
|
|
33792
34252
|
renderVoiceScenarioEvalHTML,
|
|
33793
34253
|
renderVoiceResilienceHTML,
|
|
33794
34254
|
renderVoiceReconnectContractHTML,
|
|
34255
|
+
renderVoiceRealtimeChannelMarkdown,
|
|
34256
|
+
renderVoiceRealtimeChannelHTML,
|
|
33795
34257
|
renderVoiceQualityHTML,
|
|
33796
34258
|
renderVoiceProviderSloMarkdown,
|
|
33797
34259
|
renderVoiceProviderSloHTML,
|
|
@@ -33829,6 +34291,8 @@ export {
|
|
|
33829
34291
|
renderVoiceDeliveryRuntimeHTML,
|
|
33830
34292
|
renderVoiceDataControlMarkdown,
|
|
33831
34293
|
renderVoiceDataControlHTML,
|
|
34294
|
+
renderVoiceCompetitiveCoverageMarkdown,
|
|
34295
|
+
renderVoiceCompetitiveCoverageHTML,
|
|
33832
34296
|
renderVoiceCampaignsHTML,
|
|
33833
34297
|
renderVoiceCampaignObservabilityHTML,
|
|
33834
34298
|
renderVoiceCallReviewMarkdown,
|
|
@@ -33885,6 +34349,7 @@ export {
|
|
|
33885
34349
|
evaluateVoiceTelephonyWebhookNormalizationEvidence,
|
|
33886
34350
|
evaluateVoiceTelephonyContract,
|
|
33887
34351
|
evaluateVoiceSimulationSuiteEvidence,
|
|
34352
|
+
evaluateVoiceRealtimeChannelEvidence,
|
|
33888
34353
|
evaluateVoiceQuality,
|
|
33889
34354
|
evaluateVoiceProviderStackGaps,
|
|
33890
34355
|
evaluateVoiceProviderStackEvidence,
|
|
@@ -33905,6 +34370,7 @@ export {
|
|
|
33905
34370
|
evaluateVoiceLiveOpsControlEvidence,
|
|
33906
34371
|
evaluateVoiceGuardrailPolicy,
|
|
33907
34372
|
evaluateVoiceDataControlEvidence,
|
|
34373
|
+
evaluateVoiceCompetitiveCoverage,
|
|
33908
34374
|
evaluateVoiceCampaignReadinessEvidence,
|
|
33909
34375
|
evaluateVoiceCampaignDialerProofEvidence,
|
|
33910
34376
|
evaluateVoiceAgentSquadContractEvidence,
|
|
@@ -34013,6 +34479,7 @@ export {
|
|
|
34013
34479
|
createVoiceRedisPlivoWebhookNonceStore,
|
|
34014
34480
|
createVoiceRedisIdempotencyStore,
|
|
34015
34481
|
createVoiceReconnectContractRoutes,
|
|
34482
|
+
createVoiceRealtimeChannelRoutes,
|
|
34016
34483
|
createVoiceReadinessProfile,
|
|
34017
34484
|
createVoiceQualityRoutes,
|
|
34018
34485
|
createVoiceProviderSloRoutes,
|
|
@@ -34145,6 +34612,7 @@ export {
|
|
|
34145
34612
|
createVoiceDeliveryRuntimePresetConfig,
|
|
34146
34613
|
createVoiceDeliveryRuntime,
|
|
34147
34614
|
createVoiceDataControlRoutes,
|
|
34615
|
+
createVoiceCompetitiveCoverageRoutes,
|
|
34148
34616
|
createVoiceCampaignWorkerLoop,
|
|
34149
34617
|
createVoiceCampaignWorker,
|
|
34150
34618
|
createVoiceCampaignTelephonyOutcomeHandler,
|
|
@@ -34215,6 +34683,7 @@ export {
|
|
|
34215
34683
|
buildVoiceTelephonyWebhookSecurityReport,
|
|
34216
34684
|
buildVoiceSloReadinessThresholdReport,
|
|
34217
34685
|
buildVoiceSloCalibrationReport,
|
|
34686
|
+
buildVoiceRealtimeChannelReport,
|
|
34218
34687
|
buildVoiceProviderSloReport,
|
|
34219
34688
|
buildVoiceProviderOrchestrationReport,
|
|
34220
34689
|
buildVoiceProviderDecisionTraceReport,
|
|
@@ -34246,6 +34715,7 @@ export {
|
|
|
34246
34715
|
buildVoiceDeliveryRuntimeReport,
|
|
34247
34716
|
buildVoiceDataRetentionPlan,
|
|
34248
34717
|
buildVoiceDataControlReport,
|
|
34718
|
+
buildVoiceCompetitiveCoverageReport,
|
|
34249
34719
|
buildVoiceCampaignObservabilityReport,
|
|
34250
34720
|
buildVoiceAuditTrailReport,
|
|
34251
34721
|
buildVoiceAuditExport,
|
|
@@ -34257,6 +34727,7 @@ export {
|
|
|
34257
34727
|
assertVoiceTelephonyWebhookNormalizationEvidence,
|
|
34258
34728
|
assertVoiceSloCalibration,
|
|
34259
34729
|
assertVoiceSimulationSuiteEvidence,
|
|
34730
|
+
assertVoiceRealtimeChannelEvidence,
|
|
34260
34731
|
assertVoiceProviderStackEvidence,
|
|
34261
34732
|
assertVoiceProviderSloEvidence,
|
|
34262
34733
|
assertVoiceProviderRoutingContractEvidence,
|
|
@@ -34278,6 +34749,7 @@ export {
|
|
|
34278
34749
|
assertVoiceLiveOpsControlEvidence,
|
|
34279
34750
|
assertVoiceLatencySLOGate,
|
|
34280
34751
|
assertVoiceDataControlEvidence,
|
|
34752
|
+
assertVoiceCompetitiveCoverage,
|
|
34281
34753
|
assertVoiceCampaignReadinessEvidence,
|
|
34282
34754
|
assertVoiceCampaignDialerProofEvidence,
|
|
34283
34755
|
assertVoiceAgentSquadContractEvidence,
|