@absolutejs/voice 0.0.22-beta.276 → 0.0.22-beta.278

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -53,6 +53,7 @@ export { assertVoiceProviderRoutingContractEvidence, assertVoiceProviderRoutingC
53
53
  export { assertVoiceProviderSloEvidence, buildVoiceProviderSloReport, createVoiceProviderSloRoutes, evaluateVoiceProviderSloEvidence, renderVoiceProviderSloHTML, renderVoiceProviderSloMarkdown } from './providerSlo';
54
54
  export { createVoicePhoneAgentProductionSmokeHTMLHandler, createVoicePhoneAgentProductionSmokeJSONHandler, createVoicePhoneAgentProductionSmokeRoutes, renderVoicePhoneAgentProductionSmokeHTML, runVoicePhoneAgentProductionSmokeContract } from './phoneAgentProductionSmoke';
55
55
  export { assertVoiceProductionReadinessEvidence, buildVoiceProductionReadinessGate, buildVoiceProductionReadinessReport, createVoiceProductionReadinessRoutes, evaluateVoiceProductionReadinessEvidence, renderVoiceProductionReadinessHTML, summarizeVoiceProductionReadinessGate } from './productionReadiness';
56
+ export { acknowledgeVoiceMonitorIssue, buildVoiceMonitorRunReport, createVoiceMemoryMonitorIssueStore, createVoiceMonitorRoutes, muteVoiceMonitorIssue, renderVoiceMonitorHTML, renderVoiceMonitorMarkdown, resolveVoiceMonitorIssue } from './voiceMonitoring';
56
57
  export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './readinessProfiles';
57
58
  export { assertVoiceProviderContractMatrixEvidence, assertVoiceProviderStackEvidence, buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderContractMatrixEvidence, evaluateVoiceProviderStackEvidence, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
58
59
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
@@ -121,6 +122,7 @@ export type { VoicePhoneAgentProductionSmokeIssue, VoicePhoneAgentProductionSmok
121
122
  export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesOptions } from './opsConsoleRoutes';
122
123
  export type { VoiceOpsStatus, VoiceOpsStatusLink, VoiceOpsStatusOptions, VoiceOpsStatusReport, VoiceOpsStatusRoutesOptions } from './opsStatus';
123
124
  export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptions, VoiceProductionReadinessAuditRequirement, VoiceProductionReadinessAuditSummary, VoiceProductionReadinessAssertionInput, VoiceProductionReadinessAssertionReport, VoiceProductionReadinessCheck, VoiceProductionReadinessGateIssue, VoiceProductionReadinessGateOptions, VoiceProductionReadinessGateProfile, VoiceProductionReadinessGateProfileSurface, VoiceProductionReadinessGateReport, VoiceProductionReadinessOpsActionHistoryOptions, VoiceProductionReadinessOpsActionHistorySummary, VoiceProductionReadinessOperationsRecordLink, VoiceProductionReadinessOperationsRecordLinks, VoiceProductionReadinessProfileExplanation, VoiceProductionReadinessProfileSurface, VoiceProductionReadinessProofSource, VoiceProductionReadinessReport, VoiceProductionReadinessRoutesOptions, VoiceProductionReadinessTraceDeliverySummary, VoiceProductionReadinessAuditDeliveryOptions, VoiceProductionReadinessAuditDeliverySummary, VoiceProductionReadinessTraceDeliveryOptions, VoiceProductionReadinessStatus } from './productionReadiness';
125
+ export type { VoiceMonitorDefinition, VoiceMonitorEvaluation, VoiceMonitorEvaluationInput, VoiceMonitorIssue, VoiceMonitorIssueStatus, VoiceMonitorIssueStore, VoiceMonitorRoutesOptions, VoiceMonitorRun, VoiceMonitorRunOptions, VoiceMonitorRunReport, VoiceMonitorSeverity, VoiceMonitorStatus } from './voiceMonitoring';
124
126
  export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
125
127
  export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixAssertionInput, VoiceProviderContractMatrixAssertionReport, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackAssertionInput, VoiceProviderStackAssertionReport, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
126
128
  export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordGuardrailAssertionInput, VoiceOperationsRecordGuardrailAssertionReport, VoiceOperationsRecordGuardrailDecision, VoiceOperationsRecordGuardrailFinding, VoiceOperationsRecordGuardrailSummary, VoiceOperationsRecordIntegrationEventSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordProviderDecision, VoiceOperationsRecordReviewSummary, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTaskSummary, VoiceOperationsRecordTranscriptTurn, VoiceOperationsRecordTool } from './operationsRecord';
package/dist/index.js CHANGED
@@ -27328,6 +27328,12 @@ var resolvePhoneAgentSmokes = async (options, input) => {
27328
27328
  }
27329
27329
  return typeof options.phoneAgentSmokes === "function" ? await options.phoneAgentSmokes(input) : options.phoneAgentSmokes;
27330
27330
  };
27331
+ var resolveMonitoring = async (options, input) => {
27332
+ if (options.monitoring === false || options.monitoring === undefined) {
27333
+ return;
27334
+ }
27335
+ return typeof options.monitoring === "function" ? await options.monitoring(input) : options.monitoring;
27336
+ };
27331
27337
  var isVoiceTelephonyWebhookSecurityReport = (value) => typeof value.generatedAt === "number" && Array.isArray(value.providers) && typeof value.status === "string";
27332
27338
  var resolveTelephonyWebhookSecurity = async (options, input) => {
27333
27339
  if (options.telephonyWebhookSecurity === false || options.telephonyWebhookSecurity === undefined) {
@@ -27698,6 +27704,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27698
27704
  providerStack,
27699
27705
  providerContractMatrix,
27700
27706
  phoneAgentSmokes,
27707
+ monitoring,
27701
27708
  telephonyWebhookSecurity,
27702
27709
  reconnectContracts,
27703
27710
  bargeInReports,
@@ -27737,6 +27744,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27737
27744
  resolveProviderStack(options, { query, request }),
27738
27745
  resolveProviderContractMatrix(options, { query, request }),
27739
27746
  resolvePhoneAgentSmokes(options, { query, request }),
27747
+ resolveMonitoring(options, { query, request }),
27740
27748
  resolveTelephonyWebhookSecurity(options, { query, request }),
27741
27749
  resolveReconnectContracts(options, { query, request }),
27742
27750
  resolveBargeInReports(options, { query, request }),
@@ -27945,6 +27953,12 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27945
27953
  status: phoneAgentSmokes.some((report) => !report.pass) ? "fail" : phoneAgentSmokes.length === 0 ? "warn" : "pass",
27946
27954
  total: phoneAgentSmokes.length
27947
27955
  } : undefined;
27956
+ const monitoringSummary = monitoring ? {
27957
+ criticalOpen: monitoring.summary.criticalOpen,
27958
+ open: monitoring.summary.open,
27959
+ status: monitoring.status,
27960
+ total: monitoring.summary.total
27961
+ } : undefined;
27948
27962
  const telephonyWebhookSecuritySummary = telephonyWebhookSecurity ? {
27949
27963
  enabled: telephonyWebhookSecurity.summary.enabled,
27950
27964
  failed: telephonyWebhookSecurity.summary.failed,
@@ -28341,6 +28355,22 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28341
28355
  ]
28342
28356
  });
28343
28357
  }
28358
+ if (monitoring && monitoringSummary) {
28359
+ checks.push({
28360
+ detail: monitoringSummary.status === "pass" ? `${monitoringSummary.total} monitor(s) are passing with no open issues.` : `${monitoringSummary.open} monitor issue(s) open, ${monitoringSummary.criticalOpen} critical.`,
28361
+ href: options.links?.monitoring ?? "/voice/monitors",
28362
+ label: "Monitoring issues",
28363
+ status: monitoringSummary.status,
28364
+ value: `${monitoring.summary.passed}/${monitoringSummary.total}`,
28365
+ actions: monitoringSummary.status === "pass" ? [] : [
28366
+ {
28367
+ description: "Open monitor issues and resolve or acknowledge customer-owned alerts before deploy.",
28368
+ href: options.links?.monitoring ?? "/voice/monitors",
28369
+ label: "Open monitor issues"
28370
+ }
28371
+ ]
28372
+ });
28373
+ }
28344
28374
  return {
28345
28375
  checkedAt: Date.now(),
28346
28376
  checks,
@@ -28358,6 +28388,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28358
28388
  operationsRecords: "/voice-operations",
28359
28389
  observabilityExport: "/voice/observability-export",
28360
28390
  observabilityExportDeliveries: "/api/voice/observability-export/deliveries",
28391
+ monitoring: "/voice/monitors",
28361
28392
  opsActions: "/voice/ops-actions",
28362
28393
  opsRecovery: "/ops-recovery",
28363
28394
  phoneAgentSmoke: "/sessions",
@@ -28389,6 +28420,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28389
28420
  total: handoffs.total
28390
28421
  },
28391
28422
  liveLatency,
28423
+ monitoring: monitoringSummary,
28392
28424
  opsActionHistory,
28393
28425
  opsRecovery: opsRecovery ? {
28394
28426
  issues: opsRecovery.issues.length,
@@ -28502,6 +28534,193 @@ var createVoiceProductionReadinessRoutes = (options) => {
28502
28534
  }
28503
28535
  return routes;
28504
28536
  };
28537
+ // src/voiceMonitoring.ts
28538
+ import { Elysia as Elysia44 } from "elysia";
28539
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28540
+ var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
28541
+ var rollupStatus4 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
28542
+ var createVoiceMemoryMonitorIssueStore = (initial = []) => {
28543
+ const issues = new Map(initial.map((issue) => [issue.id, { ...issue }]));
28544
+ return {
28545
+ list: () => Array.from(issues.values()).map((issue) => ({ ...issue })),
28546
+ upsert: (issue) => {
28547
+ const previous = issues.get(issue.id);
28548
+ const next = previous ? {
28549
+ ...previous,
28550
+ ...issue,
28551
+ createdAt: previous.createdAt,
28552
+ status: previous.status === "resolved" || previous.status === "muted" ? previous.status : issue.status
28553
+ } : issue;
28554
+ issues.set(issue.id, { ...next });
28555
+ return { ...next };
28556
+ },
28557
+ update: (id, patch) => {
28558
+ const previous = issues.get(id);
28559
+ if (!previous) {
28560
+ return;
28561
+ }
28562
+ const next = { ...previous, ...patch };
28563
+ issues.set(id, next);
28564
+ return { ...next };
28565
+ }
28566
+ };
28567
+ };
28568
+ var buildVoiceMonitorRunReport = async (options) => {
28569
+ const checkedAt = options.now ?? Date.now();
28570
+ const runs = await Promise.all(options.monitors.map(async (monitor) => {
28571
+ const evaluation = await monitor.evaluate({
28572
+ evidence: options.evidence,
28573
+ now: checkedAt
28574
+ });
28575
+ return {
28576
+ ...evaluation,
28577
+ checkedAt,
28578
+ description: monitor.description,
28579
+ id: monitor.id,
28580
+ label: monitor.label,
28581
+ severity: monitor.severity ?? "warn",
28582
+ windowMs: monitor.windowMs
28583
+ };
28584
+ }));
28585
+ for (const run of runs) {
28586
+ if (run.status === "pass") {
28587
+ continue;
28588
+ }
28589
+ await options.issueStore?.upsert({
28590
+ createdAt: checkedAt,
28591
+ detail: run.detail,
28592
+ id: issueIdForRun(run),
28593
+ impactedSessions: [...run.impactedSessions ?? []],
28594
+ label: run.label,
28595
+ lastSeenAt: checkedAt,
28596
+ monitorId: run.id,
28597
+ operationsRecordHrefs: [...run.operationsRecordHrefs ?? []],
28598
+ severity: run.status === "fail" ? run.severity : "warn",
28599
+ status: "open",
28600
+ threshold: run.threshold,
28601
+ value: run.value
28602
+ });
28603
+ }
28604
+ const issues = await options.issueStore?.list() ?? [];
28605
+ const openIssues = issues.filter((issue) => issue.status === "open");
28606
+ const criticalOpen = openIssues.filter((issue) => issue.severity === "critical").length;
28607
+ return {
28608
+ checkedAt,
28609
+ issues,
28610
+ runs,
28611
+ status: criticalOpen > 0 ? "fail" : openIssues.length > 0 || rollupStatus4(runs) === "warn" ? "warn" : rollupStatus4(runs),
28612
+ summary: {
28613
+ acknowledged: issues.filter((issue) => issue.status === "acknowledged").length,
28614
+ criticalOpen,
28615
+ failed: runs.filter((run) => run.status === "fail").length,
28616
+ muted: issues.filter((issue) => issue.status === "muted").length,
28617
+ open: openIssues.length,
28618
+ passed: runs.filter((run) => run.status === "pass").length,
28619
+ resolved: issues.filter((issue) => issue.status === "resolved").length,
28620
+ total: runs.length,
28621
+ warned: runs.filter((run) => run.status === "warn").length
28622
+ }
28623
+ };
28624
+ };
28625
+ var acknowledgeVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28626
+ acknowledgedAt: input.now ?? Date.now(),
28627
+ acknowledgedBy: input.actorId,
28628
+ status: "acknowledged"
28629
+ });
28630
+ var resolveVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28631
+ resolvedAt: input.now ?? Date.now(),
28632
+ resolvedBy: input.actorId,
28633
+ status: "resolved"
28634
+ });
28635
+ var muteVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28636
+ mutedAt: input.now ?? Date.now(),
28637
+ mutedBy: input.actorId,
28638
+ status: "muted"
28639
+ });
28640
+ var renderVoiceMonitorMarkdown = (report) => {
28641
+ const rows = report.runs.map((run) => `| ${run.id} | ${run.status} | ${run.severity} | ${run.value ?? ""} | ${run.threshold ?? ""} | ${run.detail ?? ""} |`).join(`
28642
+ `);
28643
+ return `# Voice Monitor Report
28644
+
28645
+ - Status: ${report.status}
28646
+ - Checks: ${report.summary.passed}/${report.summary.total} passing
28647
+ - Open issues: ${report.summary.open}
28648
+ - Critical open issues: ${report.summary.criticalOpen}
28649
+
28650
+ | Monitor | Status | Severity | Value | Threshold | Detail |
28651
+ | --- | --- | --- | --- | --- | --- |
28652
+ ${rows || "| none | pass | info | | | No monitors configured. |"}
28653
+ `;
28654
+ };
28655
+ var renderVoiceMonitorHTML = (report, options = {}) => {
28656
+ const title = options.title ?? "Voice Monitors";
28657
+ const runs = report.runs.map((run) => `<tr><td>${escapeHtml41(run.label)}</td><td class="${escapeHtml41(run.status)}">${escapeHtml41(run.status)}</td><td>${escapeHtml41(run.severity)}</td><td>${escapeHtml41(String(run.value ?? ""))}</td><td>${escapeHtml41(String(run.threshold ?? ""))}</td><td>${escapeHtml41(run.detail ?? "")}</td></tr>`).join("");
28658
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml41(issue.label)}</strong> <span class="${escapeHtml41(issue.status)}">${escapeHtml41(issue.status)}</span> ${escapeHtml41(issue.detail ?? "")}</li>`).join("");
28659
+ const snippet = escapeHtml41(`app.use(createVoiceMonitorRoutes({
28660
+ evidence,
28661
+ issueStore,
28662
+ monitors: [defineVoiceMonitor(...)]
28663
+ }));`);
28664
+ 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:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml41(title)}</h1><p class="pill ${escapeHtml41(report.status)}">Status: ${escapeHtml41(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
28665
+ };
28666
+ var actorFromRequest = async (request) => {
28667
+ if (!request.headers.get("content-type")?.includes("application/json")) {
28668
+ return;
28669
+ }
28670
+ const body = await request.json().catch(() => {
28671
+ return;
28672
+ });
28673
+ return typeof body?.actorId === "string" ? body.actorId : undefined;
28674
+ };
28675
+ var createVoiceMonitorRoutes = (options) => {
28676
+ const path = options.path ?? "/api/voice/monitors";
28677
+ const htmlPath = options.htmlPath === undefined ? "/voice/monitors" : options.htmlPath;
28678
+ const issuePath = options.issuePath ?? "/api/voice/monitor-issues";
28679
+ const issueStore = options.issueStore ?? createVoiceMemoryMonitorIssueStore();
28680
+ const report = () => buildVoiceMonitorRunReport({
28681
+ evidence: options.evidence,
28682
+ issueStore,
28683
+ monitors: options.monitors,
28684
+ now: options.now
28685
+ });
28686
+ const routes = new Elysia44({
28687
+ name: options.name ?? "absolutejs-voice-monitoring"
28688
+ }).get(path, report).get(`${path}.md`, async () => {
28689
+ return new Response(renderVoiceMonitorMarkdown(await report()), {
28690
+ headers: {
28691
+ "Content-Type": "text/markdown; charset=utf-8",
28692
+ ...options.headers
28693
+ }
28694
+ });
28695
+ }).get(issuePath, () => issueStore.list()).post(`${issuePath}/:id/acknowledge`, async ({ params, request }) => {
28696
+ const issue = await acknowledgeVoiceMonitorIssue(issueStore, params.id, {
28697
+ actorId: await actorFromRequest(request)
28698
+ });
28699
+ return issue ?? new Response("Issue not found", { status: 404 });
28700
+ }).post(`${issuePath}/:id/resolve`, async ({ params, request }) => {
28701
+ const issue = await resolveVoiceMonitorIssue(issueStore, params.id, {
28702
+ actorId: await actorFromRequest(request)
28703
+ });
28704
+ return issue ?? new Response("Issue not found", { status: 404 });
28705
+ }).post(`${issuePath}/:id/mute`, async ({ params, request }) => {
28706
+ const issue = await muteVoiceMonitorIssue(issueStore, params.id, {
28707
+ actorId: await actorFromRequest(request)
28708
+ });
28709
+ return issue ?? new Response("Issue not found", { status: 404 });
28710
+ });
28711
+ if (htmlPath !== false) {
28712
+ routes.get(htmlPath, async () => {
28713
+ const body = await (options.render ?? renderVoiceMonitorHTML)(await report(), { title: options.title });
28714
+ return new Response(body, {
28715
+ headers: {
28716
+ "Content-Type": "text/html; charset=utf-8",
28717
+ ...options.headers
28718
+ }
28719
+ });
28720
+ });
28721
+ }
28722
+ return routes;
28723
+ };
28505
28724
  // src/readinessProfiles.ts
28506
28725
  var profileSurfaceLabels = {
28507
28726
  "meeting-recorder": {
@@ -28525,6 +28744,7 @@ var profileSurfaceLabels = {
28525
28744
  observabilityExportDeliveryHistory: "observability export delivery history configured",
28526
28745
  phoneAgentSmokes: "phone-agent smoke proof configured",
28527
28746
  providerRoutingContracts: "provider routing contracts configured",
28747
+ telephonyWebhookSecurity: "carrier webhook security configured",
28528
28748
  traceDeliveries: "trace delivery queue configured"
28529
28749
  }
28530
28750
  };
@@ -28547,6 +28767,7 @@ var profileRequiredKeys = {
28547
28767
  "phoneAgentSmokes",
28548
28768
  "campaignReadiness",
28549
28769
  "providerRoutingContracts",
28770
+ "telephonyWebhookSecurity",
28550
28771
  "auditDeliveries",
28551
28772
  "traceDeliveries",
28552
28773
  "observabilityExportDeliveryHistory",
@@ -28567,6 +28788,7 @@ var configuredProfileKeys = (options) => {
28567
28788
  "phoneAgentSmokes",
28568
28789
  "providerRoutingContracts",
28569
28790
  "reconnectContracts",
28791
+ "telephonyWebhookSecurity",
28570
28792
  "traceDeliveries"
28571
28793
  ]) {
28572
28794
  if (isConfigured(options[key])) {
@@ -28675,6 +28897,12 @@ var profileExplanation = (profile, options, links) => {
28675
28897
  key: "providerRoutingContracts",
28676
28898
  label: "Provider routing contracts"
28677
28899
  },
28900
+ {
28901
+ configured: isConfigured(options.telephonyWebhookSecurity),
28902
+ href: links.telephonyWebhookSecurity,
28903
+ key: "telephonyWebhookSecurity",
28904
+ label: "Carrier webhook security"
28905
+ },
28678
28906
  {
28679
28907
  configured: isConfigured(options.deliveryRuntime),
28680
28908
  href: links.deliveryRuntime,
@@ -28779,6 +29007,7 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
28779
29007
  providerRoutingContracts: "/resilience",
28780
29008
  resilience: "/resilience",
28781
29009
  sessions: "/sessions",
29010
+ telephonyWebhookSecurity: "/api/voice/telephony/webhook-security",
28782
29011
  traceDeliveries: "/traces/deliveries"
28783
29012
  }, options.links);
28784
29013
  return withDefined({
@@ -28793,6 +29022,7 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
28793
29022
  profile: profileExplanation(profile, options, links2),
28794
29023
  proofSources: options.proofSources,
28795
29024
  providerRoutingContracts: options.providerRoutingContracts,
29025
+ telephonyWebhookSecurity: options.telephonyWebhookSecurity,
28796
29026
  traceDeliveries: options.traceDeliveries
28797
29027
  });
28798
29028
  }
@@ -28851,8 +29081,8 @@ var recommendVoiceReadinessProfile = (options) => {
28851
29081
  };
28852
29082
  };
28853
29083
  // src/providerStackRecommendations.ts
28854
- import { Elysia as Elysia44 } from "elysia";
28855
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29084
+ import { Elysia as Elysia45 } from "elysia";
29085
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28856
29086
  var profileProviderPriorities = {
28857
29087
  "meeting-recorder": {
28858
29088
  llm: ["openai", "anthropic", "gemini"],
@@ -29171,17 +29401,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
29171
29401
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
29172
29402
  const title = options.title ?? "Voice Provider Contract Matrix";
29173
29403
  const rows = report.rows.map((row) => {
29174
- const checks = row.checks.map((check) => `<li class="${escapeHtml41(check.status)}"><strong>${escapeHtml41(check.label)}</strong><span>${escapeHtml41(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml41(check.remediation.href)}">${escapeHtml41(check.remediation.label)}</a>` : escapeHtml41(check.remediation.label)}: ${escapeHtml41(check.remediation.detail)}</em>` : ""}</li>`).join("");
29175
- return `<article class="row ${escapeHtml41(row.status)}">
29404
+ const checks = row.checks.map((check) => `<li class="${escapeHtml42(check.status)}"><strong>${escapeHtml42(check.label)}</strong><span>${escapeHtml42(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml42(check.remediation.href)}">${escapeHtml42(check.remediation.label)}</a>` : escapeHtml42(check.remediation.label)}: ${escapeHtml42(check.remediation.detail)}</em>` : ""}</li>`).join("");
29405
+ return `<article class="row ${escapeHtml42(row.status)}">
29176
29406
  <div>
29177
- <p class="eyebrow">${escapeHtml41(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
29178
- <h2>${escapeHtml41(row.provider)}</h2>
29179
- <p class="status ${escapeHtml41(row.status)}">${escapeHtml41(row.status.toUpperCase())}</p>
29407
+ <p class="eyebrow">${escapeHtml42(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
29408
+ <h2>${escapeHtml42(row.provider)}</h2>
29409
+ <p class="status ${escapeHtml42(row.status)}">${escapeHtml42(row.status.toUpperCase())}</p>
29180
29410
  </div>
29181
29411
  <ul>${checks}</ul>
29182
29412
  </article>`;
29183
29413
  }).join("");
29184
- const snippet = escapeHtml41(`const providerContracts = () =>
29414
+ const snippet = escapeHtml42(`const providerContracts = () =>
29185
29415
  createVoiceProviderContractMatrixPreset('phone-agent', {
29186
29416
  env: process.env,
29187
29417
  providers: {
@@ -29202,7 +29432,7 @@ createVoiceProductionReadinessRoutes({
29202
29432
  providerContractMatrix: () =>
29203
29433
  buildVoiceProviderContractMatrix(providerContracts())
29204
29434
  });`);
29205
- 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:#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>${escapeHtml41(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>`;
29435
+ 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:#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>${escapeHtml42(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>`;
29206
29436
  };
29207
29437
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
29208
29438
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -29217,7 +29447,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
29217
29447
  var createVoiceProviderContractMatrixRoutes = (options) => {
29218
29448
  const path = options.path ?? "/api/provider-contracts";
29219
29449
  const htmlPath = options.htmlPath ?? "/provider-contracts";
29220
- const routes = new Elysia44({
29450
+ const routes = new Elysia45({
29221
29451
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
29222
29452
  });
29223
29453
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -29335,7 +29565,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
29335
29565
  return assertion;
29336
29566
  };
29337
29567
  // src/opsConsoleRoutes.ts
29338
- import { Elysia as Elysia45 } from "elysia";
29568
+ import { Elysia as Elysia46 } from "elysia";
29339
29569
  var DEFAULT_LINKS = [
29340
29570
  {
29341
29571
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -29370,7 +29600,7 @@ var DEFAULT_LINKS = [
29370
29600
  label: "Handoffs"
29371
29601
  }
29372
29602
  ];
29373
- var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29603
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29374
29604
  var countProviderStatuses = (providers) => {
29375
29605
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
29376
29606
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -29439,20 +29669,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
29439
29669
  trace
29440
29670
  };
29441
29671
  };
29442
- var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml42(input.label)}</span><strong>${escapeHtml42(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml42(input.status)}">${escapeHtml42(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml42(input.href)}">Open</a>` : ""}</article>`;
29672
+ var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml43(input.label)}</span><strong>${escapeHtml43(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml43(input.status)}">${escapeHtml43(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml43(input.href)}">Open</a>` : ""}</article>`;
29443
29673
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
29444
29674
  const links = report.links.map((link) => `<article class="surface">
29445
- <div><h2>${escapeHtml42(link.label)}</h2>${link.description ? `<p>${escapeHtml42(link.description)}</p>` : ""}</div>
29446
- <p><a href="${escapeHtml42(link.href)}">Open ${escapeHtml42(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml42(link.statusHref)}">Status</a>` : ""}</p>
29675
+ <div><h2>${escapeHtml43(link.label)}</h2>${link.description ? `<p>${escapeHtml43(link.description)}</p>` : ""}</div>
29676
+ <p><a href="${escapeHtml43(link.href)}">Open ${escapeHtml43(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml43(link.statusHref)}">Status</a>` : ""}</p>
29447
29677
  </article>`).join("");
29448
- const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml42(session.sessionId)}</td><td>${escapeHtml42(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml42(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
29449
- const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml42(event.kind)}</td><td>${escapeHtml42(event.provider ?? "unknown")}</td><td>${escapeHtml42(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml42(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
29678
+ const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml43(session.sessionId)}</td><td>${escapeHtml43(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml43(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
29679
+ const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml43(event.kind)}</td><td>${escapeHtml43(event.provider ?? "unknown")}</td><td>${escapeHtml43(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml43(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
29450
29680
  const title = options.title ?? "AbsoluteJS Voice Ops Console";
29451
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#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>${escapeHtml42(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 ${escapeHtml42(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>`;
29681
+ 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{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>${escapeHtml43(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 ${escapeHtml43(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>`;
29452
29682
  };
29453
29683
  var createVoiceOpsConsoleRoutes = (options) => {
29454
29684
  const path = options.path ?? "/ops-console";
29455
- const routes = new Elysia45({
29685
+ const routes = new Elysia46({
29456
29686
  name: options.name ?? "absolutejs-voice-ops-console"
29457
29687
  });
29458
29688
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -29469,7 +29699,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
29469
29699
  return routes;
29470
29700
  };
29471
29701
  // src/incidentBundle.ts
29472
- import { Elysia as Elysia46 } from "elysia";
29702
+ import { Elysia as Elysia47 } from "elysia";
29473
29703
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
29474
29704
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
29475
29705
  return false;
@@ -29670,7 +29900,7 @@ var buildVoiceIncidentBundle = async (options) => {
29670
29900
  var createVoiceIncidentBundleRoutes = (options) => {
29671
29901
  const path = options.path ?? "/api/voice-incidents/:sessionId";
29672
29902
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
29673
- const routes = new Elysia46({
29903
+ const routes = new Elysia47({
29674
29904
  name: options.name ?? "absolutejs-voice-incident-bundle"
29675
29905
  });
29676
29906
  const getSessionId = (params) => params.sessionId ?? "";
@@ -29871,19 +30101,19 @@ var summarizeVoiceOpsStatus = async (options) => {
29871
30101
  };
29872
30102
  };
29873
30103
  // src/opsStatusRoutes.ts
29874
- import { Elysia as Elysia47 } from "elysia";
29875
- var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30104
+ import { Elysia as Elysia48 } from "elysia";
30105
+ var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29876
30106
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
29877
30107
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
29878
30108
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
29879
30109
  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;
29880
- return `<article class="surface ${escapeHtml43(surface.status)}"><span>${escapeHtml43(surface.status.toUpperCase())}</span><h2>${escapeHtml43(key)}</h2><strong>${escapeHtml43(value)}</strong></article>`;
30110
+ return `<article class="surface ${escapeHtml44(surface.status)}"><span>${escapeHtml44(surface.status.toUpperCase())}</span><h2>${escapeHtml44(key)}</h2><strong>${escapeHtml44(value)}</strong></article>`;
29881
30111
  }).join("");
29882
- 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:#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>${escapeHtml43(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(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>`;
30112
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{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>${escapeHtml44(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml44(report.status)}">Overall: ${escapeHtml44(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>`;
29883
30113
  };
29884
30114
  var createVoiceOpsStatusRoutes = (options) => {
29885
30115
  const path = options.path ?? "/api/voice/ops-status";
29886
- const routes = new Elysia47({
30116
+ const routes = new Elysia48({
29887
30117
  name: options.name ?? "absolutejs-voice-ops-status"
29888
30118
  });
29889
30119
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -30316,8 +30546,8 @@ var createVoiceTTSProviderRouter = (options) => {
30316
30546
  };
30317
30547
  };
30318
30548
  // src/traceDeliveryRoutes.ts
30319
- import { Elysia as Elysia48 } from "elysia";
30320
- var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30549
+ import { Elysia as Elysia49 } from "elysia";
30550
+ var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30321
30551
  var getString19 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
30322
30552
  var getNumber11 = (value) => {
30323
30553
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -30398,14 +30628,14 @@ var renderSinkResults2 = (delivery) => {
30398
30628
  if (entries.length === 0) {
30399
30629
  return "<p>No sink delivery attempts recorded yet.</p>";
30400
30630
  }
30401
- return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml44(sinkId)}</strong>: ${escapeHtml44(result.status)}${result.deliveredTo ? ` to ${escapeHtml44(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml44(result.error)})` : ""}</li>`).join("")}</ul>`;
30631
+ return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml45(sinkId)}</strong>: ${escapeHtml45(result.status)}${result.deliveredTo ? ` to ${escapeHtml45(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml45(result.error)})` : ""}</li>`).join("")}</ul>`;
30402
30632
  };
30403
- var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml44(event.type)} <small>${escapeHtml44(event.id)}</small>${event.sessionId ? ` session=${escapeHtml44(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
30633
+ var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml45(event.type)} <small>${escapeHtml45(event.id)}</small>${event.sessionId ? ` session=${escapeHtml45(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
30404
30634
  var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
30405
30635
  const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
30406
- const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml44(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
30407
- const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml44(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml44(delivery.deliveryStatus)}</span><h2>${escapeHtml44(delivery.id)}</h2><p>${escapeHtml44(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml44(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml44(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
30408
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{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>${escapeHtml44(title)}</h1><p>Checked ${escapeHtml44(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>`;
30636
+ const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml45(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
30637
+ const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml45(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml45(delivery.deliveryStatus)}</span><h2>${escapeHtml45(delivery.id)}</h2><p>${escapeHtml45(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml45(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml45(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
30638
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{background:#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>${escapeHtml45(title)}</h1><p>Checked ${escapeHtml45(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>`;
30409
30639
  };
30410
30640
  var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
30411
30641
  var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
@@ -30425,7 +30655,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
30425
30655
  const path = options.path ?? "/api/voice-trace-deliveries";
30426
30656
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
30427
30657
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
30428
- const routes = new Elysia48({
30658
+ const routes = new Elysia49({
30429
30659
  name: options.name ?? "absolutejs-voice-trace-deliveries"
30430
30660
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
30431
30661
  if (htmlPath !== false) {
@@ -30522,7 +30752,7 @@ var createVoiceMemoryStore = () => {
30522
30752
  return { get, getOrCreate, list, remove, set };
30523
30753
  };
30524
30754
  // src/opsWebhook.ts
30525
- import { Elysia as Elysia49 } from "elysia";
30755
+ import { Elysia as Elysia50 } from "elysia";
30526
30756
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
30527
30757
  var signVoiceOpsWebhookBody = async (input) => {
30528
30758
  const encoder = new TextEncoder;
@@ -30652,7 +30882,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
30652
30882
  };
30653
30883
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
30654
30884
  const path = options.path ?? "/api/voice-ops/webhook";
30655
- return new Elysia49().post(path, async ({ body, request, set }) => {
30885
+ return new Elysia50().post(path, async ({ body, request, set }) => {
30656
30886
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
30657
30887
  if (options.signingSecret) {
30658
30888
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -31107,7 +31337,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
31107
31337
  };
31108
31338
  };
31109
31339
  // src/postCallAnalysis.ts
31110
- import { Elysia as Elysia50 } from "elysia";
31340
+ import { Elysia as Elysia51 } from "elysia";
31111
31341
  var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
31112
31342
  var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
31113
31343
  var getPathValue3 = (source, path) => {
@@ -31286,7 +31516,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
31286
31516
  };
31287
31517
  var createVoicePostCallAnalysisRoutes = (options = {}) => {
31288
31518
  const path = options.path ?? "/api/voice/post-call-analysis";
31289
- const routes = new Elysia50({
31519
+ const routes = new Elysia51({
31290
31520
  name: options.name ?? "absolutejs-voice-post-call-analysis"
31291
31521
  });
31292
31522
  routes.get(path, async ({ query }) => {
@@ -31311,7 +31541,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
31311
31541
  return routes;
31312
31542
  };
31313
31543
  // src/guardrails.ts
31314
- import { Elysia as Elysia51 } from "elysia";
31544
+ import { Elysia as Elysia52 } from "elysia";
31315
31545
  var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
31316
31546
  var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
31317
31547
  var matchesRule = async (rule, input) => {
@@ -31613,7 +31843,7 @@ var resolveGuardrailReport = async (options, input) => {
31613
31843
  };
31614
31844
  var createVoiceGuardrailRoutes = (options = {}) => {
31615
31845
  const path = options.path ?? "/api/voice/guardrails";
31616
- const routes = new Elysia51({
31846
+ const routes = new Elysia52({
31617
31847
  name: options.name ?? "absolutejs-voice-guardrails"
31618
31848
  });
31619
31849
  routes.all(path, async ({ request }) => {
@@ -32109,6 +32339,7 @@ export {
32109
32339
  resolveVoiceOpsTaskAssignment,
32110
32340
  resolveVoiceOpsTaskAgeBucket,
32111
32341
  resolveVoiceOpsPreset,
32342
+ resolveVoiceMonitorIssue,
32112
32343
  resolveVoiceDiagnosticsTraceFilter,
32113
32344
  resolveVoiceAuditTrailFilter,
32114
32345
  resolveVoiceAuditDeliveryFilter,
@@ -32153,6 +32384,8 @@ export {
32153
32384
  renderVoiceOperationsRecordGuardrailMarkdown,
32154
32385
  renderVoiceObservabilityExportReplayHTML,
32155
32386
  renderVoiceObservabilityExportMarkdown,
32387
+ renderVoiceMonitorMarkdown,
32388
+ renderVoiceMonitorHTML,
32156
32389
  renderVoiceLiveLatencyHTML,
32157
32390
  renderVoiceLatencySLOMarkdown,
32158
32391
  renderVoiceHandoffHealthHTML,
@@ -32195,6 +32428,7 @@ export {
32195
32428
  pruneVoiceIncidentBundleArtifacts,
32196
32429
  parseVoiceTelephonyWebhookEvent,
32197
32430
  normalizeVoiceProofTrendReport,
32431
+ muteVoiceMonitorIssue,
32198
32432
  matchesVoiceOpsTaskAssignmentRule,
32199
32433
  markVoiceOpsTaskSLABreached,
32200
32434
  loadVoiceObservabilityExportReplaySource,
@@ -32397,10 +32631,12 @@ export {
32397
32631
  createVoiceObservabilityExportSchema,
32398
32632
  createVoiceObservabilityExportRoutes,
32399
32633
  createVoiceObservabilityExportReplayRoutes,
32634
+ createVoiceMonitorRoutes,
32400
32635
  createVoiceMemoryTraceSinkDeliveryStore,
32401
32636
  createVoiceMemoryTraceEventStore,
32402
32637
  createVoiceMemoryStore,
32403
32638
  createVoiceMemoryObservabilityExportDeliveryReceiptStore,
32639
+ createVoiceMemoryMonitorIssueStore,
32404
32640
  createVoiceMemoryLiveOpsControlStore,
32405
32641
  createVoiceMemoryIncidentBundleStore,
32406
32642
  createVoiceMemoryHandoffDeliveryStore,
@@ -32548,6 +32784,7 @@ export {
32548
32784
  buildVoiceObservabilityExportDeliveryHistory,
32549
32785
  buildVoiceObservabilityExport,
32550
32786
  buildVoiceObservabilityArtifactIndex,
32787
+ buildVoiceMonitorRunReport,
32551
32788
  buildVoiceLiveOpsControlState,
32552
32789
  buildVoiceLatencySLOGate,
32553
32790
  buildVoiceIncidentBundle,
@@ -32600,6 +32837,7 @@ export {
32600
32837
  applyVoiceCampaignTelephonyOutcome,
32601
32838
  applyRiskTieredPhraseHintCorrections,
32602
32839
  applyPhraseHintCorrections,
32840
+ acknowledgeVoiceMonitorIssue,
32603
32841
  VOICE_LIVE_OPS_ACTIONS,
32604
32842
  TURN_PROFILE_DEFAULTS,
32605
32843
  DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS
@@ -2,6 +2,7 @@ import { Elysia } from 'elysia';
2
2
  import { type VoiceProviderFallbackRecoverySummary } from './sessionReplay';
3
3
  import { type VoiceTelephonyCarrierMatrixInput } from './telephony/matrix';
4
4
  import { type VoiceTelephonyWebhookSecurityOptions, type VoiceTelephonyWebhookSecurityReport } from './telephony/security';
5
+ import type { VoiceMonitorRunReport } from './voiceMonitoring';
5
6
  import type { VoiceTraceEventStore } from './trace';
6
7
  import type { VoiceTraceSinkDeliveryStore } from './trace';
7
8
  import type { VoiceAgentSquadContractReport } from './agentSquadContract';
@@ -118,6 +119,7 @@ export type VoiceProductionReadinessReport = {
118
119
  operationsRecords?: string;
119
120
  observabilityExport?: string;
120
121
  observabilityExportDeliveries?: string;
122
+ monitoring?: string;
121
123
  opsActions?: string;
122
124
  opsRecovery?: string;
123
125
  phoneAgentSmoke?: string;
@@ -176,6 +178,12 @@ export type VoiceProductionReadinessReport = {
176
178
  total: number;
177
179
  warnings: number;
178
180
  };
181
+ monitoring?: {
182
+ criticalOpen: number;
183
+ open: number;
184
+ status: VoiceProductionReadinessStatus;
185
+ total: number;
186
+ };
179
187
  opsActionHistory?: VoiceProductionReadinessOpsActionHistorySummary;
180
188
  opsRecovery?: {
181
189
  issues: number;
@@ -393,6 +401,10 @@ export type VoiceProductionReadinessRoutesOptions = {
393
401
  links?: VoiceProductionReadinessReport['links'];
394
402
  llmProviders?: readonly string[];
395
403
  name?: string;
404
+ monitoring?: false | VoiceMonitorRunReport | ((input: {
405
+ query: Record<string, unknown>;
406
+ request: Request;
407
+ }) => Promise<VoiceMonitorRunReport> | VoiceMonitorRunReport);
396
408
  opsActionHistory?: false | VoiceProductionReadinessOpsActionHistoryOptions;
397
409
  opsRecovery?: false | VoiceOpsRecoveryReport | ((input: {
398
410
  query: Record<string, unknown>;
@@ -16,6 +16,7 @@ export type VoiceReadinessProfileOptions = {
16
16
  proofSources?: VoiceProductionReadinessRoutesOptions['proofSources'];
17
17
  providerRoutingContracts?: VoiceProductionReadinessRoutesOptions['providerRoutingContracts'];
18
18
  reconnectContracts?: VoiceProductionReadinessRoutesOptions['reconnectContracts'];
19
+ telephonyWebhookSecurity?: VoiceProductionReadinessRoutesOptions['telephonyWebhookSecurity'];
19
20
  traceDeliveries?: VoiceProductionReadinessTraceDeliveryOptions;
20
21
  };
21
22
  export type VoiceReadinessProfileRoutesOptions = Partial<Omit<VoiceProductionReadinessRoutesOptions, 'store'>>;
@@ -0,0 +1,252 @@
1
+ import { Elysia } from 'elysia';
2
+ export type VoiceMonitorStatus = 'fail' | 'pass' | 'warn';
3
+ export type VoiceMonitorSeverity = 'critical' | 'info' | 'warn';
4
+ export type VoiceMonitorIssueStatus = 'acknowledged' | 'muted' | 'open' | 'resolved';
5
+ export type VoiceMonitorEvaluationInput<TEvidence = unknown> = {
6
+ evidence: TEvidence;
7
+ now: number;
8
+ };
9
+ export type VoiceMonitorEvaluation = {
10
+ detail?: string;
11
+ impactedSessions?: readonly string[];
12
+ operationsRecordHrefs?: readonly string[];
13
+ status: VoiceMonitorStatus;
14
+ threshold?: number | string;
15
+ value?: number | string;
16
+ };
17
+ export type VoiceMonitorDefinition<TEvidence = unknown> = {
18
+ description?: string;
19
+ id: string;
20
+ label: string;
21
+ severity?: VoiceMonitorSeverity;
22
+ windowMs?: number;
23
+ evaluate: (input: VoiceMonitorEvaluationInput<TEvidence>) => Promise<VoiceMonitorEvaluation> | VoiceMonitorEvaluation;
24
+ };
25
+ export type VoiceMonitorRun = VoiceMonitorEvaluation & {
26
+ checkedAt: number;
27
+ description?: string;
28
+ id: string;
29
+ label: string;
30
+ severity: VoiceMonitorSeverity;
31
+ windowMs?: number;
32
+ };
33
+ export type VoiceMonitorIssue = {
34
+ acknowledgedAt?: number;
35
+ acknowledgedBy?: string;
36
+ createdAt: number;
37
+ detail?: string;
38
+ id: string;
39
+ impactedSessions: string[];
40
+ label: string;
41
+ lastSeenAt: number;
42
+ monitorId: string;
43
+ mutedAt?: number;
44
+ mutedBy?: string;
45
+ operationsRecordHrefs: string[];
46
+ resolvedAt?: number;
47
+ resolvedBy?: string;
48
+ severity: VoiceMonitorSeverity;
49
+ status: VoiceMonitorIssueStatus;
50
+ threshold?: number | string;
51
+ value?: number | string;
52
+ };
53
+ export type VoiceMonitorIssueStore = {
54
+ list: () => Promise<VoiceMonitorIssue[]> | VoiceMonitorIssue[];
55
+ upsert: (issue: VoiceMonitorIssue) => Promise<VoiceMonitorIssue> | VoiceMonitorIssue;
56
+ update: (id: string, patch: Partial<VoiceMonitorIssue>) => Promise<VoiceMonitorIssue | undefined> | VoiceMonitorIssue | undefined;
57
+ };
58
+ export type VoiceMonitorRunReport = {
59
+ checkedAt: number;
60
+ issues: VoiceMonitorIssue[];
61
+ runs: VoiceMonitorRun[];
62
+ status: VoiceMonitorStatus;
63
+ summary: {
64
+ acknowledged: number;
65
+ criticalOpen: number;
66
+ failed: number;
67
+ muted: number;
68
+ open: number;
69
+ passed: number;
70
+ resolved: number;
71
+ total: number;
72
+ warned: number;
73
+ };
74
+ };
75
+ export type VoiceMonitorRunOptions<TEvidence = unknown> = {
76
+ evidence: TEvidence;
77
+ issueStore?: VoiceMonitorIssueStore;
78
+ monitors: readonly VoiceMonitorDefinition<TEvidence>[];
79
+ now?: number;
80
+ };
81
+ export type VoiceMonitorRoutesOptions<TEvidence = unknown> = VoiceMonitorRunOptions<TEvidence> & {
82
+ headers?: HeadersInit;
83
+ htmlPath?: false | string;
84
+ issuePath?: string;
85
+ name?: string;
86
+ path?: string;
87
+ render?: (report: VoiceMonitorRunReport) => Promise<string> | string;
88
+ title?: string;
89
+ };
90
+ export declare const createVoiceMemoryMonitorIssueStore: (initial?: readonly VoiceMonitorIssue[]) => VoiceMonitorIssueStore;
91
+ export declare const buildVoiceMonitorRunReport: <TEvidence = unknown>(options: VoiceMonitorRunOptions<TEvidence>) => Promise<VoiceMonitorRunReport>;
92
+ export declare const acknowledgeVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
93
+ actorId?: string;
94
+ now?: number;
95
+ }) => Promise<VoiceMonitorIssue | undefined>;
96
+ export declare const resolveVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
97
+ actorId?: string;
98
+ now?: number;
99
+ }) => Promise<VoiceMonitorIssue | undefined>;
100
+ export declare const muteVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
101
+ actorId?: string;
102
+ now?: number;
103
+ }) => Promise<VoiceMonitorIssue | undefined>;
104
+ export declare const renderVoiceMonitorMarkdown: (report: VoiceMonitorRunReport) => string;
105
+ export declare const renderVoiceMonitorHTML: (report: VoiceMonitorRunReport, options?: {
106
+ title?: string;
107
+ }) => string;
108
+ export declare const createVoiceMonitorRoutes: <TEvidence = unknown>(options: VoiceMonitorRoutesOptions<TEvidence>) => Elysia<"", {
109
+ decorator: {};
110
+ store: {};
111
+ derive: {};
112
+ resolve: {};
113
+ }, {
114
+ typebox: {};
115
+ error: {};
116
+ }, {
117
+ schema: {};
118
+ standaloneSchema: {};
119
+ macro: {};
120
+ macroFn: {};
121
+ parser: {};
122
+ response: {};
123
+ }, {
124
+ [x: string]: {
125
+ get: {
126
+ body: unknown;
127
+ params: {};
128
+ query: unknown;
129
+ headers: unknown;
130
+ response: {
131
+ 200: VoiceMonitorRunReport;
132
+ };
133
+ };
134
+ };
135
+ } & {
136
+ [x: `${string}.md`]: {
137
+ get: {
138
+ body: unknown;
139
+ params: {};
140
+ query: unknown;
141
+ headers: unknown;
142
+ response: {
143
+ 200: Response;
144
+ };
145
+ };
146
+ };
147
+ } & {
148
+ [x: string]: {
149
+ get: {
150
+ body: unknown;
151
+ params: {};
152
+ query: unknown;
153
+ headers: unknown;
154
+ response: {
155
+ 200: VoiceMonitorIssue[];
156
+ };
157
+ };
158
+ };
159
+ } & {
160
+ [x: string]: {
161
+ ":id": {
162
+ acknowledge: {
163
+ post: {
164
+ body: unknown;
165
+ params: {
166
+ id: string;
167
+ } & {};
168
+ query: unknown;
169
+ headers: unknown;
170
+ response: {
171
+ 200: Response | VoiceMonitorIssue;
172
+ 422: {
173
+ type: "validation";
174
+ on: string;
175
+ summary?: string;
176
+ message?: string;
177
+ found?: unknown;
178
+ property?: string;
179
+ expected?: string;
180
+ };
181
+ };
182
+ };
183
+ };
184
+ };
185
+ };
186
+ } & {
187
+ [x: string]: {
188
+ ":id": {
189
+ resolve: {
190
+ post: {
191
+ body: unknown;
192
+ params: {
193
+ id: string;
194
+ } & {};
195
+ query: unknown;
196
+ headers: unknown;
197
+ response: {
198
+ 200: Response | VoiceMonitorIssue;
199
+ 422: {
200
+ type: "validation";
201
+ on: string;
202
+ summary?: string;
203
+ message?: string;
204
+ found?: unknown;
205
+ property?: string;
206
+ expected?: string;
207
+ };
208
+ };
209
+ };
210
+ };
211
+ };
212
+ };
213
+ } & {
214
+ [x: string]: {
215
+ ":id": {
216
+ mute: {
217
+ post: {
218
+ body: unknown;
219
+ params: {
220
+ id: string;
221
+ } & {};
222
+ query: unknown;
223
+ headers: unknown;
224
+ response: {
225
+ 200: Response | VoiceMonitorIssue;
226
+ 422: {
227
+ type: "validation";
228
+ on: string;
229
+ summary?: string;
230
+ message?: string;
231
+ found?: unknown;
232
+ property?: string;
233
+ expected?: string;
234
+ };
235
+ };
236
+ };
237
+ };
238
+ };
239
+ };
240
+ }, {
241
+ derive: {};
242
+ resolve: {};
243
+ schema: {};
244
+ standaloneSchema: {};
245
+ response: {};
246
+ }, {
247
+ derive: {};
248
+ resolve: {};
249
+ schema: {};
250
+ standaloneSchema: {};
251
+ response: {};
252
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.276",
3
+ "version": "0.0.22-beta.278",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",