@absolutejs/voice 0.0.22-beta.343 → 0.0.22-beta.345
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/browserCallProfiles.d.ts +120 -0
- package/dist/client/index.js +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +606 -412
- package/dist/react/index.js +3 -0
- package/dist/vue/index.js +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12835,9 +12835,194 @@ var createVoiceBrowserMediaRoutes = (options) => {
|
|
|
12835
12835
|
}
|
|
12836
12836
|
return routes;
|
|
12837
12837
|
};
|
|
12838
|
-
// src/
|
|
12838
|
+
// src/browserCallProfiles.ts
|
|
12839
12839
|
import { Elysia as Elysia15 } from "elysia";
|
|
12840
|
+
var DEFAULT_MAX_AGE_MS = 10 * 60 * 1000;
|
|
12840
12841
|
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12842
|
+
var toTime = (value) => {
|
|
12843
|
+
if (value === undefined) {
|
|
12844
|
+
return;
|
|
12845
|
+
}
|
|
12846
|
+
const time = value instanceof Date ? value.getTime() : new Date(value).getTime();
|
|
12847
|
+
return Number.isFinite(time) ? time : undefined;
|
|
12848
|
+
};
|
|
12849
|
+
var uniqueStrings = (values) => Array.from(new Set(values.filter((value) => !!value)));
|
|
12850
|
+
var normalizeNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
12851
|
+
var summarizeResults = (results, inputSummary) => {
|
|
12852
|
+
const passedFrameworks = uniqueStrings(results.filter((result) => result.ok === true).map((result) => result.framework));
|
|
12853
|
+
const failedFrameworks = uniqueStrings(results.filter((result) => result.ok === false).map((result) => result.framework));
|
|
12854
|
+
const totals = results.reduce((summary, result) => ({
|
|
12855
|
+
messageCount: summary.messageCount + normalizeNumber(result.summary?.messageCount),
|
|
12856
|
+
openSockets: summary.openSockets + normalizeNumber(result.summary?.openSockets),
|
|
12857
|
+
receivedBytes: summary.receivedBytes + normalizeNumber(result.summary?.receivedBytes),
|
|
12858
|
+
sentBytes: summary.sentBytes + normalizeNumber(result.summary?.sentBytes)
|
|
12859
|
+
}), { messageCount: 0, openSockets: 0, receivedBytes: 0, sentBytes: 0 });
|
|
12860
|
+
return {
|
|
12861
|
+
failedFrameworks: inputSummary?.failedFrameworks && inputSummary.failedFrameworks.length > 0 ? inputSummary.failedFrameworks : failedFrameworks,
|
|
12862
|
+
openSockets: normalizeNumber(inputSummary?.openSockets) || totals.openSockets,
|
|
12863
|
+
passedFrameworks: inputSummary?.passedFrameworks && inputSummary.passedFrameworks.length > 0 ? inputSummary.passedFrameworks : passedFrameworks,
|
|
12864
|
+
receivedBytes: normalizeNumber(inputSummary?.receivedBytes) || totals.receivedBytes,
|
|
12865
|
+
sentBytes: normalizeNumber(inputSummary?.sentBytes) || totals.sentBytes,
|
|
12866
|
+
totalFrameworks: normalizeNumber(inputSummary?.totalFrameworks) || results.length,
|
|
12867
|
+
totalMessages: normalizeNumber(inputSummary?.totalMessages) || normalizeNumber(inputSummary?.messageCount) || totals.messageCount
|
|
12868
|
+
};
|
|
12869
|
+
};
|
|
12870
|
+
var buildVoiceBrowserCallProfileReport = (input = {}) => {
|
|
12871
|
+
const generatedAtTime = toTime(input.generatedAt) ?? Date.now();
|
|
12872
|
+
const generatedAt = new Date(generatedAtTime).toISOString();
|
|
12873
|
+
const now = toTime(input.now) ?? Date.now();
|
|
12874
|
+
const maxAgeMs = input.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
12875
|
+
const ageMs = Math.max(0, input.ageMs ?? now - generatedAtTime);
|
|
12876
|
+
const stale = ageMs > maxAgeMs;
|
|
12877
|
+
const results = input.results ?? [];
|
|
12878
|
+
const frameworks = uniqueStrings([
|
|
12879
|
+
...input.frameworks ?? [],
|
|
12880
|
+
...results.map((result) => result.framework)
|
|
12881
|
+
]);
|
|
12882
|
+
const summary = summarizeResults(results, input.summary);
|
|
12883
|
+
const hasFailures = results.some((result) => result.ok === false) || summary.failedFrameworks.length > 0;
|
|
12884
|
+
const allFrameworksPassed = frameworks.length > 0 && frameworks.every((framework) => summary.passedFrameworks.includes(framework));
|
|
12885
|
+
const status = input.status ?? (results.length === 0 ? "empty" : stale ? "stale" : hasFailures ? "fail" : allFrameworksPassed ? "pass" : "warn");
|
|
12886
|
+
return {
|
|
12887
|
+
ageMs,
|
|
12888
|
+
baseUrl: input.baseUrl,
|
|
12889
|
+
frameworks,
|
|
12890
|
+
freshUntil: input.freshUntil ?? new Date(generatedAtTime + maxAgeMs).toISOString(),
|
|
12891
|
+
generatedAt,
|
|
12892
|
+
maxAgeMs,
|
|
12893
|
+
ok: input.ok ?? status === "pass",
|
|
12894
|
+
outputDir: input.outputDir,
|
|
12895
|
+
profileId: input.profileId ?? "browser-call-framework-parity",
|
|
12896
|
+
results,
|
|
12897
|
+
runId: input.runId,
|
|
12898
|
+
source: input.source ?? "browser-call-profile",
|
|
12899
|
+
status,
|
|
12900
|
+
summary
|
|
12901
|
+
};
|
|
12902
|
+
};
|
|
12903
|
+
var evaluateVoiceBrowserCallProfileEvidence = (report, input = {}) => {
|
|
12904
|
+
const normalized = buildVoiceBrowserCallProfileReport(report);
|
|
12905
|
+
const issues = [];
|
|
12906
|
+
const requiredFrameworks = input.requiredFrameworks && input.requiredFrameworks.length > 0 ? input.requiredFrameworks : normalized.frameworks;
|
|
12907
|
+
const minOpenSockets = input.minOpenSocketsPerFramework ?? 1;
|
|
12908
|
+
const minSentBytes = input.minSentBytesPerFramework ?? 1;
|
|
12909
|
+
const minMessages = input.minMessageCountPerFramework ?? 0;
|
|
12910
|
+
const maxAgeMs = input.maxAgeMs ?? normalized.maxAgeMs;
|
|
12911
|
+
if (normalized.ageMs !== undefined && normalized.ageMs > maxAgeMs) {
|
|
12912
|
+
issues.push(`Browser call profile is stale: ${normalized.ageMs}ms exceeds ${maxAgeMs}ms.`);
|
|
12913
|
+
}
|
|
12914
|
+
for (const framework of requiredFrameworks) {
|
|
12915
|
+
const result = normalized.results.find((candidate) => candidate.framework === framework);
|
|
12916
|
+
if (!result) {
|
|
12917
|
+
issues.push(`Missing browser call evidence for ${framework}.`);
|
|
12918
|
+
continue;
|
|
12919
|
+
}
|
|
12920
|
+
if (result.ok !== true) {
|
|
12921
|
+
issues.push(`${framework} browser call did not pass${result.error ? `: ${result.error}` : "."}`);
|
|
12922
|
+
}
|
|
12923
|
+
if (normalizeNumber(result.summary?.openSockets) < minOpenSockets) {
|
|
12924
|
+
issues.push(`${framework} opened ${normalizeNumber(result.summary?.openSockets)} WebSocket(s); expected at least ${minOpenSockets}.`);
|
|
12925
|
+
}
|
|
12926
|
+
if (normalizeNumber(result.summary?.sentBytes) < minSentBytes) {
|
|
12927
|
+
issues.push(`${framework} sent ${normalizeNumber(result.summary?.sentBytes)} byte(s); expected at least ${minSentBytes}.`);
|
|
12928
|
+
}
|
|
12929
|
+
if (normalizeNumber(result.summary?.messageCount) < minMessages) {
|
|
12930
|
+
issues.push(`${framework} observed ${normalizeNumber(result.summary?.messageCount)} WebSocket message(s); expected at least ${minMessages}.`);
|
|
12931
|
+
}
|
|
12932
|
+
}
|
|
12933
|
+
if (input.requireAllFrameworksPass ?? true) {
|
|
12934
|
+
for (const framework of normalized.frameworks) {
|
|
12935
|
+
if (!normalized.summary.passedFrameworks.includes(framework)) {
|
|
12936
|
+
issues.push(`${framework} is listed but not passing.`);
|
|
12937
|
+
}
|
|
12938
|
+
}
|
|
12939
|
+
}
|
|
12940
|
+
return {
|
|
12941
|
+
failedFrameworks: normalized.summary.failedFrameworks,
|
|
12942
|
+
issues: Array.from(new Set(issues)),
|
|
12943
|
+
ok: issues.length === 0 && normalized.status === "pass",
|
|
12944
|
+
passedFrameworks: normalized.summary.passedFrameworks,
|
|
12945
|
+
status: normalized.status,
|
|
12946
|
+
summary: normalized.summary
|
|
12947
|
+
};
|
|
12948
|
+
};
|
|
12949
|
+
var assertVoiceBrowserCallProfileEvidence = (report, input = {}) => {
|
|
12950
|
+
const assertion = evaluateVoiceBrowserCallProfileEvidence(report, input);
|
|
12951
|
+
if (!assertion.ok) {
|
|
12952
|
+
throw new Error(assertion.issues.join(`
|
|
12953
|
+
`) || "Browser call profile failed.");
|
|
12954
|
+
}
|
|
12955
|
+
return assertion;
|
|
12956
|
+
};
|
|
12957
|
+
var renderVoiceBrowserCallProfileMarkdown = (report, options = {}) => {
|
|
12958
|
+
const normalized = buildVoiceBrowserCallProfileReport(report);
|
|
12959
|
+
const title = options.title ?? "Voice Browser Call Profiles";
|
|
12960
|
+
const rows = normalized.results.map((result) => `| ${result.framework} | ${result.ok ? "pass" : "fail"} | ${result.summary?.openSockets ?? 0} | ${result.summary?.sentBytes ?? 0} | ${result.summary?.receivedBytes ?? 0} | ${result.summary?.messageCount ?? 0} | ${result.error ?? ""} |`).join(`
|
|
12961
|
+
`);
|
|
12962
|
+
return [
|
|
12963
|
+
`# ${title}`,
|
|
12964
|
+
"",
|
|
12965
|
+
`Status: ${normalized.status}`,
|
|
12966
|
+
`Generated: ${normalized.generatedAt}`,
|
|
12967
|
+
`Fresh until: ${normalized.freshUntil ?? "unknown"}`,
|
|
12968
|
+
"",
|
|
12969
|
+
`Passed frameworks: ${normalized.summary.passedFrameworks.join(", ") || "none"}`,
|
|
12970
|
+
`Failed frameworks: ${normalized.summary.failedFrameworks.join(", ") || "none"}`,
|
|
12971
|
+
"",
|
|
12972
|
+
"| Framework | Status | WebSockets | Sent bytes | Received bytes | Messages | Error |",
|
|
12973
|
+
"| --- | --- | ---: | ---: | ---: | ---: | --- |",
|
|
12974
|
+
rows || "| none | empty | 0 | 0 | 0 | 0 | |"
|
|
12975
|
+
].join(`
|
|
12976
|
+
`);
|
|
12977
|
+
};
|
|
12978
|
+
var renderVoiceBrowserCallProfileHTML = (report, options = {}) => {
|
|
12979
|
+
const normalized = buildVoiceBrowserCallProfileReport(report);
|
|
12980
|
+
const title = options.title ?? "Voice Browser Call Profiles";
|
|
12981
|
+
const rows = normalized.results.map((result) => `<tr><td>${escapeHtml18(result.framework)}</td><td class="${result.ok ? "pass" : "fail"}">${result.ok ? "pass" : "fail"}</td><td>${String(result.summary?.openSockets ?? 0)}</td><td>${String(result.summary?.sentBytes ?? 0)}</td><td>${String(result.summary?.receivedBytes ?? 0)}</td><td>${String(result.summary?.messageCount ?? 0)}</td><td>${escapeHtml18(result.error ?? "")}</td></tr>`).join("");
|
|
12982
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml18(title)}</title><style>body{background:#11140f;color:#f4f0df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,.primitive,table{background:#191d15;border:1px solid #323a27;border-radius:22px;margin-bottom:16px}.hero,.primitive{padding:22px}.eyebrow{color:#bef264;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#bef264}.warn,.empty,.stale{color:#fde68a}.fail{color:#fecaca}.metrics{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin-top:18px}.metric{background:#10130d;border:1px solid #303827;border-radius:16px;padding:14px}.metric span{color:#b8c3a3}.metric strong{display:block;font-size:1.7rem;margin-top:4px}.primitive code{color:#d9f99d}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #323a27;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real browser microphone proof</p><h1>${escapeHtml18(title)}</h1><p class="status ${escapeHtml18(normalized.status)}">Status: ${escapeHtml18(normalized.status)}</p><p>Framework parity proof from real browser pages opening the voice WebSocket and sending microphone audio bytes.</p><section class="metrics"><div class="metric"><span>Frameworks</span><strong>${String(normalized.summary.totalFrameworks)}</strong></div><div class="metric"><span>Passing</span><strong>${String(normalized.summary.passedFrameworks.length)}</strong></div><div class="metric"><span>Open sockets</span><strong>${String(normalized.summary.openSockets)}</strong></div><div class="metric"><span>Sent bytes</span><strong>${String(normalized.summary.sentBytes)}</strong></div><div class="metric"><span>Received bytes</span><strong>${String(normalized.summary.receivedBytes)}</strong></div><div class="metric"><span>Messages</span><strong>${String(normalized.summary.totalMessages)}</strong></div></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><p><code>buildVoiceBrowserCallProfileReport(...)</code> normalizes browser-call evidence. <code>evaluateVoiceBrowserCallProfileEvidence(...)</code> gates required frameworks, WebSocket opens, sent bytes, and freshness. <code>createVoiceBrowserCallProfileRoutes(...)</code> serves JSON, HTML, and Markdown.</p></section><table><thead><tr><th>Framework</th><th>Status</th><th>WebSockets</th><th>Sent bytes</th><th>Received bytes</th><th>Messages</th><th>Error</th></tr></thead><tbody>${rows || '<tr><td colspan="7">No browser call profile evidence yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
12983
|
+
};
|
|
12984
|
+
var resolveSource = async (options) => {
|
|
12985
|
+
const source = typeof options.source === "function" ? await options.source() : options.source;
|
|
12986
|
+
return buildVoiceBrowserCallProfileReport({
|
|
12987
|
+
maxAgeMs: options.maxAgeMs,
|
|
12988
|
+
...source ?? {}
|
|
12989
|
+
});
|
|
12990
|
+
};
|
|
12991
|
+
var createVoiceBrowserCallProfileRoutes = (options = {}) => {
|
|
12992
|
+
const jsonPath = options.jsonPath ?? "/api/voice/browser-call-profiles";
|
|
12993
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/browser-call-profiles" : options.htmlPath;
|
|
12994
|
+
const markdownPath = options.markdownPath === undefined ? "/voice/browser-call-profiles.md" : options.markdownPath;
|
|
12995
|
+
const routes = new Elysia15({
|
|
12996
|
+
name: options.name ?? "absolutejs-voice-browser-call-profiles"
|
|
12997
|
+
});
|
|
12998
|
+
routes.get(jsonPath, () => resolveSource(options));
|
|
12999
|
+
if (htmlPath) {
|
|
13000
|
+
routes.get(htmlPath, async () => {
|
|
13001
|
+
const report = await resolveSource(options);
|
|
13002
|
+
return new Response(renderVoiceBrowserCallProfileHTML(report, options), {
|
|
13003
|
+
headers: {
|
|
13004
|
+
"content-type": "text/html; charset=utf-8",
|
|
13005
|
+
...options.headers
|
|
13006
|
+
}
|
|
13007
|
+
});
|
|
13008
|
+
});
|
|
13009
|
+
}
|
|
13010
|
+
if (markdownPath) {
|
|
13011
|
+
routes.get(markdownPath, async () => {
|
|
13012
|
+
const report = await resolveSource(options);
|
|
13013
|
+
return new Response(renderVoiceBrowserCallProfileMarkdown(report, options), {
|
|
13014
|
+
headers: {
|
|
13015
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
13016
|
+
...options.headers
|
|
13017
|
+
}
|
|
13018
|
+
});
|
|
13019
|
+
});
|
|
13020
|
+
}
|
|
13021
|
+
return routes;
|
|
13022
|
+
};
|
|
13023
|
+
// src/demoReadyRoutes.ts
|
|
13024
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
13025
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12841
13026
|
var rollupStatus2 = (sections) => sections.some((section) => section.status === "fail") ? "fail" : sections.some((section) => section.status === "warn") ? "warn" : "pass";
|
|
12842
13027
|
var resolveLoader = async (loader, input) => typeof loader === "function" ? await loader(input) : loader;
|
|
12843
13028
|
var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
@@ -12921,17 +13106,17 @@ var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
|
12921
13106
|
};
|
|
12922
13107
|
};
|
|
12923
13108
|
var renderVoiceDemoReadyHTML = (report) => {
|
|
12924
|
-
const sections = report.sections.map((section) => `<article class="section ${
|
|
12925
|
-
<div><span>${
|
|
12926
|
-
<strong>${
|
|
12927
|
-
${section.href ? `<a href="${
|
|
13109
|
+
const sections = report.sections.map((section) => `<article class="section ${escapeHtml19(section.status)}">
|
|
13110
|
+
<div><span>${escapeHtml19(section.status.toUpperCase())}</span><h2>${escapeHtml19(section.label)}</h2>${section.description ? `<p>${escapeHtml19(section.description)}</p>` : ""}</div>
|
|
13111
|
+
<strong>${escapeHtml19(String(section.value ?? section.status))}</strong>
|
|
13112
|
+
${section.href ? `<a href="${escapeHtml19(section.href)}">Open</a>` : ""}
|
|
12928
13113
|
</article>`).join("");
|
|
12929
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13114
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(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>${escapeHtml19(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 ${escapeHtml19(report.status)}">Overall: ${escapeHtml19(report.status.toUpperCase())}</p><p>Checked ${escapeHtml19(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>`;
|
|
12930
13115
|
};
|
|
12931
13116
|
var createVoiceDemoReadyRoutes = (options) => {
|
|
12932
13117
|
const path = options.path ?? "/api/demo-ready";
|
|
12933
13118
|
const htmlPath = options.htmlPath ?? "/demo-ready";
|
|
12934
|
-
const routes = new
|
|
13119
|
+
const routes = new Elysia16({
|
|
12935
13120
|
name: options.name ?? "absolutejs-voice-demo-ready"
|
|
12936
13121
|
});
|
|
12937
13122
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
@@ -12950,7 +13135,7 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
12950
13135
|
return routes;
|
|
12951
13136
|
};
|
|
12952
13137
|
// src/deliverySinkRoutes.ts
|
|
12953
|
-
import { Elysia as
|
|
13138
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
12954
13139
|
|
|
12955
13140
|
// src/queue.ts
|
|
12956
13141
|
var releaseLeaseScript = `
|
|
@@ -13893,7 +14078,7 @@ var createVoiceOpsTaskProcessorWorkerLoop = (options) => {
|
|
|
13893
14078
|
};
|
|
13894
14079
|
|
|
13895
14080
|
// src/deliverySinkRoutes.ts
|
|
13896
|
-
var
|
|
14081
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13897
14082
|
var deliveryStatus = (summary) => {
|
|
13898
14083
|
if (!summary) {
|
|
13899
14084
|
return "warn";
|
|
@@ -13992,13 +14177,13 @@ var renderSurfaceCard = (surface) => {
|
|
|
13992
14177
|
return "";
|
|
13993
14178
|
}
|
|
13994
14179
|
const value = `${surface.summary.delivered}/${surface.summary.total}`;
|
|
13995
|
-
const body = `<span>${
|
|
13996
|
-
return `<article>${surface.href ? `<a href="${
|
|
14180
|
+
const body = `<span>${escapeHtml20(surface.label)}</span><strong>${escapeHtml20(value)}</strong><p class="muted">Delivered export records.</p>`;
|
|
14181
|
+
return `<article>${surface.href ? `<a href="${escapeHtml20(surface.href)}">${body}</a>` : body}</article>`;
|
|
13997
14182
|
};
|
|
13998
14183
|
var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
13999
14184
|
const title = options.title ?? "AbsoluteJS Voice Delivery Sinks";
|
|
14000
|
-
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${
|
|
14001
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
14185
|
+
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${escapeHtml20(sink.kind)}</span><strong style="font-size:1.5rem">${escapeHtml20(sink.label)}</strong>${sink.description ? `<p class="muted">${escapeHtml20(sink.description)}</p>` : ""}${sink.mode ? `<p class="muted">Mode: ${escapeHtml20(sink.mode)}</p>` : ""}${sink.target ? `<p class="muted">Target: <code>${escapeHtml20(sink.target)}</code></p>` : ""}${sink.href ? `<p><a href="${escapeHtml20(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>';
|
|
14186
|
+
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:#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>${escapeHtml20(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 ${escapeHtml20(report.status)}">Overall: ${escapeHtml20(report.status.toUpperCase())}</p><p class="muted">Checked ${escapeHtml20(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({
|
|
14002
14187
|
auditDeliveries: { store: runtimeStorage.auditDeliveries },
|
|
14003
14188
|
traceDeliveries: { store: runtimeStorage.traceDeliveries },
|
|
14004
14189
|
sinks: createVoiceDeliverySinkPair({
|
|
@@ -14010,7 +14195,7 @@ var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
|
14010
14195
|
var createVoiceDeliverySinkRoutes = (options) => {
|
|
14011
14196
|
const path = options.path ?? "/api/voice-delivery-sinks";
|
|
14012
14197
|
const htmlPath = options.htmlPath === undefined ? "/delivery-sinks" : options.htmlPath;
|
|
14013
|
-
const routes = new
|
|
14198
|
+
const routes = new Elysia17({
|
|
14014
14199
|
name: options.name ?? "absolutejs-voice-delivery-sinks"
|
|
14015
14200
|
}).get(path, () => buildVoiceDeliverySinkReport(options));
|
|
14016
14201
|
if (htmlPath !== false) {
|
|
@@ -14028,7 +14213,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
|
|
|
14028
14213
|
return routes;
|
|
14029
14214
|
};
|
|
14030
14215
|
// src/opsActionAuditRoutes.ts
|
|
14031
|
-
import { Elysia as
|
|
14216
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
14032
14217
|
var readRecordBody = (body) => {
|
|
14033
14218
|
if (!body || typeof body !== "object") {
|
|
14034
14219
|
throw new Error("Voice ops action audit requires a JSON body.");
|
|
@@ -14103,7 +14288,7 @@ var createVoiceOpsActionAuditRoutes = (options) => {
|
|
|
14103
14288
|
const path = options.path ?? "/api/voice/ops-actions/audit";
|
|
14104
14289
|
const historyPath = options.historyPath === undefined ? "/api/voice/ops-actions/history" : options.historyPath;
|
|
14105
14290
|
const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
|
|
14106
|
-
const routes = new
|
|
14291
|
+
const routes = new Elysia18({
|
|
14107
14292
|
name: options.name ?? "absolutejs-voice-ops-action-audit"
|
|
14108
14293
|
}).post(path, async ({ body, request, set }) => {
|
|
14109
14294
|
try {
|
|
@@ -14153,13 +14338,13 @@ var buildVoiceOpsActionHistoryReport = async (options) => {
|
|
|
14153
14338
|
total: entries.length
|
|
14154
14339
|
};
|
|
14155
14340
|
};
|
|
14156
|
-
var
|
|
14341
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14157
14342
|
var renderVoiceOpsActionHistoryHTML = (report) => {
|
|
14158
|
-
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${
|
|
14343
|
+
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${escapeHtml21(entry.ok ? "success" : "error")}</span><strong>${escapeHtml21(entry.actionId)}</strong><p>${escapeHtml21(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</p>${entry.error ? `<p>${escapeHtml21(entry.error)}</p>` : ""}</article>`).join("");
|
|
14159
14344
|
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>`;
|
|
14160
14345
|
};
|
|
14161
14346
|
// src/platformCoverage.ts
|
|
14162
|
-
import { Elysia as
|
|
14347
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
14163
14348
|
var buildVoicePlatformCoverageSummary = (input) => {
|
|
14164
14349
|
const coverage = input.coverage ?? [];
|
|
14165
14350
|
const ok = input.ok ?? (coverage.length > 0 && coverage.every((surface) => surface.status === "pass"));
|
|
@@ -14220,7 +14405,7 @@ var assertVoicePlatformCoverage = (summary, input = {}) => {
|
|
|
14220
14405
|
var normalizeCoverageSummary = (value) => ("status" in value) && ("total" in value) && ("coverage" in value) ? value : buildVoicePlatformCoverageSummary(value);
|
|
14221
14406
|
var createVoicePlatformCoverageRoutes = (options) => {
|
|
14222
14407
|
const path = options.path ?? "/api/voice/platform-coverage";
|
|
14223
|
-
const routes = new
|
|
14408
|
+
const routes = new Elysia19({
|
|
14224
14409
|
name: options.name ?? "absolutejs-voice-platform-coverage"
|
|
14225
14410
|
});
|
|
14226
14411
|
routes.get(path, async () => {
|
|
@@ -14232,8 +14417,8 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
14232
14417
|
return routes;
|
|
14233
14418
|
};
|
|
14234
14419
|
// src/competitiveCoverage.ts
|
|
14235
|
-
import { Elysia as
|
|
14236
|
-
var
|
|
14420
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
14421
|
+
var escapeHtml22 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14237
14422
|
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
14238
14423
|
var resolveSurfaceStatus = (surface) => {
|
|
14239
14424
|
if (surface.status)
|
|
@@ -14401,24 +14586,24 @@ var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive
|
|
|
14401
14586
|
`);
|
|
14402
14587
|
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
14403
14588
|
const surfaceCards = report.surfaces.map((surface) => {
|
|
14404
|
-
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${
|
|
14405
|
-
return `<article class="surface ${
|
|
14406
|
-
<header><div><p class="eyebrow">${
|
|
14407
|
-
<p>${
|
|
14589
|
+
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${escapeHtml22(item.name)}</strong>${item.kind ? ` <span>${escapeHtml22(item.kind)}</span>` : ""}${item.status ? ` <em>${escapeHtml22(item.status)}</em>` : ""}${item.href ? ` <a href="${escapeHtml22(item.href)}">open</a>` : ""}</li>`).join("");
|
|
14590
|
+
return `<article class="surface ${escapeHtml22(surface.status)} ${escapeHtml22(surface.depth)}">
|
|
14591
|
+
<header><div><p class="eyebrow">${escapeHtml22(surface.coverage)} \xB7 ${escapeHtml22(surface.depth)}</p><h2>${escapeHtml22(surface.surface)}</h2></div><strong>${escapeHtml22(surface.status)}</strong></header>
|
|
14592
|
+
<p>${escapeHtml22(surface.why)}</p>
|
|
14408
14593
|
<dl>
|
|
14409
|
-
<div><dt>Competitors</dt><dd>${
|
|
14410
|
-
<div><dt>Operations record</dt><dd>${
|
|
14411
|
-
<div><dt>Readiness gate</dt><dd>${
|
|
14412
|
-
<div><dt>Frameworks</dt><dd>${
|
|
14594
|
+
<div><dt>Competitors</dt><dd>${escapeHtml22((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
14595
|
+
<div><dt>Operations record</dt><dd>${escapeHtml22(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
14596
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml22(surface.readinessGate ?? "unknown")}</dd></div>
|
|
14597
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml22((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
14413
14598
|
</dl>
|
|
14414
|
-
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${
|
|
14415
|
-
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${
|
|
14599
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml22(surface.remainingGap)}</p>` : ""}
|
|
14600
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml22(surface.nextMove)}</p>` : ""}
|
|
14416
14601
|
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
14417
14602
|
</article>`;
|
|
14418
14603
|
}).join(`
|
|
14419
14604
|
`);
|
|
14420
|
-
const issueList = report.issues.map((issue) => `<li class="${
|
|
14421
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
14605
|
+
const issueList = report.issues.map((issue) => `<li class="${escapeHtml22(issue.severity)}"><strong>${escapeHtml22(issue.code)}</strong>${issue.surface ? ` ${escapeHtml22(issue.surface)}` : ""}: ${escapeHtml22(issue.message)}</li>`).join("");
|
|
14606
|
+
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:#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>${escapeHtml22(title)}</h1><p>Generated ${escapeHtml22(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 ${escapeHtml22(report.status)}</span><span class="pill">Vapi-style ${escapeHtml22(report.vapiCoverageEstimate)}</span><span class="pill">Market ${escapeHtml22(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>`;
|
|
14422
14607
|
};
|
|
14423
14608
|
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
14424
14609
|
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
@@ -14431,7 +14616,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
14431
14616
|
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
14432
14617
|
return normalizeCompetitiveCoverageReport(value);
|
|
14433
14618
|
};
|
|
14434
|
-
const app = new
|
|
14619
|
+
const app = new Elysia20({
|
|
14435
14620
|
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
14436
14621
|
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
14437
14622
|
headers: {
|
|
@@ -14462,7 +14647,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
14462
14647
|
return app;
|
|
14463
14648
|
};
|
|
14464
14649
|
// src/proofTrends.ts
|
|
14465
|
-
import { Elysia as
|
|
14650
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14466
14651
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
14467
14652
|
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
14468
14653
|
{
|
|
@@ -14603,6 +14788,9 @@ var aggregateProofTrendProviders = (providers) => {
|
|
|
14603
14788
|
if (!provider.id) {
|
|
14604
14789
|
continue;
|
|
14605
14790
|
}
|
|
14791
|
+
if (provider.p95Ms === undefined && provider.p50Ms === undefined && provider.averageMs === undefined && (provider.samples ?? 0) <= 0) {
|
|
14792
|
+
continue;
|
|
14793
|
+
}
|
|
14606
14794
|
const existing = providersById.get(provider.id);
|
|
14607
14795
|
providersById.set(provider.id, {
|
|
14608
14796
|
averageMs: maxNumber([existing?.averageMs, provider.averageMs]),
|
|
@@ -15136,7 +15324,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
15136
15324
|
}
|
|
15137
15325
|
};
|
|
15138
15326
|
};
|
|
15139
|
-
var
|
|
15327
|
+
var escapeHtml23 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15140
15328
|
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
15141
15329
|
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
15142
15330
|
`# ${title}`,
|
|
@@ -15169,18 +15357,18 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
15169
15357
|
].join(`
|
|
15170
15358
|
`);
|
|
15171
15359
|
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
15172
|
-
const cards = report.recommendations.map((recommendation) => `<article class="${
|
|
15173
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
15174
|
-
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${
|
|
15175
|
-
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${
|
|
15176
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15360
|
+
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml23(recommendation.status)}"><p class="eyebrow">${escapeHtml23(recommendation.surface)} \xB7 ${escapeHtml23(recommendation.status)}</p><h2>${escapeHtml23(recommendation.recommendation)}</h2><p>${escapeHtml23(recommendation.nextMove)}</p><pre>${escapeHtml23(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
15361
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml23(issue)}</li>`).join("");
|
|
15362
|
+
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml23(provider.label ?? provider.id)}</strong><span>${escapeHtml23(provider.role ?? "provider")} \xB7 ${escapeHtml23(provider.status)} \xB7 p95 ${escapeHtml23(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml23(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml23(provider.nextMove)}</small></li>`).join("");
|
|
15363
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml23(profile.label ?? profile.id)}</strong><span>${escapeHtml23(profile.status)} \xB7 ${escapeHtml23(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml23(profile.nextMove)}</small></li>`).join("");
|
|
15364
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml23(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml23(title)}</h1><p>Generated ${escapeHtml23(report.generatedAt)} from ${escapeHtml23(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml23(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml23(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
15177
15365
|
};
|
|
15178
15366
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
15179
15367
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
15180
15368
|
const htmlPath = options.htmlPath === undefined ? "/voice/proof-trend-recommendations" : options.htmlPath;
|
|
15181
15369
|
const markdownPath = options.markdownPath === undefined ? "/voice/proof-trend-recommendations.md" : options.markdownPath;
|
|
15182
15370
|
const title = options.title ?? "Voice Provider Runtime Recommendations";
|
|
15183
|
-
const routes = new
|
|
15371
|
+
const routes = new Elysia21({
|
|
15184
15372
|
name: options.name ?? "absolutejs-voice-proof-trend-recommendations"
|
|
15185
15373
|
});
|
|
15186
15374
|
const loadReport = async () => {
|
|
@@ -15219,7 +15407,7 @@ var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
|
15219
15407
|
};
|
|
15220
15408
|
var createVoiceProofTrendRoutes = (options) => {
|
|
15221
15409
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
15222
|
-
const routes = new
|
|
15410
|
+
const routes = new Elysia21({
|
|
15223
15411
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
15224
15412
|
});
|
|
15225
15413
|
routes.get(path, async () => {
|
|
@@ -15252,11 +15440,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
15252
15440
|
return `${days}d ${hours % 24}h`;
|
|
15253
15441
|
};
|
|
15254
15442
|
// src/providerDecisionTraces.ts
|
|
15255
|
-
import { Elysia as
|
|
15443
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15256
15444
|
|
|
15257
15445
|
// src/resilienceRoutes.ts
|
|
15258
|
-
import { Elysia as
|
|
15259
|
-
var
|
|
15446
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
15447
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15260
15448
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
15261
15449
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15262
15450
|
var getBoolean2 = (value) => value === true;
|
|
@@ -15404,13 +15592,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
15404
15592
|
};
|
|
15405
15593
|
var renderProviderCards = (title, providers) => {
|
|
15406
15594
|
if (providers.length === 0) {
|
|
15407
|
-
return `<p class="muted">No ${
|
|
15595
|
+
return `<p class="muted">No ${escapeHtml24(title)} provider health yet.</p>`;
|
|
15408
15596
|
}
|
|
15409
15597
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
15410
|
-
<article class="card provider ${
|
|
15598
|
+
<article class="card provider ${escapeHtml24(provider.status)}">
|
|
15411
15599
|
<div class="card-header">
|
|
15412
|
-
<strong>${
|
|
15413
|
-
<span>${
|
|
15600
|
+
<strong>${escapeHtml24(provider.provider)}</strong>
|
|
15601
|
+
<span>${escapeHtml24(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
15414
15602
|
</div>
|
|
15415
15603
|
<dl>
|
|
15416
15604
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -15419,7 +15607,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
15419
15607
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
15420
15608
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
15421
15609
|
</dl>
|
|
15422
|
-
${provider.lastError ? `<p class="muted">${
|
|
15610
|
+
${provider.lastError ? `<p class="muted">${escapeHtml24(provider.lastError)}</p>` : ""}
|
|
15423
15611
|
</article>
|
|
15424
15612
|
`).join("")}</div>`;
|
|
15425
15613
|
};
|
|
@@ -15428,24 +15616,24 @@ var renderTimeline2 = (events) => {
|
|
|
15428
15616
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
15429
15617
|
}
|
|
15430
15618
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
15431
|
-
<article class="card event ${
|
|
15619
|
+
<article class="card event ${escapeHtml24(event.status ?? "unknown")}">
|
|
15432
15620
|
<div class="card-header">
|
|
15433
|
-
<strong>${
|
|
15621
|
+
<strong>${escapeHtml24(event.kind.toUpperCase())} ${escapeHtml24(event.operation ?? "generate")}</strong>
|
|
15434
15622
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
15435
15623
|
</div>
|
|
15436
15624
|
<p>
|
|
15437
|
-
<span class="pill">${
|
|
15438
|
-
<span class="pill">provider: ${
|
|
15439
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
15625
|
+
<span class="pill">${escapeHtml24(event.status ?? "unknown")}</span>
|
|
15626
|
+
<span class="pill">provider: ${escapeHtml24(event.provider ?? "unknown")}</span>
|
|
15627
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml24(event.fallbackProvider)}</span>` : ""}
|
|
15440
15628
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
15441
15629
|
</p>
|
|
15442
15630
|
<dl>
|
|
15443
15631
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
15444
15632
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
15445
15633
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
15446
|
-
<div><dt>Session</dt><dd>${
|
|
15634
|
+
<div><dt>Session</dt><dd>${escapeHtml24(event.sessionId)}</dd></div>
|
|
15447
15635
|
</dl>
|
|
15448
|
-
${event.error ? `<p class="muted">${
|
|
15636
|
+
${event.error ? `<p class="muted">${escapeHtml24(event.error)}</p>` : ""}
|
|
15449
15637
|
</article>
|
|
15450
15638
|
`).join("")}</div>`;
|
|
15451
15639
|
};
|
|
@@ -15455,9 +15643,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
15455
15643
|
const status = latest?.status ?? "idle";
|
|
15456
15644
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
15457
15645
|
return `<div>
|
|
15458
|
-
<dt>${
|
|
15459
|
-
<dd>${
|
|
15460
|
-
<small>${
|
|
15646
|
+
<dt>${escapeHtml24(kind.toUpperCase())}</dt>
|
|
15647
|
+
<dd>${escapeHtml24(provider)}${escapeHtml24(fallback)}</dd>
|
|
15648
|
+
<small>${escapeHtml24(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>
|
|
15461
15649
|
</div>`;
|
|
15462
15650
|
};
|
|
15463
15651
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -15465,10 +15653,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
15465
15653
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
15466
15654
|
}
|
|
15467
15655
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
15468
|
-
<article class="card session ${
|
|
15656
|
+
<article class="card session ${escapeHtml24(session.status)}">
|
|
15469
15657
|
<div class="card-header">
|
|
15470
|
-
<strong>${
|
|
15471
|
-
<span>${
|
|
15658
|
+
<strong>${escapeHtml24(session.sessionId)}</strong>
|
|
15659
|
+
<span>${escapeHtml24(session.status)}</span>
|
|
15472
15660
|
</div>
|
|
15473
15661
|
<p>
|
|
15474
15662
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -15495,21 +15683,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
15495
15683
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
15496
15684
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
15497
15685
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
15498
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
15499
|
-
<p class="muted">${
|
|
15686
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml24(pathPrefix)}">
|
|
15687
|
+
<p class="muted">${escapeHtml24(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
15500
15688
|
<div class="simulate-actions">
|
|
15501
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
15502
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
15689
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml24(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml24(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
15690
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml24(provider.provider)}">Mark ${escapeHtml24(provider.provider)} recovered</button>`).join("")}
|
|
15503
15691
|
</div>
|
|
15504
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
15692
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml24(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
15505
15693
|
<pre class="simulate-output" hidden></pre>
|
|
15506
15694
|
</div>`;
|
|
15507
15695
|
};
|
|
15508
15696
|
var renderVoiceResilienceHTML = (input) => {
|
|
15509
15697
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
15510
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
15511
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
15512
|
-
const snippet =
|
|
15698
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml24(kind)}: ${String(count)}</span>`).join("");
|
|
15699
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml24(link.href)}">${escapeHtml24(link.label)}</a>`).join(" \xB7 ") : "";
|
|
15700
|
+
const snippet = escapeHtml24(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
15513
15701
|
kind: 'stt',
|
|
15514
15702
|
providers: ['deepgram', 'assemblyai'],
|
|
15515
15703
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -15547,7 +15735,7 @@ app.use(
|
|
|
15547
15735
|
<head>
|
|
15548
15736
|
<meta charset="utf-8" />
|
|
15549
15737
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15550
|
-
<title>${
|
|
15738
|
+
<title>${escapeHtml24(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
15551
15739
|
<style>
|
|
15552
15740
|
:root { color-scheme: dark; }
|
|
15553
15741
|
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; }
|
|
@@ -15699,7 +15887,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
15699
15887
|
};
|
|
15700
15888
|
var createVoiceResilienceRoutes = (options) => {
|
|
15701
15889
|
const path = options.path ?? "/resilience";
|
|
15702
|
-
const routes = new
|
|
15890
|
+
const routes = new Elysia22({
|
|
15703
15891
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
15704
15892
|
}).get(path, async () => {
|
|
15705
15893
|
const events = await options.store.list();
|
|
@@ -15740,7 +15928,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
15740
15928
|
};
|
|
15741
15929
|
|
|
15742
15930
|
// src/providerDecisionTraces.ts
|
|
15743
|
-
var
|
|
15931
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15744
15932
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
15745
15933
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15746
15934
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -15981,7 +16169,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
15981
16169
|
<head>
|
|
15982
16170
|
<meta charset="utf-8" />
|
|
15983
16171
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15984
|
-
<title>${
|
|
16172
|
+
<title>${escapeHtml25(title)}</title>
|
|
15985
16173
|
<style>
|
|
15986
16174
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
15987
16175
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -15995,8 +16183,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
15995
16183
|
</head>
|
|
15996
16184
|
<body>
|
|
15997
16185
|
<main>
|
|
15998
|
-
<p class="status ${report.status}">${
|
|
15999
|
-
<h1>${
|
|
16186
|
+
<p class="status ${report.status}">${escapeHtml25(report.status)}</p>
|
|
16187
|
+
<h1>${escapeHtml25(title)}</h1>
|
|
16000
16188
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
16001
16189
|
<section class="grid">
|
|
16002
16190
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -16007,10 +16195,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
16007
16195
|
</section>
|
|
16008
16196
|
<section class="surfaces">
|
|
16009
16197
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
16010
|
-
<header><strong>${
|
|
16198
|
+
<header><strong>${escapeHtml25(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml25(surface.status)}</span></header>
|
|
16011
16199
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
16012
|
-
<p class="muted">Providers: ${
|
|
16013
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
16200
|
+
<p class="muted">Providers: ${escapeHtml25(surface.providers.join(", ") || "none")}</p>
|
|
16201
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml25(reason)}</code>`).join(" ")}</p>
|
|
16014
16202
|
</article>`).join(`
|
|
16015
16203
|
`)}
|
|
16016
16204
|
</section>
|
|
@@ -16024,7 +16212,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16024
16212
|
const headers = options.headers ?? {};
|
|
16025
16213
|
const title = options.title ?? "Provider Decision Traces";
|
|
16026
16214
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
16027
|
-
const app = new
|
|
16215
|
+
const app = new Elysia23({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
16028
16216
|
headers: {
|
|
16029
16217
|
"content-type": "application/json; charset=utf-8",
|
|
16030
16218
|
...headers
|
|
@@ -16052,7 +16240,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16052
16240
|
return app;
|
|
16053
16241
|
};
|
|
16054
16242
|
// src/sloCalibration.ts
|
|
16055
|
-
import { Elysia as
|
|
16243
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
16056
16244
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
16057
16245
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
16058
16246
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -16233,7 +16421,7 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
16233
16421
|
};
|
|
16234
16422
|
};
|
|
16235
16423
|
var escapeMarkdown3 = (value) => value.replaceAll("|", "\\|");
|
|
16236
|
-
var
|
|
16424
|
+
var escapeHtml26 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16237
16425
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
16238
16426
|
var readinessThresholdRows = (report) => [
|
|
16239
16427
|
{
|
|
@@ -16324,15 +16512,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
16324
16512
|
};
|
|
16325
16513
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
16326
16514
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
16327
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
16328
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
16329
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
16330
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
16515
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml26(row.control)}</td><td>${escapeHtml26(formatMs(row.value))}</td><td>${escapeHtml26(row.usedBy)}</td></tr>`).join("");
|
|
16516
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml26(issue)}</li>`).join("");
|
|
16517
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml26(source)}</code></li>`).join("");
|
|
16518
|
+
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:#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>${escapeHtml26(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">${escapeHtml26(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml26(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml26(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml26(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>`;
|
|
16331
16519
|
};
|
|
16332
16520
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
16333
16521
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
16334
16522
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
16335
|
-
const routes = new
|
|
16523
|
+
const routes = new Elysia24({
|
|
16336
16524
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
16337
16525
|
});
|
|
16338
16526
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -16356,7 +16544,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
16356
16544
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
16357
16545
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
16358
16546
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
16359
|
-
const routes = new
|
|
16547
|
+
const routes = new Elysia24({
|
|
16360
16548
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
16361
16549
|
});
|
|
16362
16550
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -16390,7 +16578,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
16390
16578
|
return routes;
|
|
16391
16579
|
};
|
|
16392
16580
|
// src/liveOps.ts
|
|
16393
|
-
import { Elysia as
|
|
16581
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16394
16582
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
16395
16583
|
"assign",
|
|
16396
16584
|
"create-task",
|
|
@@ -16700,7 +16888,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
16700
16888
|
const controller = createVoiceLiveOpsController(options);
|
|
16701
16889
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
16702
16890
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
16703
|
-
return new
|
|
16891
|
+
return new Elysia25({
|
|
16704
16892
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
16705
16893
|
}).post(path, async ({ request, set }) => {
|
|
16706
16894
|
try {
|
|
@@ -16722,15 +16910,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
16722
16910
|
});
|
|
16723
16911
|
};
|
|
16724
16912
|
// src/deliveryRuntime.ts
|
|
16725
|
-
import { Elysia as
|
|
16913
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16726
16914
|
import { mkdir } from "fs/promises";
|
|
16727
16915
|
import { dirname, join } from "path";
|
|
16728
|
-
var
|
|
16916
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16729
16917
|
var renderSummaryCard = (label, summary) => {
|
|
16730
16918
|
if (!summary) {
|
|
16731
|
-
return `<article><span>${
|
|
16919
|
+
return `<article><span>${escapeHtml27(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
16732
16920
|
}
|
|
16733
|
-
return `<article><span>${
|
|
16921
|
+
return `<article><span>${escapeHtml27(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>`;
|
|
16734
16922
|
};
|
|
16735
16923
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
16736
16924
|
audit: leases,
|
|
@@ -16941,9 +17129,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
16941
17129
|
});
|
|
16942
17130
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
16943
17131
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
16944
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
16945
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
16946
|
-
const snippet =
|
|
17132
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml27(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
17133
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml27(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
17134
|
+
const snippet = escapeHtml27(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
16947
17135
|
createVoiceDeliveryRuntimePresetConfig({
|
|
16948
17136
|
audit: {
|
|
16949
17137
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -16969,14 +17157,14 @@ app.use(
|
|
|
16969
17157
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
16970
17158
|
})
|
|
16971
17159
|
);`);
|
|
16972
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17160
|
+
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:#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>${escapeHtml27(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 ${escapeHtml27(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>`;
|
|
16973
17161
|
};
|
|
16974
17162
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
16975
17163
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
16976
17164
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
16977
17165
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
16978
17166
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
16979
|
-
const routes = new
|
|
17167
|
+
const routes = new Elysia26({
|
|
16980
17168
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
16981
17169
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
16982
17170
|
if (tickPath !== false) {
|
|
@@ -17012,7 +17200,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
17012
17200
|
return routes;
|
|
17013
17201
|
};
|
|
17014
17202
|
// src/dataControl.ts
|
|
17015
|
-
import { Elysia as
|
|
17203
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
17016
17204
|
var voiceComplianceRedactionDefaults = {
|
|
17017
17205
|
keys: [
|
|
17018
17206
|
"apiKey",
|
|
@@ -17251,7 +17439,7 @@ var parseRetentionScopes = (value) => {
|
|
|
17251
17439
|
const allowed = new Set(allRetentionScopes);
|
|
17252
17440
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
17253
17441
|
};
|
|
17254
|
-
var
|
|
17442
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17255
17443
|
var buildStorageSurfaces = (options) => [
|
|
17256
17444
|
{
|
|
17257
17445
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -17488,12 +17676,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
17488
17676
|
zeroRetentionAvailable: true
|
|
17489
17677
|
};
|
|
17490
17678
|
};
|
|
17491
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
17679
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml28(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml28(scope.skippedReason ?? "")}</td><td><code>${escapeHtml28(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
17492
17680
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
17493
17681
|
const title = options.title ?? "Voice Data Control";
|
|
17494
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
17495
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
17496
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
17682
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml28(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml28(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
17683
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml28(key.name)}</td><td><code>${escapeHtml28(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml28(key.recommendation)}</td></tr>`).join("");
|
|
17684
|
+
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:#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>${escapeHtml28(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>`;
|
|
17497
17685
|
};
|
|
17498
17686
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
17499
17687
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -17551,7 +17739,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
17551
17739
|
var createVoiceDataControlRoutes = (options) => {
|
|
17552
17740
|
const path = options.path ?? "/data-control";
|
|
17553
17741
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
17554
|
-
const routes = new
|
|
17742
|
+
const routes = new Elysia27({
|
|
17555
17743
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
17556
17744
|
});
|
|
17557
17745
|
routes.get(path, async ({ query }) => {
|
|
@@ -17627,16 +17815,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
17627
17815
|
return routes;
|
|
17628
17816
|
};
|
|
17629
17817
|
// src/evalRoutes.ts
|
|
17630
|
-
import { Elysia as
|
|
17818
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
17631
17819
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
17632
17820
|
import { dirname as dirname2 } from "path";
|
|
17633
17821
|
|
|
17634
17822
|
// src/qualityRoutes.ts
|
|
17635
|
-
import { Elysia as
|
|
17823
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17636
17824
|
|
|
17637
17825
|
// src/handoffHealth.ts
|
|
17638
|
-
import { Elysia as
|
|
17639
|
-
var
|
|
17826
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17827
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17640
17828
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
17641
17829
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
17642
17830
|
var increment3 = (record, key) => {
|
|
@@ -17754,10 +17942,10 @@ var renderActionSummary = (summary) => {
|
|
|
17754
17942
|
return [
|
|
17755
17943
|
'<section class="voice-handoff-health-columns">',
|
|
17756
17944
|
"<article><h3>Actions</h3>",
|
|
17757
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
17945
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml29(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
17758
17946
|
"</article>",
|
|
17759
17947
|
"<article><h3>Adapters</h3>",
|
|
17760
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
17948
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml29(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
17761
17949
|
"</article>",
|
|
17762
17950
|
"</section>"
|
|
17763
17951
|
].join("");
|
|
@@ -17771,22 +17959,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
17771
17959
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
17772
17960
|
'<div class="voice-handoff-health-events">',
|
|
17773
17961
|
...summary.events.map((event) => [
|
|
17774
|
-
`<article class="${
|
|
17962
|
+
`<article class="${escapeHtml29(event.status)}">`,
|
|
17775
17963
|
'<div class="voice-handoff-health-event-header">',
|
|
17776
|
-
`<strong>${
|
|
17777
|
-
`<span>${
|
|
17964
|
+
`<strong>${escapeHtml29(event.action ?? "handoff")}</strong>`,
|
|
17965
|
+
`<span>${escapeHtml29(event.status)}</span>`,
|
|
17778
17966
|
"</div>",
|
|
17779
|
-
`<p><small>${
|
|
17780
|
-
event.target ? `<p>Target: ${
|
|
17781
|
-
event.reason ? `<p>Reason: ${
|
|
17967
|
+
`<p><small>${escapeHtml29(event.sessionId)}</small></p>`,
|
|
17968
|
+
event.target ? `<p>Target: ${escapeHtml29(event.target)}</p>` : "",
|
|
17969
|
+
event.reason ? `<p>Reason: ${escapeHtml29(event.reason)}</p>` : "",
|
|
17782
17970
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
17783
17971
|
"<li>",
|
|
17784
|
-
`${
|
|
17785
|
-
delivery.deliveredTo ? ` to ${
|
|
17786
|
-
delivery.error ? ` (${
|
|
17972
|
+
`${escapeHtml29(delivery.adapterId)}: ${escapeHtml29(delivery.status)}`,
|
|
17973
|
+
delivery.deliveredTo ? ` to ${escapeHtml29(delivery.deliveredTo)}` : "",
|
|
17974
|
+
delivery.error ? ` (${escapeHtml29(delivery.error)})` : "",
|
|
17787
17975
|
"</li>"
|
|
17788
17976
|
].join("")).join("")}</ul>` : "",
|
|
17789
|
-
event.replayHref ? `<p><a href="${
|
|
17977
|
+
event.replayHref ? `<p><a href="${escapeHtml29(event.replayHref)}">Open replay</a></p>` : "",
|
|
17790
17978
|
"</article>"
|
|
17791
17979
|
].join("")),
|
|
17792
17980
|
"</div>"
|
|
@@ -17818,7 +18006,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
17818
18006
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
17819
18007
|
const path = options.path ?? "/api/voice-handoffs";
|
|
17820
18008
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17821
|
-
const routes = new
|
|
18009
|
+
const routes = new Elysia28({
|
|
17822
18010
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
17823
18011
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
17824
18012
|
if (htmlPath) {
|
|
@@ -17939,17 +18127,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
17939
18127
|
thresholds
|
|
17940
18128
|
};
|
|
17941
18129
|
};
|
|
17942
|
-
var
|
|
18130
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17943
18131
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
17944
18132
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
17945
18133
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
17946
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
17947
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18134
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml30(metric.label)}</td><td>${escapeHtml30(formatMetricValue(metric))}</td><td>${escapeHtml30(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml30(key)}</code></td></tr>`).join("");
|
|
18135
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml30(link.href)}">${escapeHtml30(link.label)}</a>`).join("")}</nav>` : "";
|
|
17948
18136
|
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>`;
|
|
17949
18137
|
};
|
|
17950
18138
|
var createVoiceQualityRoutes = (options) => {
|
|
17951
18139
|
const path = options.path ?? "/quality";
|
|
17952
|
-
const routes = new
|
|
18140
|
+
const routes = new Elysia29({
|
|
17953
18141
|
name: options.name ?? "absolutejs-voice-quality"
|
|
17954
18142
|
});
|
|
17955
18143
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -17978,7 +18166,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
17978
18166
|
};
|
|
17979
18167
|
|
|
17980
18168
|
// src/evalRoutes.ts
|
|
17981
|
-
var
|
|
18169
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17982
18170
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
17983
18171
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
17984
18172
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -18300,7 +18488,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
18300
18488
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
18301
18489
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
18302
18490
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
18303
|
-
const snippet =
|
|
18491
|
+
const snippet = escapeHtml31(`app.use(
|
|
18304
18492
|
createVoiceEvalRoutes({
|
|
18305
18493
|
path: '/evals',
|
|
18306
18494
|
store: traceStore,
|
|
@@ -18321,48 +18509,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
18321
18509
|
};
|
|
18322
18510
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
18323
18511
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
18324
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18325
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
18512
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml31(link.href)}">${escapeHtml31(link.label)}</a>`).join("")}</nav>` : "";
|
|
18513
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml31(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>';
|
|
18326
18514
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
18327
18515
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
18328
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
18329
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
18516
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml31(session.operationsRecordHref)}">${escapeHtml31(session.sessionId)}</a>` : escapeHtml31(session.sessionId);
|
|
18517
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml31(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml31(formatTime(session.endedAt))}</td><td>${escapeHtml31(failedMetrics || "none")}</td></tr>`;
|
|
18330
18518
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
18331
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18519
|
+
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{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>${escapeHtml31(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>`;
|
|
18332
18520
|
};
|
|
18333
18521
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
18334
18522
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
18335
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18336
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
18337
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
18338
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
18339
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18523
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml31(link.href)}">${escapeHtml31(link.label)}</a>`).join("")}</nav>` : "";
|
|
18524
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml31(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
18525
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml31(id)}</li>`).join("") : "<li>none</li>";
|
|
18526
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml31(id)}</li>`).join("") : "<li>none</li>";
|
|
18527
|
+
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{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>${escapeHtml31(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml31(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml31(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>${escapeHtml31(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>`;
|
|
18340
18528
|
};
|
|
18341
18529
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
18342
18530
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
18343
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18531
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml31(link.href)}">${escapeHtml31(link.label)}</a>`).join("")}</nav>` : "";
|
|
18344
18532
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
18345
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
18533
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml31(issue)}</li>`).join("")}</ul>` : "";
|
|
18346
18534
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
18347
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
18348
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
18535
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml31(session.operationsRecordHref)}">${escapeHtml31(session.sessionId)}</a>` : escapeHtml31(session.sessionId);
|
|
18536
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml31(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml31(session.issues.join(", ") || "none")}</td></tr>`;
|
|
18349
18537
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
18350
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
18538
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml31(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml31(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>`;
|
|
18351
18539
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
18352
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18540
|
+
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{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>${escapeHtml31(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>`;
|
|
18353
18541
|
};
|
|
18354
18542
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
18355
18543
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
18356
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18544
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml31(link.href)}">${escapeHtml31(link.label)}</a>`).join("")}</nav>` : "";
|
|
18357
18545
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
18358
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
18359
|
-
return `<section class="${fixture.status}"><h2>${
|
|
18546
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml31(scenario.label)}</td><td>${escapeHtml31(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml31([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
18547
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml31(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml31(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>`;
|
|
18360
18548
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
18361
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18549
|
+
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{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>${escapeHtml31(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>`;
|
|
18362
18550
|
};
|
|
18363
18551
|
var createVoiceEvalRoutes = (options) => {
|
|
18364
18552
|
const path = options.path ?? "/evals";
|
|
18365
|
-
const routes = new
|
|
18553
|
+
const routes = new Elysia30({
|
|
18366
18554
|
name: options.name ?? "absolutejs-voice-evals"
|
|
18367
18555
|
});
|
|
18368
18556
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -18499,11 +18687,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
18499
18687
|
return routes;
|
|
18500
18688
|
};
|
|
18501
18689
|
// src/simulationSuite.ts
|
|
18502
|
-
import { Elysia as
|
|
18690
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
18503
18691
|
|
|
18504
18692
|
// src/outcomeContract.ts
|
|
18505
|
-
import { Elysia as
|
|
18506
|
-
var
|
|
18693
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18694
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18507
18695
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
18508
18696
|
if (value === false) {
|
|
18509
18697
|
return;
|
|
@@ -18714,13 +18902,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
18714
18902
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
18715
18903
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
18716
18904
|
const contracts = report.contracts.map((contract) => {
|
|
18717
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
18905
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml32(href)}">${escapeHtml32(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
18718
18906
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
18719
18907
|
<div class="contract-header">
|
|
18720
18908
|
<div>
|
|
18721
|
-
<p class="eyebrow">${
|
|
18722
|
-
<h2>${
|
|
18723
|
-
${contract.description ? `<p>${
|
|
18909
|
+
<p class="eyebrow">${escapeHtml32(contract.contractId)}</p>
|
|
18910
|
+
<h2>${escapeHtml32(contract.label ?? contract.contractId)}</h2>
|
|
18911
|
+
${contract.description ? `<p>${escapeHtml32(contract.description)}</p>` : ""}
|
|
18724
18912
|
${sessionLinks}
|
|
18725
18913
|
</div>
|
|
18726
18914
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -18732,10 +18920,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
18732
18920
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
18733
18921
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
18734
18922
|
</div>
|
|
18735
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
18923
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml32(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
18736
18924
|
</section>`;
|
|
18737
18925
|
}).join("");
|
|
18738
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
18926
|
+
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,.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>${escapeHtml32(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>`;
|
|
18739
18927
|
};
|
|
18740
18928
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
18741
18929
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -18751,7 +18939,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
18751
18939
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
18752
18940
|
const path = options.path ?? "/api/outcome-contracts";
|
|
18753
18941
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18754
|
-
const routes = new
|
|
18942
|
+
const routes = new Elysia31({
|
|
18755
18943
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
18756
18944
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
18757
18945
|
if (htmlPath) {
|
|
@@ -18761,7 +18949,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
18761
18949
|
};
|
|
18762
18950
|
|
|
18763
18951
|
// src/toolContract.ts
|
|
18764
|
-
import { Elysia as
|
|
18952
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18765
18953
|
|
|
18766
18954
|
// src/toolRuntime.ts
|
|
18767
18955
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -18970,7 +19158,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
18970
19158
|
});
|
|
18971
19159
|
var defaultApi = {};
|
|
18972
19160
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
18973
|
-
var
|
|
19161
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18974
19162
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
18975
19163
|
if (value === false) {
|
|
18976
19164
|
return;
|
|
@@ -19219,7 +19407,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
19219
19407
|
};
|
|
19220
19408
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
19221
19409
|
const title = options.title ?? "Voice Tool Contracts";
|
|
19222
|
-
const snippet =
|
|
19410
|
+
const snippet = escapeHtml33(`app.use(
|
|
19223
19411
|
createVoiceToolContractRoutes({
|
|
19224
19412
|
htmlPath: '/tool-contracts',
|
|
19225
19413
|
path: '/api/tool-contracts',
|
|
@@ -19245,20 +19433,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19245
19433
|
);`);
|
|
19246
19434
|
const contracts = report.contracts.map((contract) => {
|
|
19247
19435
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
19248
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
19436
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml33(testCase.operationsRecordHref)}">${escapeHtml33(testCase.label ?? testCase.caseId)}</a>` : escapeHtml33(testCase.label ?? testCase.caseId)}</td>
|
|
19249
19437
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
19250
|
-
<td>${
|
|
19251
|
-
<td>${
|
|
19438
|
+
<td>${escapeHtml33(testCase.status)}</td>
|
|
19439
|
+
<td>${escapeHtml33(testCase.sessionId)}</td>
|
|
19252
19440
|
<td>${String(testCase.attempts)}</td>
|
|
19253
19441
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
19254
19442
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
19255
|
-
<td>${
|
|
19443
|
+
<td>${escapeHtml33(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
19256
19444
|
</tr>`).join("");
|
|
19257
19445
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
19258
19446
|
<div class="contract-header">
|
|
19259
19447
|
<div>
|
|
19260
|
-
<p class="eyebrow">${
|
|
19261
|
-
<h2>${
|
|
19448
|
+
<p class="eyebrow">${escapeHtml33(contract.toolName)}</p>
|
|
19449
|
+
<h2>${escapeHtml33(contract.label ?? contract.contractId)}</h2>
|
|
19262
19450
|
</div>
|
|
19263
19451
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
19264
19452
|
</div>
|
|
@@ -19268,7 +19456,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19268
19456
|
</table>
|
|
19269
19457
|
</section>`;
|
|
19270
19458
|
}).join("");
|
|
19271
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19459
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml33(title)}</title><style>body{background:#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>${escapeHtml33(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml33(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>`;
|
|
19272
19460
|
};
|
|
19273
19461
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
19274
19462
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -19285,7 +19473,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
19285
19473
|
var createVoiceToolContractRoutes = (options) => {
|
|
19286
19474
|
const path = options.path ?? "/api/tool-contracts";
|
|
19287
19475
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19288
|
-
const routes = new
|
|
19476
|
+
const routes = new Elysia32({
|
|
19289
19477
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
19290
19478
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
19291
19479
|
if (htmlPath) {
|
|
@@ -19295,7 +19483,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
19295
19483
|
};
|
|
19296
19484
|
|
|
19297
19485
|
// src/simulationSuite.ts
|
|
19298
|
-
var
|
|
19486
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19299
19487
|
var summarizeSection = (report) => ({
|
|
19300
19488
|
failed: report.failed,
|
|
19301
19489
|
passed: report.passed,
|
|
@@ -19491,15 +19679,15 @@ var renderSection = (label, summary) => {
|
|
|
19491
19679
|
if (!summary) {
|
|
19492
19680
|
return "";
|
|
19493
19681
|
}
|
|
19494
|
-
return `<article class="${
|
|
19682
|
+
return `<article class="${escapeHtml34(summary.status)}"><span>${escapeHtml34(label)}</span><strong>${escapeHtml34(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
19495
19683
|
};
|
|
19496
19684
|
var renderAction = (action) => {
|
|
19497
|
-
const content = `<strong>${
|
|
19498
|
-
return action.href ? `<a class="action" href="${
|
|
19685
|
+
const content = `<strong>${escapeHtml34(action.label)}</strong><p>${escapeHtml34(action.description)}</p><span>${escapeHtml34(action.section)} / ${escapeHtml34(action.severity)}</span>`;
|
|
19686
|
+
return action.href ? `<a class="action" href="${escapeHtml34(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
19499
19687
|
};
|
|
19500
19688
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
19501
19689
|
const title = options.title ?? "Voice Simulation Suite";
|
|
19502
|
-
const snippet =
|
|
19690
|
+
const snippet = escapeHtml34(`app.use(
|
|
19503
19691
|
createVoiceSimulationSuiteRoutes({
|
|
19504
19692
|
htmlPath: '/voice/simulations',
|
|
19505
19693
|
path: '/api/voice/simulations',
|
|
@@ -19532,12 +19720,12 @@ app.use(
|
|
|
19532
19720
|
store: traceStore
|
|
19533
19721
|
})
|
|
19534
19722
|
);`);
|
|
19535
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19723
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml34(title)}</title><style>body{background:#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>${escapeHtml34(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml34(report.status)}">Status: ${escapeHtml34(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>${escapeHtml34(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
19536
19724
|
};
|
|
19537
19725
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
19538
19726
|
const path = options.path ?? "/api/voice/simulations";
|
|
19539
19727
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
19540
|
-
const app = new
|
|
19728
|
+
const app = new Elysia33({
|
|
19541
19729
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
19542
19730
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
19543
19731
|
if (htmlPath) {
|
|
@@ -19849,9 +20037,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
19849
20037
|
};
|
|
19850
20038
|
};
|
|
19851
20039
|
// src/sessionReplay.ts
|
|
19852
|
-
import { Elysia as
|
|
20040
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19853
20041
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
19854
|
-
var
|
|
20042
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19855
20043
|
var increment4 = (record, key) => {
|
|
19856
20044
|
record[key] = (record[key] ?? 0) + 1;
|
|
19857
20045
|
};
|
|
@@ -20045,10 +20233,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
20045
20233
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
20046
20234
|
'<div class="voice-sessions-list">',
|
|
20047
20235
|
...sessions.map((session) => [
|
|
20048
|
-
`<article class="voice-session-card ${
|
|
20236
|
+
`<article class="voice-session-card ${escapeHtml35(session.status)}">`,
|
|
20049
20237
|
'<div class="voice-session-card-header">',
|
|
20050
|
-
`<strong>${
|
|
20051
|
-
`<span>${
|
|
20238
|
+
`<strong>${escapeHtml35(session.sessionId)}</strong>`,
|
|
20239
|
+
`<span>${escapeHtml35(session.status)}</span>`,
|
|
20052
20240
|
"</div>",
|
|
20053
20241
|
"<dl>",
|
|
20054
20242
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -20056,9 +20244,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
20056
20244
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
20057
20245
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
20058
20246
|
"</dl>",
|
|
20059
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
20060
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
20061
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
20247
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml35(session.latestOutcome)}</p>` : "",
|
|
20248
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml35).join(", ")}</p>` : "",
|
|
20249
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml35(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml35(session.replayHref)}">Open replay</a></p>` : "",
|
|
20062
20250
|
"</article>"
|
|
20063
20251
|
].join("")),
|
|
20064
20252
|
"</div>"
|
|
@@ -20089,7 +20277,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
20089
20277
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
20090
20278
|
const path = options.path ?? "/api/voice-sessions";
|
|
20091
20279
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20092
|
-
const routes = new
|
|
20280
|
+
const routes = new Elysia34({
|
|
20093
20281
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
20094
20282
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
20095
20283
|
if (htmlPath) {
|
|
@@ -20117,7 +20305,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
20117
20305
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
20118
20306
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
20119
20307
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20120
|
-
const routes = new
|
|
20308
|
+
const routes = new Elysia34({
|
|
20121
20309
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
20122
20310
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
20123
20311
|
if (htmlPath) {
|
|
@@ -20431,10 +20619,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
20431
20619
|
return report;
|
|
20432
20620
|
};
|
|
20433
20621
|
// src/turnLatency.ts
|
|
20434
|
-
import { Elysia as
|
|
20622
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
20435
20623
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
20436
20624
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
20437
|
-
var
|
|
20625
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20438
20626
|
var firstNumber2 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
20439
20627
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
20440
20628
|
var createTraceStageIndex = (events) => {
|
|
@@ -20566,11 +20754,11 @@ await traceStore.append({
|
|
|
20566
20754
|
turnId,
|
|
20567
20755
|
type: 'turn_latency.stage'
|
|
20568
20756
|
});`;
|
|
20569
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
20570
|
-
<header><div><p class="eyebrow">${
|
|
20571
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
20757
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml36(turn.status)}">
|
|
20758
|
+
<header><div><p class="eyebrow">${escapeHtml36(turn.sessionId)} \xB7 ${escapeHtml36(turn.turnId)}</p><h2>${escapeHtml36(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml36(turn.status)}</strong></header>
|
|
20759
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml36(stage.label)}</dt><dd>${escapeHtml36(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
20572
20760
|
</article>`).join("");
|
|
20573
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20761
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml36(title)}</title><style>body{background:#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>${escapeHtml36(title)}</h1><div class="summary"><span class="pill ${escapeHtml36(report.status)}">${escapeHtml36(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml36(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>${escapeHtml36(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
20574
20762
|
};
|
|
20575
20763
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
20576
20764
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -20587,7 +20775,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
20587
20775
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
20588
20776
|
const path = options.path ?? "/api/turn-latency";
|
|
20589
20777
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20590
|
-
const routes = new
|
|
20778
|
+
const routes = new Elysia35({
|
|
20591
20779
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
20592
20780
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
20593
20781
|
if (htmlPath) {
|
|
@@ -20596,8 +20784,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
20596
20784
|
return routes;
|
|
20597
20785
|
};
|
|
20598
20786
|
// src/liveLatency.ts
|
|
20599
|
-
import { Elysia as
|
|
20600
|
-
var
|
|
20787
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
20788
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20601
20789
|
var percentile3 = (values, percentileValue) => {
|
|
20602
20790
|
if (values.length === 0) {
|
|
20603
20791
|
return;
|
|
@@ -20664,13 +20852,13 @@ await traceStore.append({
|
|
|
20664
20852
|
sessionId,
|
|
20665
20853
|
type: 'client.live_latency'
|
|
20666
20854
|
});`;
|
|
20667
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
20668
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20855
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml37(sample.sessionId)}</td><td>${escapeHtml37(formatMs3(sample.latencyMs))}</td><td>${escapeHtml37(sample.status ?? "unknown")}</td><td>${escapeHtml37(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
20856
|
+
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:#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>${escapeHtml37(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml37(report.status)}">Status: ${escapeHtml37(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml37(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml37(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml37(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>${escapeHtml37(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>`;
|
|
20669
20857
|
};
|
|
20670
20858
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
20671
20859
|
const path = options.path ?? "/api/live-latency";
|
|
20672
20860
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
20673
|
-
const routes = new
|
|
20861
|
+
const routes = new Elysia36({
|
|
20674
20862
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
20675
20863
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
20676
20864
|
if (htmlPath) {
|
|
@@ -20989,9 +21177,9 @@ None.
|
|
|
20989
21177
|
`}`;
|
|
20990
21178
|
};
|
|
20991
21179
|
// src/turnQuality.ts
|
|
20992
|
-
import { Elysia as
|
|
21180
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
20993
21181
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
20994
|
-
var
|
|
21182
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20995
21183
|
var getTurnLatencyMs = (turn) => {
|
|
20996
21184
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
20997
21185
|
if (firstTranscriptAt === undefined) {
|
|
@@ -21062,24 +21250,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
21062
21250
|
};
|
|
21063
21251
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
21064
21252
|
const title = options.title ?? "Voice Turn Quality";
|
|
21065
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
21253
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml38(turn.status)}">
|
|
21066
21254
|
<div class="turn-header">
|
|
21067
21255
|
<div>
|
|
21068
|
-
<p class="eyebrow">${
|
|
21069
|
-
<h2>${
|
|
21256
|
+
<p class="eyebrow">${escapeHtml38(turn.sessionId)} \xB7 ${escapeHtml38(turn.turnId)}</p>
|
|
21257
|
+
<h2>${escapeHtml38(turn.text || "Empty turn")}</h2>
|
|
21070
21258
|
</div>
|
|
21071
|
-
<strong>${
|
|
21259
|
+
<strong>${escapeHtml38(turn.status)}</strong>
|
|
21072
21260
|
</div>
|
|
21073
21261
|
<dl>
|
|
21074
|
-
<div><dt>Source</dt><dd>${
|
|
21262
|
+
<div><dt>Source</dt><dd>${escapeHtml38(turn.source ?? "unknown")}</dd></div>
|
|
21075
21263
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
21076
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
21077
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
21264
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml38(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
21265
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml38(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
21078
21266
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
21079
21267
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
21080
21268
|
</dl>
|
|
21081
21269
|
</article>`).join("");
|
|
21082
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21270
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml38(title)}</h1><div class="summary"><span class="pill ${escapeHtml38(report.status)}">${escapeHtml38(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>`;
|
|
21083
21271
|
};
|
|
21084
21272
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
21085
21273
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -21096,7 +21284,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
21096
21284
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
21097
21285
|
const path = options.path ?? "/api/turn-quality";
|
|
21098
21286
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
21099
|
-
const routes = new
|
|
21287
|
+
const routes = new Elysia37({
|
|
21100
21288
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
21101
21289
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
21102
21290
|
if (htmlPath) {
|
|
@@ -21105,7 +21293,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
21105
21293
|
return routes;
|
|
21106
21294
|
};
|
|
21107
21295
|
// src/telephonyOutcome.ts
|
|
21108
|
-
import { Elysia as
|
|
21296
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21109
21297
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
21110
21298
|
"answered",
|
|
21111
21299
|
"completed",
|
|
@@ -21866,7 +22054,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
21866
22054
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
21867
22055
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
21868
22056
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
21869
|
-
return new
|
|
22057
|
+
return new Elysia38({
|
|
21870
22058
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
21871
22059
|
}).post(path, async ({ query, request }) => {
|
|
21872
22060
|
try {
|
|
@@ -21887,12 +22075,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
21887
22075
|
});
|
|
21888
22076
|
};
|
|
21889
22077
|
// src/phoneAgent.ts
|
|
21890
|
-
import { Elysia as
|
|
22078
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
21891
22079
|
|
|
21892
22080
|
// src/telephony/plivo.ts
|
|
21893
22081
|
import { Buffer as Buffer5 } from "buffer";
|
|
21894
22082
|
import { Database } from "bun:sqlite";
|
|
21895
|
-
import { Elysia as
|
|
22083
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
21896
22084
|
|
|
21897
22085
|
// src/telephony/contract.ts
|
|
21898
22086
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -21976,7 +22164,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
21976
22164
|
|
|
21977
22165
|
// src/telephony/twilio.ts
|
|
21978
22166
|
import { Buffer as Buffer4 } from "buffer";
|
|
21979
|
-
import { Elysia as
|
|
22167
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
21980
22168
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
21981
22169
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
21982
22170
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -22006,7 +22194,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
22006
22194
|
return parameters;
|
|
22007
22195
|
};
|
|
22008
22196
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22009
|
-
var
|
|
22197
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22010
22198
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
22011
22199
|
if (!webhook?.verificationUrl) {
|
|
22012
22200
|
return;
|
|
@@ -22049,23 +22237,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
22049
22237
|
};
|
|
22050
22238
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22051
22239
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
22052
|
-
<h1>${
|
|
22240
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22053
22241
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22054
22242
|
<section>
|
|
22055
22243
|
<h2>URLs</h2>
|
|
22056
22244
|
<ul>
|
|
22057
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22058
|
-
<li><strong>Media stream:</strong> <code>${
|
|
22059
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
22245
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml39(status.urls.twiml)}</code></li>
|
|
22246
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml39(status.urls.stream)}</code></li>
|
|
22247
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml39(status.urls.webhook)}</code></li>
|
|
22060
22248
|
</ul>
|
|
22061
22249
|
</section>
|
|
22062
22250
|
<section>
|
|
22063
22251
|
<h2>Signing</h2>
|
|
22064
22252
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
22065
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
22253
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml39(status.signing.verificationUrl)}</code></p>` : ""}
|
|
22066
22254
|
</section>
|
|
22067
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
22068
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
22255
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml39(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
22256
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml39(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
22069
22257
|
</main>`;
|
|
22070
22258
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
22071
22259
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -22076,20 +22264,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
22076
22264
|
});
|
|
22077
22265
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22078
22266
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
22079
|
-
<h1>${
|
|
22267
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22080
22268
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22081
22269
|
<section>
|
|
22082
22270
|
<h2>Checks</h2>
|
|
22083
22271
|
<ul>
|
|
22084
|
-
${report.checks.map((check) => `<li><strong>${
|
|
22272
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml39(check.name)}</strong>: ${escapeHtml39(check.status)}${check.message ? ` - ${escapeHtml39(check.message)}` : ""}</li>`).join("")}
|
|
22085
22273
|
</ul>
|
|
22086
22274
|
</section>
|
|
22087
22275
|
<section>
|
|
22088
22276
|
<h2>Observed URLs</h2>
|
|
22089
22277
|
<ul>
|
|
22090
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22091
|
-
<li><strong>Stream:</strong> <code>${
|
|
22092
|
-
<li><strong>Webhook:</strong> <code>${
|
|
22278
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml39(report.setup.urls.twiml)}</code></li>
|
|
22279
|
+
<li><strong>Stream:</strong> <code>${escapeHtml39(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
22280
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml39(report.setup.urls.webhook)}</code></li>
|
|
22093
22281
|
</ul>
|
|
22094
22282
|
</section>
|
|
22095
22283
|
</main>`;
|
|
@@ -22635,7 +22823,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
22635
22823
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
22636
22824
|
const bridges = new WeakMap;
|
|
22637
22825
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
22638
|
-
const app = new
|
|
22826
|
+
const app = new Elysia39({
|
|
22639
22827
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
22640
22828
|
}).get(twimlPath, async ({ query, request }) => {
|
|
22641
22829
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -22772,7 +22960,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
22772
22960
|
|
|
22773
22961
|
// src/telephony/plivo.ts
|
|
22774
22962
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22775
|
-
var
|
|
22963
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22776
22964
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22777
22965
|
var resolveRequestOrigin2 = (request) => {
|
|
22778
22966
|
const url = new URL(request.url);
|
|
@@ -23203,21 +23391,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
23203
23391
|
};
|
|
23204
23392
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23205
23393
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
23206
|
-
<h1>${
|
|
23394
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23207
23395
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23208
23396
|
<ul>
|
|
23209
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
23210
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
23211
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
23397
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml40(status.urls.answer)}</code></li>
|
|
23398
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml40(status.urls.stream)}</code></li>
|
|
23399
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml40(status.urls.webhook)}</code></li>
|
|
23212
23400
|
</ul>
|
|
23213
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23214
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
23401
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml40(name)}</code></li>`).join("")}</ul>` : ""}
|
|
23402
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml40(warning)}</li>`).join("")}</ul>` : ""}
|
|
23215
23403
|
</main>`;
|
|
23216
23404
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23217
23405
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
23218
|
-
<h1>${
|
|
23406
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23219
23407
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23220
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
23408
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml40(check.name)}</strong>: ${escapeHtml40(check.status)}${check.message ? ` - ${escapeHtml40(check.message)}` : ""}</li>`).join("")}</ul>
|
|
23221
23409
|
</main>`;
|
|
23222
23410
|
var runPlivoSmokeTest = async (input) => {
|
|
23223
23411
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -23307,7 +23495,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
23307
23495
|
nonceStore: options.webhook.nonceStore,
|
|
23308
23496
|
verificationUrl: options.webhook.verificationUrl
|
|
23309
23497
|
}) : undefined);
|
|
23310
|
-
const app = new
|
|
23498
|
+
const app = new Elysia40({
|
|
23311
23499
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
23312
23500
|
}).get(answerPath, async ({ query, request }) => {
|
|
23313
23501
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -23419,9 +23607,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
23419
23607
|
// src/telephony/telnyx.ts
|
|
23420
23608
|
import { Buffer as Buffer6 } from "buffer";
|
|
23421
23609
|
import { Database as Database2 } from "bun:sqlite";
|
|
23422
|
-
import { Elysia as
|
|
23610
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
23423
23611
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23424
|
-
var
|
|
23612
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23425
23613
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
23426
23614
|
var resolveRequestOrigin3 = (request) => {
|
|
23427
23615
|
const url = new URL(request.url);
|
|
@@ -23815,21 +24003,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
23815
24003
|
};
|
|
23816
24004
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23817
24005
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
23818
|
-
<h1>${
|
|
24006
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23819
24007
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23820
24008
|
<ul>
|
|
23821
|
-
<li><strong>TeXML:</strong> <code>${
|
|
23822
|
-
<li><strong>Media stream:</strong> <code>${
|
|
23823
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
24009
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml41(status.urls.texml)}</code></li>
|
|
24010
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml41(status.urls.stream)}</code></li>
|
|
24011
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml41(status.urls.webhook)}</code></li>
|
|
23824
24012
|
</ul>
|
|
23825
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23826
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
24013
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml41(name)}</code></li>`).join("")}</ul>` : ""}
|
|
24014
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml41(warning)}</li>`).join("")}</ul>` : ""}
|
|
23827
24015
|
</main>`;
|
|
23828
24016
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23829
24017
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
23830
|
-
<h1>${
|
|
24018
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23831
24019
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23832
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
24020
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml41(check.name)}</strong>: ${escapeHtml41(check.status)}${check.message ? ` - ${escapeHtml41(check.message)}` : ""}</li>`).join("")}</ul>
|
|
23833
24021
|
</main>`;
|
|
23834
24022
|
var runTelnyxSmokeTest = async (input) => {
|
|
23835
24023
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -23922,7 +24110,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
23922
24110
|
publicKey: options.webhook.publicKey,
|
|
23923
24111
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
23924
24112
|
}) : undefined);
|
|
23925
|
-
const app = new
|
|
24113
|
+
const app = new Elysia41({
|
|
23926
24114
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
23927
24115
|
}).get(texmlPath, async ({ query, request }) => {
|
|
23928
24116
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -24032,8 +24220,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
24032
24220
|
};
|
|
24033
24221
|
|
|
24034
24222
|
// src/telephony/matrix.ts
|
|
24035
|
-
import { Elysia as
|
|
24036
|
-
var
|
|
24223
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24224
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24037
24225
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
24038
24226
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
24039
24227
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -24094,13 +24282,13 @@ var badgeStyles = {
|
|
|
24094
24282
|
};
|
|
24095
24283
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
24096
24284
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
24097
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
24285
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml42(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
24098
24286
|
<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>
|
|
24099
24287
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
24100
24288
|
${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);">
|
|
24101
24289
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
24102
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
24103
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
24290
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml42(entry.name)}</h2>
|
|
24291
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml42(entry.status.toUpperCase())}</span>
|
|
24104
24292
|
</div>
|
|
24105
24293
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
24106
24294
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -24108,15 +24296,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
24108
24296
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
24109
24297
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
24110
24298
|
</dl>
|
|
24111
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
24112
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
24113
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
24299
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml42(entry.setup.urls.stream || "missing")}</code></p>
|
|
24300
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml42(entry.setup.urls.webhook || "missing")}</code></p>
|
|
24301
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml42(issue.severity)}: ${escapeHtml42(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
24114
24302
|
</article>`).join("")}
|
|
24115
24303
|
</section>
|
|
24116
24304
|
</main>`;
|
|
24117
24305
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
24118
24306
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
24119
|
-
return new
|
|
24307
|
+
return new Elysia42({
|
|
24120
24308
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
24121
24309
|
}).get(path, async ({ query, request }) => {
|
|
24122
24310
|
const providers = await options.load({ query, request });
|
|
@@ -24138,7 +24326,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
24138
24326
|
};
|
|
24139
24327
|
|
|
24140
24328
|
// src/phoneAgentProductionSmoke.ts
|
|
24141
|
-
import { Elysia as
|
|
24329
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24142
24330
|
var defaultRequirements = [
|
|
24143
24331
|
"media-started",
|
|
24144
24332
|
"transcript",
|
|
@@ -24146,7 +24334,7 @@ var defaultRequirements = [
|
|
|
24146
24334
|
"lifecycle-outcome",
|
|
24147
24335
|
"no-session-error"
|
|
24148
24336
|
];
|
|
24149
|
-
var
|
|
24337
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24150
24338
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
24151
24339
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
24152
24340
|
const value = event.payload[key];
|
|
@@ -24255,10 +24443,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
24255
24443
|
});
|
|
24256
24444
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
24257
24445
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
24258
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
24259
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
24260
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
24261
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24446
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml43(issue.requirement)}</strong>: ${escapeHtml43(issue.message)}</li>`).join("");
|
|
24447
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml43(outcome)}</span>`).join("");
|
|
24448
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml43(requirement)}</span>`).join("");
|
|
24449
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#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>${escapeHtml43(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml43(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml43(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml43(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>`;
|
|
24262
24450
|
};
|
|
24263
24451
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
24264
24452
|
query,
|
|
@@ -24281,7 +24469,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
24281
24469
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
24282
24470
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
24283
24471
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
24284
|
-
const routes = new
|
|
24472
|
+
const routes = new Elysia43({
|
|
24285
24473
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
24286
24474
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
24287
24475
|
if (htmlPath) {
|
|
@@ -24324,7 +24512,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
24324
24512
|
"completed",
|
|
24325
24513
|
"failed"
|
|
24326
24514
|
];
|
|
24327
|
-
var
|
|
24515
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24328
24516
|
var loadRouteJson = async (input) => {
|
|
24329
24517
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
24330
24518
|
headers: {
|
|
@@ -24562,10 +24750,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
24562
24750
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
24563
24751
|
const urls = entry?.setup.urls;
|
|
24564
24752
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
24565
|
-
return `<tr><td>${
|
|
24753
|
+
return `<tr><td>${escapeHtml44(carrier.name ?? carrier.provider)}</td><td>${escapeHtml44(carrier.provider)}</td><td><code>${escapeHtml44(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml44(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml44(entry.status)}">${escapeHtml44(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml44(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml44(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml44(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
24566
24754
|
}).join("");
|
|
24567
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
24568
|
-
const snippet =
|
|
24755
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml44(stage)}</code></li>`).join("");
|
|
24756
|
+
const snippet = escapeHtml44(`const phoneAgent = createVoicePhoneAgent({
|
|
24569
24757
|
carriers: [
|
|
24570
24758
|
{
|
|
24571
24759
|
provider: 'twilio',
|
|
@@ -24599,11 +24787,11 @@ app.use(
|
|
|
24599
24787
|
);`);
|
|
24600
24788
|
const checklist = report.carriers.map((carrier) => {
|
|
24601
24789
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
24602
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
24603
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
24604
|
-
return `<article><h3>${
|
|
24790
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml44(issue)}</li>`).join("") ?? "";
|
|
24791
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml44(step)}</li>`).join("") ?? "";
|
|
24792
|
+
return `<article><h3>${escapeHtml44(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
24605
24793
|
}).join("");
|
|
24606
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24794
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(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>${escapeHtml44(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="${escapeHtml44(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>`;
|
|
24607
24795
|
};
|
|
24608
24796
|
var createVoicePhoneAgent = (options) => {
|
|
24609
24797
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -24612,7 +24800,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
24612
24800
|
setupPath: resolveSetupPath(carrier),
|
|
24613
24801
|
smokePath: resolveSmokePath(carrier)
|
|
24614
24802
|
}));
|
|
24615
|
-
const app = new
|
|
24803
|
+
const app = new Elysia44({
|
|
24616
24804
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
24617
24805
|
});
|
|
24618
24806
|
for (const carrier of options.carriers) {
|
|
@@ -26242,8 +26430,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
26242
26430
|
};
|
|
26243
26431
|
};
|
|
26244
26432
|
// src/providerCapabilities.ts
|
|
26245
|
-
import { Elysia as
|
|
26246
|
-
var
|
|
26433
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
26434
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26247
26435
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
26248
26436
|
configured: true,
|
|
26249
26437
|
features: options.features?.[provider],
|
|
@@ -26306,27 +26494,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
26306
26494
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
26307
26495
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
26308
26496
|
const cards = report.capabilities.map((capability) => {
|
|
26309
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
26310
|
-
return `<article class="card ${
|
|
26497
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml45(feature)}</span>`).join("");
|
|
26498
|
+
return `<article class="card ${escapeHtml45(capability.status)}">
|
|
26311
26499
|
<div class="card-header">
|
|
26312
26500
|
<div>
|
|
26313
|
-
<p class="eyebrow">${
|
|
26314
|
-
<h2>${
|
|
26501
|
+
<p class="eyebrow">${escapeHtml45(capability.kind)}</p>
|
|
26502
|
+
<h2>${escapeHtml45(capability.label ?? capability.provider)}</h2>
|
|
26315
26503
|
</div>
|
|
26316
|
-
<strong>${
|
|
26504
|
+
<strong>${escapeHtml45(capability.status)}</strong>
|
|
26317
26505
|
</div>
|
|
26318
|
-
${capability.description ? `<p>${
|
|
26506
|
+
${capability.description ? `<p>${escapeHtml45(capability.description)}</p>` : ""}
|
|
26319
26507
|
<dl>
|
|
26320
26508
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
26321
26509
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
26322
|
-
<div><dt>Model</dt><dd>${
|
|
26510
|
+
<div><dt>Model</dt><dd>${escapeHtml45(capability.model ?? "default")}</dd></div>
|
|
26323
26511
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
26324
26512
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
26325
26513
|
</dl>
|
|
26326
26514
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
26327
26515
|
</article>`;
|
|
26328
26516
|
}).join("");
|
|
26329
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26517
|
+
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:#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>${escapeHtml45(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>`;
|
|
26330
26518
|
};
|
|
26331
26519
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
26332
26520
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -26343,7 +26531,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
26343
26531
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
26344
26532
|
const path = options.path ?? "/api/provider-capabilities";
|
|
26345
26533
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
26346
|
-
const routes = new
|
|
26534
|
+
const routes = new Elysia45({
|
|
26347
26535
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
26348
26536
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
26349
26537
|
if (htmlPath) {
|
|
@@ -26352,7 +26540,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
26352
26540
|
return routes;
|
|
26353
26541
|
};
|
|
26354
26542
|
// src/providerOrchestration.ts
|
|
26355
|
-
import { Elysia as
|
|
26543
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
26356
26544
|
var defaultRequirement = {
|
|
26357
26545
|
minProviders: 1,
|
|
26358
26546
|
requireBudgetPolicy: false,
|
|
@@ -26365,7 +26553,7 @@ var statusRank4 = {
|
|
|
26365
26553
|
warn: 1,
|
|
26366
26554
|
fail: 2
|
|
26367
26555
|
};
|
|
26368
|
-
var
|
|
26556
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26369
26557
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
26370
26558
|
var uniqueSorted6 = (values) => [
|
|
26371
26559
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -26508,27 +26696,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
26508
26696
|
};
|
|
26509
26697
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
26510
26698
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
26511
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
26512
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
26699
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml46(surface.status)}">
|
|
26700
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml46(surface.surface)}</p><h2>${escapeHtml46(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml46(surface.status)}</strong></div>
|
|
26513
26701
|
<dl>
|
|
26514
|
-
<div><dt>Providers</dt><dd>${
|
|
26515
|
-
<div><dt>Fallback</dt><dd>${
|
|
26702
|
+
<div><dt>Providers</dt><dd>${escapeHtml46(surface.providers.join(", ") || "none")}</dd></div>
|
|
26703
|
+
<div><dt>Fallback</dt><dd>${escapeHtml46(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
26516
26704
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
26517
26705
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
26518
26706
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
26519
26707
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
26520
26708
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
26521
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
26709
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml46(surface.fallbackMode || "default")}</dd></div>
|
|
26522
26710
|
</dl>
|
|
26523
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
26711
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml46(issue.status)}</strong> ${escapeHtml46(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
26524
26712
|
</article>`).join("");
|
|
26525
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26713
|
+
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:#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>${escapeHtml46(title)}</h1><div class="summary"><span class="pill">${escapeHtml46(report.profileId)}</span><span class="pill">${escapeHtml46(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>`;
|
|
26526
26714
|
};
|
|
26527
26715
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
26528
26716
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
26529
26717
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
26530
26718
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
26531
|
-
const routes = new
|
|
26719
|
+
const routes = new Elysia46({
|
|
26532
26720
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
26533
26721
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
26534
26722
|
if (htmlPath) {
|
|
@@ -26699,7 +26887,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
26699
26887
|
return report;
|
|
26700
26888
|
};
|
|
26701
26889
|
// src/providerSlo.ts
|
|
26702
|
-
import { Elysia as
|
|
26890
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
26703
26891
|
var defaultThresholds = {
|
|
26704
26892
|
llm: {
|
|
26705
26893
|
maxAverageElapsedMs: 2500,
|
|
@@ -26732,7 +26920,7 @@ var statusRank5 = {
|
|
|
26732
26920
|
warn: 1,
|
|
26733
26921
|
fail: 2
|
|
26734
26922
|
};
|
|
26735
|
-
var
|
|
26923
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26736
26924
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
26737
26925
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
26738
26926
|
var uniqueSorted7 = (values) => [
|
|
@@ -27028,11 +27216,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27028
27216
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
27029
27217
|
const kindCards = providerKinds.map((kind) => {
|
|
27030
27218
|
const kindReport = report.kinds[kind];
|
|
27031
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
27219
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml47(metric.label)}</dt><dd>${escapeHtml47(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml47(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
27032
27220
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
27033
|
-
return `<article class="${
|
|
27221
|
+
return `<article class="${escapeHtml47(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml47(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml47(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
27034
27222
|
}).join("");
|
|
27035
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
27223
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml47(issue.status)}"><strong>${escapeHtml47(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml47(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
27036
27224
|
const snippet = `createVoiceProviderSloRoutes({
|
|
27037
27225
|
store: runtimeStorage.traces,
|
|
27038
27226
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -27042,7 +27230,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27042
27230
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
27043
27231
|
}
|
|
27044
27232
|
})`;
|
|
27045
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27233
|
+
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:#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>${escapeHtml47(title)}</h1><p class="status ${escapeHtml47(report.status)}">${escapeHtml47(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>${escapeHtml47(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
27046
27234
|
};
|
|
27047
27235
|
var createVoiceProviderSloRoutes = (options) => {
|
|
27048
27236
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -27053,7 +27241,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27053
27241
|
...options.headers ?? {}
|
|
27054
27242
|
};
|
|
27055
27243
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
27056
|
-
const app = new
|
|
27244
|
+
const app = new Elysia47({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
27057
27245
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
27058
27246
|
if (markdownPath !== false) {
|
|
27059
27247
|
app.get(markdownPath, async () => {
|
|
@@ -27083,10 +27271,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27083
27271
|
return app;
|
|
27084
27272
|
};
|
|
27085
27273
|
// src/productionReadiness.ts
|
|
27086
|
-
import { Elysia as
|
|
27274
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
27087
27275
|
|
|
27088
27276
|
// src/telephony/security.ts
|
|
27089
|
-
import { Elysia as
|
|
27277
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
27090
27278
|
|
|
27091
27279
|
// src/postgresStore.ts
|
|
27092
27280
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -27824,7 +28012,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
27824
28012
|
};
|
|
27825
28013
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
27826
28014
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
27827
|
-
return new
|
|
28015
|
+
return new Elysia48({
|
|
27828
28016
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
27829
28017
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
27830
28018
|
};
|
|
@@ -27881,8 +28069,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
27881
28069
|
};
|
|
27882
28070
|
|
|
27883
28071
|
// src/opsRecovery.ts
|
|
27884
|
-
import { Elysia as
|
|
27885
|
-
var
|
|
28072
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
28073
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27886
28074
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
27887
28075
|
var hrefForSession = (value, sessionId) => {
|
|
27888
28076
|
if (typeof value === "function") {
|
|
@@ -28096,19 +28284,19 @@ ${failedSessions || "None."}
|
|
|
28096
28284
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
28097
28285
|
`;
|
|
28098
28286
|
};
|
|
28099
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
28287
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml48(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>${escapeHtml48(label)}</span><strong>not configured</strong></article>`;
|
|
28100
28288
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
28101
28289
|
const title = options.title ?? "Voice Ops Recovery";
|
|
28102
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
28103
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
28104
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
28105
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
28290
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml48(issue.severity)}</td><td><code>${escapeHtml48(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml48(issue.href)}">${escapeHtml48(issue.label)}</a>` : escapeHtml48(issue.label)}</td><td>${escapeHtml48(String(issue.value ?? ""))}</td><td>${escapeHtml48(issue.detail ?? "")}</td></tr>`).join("");
|
|
28291
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml48(provider.provider)}</td><td>${escapeHtml48(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml48(provider.lastError ?? "")}</td></tr>`).join("");
|
|
28292
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml48(session.operationsRecordHref)}">${escapeHtml48(session.sessionId)}</a>` : escapeHtml48(session.sessionId)}${session.provider ? ` via ${escapeHtml48(session.provider)}` : ""}${session.error ? `: ${escapeHtml48(session.error)}` : ""}</li>`).join("");
|
|
28293
|
+
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:#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>${escapeHtml48(title)}</h1><p><span class="status">${escapeHtml48(report.status)}</span> Checked ${escapeHtml48(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>${escapeHtml48(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>`;
|
|
28106
28294
|
};
|
|
28107
28295
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
28108
28296
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
28109
28297
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
28110
28298
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
28111
|
-
const routes = new
|
|
28299
|
+
const routes = new Elysia49({
|
|
28112
28300
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
28113
28301
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
28114
28302
|
if (htmlPath) {
|
|
@@ -28138,18 +28326,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
28138
28326
|
};
|
|
28139
28327
|
|
|
28140
28328
|
// src/observabilityExport.ts
|
|
28141
|
-
import { Elysia as
|
|
28329
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
28142
28330
|
import { Database as Database4 } from "bun:sqlite";
|
|
28143
28331
|
import { createHash } from "crypto";
|
|
28144
28332
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
28145
28333
|
import { join as join3 } from "path";
|
|
28146
28334
|
|
|
28147
28335
|
// src/operationsRecord.ts
|
|
28148
|
-
import { Elysia as
|
|
28336
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
28149
28337
|
|
|
28150
28338
|
// src/traceTimeline.ts
|
|
28151
|
-
import { Elysia as
|
|
28152
|
-
var
|
|
28339
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
28340
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28153
28341
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
28154
28342
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
28155
28343
|
var firstString4 = (payload, keys) => {
|
|
@@ -28332,17 +28520,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
28332
28520
|
};
|
|
28333
28521
|
};
|
|
28334
28522
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
28335
|
-
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>${
|
|
28523
|
+
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>${escapeHtml49(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>`;
|
|
28336
28524
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
28337
|
-
const events = session.events.map((event) => `<tr class="${
|
|
28338
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
28339
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
28340
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
28525
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml49(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml49(event.type)}</td><td>${escapeHtml49(event.label)}</td><td>${escapeHtml49(event.provider ?? "")}</td><td>${escapeHtml49(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
28526
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml49(issue.severity)}">${escapeHtml49(issue.code)}: ${escapeHtml49(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
28527
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml49(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
28528
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml49(session.sessionId)}</h1><p class="status ${escapeHtml49(session.status)}">${escapeHtml49(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>`;
|
|
28341
28529
|
};
|
|
28342
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
28530
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml49(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml49(session.operationsRecordHref)}">${escapeHtml49(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml49(session.sessionId)}</a>`}</td><td>${escapeHtml49(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) => escapeHtml49(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
28343
28531
|
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}}";
|
|
28344
28532
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
28345
|
-
const snippet =
|
|
28533
|
+
const snippet = escapeHtml49(`const traceStore = createVoiceTraceSinkStore({
|
|
28346
28534
|
store: runtimeStorage.traces,
|
|
28347
28535
|
sinks: [
|
|
28348
28536
|
createVoiceTraceHTTPSink({
|
|
@@ -28368,13 +28556,13 @@ app.use(
|
|
|
28368
28556
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
28369
28557
|
})
|
|
28370
28558
|
);`);
|
|
28371
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
28559
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(options.title ?? "Voice 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>${escapeHtml49(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>`;
|
|
28372
28560
|
};
|
|
28373
28561
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
28374
28562
|
const path = options.path ?? "/api/voice-traces";
|
|
28375
28563
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
28376
28564
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
28377
|
-
const routes = new
|
|
28565
|
+
const routes = new Elysia50({
|
|
28378
28566
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
28379
28567
|
});
|
|
28380
28568
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -29004,7 +29192,7 @@ var renderVoiceFailureReplayMarkdown = (report) => {
|
|
|
29004
29192
|
].join(`
|
|
29005
29193
|
`);
|
|
29006
29194
|
};
|
|
29007
|
-
var
|
|
29195
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29008
29196
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
29009
29197
|
var outcomeLabels = (outcome) => [
|
|
29010
29198
|
outcome.complete ? "complete" : undefined,
|
|
@@ -29114,18 +29302,18 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
29114
29302
|
`);
|
|
29115
29303
|
};
|
|
29116
29304
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
29117
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
29118
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
29119
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
29305
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml50(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>';
|
|
29306
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml50(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml50(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml50(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml50(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
29307
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml50(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml50(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml50(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml50(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml50(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml50(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml50(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml50(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
29120
29308
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
29121
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
29122
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
29123
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
29124
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
29125
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
29309
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml50(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml50(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml50(handoff.status ?? "")}</span><p>${escapeHtml50(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
29310
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml50(tool.toolName ?? "tool")}</strong> <span>${escapeHtml50(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml50(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
29311
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml50(review.title)}</strong> <span>${escapeHtml50(review.summary.outcome ?? "")}</span><p>${escapeHtml50(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
29312
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml50(task.title)}</strong> <span>${escapeHtml50(task.status)}</span><p>${escapeHtml50(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
29313
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml50(event.type)}</strong> <span>${escapeHtml50(event.deliveryStatus ?? "local")}</span><p>${escapeHtml50(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
29126
29314
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
29127
29315
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
29128
|
-
return `<li><strong>assistant.guardrail ${
|
|
29316
|
+
return `<li><strong>assistant.guardrail ${escapeHtml50(decision.stage ?? "unknown")}</strong> <span>${escapeHtml50(decision.status ?? "")}</span><p>Allowed: ${escapeHtml50(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml50(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml50(decision.turnId)}` : ""}</p><p>${escapeHtml50(findings)}</p></li>`;
|
|
29129
29317
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
29130
29318
|
const telephonyMedia = record.telephonyMedia.events.length ? record.telephonyMedia.events.slice(0, 50).map((event) => {
|
|
29131
29319
|
const details = [
|
|
@@ -29136,9 +29324,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29136
29324
|
event.sequenceNumber ? `Seq: ${event.sequenceNumber}` : undefined,
|
|
29137
29325
|
`Audio bytes: ${String(event.audioBytes)}`
|
|
29138
29326
|
].filter((detail) => typeof detail === "string");
|
|
29139
|
-
return `<li><strong>${
|
|
29327
|
+
return `<li><strong>${escapeHtml50(event.event)}</strong> <span>${escapeHtml50(new Date(event.at).toLocaleString())}</span><p>${escapeHtml50(details.join(" \xB7 "))}</p></li>`;
|
|
29140
29328
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
29141
|
-
const snippet =
|
|
29329
|
+
const snippet = escapeHtml50(`app.use(
|
|
29142
29330
|
createVoiceOperationsRecordRoutes({
|
|
29143
29331
|
audit: auditStore,
|
|
29144
29332
|
integrationEvents: opsEvents,
|
|
@@ -29152,16 +29340,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29152
29340
|
tasks: opsTasks
|
|
29153
29341
|
})
|
|
29154
29342
|
);`);
|
|
29155
|
-
const incidentMarkdown =
|
|
29156
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
29157
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29343
|
+
const incidentMarkdown = escapeHtml50(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
29344
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml50(options.incidentHref)}">Download incident.md</a>` : "";
|
|
29345
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(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>${escapeHtml50(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml50(record.status)}">${escapeHtml50(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</a><a href="#telephony-media">Telephony media</a><a href="#guardrails">Guardrails</a><a href="#incident-handoff">Incident handoff</a>${incidentLink}</div><section class="grid"><div class="card"><span>Events</span><strong>${String(record.summary.eventCount)}</strong></div><div class="card"><span>Turns</span><strong>${String(record.summary.turnCount)}</strong></div><div class="card"><span>Errors</span><strong>${String(record.summary.errorCount)}</strong></div><div class="card"><span>Duration</span><strong>${formatMs5(record.summary.callDurationMs)}</strong></div><div class="card"><span>Provider recovery</span><strong>${escapeHtml50(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</span></div><div class="card"><span>Telephony media</span><strong>${String(record.telephonyMedia.media)}</strong><span>${String(record.telephonyMedia.inbound)} inbound / ${String(record.telephonyMedia.outbound)} outbound / ${String(record.telephonyMedia.clears)} clears</span></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div></section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="telephony-media"><h2>Telephony Media</h2><p class="muted">Live <code>client.telephony_media</code> stream lifecycle evidence attached to this session. Carriers: ${escapeHtml50(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml50(record.telephonyMedia.streamIds.join(", ") || "none")}. Inbound: ${String(record.telephonyMedia.inbound)}. Outbound: ${String(record.telephonyMedia.outbound)}. Marks: ${String(record.telephonyMedia.marks)}. Clears: ${String(record.telephonyMedia.clears)}.</p><ul>${telephonyMedia}</ul></section><section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, media streams, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
29158
29346
|
};
|
|
29159
29347
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
29160
29348
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
29161
29349
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
29162
29350
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
29163
29351
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
29164
|
-
const routes = new
|
|
29352
|
+
const routes = new Elysia51({
|
|
29165
29353
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
29166
29354
|
});
|
|
29167
29355
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -29812,7 +30000,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
29812
30000
|
...options.headers ?? {}
|
|
29813
30001
|
};
|
|
29814
30002
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
29815
|
-
const app = new
|
|
30003
|
+
const app = new Elysia52({
|
|
29816
30004
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
29817
30005
|
});
|
|
29818
30006
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -30621,7 +30809,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
30621
30809
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
30622
30810
|
}
|
|
30623
30811
|
});
|
|
30624
|
-
const app = new
|
|
30812
|
+
const app = new Elysia52({
|
|
30625
30813
|
name: options.name ?? "absolute-voice-observability-export"
|
|
30626
30814
|
});
|
|
30627
30815
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -30698,7 +30886,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
30698
30886
|
};
|
|
30699
30887
|
|
|
30700
30888
|
// src/productionReadiness.ts
|
|
30701
|
-
var
|
|
30889
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30702
30890
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
30703
30891
|
var readinessGateCodes = {
|
|
30704
30892
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -32336,25 +32524,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
32336
32524
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
32337
32525
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
32338
32526
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
32339
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
32340
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
32527
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml51(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
32528
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml51(report.profile.name)}</h2><p>${escapeHtml51(report.profile.description)}</p><p>${escapeHtml51(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="${escapeHtml51(surface.href)}">${escapeHtml51(surface.label)}</a>` : escapeHtml51(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
32341
32529
|
const checks = report.checks.map((check, index) => {
|
|
32342
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
32343
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
32344
|
-
return `<article class="check ${
|
|
32530
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml51(action.href)}">${escapeHtml51(action.label)}</button>` : `<a href="${escapeHtml51(action.href)}">${escapeHtml51(action.label)}</a>`).join("");
|
|
32531
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml51(check.status)}: observed ${escapeHtml51(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml51(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml51(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml51(check.gateExplanation.unit)}` : ""}. ${escapeHtml51(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml51(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
32532
|
+
return `<article class="check ${escapeHtml51(check.status)}">
|
|
32345
32533
|
<div>
|
|
32346
|
-
<span>${
|
|
32347
|
-
<h2>${
|
|
32348
|
-
${check.detail ? `<p>${
|
|
32534
|
+
<span>${escapeHtml51(check.status.toUpperCase())}</span>
|
|
32535
|
+
<h2>${escapeHtml51(check.label)}</h2>
|
|
32536
|
+
${check.detail ? `<p>${escapeHtml51(check.detail)}</p>` : ""}
|
|
32349
32537
|
${explanation}
|
|
32350
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
32538
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml51(check.proofSource.href)}">${escapeHtml51(check.proofSource.sourceLabel)}</a>` : escapeHtml51(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml51(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
32351
32539
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
32352
32540
|
</div>
|
|
32353
|
-
<strong>${
|
|
32354
|
-
${check.href ? `<a href="${
|
|
32541
|
+
<strong>${escapeHtml51(String(check.value ?? check.status))}</strong>
|
|
32542
|
+
${check.href ? `<a href="${escapeHtml51(check.href)}">Open surface</a>` : ""}
|
|
32355
32543
|
</article>`;
|
|
32356
32544
|
}).join("");
|
|
32357
|
-
const snippet =
|
|
32545
|
+
const snippet = escapeHtml51(`createVoiceProductionReadinessRoutes({
|
|
32358
32546
|
htmlPath: '/production-readiness',
|
|
32359
32547
|
path: '/api/production-readiness',
|
|
32360
32548
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -32370,13 +32558,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
32370
32558
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
32371
32559
|
store: traceStore
|
|
32372
32560
|
});`);
|
|
32373
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32561
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#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>${escapeHtml51(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 ${escapeHtml51(report.status)}">Overall: ${escapeHtml51(report.status.toUpperCase())}</p><p>Checked ${escapeHtml51(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>`;
|
|
32374
32562
|
};
|
|
32375
32563
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
32376
32564
|
const path = options.path ?? "/api/production-readiness";
|
|
32377
32565
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
32378
32566
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
32379
|
-
const routes = new
|
|
32567
|
+
const routes = new Elysia53({
|
|
32380
32568
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
32381
32569
|
});
|
|
32382
32570
|
const resolveOptions = async (input) => {
|
|
@@ -32424,8 +32612,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
32424
32612
|
return routes;
|
|
32425
32613
|
};
|
|
32426
32614
|
// src/voiceMonitoring.ts
|
|
32427
|
-
import { Elysia as
|
|
32428
|
-
var
|
|
32615
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
32616
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32429
32617
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
32430
32618
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
32431
32619
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -32678,14 +32866,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
32678
32866
|
};
|
|
32679
32867
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
32680
32868
|
const title = options.title ?? "Voice Monitors";
|
|
32681
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
32682
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
32683
|
-
const snippet =
|
|
32869
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml52(run.label)}</td><td class="${escapeHtml52(run.status)}">${escapeHtml52(run.status)}</td><td>${escapeHtml52(run.severity)}</td><td>${escapeHtml52(String(run.value ?? ""))}</td><td>${escapeHtml52(String(run.threshold ?? ""))}</td><td>${escapeHtml52(run.detail ?? "")}</td></tr>`).join("");
|
|
32870
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml52(issue.label)}</strong> <span class="${escapeHtml52(issue.status)}">${escapeHtml52(issue.status)}</span> ${escapeHtml52(issue.detail ?? "")}</li>`).join("");
|
|
32871
|
+
const snippet = escapeHtml52(`app.use(createVoiceMonitorRoutes({
|
|
32684
32872
|
evidence,
|
|
32685
32873
|
issueStore,
|
|
32686
32874
|
monitors: [defineVoiceMonitor(...)]
|
|
32687
32875
|
}));`);
|
|
32688
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32876
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#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>${escapeHtml52(title)}</h1><p class="pill ${escapeHtml52(report.status)}">Status: ${escapeHtml52(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>`;
|
|
32689
32877
|
};
|
|
32690
32878
|
var actorFromRequest = async (request) => {
|
|
32691
32879
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -32709,7 +32897,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
32709
32897
|
monitors: options.monitors,
|
|
32710
32898
|
now: options.now
|
|
32711
32899
|
});
|
|
32712
|
-
const routes = new
|
|
32900
|
+
const routes = new Elysia54({
|
|
32713
32901
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
32714
32902
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
32715
32903
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -32756,7 +32944,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
32756
32944
|
};
|
|
32757
32945
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
32758
32946
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
32759
|
-
return new
|
|
32947
|
+
return new Elysia54({
|
|
32760
32948
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
32761
32949
|
}).get(path, () => ({
|
|
32762
32950
|
isRunning: options.runner.isRunning()
|
|
@@ -33132,8 +33320,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
33132
33320
|
};
|
|
33133
33321
|
};
|
|
33134
33322
|
// src/providerStackRecommendations.ts
|
|
33135
|
-
import { Elysia as
|
|
33136
|
-
var
|
|
33323
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
33324
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33137
33325
|
var profileProviderPriorities = {
|
|
33138
33326
|
"meeting-recorder": {
|
|
33139
33327
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -33452,17 +33640,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
33452
33640
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
33453
33641
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
33454
33642
|
const rows = report.rows.map((row) => {
|
|
33455
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
33456
|
-
return `<article class="row ${
|
|
33643
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml53(check.status)}"><strong>${escapeHtml53(check.label)}</strong><span>${escapeHtml53(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml53(check.remediation.href)}">${escapeHtml53(check.remediation.label)}</a>` : escapeHtml53(check.remediation.label)}: ${escapeHtml53(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
33644
|
+
return `<article class="row ${escapeHtml53(row.status)}">
|
|
33457
33645
|
<div>
|
|
33458
|
-
<p class="eyebrow">${
|
|
33459
|
-
<h2>${
|
|
33460
|
-
<p class="status ${
|
|
33646
|
+
<p class="eyebrow">${escapeHtml53(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
33647
|
+
<h2>${escapeHtml53(row.provider)}</h2>
|
|
33648
|
+
<p class="status ${escapeHtml53(row.status)}">${escapeHtml53(row.status.toUpperCase())}</p>
|
|
33461
33649
|
</div>
|
|
33462
33650
|
<ul>${checks}</ul>
|
|
33463
33651
|
</article>`;
|
|
33464
33652
|
}).join("");
|
|
33465
|
-
const snippet =
|
|
33653
|
+
const snippet = escapeHtml53(`const providerContracts = () =>
|
|
33466
33654
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
33467
33655
|
env: process.env,
|
|
33468
33656
|
providers: {
|
|
@@ -33483,7 +33671,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
33483
33671
|
providerContractMatrix: () =>
|
|
33484
33672
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
33485
33673
|
});`);
|
|
33486
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33674
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(title)}</title><style>body{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>${escapeHtml53(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>`;
|
|
33487
33675
|
};
|
|
33488
33676
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
33489
33677
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -33498,7 +33686,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
33498
33686
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
33499
33687
|
const path = options.path ?? "/api/provider-contracts";
|
|
33500
33688
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
33501
|
-
const routes = new
|
|
33689
|
+
const routes = new Elysia55({
|
|
33502
33690
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
33503
33691
|
});
|
|
33504
33692
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -33616,7 +33804,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
33616
33804
|
return assertion;
|
|
33617
33805
|
};
|
|
33618
33806
|
// src/opsConsoleRoutes.ts
|
|
33619
|
-
import { Elysia as
|
|
33807
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
33620
33808
|
var DEFAULT_LINKS = [
|
|
33621
33809
|
{
|
|
33622
33810
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -33651,7 +33839,7 @@ var DEFAULT_LINKS = [
|
|
|
33651
33839
|
label: "Handoffs"
|
|
33652
33840
|
}
|
|
33653
33841
|
];
|
|
33654
|
-
var
|
|
33842
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33655
33843
|
var countProviderStatuses = (providers) => {
|
|
33656
33844
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
33657
33845
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -33720,20 +33908,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
33720
33908
|
trace
|
|
33721
33909
|
};
|
|
33722
33910
|
};
|
|
33723
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
33911
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml54(input.label)}</span><strong>${escapeHtml54(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml54(input.status)}">${escapeHtml54(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml54(input.href)}">Open</a>` : ""}</article>`;
|
|
33724
33912
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
33725
33913
|
const links = report.links.map((link) => `<article class="surface">
|
|
33726
|
-
<div><h2>${
|
|
33727
|
-
<p><a href="${
|
|
33914
|
+
<div><h2>${escapeHtml54(link.label)}</h2>${link.description ? `<p>${escapeHtml54(link.description)}</p>` : ""}</div>
|
|
33915
|
+
<p><a href="${escapeHtml54(link.href)}">Open ${escapeHtml54(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml54(link.statusHref)}">Status</a>` : ""}</p>
|
|
33728
33916
|
</article>`).join("");
|
|
33729
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
33730
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
33917
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml54(session.sessionId)}</td><td>${escapeHtml54(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml54(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
33918
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml54(event.kind)}</td><td>${escapeHtml54(event.provider ?? "unknown")}</td><td>${escapeHtml54(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml54(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
33731
33919
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
33732
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33920
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(title)}</title><style>body{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>${escapeHtml54(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 ${escapeHtml54(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>`;
|
|
33733
33921
|
};
|
|
33734
33922
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
33735
33923
|
const path = options.path ?? "/ops-console";
|
|
33736
|
-
const routes = new
|
|
33924
|
+
const routes = new Elysia56({
|
|
33737
33925
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
33738
33926
|
});
|
|
33739
33927
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -33750,7 +33938,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
33750
33938
|
return routes;
|
|
33751
33939
|
};
|
|
33752
33940
|
// src/incidentBundle.ts
|
|
33753
|
-
import { Elysia as
|
|
33941
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
33754
33942
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
33755
33943
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
33756
33944
|
return false;
|
|
@@ -33951,7 +34139,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
33951
34139
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
33952
34140
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
33953
34141
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
33954
|
-
const routes = new
|
|
34142
|
+
const routes = new Elysia57({
|
|
33955
34143
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
33956
34144
|
});
|
|
33957
34145
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -34152,19 +34340,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
34152
34340
|
};
|
|
34153
34341
|
};
|
|
34154
34342
|
// src/opsStatusRoutes.ts
|
|
34155
|
-
import { Elysia as
|
|
34156
|
-
var
|
|
34343
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
34344
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34157
34345
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
34158
34346
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
34159
34347
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
34160
34348
|
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;
|
|
34161
|
-
return `<article class="surface ${
|
|
34349
|
+
return `<article class="surface ${escapeHtml55(surface.status)}"><span>${escapeHtml55(surface.status.toUpperCase())}</span><h2>${escapeHtml55(key)}</h2><strong>${escapeHtml55(value)}</strong></article>`;
|
|
34162
34350
|
}).join("");
|
|
34163
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34351
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#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>${escapeHtml55(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml55(report.status)}">Overall: ${escapeHtml55(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>`;
|
|
34164
34352
|
};
|
|
34165
34353
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
34166
34354
|
const path = options.path ?? "/api/voice/ops-status";
|
|
34167
|
-
const routes = new
|
|
34355
|
+
const routes = new Elysia58({
|
|
34168
34356
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
34169
34357
|
});
|
|
34170
34358
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -34597,8 +34785,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
34597
34785
|
};
|
|
34598
34786
|
};
|
|
34599
34787
|
// src/traceDeliveryRoutes.ts
|
|
34600
|
-
import { Elysia as
|
|
34601
|
-
var
|
|
34788
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
34789
|
+
var escapeHtml56 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34602
34790
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
34603
34791
|
var getNumber12 = (value) => {
|
|
34604
34792
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -34679,14 +34867,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
34679
34867
|
if (entries.length === 0) {
|
|
34680
34868
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
34681
34869
|
}
|
|
34682
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
34870
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml56(sinkId)}</strong>: ${escapeHtml56(result.status)}${result.deliveredTo ? ` to ${escapeHtml56(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml56(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
34683
34871
|
};
|
|
34684
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
34872
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml56(event.type)} <small>${escapeHtml56(event.id)}</small>${event.sessionId ? ` session=${escapeHtml56(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
34685
34873
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
34686
34874
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
34687
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
34688
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
34689
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34875
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml56(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
34876
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml56(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml56(delivery.deliveryStatus)}</span><h2>${escapeHtml56(delivery.id)}</h2><p>${escapeHtml56(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml56(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml56(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
34877
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(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>${escapeHtml56(title)}</h1><p>Checked ${escapeHtml56(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>`;
|
|
34690
34878
|
};
|
|
34691
34879
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
34692
34880
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -34706,7 +34894,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
34706
34894
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
34707
34895
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
34708
34896
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
34709
|
-
const routes = new
|
|
34897
|
+
const routes = new Elysia59({
|
|
34710
34898
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
34711
34899
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
34712
34900
|
if (htmlPath !== false) {
|
|
@@ -34803,7 +34991,7 @@ var createVoiceMemoryStore = () => {
|
|
|
34803
34991
|
return { get, getOrCreate, list, remove, set };
|
|
34804
34992
|
};
|
|
34805
34993
|
// src/opsWebhook.ts
|
|
34806
|
-
import { Elysia as
|
|
34994
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
34807
34995
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
34808
34996
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
34809
34997
|
const encoder = new TextEncoder;
|
|
@@ -34933,7 +35121,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
34933
35121
|
};
|
|
34934
35122
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
34935
35123
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
34936
|
-
return new
|
|
35124
|
+
return new Elysia60().post(path, async ({ body, request, set }) => {
|
|
34937
35125
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
34938
35126
|
if (options.signingSecret) {
|
|
34939
35127
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -35388,7 +35576,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
35388
35576
|
};
|
|
35389
35577
|
};
|
|
35390
35578
|
// src/postCallAnalysis.ts
|
|
35391
|
-
import { Elysia as
|
|
35579
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
35392
35580
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
35393
35581
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
35394
35582
|
var getPathValue3 = (source, path) => {
|
|
@@ -35567,7 +35755,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
35567
35755
|
};
|
|
35568
35756
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
35569
35757
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
35570
|
-
const routes = new
|
|
35758
|
+
const routes = new Elysia61({
|
|
35571
35759
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
35572
35760
|
});
|
|
35573
35761
|
routes.get(path, async ({ query }) => {
|
|
@@ -35592,7 +35780,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
35592
35780
|
return routes;
|
|
35593
35781
|
};
|
|
35594
35782
|
// src/guardrails.ts
|
|
35595
|
-
import { Elysia as
|
|
35783
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
35596
35784
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
35597
35785
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
35598
35786
|
var matchesRule = async (rule, input) => {
|
|
@@ -35894,7 +36082,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
35894
36082
|
};
|
|
35895
36083
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
35896
36084
|
const path = options.path ?? "/api/voice/guardrails";
|
|
35897
|
-
const routes = new
|
|
36085
|
+
const routes = new Elysia62({
|
|
35898
36086
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
35899
36087
|
});
|
|
35900
36088
|
routes.all(path, async ({ request }) => {
|
|
@@ -36837,6 +37025,8 @@ export {
|
|
|
36837
37025
|
renderVoiceCallReviewMarkdown,
|
|
36838
37026
|
renderVoiceCallReviewHTML,
|
|
36839
37027
|
renderVoiceBrowserMediaHTML,
|
|
37028
|
+
renderVoiceBrowserCallProfileMarkdown,
|
|
37029
|
+
renderVoiceBrowserCallProfileHTML,
|
|
36840
37030
|
renderVoiceBargeInHTML,
|
|
36841
37031
|
renderVoiceAuditTrailHTML,
|
|
36842
37032
|
renderVoiceAuditMarkdown,
|
|
@@ -36918,6 +37108,7 @@ export {
|
|
|
36918
37108
|
evaluateVoiceCompetitiveCoverage,
|
|
36919
37109
|
evaluateVoiceCampaignReadinessEvidence,
|
|
36920
37110
|
evaluateVoiceCampaignDialerProofEvidence,
|
|
37111
|
+
evaluateVoiceBrowserCallProfileEvidence,
|
|
36921
37112
|
evaluateVoiceAgentSquadContractEvidence,
|
|
36922
37113
|
encodeTwilioMulawBase64,
|
|
36923
37114
|
deliverVoiceTraceEventsToSinks,
|
|
@@ -37174,6 +37365,7 @@ export {
|
|
|
37174
37365
|
createVoiceCallCompletedEvent,
|
|
37175
37366
|
createVoiceCRMActivitySink,
|
|
37176
37367
|
createVoiceBrowserMediaRoutes,
|
|
37368
|
+
createVoiceBrowserCallProfileRoutes,
|
|
37177
37369
|
createVoiceBargeInRoutes,
|
|
37178
37370
|
createVoiceAuditTrailRoutes,
|
|
37179
37371
|
createVoiceAuditSinkStore,
|
|
@@ -37275,6 +37467,7 @@ export {
|
|
|
37275
37467
|
buildVoiceDataControlReport,
|
|
37276
37468
|
buildVoiceCompetitiveCoverageReport,
|
|
37277
37469
|
buildVoiceCampaignObservabilityReport,
|
|
37470
|
+
buildVoiceBrowserCallProfileReport,
|
|
37278
37471
|
buildVoiceAuditTrailReport,
|
|
37279
37472
|
buildVoiceAuditExport,
|
|
37280
37473
|
buildVoiceAuditDeliveryReport,
|
|
@@ -37312,6 +37505,7 @@ export {
|
|
|
37312
37505
|
assertVoiceCompetitiveCoverage,
|
|
37313
37506
|
assertVoiceCampaignReadinessEvidence,
|
|
37314
37507
|
assertVoiceCampaignDialerProofEvidence,
|
|
37508
|
+
assertVoiceBrowserCallProfileEvidence,
|
|
37315
37509
|
assertVoiceAgentSquadContractEvidence,
|
|
37316
37510
|
assertVoiceAgentSquadContract,
|
|
37317
37511
|
applyVoiceTelephonyOutcome,
|