@absolutejs/voice 0.0.22-beta.344 → 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/index.d.ts +2 -0
- package/dist/index.js +603 -412
- 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
|
{
|
|
@@ -15139,7 +15324,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
15139
15324
|
}
|
|
15140
15325
|
};
|
|
15141
15326
|
};
|
|
15142
|
-
var
|
|
15327
|
+
var escapeHtml23 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15143
15328
|
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
15144
15329
|
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
15145
15330
|
`# ${title}`,
|
|
@@ -15172,18 +15357,18 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
15172
15357
|
].join(`
|
|
15173
15358
|
`);
|
|
15174
15359
|
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
15175
|
-
const cards = report.recommendations.map((recommendation) => `<article class="${
|
|
15176
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
15177
|
-
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${
|
|
15178
|
-
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${
|
|
15179
|
-
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>`;
|
|
15180
15365
|
};
|
|
15181
15366
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
15182
15367
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
15183
15368
|
const htmlPath = options.htmlPath === undefined ? "/voice/proof-trend-recommendations" : options.htmlPath;
|
|
15184
15369
|
const markdownPath = options.markdownPath === undefined ? "/voice/proof-trend-recommendations.md" : options.markdownPath;
|
|
15185
15370
|
const title = options.title ?? "Voice Provider Runtime Recommendations";
|
|
15186
|
-
const routes = new
|
|
15371
|
+
const routes = new Elysia21({
|
|
15187
15372
|
name: options.name ?? "absolutejs-voice-proof-trend-recommendations"
|
|
15188
15373
|
});
|
|
15189
15374
|
const loadReport = async () => {
|
|
@@ -15222,7 +15407,7 @@ var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
|
15222
15407
|
};
|
|
15223
15408
|
var createVoiceProofTrendRoutes = (options) => {
|
|
15224
15409
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
15225
|
-
const routes = new
|
|
15410
|
+
const routes = new Elysia21({
|
|
15226
15411
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
15227
15412
|
});
|
|
15228
15413
|
routes.get(path, async () => {
|
|
@@ -15255,11 +15440,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
15255
15440
|
return `${days}d ${hours % 24}h`;
|
|
15256
15441
|
};
|
|
15257
15442
|
// src/providerDecisionTraces.ts
|
|
15258
|
-
import { Elysia as
|
|
15443
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
15259
15444
|
|
|
15260
15445
|
// src/resilienceRoutes.ts
|
|
15261
|
-
import { Elysia as
|
|
15262
|
-
var
|
|
15446
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
15447
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15263
15448
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
15264
15449
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15265
15450
|
var getBoolean2 = (value) => value === true;
|
|
@@ -15407,13 +15592,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
15407
15592
|
};
|
|
15408
15593
|
var renderProviderCards = (title, providers) => {
|
|
15409
15594
|
if (providers.length === 0) {
|
|
15410
|
-
return `<p class="muted">No ${
|
|
15595
|
+
return `<p class="muted">No ${escapeHtml24(title)} provider health yet.</p>`;
|
|
15411
15596
|
}
|
|
15412
15597
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
15413
|
-
<article class="card provider ${
|
|
15598
|
+
<article class="card provider ${escapeHtml24(provider.status)}">
|
|
15414
15599
|
<div class="card-header">
|
|
15415
|
-
<strong>${
|
|
15416
|
-
<span>${
|
|
15600
|
+
<strong>${escapeHtml24(provider.provider)}</strong>
|
|
15601
|
+
<span>${escapeHtml24(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
15417
15602
|
</div>
|
|
15418
15603
|
<dl>
|
|
15419
15604
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -15422,7 +15607,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
15422
15607
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
15423
15608
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
15424
15609
|
</dl>
|
|
15425
|
-
${provider.lastError ? `<p class="muted">${
|
|
15610
|
+
${provider.lastError ? `<p class="muted">${escapeHtml24(provider.lastError)}</p>` : ""}
|
|
15426
15611
|
</article>
|
|
15427
15612
|
`).join("")}</div>`;
|
|
15428
15613
|
};
|
|
@@ -15431,24 +15616,24 @@ var renderTimeline2 = (events) => {
|
|
|
15431
15616
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
15432
15617
|
}
|
|
15433
15618
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
15434
|
-
<article class="card event ${
|
|
15619
|
+
<article class="card event ${escapeHtml24(event.status ?? "unknown")}">
|
|
15435
15620
|
<div class="card-header">
|
|
15436
|
-
<strong>${
|
|
15621
|
+
<strong>${escapeHtml24(event.kind.toUpperCase())} ${escapeHtml24(event.operation ?? "generate")}</strong>
|
|
15437
15622
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
15438
15623
|
</div>
|
|
15439
15624
|
<p>
|
|
15440
|
-
<span class="pill">${
|
|
15441
|
-
<span class="pill">provider: ${
|
|
15442
|
-
${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>` : ""}
|
|
15443
15628
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
15444
15629
|
</p>
|
|
15445
15630
|
<dl>
|
|
15446
15631
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
15447
15632
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
15448
15633
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
15449
|
-
<div><dt>Session</dt><dd>${
|
|
15634
|
+
<div><dt>Session</dt><dd>${escapeHtml24(event.sessionId)}</dd></div>
|
|
15450
15635
|
</dl>
|
|
15451
|
-
${event.error ? `<p class="muted">${
|
|
15636
|
+
${event.error ? `<p class="muted">${escapeHtml24(event.error)}</p>` : ""}
|
|
15452
15637
|
</article>
|
|
15453
15638
|
`).join("")}</div>`;
|
|
15454
15639
|
};
|
|
@@ -15458,9 +15643,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
15458
15643
|
const status = latest?.status ?? "idle";
|
|
15459
15644
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
15460
15645
|
return `<div>
|
|
15461
|
-
<dt>${
|
|
15462
|
-
<dd>${
|
|
15463
|
-
<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>
|
|
15464
15649
|
</div>`;
|
|
15465
15650
|
};
|
|
15466
15651
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -15468,10 +15653,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
15468
15653
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
15469
15654
|
}
|
|
15470
15655
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
15471
|
-
<article class="card session ${
|
|
15656
|
+
<article class="card session ${escapeHtml24(session.status)}">
|
|
15472
15657
|
<div class="card-header">
|
|
15473
|
-
<strong>${
|
|
15474
|
-
<span>${
|
|
15658
|
+
<strong>${escapeHtml24(session.sessionId)}</strong>
|
|
15659
|
+
<span>${escapeHtml24(session.status)}</span>
|
|
15475
15660
|
</div>
|
|
15476
15661
|
<p>
|
|
15477
15662
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -15498,21 +15683,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
15498
15683
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
15499
15684
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
15500
15685
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
15501
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
15502
|
-
<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>
|
|
15503
15688
|
<div class="simulate-actions">
|
|
15504
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
15505
|
-
${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("")}
|
|
15506
15691
|
</div>
|
|
15507
|
-
${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>` : ""}
|
|
15508
15693
|
<pre class="simulate-output" hidden></pre>
|
|
15509
15694
|
</div>`;
|
|
15510
15695
|
};
|
|
15511
15696
|
var renderVoiceResilienceHTML = (input) => {
|
|
15512
15697
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
15513
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
15514
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
15515
|
-
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({
|
|
15516
15701
|
kind: 'stt',
|
|
15517
15702
|
providers: ['deepgram', 'assemblyai'],
|
|
15518
15703
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -15550,7 +15735,7 @@ app.use(
|
|
|
15550
15735
|
<head>
|
|
15551
15736
|
<meta charset="utf-8" />
|
|
15552
15737
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15553
|
-
<title>${
|
|
15738
|
+
<title>${escapeHtml24(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
15554
15739
|
<style>
|
|
15555
15740
|
:root { color-scheme: dark; }
|
|
15556
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; }
|
|
@@ -15702,7 +15887,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
15702
15887
|
};
|
|
15703
15888
|
var createVoiceResilienceRoutes = (options) => {
|
|
15704
15889
|
const path = options.path ?? "/resilience";
|
|
15705
|
-
const routes = new
|
|
15890
|
+
const routes = new Elysia22({
|
|
15706
15891
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
15707
15892
|
}).get(path, async () => {
|
|
15708
15893
|
const events = await options.store.list();
|
|
@@ -15743,7 +15928,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
15743
15928
|
};
|
|
15744
15929
|
|
|
15745
15930
|
// src/providerDecisionTraces.ts
|
|
15746
|
-
var
|
|
15931
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15747
15932
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
15748
15933
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15749
15934
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -15984,7 +16169,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
15984
16169
|
<head>
|
|
15985
16170
|
<meta charset="utf-8" />
|
|
15986
16171
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15987
|
-
<title>${
|
|
16172
|
+
<title>${escapeHtml25(title)}</title>
|
|
15988
16173
|
<style>
|
|
15989
16174
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
15990
16175
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -15998,8 +16183,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
15998
16183
|
</head>
|
|
15999
16184
|
<body>
|
|
16000
16185
|
<main>
|
|
16001
|
-
<p class="status ${report.status}">${
|
|
16002
|
-
<h1>${
|
|
16186
|
+
<p class="status ${report.status}">${escapeHtml25(report.status)}</p>
|
|
16187
|
+
<h1>${escapeHtml25(title)}</h1>
|
|
16003
16188
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
16004
16189
|
<section class="grid">
|
|
16005
16190
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -16010,10 +16195,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
16010
16195
|
</section>
|
|
16011
16196
|
<section class="surfaces">
|
|
16012
16197
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
16013
|
-
<header><strong>${
|
|
16198
|
+
<header><strong>${escapeHtml25(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml25(surface.status)}</span></header>
|
|
16014
16199
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
16015
|
-
<p class="muted">Providers: ${
|
|
16016
|
-
<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>
|
|
16017
16202
|
</article>`).join(`
|
|
16018
16203
|
`)}
|
|
16019
16204
|
</section>
|
|
@@ -16027,7 +16212,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16027
16212
|
const headers = options.headers ?? {};
|
|
16028
16213
|
const title = options.title ?? "Provider Decision Traces";
|
|
16029
16214
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
16030
|
-
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), {
|
|
16031
16216
|
headers: {
|
|
16032
16217
|
"content-type": "application/json; charset=utf-8",
|
|
16033
16218
|
...headers
|
|
@@ -16055,7 +16240,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16055
16240
|
return app;
|
|
16056
16241
|
};
|
|
16057
16242
|
// src/sloCalibration.ts
|
|
16058
|
-
import { Elysia as
|
|
16243
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
16059
16244
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
16060
16245
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
16061
16246
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -16236,7 +16421,7 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
16236
16421
|
};
|
|
16237
16422
|
};
|
|
16238
16423
|
var escapeMarkdown3 = (value) => value.replaceAll("|", "\\|");
|
|
16239
|
-
var
|
|
16424
|
+
var escapeHtml26 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16240
16425
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
16241
16426
|
var readinessThresholdRows = (report) => [
|
|
16242
16427
|
{
|
|
@@ -16327,15 +16512,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
16327
16512
|
};
|
|
16328
16513
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
16329
16514
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
16330
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
16331
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
16332
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
16333
|
-
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>`;
|
|
16334
16519
|
};
|
|
16335
16520
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
16336
16521
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
16337
16522
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
16338
|
-
const routes = new
|
|
16523
|
+
const routes = new Elysia24({
|
|
16339
16524
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
16340
16525
|
});
|
|
16341
16526
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -16359,7 +16544,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
16359
16544
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
16360
16545
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
16361
16546
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
16362
|
-
const routes = new
|
|
16547
|
+
const routes = new Elysia24({
|
|
16363
16548
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
16364
16549
|
});
|
|
16365
16550
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -16393,7 +16578,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
16393
16578
|
return routes;
|
|
16394
16579
|
};
|
|
16395
16580
|
// src/liveOps.ts
|
|
16396
|
-
import { Elysia as
|
|
16581
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16397
16582
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
16398
16583
|
"assign",
|
|
16399
16584
|
"create-task",
|
|
@@ -16703,7 +16888,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
16703
16888
|
const controller = createVoiceLiveOpsController(options);
|
|
16704
16889
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
16705
16890
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
16706
|
-
return new
|
|
16891
|
+
return new Elysia25({
|
|
16707
16892
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
16708
16893
|
}).post(path, async ({ request, set }) => {
|
|
16709
16894
|
try {
|
|
@@ -16725,15 +16910,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
16725
16910
|
});
|
|
16726
16911
|
};
|
|
16727
16912
|
// src/deliveryRuntime.ts
|
|
16728
|
-
import { Elysia as
|
|
16913
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
16729
16914
|
import { mkdir } from "fs/promises";
|
|
16730
16915
|
import { dirname, join } from "path";
|
|
16731
|
-
var
|
|
16916
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16732
16917
|
var renderSummaryCard = (label, summary) => {
|
|
16733
16918
|
if (!summary) {
|
|
16734
|
-
return `<article><span>${
|
|
16919
|
+
return `<article><span>${escapeHtml27(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
16735
16920
|
}
|
|
16736
|
-
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>`;
|
|
16737
16922
|
};
|
|
16738
16923
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
16739
16924
|
audit: leases,
|
|
@@ -16944,9 +17129,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
16944
17129
|
});
|
|
16945
17130
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
16946
17131
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
16947
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
16948
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
16949
|
-
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(
|
|
16950
17135
|
createVoiceDeliveryRuntimePresetConfig({
|
|
16951
17136
|
audit: {
|
|
16952
17137
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -16972,14 +17157,14 @@ app.use(
|
|
|
16972
17157
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
16973
17158
|
})
|
|
16974
17159
|
);`);
|
|
16975
|
-
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>`;
|
|
16976
17161
|
};
|
|
16977
17162
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
16978
17163
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
16979
17164
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
16980
17165
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
16981
17166
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
16982
|
-
const routes = new
|
|
17167
|
+
const routes = new Elysia26({
|
|
16983
17168
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
16984
17169
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
16985
17170
|
if (tickPath !== false) {
|
|
@@ -17015,7 +17200,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
17015
17200
|
return routes;
|
|
17016
17201
|
};
|
|
17017
17202
|
// src/dataControl.ts
|
|
17018
|
-
import { Elysia as
|
|
17203
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
17019
17204
|
var voiceComplianceRedactionDefaults = {
|
|
17020
17205
|
keys: [
|
|
17021
17206
|
"apiKey",
|
|
@@ -17254,7 +17439,7 @@ var parseRetentionScopes = (value) => {
|
|
|
17254
17439
|
const allowed = new Set(allRetentionScopes);
|
|
17255
17440
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
17256
17441
|
};
|
|
17257
|
-
var
|
|
17442
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17258
17443
|
var buildStorageSurfaces = (options) => [
|
|
17259
17444
|
{
|
|
17260
17445
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -17491,12 +17676,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
17491
17676
|
zeroRetentionAvailable: true
|
|
17492
17677
|
};
|
|
17493
17678
|
};
|
|
17494
|
-
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("");
|
|
17495
17680
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
17496
17681
|
const title = options.title ?? "Voice Data Control";
|
|
17497
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
17498
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
17499
|
-
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>`;
|
|
17500
17685
|
};
|
|
17501
17686
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
17502
17687
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -17554,7 +17739,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
17554
17739
|
var createVoiceDataControlRoutes = (options) => {
|
|
17555
17740
|
const path = options.path ?? "/data-control";
|
|
17556
17741
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
17557
|
-
const routes = new
|
|
17742
|
+
const routes = new Elysia27({
|
|
17558
17743
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
17559
17744
|
});
|
|
17560
17745
|
routes.get(path, async ({ query }) => {
|
|
@@ -17630,16 +17815,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
17630
17815
|
return routes;
|
|
17631
17816
|
};
|
|
17632
17817
|
// src/evalRoutes.ts
|
|
17633
|
-
import { Elysia as
|
|
17818
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
17634
17819
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
17635
17820
|
import { dirname as dirname2 } from "path";
|
|
17636
17821
|
|
|
17637
17822
|
// src/qualityRoutes.ts
|
|
17638
|
-
import { Elysia as
|
|
17823
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
17639
17824
|
|
|
17640
17825
|
// src/handoffHealth.ts
|
|
17641
|
-
import { Elysia as
|
|
17642
|
-
var
|
|
17826
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17827
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17643
17828
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
17644
17829
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
17645
17830
|
var increment3 = (record, key) => {
|
|
@@ -17757,10 +17942,10 @@ var renderActionSummary = (summary) => {
|
|
|
17757
17942
|
return [
|
|
17758
17943
|
'<section class="voice-handoff-health-columns">',
|
|
17759
17944
|
"<article><h3>Actions</h3>",
|
|
17760
|
-
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>`,
|
|
17761
17946
|
"</article>",
|
|
17762
17947
|
"<article><h3>Adapters</h3>",
|
|
17763
|
-
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>`,
|
|
17764
17949
|
"</article>",
|
|
17765
17950
|
"</section>"
|
|
17766
17951
|
].join("");
|
|
@@ -17774,22 +17959,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
17774
17959
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
17775
17960
|
'<div class="voice-handoff-health-events">',
|
|
17776
17961
|
...summary.events.map((event) => [
|
|
17777
|
-
`<article class="${
|
|
17962
|
+
`<article class="${escapeHtml29(event.status)}">`,
|
|
17778
17963
|
'<div class="voice-handoff-health-event-header">',
|
|
17779
|
-
`<strong>${
|
|
17780
|
-
`<span>${
|
|
17964
|
+
`<strong>${escapeHtml29(event.action ?? "handoff")}</strong>`,
|
|
17965
|
+
`<span>${escapeHtml29(event.status)}</span>`,
|
|
17781
17966
|
"</div>",
|
|
17782
|
-
`<p><small>${
|
|
17783
|
-
event.target ? `<p>Target: ${
|
|
17784
|
-
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>` : "",
|
|
17785
17970
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
17786
17971
|
"<li>",
|
|
17787
|
-
`${
|
|
17788
|
-
delivery.deliveredTo ? ` to ${
|
|
17789
|
-
delivery.error ? ` (${
|
|
17972
|
+
`${escapeHtml29(delivery.adapterId)}: ${escapeHtml29(delivery.status)}`,
|
|
17973
|
+
delivery.deliveredTo ? ` to ${escapeHtml29(delivery.deliveredTo)}` : "",
|
|
17974
|
+
delivery.error ? ` (${escapeHtml29(delivery.error)})` : "",
|
|
17790
17975
|
"</li>"
|
|
17791
17976
|
].join("")).join("")}</ul>` : "",
|
|
17792
|
-
event.replayHref ? `<p><a href="${
|
|
17977
|
+
event.replayHref ? `<p><a href="${escapeHtml29(event.replayHref)}">Open replay</a></p>` : "",
|
|
17793
17978
|
"</article>"
|
|
17794
17979
|
].join("")),
|
|
17795
17980
|
"</div>"
|
|
@@ -17821,7 +18006,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
17821
18006
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
17822
18007
|
const path = options.path ?? "/api/voice-handoffs";
|
|
17823
18008
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
17824
|
-
const routes = new
|
|
18009
|
+
const routes = new Elysia28({
|
|
17825
18010
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
17826
18011
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
17827
18012
|
if (htmlPath) {
|
|
@@ -17942,17 +18127,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
17942
18127
|
thresholds
|
|
17943
18128
|
};
|
|
17944
18129
|
};
|
|
17945
|
-
var
|
|
18130
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17946
18131
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
17947
18132
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
17948
18133
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
17949
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
17950
|
-
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>` : "";
|
|
17951
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>`;
|
|
17952
18137
|
};
|
|
17953
18138
|
var createVoiceQualityRoutes = (options) => {
|
|
17954
18139
|
const path = options.path ?? "/quality";
|
|
17955
|
-
const routes = new
|
|
18140
|
+
const routes = new Elysia29({
|
|
17956
18141
|
name: options.name ?? "absolutejs-voice-quality"
|
|
17957
18142
|
});
|
|
17958
18143
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -17981,7 +18166,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
17981
18166
|
};
|
|
17982
18167
|
|
|
17983
18168
|
// src/evalRoutes.ts
|
|
17984
|
-
var
|
|
18169
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17985
18170
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
17986
18171
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
17987
18172
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -18303,7 +18488,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
18303
18488
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
18304
18489
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
18305
18490
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
18306
|
-
const snippet =
|
|
18491
|
+
const snippet = escapeHtml31(`app.use(
|
|
18307
18492
|
createVoiceEvalRoutes({
|
|
18308
18493
|
path: '/evals',
|
|
18309
18494
|
store: traceStore,
|
|
@@ -18324,48 +18509,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
18324
18509
|
};
|
|
18325
18510
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
18326
18511
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
18327
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18328
|
-
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>';
|
|
18329
18514
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
18330
18515
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
18331
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
18332
|
-
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>`;
|
|
18333
18518
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
18334
|
-
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>`;
|
|
18335
18520
|
};
|
|
18336
18521
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
18337
18522
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
18338
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18339
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
18340
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
18341
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
18342
|
-
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>`;
|
|
18343
18528
|
};
|
|
18344
18529
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
18345
18530
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
18346
|
-
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>` : "";
|
|
18347
18532
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
18348
|
-
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>` : "";
|
|
18349
18534
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
18350
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
18351
|
-
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>`;
|
|
18352
18537
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
18353
|
-
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>`;
|
|
18354
18539
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
18355
|
-
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>`;
|
|
18356
18541
|
};
|
|
18357
18542
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
18358
18543
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
18359
|
-
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>` : "";
|
|
18360
18545
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
18361
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
18362
|
-
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>`;
|
|
18363
18548
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
18364
|
-
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>`;
|
|
18365
18550
|
};
|
|
18366
18551
|
var createVoiceEvalRoutes = (options) => {
|
|
18367
18552
|
const path = options.path ?? "/evals";
|
|
18368
|
-
const routes = new
|
|
18553
|
+
const routes = new Elysia30({
|
|
18369
18554
|
name: options.name ?? "absolutejs-voice-evals"
|
|
18370
18555
|
});
|
|
18371
18556
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -18502,11 +18687,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
18502
18687
|
return routes;
|
|
18503
18688
|
};
|
|
18504
18689
|
// src/simulationSuite.ts
|
|
18505
|
-
import { Elysia as
|
|
18690
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
18506
18691
|
|
|
18507
18692
|
// src/outcomeContract.ts
|
|
18508
|
-
import { Elysia as
|
|
18509
|
-
var
|
|
18693
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18694
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18510
18695
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
18511
18696
|
if (value === false) {
|
|
18512
18697
|
return;
|
|
@@ -18717,13 +18902,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
18717
18902
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
18718
18903
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
18719
18904
|
const contracts = report.contracts.map((contract) => {
|
|
18720
|
-
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>` : "";
|
|
18721
18906
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
18722
18907
|
<div class="contract-header">
|
|
18723
18908
|
<div>
|
|
18724
|
-
<p class="eyebrow">${
|
|
18725
|
-
<h2>${
|
|
18726
|
-
${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>` : ""}
|
|
18727
18912
|
${sessionLinks}
|
|
18728
18913
|
</div>
|
|
18729
18914
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -18735,10 +18920,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
18735
18920
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
18736
18921
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
18737
18922
|
</div>
|
|
18738
|
-
${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>` : ""}
|
|
18739
18924
|
</section>`;
|
|
18740
18925
|
}).join("");
|
|
18741
|
-
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>`;
|
|
18742
18927
|
};
|
|
18743
18928
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
18744
18929
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -18754,7 +18939,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
18754
18939
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
18755
18940
|
const path = options.path ?? "/api/outcome-contracts";
|
|
18756
18941
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18757
|
-
const routes = new
|
|
18942
|
+
const routes = new Elysia31({
|
|
18758
18943
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
18759
18944
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
18760
18945
|
if (htmlPath) {
|
|
@@ -18764,7 +18949,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
18764
18949
|
};
|
|
18765
18950
|
|
|
18766
18951
|
// src/toolContract.ts
|
|
18767
|
-
import { Elysia as
|
|
18952
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
18768
18953
|
|
|
18769
18954
|
// src/toolRuntime.ts
|
|
18770
18955
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -18973,7 +19158,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
18973
19158
|
});
|
|
18974
19159
|
var defaultApi = {};
|
|
18975
19160
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
18976
|
-
var
|
|
19161
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18977
19162
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
18978
19163
|
if (value === false) {
|
|
18979
19164
|
return;
|
|
@@ -19222,7 +19407,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
19222
19407
|
};
|
|
19223
19408
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
19224
19409
|
const title = options.title ?? "Voice Tool Contracts";
|
|
19225
|
-
const snippet =
|
|
19410
|
+
const snippet = escapeHtml33(`app.use(
|
|
19226
19411
|
createVoiceToolContractRoutes({
|
|
19227
19412
|
htmlPath: '/tool-contracts',
|
|
19228
19413
|
path: '/api/tool-contracts',
|
|
@@ -19248,20 +19433,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19248
19433
|
);`);
|
|
19249
19434
|
const contracts = report.contracts.map((contract) => {
|
|
19250
19435
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
19251
|
-
<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>
|
|
19252
19437
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
19253
|
-
<td>${
|
|
19254
|
-
<td>${
|
|
19438
|
+
<td>${escapeHtml33(testCase.status)}</td>
|
|
19439
|
+
<td>${escapeHtml33(testCase.sessionId)}</td>
|
|
19255
19440
|
<td>${String(testCase.attempts)}</td>
|
|
19256
19441
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
19257
19442
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
19258
|
-
<td>${
|
|
19443
|
+
<td>${escapeHtml33(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
19259
19444
|
</tr>`).join("");
|
|
19260
19445
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
19261
19446
|
<div class="contract-header">
|
|
19262
19447
|
<div>
|
|
19263
|
-
<p class="eyebrow">${
|
|
19264
|
-
<h2>${
|
|
19448
|
+
<p class="eyebrow">${escapeHtml33(contract.toolName)}</p>
|
|
19449
|
+
<h2>${escapeHtml33(contract.label ?? contract.contractId)}</h2>
|
|
19265
19450
|
</div>
|
|
19266
19451
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
19267
19452
|
</div>
|
|
@@ -19271,7 +19456,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19271
19456
|
</table>
|
|
19272
19457
|
</section>`;
|
|
19273
19458
|
}).join("");
|
|
19274
|
-
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>`;
|
|
19275
19460
|
};
|
|
19276
19461
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
19277
19462
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -19288,7 +19473,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
19288
19473
|
var createVoiceToolContractRoutes = (options) => {
|
|
19289
19474
|
const path = options.path ?? "/api/tool-contracts";
|
|
19290
19475
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19291
|
-
const routes = new
|
|
19476
|
+
const routes = new Elysia32({
|
|
19292
19477
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
19293
19478
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
19294
19479
|
if (htmlPath) {
|
|
@@ -19298,7 +19483,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
19298
19483
|
};
|
|
19299
19484
|
|
|
19300
19485
|
// src/simulationSuite.ts
|
|
19301
|
-
var
|
|
19486
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19302
19487
|
var summarizeSection = (report) => ({
|
|
19303
19488
|
failed: report.failed,
|
|
19304
19489
|
passed: report.passed,
|
|
@@ -19494,15 +19679,15 @@ var renderSection = (label, summary) => {
|
|
|
19494
19679
|
if (!summary) {
|
|
19495
19680
|
return "";
|
|
19496
19681
|
}
|
|
19497
|
-
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>`;
|
|
19498
19683
|
};
|
|
19499
19684
|
var renderAction = (action) => {
|
|
19500
|
-
const content = `<strong>${
|
|
19501
|
-
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>`;
|
|
19502
19687
|
};
|
|
19503
19688
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
19504
19689
|
const title = options.title ?? "Voice Simulation Suite";
|
|
19505
|
-
const snippet =
|
|
19690
|
+
const snippet = escapeHtml34(`app.use(
|
|
19506
19691
|
createVoiceSimulationSuiteRoutes({
|
|
19507
19692
|
htmlPath: '/voice/simulations',
|
|
19508
19693
|
path: '/api/voice/simulations',
|
|
@@ -19535,12 +19720,12 @@ app.use(
|
|
|
19535
19720
|
store: traceStore
|
|
19536
19721
|
})
|
|
19537
19722
|
);`);
|
|
19538
|
-
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>`;
|
|
19539
19724
|
};
|
|
19540
19725
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
19541
19726
|
const path = options.path ?? "/api/voice/simulations";
|
|
19542
19727
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
19543
|
-
const app = new
|
|
19728
|
+
const app = new Elysia33({
|
|
19544
19729
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
19545
19730
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
19546
19731
|
if (htmlPath) {
|
|
@@ -19852,9 +20037,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
19852
20037
|
};
|
|
19853
20038
|
};
|
|
19854
20039
|
// src/sessionReplay.ts
|
|
19855
|
-
import { Elysia as
|
|
20040
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19856
20041
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
19857
|
-
var
|
|
20042
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19858
20043
|
var increment4 = (record, key) => {
|
|
19859
20044
|
record[key] = (record[key] ?? 0) + 1;
|
|
19860
20045
|
};
|
|
@@ -20048,10 +20233,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
20048
20233
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
20049
20234
|
'<div class="voice-sessions-list">',
|
|
20050
20235
|
...sessions.map((session) => [
|
|
20051
|
-
`<article class="voice-session-card ${
|
|
20236
|
+
`<article class="voice-session-card ${escapeHtml35(session.status)}">`,
|
|
20052
20237
|
'<div class="voice-session-card-header">',
|
|
20053
|
-
`<strong>${
|
|
20054
|
-
`<span>${
|
|
20238
|
+
`<strong>${escapeHtml35(session.sessionId)}</strong>`,
|
|
20239
|
+
`<span>${escapeHtml35(session.status)}</span>`,
|
|
20055
20240
|
"</div>",
|
|
20056
20241
|
"<dl>",
|
|
20057
20242
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -20059,9 +20244,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
20059
20244
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
20060
20245
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
20061
20246
|
"</dl>",
|
|
20062
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
20063
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
20064
|
-
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>` : "",
|
|
20065
20250
|
"</article>"
|
|
20066
20251
|
].join("")),
|
|
20067
20252
|
"</div>"
|
|
@@ -20092,7 +20277,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
20092
20277
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
20093
20278
|
const path = options.path ?? "/api/voice-sessions";
|
|
20094
20279
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20095
|
-
const routes = new
|
|
20280
|
+
const routes = new Elysia34({
|
|
20096
20281
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
20097
20282
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
20098
20283
|
if (htmlPath) {
|
|
@@ -20120,7 +20305,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
20120
20305
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
20121
20306
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
20122
20307
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20123
|
-
const routes = new
|
|
20308
|
+
const routes = new Elysia34({
|
|
20124
20309
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
20125
20310
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
20126
20311
|
if (htmlPath) {
|
|
@@ -20434,10 +20619,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
20434
20619
|
return report;
|
|
20435
20620
|
};
|
|
20436
20621
|
// src/turnLatency.ts
|
|
20437
|
-
import { Elysia as
|
|
20622
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
20438
20623
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
20439
20624
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
20440
|
-
var
|
|
20625
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20441
20626
|
var firstNumber2 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
20442
20627
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
20443
20628
|
var createTraceStageIndex = (events) => {
|
|
@@ -20569,11 +20754,11 @@ await traceStore.append({
|
|
|
20569
20754
|
turnId,
|
|
20570
20755
|
type: 'turn_latency.stage'
|
|
20571
20756
|
});`;
|
|
20572
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
20573
|
-
<header><div><p class="eyebrow">${
|
|
20574
|
-
<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>
|
|
20575
20760
|
</article>`).join("");
|
|
20576
|
-
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>`;
|
|
20577
20762
|
};
|
|
20578
20763
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
20579
20764
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -20590,7 +20775,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
20590
20775
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
20591
20776
|
const path = options.path ?? "/api/turn-latency";
|
|
20592
20777
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20593
|
-
const routes = new
|
|
20778
|
+
const routes = new Elysia35({
|
|
20594
20779
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
20595
20780
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
20596
20781
|
if (htmlPath) {
|
|
@@ -20599,8 +20784,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
20599
20784
|
return routes;
|
|
20600
20785
|
};
|
|
20601
20786
|
// src/liveLatency.ts
|
|
20602
|
-
import { Elysia as
|
|
20603
|
-
var
|
|
20787
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
20788
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20604
20789
|
var percentile3 = (values, percentileValue) => {
|
|
20605
20790
|
if (values.length === 0) {
|
|
20606
20791
|
return;
|
|
@@ -20667,13 +20852,13 @@ await traceStore.append({
|
|
|
20667
20852
|
sessionId,
|
|
20668
20853
|
type: 'client.live_latency'
|
|
20669
20854
|
});`;
|
|
20670
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
20671
|
-
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>`;
|
|
20672
20857
|
};
|
|
20673
20858
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
20674
20859
|
const path = options.path ?? "/api/live-latency";
|
|
20675
20860
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
20676
|
-
const routes = new
|
|
20861
|
+
const routes = new Elysia36({
|
|
20677
20862
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
20678
20863
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
20679
20864
|
if (htmlPath) {
|
|
@@ -20992,9 +21177,9 @@ None.
|
|
|
20992
21177
|
`}`;
|
|
20993
21178
|
};
|
|
20994
21179
|
// src/turnQuality.ts
|
|
20995
|
-
import { Elysia as
|
|
21180
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
20996
21181
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
20997
|
-
var
|
|
21182
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20998
21183
|
var getTurnLatencyMs = (turn) => {
|
|
20999
21184
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
21000
21185
|
if (firstTranscriptAt === undefined) {
|
|
@@ -21065,24 +21250,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
21065
21250
|
};
|
|
21066
21251
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
21067
21252
|
const title = options.title ?? "Voice Turn Quality";
|
|
21068
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
21253
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml38(turn.status)}">
|
|
21069
21254
|
<div class="turn-header">
|
|
21070
21255
|
<div>
|
|
21071
|
-
<p class="eyebrow">${
|
|
21072
|
-
<h2>${
|
|
21256
|
+
<p class="eyebrow">${escapeHtml38(turn.sessionId)} \xB7 ${escapeHtml38(turn.turnId)}</p>
|
|
21257
|
+
<h2>${escapeHtml38(turn.text || "Empty turn")}</h2>
|
|
21073
21258
|
</div>
|
|
21074
|
-
<strong>${
|
|
21259
|
+
<strong>${escapeHtml38(turn.status)}</strong>
|
|
21075
21260
|
</div>
|
|
21076
21261
|
<dl>
|
|
21077
|
-
<div><dt>Source</dt><dd>${
|
|
21262
|
+
<div><dt>Source</dt><dd>${escapeHtml38(turn.source ?? "unknown")}</dd></div>
|
|
21078
21263
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
21079
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
21080
|
-
<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>
|
|
21081
21266
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
21082
21267
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
21083
21268
|
</dl>
|
|
21084
21269
|
</article>`).join("");
|
|
21085
|
-
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>`;
|
|
21086
21271
|
};
|
|
21087
21272
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
21088
21273
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -21099,7 +21284,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
21099
21284
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
21100
21285
|
const path = options.path ?? "/api/turn-quality";
|
|
21101
21286
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
21102
|
-
const routes = new
|
|
21287
|
+
const routes = new Elysia37({
|
|
21103
21288
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
21104
21289
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
21105
21290
|
if (htmlPath) {
|
|
@@ -21108,7 +21293,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
21108
21293
|
return routes;
|
|
21109
21294
|
};
|
|
21110
21295
|
// src/telephonyOutcome.ts
|
|
21111
|
-
import { Elysia as
|
|
21296
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21112
21297
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
21113
21298
|
"answered",
|
|
21114
21299
|
"completed",
|
|
@@ -21869,7 +22054,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
21869
22054
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
21870
22055
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
21871
22056
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
21872
|
-
return new
|
|
22057
|
+
return new Elysia38({
|
|
21873
22058
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
21874
22059
|
}).post(path, async ({ query, request }) => {
|
|
21875
22060
|
try {
|
|
@@ -21890,12 +22075,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
21890
22075
|
});
|
|
21891
22076
|
};
|
|
21892
22077
|
// src/phoneAgent.ts
|
|
21893
|
-
import { Elysia as
|
|
22078
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
21894
22079
|
|
|
21895
22080
|
// src/telephony/plivo.ts
|
|
21896
22081
|
import { Buffer as Buffer5 } from "buffer";
|
|
21897
22082
|
import { Database } from "bun:sqlite";
|
|
21898
|
-
import { Elysia as
|
|
22083
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
21899
22084
|
|
|
21900
22085
|
// src/telephony/contract.ts
|
|
21901
22086
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -21979,7 +22164,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
21979
22164
|
|
|
21980
22165
|
// src/telephony/twilio.ts
|
|
21981
22166
|
import { Buffer as Buffer4 } from "buffer";
|
|
21982
|
-
import { Elysia as
|
|
22167
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
21983
22168
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
21984
22169
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
21985
22170
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -22009,7 +22194,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
22009
22194
|
return parameters;
|
|
22010
22195
|
};
|
|
22011
22196
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22012
|
-
var
|
|
22197
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22013
22198
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
22014
22199
|
if (!webhook?.verificationUrl) {
|
|
22015
22200
|
return;
|
|
@@ -22052,23 +22237,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
22052
22237
|
};
|
|
22053
22238
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22054
22239
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
22055
|
-
<h1>${
|
|
22240
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22056
22241
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22057
22242
|
<section>
|
|
22058
22243
|
<h2>URLs</h2>
|
|
22059
22244
|
<ul>
|
|
22060
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22061
|
-
<li><strong>Media stream:</strong> <code>${
|
|
22062
|
-
<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>
|
|
22063
22248
|
</ul>
|
|
22064
22249
|
</section>
|
|
22065
22250
|
<section>
|
|
22066
22251
|
<h2>Signing</h2>
|
|
22067
22252
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
22068
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
22253
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml39(status.signing.verificationUrl)}</code></p>` : ""}
|
|
22069
22254
|
</section>
|
|
22070
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
22071
|
-
${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>` : ""}
|
|
22072
22257
|
</main>`;
|
|
22073
22258
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
22074
22259
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -22079,20 +22264,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
22079
22264
|
});
|
|
22080
22265
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22081
22266
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
22082
|
-
<h1>${
|
|
22267
|
+
<h1>${escapeHtml39(title)}</h1>
|
|
22083
22268
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22084
22269
|
<section>
|
|
22085
22270
|
<h2>Checks</h2>
|
|
22086
22271
|
<ul>
|
|
22087
|
-
${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("")}
|
|
22088
22273
|
</ul>
|
|
22089
22274
|
</section>
|
|
22090
22275
|
<section>
|
|
22091
22276
|
<h2>Observed URLs</h2>
|
|
22092
22277
|
<ul>
|
|
22093
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22094
|
-
<li><strong>Stream:</strong> <code>${
|
|
22095
|
-
<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>
|
|
22096
22281
|
</ul>
|
|
22097
22282
|
</section>
|
|
22098
22283
|
</main>`;
|
|
@@ -22638,7 +22823,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
22638
22823
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
22639
22824
|
const bridges = new WeakMap;
|
|
22640
22825
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
22641
|
-
const app = new
|
|
22826
|
+
const app = new Elysia39({
|
|
22642
22827
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
22643
22828
|
}).get(twimlPath, async ({ query, request }) => {
|
|
22644
22829
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -22775,7 +22960,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
22775
22960
|
|
|
22776
22961
|
// src/telephony/plivo.ts
|
|
22777
22962
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22778
|
-
var
|
|
22963
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22779
22964
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22780
22965
|
var resolveRequestOrigin2 = (request) => {
|
|
22781
22966
|
const url = new URL(request.url);
|
|
@@ -23206,21 +23391,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
23206
23391
|
};
|
|
23207
23392
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23208
23393
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
23209
|
-
<h1>${
|
|
23394
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23210
23395
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23211
23396
|
<ul>
|
|
23212
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
23213
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
23214
|
-
<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>
|
|
23215
23400
|
</ul>
|
|
23216
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23217
|
-
${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>` : ""}
|
|
23218
23403
|
</main>`;
|
|
23219
23404
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23220
23405
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
23221
|
-
<h1>${
|
|
23406
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
23222
23407
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23223
|
-
<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>
|
|
23224
23409
|
</main>`;
|
|
23225
23410
|
var runPlivoSmokeTest = async (input) => {
|
|
23226
23411
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -23310,7 +23495,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
23310
23495
|
nonceStore: options.webhook.nonceStore,
|
|
23311
23496
|
verificationUrl: options.webhook.verificationUrl
|
|
23312
23497
|
}) : undefined);
|
|
23313
|
-
const app = new
|
|
23498
|
+
const app = new Elysia40({
|
|
23314
23499
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
23315
23500
|
}).get(answerPath, async ({ query, request }) => {
|
|
23316
23501
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -23422,9 +23607,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
23422
23607
|
// src/telephony/telnyx.ts
|
|
23423
23608
|
import { Buffer as Buffer6 } from "buffer";
|
|
23424
23609
|
import { Database as Database2 } from "bun:sqlite";
|
|
23425
|
-
import { Elysia as
|
|
23610
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
23426
23611
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23427
|
-
var
|
|
23612
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23428
23613
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
23429
23614
|
var resolveRequestOrigin3 = (request) => {
|
|
23430
23615
|
const url = new URL(request.url);
|
|
@@ -23818,21 +24003,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
23818
24003
|
};
|
|
23819
24004
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23820
24005
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
23821
|
-
<h1>${
|
|
24006
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23822
24007
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23823
24008
|
<ul>
|
|
23824
|
-
<li><strong>TeXML:</strong> <code>${
|
|
23825
|
-
<li><strong>Media stream:</strong> <code>${
|
|
23826
|
-
<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>
|
|
23827
24012
|
</ul>
|
|
23828
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23829
|
-
${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>` : ""}
|
|
23830
24015
|
</main>`;
|
|
23831
24016
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23832
24017
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
23833
|
-
<h1>${
|
|
24018
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23834
24019
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23835
|
-
<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>
|
|
23836
24021
|
</main>`;
|
|
23837
24022
|
var runTelnyxSmokeTest = async (input) => {
|
|
23838
24023
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -23925,7 +24110,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
23925
24110
|
publicKey: options.webhook.publicKey,
|
|
23926
24111
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
23927
24112
|
}) : undefined);
|
|
23928
|
-
const app = new
|
|
24113
|
+
const app = new Elysia41({
|
|
23929
24114
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
23930
24115
|
}).get(texmlPath, async ({ query, request }) => {
|
|
23931
24116
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -24035,8 +24220,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
24035
24220
|
};
|
|
24036
24221
|
|
|
24037
24222
|
// src/telephony/matrix.ts
|
|
24038
|
-
import { Elysia as
|
|
24039
|
-
var
|
|
24223
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24224
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24040
24225
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
24041
24226
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
24042
24227
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -24097,13 +24282,13 @@ var badgeStyles = {
|
|
|
24097
24282
|
};
|
|
24098
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;">
|
|
24099
24284
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
24100
|
-
<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>
|
|
24101
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>
|
|
24102
24287
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
24103
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);">
|
|
24104
24289
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
24105
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
24106
|
-
<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>
|
|
24107
24292
|
</div>
|
|
24108
24293
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
24109
24294
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -24111,15 +24296,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
24111
24296
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
24112
24297
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
24113
24298
|
</dl>
|
|
24114
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
24115
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
24116
|
-
${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>'}
|
|
24117
24302
|
</article>`).join("")}
|
|
24118
24303
|
</section>
|
|
24119
24304
|
</main>`;
|
|
24120
24305
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
24121
24306
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
24122
|
-
return new
|
|
24307
|
+
return new Elysia42({
|
|
24123
24308
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
24124
24309
|
}).get(path, async ({ query, request }) => {
|
|
24125
24310
|
const providers = await options.load({ query, request });
|
|
@@ -24141,7 +24326,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
24141
24326
|
};
|
|
24142
24327
|
|
|
24143
24328
|
// src/phoneAgentProductionSmoke.ts
|
|
24144
|
-
import { Elysia as
|
|
24329
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24145
24330
|
var defaultRequirements = [
|
|
24146
24331
|
"media-started",
|
|
24147
24332
|
"transcript",
|
|
@@ -24149,7 +24334,7 @@ var defaultRequirements = [
|
|
|
24149
24334
|
"lifecycle-outcome",
|
|
24150
24335
|
"no-session-error"
|
|
24151
24336
|
];
|
|
24152
|
-
var
|
|
24337
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24153
24338
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
24154
24339
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
24155
24340
|
const value = event.payload[key];
|
|
@@ -24258,10 +24443,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
24258
24443
|
});
|
|
24259
24444
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
24260
24445
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
24261
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
24262
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
24263
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
24264
|
-
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>`;
|
|
24265
24450
|
};
|
|
24266
24451
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
24267
24452
|
query,
|
|
@@ -24284,7 +24469,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
24284
24469
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
24285
24470
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
24286
24471
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
24287
|
-
const routes = new
|
|
24472
|
+
const routes = new Elysia43({
|
|
24288
24473
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
24289
24474
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
24290
24475
|
if (htmlPath) {
|
|
@@ -24327,7 +24512,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
24327
24512
|
"completed",
|
|
24328
24513
|
"failed"
|
|
24329
24514
|
];
|
|
24330
|
-
var
|
|
24515
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24331
24516
|
var loadRouteJson = async (input) => {
|
|
24332
24517
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
24333
24518
|
headers: {
|
|
@@ -24565,10 +24750,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
24565
24750
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
24566
24751
|
const urls = entry?.setup.urls;
|
|
24567
24752
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
24568
|
-
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>`;
|
|
24569
24754
|
}).join("");
|
|
24570
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
24571
|
-
const snippet =
|
|
24755
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml44(stage)}</code></li>`).join("");
|
|
24756
|
+
const snippet = escapeHtml44(`const phoneAgent = createVoicePhoneAgent({
|
|
24572
24757
|
carriers: [
|
|
24573
24758
|
{
|
|
24574
24759
|
provider: 'twilio',
|
|
@@ -24602,11 +24787,11 @@ app.use(
|
|
|
24602
24787
|
);`);
|
|
24603
24788
|
const checklist = report.carriers.map((carrier) => {
|
|
24604
24789
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
24605
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
24606
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
24607
|
-
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>`;
|
|
24608
24793
|
}).join("");
|
|
24609
|
-
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>`;
|
|
24610
24795
|
};
|
|
24611
24796
|
var createVoicePhoneAgent = (options) => {
|
|
24612
24797
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -24615,7 +24800,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
24615
24800
|
setupPath: resolveSetupPath(carrier),
|
|
24616
24801
|
smokePath: resolveSmokePath(carrier)
|
|
24617
24802
|
}));
|
|
24618
|
-
const app = new
|
|
24803
|
+
const app = new Elysia44({
|
|
24619
24804
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
24620
24805
|
});
|
|
24621
24806
|
for (const carrier of options.carriers) {
|
|
@@ -26245,8 +26430,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
26245
26430
|
};
|
|
26246
26431
|
};
|
|
26247
26432
|
// src/providerCapabilities.ts
|
|
26248
|
-
import { Elysia as
|
|
26249
|
-
var
|
|
26433
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
26434
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26250
26435
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
26251
26436
|
configured: true,
|
|
26252
26437
|
features: options.features?.[provider],
|
|
@@ -26309,27 +26494,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
26309
26494
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
26310
26495
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
26311
26496
|
const cards = report.capabilities.map((capability) => {
|
|
26312
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
26313
|
-
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)}">
|
|
26314
26499
|
<div class="card-header">
|
|
26315
26500
|
<div>
|
|
26316
|
-
<p class="eyebrow">${
|
|
26317
|
-
<h2>${
|
|
26501
|
+
<p class="eyebrow">${escapeHtml45(capability.kind)}</p>
|
|
26502
|
+
<h2>${escapeHtml45(capability.label ?? capability.provider)}</h2>
|
|
26318
26503
|
</div>
|
|
26319
|
-
<strong>${
|
|
26504
|
+
<strong>${escapeHtml45(capability.status)}</strong>
|
|
26320
26505
|
</div>
|
|
26321
|
-
${capability.description ? `<p>${
|
|
26506
|
+
${capability.description ? `<p>${escapeHtml45(capability.description)}</p>` : ""}
|
|
26322
26507
|
<dl>
|
|
26323
26508
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
26324
26509
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
26325
|
-
<div><dt>Model</dt><dd>${
|
|
26510
|
+
<div><dt>Model</dt><dd>${escapeHtml45(capability.model ?? "default")}</dd></div>
|
|
26326
26511
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
26327
26512
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
26328
26513
|
</dl>
|
|
26329
26514
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
26330
26515
|
</article>`;
|
|
26331
26516
|
}).join("");
|
|
26332
|
-
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>`;
|
|
26333
26518
|
};
|
|
26334
26519
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
26335
26520
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -26346,7 +26531,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
26346
26531
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
26347
26532
|
const path = options.path ?? "/api/provider-capabilities";
|
|
26348
26533
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
26349
|
-
const routes = new
|
|
26534
|
+
const routes = new Elysia45({
|
|
26350
26535
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
26351
26536
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
26352
26537
|
if (htmlPath) {
|
|
@@ -26355,7 +26540,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
26355
26540
|
return routes;
|
|
26356
26541
|
};
|
|
26357
26542
|
// src/providerOrchestration.ts
|
|
26358
|
-
import { Elysia as
|
|
26543
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
26359
26544
|
var defaultRequirement = {
|
|
26360
26545
|
minProviders: 1,
|
|
26361
26546
|
requireBudgetPolicy: false,
|
|
@@ -26368,7 +26553,7 @@ var statusRank4 = {
|
|
|
26368
26553
|
warn: 1,
|
|
26369
26554
|
fail: 2
|
|
26370
26555
|
};
|
|
26371
|
-
var
|
|
26556
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26372
26557
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
26373
26558
|
var uniqueSorted6 = (values) => [
|
|
26374
26559
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -26511,27 +26696,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
26511
26696
|
};
|
|
26512
26697
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
26513
26698
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
26514
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
26515
|
-
<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>
|
|
26516
26701
|
<dl>
|
|
26517
|
-
<div><dt>Providers</dt><dd>${
|
|
26518
|
-
<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>
|
|
26519
26704
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
26520
26705
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
26521
26706
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
26522
26707
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
26523
26708
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
26524
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
26709
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml46(surface.fallbackMode || "default")}</dd></div>
|
|
26525
26710
|
</dl>
|
|
26526
|
-
${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>"}
|
|
26527
26712
|
</article>`).join("");
|
|
26528
|
-
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>`;
|
|
26529
26714
|
};
|
|
26530
26715
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
26531
26716
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
26532
26717
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
26533
26718
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
26534
|
-
const routes = new
|
|
26719
|
+
const routes = new Elysia46({
|
|
26535
26720
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
26536
26721
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
26537
26722
|
if (htmlPath) {
|
|
@@ -26702,7 +26887,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
26702
26887
|
return report;
|
|
26703
26888
|
};
|
|
26704
26889
|
// src/providerSlo.ts
|
|
26705
|
-
import { Elysia as
|
|
26890
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
26706
26891
|
var defaultThresholds = {
|
|
26707
26892
|
llm: {
|
|
26708
26893
|
maxAverageElapsedMs: 2500,
|
|
@@ -26735,7 +26920,7 @@ var statusRank5 = {
|
|
|
26735
26920
|
warn: 1,
|
|
26736
26921
|
fail: 2
|
|
26737
26922
|
};
|
|
26738
|
-
var
|
|
26923
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26739
26924
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
26740
26925
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
26741
26926
|
var uniqueSorted7 = (values) => [
|
|
@@ -27031,11 +27216,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27031
27216
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
27032
27217
|
const kindCards = providerKinds.map((kind) => {
|
|
27033
27218
|
const kindReport = report.kinds[kind];
|
|
27034
|
-
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("");
|
|
27035
27220
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
27036
|
-
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>`;
|
|
27037
27222
|
}).join("");
|
|
27038
|
-
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>";
|
|
27039
27224
|
const snippet = `createVoiceProviderSloRoutes({
|
|
27040
27225
|
store: runtimeStorage.traces,
|
|
27041
27226
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -27045,7 +27230,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27045
27230
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
27046
27231
|
}
|
|
27047
27232
|
})`;
|
|
27048
|
-
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>`;
|
|
27049
27234
|
};
|
|
27050
27235
|
var createVoiceProviderSloRoutes = (options) => {
|
|
27051
27236
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -27056,7 +27241,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27056
27241
|
...options.headers ?? {}
|
|
27057
27242
|
};
|
|
27058
27243
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
27059
|
-
const app = new
|
|
27244
|
+
const app = new Elysia47({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
27060
27245
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
27061
27246
|
if (markdownPath !== false) {
|
|
27062
27247
|
app.get(markdownPath, async () => {
|
|
@@ -27086,10 +27271,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27086
27271
|
return app;
|
|
27087
27272
|
};
|
|
27088
27273
|
// src/productionReadiness.ts
|
|
27089
|
-
import { Elysia as
|
|
27274
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
27090
27275
|
|
|
27091
27276
|
// src/telephony/security.ts
|
|
27092
|
-
import { Elysia as
|
|
27277
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
27093
27278
|
|
|
27094
27279
|
// src/postgresStore.ts
|
|
27095
27280
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -27827,7 +28012,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
27827
28012
|
};
|
|
27828
28013
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
27829
28014
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
27830
|
-
return new
|
|
28015
|
+
return new Elysia48({
|
|
27831
28016
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
27832
28017
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
27833
28018
|
};
|
|
@@ -27884,8 +28069,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
27884
28069
|
};
|
|
27885
28070
|
|
|
27886
28071
|
// src/opsRecovery.ts
|
|
27887
|
-
import { Elysia as
|
|
27888
|
-
var
|
|
28072
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
28073
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27889
28074
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
27890
28075
|
var hrefForSession = (value, sessionId) => {
|
|
27891
28076
|
if (typeof value === "function") {
|
|
@@ -28099,19 +28284,19 @@ ${failedSessions || "None."}
|
|
|
28099
28284
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
28100
28285
|
`;
|
|
28101
28286
|
};
|
|
28102
|
-
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>`;
|
|
28103
28288
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
28104
28289
|
const title = options.title ?? "Voice Ops Recovery";
|
|
28105
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
28106
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
28107
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
28108
|
-
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>`;
|
|
28109
28294
|
};
|
|
28110
28295
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
28111
28296
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
28112
28297
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
28113
28298
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
28114
|
-
const routes = new
|
|
28299
|
+
const routes = new Elysia49({
|
|
28115
28300
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
28116
28301
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
28117
28302
|
if (htmlPath) {
|
|
@@ -28141,18 +28326,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
28141
28326
|
};
|
|
28142
28327
|
|
|
28143
28328
|
// src/observabilityExport.ts
|
|
28144
|
-
import { Elysia as
|
|
28329
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
28145
28330
|
import { Database as Database4 } from "bun:sqlite";
|
|
28146
28331
|
import { createHash } from "crypto";
|
|
28147
28332
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
28148
28333
|
import { join as join3 } from "path";
|
|
28149
28334
|
|
|
28150
28335
|
// src/operationsRecord.ts
|
|
28151
|
-
import { Elysia as
|
|
28336
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
28152
28337
|
|
|
28153
28338
|
// src/traceTimeline.ts
|
|
28154
|
-
import { Elysia as
|
|
28155
|
-
var
|
|
28339
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
28340
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28156
28341
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
28157
28342
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
28158
28343
|
var firstString4 = (payload, keys) => {
|
|
@@ -28335,17 +28520,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
28335
28520
|
};
|
|
28336
28521
|
};
|
|
28337
28522
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
28338
|
-
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>`;
|
|
28339
28524
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
28340
|
-
const events = session.events.map((event) => `<tr class="${
|
|
28341
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
28342
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
28343
|
-
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>`;
|
|
28344
28529
|
};
|
|
28345
|
-
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("");
|
|
28346
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}}";
|
|
28347
28532
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
28348
|
-
const snippet =
|
|
28533
|
+
const snippet = escapeHtml49(`const traceStore = createVoiceTraceSinkStore({
|
|
28349
28534
|
store: runtimeStorage.traces,
|
|
28350
28535
|
sinks: [
|
|
28351
28536
|
createVoiceTraceHTTPSink({
|
|
@@ -28371,13 +28556,13 @@ app.use(
|
|
|
28371
28556
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
28372
28557
|
})
|
|
28373
28558
|
);`);
|
|
28374
|
-
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>`;
|
|
28375
28560
|
};
|
|
28376
28561
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
28377
28562
|
const path = options.path ?? "/api/voice-traces";
|
|
28378
28563
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
28379
28564
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
28380
|
-
const routes = new
|
|
28565
|
+
const routes = new Elysia50({
|
|
28381
28566
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
28382
28567
|
});
|
|
28383
28568
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -29007,7 +29192,7 @@ var renderVoiceFailureReplayMarkdown = (report) => {
|
|
|
29007
29192
|
].join(`
|
|
29008
29193
|
`);
|
|
29009
29194
|
};
|
|
29010
|
-
var
|
|
29195
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29011
29196
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
29012
29197
|
var outcomeLabels = (outcome) => [
|
|
29013
29198
|
outcome.complete ? "complete" : undefined,
|
|
@@ -29117,18 +29302,18 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
29117
29302
|
`);
|
|
29118
29303
|
};
|
|
29119
29304
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
29120
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
29121
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
29122
|
-
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>";
|
|
29123
29308
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
29124
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
29125
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
29126
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
29127
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
29128
|
-
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>";
|
|
29129
29314
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
29130
29315
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
29131
|
-
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>`;
|
|
29132
29317
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
29133
29318
|
const telephonyMedia = record.telephonyMedia.events.length ? record.telephonyMedia.events.slice(0, 50).map((event) => {
|
|
29134
29319
|
const details = [
|
|
@@ -29139,9 +29324,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29139
29324
|
event.sequenceNumber ? `Seq: ${event.sequenceNumber}` : undefined,
|
|
29140
29325
|
`Audio bytes: ${String(event.audioBytes)}`
|
|
29141
29326
|
].filter((detail) => typeof detail === "string");
|
|
29142
|
-
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>`;
|
|
29143
29328
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
29144
|
-
const snippet =
|
|
29329
|
+
const snippet = escapeHtml50(`app.use(
|
|
29145
29330
|
createVoiceOperationsRecordRoutes({
|
|
29146
29331
|
audit: auditStore,
|
|
29147
29332
|
integrationEvents: opsEvents,
|
|
@@ -29155,16 +29340,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29155
29340
|
tasks: opsTasks
|
|
29156
29341
|
})
|
|
29157
29342
|
);`);
|
|
29158
|
-
const incidentMarkdown =
|
|
29159
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
29160
|
-
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>`;
|
|
29161
29346
|
};
|
|
29162
29347
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
29163
29348
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
29164
29349
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
29165
29350
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
29166
29351
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
29167
|
-
const routes = new
|
|
29352
|
+
const routes = new Elysia51({
|
|
29168
29353
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
29169
29354
|
});
|
|
29170
29355
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -29815,7 +30000,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
29815
30000
|
...options.headers ?? {}
|
|
29816
30001
|
};
|
|
29817
30002
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
29818
|
-
const app = new
|
|
30003
|
+
const app = new Elysia52({
|
|
29819
30004
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
29820
30005
|
});
|
|
29821
30006
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -30624,7 +30809,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
30624
30809
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
30625
30810
|
}
|
|
30626
30811
|
});
|
|
30627
|
-
const app = new
|
|
30812
|
+
const app = new Elysia52({
|
|
30628
30813
|
name: options.name ?? "absolute-voice-observability-export"
|
|
30629
30814
|
});
|
|
30630
30815
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -30701,7 +30886,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
30701
30886
|
};
|
|
30702
30887
|
|
|
30703
30888
|
// src/productionReadiness.ts
|
|
30704
|
-
var
|
|
30889
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30705
30890
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
30706
30891
|
var readinessGateCodes = {
|
|
30707
30892
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -32339,25 +32524,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
32339
32524
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
32340
32525
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
32341
32526
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
32342
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
32343
|
-
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>` : "";
|
|
32344
32529
|
const checks = report.checks.map((check, index) => {
|
|
32345
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
32346
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
32347
|
-
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)}">
|
|
32348
32533
|
<div>
|
|
32349
|
-
<span>${
|
|
32350
|
-
<h2>${
|
|
32351
|
-
${check.detail ? `<p>${
|
|
32534
|
+
<span>${escapeHtml51(check.status.toUpperCase())}</span>
|
|
32535
|
+
<h2>${escapeHtml51(check.label)}</h2>
|
|
32536
|
+
${check.detail ? `<p>${escapeHtml51(check.detail)}</p>` : ""}
|
|
32352
32537
|
${explanation}
|
|
32353
|
-
${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>` : ""}
|
|
32354
32539
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
32355
32540
|
</div>
|
|
32356
|
-
<strong>${
|
|
32357
|
-
${check.href ? `<a href="${
|
|
32541
|
+
<strong>${escapeHtml51(String(check.value ?? check.status))}</strong>
|
|
32542
|
+
${check.href ? `<a href="${escapeHtml51(check.href)}">Open surface</a>` : ""}
|
|
32358
32543
|
</article>`;
|
|
32359
32544
|
}).join("");
|
|
32360
|
-
const snippet =
|
|
32545
|
+
const snippet = escapeHtml51(`createVoiceProductionReadinessRoutes({
|
|
32361
32546
|
htmlPath: '/production-readiness',
|
|
32362
32547
|
path: '/api/production-readiness',
|
|
32363
32548
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -32373,13 +32558,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
32373
32558
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
32374
32559
|
store: traceStore
|
|
32375
32560
|
});`);
|
|
32376
|
-
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>`;
|
|
32377
32562
|
};
|
|
32378
32563
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
32379
32564
|
const path = options.path ?? "/api/production-readiness";
|
|
32380
32565
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
32381
32566
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
32382
|
-
const routes = new
|
|
32567
|
+
const routes = new Elysia53({
|
|
32383
32568
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
32384
32569
|
});
|
|
32385
32570
|
const resolveOptions = async (input) => {
|
|
@@ -32427,8 +32612,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
32427
32612
|
return routes;
|
|
32428
32613
|
};
|
|
32429
32614
|
// src/voiceMonitoring.ts
|
|
32430
|
-
import { Elysia as
|
|
32431
|
-
var
|
|
32615
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
32616
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32432
32617
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
32433
32618
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
32434
32619
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -32681,14 +32866,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
32681
32866
|
};
|
|
32682
32867
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
32683
32868
|
const title = options.title ?? "Voice Monitors";
|
|
32684
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
32685
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
32686
|
-
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({
|
|
32687
32872
|
evidence,
|
|
32688
32873
|
issueStore,
|
|
32689
32874
|
monitors: [defineVoiceMonitor(...)]
|
|
32690
32875
|
}));`);
|
|
32691
|
-
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>`;
|
|
32692
32877
|
};
|
|
32693
32878
|
var actorFromRequest = async (request) => {
|
|
32694
32879
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -32712,7 +32897,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
32712
32897
|
monitors: options.monitors,
|
|
32713
32898
|
now: options.now
|
|
32714
32899
|
});
|
|
32715
|
-
const routes = new
|
|
32900
|
+
const routes = new Elysia54({
|
|
32716
32901
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
32717
32902
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
32718
32903
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -32759,7 +32944,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
32759
32944
|
};
|
|
32760
32945
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
32761
32946
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
32762
|
-
return new
|
|
32947
|
+
return new Elysia54({
|
|
32763
32948
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
32764
32949
|
}).get(path, () => ({
|
|
32765
32950
|
isRunning: options.runner.isRunning()
|
|
@@ -33135,8 +33320,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
33135
33320
|
};
|
|
33136
33321
|
};
|
|
33137
33322
|
// src/providerStackRecommendations.ts
|
|
33138
|
-
import { Elysia as
|
|
33139
|
-
var
|
|
33323
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
33324
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33140
33325
|
var profileProviderPriorities = {
|
|
33141
33326
|
"meeting-recorder": {
|
|
33142
33327
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -33455,17 +33640,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
33455
33640
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
33456
33641
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
33457
33642
|
const rows = report.rows.map((row) => {
|
|
33458
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
33459
|
-
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)}">
|
|
33460
33645
|
<div>
|
|
33461
|
-
<p class="eyebrow">${
|
|
33462
|
-
<h2>${
|
|
33463
|
-
<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>
|
|
33464
33649
|
</div>
|
|
33465
33650
|
<ul>${checks}</ul>
|
|
33466
33651
|
</article>`;
|
|
33467
33652
|
}).join("");
|
|
33468
|
-
const snippet =
|
|
33653
|
+
const snippet = escapeHtml53(`const providerContracts = () =>
|
|
33469
33654
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
33470
33655
|
env: process.env,
|
|
33471
33656
|
providers: {
|
|
@@ -33486,7 +33671,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
33486
33671
|
providerContractMatrix: () =>
|
|
33487
33672
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
33488
33673
|
});`);
|
|
33489
|
-
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>`;
|
|
33490
33675
|
};
|
|
33491
33676
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
33492
33677
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -33501,7 +33686,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
33501
33686
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
33502
33687
|
const path = options.path ?? "/api/provider-contracts";
|
|
33503
33688
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
33504
|
-
const routes = new
|
|
33689
|
+
const routes = new Elysia55({
|
|
33505
33690
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
33506
33691
|
});
|
|
33507
33692
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -33619,7 +33804,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
33619
33804
|
return assertion;
|
|
33620
33805
|
};
|
|
33621
33806
|
// src/opsConsoleRoutes.ts
|
|
33622
|
-
import { Elysia as
|
|
33807
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
33623
33808
|
var DEFAULT_LINKS = [
|
|
33624
33809
|
{
|
|
33625
33810
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -33654,7 +33839,7 @@ var DEFAULT_LINKS = [
|
|
|
33654
33839
|
label: "Handoffs"
|
|
33655
33840
|
}
|
|
33656
33841
|
];
|
|
33657
|
-
var
|
|
33842
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33658
33843
|
var countProviderStatuses = (providers) => {
|
|
33659
33844
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
33660
33845
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -33723,20 +33908,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
33723
33908
|
trace
|
|
33724
33909
|
};
|
|
33725
33910
|
};
|
|
33726
|
-
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>`;
|
|
33727
33912
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
33728
33913
|
const links = report.links.map((link) => `<article class="surface">
|
|
33729
|
-
<div><h2>${
|
|
33730
|
-
<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>
|
|
33731
33916
|
</article>`).join("");
|
|
33732
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
33733
|
-
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>';
|
|
33734
33919
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
33735
|
-
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>`;
|
|
33736
33921
|
};
|
|
33737
33922
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
33738
33923
|
const path = options.path ?? "/ops-console";
|
|
33739
|
-
const routes = new
|
|
33924
|
+
const routes = new Elysia56({
|
|
33740
33925
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
33741
33926
|
});
|
|
33742
33927
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -33753,7 +33938,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
33753
33938
|
return routes;
|
|
33754
33939
|
};
|
|
33755
33940
|
// src/incidentBundle.ts
|
|
33756
|
-
import { Elysia as
|
|
33941
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
33757
33942
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
33758
33943
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
33759
33944
|
return false;
|
|
@@ -33954,7 +34139,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
33954
34139
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
33955
34140
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
33956
34141
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
33957
|
-
const routes = new
|
|
34142
|
+
const routes = new Elysia57({
|
|
33958
34143
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
33959
34144
|
});
|
|
33960
34145
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -34155,19 +34340,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
34155
34340
|
};
|
|
34156
34341
|
};
|
|
34157
34342
|
// src/opsStatusRoutes.ts
|
|
34158
|
-
import { Elysia as
|
|
34159
|
-
var
|
|
34343
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
34344
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34160
34345
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
34161
34346
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
34162
34347
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
34163
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;
|
|
34164
|
-
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>`;
|
|
34165
34350
|
}).join("");
|
|
34166
|
-
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>`;
|
|
34167
34352
|
};
|
|
34168
34353
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
34169
34354
|
const path = options.path ?? "/api/voice/ops-status";
|
|
34170
|
-
const routes = new
|
|
34355
|
+
const routes = new Elysia58({
|
|
34171
34356
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
34172
34357
|
});
|
|
34173
34358
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -34600,8 +34785,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
34600
34785
|
};
|
|
34601
34786
|
};
|
|
34602
34787
|
// src/traceDeliveryRoutes.ts
|
|
34603
|
-
import { Elysia as
|
|
34604
|
-
var
|
|
34788
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
34789
|
+
var escapeHtml56 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34605
34790
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
34606
34791
|
var getNumber12 = (value) => {
|
|
34607
34792
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -34682,14 +34867,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
34682
34867
|
if (entries.length === 0) {
|
|
34683
34868
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
34684
34869
|
}
|
|
34685
|
-
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>`;
|
|
34686
34871
|
};
|
|
34687
|
-
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>`;
|
|
34688
34873
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
34689
34874
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
34690
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
34691
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
34692
|
-
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>`;
|
|
34693
34878
|
};
|
|
34694
34879
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
34695
34880
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -34709,7 +34894,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
34709
34894
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
34710
34895
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
34711
34896
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
34712
|
-
const routes = new
|
|
34897
|
+
const routes = new Elysia59({
|
|
34713
34898
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
34714
34899
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
34715
34900
|
if (htmlPath !== false) {
|
|
@@ -34806,7 +34991,7 @@ var createVoiceMemoryStore = () => {
|
|
|
34806
34991
|
return { get, getOrCreate, list, remove, set };
|
|
34807
34992
|
};
|
|
34808
34993
|
// src/opsWebhook.ts
|
|
34809
|
-
import { Elysia as
|
|
34994
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
34810
34995
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
34811
34996
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
34812
34997
|
const encoder = new TextEncoder;
|
|
@@ -34936,7 +35121,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
34936
35121
|
};
|
|
34937
35122
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
34938
35123
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
34939
|
-
return new
|
|
35124
|
+
return new Elysia60().post(path, async ({ body, request, set }) => {
|
|
34940
35125
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
34941
35126
|
if (options.signingSecret) {
|
|
34942
35127
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -35391,7 +35576,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
35391
35576
|
};
|
|
35392
35577
|
};
|
|
35393
35578
|
// src/postCallAnalysis.ts
|
|
35394
|
-
import { Elysia as
|
|
35579
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
35395
35580
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
35396
35581
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
35397
35582
|
var getPathValue3 = (source, path) => {
|
|
@@ -35570,7 +35755,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
35570
35755
|
};
|
|
35571
35756
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
35572
35757
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
35573
|
-
const routes = new
|
|
35758
|
+
const routes = new Elysia61({
|
|
35574
35759
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
35575
35760
|
});
|
|
35576
35761
|
routes.get(path, async ({ query }) => {
|
|
@@ -35595,7 +35780,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
35595
35780
|
return routes;
|
|
35596
35781
|
};
|
|
35597
35782
|
// src/guardrails.ts
|
|
35598
|
-
import { Elysia as
|
|
35783
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
35599
35784
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
35600
35785
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
35601
35786
|
var matchesRule = async (rule, input) => {
|
|
@@ -35897,7 +36082,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
35897
36082
|
};
|
|
35898
36083
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
35899
36084
|
const path = options.path ?? "/api/voice/guardrails";
|
|
35900
|
-
const routes = new
|
|
36085
|
+
const routes = new Elysia62({
|
|
35901
36086
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
35902
36087
|
});
|
|
35903
36088
|
routes.all(path, async ({ request }) => {
|
|
@@ -36840,6 +37025,8 @@ export {
|
|
|
36840
37025
|
renderVoiceCallReviewMarkdown,
|
|
36841
37026
|
renderVoiceCallReviewHTML,
|
|
36842
37027
|
renderVoiceBrowserMediaHTML,
|
|
37028
|
+
renderVoiceBrowserCallProfileMarkdown,
|
|
37029
|
+
renderVoiceBrowserCallProfileHTML,
|
|
36843
37030
|
renderVoiceBargeInHTML,
|
|
36844
37031
|
renderVoiceAuditTrailHTML,
|
|
36845
37032
|
renderVoiceAuditMarkdown,
|
|
@@ -36921,6 +37108,7 @@ export {
|
|
|
36921
37108
|
evaluateVoiceCompetitiveCoverage,
|
|
36922
37109
|
evaluateVoiceCampaignReadinessEvidence,
|
|
36923
37110
|
evaluateVoiceCampaignDialerProofEvidence,
|
|
37111
|
+
evaluateVoiceBrowserCallProfileEvidence,
|
|
36924
37112
|
evaluateVoiceAgentSquadContractEvidence,
|
|
36925
37113
|
encodeTwilioMulawBase64,
|
|
36926
37114
|
deliverVoiceTraceEventsToSinks,
|
|
@@ -37177,6 +37365,7 @@ export {
|
|
|
37177
37365
|
createVoiceCallCompletedEvent,
|
|
37178
37366
|
createVoiceCRMActivitySink,
|
|
37179
37367
|
createVoiceBrowserMediaRoutes,
|
|
37368
|
+
createVoiceBrowserCallProfileRoutes,
|
|
37180
37369
|
createVoiceBargeInRoutes,
|
|
37181
37370
|
createVoiceAuditTrailRoutes,
|
|
37182
37371
|
createVoiceAuditSinkStore,
|
|
@@ -37278,6 +37467,7 @@ export {
|
|
|
37278
37467
|
buildVoiceDataControlReport,
|
|
37279
37468
|
buildVoiceCompetitiveCoverageReport,
|
|
37280
37469
|
buildVoiceCampaignObservabilityReport,
|
|
37470
|
+
buildVoiceBrowserCallProfileReport,
|
|
37281
37471
|
buildVoiceAuditTrailReport,
|
|
37282
37472
|
buildVoiceAuditExport,
|
|
37283
37473
|
buildVoiceAuditDeliveryReport,
|
|
@@ -37315,6 +37505,7 @@ export {
|
|
|
37315
37505
|
assertVoiceCompetitiveCoverage,
|
|
37316
37506
|
assertVoiceCampaignReadinessEvidence,
|
|
37317
37507
|
assertVoiceCampaignDialerProofEvidence,
|
|
37508
|
+
assertVoiceBrowserCallProfileEvidence,
|
|
37318
37509
|
assertVoiceAgentSquadContractEvidence,
|
|
37319
37510
|
assertVoiceAgentSquadContract,
|
|
37320
37511
|
applyVoiceTelephonyOutcome,
|