@absolutejs/voice 0.0.22-beta.194 → 0.0.22-beta.196

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12712,6 +12712,20 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
12712
12712
  return routes;
12713
12713
  };
12714
12714
  // src/dataControl.ts
12715
+ import { Elysia as Elysia15 } from "elysia";
12716
+ var voiceComplianceRedactionDefaults = {
12717
+ keys: [
12718
+ "apiKey",
12719
+ "authorization",
12720
+ "email",
12721
+ "password",
12722
+ "phone",
12723
+ "secret",
12724
+ "token"
12725
+ ],
12726
+ redactEmails: true,
12727
+ redactPhoneNumbers: true
12728
+ };
12715
12729
  var allRetentionScopes = [
12716
12730
  "auditDeliveries",
12717
12731
  "campaigns",
@@ -12925,17 +12939,269 @@ var applyVoiceDataRetentionPolicy = async (options) => {
12925
12939
  return report;
12926
12940
  };
12927
12941
  var buildVoiceDataRetentionPlan = (options) => applyVoiceDataRetentionPolicy({ ...options, dryRun: true });
12942
+ var getBooleanQuery = (value) => value === true || value === "true" || value === "1";
12943
+ var getNumberQuery = (value) => {
12944
+ const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : undefined;
12945
+ return typeof parsed === "number" && Number.isFinite(parsed) ? parsed : undefined;
12946
+ };
12947
+ var parseRetentionScopes = (value) => {
12948
+ if (typeof value !== "string" || !value.trim()) {
12949
+ return;
12950
+ }
12951
+ const allowed = new Set(allRetentionScopes);
12952
+ return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
12953
+ };
12954
+ var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
12955
+ var buildStorageSurfaces = (options) => [
12956
+ {
12957
+ configured: Boolean(options.session ?? options.sessions),
12958
+ control: "session",
12959
+ name: "Sessions",
12960
+ selfHosted: true
12961
+ },
12962
+ {
12963
+ configured: Boolean(options.traces),
12964
+ control: "audit",
12965
+ name: "Trace events",
12966
+ selfHosted: true
12967
+ },
12968
+ {
12969
+ configured: Boolean(options.audit),
12970
+ control: "audit",
12971
+ name: "Audit events",
12972
+ selfHosted: true
12973
+ },
12974
+ {
12975
+ configured: Boolean(options.reviews),
12976
+ control: "artifact",
12977
+ name: "Call reviews",
12978
+ selfHosted: true
12979
+ },
12980
+ {
12981
+ configured: Boolean(options.tasks),
12982
+ control: "workflow",
12983
+ name: "Ops tasks",
12984
+ selfHosted: true
12985
+ },
12986
+ {
12987
+ configured: Boolean(options.events),
12988
+ control: "workflow",
12989
+ name: "Integration events",
12990
+ selfHosted: true
12991
+ },
12992
+ {
12993
+ configured: Boolean(options.campaigns),
12994
+ control: "workflow",
12995
+ name: "Campaign records",
12996
+ selfHosted: true
12997
+ },
12998
+ {
12999
+ configured: Boolean(options.auditDeliveries ?? options.traceDeliveries),
13000
+ control: "queue",
13001
+ name: "Audit/trace delivery queues",
13002
+ selfHosted: true
13003
+ },
13004
+ {
13005
+ configured: Boolean(options.incidentBundles),
13006
+ control: "artifact",
13007
+ name: "Incident bundles",
13008
+ selfHosted: true
13009
+ }
13010
+ ];
13011
+ var defaultProviderKeys = [
13012
+ {
13013
+ env: "OPENAI_API_KEY",
13014
+ name: "OpenAI",
13015
+ recommendation: "Keep provider keys server-side, scoped per environment, and never expose them to browser voice clients.",
13016
+ required: false
13017
+ },
13018
+ {
13019
+ env: "ANTHROPIC_API_KEY",
13020
+ name: "Anthropic",
13021
+ recommendation: "Use least-privilege project keys and route all requests through your AbsoluteJS server.",
13022
+ required: false
13023
+ },
13024
+ {
13025
+ env: "GEMINI_API_KEY",
13026
+ name: "Gemini",
13027
+ recommendation: "Use server-owned credentials and redact prompts/tool payloads before support export.",
13028
+ required: false
13029
+ },
13030
+ {
13031
+ env: "DEEPGRAM_API_KEY",
13032
+ name: "Deepgram",
13033
+ recommendation: "Keep STT credentials server-side and pair transcript exports with PII redaction.",
13034
+ required: false
13035
+ }
13036
+ ];
13037
+ var resolveDataControlRedaction = (redact) => redact === false ? undefined : redact === true || redact === undefined ? voiceComplianceRedactionDefaults : redact;
13038
+ var createVoiceZeroRetentionPolicy = (options) => ({
13039
+ ...options,
13040
+ beforeOrAt: options.beforeOrAt ?? Date.now(),
13041
+ dryRun: options.dryRun ?? true,
13042
+ scopes: options.scopes ?? allRetentionScopes
13043
+ });
13044
+ var buildVoiceDataControlReport = async (options) => {
13045
+ const redaction = resolveDataControlRedaction(options.redact);
13046
+ const retentionPlan = await buildVoiceDataRetentionPlan({
13047
+ ...options,
13048
+ ...options.retention ?? {},
13049
+ auditDeliveries: options.auditDeliveries,
13050
+ traceDeliveries: options.traceDeliveries
13051
+ });
13052
+ const auditExport = options.audit ? await exportVoiceAuditTrail({
13053
+ filter: options.auditFilter,
13054
+ redact: redaction,
13055
+ store: options.audit
13056
+ }) : undefined;
13057
+ return {
13058
+ auditExport,
13059
+ checkedAt: Date.now(),
13060
+ redaction: {
13061
+ defaults: voiceComplianceRedactionDefaults,
13062
+ enabled: Boolean(redaction)
13063
+ },
13064
+ retentionPlan,
13065
+ storage: buildStorageSurfaces(options),
13066
+ providerKeys: options.providerKeys ?? defaultProviderKeys,
13067
+ zeroRetentionAvailable: true
13068
+ };
13069
+ };
13070
+ var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml17(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml17(scope.skippedReason ?? "")}</td><td><code>${escapeHtml17(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
13071
+ var renderVoiceDataControlHTML = (report, options = {}) => {
13072
+ const title = options.title ?? "Voice Data Control";
13073
+ const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml17(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml17(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
13074
+ const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml17(key.name)}</td><td><code>${escapeHtml17(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml17(key.recommendation)}</td></tr>`).join("");
13075
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml17(title)}</title><style>body{background:#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>${escapeHtml17(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>`;
13076
+ };
13077
+ var renderVoiceDataControlMarkdown = (report, options = {}) => [
13078
+ `# ${options.title ?? "Voice Data Control"}`,
13079
+ "",
13080
+ `Checked: ${new Date(report.checkedAt).toISOString()}`,
13081
+ `Redaction: ${report.redaction.enabled ? "enabled" : "disabled"}`,
13082
+ `Retention dry-run deletes: ${report.retentionPlan.deletedCount}`,
13083
+ `Audit export events: ${report.auditExport?.events.length ?? 0}`,
13084
+ "",
13085
+ "## Customer-Owned Storage",
13086
+ "",
13087
+ ...report.storage.map((surface) => `- ${surface.name}: ${surface.configured ? "configured" : "missing"} (${surface.control})`),
13088
+ "",
13089
+ "## Retention Plan",
13090
+ "",
13091
+ ...report.retentionPlan.scopes.map((scope) => `- ${scope.scope}: scanned ${scope.scannedCount}, would delete ${scope.deletedCount}${scope.skippedReason ? `, skipped=${scope.skippedReason}` : ""}`),
13092
+ "",
13093
+ "## Provider Keys",
13094
+ "",
13095
+ ...report.providerKeys.map((key) => `- ${key.name}${key.env ? ` (${key.env})` : ""}: ${key.recommendation}`)
13096
+ ].join(`
13097
+ `);
13098
+ var buildRetentionPolicyFromQuery = (query, options) => ({
13099
+ ...options,
13100
+ before: getNumberQuery(query.before),
13101
+ beforeOrAt: getNumberQuery(query.beforeOrAt),
13102
+ dryRun: !getBooleanQuery(query.apply),
13103
+ limit: getNumberQuery(query.limit),
13104
+ scopes: parseRetentionScopes(query.scopes),
13105
+ traceFilter: typeof query.sessionId === "string" && query.sessionId.trim() ? { sessionId: query.sessionId } : undefined
13106
+ });
13107
+ var parseRetentionPolicyBody = (body, options, dryRun) => {
13108
+ const input = body && typeof body === "object" ? body : {};
13109
+ return {
13110
+ ...options,
13111
+ before: getNumberQuery(input.before),
13112
+ beforeOrAt: getNumberQuery(input.beforeOrAt),
13113
+ dryRun,
13114
+ limit: getNumberQuery(input.limit),
13115
+ scopes: parseRetentionScopes(input.scopes),
13116
+ traceFilter: typeof input.sessionId === "string" && input.sessionId.trim() ? { sessionId: input.sessionId } : undefined
13117
+ };
13118
+ };
13119
+ var createVoiceDataControlRoutes = (options) => {
13120
+ const path = options.path ?? "/data-control";
13121
+ const title = options.title ?? "AbsoluteJS Voice Data Control";
13122
+ const routes = new Elysia15({
13123
+ name: options.name ?? "absolutejs-voice-data-control"
13124
+ });
13125
+ routes.get(path, async ({ query }) => {
13126
+ const report = await buildVoiceDataControlReport({
13127
+ ...options,
13128
+ retention: buildRetentionPolicyFromQuery(query, options)
13129
+ });
13130
+ return new Response(renderVoiceDataControlHTML(report, { title }), {
13131
+ headers: {
13132
+ "Content-Type": "text/html; charset=utf-8",
13133
+ ...options.headers
13134
+ }
13135
+ });
13136
+ });
13137
+ routes.get(`${path}.json`, async ({ query }) => buildVoiceDataControlReport({
13138
+ ...options,
13139
+ retention: buildRetentionPolicyFromQuery(query, options)
13140
+ }));
13141
+ routes.get(`${path}.md`, async ({ query }) => {
13142
+ const report = await buildVoiceDataControlReport({
13143
+ ...options,
13144
+ retention: buildRetentionPolicyFromQuery(query, options)
13145
+ });
13146
+ return new Response(renderVoiceDataControlMarkdown(report, { title }), {
13147
+ headers: {
13148
+ "Content-Type": "text/markdown; charset=utf-8",
13149
+ ...options.headers
13150
+ }
13151
+ });
13152
+ });
13153
+ routes.post(`${path}/retention/plan`, async ({ body }) => buildVoiceDataRetentionPlan(parseRetentionPolicyBody(body, options, true)));
13154
+ routes.post(`${path}/retention/apply`, async ({ body, set }) => {
13155
+ const input = body && typeof body === "object" ? body : {};
13156
+ if (input.confirm !== "apply-retention-policy") {
13157
+ set.status = 400;
13158
+ return {
13159
+ error: 'Refusing to apply retention without confirm="apply-retention-policy". Use /retention/plan first.'
13160
+ };
13161
+ }
13162
+ return applyVoiceDataRetentionPolicy(parseRetentionPolicyBody(body, options, false));
13163
+ });
13164
+ routes.get(`${path}/audit.json`, async () => options.audit ? exportVoiceAuditTrail({
13165
+ redact: resolveDataControlRedaction(options.redact),
13166
+ store: options.audit
13167
+ }) : { events: [], exportedAt: Date.now(), redacted: false });
13168
+ routes.get(`${path}/audit.md`, async () => {
13169
+ const events = options.audit ? await options.audit.list() : [];
13170
+ return new Response(renderVoiceAuditMarkdown(events, {
13171
+ redact: resolveDataControlRedaction(options.redact),
13172
+ title: `${title} Audit Export`
13173
+ }), {
13174
+ headers: {
13175
+ "Content-Type": "text/markdown; charset=utf-8",
13176
+ ...options.headers
13177
+ }
13178
+ });
13179
+ });
13180
+ routes.get(`${path}/audit.html`, async () => {
13181
+ const events = options.audit ? await options.audit.list() : [];
13182
+ return new Response(renderVoiceAuditHTML(events, {
13183
+ redact: resolveDataControlRedaction(options.redact),
13184
+ title: `${title} Audit Export`
13185
+ }), {
13186
+ headers: {
13187
+ "Content-Type": "text/html; charset=utf-8",
13188
+ ...options.headers
13189
+ }
13190
+ });
13191
+ });
13192
+ return routes;
13193
+ };
12928
13194
  // src/evalRoutes.ts
12929
- import { Elysia as Elysia17 } from "elysia";
13195
+ import { Elysia as Elysia18 } from "elysia";
12930
13196
  import { mkdir as mkdir2 } from "fs/promises";
12931
13197
  import { dirname as dirname2 } from "path";
12932
13198
 
12933
13199
  // src/qualityRoutes.ts
12934
- import { Elysia as Elysia16 } from "elysia";
13200
+ import { Elysia as Elysia17 } from "elysia";
12935
13201
 
12936
13202
  // src/handoffHealth.ts
12937
- import { Elysia as Elysia15 } from "elysia";
12938
- var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13203
+ import { Elysia as Elysia16 } from "elysia";
13204
+ var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
12939
13205
  var getString6 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
12940
13206
  var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
12941
13207
  var increment3 = (record, key) => {
@@ -13053,10 +13319,10 @@ var renderActionSummary = (summary) => {
13053
13319
  return [
13054
13320
  '<section class="voice-handoff-health-columns">',
13055
13321
  "<article><h3>Actions</h3>",
13056
- actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml17(action)}: ${String(count)}</li>`).join("")}</ul>`,
13322
+ actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml18(action)}: ${String(count)}</li>`).join("")}</ul>`,
13057
13323
  "</article>",
13058
13324
  "<article><h3>Adapters</h3>",
13059
- adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml17(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
13325
+ adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml18(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
13060
13326
  "</article>",
13061
13327
  "</section>"
13062
13328
  ].join("");
@@ -13070,22 +13336,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
13070
13336
  summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
13071
13337
  '<div class="voice-handoff-health-events">',
13072
13338
  ...summary.events.map((event) => [
13073
- `<article class="${escapeHtml17(event.status)}">`,
13339
+ `<article class="${escapeHtml18(event.status)}">`,
13074
13340
  '<div class="voice-handoff-health-event-header">',
13075
- `<strong>${escapeHtml17(event.action ?? "handoff")}</strong>`,
13076
- `<span>${escapeHtml17(event.status)}</span>`,
13341
+ `<strong>${escapeHtml18(event.action ?? "handoff")}</strong>`,
13342
+ `<span>${escapeHtml18(event.status)}</span>`,
13077
13343
  "</div>",
13078
- `<p><small>${escapeHtml17(event.sessionId)}</small></p>`,
13079
- event.target ? `<p>Target: ${escapeHtml17(event.target)}</p>` : "",
13080
- event.reason ? `<p>Reason: ${escapeHtml17(event.reason)}</p>` : "",
13344
+ `<p><small>${escapeHtml18(event.sessionId)}</small></p>`,
13345
+ event.target ? `<p>Target: ${escapeHtml18(event.target)}</p>` : "",
13346
+ event.reason ? `<p>Reason: ${escapeHtml18(event.reason)}</p>` : "",
13081
13347
  event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
13082
13348
  "<li>",
13083
- `${escapeHtml17(delivery.adapterId)}: ${escapeHtml17(delivery.status)}`,
13084
- delivery.deliveredTo ? ` to ${escapeHtml17(delivery.deliveredTo)}` : "",
13085
- delivery.error ? ` (${escapeHtml17(delivery.error)})` : "",
13349
+ `${escapeHtml18(delivery.adapterId)}: ${escapeHtml18(delivery.status)}`,
13350
+ delivery.deliveredTo ? ` to ${escapeHtml18(delivery.deliveredTo)}` : "",
13351
+ delivery.error ? ` (${escapeHtml18(delivery.error)})` : "",
13086
13352
  "</li>"
13087
13353
  ].join("")).join("")}</ul>` : "",
13088
- event.replayHref ? `<p><a href="${escapeHtml17(event.replayHref)}">Open replay</a></p>` : "",
13354
+ event.replayHref ? `<p><a href="${escapeHtml18(event.replayHref)}">Open replay</a></p>` : "",
13089
13355
  "</article>"
13090
13356
  ].join("")),
13091
13357
  "</div>"
@@ -13117,7 +13383,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
13117
13383
  var createVoiceHandoffHealthRoutes = (options = {}) => {
13118
13384
  const path = options.path ?? "/api/voice-handoffs";
13119
13385
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
13120
- const routes = new Elysia15({
13386
+ const routes = new Elysia16({
13121
13387
  name: options.name ?? "absolutejs-voice-handoff-health"
13122
13388
  }).get(path, createVoiceHandoffHealthJSONHandler(options));
13123
13389
  if (htmlPath) {
@@ -13238,17 +13504,17 @@ var evaluateVoiceQuality = async (input) => {
13238
13504
  thresholds
13239
13505
  };
13240
13506
  };
13241
- var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13507
+ var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13242
13508
  var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
13243
13509
  var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
13244
13510
  var renderVoiceQualityHTML = (report, options = {}) => {
13245
- const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml18(metric.label)}</td><td>${escapeHtml18(formatMetricValue(metric))}</td><td>${escapeHtml18(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml18(key)}</code></td></tr>`).join("");
13246
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml18(link.href)}">${escapeHtml18(link.label)}</a>`).join("")}</nav>` : "";
13511
+ const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml19(metric.label)}</td><td>${escapeHtml19(formatMetricValue(metric))}</td><td>${escapeHtml19(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml19(key)}</code></td></tr>`).join("");
13512
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml19(link.href)}">${escapeHtml19(link.label)}</a>`).join("")}</nav>` : "";
13247
13513
  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>`;
13248
13514
  };
13249
13515
  var createVoiceQualityRoutes = (options) => {
13250
13516
  const path = options.path ?? "/quality";
13251
- const routes = new Elysia16({
13517
+ const routes = new Elysia17({
13252
13518
  name: options.name ?? "absolutejs-voice-quality"
13253
13519
  });
13254
13520
  const getReport = () => evaluateVoiceQuality({
@@ -13277,7 +13543,7 @@ var createVoiceQualityRoutes = (options) => {
13277
13543
  };
13278
13544
 
13279
13545
  // src/evalRoutes.ts
13280
- var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13546
+ var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13281
13547
  var rate2 = (count, total) => count / Math.max(1, total);
13282
13548
  var normalizeSearchText = (value) => value.trim().toLowerCase();
13283
13549
  var getString8 = (value) => typeof value === "string" ? value : undefined;
@@ -13585,7 +13851,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
13585
13851
  var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
13586
13852
  var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
13587
13853
  var renderVoiceEvalPrimitiveCopy = () => {
13588
- const snippet = escapeHtml19(`app.use(
13854
+ const snippet = escapeHtml20(`app.use(
13589
13855
  createVoiceEvalRoutes({
13590
13856
  path: '/evals',
13591
13857
  store: traceStore,
@@ -13606,44 +13872,44 @@ var renderVoiceEvalPrimitiveCopy = () => {
13606
13872
  };
13607
13873
  var renderVoiceEvalHTML = (report, options = {}) => {
13608
13874
  const title = options.title ?? "AbsoluteJS Voice Evals";
13609
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml19(link.href)}">${escapeHtml19(link.label)}</a>`).join("")}</nav>` : "";
13610
- const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml19(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>';
13875
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join("")}</nav>` : "";
13876
+ const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml20(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>';
13611
13877
  const sessions = report.sessions.length ? report.sessions.map((session) => {
13612
13878
  const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
13613
- return `<tr class="${session.status}"><td>${escapeHtml19(session.sessionId)}</td><td>${escapeHtml19(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml19(formatTime(session.endedAt))}</td><td>${escapeHtml19(failedMetrics || "none")}</td></tr>`;
13879
+ return `<tr class="${session.status}"><td>${escapeHtml20(session.sessionId)}</td><td>${escapeHtml20(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml20(formatTime(session.endedAt))}</td><td>${escapeHtml20(failedMetrics || "none")}</td></tr>`;
13614
13880
  }).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
13615
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(title)}</title><style>body{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>${escapeHtml19(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>`;
13881
+ 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{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>${escapeHtml20(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>`;
13616
13882
  };
13617
13883
  var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
13618
13884
  const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
13619
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml19(link.href)}">${escapeHtml19(link.label)}</a>`).join("")}</nav>` : "";
13620
- const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml19(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
13621
- const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml19(id)}</li>`).join("") : "<li>none</li>";
13622
- const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml19(id)}</li>`).join("") : "<li>none</li>";
13623
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(title)}</title><style>body{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>${escapeHtml19(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml19(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml19(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>${escapeHtml19(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>`;
13885
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join("")}</nav>` : "";
13886
+ const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml20(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
13887
+ const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml20(id)}</li>`).join("") : "<li>none</li>";
13888
+ const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml20(id)}</li>`).join("") : "<li>none</li>";
13889
+ 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{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>${escapeHtml20(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml20(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml20(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>${escapeHtml20(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>`;
13624
13890
  };
13625
13891
  var renderVoiceScenarioEvalHTML = (report, options = {}) => {
13626
13892
  const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
13627
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml19(link.href)}">${escapeHtml19(link.label)}</a>`).join("")}</nav>` : "";
13893
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join("")}</nav>` : "";
13628
13894
  const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
13629
- const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml19(issue)}</li>`).join("")}</ul>` : "";
13630
- const sessions = scenario.sessions.length ? scenario.sessions.map((session) => `<tr class="${session.status}"><td>${escapeHtml19(session.sessionId)}</td><td>${escapeHtml19(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml19(session.issues.join(", ") || "none")}</td></tr>`).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
13631
- return `<section class="scenario ${scenario.status}"><h2>${escapeHtml19(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml19(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>`;
13895
+ const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml20(issue)}</li>`).join("")}</ul>` : "";
13896
+ const sessions = scenario.sessions.length ? scenario.sessions.map((session) => `<tr class="${session.status}"><td>${escapeHtml20(session.sessionId)}</td><td>${escapeHtml20(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml20(session.issues.join(", ") || "none")}</td></tr>`).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
13897
+ return `<section class="scenario ${scenario.status}"><h2>${escapeHtml20(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml20(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>`;
13632
13898
  }).join("") : "<section><p>No scenarios configured.</p></section>";
13633
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(title)}</title><style>body{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>${escapeHtml19(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>`;
13899
+ 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{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>${escapeHtml20(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>`;
13634
13900
  };
13635
13901
  var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
13636
13902
  const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
13637
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml19(link.href)}">${escapeHtml19(link.label)}</a>`).join("")}</nav>` : "";
13903
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml20(link.href)}">${escapeHtml20(link.label)}</a>`).join("")}</nav>` : "";
13638
13904
  const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
13639
- const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml19(scenario.label)}</td><td>${escapeHtml19(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml19([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
13640
- return `<section class="${fixture.status}"><h2>${escapeHtml19(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml19(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>`;
13905
+ const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml20(scenario.label)}</td><td>${escapeHtml20(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml20([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
13906
+ return `<section class="${fixture.status}"><h2>${escapeHtml20(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml20(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>`;
13641
13907
  }).join("") : "<section><p>No scenario fixtures configured.</p></section>";
13642
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(title)}</title><style>body{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>${escapeHtml19(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>`;
13908
+ 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{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>${escapeHtml20(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>`;
13643
13909
  };
13644
13910
  var createVoiceEvalRoutes = (options) => {
13645
13911
  const path = options.path ?? "/evals";
13646
- const routes = new Elysia17({
13912
+ const routes = new Elysia18({
13647
13913
  name: options.name ?? "absolutejs-voice-evals"
13648
13914
  });
13649
13915
  const getReport = () => runVoiceSessionEvals({
@@ -13777,11 +14043,11 @@ var createVoiceEvalRoutes = (options) => {
13777
14043
  return routes;
13778
14044
  };
13779
14045
  // src/simulationSuite.ts
13780
- import { Elysia as Elysia20 } from "elysia";
14046
+ import { Elysia as Elysia21 } from "elysia";
13781
14047
 
13782
14048
  // src/outcomeContract.ts
13783
- import { Elysia as Elysia18 } from "elysia";
13784
- var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14049
+ import { Elysia as Elysia19 } from "elysia";
14050
+ var escapeHtml21 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13785
14051
  var getPayloadString = (event, key) => typeof event.payload[key] === "string" ? event.payload[key] : undefined;
13786
14052
  var toList = async (input) => Array.isArray(input) ? input : await input?.list() ?? [];
13787
14053
  var hydrateSessions = async (input) => {
@@ -13889,9 +14155,9 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
13889
14155
  const contracts = report.contracts.map((contract) => `<section class="contract ${contract.pass ? "pass" : "fail"}">
13890
14156
  <div class="contract-header">
13891
14157
  <div>
13892
- <p class="eyebrow">${escapeHtml20(contract.contractId)}</p>
13893
- <h2>${escapeHtml20(contract.label ?? contract.contractId)}</h2>
13894
- ${contract.description ? `<p>${escapeHtml20(contract.description)}</p>` : ""}
14158
+ <p class="eyebrow">${escapeHtml21(contract.contractId)}</p>
14159
+ <h2>${escapeHtml21(contract.label ?? contract.contractId)}</h2>
14160
+ ${contract.description ? `<p>${escapeHtml21(contract.description)}</p>` : ""}
13895
14161
  </div>
13896
14162
  <strong>${contract.pass ? "pass" : "fail"}</strong>
13897
14163
  </div>
@@ -13902,9 +14168,9 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
13902
14168
  <span>handoffs ${String(contract.matched.handoffs)}</span>
13903
14169
  <span>events ${String(contract.matched.integrationEvents)}</span>
13904
14170
  </div>
13905
- ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml20(issue.message)}</li>`).join("")}</ul>` : ""}
14171
+ ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml21(issue.message)}</li>`).join("")}</ul>` : ""}
13906
14172
  </section>`).join("");
13907
- 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:#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>${escapeHtml20(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>`;
14173
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml21(title)}</title><style>body{background:#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>${escapeHtml21(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>`;
13908
14174
  };
13909
14175
  var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
13910
14176
  var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
@@ -13920,7 +14186,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
13920
14186
  var createVoiceOutcomeContractRoutes = (options) => {
13921
14187
  const path = options.path ?? "/api/outcome-contracts";
13922
14188
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
13923
- const routes = new Elysia18({
14189
+ const routes = new Elysia19({
13924
14190
  name: options.name ?? "absolutejs-voice-outcome-contracts"
13925
14191
  }).get(path, createVoiceOutcomeContractJSONHandler(options));
13926
14192
  if (htmlPath) {
@@ -13930,7 +14196,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
13930
14196
  };
13931
14197
 
13932
14198
  // src/toolContract.ts
13933
- import { Elysia as Elysia19 } from "elysia";
14199
+ import { Elysia as Elysia20 } from "elysia";
13934
14200
 
13935
14201
  // src/toolRuntime.ts
13936
14202
  var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
@@ -14139,7 +14405,7 @@ var createDefaultTurn = (caseId) => ({
14139
14405
  });
14140
14406
  var defaultApi = {};
14141
14407
  var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
14142
- var escapeHtml21 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14408
+ var escapeHtml22 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14143
14409
  var evaluateExpectation = (input) => {
14144
14410
  const issues = [];
14145
14411
  const expect = input.expect;
@@ -14303,7 +14569,7 @@ var runVoiceToolContractSuite = async (options) => {
14303
14569
  };
14304
14570
  var renderVoiceToolContractHTML = (report, options = {}) => {
14305
14571
  const title = options.title ?? "Voice Tool Contracts";
14306
- const snippet = escapeHtml21(`app.use(
14572
+ const snippet = escapeHtml22(`app.use(
14307
14573
  createVoiceToolContractRoutes({
14308
14574
  htmlPath: '/tool-contracts',
14309
14575
  path: '/api/tool-contracts',
@@ -14329,19 +14595,19 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
14329
14595
  );`);
14330
14596
  const contracts = report.contracts.map((contract) => {
14331
14597
  const cases = contract.cases.map((testCase) => `<tr>
14332
- <td>${escapeHtml21(testCase.label ?? testCase.caseId)}</td>
14598
+ <td>${escapeHtml22(testCase.label ?? testCase.caseId)}</td>
14333
14599
  <td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
14334
- <td>${escapeHtml21(testCase.status)}</td>
14600
+ <td>${escapeHtml22(testCase.status)}</td>
14335
14601
  <td>${String(testCase.attempts)}</td>
14336
14602
  <td>${String(testCase.elapsedMs)}ms</td>
14337
14603
  <td>${testCase.timedOut ? "yes" : "no"}</td>
14338
- <td>${escapeHtml21(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
14604
+ <td>${escapeHtml22(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
14339
14605
  </tr>`).join("");
14340
14606
  return `<section class="contract ${contract.pass ? "pass" : "fail"}">
14341
14607
  <div class="contract-header">
14342
14608
  <div>
14343
- <p class="eyebrow">${escapeHtml21(contract.toolName)}</p>
14344
- <h2>${escapeHtml21(contract.label ?? contract.contractId)}</h2>
14609
+ <p class="eyebrow">${escapeHtml22(contract.toolName)}</p>
14610
+ <h2>${escapeHtml22(contract.label ?? contract.contractId)}</h2>
14345
14611
  </div>
14346
14612
  <strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
14347
14613
  </div>
@@ -14351,7 +14617,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
14351
14617
  </table>
14352
14618
  </section>`;
14353
14619
  }).join("");
14354
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml21(title)}</title><style>body{background:#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>${escapeHtml21(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml21(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>`;
14620
+ 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:#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>${escapeHtml22(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml22(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>`;
14355
14621
  };
14356
14622
  var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
14357
14623
  var createVoiceToolContractHTMLHandler = (options) => async () => {
@@ -14368,7 +14634,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
14368
14634
  var createVoiceToolContractRoutes = (options) => {
14369
14635
  const path = options.path ?? "/api/tool-contracts";
14370
14636
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
14371
- const routes = new Elysia19({
14637
+ const routes = new Elysia20({
14372
14638
  name: options.name ?? "absolutejs-voice-tool-contracts"
14373
14639
  }).get(path, createVoiceToolContractJSONHandler(options));
14374
14640
  if (htmlPath) {
@@ -14378,7 +14644,7 @@ var createVoiceToolContractRoutes = (options) => {
14378
14644
  };
14379
14645
 
14380
14646
  // src/simulationSuite.ts
14381
- var escapeHtml22 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14647
+ var escapeHtml23 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14382
14648
  var summarizeSection = (report) => ({
14383
14649
  failed: report.failed,
14384
14650
  passed: report.passed,
@@ -14514,15 +14780,15 @@ var renderSection = (label, summary) => {
14514
14780
  if (!summary) {
14515
14781
  return "";
14516
14782
  }
14517
- return `<article class="${escapeHtml22(summary.status)}"><span>${escapeHtml22(label)}</span><strong>${escapeHtml22(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
14783
+ return `<article class="${escapeHtml23(summary.status)}"><span>${escapeHtml23(label)}</span><strong>${escapeHtml23(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
14518
14784
  };
14519
14785
  var renderAction = (action) => {
14520
- const content = `<strong>${escapeHtml22(action.label)}</strong><p>${escapeHtml22(action.description)}</p><span>${escapeHtml22(action.section)} / ${escapeHtml22(action.severity)}</span>`;
14521
- return action.href ? `<a class="action" href="${escapeHtml22(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
14786
+ const content = `<strong>${escapeHtml23(action.label)}</strong><p>${escapeHtml23(action.description)}</p><span>${escapeHtml23(action.section)} / ${escapeHtml23(action.severity)}</span>`;
14787
+ return action.href ? `<a class="action" href="${escapeHtml23(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
14522
14788
  };
14523
14789
  var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
14524
14790
  const title = options.title ?? "Voice Simulation Suite";
14525
- const snippet = escapeHtml22(`app.use(
14791
+ const snippet = escapeHtml23(`app.use(
14526
14792
  createVoiceSimulationSuiteRoutes({
14527
14793
  htmlPath: '/voice/simulations',
14528
14794
  path: '/api/voice/simulations',
@@ -14555,12 +14821,12 @@ app.use(
14555
14821
  store: traceStore
14556
14822
  })
14557
14823
  );`);
14558
- 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:#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>${escapeHtml22(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml22(report.status)}">Status: ${escapeHtml22(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>${escapeHtml22(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
14824
+ 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:#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>${escapeHtml23(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml23(report.status)}">Status: ${escapeHtml23(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>${escapeHtml23(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
14559
14825
  };
14560
14826
  var createVoiceSimulationSuiteRoutes = (options) => {
14561
14827
  const path = options.path ?? "/api/voice/simulations";
14562
14828
  const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
14563
- const app = new Elysia20({
14829
+ const app = new Elysia21({
14564
14830
  name: options.name ?? "absolutejs-voice-simulation-suite"
14565
14831
  }).get(path, () => runVoiceSimulationSuite(options));
14566
14832
  if (htmlPath) {
@@ -14872,9 +15138,9 @@ var createVoiceWorkflowContractHandler = (input) => {
14872
15138
  };
14873
15139
  };
14874
15140
  // src/sessionReplay.ts
14875
- import { Elysia as Elysia21 } from "elysia";
15141
+ import { Elysia as Elysia22 } from "elysia";
14876
15142
  var getString9 = (value) => typeof value === "string" ? value : undefined;
14877
- var escapeHtml23 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15143
+ var escapeHtml24 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14878
15144
  var increment4 = (record, key) => {
14879
15145
  record[key] = (record[key] ?? 0) + 1;
14880
15146
  };
@@ -15054,10 +15320,10 @@ var summarizeVoiceSessions = async (options = {}) => {
15054
15320
  var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
15055
15321
  '<div class="voice-sessions-list">',
15056
15322
  ...sessions.map((session) => [
15057
- `<article class="voice-session-card ${escapeHtml23(session.status)}">`,
15323
+ `<article class="voice-session-card ${escapeHtml24(session.status)}">`,
15058
15324
  '<div class="voice-session-card-header">',
15059
- `<strong>${escapeHtml23(session.sessionId)}</strong>`,
15060
- `<span>${escapeHtml23(session.status)}</span>`,
15325
+ `<strong>${escapeHtml24(session.sessionId)}</strong>`,
15326
+ `<span>${escapeHtml24(session.status)}</span>`,
15061
15327
  "</div>",
15062
15328
  "<dl>",
15063
15329
  `<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
@@ -15065,9 +15331,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
15065
15331
  `<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
15066
15332
  `<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
15067
15333
  "</dl>",
15068
- session.latestOutcome ? `<p>Outcome: ${escapeHtml23(session.latestOutcome)}</p>` : "",
15069
- session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml23).join(", ")}</p>` : "",
15070
- session.replayHref ? `<p><a href="${escapeHtml23(session.replayHref)}">Open replay</a></p>` : "",
15334
+ session.latestOutcome ? `<p>Outcome: ${escapeHtml24(session.latestOutcome)}</p>` : "",
15335
+ session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml24).join(", ")}</p>` : "",
15336
+ session.replayHref ? `<p><a href="${escapeHtml24(session.replayHref)}">Open replay</a></p>` : "",
15071
15337
  "</article>"
15072
15338
  ].join("")),
15073
15339
  "</div>"
@@ -15098,7 +15364,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
15098
15364
  var createVoiceSessionListRoutes = (options = {}) => {
15099
15365
  const path = options.path ?? "/api/voice-sessions";
15100
15366
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
15101
- const routes = new Elysia21({
15367
+ const routes = new Elysia22({
15102
15368
  name: options.name ?? "absolutejs-voice-session-list"
15103
15369
  }).get(path, createVoiceSessionsJSONHandler(options));
15104
15370
  if (htmlPath) {
@@ -15126,7 +15392,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
15126
15392
  var createVoiceSessionReplayRoutes = (options) => {
15127
15393
  const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
15128
15394
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
15129
- const routes = new Elysia21({
15395
+ const routes = new Elysia22({
15130
15396
  name: options.name ?? "absolutejs-voice-session-replay"
15131
15397
  }).get(path, createVoiceSessionReplayJSONHandler(options));
15132
15398
  if (htmlPath) {
@@ -15355,10 +15621,10 @@ var assertVoiceAgentSquadContract = async (options) => {
15355
15621
  return report;
15356
15622
  };
15357
15623
  // src/turnLatency.ts
15358
- import { Elysia as Elysia22 } from "elysia";
15624
+ import { Elysia as Elysia23 } from "elysia";
15359
15625
  var DEFAULT_WARN_AFTER_MS = 1800;
15360
15626
  var DEFAULT_FAIL_AFTER_MS = 3200;
15361
- var escapeHtml24 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15627
+ var escapeHtml25 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15362
15628
  var firstNumber = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
15363
15629
  var getString10 = (value) => typeof value === "string" && value.trim() ? value : undefined;
15364
15630
  var createTraceStageIndex = (events) => {
@@ -15490,11 +15756,11 @@ await traceStore.append({
15490
15756
  turnId,
15491
15757
  type: 'turn_latency.stage'
15492
15758
  });`;
15493
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml24(turn.status)}">
15494
- <header><div><p class="eyebrow">${escapeHtml24(turn.sessionId)} \xB7 ${escapeHtml24(turn.turnId)}</p><h2>${escapeHtml24(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml24(turn.status)}</strong></header>
15495
- <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml24(stage.label)}</dt><dd>${escapeHtml24(formatMs(stage.valueMs))}</dd></div>`).join("")}</dl>
15759
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml25(turn.status)}">
15760
+ <header><div><p class="eyebrow">${escapeHtml25(turn.sessionId)} \xB7 ${escapeHtml25(turn.turnId)}</p><h2>${escapeHtml25(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml25(turn.status)}</strong></header>
15761
+ <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml25(stage.label)}</dt><dd>${escapeHtml25(formatMs(stage.valueMs))}</dd></div>`).join("")}</dl>
15496
15762
  </article>`).join("");
15497
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml24(title)}</title><style>body{background:#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>${escapeHtml24(title)}</h1><div class="summary"><span class="pill ${escapeHtml24(report.status)}">${escapeHtml24(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml24(formatMs(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>${escapeHtml24(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
15763
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><div class="summary"><span class="pill ${escapeHtml25(report.status)}">${escapeHtml25(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml25(formatMs(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>${escapeHtml25(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
15498
15764
  };
15499
15765
  var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
15500
15766
  var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
@@ -15511,7 +15777,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
15511
15777
  var createVoiceTurnLatencyRoutes = (options) => {
15512
15778
  const path = options.path ?? "/api/turn-latency";
15513
15779
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
15514
- const routes = new Elysia22({
15780
+ const routes = new Elysia23({
15515
15781
  name: options.name ?? "absolutejs-voice-turn-latency"
15516
15782
  }).get(path, createVoiceTurnLatencyJSONHandler(options));
15517
15783
  if (htmlPath) {
@@ -15520,8 +15786,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
15520
15786
  return routes;
15521
15787
  };
15522
15788
  // src/liveLatency.ts
15523
- import { Elysia as Elysia23 } from "elysia";
15524
- var escapeHtml25 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15789
+ import { Elysia as Elysia24 } from "elysia";
15790
+ var escapeHtml26 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15525
15791
  var percentile = (values, percentileValue) => {
15526
15792
  if (values.length === 0) {
15527
15793
  return;
@@ -15588,13 +15854,13 @@ await traceStore.append({
15588
15854
  sessionId,
15589
15855
  type: 'client.live_latency'
15590
15856
  });`;
15591
- const rows = report.recent.map((sample) => `<tr><td>${escapeHtml25(sample.sessionId)}</td><td>${escapeHtml25(formatMs2(sample.latencyMs))}</td><td>${escapeHtml25(sample.status ?? "unknown")}</td><td>${escapeHtml25(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
15592
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml25(title)}</title><style>body{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>${escapeHtml25(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml25(report.status)}">Status: ${escapeHtml25(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml25(formatMs2(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml25(formatMs2(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml25(formatMs2(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>${escapeHtml25(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>`;
15857
+ const rows = report.recent.map((sample) => `<tr><td>${escapeHtml26(sample.sessionId)}</td><td>${escapeHtml26(formatMs2(sample.latencyMs))}</td><td>${escapeHtml26(sample.status ?? "unknown")}</td><td>${escapeHtml26(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
15858
+ 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:#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>${escapeHtml26(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml26(report.status)}">Status: ${escapeHtml26(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml26(formatMs2(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml26(formatMs2(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml26(formatMs2(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>${escapeHtml26(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>`;
15593
15859
  };
15594
15860
  var createVoiceLiveLatencyRoutes = (options) => {
15595
15861
  const path = options.path ?? "/api/live-latency";
15596
15862
  const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
15597
- const routes = new Elysia23({
15863
+ const routes = new Elysia24({
15598
15864
  name: options.name ?? "absolutejs-voice-live-latency"
15599
15865
  }).get(path, () => summarizeVoiceLiveLatency(options));
15600
15866
  if (htmlPath) {
@@ -15913,9 +16179,9 @@ None.
15913
16179
  `}`;
15914
16180
  };
15915
16181
  // src/turnQuality.ts
15916
- import { Elysia as Elysia24 } from "elysia";
16182
+ import { Elysia as Elysia25 } from "elysia";
15917
16183
  var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
15918
- var escapeHtml26 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
16184
+ var escapeHtml27 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
15919
16185
  var getTurnLatencyMs = (turn) => {
15920
16186
  const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
15921
16187
  if (firstTranscriptAt === undefined) {
@@ -15986,24 +16252,24 @@ var summarizeVoiceTurnQuality = async (options) => {
15986
16252
  };
15987
16253
  var renderVoiceTurnQualityHTML = (report, options = {}) => {
15988
16254
  const title = options.title ?? "Voice Turn Quality";
15989
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml26(turn.status)}">
16255
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml27(turn.status)}">
15990
16256
  <div class="turn-header">
15991
16257
  <div>
15992
- <p class="eyebrow">${escapeHtml26(turn.sessionId)} \xB7 ${escapeHtml26(turn.turnId)}</p>
15993
- <h2>${escapeHtml26(turn.text || "Empty turn")}</h2>
16258
+ <p class="eyebrow">${escapeHtml27(turn.sessionId)} \xB7 ${escapeHtml27(turn.turnId)}</p>
16259
+ <h2>${escapeHtml27(turn.text || "Empty turn")}</h2>
15994
16260
  </div>
15995
- <strong>${escapeHtml26(turn.status)}</strong>
16261
+ <strong>${escapeHtml27(turn.status)}</strong>
15996
16262
  </div>
15997
16263
  <dl>
15998
- <div><dt>Source</dt><dd>${escapeHtml26(turn.source ?? "unknown")}</dd></div>
16264
+ <div><dt>Source</dt><dd>${escapeHtml27(turn.source ?? "unknown")}</dd></div>
15999
16265
  <div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
16000
- <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml26(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
16001
- <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml26(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
16266
+ <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml27(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
16267
+ <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml27(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
16002
16268
  <div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
16003
16269
  <div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
16004
16270
  </dl>
16005
16271
  </article>`).join("");
16006
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml26(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml26(title)}</h1><div class="summary"><span class="pill ${escapeHtml26(report.status)}">${escapeHtml26(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>`;
16272
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml27(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml27(title)}</h1><div class="summary"><span class="pill ${escapeHtml27(report.status)}">${escapeHtml27(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>`;
16007
16273
  };
16008
16274
  var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
16009
16275
  var createVoiceTurnQualityHTMLHandler = (options) => async () => {
@@ -16020,7 +16286,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
16020
16286
  var createVoiceTurnQualityRoutes = (options) => {
16021
16287
  const path = options.path ?? "/api/turn-quality";
16022
16288
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
16023
- const routes = new Elysia24({
16289
+ const routes = new Elysia25({
16024
16290
  name: options.name ?? "absolutejs-voice-turn-quality"
16025
16291
  }).get(path, createVoiceTurnQualityJSONHandler(options));
16026
16292
  if (htmlPath) {
@@ -16029,7 +16295,7 @@ var createVoiceTurnQualityRoutes = (options) => {
16029
16295
  return routes;
16030
16296
  };
16031
16297
  // src/telephonyOutcome.ts
16032
- import { Elysia as Elysia25 } from "elysia";
16298
+ import { Elysia as Elysia26 } from "elysia";
16033
16299
  var DEFAULT_COMPLETED_STATUSES = [
16034
16300
  "answered",
16035
16301
  "completed",
@@ -16679,7 +16945,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
16679
16945
  var createVoiceTelephonyWebhookRoutes = (options = {}) => {
16680
16946
  const path = options.path ?? "/api/voice/telephony/webhook";
16681
16947
  const handler = createVoiceTelephonyWebhookHandler(options);
16682
- return new Elysia25({
16948
+ return new Elysia26({
16683
16949
  name: options.name ?? "absolutejs-voice-telephony-webhooks"
16684
16950
  }).post(path, async ({ query, request }) => {
16685
16951
  try {
@@ -16700,11 +16966,11 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
16700
16966
  });
16701
16967
  };
16702
16968
  // src/phoneAgent.ts
16703
- import { Elysia as Elysia31 } from "elysia";
16969
+ import { Elysia as Elysia32 } from "elysia";
16704
16970
 
16705
16971
  // src/telephony/plivo.ts
16706
16972
  import { Buffer as Buffer5 } from "buffer";
16707
- import { Elysia as Elysia27 } from "elysia";
16973
+ import { Elysia as Elysia28 } from "elysia";
16708
16974
 
16709
16975
  // src/telephony/contract.ts
16710
16976
  var DEFAULT_REQUIREMENTS = [
@@ -16788,7 +17054,7 @@ var evaluateVoiceTelephonyContract = (input) => {
16788
17054
 
16789
17055
  // src/telephony/twilio.ts
16790
17056
  import { Buffer as Buffer4 } from "buffer";
16791
- import { Elysia as Elysia26 } from "elysia";
17057
+ import { Elysia as Elysia27 } from "elysia";
16792
17058
  var TWILIO_MULAW_SAMPLE_RATE = 8000;
16793
17059
  var VOICE_PCM_SAMPLE_RATE = 16000;
16794
17060
  var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
@@ -16818,7 +17084,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
16818
17084
  return parameters;
16819
17085
  };
16820
17086
  var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
16821
- var escapeHtml27 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17087
+ var escapeHtml28 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
16822
17088
  var getWebhookVerificationUrl = (webhook, input) => {
16823
17089
  if (!webhook?.verificationUrl) {
16824
17090
  return;
@@ -16861,23 +17127,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
16861
17127
  };
16862
17128
  var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
16863
17129
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
16864
- <h1>${escapeHtml27(title)}</h1>
17130
+ <h1>${escapeHtml28(title)}</h1>
16865
17131
  <p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
16866
17132
  <section>
16867
17133
  <h2>URLs</h2>
16868
17134
  <ul>
16869
- <li><strong>TwiML:</strong> <code>${escapeHtml27(status.urls.twiml)}</code></li>
16870
- <li><strong>Media stream:</strong> <code>${escapeHtml27(status.urls.stream)}</code></li>
16871
- <li><strong>Status webhook:</strong> <code>${escapeHtml27(status.urls.webhook)}</code></li>
17135
+ <li><strong>TwiML:</strong> <code>${escapeHtml28(status.urls.twiml)}</code></li>
17136
+ <li><strong>Media stream:</strong> <code>${escapeHtml28(status.urls.stream)}</code></li>
17137
+ <li><strong>Status webhook:</strong> <code>${escapeHtml28(status.urls.webhook)}</code></li>
16872
17138
  </ul>
16873
17139
  </section>
16874
17140
  <section>
16875
17141
  <h2>Signing</h2>
16876
17142
  <p>Mode: <code>${status.signing.mode}</code></p>
16877
- ${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml27(status.signing.verificationUrl)}</code></p>` : ""}
17143
+ ${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml28(status.signing.verificationUrl)}</code></p>` : ""}
16878
17144
  </section>
16879
- ${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml27(name)}</code></li>`).join("")}</ul></section>` : ""}
16880
- ${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml27(warning)}</li>`).join("")}</ul></section>` : ""}
17145
+ ${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml28(name)}</code></li>`).join("")}</ul></section>` : ""}
17146
+ ${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml28(warning)}</li>`).join("")}</ul></section>` : ""}
16881
17147
  </main>`;
16882
17148
  var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&amp;", "&");
16883
17149
  var createSmokeCheck = (name, status, message, details) => ({
@@ -16888,20 +17154,20 @@ var createSmokeCheck = (name, status, message, details) => ({
16888
17154
  });
16889
17155
  var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
16890
17156
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
16891
- <h1>${escapeHtml27(title)}</h1>
17157
+ <h1>${escapeHtml28(title)}</h1>
16892
17158
  <p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
16893
17159
  <section>
16894
17160
  <h2>Checks</h2>
16895
17161
  <ul>
16896
- ${report.checks.map((check) => `<li><strong>${escapeHtml27(check.name)}</strong>: ${escapeHtml27(check.status)}${check.message ? ` - ${escapeHtml27(check.message)}` : ""}</li>`).join("")}
17162
+ ${report.checks.map((check) => `<li><strong>${escapeHtml28(check.name)}</strong>: ${escapeHtml28(check.status)}${check.message ? ` - ${escapeHtml28(check.message)}` : ""}</li>`).join("")}
16897
17163
  </ul>
16898
17164
  </section>
16899
17165
  <section>
16900
17166
  <h2>Observed URLs</h2>
16901
17167
  <ul>
16902
- <li><strong>TwiML:</strong> <code>${escapeHtml27(report.setup.urls.twiml)}</code></li>
16903
- <li><strong>Stream:</strong> <code>${escapeHtml27(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
16904
- <li><strong>Webhook:</strong> <code>${escapeHtml27(report.setup.urls.webhook)}</code></li>
17168
+ <li><strong>TwiML:</strong> <code>${escapeHtml28(report.setup.urls.twiml)}</code></li>
17169
+ <li><strong>Stream:</strong> <code>${escapeHtml28(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
17170
+ <li><strong>Webhook:</strong> <code>${escapeHtml28(report.setup.urls.webhook)}</code></li>
16905
17171
  </ul>
16906
17172
  </section>
16907
17173
  </main>`;
@@ -17361,7 +17627,7 @@ var createTwilioVoiceRoutes = (options) => {
17361
17627
  const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
17362
17628
  const bridges = new WeakMap;
17363
17629
  const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
17364
- const app = new Elysia26({
17630
+ const app = new Elysia27({
17365
17631
  name: options.name ?? "absolutejs-voice-twilio"
17366
17632
  }).get(twimlPath, async ({ query, request }) => {
17367
17633
  const streamUrl = await resolveTwilioStreamUrl(options, {
@@ -17498,7 +17764,7 @@ var createTwilioVoiceRoutes = (options) => {
17498
17764
 
17499
17765
  // src/telephony/plivo.ts
17500
17766
  var escapeXml3 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17501
- var escapeHtml28 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17767
+ var escapeHtml29 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17502
17768
  var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
17503
17769
  var resolveRequestOrigin2 = (request) => {
17504
17770
  const url = new URL(request.url);
@@ -17749,21 +18015,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
17749
18015
  };
17750
18016
  var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
17751
18017
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
17752
- <h1>${escapeHtml28(title)}</h1>
18018
+ <h1>${escapeHtml29(title)}</h1>
17753
18019
  <p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
17754
18020
  <ul>
17755
- <li><strong>Answer XML:</strong> <code>${escapeHtml28(status.urls.answer)}</code></li>
17756
- <li><strong>Audio stream:</strong> <code>${escapeHtml28(status.urls.stream)}</code></li>
17757
- <li><strong>Status webhook:</strong> <code>${escapeHtml28(status.urls.webhook)}</code></li>
18021
+ <li><strong>Answer XML:</strong> <code>${escapeHtml29(status.urls.answer)}</code></li>
18022
+ <li><strong>Audio stream:</strong> <code>${escapeHtml29(status.urls.stream)}</code></li>
18023
+ <li><strong>Status webhook:</strong> <code>${escapeHtml29(status.urls.webhook)}</code></li>
17758
18024
  </ul>
17759
- ${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml28(name)}</code></li>`).join("")}</ul>` : ""}
17760
- ${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml28(warning)}</li>`).join("")}</ul>` : ""}
18025
+ ${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml29(name)}</code></li>`).join("")}</ul>` : ""}
18026
+ ${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml29(warning)}</li>`).join("")}</ul>` : ""}
17761
18027
  </main>`;
17762
18028
  var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
17763
18029
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
17764
- <h1>${escapeHtml28(title)}</h1>
18030
+ <h1>${escapeHtml29(title)}</h1>
17765
18031
  <p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
17766
- <ul>${report.checks.map((check) => `<li><strong>${escapeHtml28(check.name)}</strong>: ${escapeHtml28(check.status)}${check.message ? ` - ${escapeHtml28(check.message)}` : ""}</li>`).join("")}</ul>
18032
+ <ul>${report.checks.map((check) => `<li><strong>${escapeHtml29(check.name)}</strong>: ${escapeHtml29(check.status)}${check.message ? ` - ${escapeHtml29(check.message)}` : ""}</li>`).join("")}</ul>
17767
18033
  </main>`;
17768
18034
  var runPlivoSmokeTest = async (input) => {
17769
18035
  const setup = await buildPlivoVoiceSetupStatus(input.options, input);
@@ -17858,7 +18124,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
17858
18124
  request: input.request
17859
18125
  }) : verificationUrl ?? input.request.url
17860
18126
  }) : undefined);
17861
- const app = new Elysia27({
18127
+ const app = new Elysia28({
17862
18128
  name: options.name ?? "absolutejs-voice-plivo"
17863
18129
  }).get(answerPath, async ({ query, request }) => {
17864
18130
  const streamUrl = await resolvePlivoStreamUrl(options, {
@@ -17969,9 +18235,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
17969
18235
 
17970
18236
  // src/telephony/telnyx.ts
17971
18237
  import { Buffer as Buffer6 } from "buffer";
17972
- import { Elysia as Elysia28 } from "elysia";
18238
+ import { Elysia as Elysia29 } from "elysia";
17973
18239
  var escapeXml4 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17974
- var escapeHtml29 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18240
+ var escapeHtml30 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17975
18241
  var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
17976
18242
  var resolveRequestOrigin3 = (request) => {
17977
18243
  const url = new URL(request.url);
@@ -18172,21 +18438,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
18172
18438
  };
18173
18439
  var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
18174
18440
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
18175
- <h1>${escapeHtml29(title)}</h1>
18441
+ <h1>${escapeHtml30(title)}</h1>
18176
18442
  <p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
18177
18443
  <ul>
18178
- <li><strong>TeXML:</strong> <code>${escapeHtml29(status.urls.texml)}</code></li>
18179
- <li><strong>Media stream:</strong> <code>${escapeHtml29(status.urls.stream)}</code></li>
18180
- <li><strong>Status webhook:</strong> <code>${escapeHtml29(status.urls.webhook)}</code></li>
18444
+ <li><strong>TeXML:</strong> <code>${escapeHtml30(status.urls.texml)}</code></li>
18445
+ <li><strong>Media stream:</strong> <code>${escapeHtml30(status.urls.stream)}</code></li>
18446
+ <li><strong>Status webhook:</strong> <code>${escapeHtml30(status.urls.webhook)}</code></li>
18181
18447
  </ul>
18182
- ${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml29(name)}</code></li>`).join("")}</ul>` : ""}
18183
- ${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml29(warning)}</li>`).join("")}</ul>` : ""}
18448
+ ${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml30(name)}</code></li>`).join("")}</ul>` : ""}
18449
+ ${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml30(warning)}</li>`).join("")}</ul>` : ""}
18184
18450
  </main>`;
18185
18451
  var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
18186
18452
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
18187
- <h1>${escapeHtml29(title)}</h1>
18453
+ <h1>${escapeHtml30(title)}</h1>
18188
18454
  <p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
18189
- <ul>${report.checks.map((check) => `<li><strong>${escapeHtml29(check.name)}</strong>: ${escapeHtml29(check.status)}${check.message ? ` - ${escapeHtml29(check.message)}` : ""}</li>`).join("")}</ul>
18455
+ <ul>${report.checks.map((check) => `<li><strong>${escapeHtml30(check.name)}</strong>: ${escapeHtml30(check.status)}${check.message ? ` - ${escapeHtml30(check.message)}` : ""}</li>`).join("")}</ul>
18190
18456
  </main>`;
18191
18457
  var runTelnyxSmokeTest = async (input) => {
18192
18458
  const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
@@ -18280,7 +18546,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
18280
18546
  publicKey: options.webhook?.publicKey,
18281
18547
  toleranceSeconds: options.webhook?.toleranceSeconds
18282
18548
  }) : undefined);
18283
- const app = new Elysia28({
18549
+ const app = new Elysia29({
18284
18550
  name: options.name ?? "absolutejs-voice-telnyx"
18285
18551
  }).get(texmlPath, async ({ query, request }) => {
18286
18552
  const streamUrl = await resolveTelnyxStreamUrl(options, {
@@ -18390,8 +18656,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
18390
18656
  };
18391
18657
 
18392
18658
  // src/telephony/matrix.ts
18393
- import { Elysia as Elysia29 } from "elysia";
18394
- var escapeHtml30 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18659
+ import { Elysia as Elysia30 } from "elysia";
18660
+ var escapeHtml31 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18395
18661
  var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
18396
18662
  var resolveEntryStatus = (contract, setup, smoke) => {
18397
18663
  if (!contract.pass || !setup.ready || smoke?.pass === false) {
@@ -18452,13 +18718,13 @@ var badgeStyles = {
18452
18718
  };
18453
18719
  var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
18454
18720
  <p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
18455
- <h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml30(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
18721
+ <h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml31(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
18456
18722
  <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>
18457
18723
  <section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
18458
18724
  ${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);">
18459
18725
  <div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
18460
- <h2 style="margin:0; font-size:20px;">${escapeHtml30(entry.name)}</h2>
18461
- <span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml30(entry.status.toUpperCase())}</span>
18726
+ <h2 style="margin:0; font-size:20px;">${escapeHtml31(entry.name)}</h2>
18727
+ <span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml31(entry.status.toUpperCase())}</span>
18462
18728
  </div>
18463
18729
  <dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
18464
18730
  <dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
@@ -18466,15 +18732,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
18466
18732
  <dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
18467
18733
  <dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
18468
18734
  </dl>
18469
- <p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml30(entry.setup.urls.stream || "missing")}</code></p>
18470
- <p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml30(entry.setup.urls.webhook || "missing")}</code></p>
18471
- ${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml30(issue.severity)}: ${escapeHtml30(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
18735
+ <p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml31(entry.setup.urls.stream || "missing")}</code></p>
18736
+ <p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml31(entry.setup.urls.webhook || "missing")}</code></p>
18737
+ ${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml31(issue.severity)}: ${escapeHtml31(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
18472
18738
  </article>`).join("")}
18473
18739
  </section>
18474
18740
  </main>`;
18475
18741
  var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
18476
18742
  const path = options.path ?? "/api/voice/telephony/carriers";
18477
- return new Elysia29({
18743
+ return new Elysia30({
18478
18744
  name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
18479
18745
  }).get(path, async ({ query, request }) => {
18480
18746
  const providers = await options.load({ query, request });
@@ -18496,7 +18762,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
18496
18762
  };
18497
18763
 
18498
18764
  // src/phoneAgentProductionSmoke.ts
18499
- import { Elysia as Elysia30 } from "elysia";
18765
+ import { Elysia as Elysia31 } from "elysia";
18500
18766
  var defaultRequirements = [
18501
18767
  "media-started",
18502
18768
  "transcript",
@@ -18504,7 +18770,7 @@ var defaultRequirements = [
18504
18770
  "lifecycle-outcome",
18505
18771
  "no-session-error"
18506
18772
  ];
18507
- var escapeHtml31 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
18773
+ var escapeHtml32 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
18508
18774
  var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
18509
18775
  var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
18510
18776
  const value = event.payload[key];
@@ -18613,10 +18879,10 @@ var resolveHandlerOptions = async (options, input) => ({
18613
18879
  });
18614
18880
  var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
18615
18881
  const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
18616
- const issues = report.issues.map((issue) => `<li><strong>${escapeHtml31(issue.requirement)}</strong>: ${escapeHtml31(issue.message)}</li>`).join("");
18617
- const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml31(outcome)}</span>`).join("");
18618
- const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml31(requirement)}</span>`).join("");
18619
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml31(title)}</title><style>body{background:#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>${escapeHtml31(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml31(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml31(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml31(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>`;
18882
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml32(issue.requirement)}</strong>: ${escapeHtml32(issue.message)}</li>`).join("");
18883
+ const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml32(outcome)}</span>`).join("");
18884
+ const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml32(requirement)}</span>`).join("");
18885
+ 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:#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>${escapeHtml32(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml32(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml32(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml32(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>`;
18620
18886
  };
18621
18887
  var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
18622
18888
  query,
@@ -18639,7 +18905,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
18639
18905
  var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
18640
18906
  const path = options.path ?? "/api/voice/phone/smoke-contract";
18641
18907
  const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
18642
- const routes = new Elysia30({
18908
+ const routes = new Elysia31({
18643
18909
  name: options.name ?? "absolutejs-voice-phone-smoke-contract"
18644
18910
  }).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
18645
18911
  if (htmlPath) {
@@ -18682,7 +18948,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
18682
18948
  "completed",
18683
18949
  "failed"
18684
18950
  ];
18685
- var escapeHtml32 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18951
+ var escapeHtml33 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
18686
18952
  var loadRouteJson = async (input) => {
18687
18953
  const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
18688
18954
  headers: {
@@ -18742,10 +19008,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
18742
19008
  const entry = report.matrix?.entries.find((candidate) => candidate.provider === carrier.provider && (candidate.name === carrier.name || candidate.name === (carrier.name ?? carrier.provider)));
18743
19009
  const urls = entry?.setup.urls;
18744
19010
  const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
18745
- return `<tr><td>${escapeHtml32(carrier.name ?? carrier.provider)}</td><td>${escapeHtml32(carrier.provider)}</td><td><code>${escapeHtml32(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml32(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml32(entry.status)}">${escapeHtml32(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml32(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml32(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml32(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
19011
+ return `<tr><td>${escapeHtml33(carrier.name ?? carrier.provider)}</td><td>${escapeHtml33(carrier.provider)}</td><td><code>${escapeHtml33(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml33(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml33(entry.status)}">${escapeHtml33(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml33(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml33(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml33(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
18746
19012
  }).join("");
18747
- const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml32(stage)}</code></li>`).join("");
18748
- const snippet = escapeHtml32(`const phoneAgent = createVoicePhoneAgent({
19013
+ const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml33(stage)}</code></li>`).join("");
19014
+ const snippet = escapeHtml33(`const phoneAgent = createVoicePhoneAgent({
18749
19015
  carriers: [
18750
19016
  {
18751
19017
  provider: 'twilio',
@@ -18782,10 +19048,10 @@ app.use(
18782
19048
  const urls = entry?.setup.urls;
18783
19049
  const answerLabel = carrier.provider === "telnyx" ? "TeXML URL" : carrier.provider === "plivo" ? "Answer URL" : "TwiML URL";
18784
19050
  const answerUrl = urls?.twiml;
18785
- const issueList = entry?.issues.map((issue) => `<li>${escapeHtml32(issue.severity)}: ${escapeHtml32(issue.message)}</li>`).join("") ?? "";
18786
- return `<article><h3>${escapeHtml32(carrier.name ?? carrier.provider)}</h3><ol><li>Set ${escapeHtml32(answerLabel)} to <code>${escapeHtml32(answerUrl ?? "missing")}</code>.</li><li>Set status webhook to <code>${escapeHtml32(urls?.webhook ?? "missing")}</code>.</li><li>Allow media stream URL <code>${escapeHtml32(urls?.stream ?? "missing")}</code>.</li><li>Open setup: ${carrier.setupPath ? `<a href="${escapeHtml32(carrier.setupPath)}?format=html">${escapeHtml32(carrier.setupPath)}</a>` : '<span class="muted">disabled</span>'}.</li><li>Run smoke: ${carrier.smokePath ? `<a href="${escapeHtml32(carrier.smokePath)}?format=html">${escapeHtml32(carrier.smokePath)}</a>` : '<span class="muted">disabled</span>'}.</li>${report.productionSmokePath ? `<li>Certify production smoke traces: <a href="${escapeHtml32(report.productionSmokePath.replace("/api/", "/"))}?sessionId=">${escapeHtml32(report.productionSmokePath)}</a>.</li>` : ""}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
19051
+ const issueList = entry?.issues.map((issue) => `<li>${escapeHtml33(issue.severity)}: ${escapeHtml33(issue.message)}</li>`).join("") ?? "";
19052
+ return `<article><h3>${escapeHtml33(carrier.name ?? carrier.provider)}</h3><ol><li>Set ${escapeHtml33(answerLabel)} to <code>${escapeHtml33(answerUrl ?? "missing")}</code>.</li><li>Set status webhook to <code>${escapeHtml33(urls?.webhook ?? "missing")}</code>.</li><li>Allow media stream URL <code>${escapeHtml33(urls?.stream ?? "missing")}</code>.</li><li>Open setup: ${carrier.setupPath ? `<a href="${escapeHtml33(carrier.setupPath)}?format=html">${escapeHtml33(carrier.setupPath)}</a>` : '<span class="muted">disabled</span>'}.</li><li>Run smoke: ${carrier.smokePath ? `<a href="${escapeHtml33(carrier.smokePath)}?format=html">${escapeHtml33(carrier.smokePath)}</a>` : '<span class="muted">disabled</span>'}.</li>${report.productionSmokePath ? `<li>Certify production smoke traces: <a href="${escapeHtml33(report.productionSmokePath.replace("/api/", "/"))}?sessionId=">${escapeHtml33(report.productionSmokePath)}</a>.</li>` : ""}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
18787
19053
  }).join("");
18788
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(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>${escapeHtml32(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="${escapeHtml32(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>`;
19054
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml33(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>${escapeHtml33(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="${escapeHtml33(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>`;
18789
19055
  };
18790
19056
  var createVoicePhoneAgent = (options) => {
18791
19057
  const carrierSummaries = options.carriers.map((carrier) => ({
@@ -18794,7 +19060,7 @@ var createVoicePhoneAgent = (options) => {
18794
19060
  setupPath: resolveSetupPath(carrier),
18795
19061
  smokePath: resolveSmokePath(carrier)
18796
19062
  }));
18797
- const app = new Elysia31({
19063
+ const app = new Elysia32({
18798
19064
  name: options.name ?? "absolutejs-voice-phone-agent"
18799
19065
  });
18800
19066
  for (const carrier of options.carriers) {
@@ -20848,8 +21114,8 @@ var createOpenAIVoiceTTS = (options) => {
20848
21114
  };
20849
21115
  };
20850
21116
  // src/providerCapabilities.ts
20851
- import { Elysia as Elysia32 } from "elysia";
20852
- var escapeHtml33 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21117
+ import { Elysia as Elysia33 } from "elysia";
21118
+ var escapeHtml34 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
20853
21119
  var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
20854
21120
  configured: true,
20855
21121
  features: options.features?.[provider],
@@ -20912,27 +21178,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
20912
21178
  var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
20913
21179
  const title = options.title ?? "Voice Provider Capabilities";
20914
21180
  const cards = report.capabilities.map((capability) => {
20915
- const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml33(feature)}</span>`).join("");
20916
- return `<article class="card ${escapeHtml33(capability.status)}">
21181
+ const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml34(feature)}</span>`).join("");
21182
+ return `<article class="card ${escapeHtml34(capability.status)}">
20917
21183
  <div class="card-header">
20918
21184
  <div>
20919
- <p class="eyebrow">${escapeHtml33(capability.kind)}</p>
20920
- <h2>${escapeHtml33(capability.label ?? capability.provider)}</h2>
21185
+ <p class="eyebrow">${escapeHtml34(capability.kind)}</p>
21186
+ <h2>${escapeHtml34(capability.label ?? capability.provider)}</h2>
20921
21187
  </div>
20922
- <strong>${escapeHtml33(capability.status)}</strong>
21188
+ <strong>${escapeHtml34(capability.status)}</strong>
20923
21189
  </div>
20924
- ${capability.description ? `<p>${escapeHtml33(capability.description)}</p>` : ""}
21190
+ ${capability.description ? `<p>${escapeHtml34(capability.description)}</p>` : ""}
20925
21191
  <dl>
20926
21192
  <div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
20927
21193
  <div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
20928
- <div><dt>Model</dt><dd>${escapeHtml33(capability.model ?? "default")}</dd></div>
21194
+ <div><dt>Model</dt><dd>${escapeHtml34(capability.model ?? "default")}</dd></div>
20929
21195
  <div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
20930
21196
  <div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
20931
21197
  </dl>
20932
21198
  ${features ? `<div class="features">${features}</div>` : ""}
20933
21199
  </article>`;
20934
21200
  }).join("");
20935
- 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,.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>${escapeHtml33(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>`;
21201
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml34(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.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>${escapeHtml34(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>`;
20936
21202
  };
20937
21203
  var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
20938
21204
  var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
@@ -20949,7 +21215,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
20949
21215
  var createVoiceProviderCapabilityRoutes = (options) => {
20950
21216
  const path = options.path ?? "/api/provider-capabilities";
20951
21217
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
20952
- const routes = new Elysia32({
21218
+ const routes = new Elysia33({
20953
21219
  name: options.name ?? "absolutejs-voice-provider-capabilities"
20954
21220
  }).get(path, createVoiceProviderCapabilityJSONHandler(options));
20955
21221
  if (htmlPath) {
@@ -20958,8 +21224,8 @@ var createVoiceProviderCapabilityRoutes = (options) => {
20958
21224
  return routes;
20959
21225
  };
20960
21226
  // src/resilienceRoutes.ts
20961
- import { Elysia as Elysia33 } from "elysia";
20962
- var escapeHtml34 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21227
+ import { Elysia as Elysia34 } from "elysia";
21228
+ var escapeHtml35 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
20963
21229
  var getString12 = (value) => typeof value === "string" ? value : undefined;
20964
21230
  var getNumber7 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
20965
21231
  var getBoolean2 = (value) => value === true;
@@ -21106,13 +21372,13 @@ var summarizeRoutingEvents = (events) => {
21106
21372
  };
21107
21373
  var renderProviderCards = (title, providers) => {
21108
21374
  if (providers.length === 0) {
21109
- return `<p class="muted">No ${escapeHtml34(title)} provider health yet.</p>`;
21375
+ return `<p class="muted">No ${escapeHtml35(title)} provider health yet.</p>`;
21110
21376
  }
21111
21377
  return `<div class="provider-grid">${providers.map((provider) => `
21112
- <article class="card provider ${escapeHtml34(provider.status)}">
21378
+ <article class="card provider ${escapeHtml35(provider.status)}">
21113
21379
  <div class="card-header">
21114
- <strong>${escapeHtml34(provider.provider)}</strong>
21115
- <span>${escapeHtml34(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
21380
+ <strong>${escapeHtml35(provider.provider)}</strong>
21381
+ <span>${escapeHtml35(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
21116
21382
  </div>
21117
21383
  <dl>
21118
21384
  <div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
@@ -21121,7 +21387,7 @@ var renderProviderCards = (title, providers) => {
21121
21387
  <div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
21122
21388
  <div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
21123
21389
  </dl>
21124
- ${provider.lastError ? `<p class="muted">${escapeHtml34(provider.lastError)}</p>` : ""}
21390
+ ${provider.lastError ? `<p class="muted">${escapeHtml35(provider.lastError)}</p>` : ""}
21125
21391
  </article>
21126
21392
  `).join("")}</div>`;
21127
21393
  };
@@ -21130,24 +21396,24 @@ var renderTimeline2 = (events) => {
21130
21396
  return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
21131
21397
  }
21132
21398
  return `<div class="timeline">${events.slice(0, 40).map((event) => `
21133
- <article class="card event ${escapeHtml34(event.status ?? "unknown")}">
21399
+ <article class="card event ${escapeHtml35(event.status ?? "unknown")}">
21134
21400
  <div class="card-header">
21135
- <strong>${escapeHtml34(event.kind.toUpperCase())} ${escapeHtml34(event.operation ?? "generate")}</strong>
21401
+ <strong>${escapeHtml35(event.kind.toUpperCase())} ${escapeHtml35(event.operation ?? "generate")}</strong>
21136
21402
  <span>${new Date(event.at).toLocaleString()}</span>
21137
21403
  </div>
21138
21404
  <p>
21139
- <span class="pill">${escapeHtml34(event.status ?? "unknown")}</span>
21140
- <span class="pill">provider: ${escapeHtml34(event.provider ?? "unknown")}</span>
21141
- ${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml34(event.fallbackProvider)}</span>` : ""}
21405
+ <span class="pill">${escapeHtml35(event.status ?? "unknown")}</span>
21406
+ <span class="pill">provider: ${escapeHtml35(event.provider ?? "unknown")}</span>
21407
+ ${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml35(event.fallbackProvider)}</span>` : ""}
21142
21408
  ${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
21143
21409
  </p>
21144
21410
  <dl>
21145
21411
  <div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
21146
21412
  <div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
21147
21413
  <div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
21148
- <div><dt>Session</dt><dd>${escapeHtml34(event.sessionId)}</dd></div>
21414
+ <div><dt>Session</dt><dd>${escapeHtml35(event.sessionId)}</dd></div>
21149
21415
  </dl>
21150
- ${event.error ? `<p class="muted">${escapeHtml34(event.error)}</p>` : ""}
21416
+ ${event.error ? `<p class="muted">${escapeHtml35(event.error)}</p>` : ""}
21151
21417
  </article>
21152
21418
  `).join("")}</div>`;
21153
21419
  };
@@ -21157,9 +21423,9 @@ var renderSessionKind = (kind, summary) => {
21157
21423
  const status = latest?.status ?? "idle";
21158
21424
  const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
21159
21425
  return `<div>
21160
- <dt>${escapeHtml34(kind.toUpperCase())}</dt>
21161
- <dd>${escapeHtml34(provider)}${escapeHtml34(fallback)}</dd>
21162
- <small>${escapeHtml34(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>
21426
+ <dt>${escapeHtml35(kind.toUpperCase())}</dt>
21427
+ <dd>${escapeHtml35(provider)}${escapeHtml35(fallback)}</dd>
21428
+ <small>${escapeHtml35(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>
21163
21429
  </div>`;
21164
21430
  };
21165
21431
  var renderSessionSummaries = (sessions) => {
@@ -21167,10 +21433,10 @@ var renderSessionSummaries = (sessions) => {
21167
21433
  return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
21168
21434
  }
21169
21435
  return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
21170
- <article class="card session ${escapeHtml34(session.status)}">
21436
+ <article class="card session ${escapeHtml35(session.status)}">
21171
21437
  <div class="card-header">
21172
- <strong>${escapeHtml34(session.sessionId)}</strong>
21173
- <span>${escapeHtml34(session.status)}</span>
21438
+ <strong>${escapeHtml35(session.sessionId)}</strong>
21439
+ <span>${escapeHtml35(session.status)}</span>
21174
21440
  </div>
21175
21441
  <p>
21176
21442
  <span class="pill">${session.eventCount} routing events</span>
@@ -21197,21 +21463,21 @@ var renderSimulationControls = (kind, simulation) => {
21197
21463
  const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
21198
21464
  const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
21199
21465
  const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
21200
- return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml34(pathPrefix)}">
21201
- <p class="muted">${escapeHtml34(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
21466
+ return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml35(pathPrefix)}">
21467
+ <p class="muted">${escapeHtml35(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
21202
21468
  <div class="simulate-actions">
21203
- ${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml34(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml34(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
21204
- ${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml34(provider.provider)}">Mark ${escapeHtml34(provider.provider)} recovered</button>`).join("")}
21469
+ ${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml35(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml35(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
21470
+ ${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml35(provider.provider)}">Mark ${escapeHtml35(provider.provider)} recovered</button>`).join("")}
21205
21471
  </div>
21206
- ${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml34(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
21472
+ ${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml35(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
21207
21473
  <pre class="simulate-output" hidden></pre>
21208
21474
  </div>`;
21209
21475
  };
21210
21476
  var renderVoiceResilienceHTML = (input) => {
21211
21477
  const summary = summarizeRoutingEvents(input.routingEvents);
21212
- const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml34(kind)}: ${String(count)}</span>`).join("");
21213
- const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml34(link.href)}">${escapeHtml34(link.label)}</a>`).join(" \xB7 ") : "";
21214
- const snippet = escapeHtml34(`const sttSimulator = createVoiceIOProviderFailureSimulator({
21478
+ const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml35(kind)}: ${String(count)}</span>`).join("");
21479
+ const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml35(link.href)}">${escapeHtml35(link.label)}</a>`).join(" \xB7 ") : "";
21480
+ const snippet = escapeHtml35(`const sttSimulator = createVoiceIOProviderFailureSimulator({
21215
21481
  kind: 'stt',
21216
21482
  providers: ['deepgram', 'assemblyai'],
21217
21483
  fallback: ['deepgram', 'assemblyai'],
@@ -21249,7 +21515,7 @@ app.use(
21249
21515
  <head>
21250
21516
  <meta charset="utf-8" />
21251
21517
  <meta name="viewport" content="width=device-width, initial-scale=1" />
21252
- <title>${escapeHtml34(input.title ?? "AbsoluteJS Voice Resilience")}</title>
21518
+ <title>${escapeHtml35(input.title ?? "AbsoluteJS Voice Resilience")}</title>
21253
21519
  <style>
21254
21520
  :root { color-scheme: dark; }
21255
21521
  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; }
@@ -21401,7 +21667,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
21401
21667
  };
21402
21668
  var createVoiceResilienceRoutes = (options) => {
21403
21669
  const path = options.path ?? "/resilience";
21404
- const routes = new Elysia33({
21670
+ const routes = new Elysia34({
21405
21671
  name: options.name ?? "absolutejs-voice-resilience"
21406
21672
  }).get(path, async () => {
21407
21673
  const events = await options.store.list();
@@ -21479,8 +21745,8 @@ var assertVoiceProviderRoutingContract = async (options) => {
21479
21745
  return report;
21480
21746
  };
21481
21747
  // src/productionReadiness.ts
21482
- import { Elysia as Elysia34 } from "elysia";
21483
- var escapeHtml35 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21748
+ import { Elysia as Elysia35 } from "elysia";
21749
+ var escapeHtml36 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21484
21750
  var rollupStatus2 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
21485
21751
  var readinessGateCodes = {
21486
21752
  "Agent squad contracts": "voice.readiness.agent_squad_contracts",
@@ -22431,22 +22697,22 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
22431
22697
  var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
22432
22698
  var renderVoiceProductionReadinessHTML = (report, options = {}) => {
22433
22699
  const title = options.title ?? "AbsoluteJS Voice Production Readiness";
22434
- const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml35(report.profile.name)}</h2><p>${escapeHtml35(report.profile.description)}</p><p>${escapeHtml35(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="${escapeHtml35(surface.href)}">${escapeHtml35(surface.label)}</a>` : escapeHtml35(surface.label)}</strong></article>`).join("")}</div></section>` : "";
22700
+ const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml36(report.profile.name)}</h2><p>${escapeHtml36(report.profile.description)}</p><p>${escapeHtml36(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="${escapeHtml36(surface.href)}">${escapeHtml36(surface.label)}</a>` : escapeHtml36(surface.label)}</strong></article>`).join("")}</div></section>` : "";
22435
22701
  const checks = report.checks.map((check, index) => {
22436
- const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml35(action.href)}">${escapeHtml35(action.label)}</button>` : `<a href="${escapeHtml35(action.href)}">${escapeHtml35(action.label)}</a>`).join("");
22437
- return `<article class="check ${escapeHtml35(check.status)}">
22702
+ const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml36(action.href)}">${escapeHtml36(action.label)}</button>` : `<a href="${escapeHtml36(action.href)}">${escapeHtml36(action.label)}</a>`).join("");
22703
+ return `<article class="check ${escapeHtml36(check.status)}">
22438
22704
  <div>
22439
- <span>${escapeHtml35(check.status.toUpperCase())}</span>
22440
- <h2>${escapeHtml35(check.label)}</h2>
22441
- ${check.detail ? `<p>${escapeHtml35(check.detail)}</p>` : ""}
22442
- ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml35(check.proofSource.href)}">${escapeHtml35(check.proofSource.sourceLabel)}</a>` : escapeHtml35(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml35(check.proofSource.detail)}` : ""}</p>` : ""}
22705
+ <span>${escapeHtml36(check.status.toUpperCase())}</span>
22706
+ <h2>${escapeHtml36(check.label)}</h2>
22707
+ ${check.detail ? `<p>${escapeHtml36(check.detail)}</p>` : ""}
22708
+ ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml36(check.proofSource.href)}">${escapeHtml36(check.proofSource.sourceLabel)}</a>` : escapeHtml36(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml36(check.proofSource.detail)}` : ""}</p>` : ""}
22443
22709
  ${actions ? `<p class="actions">${actions}</p>` : ""}
22444
22710
  </div>
22445
- <strong>${escapeHtml35(String(check.value ?? check.status))}</strong>
22446
- ${check.href ? `<a href="${escapeHtml35(check.href)}">Open surface</a>` : ""}
22711
+ <strong>${escapeHtml36(String(check.value ?? check.status))}</strong>
22712
+ ${check.href ? `<a href="${escapeHtml36(check.href)}">Open surface</a>` : ""}
22447
22713
  </article>`;
22448
22714
  }).join("");
22449
- const snippet = escapeHtml35(`createVoiceProductionReadinessRoutes({
22715
+ const snippet = escapeHtml36(`createVoiceProductionReadinessRoutes({
22450
22716
  htmlPath: '/production-readiness',
22451
22717
  path: '/api/production-readiness',
22452
22718
  gatePath: '/api/production-readiness/gate',
@@ -22462,13 +22728,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
22462
22728
  providerRoutingContracts: loadProviderRoutingContracts,
22463
22729
  store: traceStore
22464
22730
  });`);
22465
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml35(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 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>${escapeHtml35(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 ${escapeHtml35(report.status)}">Overall: ${escapeHtml35(report.status.toUpperCase())}</p><p>Checked ${escapeHtml35(new Date(report.checkedAt).toLocaleString())}</p></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>`;
22731
+ 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:#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 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>${escapeHtml36(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 ${escapeHtml36(report.status)}">Overall: ${escapeHtml36(report.status.toUpperCase())}</p><p>Checked ${escapeHtml36(new Date(report.checkedAt).toLocaleString())}</p></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>`;
22466
22732
  };
22467
22733
  var createVoiceProductionReadinessRoutes = (options) => {
22468
22734
  const path = options.path ?? "/api/production-readiness";
22469
22735
  const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
22470
22736
  const htmlPath = options.htmlPath ?? "/production-readiness";
22471
- const routes = new Elysia34({
22737
+ const routes = new Elysia35({
22472
22738
  name: options.name ?? "absolutejs-voice-production-readiness"
22473
22739
  });
22474
22740
  routes.get(path, async ({ query, request }) => buildVoiceProductionReadinessReport(options, { query, request }));
@@ -22832,8 +23098,8 @@ var recommendVoiceReadinessProfile = (options) => {
22832
23098
  };
22833
23099
  };
22834
23100
  // src/providerStackRecommendations.ts
22835
- import { Elysia as Elysia35 } from "elysia";
22836
- var escapeHtml36 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23101
+ import { Elysia as Elysia36 } from "elysia";
23102
+ var escapeHtml37 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
22837
23103
  var profileProviderPriorities = {
22838
23104
  "meeting-recorder": {
22839
23105
  llm: ["openai", "anthropic", "gemini"],
@@ -23076,17 +23342,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
23076
23342
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
23077
23343
  const title = options.title ?? "Voice Provider Contract Matrix";
23078
23344
  const rows = report.rows.map((row) => {
23079
- const checks = row.checks.map((check) => `<li class="${escapeHtml36(check.status)}"><strong>${escapeHtml36(check.label)}</strong><span>${escapeHtml36(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml36(check.remediation.href)}">${escapeHtml36(check.remediation.label)}</a>` : escapeHtml36(check.remediation.label)}: ${escapeHtml36(check.remediation.detail)}</em>` : ""}</li>`).join("");
23080
- return `<article class="row ${escapeHtml36(row.status)}">
23345
+ const checks = row.checks.map((check) => `<li class="${escapeHtml37(check.status)}"><strong>${escapeHtml37(check.label)}</strong><span>${escapeHtml37(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml37(check.remediation.href)}">${escapeHtml37(check.remediation.label)}</a>` : escapeHtml37(check.remediation.label)}: ${escapeHtml37(check.remediation.detail)}</em>` : ""}</li>`).join("");
23346
+ return `<article class="row ${escapeHtml37(row.status)}">
23081
23347
  <div>
23082
- <p class="eyebrow">${escapeHtml36(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
23083
- <h2>${escapeHtml36(row.provider)}</h2>
23084
- <p class="status ${escapeHtml36(row.status)}">${escapeHtml36(row.status.toUpperCase())}</p>
23348
+ <p class="eyebrow">${escapeHtml37(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
23349
+ <h2>${escapeHtml37(row.provider)}</h2>
23350
+ <p class="status ${escapeHtml37(row.status)}">${escapeHtml37(row.status.toUpperCase())}</p>
23085
23351
  </div>
23086
23352
  <ul>${checks}</ul>
23087
23353
  </article>`;
23088
23354
  }).join("");
23089
- const snippet = escapeHtml36(`const providerContracts = () =>
23355
+ const snippet = escapeHtml37(`const providerContracts = () =>
23090
23356
  createVoiceProviderContractMatrixPreset('phone-agent', {
23091
23357
  env: process.env,
23092
23358
  providers: {
@@ -23107,7 +23373,7 @@ createVoiceProductionReadinessRoutes({
23107
23373
  providerContractMatrix: () =>
23108
23374
  buildVoiceProviderContractMatrix(providerContracts())
23109
23375
  });`);
23110
- 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:#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>${escapeHtml36(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>`;
23376
+ 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:#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>${escapeHtml37(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>`;
23111
23377
  };
23112
23378
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
23113
23379
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -23122,7 +23388,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
23122
23388
  var createVoiceProviderContractMatrixRoutes = (options) => {
23123
23389
  const path = options.path ?? "/api/provider-contracts";
23124
23390
  const htmlPath = options.htmlPath ?? "/provider-contracts";
23125
- const routes = new Elysia35({
23391
+ const routes = new Elysia36({
23126
23392
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
23127
23393
  });
23128
23394
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -23181,7 +23447,7 @@ var evaluateVoiceProviderStackGaps = (input) => {
23181
23447
  };
23182
23448
  };
23183
23449
  // src/opsConsoleRoutes.ts
23184
- import { Elysia as Elysia36 } from "elysia";
23450
+ import { Elysia as Elysia37 } from "elysia";
23185
23451
  var DEFAULT_LINKS = [
23186
23452
  {
23187
23453
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -23216,7 +23482,7 @@ var DEFAULT_LINKS = [
23216
23482
  label: "Handoffs"
23217
23483
  }
23218
23484
  ];
23219
- var escapeHtml37 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23485
+ var escapeHtml38 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23220
23486
  var countProviderStatuses = (providers) => {
23221
23487
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
23222
23488
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -23285,20 +23551,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
23285
23551
  trace
23286
23552
  };
23287
23553
  };
23288
- var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml37(input.label)}</span><strong>${escapeHtml37(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml37(input.status)}">${escapeHtml37(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml37(input.href)}">Open</a>` : ""}</article>`;
23554
+ var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml38(input.label)}</span><strong>${escapeHtml38(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml38(input.status)}">${escapeHtml38(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml38(input.href)}">Open</a>` : ""}</article>`;
23289
23555
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
23290
23556
  const links = report.links.map((link) => `<article class="surface">
23291
- <div><h2>${escapeHtml37(link.label)}</h2>${link.description ? `<p>${escapeHtml37(link.description)}</p>` : ""}</div>
23292
- <p><a href="${escapeHtml37(link.href)}">Open ${escapeHtml37(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml37(link.statusHref)}">Status</a>` : ""}</p>
23557
+ <div><h2>${escapeHtml38(link.label)}</h2>${link.description ? `<p>${escapeHtml38(link.description)}</p>` : ""}</div>
23558
+ <p><a href="${escapeHtml38(link.href)}">Open ${escapeHtml38(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml38(link.statusHref)}">Status</a>` : ""}</p>
23293
23559
  </article>`).join("");
23294
- const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml37(session.sessionId)}</td><td>${escapeHtml37(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml37(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
23295
- const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml37(event.kind)}</td><td>${escapeHtml37(event.provider ?? "unknown")}</td><td>${escapeHtml37(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml37(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
23560
+ const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml38(session.sessionId)}</td><td>${escapeHtml38(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml38(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
23561
+ const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml38(event.kind)}</td><td>${escapeHtml38(event.provider ?? "unknown")}</td><td>${escapeHtml38(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml38(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
23296
23562
  const title = options.title ?? "AbsoluteJS Voice Ops Console";
23297
- 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{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>${escapeHtml37(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 ${escapeHtml37(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>`;
23563
+ 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{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>${escapeHtml38(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 ${escapeHtml38(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>`;
23298
23564
  };
23299
23565
  var createVoiceOpsConsoleRoutes = (options) => {
23300
23566
  const path = options.path ?? "/ops-console";
23301
- const routes = new Elysia36({
23567
+ const routes = new Elysia37({
23302
23568
  name: options.name ?? "absolutejs-voice-ops-console"
23303
23569
  });
23304
23570
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -23315,11 +23581,11 @@ var createVoiceOpsConsoleRoutes = (options) => {
23315
23581
  return routes;
23316
23582
  };
23317
23583
  // src/operationsRecord.ts
23318
- import { Elysia as Elysia38 } from "elysia";
23584
+ import { Elysia as Elysia39 } from "elysia";
23319
23585
 
23320
23586
  // src/traceTimeline.ts
23321
- import { Elysia as Elysia37 } from "elysia";
23322
- var escapeHtml38 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23587
+ import { Elysia as Elysia38 } from "elysia";
23588
+ var escapeHtml39 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23323
23589
  var getString14 = (value) => typeof value === "string" && value.trim() ? value : undefined;
23324
23590
  var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
23325
23591
  var firstString3 = (payload, keys) => {
@@ -23487,16 +23753,16 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
23487
23753
  };
23488
23754
  };
23489
23755
  var formatMs3 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
23490
- 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>${escapeHtml38(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs3(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs3(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>`;
23756
+ 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>${escapeHtml39(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs3(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs3(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>`;
23491
23757
  var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
23492
- const events = session.events.map((event) => `<tr class="${escapeHtml38(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml38(event.type)}</td><td>${escapeHtml38(event.label)}</td><td>${escapeHtml38(event.provider ?? "")}</td><td>${escapeHtml38(event.status ?? "")}</td><td>${formatMs3(event.elapsedMs)}</td></tr>`).join("");
23493
- const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml38(issue.severity)}">${escapeHtml38(issue.code)}: ${escapeHtml38(issue.message)}</li>`).join("") : "<li>none</li>";
23494
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(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>${escapeHtml38(session.sessionId)}</h1><p class="status ${escapeHtml38(session.status)}">${escapeHtml38(session.status)}</p></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>${formatMs3(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>`;
23758
+ const events = session.events.map((event) => `<tr class="${escapeHtml39(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml39(event.type)}</td><td>${escapeHtml39(event.label)}</td><td>${escapeHtml39(event.provider ?? "")}</td><td>${escapeHtml39(event.status ?? "")}</td><td>${formatMs3(event.elapsedMs)}</td></tr>`).join("");
23759
+ const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml39(issue.severity)}">${escapeHtml39(issue.code)}: ${escapeHtml39(issue.message)}</li>`).join("") : "<li>none</li>";
23760
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(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>${escapeHtml39(session.sessionId)}</h1><p class="status ${escapeHtml39(session.status)}">${escapeHtml39(session.status)}</p></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>${formatMs3(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>`;
23495
23761
  };
23496
- var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml38(session.status)}"><td><a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml38(session.sessionId)}</a></td><td>${escapeHtml38(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs3(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml38(provider.provider)).join(", ")}</td></tr>`).join("");
23762
+ var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml39(session.status)}"><td><a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml39(session.sessionId)}</a></td><td>${escapeHtml39(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs3(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml39(provider.provider)).join(", ")}</td></tr>`).join("");
23497
23763
  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}}";
23498
23764
  var renderVoiceTraceTimelineHTML = (report, options = {}) => {
23499
- const snippet = escapeHtml38(`const traceStore = createVoiceTraceSinkStore({
23765
+ const snippet = escapeHtml39(`const traceStore = createVoiceTraceSinkStore({
23500
23766
  store: runtimeStorage.traces,
23501
23767
  sinks: [
23502
23768
  createVoiceTraceHTTPSink({
@@ -23522,13 +23788,13 @@ app.use(
23522
23788
  traceDeliveries: runtimeStorage.traceDeliveries
23523
23789
  })
23524
23790
  );`);
23525
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(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>${escapeHtml38(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>`;
23791
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(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>${escapeHtml39(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>`;
23526
23792
  };
23527
23793
  var createVoiceTraceTimelineRoutes = (options) => {
23528
23794
  const path = options.path ?? "/api/voice-traces";
23529
23795
  const htmlPath = options.htmlPath ?? "/traces";
23530
23796
  const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
23531
- const routes = new Elysia37({
23797
+ const routes = new Elysia38({
23532
23798
  name: options.name ?? "absolutejs-voice-trace-timelines"
23533
23799
  });
23534
23800
  const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
@@ -23682,16 +23948,16 @@ var buildVoiceOperationsRecord = async (options) => {
23682
23948
  traceEvents
23683
23949
  };
23684
23950
  };
23685
- var escapeHtml39 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23951
+ var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23686
23952
  var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
23687
23953
  var renderVoiceOperationsRecordHTML = (record, options = {}) => {
23688
- const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml39(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs4(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
23689
- const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml39(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml39(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml39(handoff.status ?? "")}</span><p>${escapeHtml39(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
23690
- const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml39(tool.toolName ?? "tool")}</strong> <span>${escapeHtml39(tool.status ?? "")}</span> ${formatMs4(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml39(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
23691
- const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml39(review.title)}</strong> <span>${escapeHtml39(review.summary.outcome ?? "")}</span><p>${escapeHtml39(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
23692
- const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml39(task.title)}</strong> <span>${escapeHtml39(task.status)}</span><p>${escapeHtml39(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
23693
- const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml39(event.type)}</strong> <span>${escapeHtml39(event.deliveryStatus ?? "local")}</span><p>${escapeHtml39(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
23694
- const snippet = escapeHtml39(`app.use(
23954
+ const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml40(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs4(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
23955
+ const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml40(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml40(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml40(handoff.status ?? "")}</span><p>${escapeHtml40(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
23956
+ const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml40(tool.toolName ?? "tool")}</strong> <span>${escapeHtml40(tool.status ?? "")}</span> ${formatMs4(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml40(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
23957
+ const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml40(review.title)}</strong> <span>${escapeHtml40(review.summary.outcome ?? "")}</span><p>${escapeHtml40(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
23958
+ const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml40(task.title)}</strong> <span>${escapeHtml40(task.status)}</span><p>${escapeHtml40(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
23959
+ const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml40(event.type)}</strong> <span>${escapeHtml40(event.deliveryStatus ?? "local")}</span><p>${escapeHtml40(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
23960
+ const snippet = escapeHtml40(`app.use(
23695
23961
  createVoiceOperationsRecordRoutes({
23696
23962
  audit: auditStore,
23697
23963
  integrationEvents: opsEvents,
@@ -23705,12 +23971,12 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
23705
23971
  tasks: opsTasks
23706
23972
  })
23707
23973
  );`);
23708
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(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{color:#a9b4bd}.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}</style></head><body><main><p class="eyebrow">Portable production proof</p><h1>${escapeHtml39(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml39(record.status)}">${escapeHtml39(record.status)}</p><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>${formatMs4(record.summary.callDurationMs)}</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="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, audit, latency, replay, reviews, tasks, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Providers</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>`;
23974
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(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{color:#a9b4bd}.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}</style></head><body><main><p class="eyebrow">Portable production proof</p><h1>${escapeHtml40(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml40(record.status)}">${escapeHtml40(record.status)}</p><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>${formatMs4(record.summary.callDurationMs)}</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="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, audit, latency, replay, reviews, tasks, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Providers</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>`;
23709
23975
  };
23710
23976
  var createVoiceOperationsRecordRoutes = (options) => {
23711
23977
  const path = options.path ?? "/api/voice-operations/:sessionId";
23712
23978
  const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
23713
- const routes = new Elysia38({
23979
+ const routes = new Elysia39({
23714
23980
  name: options.name ?? "absolutejs-voice-operations-record"
23715
23981
  });
23716
23982
  const buildRecord = (sessionId) => buildVoiceOperationsRecord({
@@ -23742,8 +24008,248 @@ var createVoiceOperationsRecordRoutes = (options) => {
23742
24008
  }
23743
24009
  return routes;
23744
24010
  };
24011
+ // src/opsRecovery.ts
24012
+ import { Elysia as Elysia40 } from "elysia";
24013
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24014
+ var getString16 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
24015
+ var hrefForSession = (value, sessionId) => typeof value === "function" ? value(sessionId) : value;
24016
+ var rollupStatus3 = (issues) => issues.some((issue) => issue.severity === "fail") ? "fail" : issues.some((issue) => issue.severity === "warn") ? "warn" : "pass";
24017
+ var providerUnresolved = (provider) => provider.status === "degraded" || provider.status === "rate-limited" || provider.status === "suppressed";
24018
+ var collectFailedSessions = (events, limit) => events.filter((event) => {
24019
+ if (event.type !== "session.error") {
24020
+ return false;
24021
+ }
24022
+ const providerStatus = event.payload.providerStatus;
24023
+ return providerStatus !== "success" && providerStatus !== "fallback";
24024
+ }).sort((left, right) => right.at - left.at).slice(0, limit).map((event) => ({
24025
+ at: event.at,
24026
+ error: getString16(event.payload.error),
24027
+ provider: getString16(event.payload.provider),
24028
+ sessionId: event.sessionId,
24029
+ traceId: event.traceId
24030
+ }));
24031
+ var collectInterventions = (events, limit) => {
24032
+ const interventionEvents = events.filter((event) => event.type === "operator.action").sort((left, right) => right.at - left.at);
24033
+ return {
24034
+ events: interventionEvents.slice(0, limit).map((event) => ({
24035
+ action: getString16(event.payload.action),
24036
+ at: event.at,
24037
+ operatorId: getString16(event.payload.operatorId) ?? getString16(event.payload.actorId),
24038
+ sessionId: event.sessionId,
24039
+ traceId: event.traceId
24040
+ })),
24041
+ total: interventionEvents.length
24042
+ };
24043
+ };
24044
+ var addDeliveryIssues = (issues, input) => {
24045
+ if (!input.summary) {
24046
+ return;
24047
+ }
24048
+ const failed = input.summary.failed + input.summary.deadLettered;
24049
+ if (failed > 0) {
24050
+ issues.push({
24051
+ code: input.failedCode,
24052
+ detail: `${failed} failed or dead-lettered delivery record(s).`,
24053
+ href: input.href,
24054
+ label: input.failedLabel,
24055
+ severity: "fail",
24056
+ value: failed
24057
+ });
24058
+ }
24059
+ const pending = input.summary.pending + input.summary.retryEligible;
24060
+ if (pending > 0) {
24061
+ issues.push({
24062
+ code: input.pendingCode,
24063
+ detail: `${pending} pending or retry-eligible delivery record(s).`,
24064
+ href: input.href,
24065
+ label: input.pendingLabel,
24066
+ severity: "warn",
24067
+ value: pending
24068
+ });
24069
+ }
24070
+ };
24071
+ var buildVoiceOpsRecoveryReport = async (options = {}) => {
24072
+ const limit = options.limit ?? 50;
24073
+ const events = options.events ?? await options.traces?.list({ limit: Math.max(limit, 500) }) ?? [];
24074
+ const providers = await summarizeVoiceProviderHealth({
24075
+ events,
24076
+ providers: options.providers
24077
+ });
24078
+ const auditDeliveries = options.auditDeliveries ? await summarizeVoiceAuditSinkDeliveries(await options.auditDeliveries.list(), {
24079
+ deadLetters: options.auditDeliveryDeadLetters
24080
+ }) : undefined;
24081
+ const traceDeliveries = options.traceDeliveries ? await summarizeVoiceTraceSinkDeliveries(await options.traceDeliveries.list(), {
24082
+ deadLetters: options.traceDeliveryDeadLetters
24083
+ }) : undefined;
24084
+ const handoffDeliveries = options.handoffDeliveries ? await summarizeVoiceHandoffDeliveries(await options.handoffDeliveries.list(), {
24085
+ deadLetters: options.handoffDeliveryDeadLetters
24086
+ }) : undefined;
24087
+ const latency = options.latency === false ? undefined : await buildVoiceLatencySLOGate({
24088
+ events,
24089
+ ...options.latency ?? {}
24090
+ });
24091
+ const failedSessions = collectFailedSessions(events, limit);
24092
+ const interventions = collectInterventions(events, limit);
24093
+ const issues = [];
24094
+ const unresolvedProviders = providers.filter(providerUnresolved);
24095
+ for (const provider of unresolvedProviders) {
24096
+ issues.push({
24097
+ code: "voice.ops_recovery.provider_unresolved_failure",
24098
+ detail: provider.lastError ?? `${provider.provider} status is ${provider.status}.`,
24099
+ href: options.links?.providers,
24100
+ label: `Provider ${provider.provider} needs recovery`,
24101
+ severity: "fail",
24102
+ value: provider.status
24103
+ });
24104
+ }
24105
+ addDeliveryIssues(issues, {
24106
+ failedCode: "voice.ops_recovery.audit_delivery_failed",
24107
+ failedLabel: "Audit delivery failures",
24108
+ href: options.links?.auditDeliveries,
24109
+ pendingCode: "voice.ops_recovery.audit_delivery_pending",
24110
+ pendingLabel: "Audit delivery backlog",
24111
+ summary: auditDeliveries
24112
+ });
24113
+ addDeliveryIssues(issues, {
24114
+ failedCode: "voice.ops_recovery.trace_delivery_failed",
24115
+ failedLabel: "Trace delivery failures",
24116
+ href: options.links?.traceDeliveries,
24117
+ pendingCode: "voice.ops_recovery.trace_delivery_pending",
24118
+ pendingLabel: "Trace delivery backlog",
24119
+ summary: traceDeliveries
24120
+ });
24121
+ addDeliveryIssues(issues, {
24122
+ failedCode: "voice.ops_recovery.handoff_failed",
24123
+ failedLabel: "Handoff delivery failures",
24124
+ href: options.links?.handoffs,
24125
+ pendingCode: "voice.ops_recovery.handoff_pending",
24126
+ pendingLabel: "Handoff delivery backlog",
24127
+ summary: handoffDeliveries
24128
+ });
24129
+ if (latency?.failed) {
24130
+ issues.push({
24131
+ code: "voice.ops_recovery.latency_slo_failed",
24132
+ detail: `${latency.failed} latency SLO measurement(s) failed.`,
24133
+ href: options.links?.traces ? hrefForSession(options.links.traces, latency.measurements[0]?.sessionId ?? "") : undefined,
24134
+ label: "Latency SLO failures",
24135
+ severity: "fail",
24136
+ value: latency.failed
24137
+ });
24138
+ } else if (latency?.warnings) {
24139
+ issues.push({
24140
+ code: "voice.ops_recovery.latency_slo_warn",
24141
+ detail: `${latency.warnings} latency SLO measurement(s) are warning.`,
24142
+ label: "Latency SLO warnings",
24143
+ severity: "warn",
24144
+ value: latency.warnings
24145
+ });
24146
+ }
24147
+ return {
24148
+ auditDeliveries,
24149
+ checkedAt: Date.now(),
24150
+ failedSessions,
24151
+ handoffDeliveries,
24152
+ interventions,
24153
+ issues,
24154
+ latency,
24155
+ providers: {
24156
+ healthy: providers.filter((provider) => provider.status === "healthy").length,
24157
+ providers,
24158
+ recoveredFallbacks: providers.reduce((total, provider) => total + provider.fallbackCount, 0),
24159
+ unresolvedFailures: unresolvedProviders.length
24160
+ },
24161
+ status: rollupStatus3(issues),
24162
+ traceDeliveries
24163
+ };
24164
+ };
24165
+ var buildVoiceOpsRecoveryReadinessCheck = (report, options = {}) => ({
24166
+ detail: report.status === "pass" ? `${report.providers.recoveredFallbacks} recovered fallback(s), ${report.interventions.total} operator intervention(s), and no unresolved recovery issues.` : `${report.issues.length} recovery issue(s) require attention.`,
24167
+ href: options.href,
24168
+ label: options.label ?? "Ops recovery",
24169
+ status: report.status,
24170
+ value: report.issues.length
24171
+ });
24172
+ var renderVoiceOpsRecoveryMarkdown = (report, options = {}) => {
24173
+ const title = options.title ?? "Voice Ops Recovery";
24174
+ const issueRows = report.issues.map((issue) => `| ${issue.severity} | ${issue.code} | ${issue.label} | ${issue.value ?? ""} | ${issue.detail ?? ""} |`).join(`
24175
+ `);
24176
+ const providers = report.providers.providers.map((provider) => `| ${provider.provider} | ${provider.status} | ${provider.runCount} | ${provider.errorCount} | ${provider.fallbackCount} | ${provider.lastError ?? ""} |`).join(`
24177
+ `);
24178
+ const failedSessions = report.failedSessions.map((session) => `- ${session.sessionId}${session.provider ? ` via ${session.provider}` : ""}${session.error ? `: ${session.error}` : ""}`).join(`
24179
+ `);
24180
+ return `# ${title}
24181
+
24182
+ Status: ${report.status}
24183
+
24184
+ Checked at: ${new Date(report.checkedAt).toISOString()}
24185
+
24186
+ Recovered fallbacks: ${report.providers.recoveredFallbacks}
24187
+ Unresolved provider failures: ${report.providers.unresolvedFailures}
24188
+ Operator interventions: ${report.interventions.total}
24189
+
24190
+ ## Issues
24191
+
24192
+ | Severity | Code | Label | Value | Detail |
24193
+ | --- | --- | --- | ---: | --- |
24194
+ ${issueRows || "| pass | none | No recovery issues | 0 | |"}
24195
+
24196
+ ## Providers
24197
+
24198
+ | Provider | Status | Runs | Errors | Fallbacks | Last error |
24199
+ | --- | --- | ---: | ---: | ---: | --- |
24200
+ ${providers || "| none | idle | 0 | 0 | 0 | |"}
24201
+
24202
+ ## Failed Sessions
24203
+
24204
+ ${failedSessions || "None."}
24205
+
24206
+ ## Latency
24207
+
24208
+ ${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
24209
+ `;
24210
+ };
24211
+ var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml41(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>${escapeHtml41(label)}</span><strong>not configured</strong></article>`;
24212
+ var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
24213
+ const title = options.title ?? "Voice Ops Recovery";
24214
+ const issues = report.issues.map((issue) => `<tr><td>${escapeHtml41(issue.severity)}</td><td><code>${escapeHtml41(issue.code)}</code></td><td>${escapeHtml41(issue.label)}</td><td>${escapeHtml41(String(issue.value ?? ""))}</td><td>${escapeHtml41(issue.detail ?? "")}</td></tr>`).join("");
24215
+ const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml41(provider.provider)}</td><td>${escapeHtml41(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml41(provider.lastError ?? "")}</td></tr>`).join("");
24216
+ const failedSessions = report.failedSessions.map((session) => `<li>${escapeHtml41(session.sessionId)}${session.provider ? ` via ${escapeHtml41(session.provider)}` : ""}${session.error ? `: ${escapeHtml41(session.error)}` : ""}</li>`).join("");
24217
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{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>${escapeHtml41(title)}</h1><p><span class="status">${escapeHtml41(report.status)}</span> Checked ${escapeHtml41(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>${escapeHtml41(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>`;
24218
+ };
24219
+ var createVoiceOpsRecoveryRoutes = (options = {}) => {
24220
+ const path = options.path ?? "/api/voice/ops-recovery";
24221
+ const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
24222
+ const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
24223
+ const routes = new Elysia40({
24224
+ name: options.name ?? "absolutejs-voice-ops-recovery"
24225
+ }).get(path, async () => buildVoiceOpsRecoveryReport(options));
24226
+ if (htmlPath) {
24227
+ routes.get(htmlPath, async () => {
24228
+ const report = await buildVoiceOpsRecoveryReport(options);
24229
+ const render = options.render ?? renderVoiceOpsRecoveryHTML;
24230
+ return new Response(await render(report), {
24231
+ headers: {
24232
+ "content-type": "text/html; charset=utf-8",
24233
+ ...options.headers
24234
+ }
24235
+ });
24236
+ });
24237
+ }
24238
+ if (markdownPath) {
24239
+ routes.get(markdownPath, async () => {
24240
+ const report = await buildVoiceOpsRecoveryReport(options);
24241
+ return new Response(renderVoiceOpsRecoveryMarkdown(report, { title: options.title }), {
24242
+ headers: {
24243
+ "content-type": "text/markdown; charset=utf-8",
24244
+ ...options.headers
24245
+ }
24246
+ });
24247
+ });
24248
+ }
24249
+ return routes;
24250
+ };
23745
24251
  // src/incidentBundle.ts
23746
- import { Elysia as Elysia39 } from "elysia";
24252
+ import { Elysia as Elysia41 } from "elysia";
23747
24253
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
23748
24254
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
23749
24255
  return false;
@@ -23942,7 +24448,7 @@ var buildVoiceIncidentBundle = async (options) => {
23942
24448
  var createVoiceIncidentBundleRoutes = (options) => {
23943
24449
  const path = options.path ?? "/api/voice-incidents/:sessionId";
23944
24450
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
23945
- const routes = new Elysia39({
24451
+ const routes = new Elysia41({
23946
24452
  name: options.name ?? "absolutejs-voice-incident-bundle"
23947
24453
  });
23948
24454
  const getSessionId = (params) => params.sessionId ?? "";
@@ -24143,19 +24649,19 @@ var summarizeVoiceOpsStatus = async (options) => {
24143
24649
  };
24144
24650
  };
24145
24651
  // src/opsStatusRoutes.ts
24146
- import { Elysia as Elysia40 } from "elysia";
24147
- var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24652
+ import { Elysia as Elysia42 } from "elysia";
24653
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24148
24654
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
24149
24655
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
24150
24656
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
24151
24657
  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;
24152
- return `<article class="surface ${escapeHtml40(surface.status)}"><span>${escapeHtml40(surface.status.toUpperCase())}</span><h2>${escapeHtml40(key)}</h2><strong>${escapeHtml40(value)}</strong></article>`;
24658
+ return `<article class="surface ${escapeHtml42(surface.status)}"><span>${escapeHtml42(surface.status.toUpperCase())}</span><h2>${escapeHtml42(key)}</h2><strong>${escapeHtml42(value)}</strong></article>`;
24153
24659
  }).join("");
24154
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(title)}</title><style>body{background:#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>${escapeHtml40(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml40(report.status)}">Overall: ${escapeHtml40(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>`;
24660
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#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>${escapeHtml42(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(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>`;
24155
24661
  };
24156
24662
  var createVoiceOpsStatusRoutes = (options) => {
24157
24663
  const path = options.path ?? "/api/voice/ops-status";
24158
- const routes = new Elysia40({
24664
+ const routes = new Elysia42({
24159
24665
  name: options.name ?? "absolutejs-voice-ops-status"
24160
24666
  });
24161
24667
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -24588,9 +25094,9 @@ var createVoiceTTSProviderRouter = (options) => {
24588
25094
  };
24589
25095
  };
24590
25096
  // src/traceDeliveryRoutes.ts
24591
- import { Elysia as Elysia41 } from "elysia";
24592
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24593
- var getString16 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
25097
+ import { Elysia as Elysia43 } from "elysia";
25098
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
25099
+ var getString17 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
24594
25100
  var getNumber11 = (value) => {
24595
25101
  if (typeof value === "number" && Number.isFinite(value)) {
24596
25102
  return value;
@@ -24602,13 +25108,13 @@ var getNumber11 = (value) => {
24602
25108
  return;
24603
25109
  };
24604
25110
  var parseStatus2 = (value) => {
24605
- const text = getString16(value);
25111
+ const text = getString17(value);
24606
25112
  return text === "pending" || text === "delivered" || text === "failed" || text === "skipped" || text === "all" ? text : undefined;
24607
25113
  };
24608
25114
  var resolveVoiceTraceDeliveryFilter = (query = {}, base = {}) => ({
24609
25115
  ...base,
24610
25116
  limit: getNumber11(query.limit) ?? base.limit,
24611
- q: getString16(query.q) ?? base.q,
25117
+ q: getString17(query.q) ?? base.q,
24612
25118
  status: parseStatus2(query.status) ?? base.status
24613
25119
  });
24614
25120
  var deliverySearchText2 = (delivery) => [
@@ -24670,14 +25176,14 @@ var renderSinkResults2 = (delivery) => {
24670
25176
  if (entries.length === 0) {
24671
25177
  return "<p>No sink delivery attempts recorded yet.</p>";
24672
25178
  }
24673
- return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml41(sinkId)}</strong>: ${escapeHtml41(result.status)}${result.deliveredTo ? ` to ${escapeHtml41(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml41(result.error)})` : ""}</li>`).join("")}</ul>`;
25179
+ return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml43(sinkId)}</strong>: ${escapeHtml43(result.status)}${result.deliveredTo ? ` to ${escapeHtml43(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml43(result.error)})` : ""}</li>`).join("")}</ul>`;
24674
25180
  };
24675
- var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml41(event.type)} <small>${escapeHtml41(event.id)}</small>${event.sessionId ? ` session=${escapeHtml41(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
25181
+ var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml43(event.type)} <small>${escapeHtml43(event.id)}</small>${event.sessionId ? ` session=${escapeHtml43(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
24676
25182
  var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
24677
25183
  const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
24678
- const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml41(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
24679
- const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml41(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml41(delivery.deliveryStatus)}</span><h2>${escapeHtml41(delivery.id)}</h2><p>${escapeHtml41(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml41(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml41(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
24680
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#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>${escapeHtml41(title)}</h1><p>Checked ${escapeHtml41(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>`;
25184
+ const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml43(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
25185
+ const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml43(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml43(delivery.deliveryStatus)}</span><h2>${escapeHtml43(delivery.id)}</h2><p>${escapeHtml43(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml43(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml43(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
25186
+ 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:#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>${escapeHtml43(title)}</h1><p>Checked ${escapeHtml43(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>`;
24681
25187
  };
24682
25188
  var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
24683
25189
  var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
@@ -24697,7 +25203,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
24697
25203
  const path = options.path ?? "/api/voice-trace-deliveries";
24698
25204
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
24699
25205
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
24700
- const routes = new Elysia41({
25206
+ const routes = new Elysia43({
24701
25207
  name: options.name ?? "absolutejs-voice-trace-deliveries"
24702
25208
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
24703
25209
  if (htmlPath !== false) {
@@ -25321,7 +25827,7 @@ var createVoiceMemoryStore = () => {
25321
25827
  return { get, getOrCreate, list, remove, set };
25322
25828
  };
25323
25829
  // src/opsWebhook.ts
25324
- import { Elysia as Elysia42 } from "elysia";
25830
+ import { Elysia as Elysia44 } from "elysia";
25325
25831
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
25326
25832
  var signVoiceOpsWebhookBody = async (input) => {
25327
25833
  const encoder = new TextEncoder;
@@ -25451,7 +25957,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
25451
25957
  };
25452
25958
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
25453
25959
  const path = options.path ?? "/api/voice-ops/webhook";
25454
- return new Elysia42().post(path, async ({ body, request, set }) => {
25960
+ return new Elysia44().post(path, async ({ body, request, set }) => {
25455
25961
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
25456
25962
  if (options.signingSecret) {
25457
25963
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -26295,6 +26801,7 @@ export {
26295
26801
  withVoiceOpsTaskId,
26296
26802
  withVoiceIntegrationEventId,
26297
26803
  voiceTelephonyOutcomeToRouteResult,
26804
+ voiceComplianceRedactionDefaults,
26298
26805
  voice,
26299
26806
  verifyVoiceTwilioWebhookSignature,
26300
26807
  verifyVoiceTelnyxWebhookSignature,
@@ -26393,6 +26900,8 @@ export {
26393
26900
  renderVoicePhoneAgentProductionSmokeHTML,
26394
26901
  renderVoiceOutcomeContractHTML,
26395
26902
  renderVoiceOpsStatusHTML,
26903
+ renderVoiceOpsRecoveryMarkdown,
26904
+ renderVoiceOpsRecoveryHTML,
26396
26905
  renderVoiceOpsConsoleHTML,
26397
26906
  renderVoiceOpsActionHistoryHTML,
26398
26907
  renderVoiceOperationsRecordHTML,
@@ -26404,6 +26913,8 @@ export {
26404
26913
  renderVoiceDemoReadyHTML,
26405
26914
  renderVoiceDeliverySinkHTML,
26406
26915
  renderVoiceDeliveryRuntimeHTML,
26916
+ renderVoiceDataControlMarkdown,
26917
+ renderVoiceDataControlHTML,
26407
26918
  renderVoiceCampaignsHTML,
26408
26919
  renderVoiceCampaignObservabilityHTML,
26409
26920
  renderVoiceCallReviewMarkdown,
@@ -26461,6 +26972,7 @@ export {
26461
26972
  deliverVoiceAuditEventsToSinks,
26462
26973
  decodeTwilioMulawBase64,
26463
26974
  deadLetterVoiceOpsTask,
26975
+ createVoiceZeroRetentionPolicy,
26464
26976
  createVoiceZendeskTicketUpdateSink,
26465
26977
  createVoiceZendeskTicketSyncSinks,
26466
26978
  createVoiceZendeskTicketSink,
@@ -26586,6 +27098,7 @@ export {
26586
27098
  createVoiceOpsTaskProcessorWorker,
26587
27099
  createVoiceOpsStatusRoutes,
26588
27100
  createVoiceOpsRuntime,
27101
+ createVoiceOpsRecoveryRoutes,
26589
27102
  createVoiceOpsConsoleRoutes,
26590
27103
  createVoiceOpsActionAuditRoutes,
26591
27104
  createVoiceOperationsRecordRoutes,
@@ -26648,6 +27161,7 @@ export {
26648
27161
  createVoiceDeliveryRuntimeRoutes,
26649
27162
  createVoiceDeliveryRuntimePresetConfig,
26650
27163
  createVoiceDeliveryRuntime,
27164
+ createVoiceDataControlRoutes,
26651
27165
  createVoiceCampaignWorkerLoop,
26652
27166
  createVoiceCampaignWorker,
26653
27167
  createVoiceCampaignTelephonyOutcomeHandler,
@@ -26718,6 +27232,8 @@ export {
26718
27232
  buildVoiceProductionReadinessGate,
26719
27233
  buildVoiceOpsTaskFromSLABreach,
26720
27234
  buildVoiceOpsTaskFromReview,
27235
+ buildVoiceOpsRecoveryReport,
27236
+ buildVoiceOpsRecoveryReadinessCheck,
26721
27237
  buildVoiceOpsConsoleReport,
26722
27238
  buildVoiceOpsActionHistoryReport,
26723
27239
  buildVoiceOperationsRecord,
@@ -26729,6 +27245,7 @@ export {
26729
27245
  buildVoiceDeliverySinkReport,
26730
27246
  buildVoiceDeliveryRuntimeReport,
26731
27247
  buildVoiceDataRetentionPlan,
27248
+ buildVoiceDataControlReport,
26732
27249
  buildVoiceCampaignObservabilityReport,
26733
27250
  buildVoiceAuditTrailReport,
26734
27251
  buildVoiceAuditExport,