@absolutejs/voice 0.0.22-beta.277 → 0.0.22-beta.279

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, createVoiceMemoryMonitorNotifierDeliveryReceiptStore, createVoiceMonitorRoutes, createVoiceMonitorWebhookNotifier, deliverVoiceMonitorIssueNotifications, 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, VoiceMonitorNotifier, VoiceMonitorNotifierDeliveryInput, VoiceMonitorNotifierDeliveryOptions, VoiceMonitorNotifierDeliveryReceipt, VoiceMonitorNotifierDeliveryReceiptStore, VoiceMonitorNotifierDeliveryReport, VoiceMonitorNotifierDeliveryResult, VoiceMonitorRoutesOptions, VoiceMonitorRun, VoiceMonitorRunOptions, VoiceMonitorRunReport, VoiceMonitorSeverity, VoiceMonitorStatus, VoiceMonitorWebhookNotifierOptions } 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,18 @@ 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
+ };
27337
+ var resolveMonitoringNotifierDelivery = async (options, input) => {
27338
+ if (options.monitoringNotifierDelivery === false || options.monitoringNotifierDelivery === undefined) {
27339
+ return;
27340
+ }
27341
+ return typeof options.monitoringNotifierDelivery === "function" ? await options.monitoringNotifierDelivery(input) : options.monitoringNotifierDelivery;
27342
+ };
27331
27343
  var isVoiceTelephonyWebhookSecurityReport = (value) => typeof value.generatedAt === "number" && Array.isArray(value.providers) && typeof value.status === "string";
27332
27344
  var resolveTelephonyWebhookSecurity = async (options, input) => {
27333
27345
  if (options.telephonyWebhookSecurity === false || options.telephonyWebhookSecurity === undefined) {
@@ -27698,6 +27710,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27698
27710
  providerStack,
27699
27711
  providerContractMatrix,
27700
27712
  phoneAgentSmokes,
27713
+ monitoring,
27714
+ monitoringNotifierDelivery,
27701
27715
  telephonyWebhookSecurity,
27702
27716
  reconnectContracts,
27703
27717
  bargeInReports,
@@ -27737,6 +27751,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27737
27751
  resolveProviderStack(options, { query, request }),
27738
27752
  resolveProviderContractMatrix(options, { query, request }),
27739
27753
  resolvePhoneAgentSmokes(options, { query, request }),
27754
+ resolveMonitoring(options, { query, request }),
27755
+ resolveMonitoringNotifierDelivery(options, { query, request }),
27740
27756
  resolveTelephonyWebhookSecurity(options, { query, request }),
27741
27757
  resolveReconnectContracts(options, { query, request }),
27742
27758
  resolveBargeInReports(options, { query, request }),
@@ -27945,6 +27961,19 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
27945
27961
  status: phoneAgentSmokes.some((report) => !report.pass) ? "fail" : phoneAgentSmokes.length === 0 ? "warn" : "pass",
27946
27962
  total: phoneAgentSmokes.length
27947
27963
  } : undefined;
27964
+ const monitoringSummary = monitoring ? {
27965
+ criticalOpen: monitoring.summary.criticalOpen,
27966
+ open: monitoring.summary.open,
27967
+ status: monitoring.status,
27968
+ total: monitoring.summary.total
27969
+ } : undefined;
27970
+ const monitoringNotifierDeliverySummary = monitoringNotifierDelivery ? {
27971
+ failed: monitoringNotifierDelivery.summary.failed,
27972
+ notifiers: monitoringNotifierDelivery.summary.notifiers,
27973
+ sent: monitoringNotifierDelivery.summary.sent,
27974
+ status: monitoringNotifierDelivery.status,
27975
+ total: monitoringNotifierDelivery.summary.total
27976
+ } : undefined;
27948
27977
  const telephonyWebhookSecuritySummary = telephonyWebhookSecurity ? {
27949
27978
  enabled: telephonyWebhookSecurity.summary.enabled,
27950
27979
  failed: telephonyWebhookSecurity.summary.failed,
@@ -28341,6 +28370,38 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28341
28370
  ]
28342
28371
  });
28343
28372
  }
28373
+ if (monitoring && monitoringSummary) {
28374
+ checks.push({
28375
+ detail: monitoringSummary.status === "pass" ? `${monitoringSummary.total} monitor(s) are passing with no open issues.` : `${monitoringSummary.open} monitor issue(s) open, ${monitoringSummary.criticalOpen} critical.`,
28376
+ href: options.links?.monitoring ?? "/voice/monitors",
28377
+ label: "Monitoring issues",
28378
+ status: monitoringSummary.status,
28379
+ value: `${monitoring.summary.passed}/${monitoringSummary.total}`,
28380
+ actions: monitoringSummary.status === "pass" ? [] : [
28381
+ {
28382
+ description: "Open monitor issues and resolve or acknowledge customer-owned alerts before deploy.",
28383
+ href: options.links?.monitoring ?? "/voice/monitors",
28384
+ label: "Open monitor issues"
28385
+ }
28386
+ ]
28387
+ });
28388
+ }
28389
+ if (monitoringNotifierDelivery && monitoringNotifierDeliverySummary) {
28390
+ checks.push({
28391
+ detail: monitoringNotifierDeliverySummary.status === "pass" ? `${monitoringNotifierDeliverySummary.sent} monitor notification(s) delivered.` : `${monitoringNotifierDeliverySummary.failed} monitor notification delivery failure(s).`,
28392
+ href: options.links?.monitoringNotifierDelivery ?? "/api/voice/monitor-issues/notifications",
28393
+ label: "Monitor notifier delivery",
28394
+ status: monitoringNotifierDeliverySummary.status,
28395
+ value: `${monitoringNotifierDeliverySummary.sent}/${monitoringNotifierDeliverySummary.total}`,
28396
+ actions: monitoringNotifierDeliverySummary.status === "pass" ? [] : [
28397
+ {
28398
+ description: "Open monitor notification receipts and confirm webhook, Slack, email, or audit destinations are receiving issue alerts.",
28399
+ href: options.links?.monitoringNotifierDelivery ?? "/api/voice/monitor-issues/notifications",
28400
+ label: "Open monitor notification receipts"
28401
+ }
28402
+ ]
28403
+ });
28404
+ }
28344
28405
  return {
28345
28406
  checkedAt: Date.now(),
28346
28407
  checks,
@@ -28358,6 +28419,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28358
28419
  operationsRecords: "/voice-operations",
28359
28420
  observabilityExport: "/voice/observability-export",
28360
28421
  observabilityExportDeliveries: "/api/voice/observability-export/deliveries",
28422
+ monitoring: "/voice/monitors",
28423
+ monitoringNotifierDelivery: "/api/voice/monitor-issues/notifications",
28361
28424
  opsActions: "/voice/ops-actions",
28362
28425
  opsRecovery: "/ops-recovery",
28363
28426
  phoneAgentSmoke: "/sessions",
@@ -28389,6 +28452,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
28389
28452
  total: handoffs.total
28390
28453
  },
28391
28454
  liveLatency,
28455
+ monitoring: monitoringSummary,
28456
+ monitoringNotifierDelivery: monitoringNotifierDeliverySummary,
28392
28457
  opsActionHistory,
28393
28458
  opsRecovery: opsRecovery ? {
28394
28459
  issues: opsRecovery.issues.length,
@@ -28502,6 +28567,278 @@ var createVoiceProductionReadinessRoutes = (options) => {
28502
28567
  }
28503
28568
  return routes;
28504
28569
  };
28570
+ // src/voiceMonitoring.ts
28571
+ import { Elysia as Elysia44 } from "elysia";
28572
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28573
+ var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
28574
+ var rollupStatus4 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
28575
+ var createVoiceMemoryMonitorIssueStore = (initial = []) => {
28576
+ const issues = new Map(initial.map((issue) => [issue.id, { ...issue }]));
28577
+ return {
28578
+ list: () => Array.from(issues.values()).map((issue) => ({ ...issue })),
28579
+ upsert: (issue) => {
28580
+ const previous = issues.get(issue.id);
28581
+ const next = previous ? {
28582
+ ...previous,
28583
+ ...issue,
28584
+ createdAt: previous.createdAt,
28585
+ status: previous.status === "resolved" || previous.status === "muted" ? previous.status : issue.status
28586
+ } : issue;
28587
+ issues.set(issue.id, { ...next });
28588
+ return { ...next };
28589
+ },
28590
+ update: (id, patch) => {
28591
+ const previous = issues.get(id);
28592
+ if (!previous) {
28593
+ return;
28594
+ }
28595
+ const next = { ...previous, ...patch };
28596
+ issues.set(id, next);
28597
+ return { ...next };
28598
+ }
28599
+ };
28600
+ };
28601
+ var createVoiceMemoryMonitorNotifierDeliveryReceiptStore = (initial = []) => {
28602
+ const receipts = new Map(initial.map((receipt) => [receipt.id, { ...receipt }]));
28603
+ return {
28604
+ list: () => Array.from(receipts.values()).map((receipt) => ({ ...receipt })),
28605
+ set: (id, receipt) => {
28606
+ receipts.set(id, { ...receipt });
28607
+ return { ...receipt };
28608
+ }
28609
+ };
28610
+ };
28611
+ var buildVoiceMonitorRunReport = async (options) => {
28612
+ const checkedAt = options.now ?? Date.now();
28613
+ const runs = await Promise.all(options.monitors.map(async (monitor) => {
28614
+ const evaluation = await monitor.evaluate({
28615
+ evidence: options.evidence,
28616
+ now: checkedAt
28617
+ });
28618
+ return {
28619
+ ...evaluation,
28620
+ checkedAt,
28621
+ description: monitor.description,
28622
+ id: monitor.id,
28623
+ label: monitor.label,
28624
+ severity: monitor.severity ?? "warn",
28625
+ windowMs: monitor.windowMs
28626
+ };
28627
+ }));
28628
+ for (const run of runs) {
28629
+ if (run.status === "pass") {
28630
+ continue;
28631
+ }
28632
+ await options.issueStore?.upsert({
28633
+ createdAt: checkedAt,
28634
+ detail: run.detail,
28635
+ id: issueIdForRun(run),
28636
+ impactedSessions: [...run.impactedSessions ?? []],
28637
+ label: run.label,
28638
+ lastSeenAt: checkedAt,
28639
+ monitorId: run.id,
28640
+ operationsRecordHrefs: [...run.operationsRecordHrefs ?? []],
28641
+ severity: run.status === "fail" ? run.severity : "warn",
28642
+ status: "open",
28643
+ threshold: run.threshold,
28644
+ value: run.value
28645
+ });
28646
+ }
28647
+ const issues = await options.issueStore?.list() ?? [];
28648
+ const openIssues = issues.filter((issue) => issue.status === "open");
28649
+ const criticalOpen = openIssues.filter((issue) => issue.severity === "critical").length;
28650
+ return {
28651
+ checkedAt,
28652
+ issues,
28653
+ runs,
28654
+ status: criticalOpen > 0 ? "fail" : openIssues.length > 0 || rollupStatus4(runs) === "warn" ? "warn" : rollupStatus4(runs),
28655
+ summary: {
28656
+ acknowledged: issues.filter((issue) => issue.status === "acknowledged").length,
28657
+ criticalOpen,
28658
+ failed: runs.filter((run) => run.status === "fail").length,
28659
+ muted: issues.filter((issue) => issue.status === "muted").length,
28660
+ open: openIssues.length,
28661
+ passed: runs.filter((run) => run.status === "pass").length,
28662
+ resolved: issues.filter((issue) => issue.status === "resolved").length,
28663
+ total: runs.length,
28664
+ warned: runs.filter((run) => run.status === "warn").length
28665
+ }
28666
+ };
28667
+ };
28668
+ var acknowledgeVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28669
+ acknowledgedAt: input.now ?? Date.now(),
28670
+ acknowledgedBy: input.actorId,
28671
+ status: "acknowledged"
28672
+ });
28673
+ var resolveVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28674
+ resolvedAt: input.now ?? Date.now(),
28675
+ resolvedBy: input.actorId,
28676
+ status: "resolved"
28677
+ });
28678
+ var muteVoiceMonitorIssue = async (store, id, input = {}) => store.update(id, {
28679
+ mutedAt: input.now ?? Date.now(),
28680
+ mutedBy: input.actorId,
28681
+ status: "muted"
28682
+ });
28683
+ var createVoiceMonitorWebhookNotifier = (options) => ({
28684
+ id: options.id,
28685
+ label: options.label ?? options.id,
28686
+ deliver: async ({ issue }) => {
28687
+ const response = await (options.fetch ?? fetch)(options.url, {
28688
+ body: JSON.stringify(options.mapIssue?.(issue) ?? {
28689
+ detail: issue.detail,
28690
+ impactedSessions: issue.impactedSessions,
28691
+ issueId: issue.id,
28692
+ label: issue.label,
28693
+ monitorId: issue.monitorId,
28694
+ operationsRecordHrefs: issue.operationsRecordHrefs,
28695
+ severity: issue.severity,
28696
+ status: issue.status,
28697
+ value: issue.value
28698
+ }),
28699
+ headers: {
28700
+ "content-type": "application/json",
28701
+ ...options.headers
28702
+ },
28703
+ method: "POST"
28704
+ });
28705
+ return {
28706
+ detail: `HTTP ${response.status}`,
28707
+ status: response.ok ? "sent" : "failed"
28708
+ };
28709
+ }
28710
+ });
28711
+ var deliverVoiceMonitorIssueNotifications = async (options) => {
28712
+ const checkedAt = options.now ?? Date.now();
28713
+ const statuses = new Set(options.statuses ?? ["open"]);
28714
+ const issues = (await options.issueStore.list()).filter((issue) => statuses.has(issue.status));
28715
+ const receipts = [];
28716
+ for (const issue of issues) {
28717
+ for (const notifier of options.notifiers) {
28718
+ const result = await notifier.deliver({ issue, now: checkedAt });
28719
+ const receipt = {
28720
+ detail: result.detail,
28721
+ id: `voice-monitor-notifier:${notifier.id}:${issue.id}:${checkedAt}`,
28722
+ issueId: issue.id,
28723
+ notifierId: notifier.id,
28724
+ notifierLabel: notifier.label,
28725
+ sentAt: checkedAt,
28726
+ status: result.status
28727
+ };
28728
+ receipts.push(receipt);
28729
+ await options.receiptStore?.set(receipt.id, receipt);
28730
+ }
28731
+ }
28732
+ const allReceipts = options.receiptStore ? await options.receiptStore.list() : receipts;
28733
+ const failed = allReceipts.filter((receipt) => receipt.status === "failed").length;
28734
+ const sent = allReceipts.filter((receipt) => receipt.status === "sent").length;
28735
+ const skipped = allReceipts.filter((receipt) => receipt.status === "skipped").length;
28736
+ return {
28737
+ checkedAt,
28738
+ receipts: allReceipts,
28739
+ status: failed > 0 ? "fail" : allReceipts.length === 0 ? "warn" : "pass",
28740
+ summary: {
28741
+ failed,
28742
+ notifiers: options.notifiers.length,
28743
+ sent,
28744
+ skipped,
28745
+ total: allReceipts.length
28746
+ }
28747
+ };
28748
+ };
28749
+ var renderVoiceMonitorMarkdown = (report) => {
28750
+ const rows = report.runs.map((run) => `| ${run.id} | ${run.status} | ${run.severity} | ${run.value ?? ""} | ${run.threshold ?? ""} | ${run.detail ?? ""} |`).join(`
28751
+ `);
28752
+ return `# Voice Monitor Report
28753
+
28754
+ - Status: ${report.status}
28755
+ - Checks: ${report.summary.passed}/${report.summary.total} passing
28756
+ - Open issues: ${report.summary.open}
28757
+ - Critical open issues: ${report.summary.criticalOpen}
28758
+
28759
+ | Monitor | Status | Severity | Value | Threshold | Detail |
28760
+ | --- | --- | --- | --- | --- | --- |
28761
+ ${rows || "| none | pass | info | | | No monitors configured. |"}
28762
+ `;
28763
+ };
28764
+ var renderVoiceMonitorHTML = (report, options = {}) => {
28765
+ const title = options.title ?? "Voice Monitors";
28766
+ 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("");
28767
+ 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("");
28768
+ const snippet = escapeHtml41(`app.use(createVoiceMonitorRoutes({
28769
+ evidence,
28770
+ issueStore,
28771
+ monitors: [defineVoiceMonitor(...)]
28772
+ }));`);
28773
+ 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>`;
28774
+ };
28775
+ var actorFromRequest = async (request) => {
28776
+ if (!request.headers.get("content-type")?.includes("application/json")) {
28777
+ return;
28778
+ }
28779
+ const body = await request.json().catch(() => {
28780
+ return;
28781
+ });
28782
+ return typeof body?.actorId === "string" ? body.actorId : undefined;
28783
+ };
28784
+ var createVoiceMonitorRoutes = (options) => {
28785
+ const path = options.path ?? "/api/voice/monitors";
28786
+ const htmlPath = options.htmlPath === undefined ? "/voice/monitors" : options.htmlPath;
28787
+ const issuePath = options.issuePath ?? "/api/voice/monitor-issues";
28788
+ const notifierPath = options.notifierPath === undefined ? "/api/voice/monitor-notifications" : options.notifierPath;
28789
+ const issueStore = options.issueStore ?? createVoiceMemoryMonitorIssueStore();
28790
+ const receiptStore = options.receiptStore ?? createVoiceMemoryMonitorNotifierDeliveryReceiptStore();
28791
+ const report = () => buildVoiceMonitorRunReport({
28792
+ evidence: options.evidence,
28793
+ issueStore,
28794
+ monitors: options.monitors,
28795
+ now: options.now
28796
+ });
28797
+ const routes = new Elysia44({
28798
+ name: options.name ?? "absolutejs-voice-monitoring"
28799
+ }).get(path, report).get(`${path}.md`, async () => {
28800
+ return new Response(renderVoiceMonitorMarkdown(await report()), {
28801
+ headers: {
28802
+ "Content-Type": "text/markdown; charset=utf-8",
28803
+ ...options.headers
28804
+ }
28805
+ });
28806
+ }).get(issuePath, () => issueStore.list()).get(`${issuePath}/notifications`, () => receiptStore.list()).post(`${issuePath}/:id/acknowledge`, async ({ params, request }) => {
28807
+ const issue = await acknowledgeVoiceMonitorIssue(issueStore, params.id, {
28808
+ actorId: await actorFromRequest(request)
28809
+ });
28810
+ return issue ?? new Response("Issue not found", { status: 404 });
28811
+ }).post(`${issuePath}/:id/resolve`, async ({ params, request }) => {
28812
+ const issue = await resolveVoiceMonitorIssue(issueStore, params.id, {
28813
+ actorId: await actorFromRequest(request)
28814
+ });
28815
+ return issue ?? new Response("Issue not found", { status: 404 });
28816
+ }).post(`${issuePath}/:id/mute`, async ({ params, request }) => {
28817
+ const issue = await muteVoiceMonitorIssue(issueStore, params.id, {
28818
+ actorId: await actorFromRequest(request)
28819
+ });
28820
+ return issue ?? new Response("Issue not found", { status: 404 });
28821
+ });
28822
+ if (notifierPath !== false) {
28823
+ routes.post(notifierPath, () => deliverVoiceMonitorIssueNotifications({
28824
+ issueStore,
28825
+ notifiers: options.notifiers ?? [],
28826
+ receiptStore
28827
+ }));
28828
+ }
28829
+ if (htmlPath !== false) {
28830
+ routes.get(htmlPath, async () => {
28831
+ const body = await (options.render ?? renderVoiceMonitorHTML)(await report(), { title: options.title });
28832
+ return new Response(body, {
28833
+ headers: {
28834
+ "Content-Type": "text/html; charset=utf-8",
28835
+ ...options.headers
28836
+ }
28837
+ });
28838
+ });
28839
+ }
28840
+ return routes;
28841
+ };
28505
28842
  // src/readinessProfiles.ts
28506
28843
  var profileSurfaceLabels = {
28507
28844
  "meeting-recorder": {
@@ -28862,8 +29199,8 @@ var recommendVoiceReadinessProfile = (options) => {
28862
29199
  };
28863
29200
  };
28864
29201
  // src/providerStackRecommendations.ts
28865
- import { Elysia as Elysia44 } from "elysia";
28866
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29202
+ import { Elysia as Elysia45 } from "elysia";
29203
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28867
29204
  var profileProviderPriorities = {
28868
29205
  "meeting-recorder": {
28869
29206
  llm: ["openai", "anthropic", "gemini"],
@@ -29182,17 +29519,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
29182
29519
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
29183
29520
  const title = options.title ?? "Voice Provider Contract Matrix";
29184
29521
  const rows = report.rows.map((row) => {
29185
- 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("");
29186
- return `<article class="row ${escapeHtml41(row.status)}">
29522
+ 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("");
29523
+ return `<article class="row ${escapeHtml42(row.status)}">
29187
29524
  <div>
29188
- <p class="eyebrow">${escapeHtml41(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
29189
- <h2>${escapeHtml41(row.provider)}</h2>
29190
- <p class="status ${escapeHtml41(row.status)}">${escapeHtml41(row.status.toUpperCase())}</p>
29525
+ <p class="eyebrow">${escapeHtml42(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
29526
+ <h2>${escapeHtml42(row.provider)}</h2>
29527
+ <p class="status ${escapeHtml42(row.status)}">${escapeHtml42(row.status.toUpperCase())}</p>
29191
29528
  </div>
29192
29529
  <ul>${checks}</ul>
29193
29530
  </article>`;
29194
29531
  }).join("");
29195
- const snippet = escapeHtml41(`const providerContracts = () =>
29532
+ const snippet = escapeHtml42(`const providerContracts = () =>
29196
29533
  createVoiceProviderContractMatrixPreset('phone-agent', {
29197
29534
  env: process.env,
29198
29535
  providers: {
@@ -29213,7 +29550,7 @@ createVoiceProductionReadinessRoutes({
29213
29550
  providerContractMatrix: () =>
29214
29551
  buildVoiceProviderContractMatrix(providerContracts())
29215
29552
  });`);
29216
- 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>`;
29553
+ 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>`;
29217
29554
  };
29218
29555
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
29219
29556
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -29228,7 +29565,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
29228
29565
  var createVoiceProviderContractMatrixRoutes = (options) => {
29229
29566
  const path = options.path ?? "/api/provider-contracts";
29230
29567
  const htmlPath = options.htmlPath ?? "/provider-contracts";
29231
- const routes = new Elysia44({
29568
+ const routes = new Elysia45({
29232
29569
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
29233
29570
  });
29234
29571
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -29346,7 +29683,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
29346
29683
  return assertion;
29347
29684
  };
29348
29685
  // src/opsConsoleRoutes.ts
29349
- import { Elysia as Elysia45 } from "elysia";
29686
+ import { Elysia as Elysia46 } from "elysia";
29350
29687
  var DEFAULT_LINKS = [
29351
29688
  {
29352
29689
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -29381,7 +29718,7 @@ var DEFAULT_LINKS = [
29381
29718
  label: "Handoffs"
29382
29719
  }
29383
29720
  ];
29384
- var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29721
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29385
29722
  var countProviderStatuses = (providers) => {
29386
29723
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
29387
29724
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -29450,20 +29787,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
29450
29787
  trace
29451
29788
  };
29452
29789
  };
29453
- 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>`;
29790
+ 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>`;
29454
29791
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
29455
29792
  const links = report.links.map((link) => `<article class="surface">
29456
- <div><h2>${escapeHtml42(link.label)}</h2>${link.description ? `<p>${escapeHtml42(link.description)}</p>` : ""}</div>
29457
- <p><a href="${escapeHtml42(link.href)}">Open ${escapeHtml42(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml42(link.statusHref)}">Status</a>` : ""}</p>
29793
+ <div><h2>${escapeHtml43(link.label)}</h2>${link.description ? `<p>${escapeHtml43(link.description)}</p>` : ""}</div>
29794
+ <p><a href="${escapeHtml43(link.href)}">Open ${escapeHtml43(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml43(link.statusHref)}">Status</a>` : ""}</p>
29458
29795
  </article>`).join("");
29459
- 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>';
29460
- 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>';
29796
+ 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>';
29797
+ 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>';
29461
29798
  const title = options.title ?? "AbsoluteJS Voice Ops Console";
29462
- 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>`;
29799
+ 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>`;
29463
29800
  };
29464
29801
  var createVoiceOpsConsoleRoutes = (options) => {
29465
29802
  const path = options.path ?? "/ops-console";
29466
- const routes = new Elysia45({
29803
+ const routes = new Elysia46({
29467
29804
  name: options.name ?? "absolutejs-voice-ops-console"
29468
29805
  });
29469
29806
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -29480,7 +29817,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
29480
29817
  return routes;
29481
29818
  };
29482
29819
  // src/incidentBundle.ts
29483
- import { Elysia as Elysia46 } from "elysia";
29820
+ import { Elysia as Elysia47 } from "elysia";
29484
29821
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
29485
29822
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
29486
29823
  return false;
@@ -29681,7 +30018,7 @@ var buildVoiceIncidentBundle = async (options) => {
29681
30018
  var createVoiceIncidentBundleRoutes = (options) => {
29682
30019
  const path = options.path ?? "/api/voice-incidents/:sessionId";
29683
30020
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
29684
- const routes = new Elysia46({
30021
+ const routes = new Elysia47({
29685
30022
  name: options.name ?? "absolutejs-voice-incident-bundle"
29686
30023
  });
29687
30024
  const getSessionId = (params) => params.sessionId ?? "";
@@ -29882,19 +30219,19 @@ var summarizeVoiceOpsStatus = async (options) => {
29882
30219
  };
29883
30220
  };
29884
30221
  // src/opsStatusRoutes.ts
29885
- import { Elysia as Elysia47 } from "elysia";
29886
- var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30222
+ import { Elysia as Elysia48 } from "elysia";
30223
+ var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29887
30224
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
29888
30225
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
29889
30226
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
29890
30227
  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;
29891
- return `<article class="surface ${escapeHtml43(surface.status)}"><span>${escapeHtml43(surface.status.toUpperCase())}</span><h2>${escapeHtml43(key)}</h2><strong>${escapeHtml43(value)}</strong></article>`;
30228
+ return `<article class="surface ${escapeHtml44(surface.status)}"><span>${escapeHtml44(surface.status.toUpperCase())}</span><h2>${escapeHtml44(key)}</h2><strong>${escapeHtml44(value)}</strong></article>`;
29892
30229
  }).join("");
29893
- 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>`;
30230
+ 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>`;
29894
30231
  };
29895
30232
  var createVoiceOpsStatusRoutes = (options) => {
29896
30233
  const path = options.path ?? "/api/voice/ops-status";
29897
- const routes = new Elysia47({
30234
+ const routes = new Elysia48({
29898
30235
  name: options.name ?? "absolutejs-voice-ops-status"
29899
30236
  });
29900
30237
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -30327,8 +30664,8 @@ var createVoiceTTSProviderRouter = (options) => {
30327
30664
  };
30328
30665
  };
30329
30666
  // src/traceDeliveryRoutes.ts
30330
- import { Elysia as Elysia48 } from "elysia";
30331
- var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30667
+ import { Elysia as Elysia49 } from "elysia";
30668
+ var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30332
30669
  var getString19 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
30333
30670
  var getNumber11 = (value) => {
30334
30671
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -30409,14 +30746,14 @@ var renderSinkResults2 = (delivery) => {
30409
30746
  if (entries.length === 0) {
30410
30747
  return "<p>No sink delivery attempts recorded yet.</p>";
30411
30748
  }
30412
- 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>`;
30749
+ 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>`;
30413
30750
  };
30414
- 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>`;
30751
+ 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>`;
30415
30752
  var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
30416
30753
  const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
30417
- 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>`;
30418
- 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("");
30419
- 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>`;
30754
+ 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>`;
30755
+ 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("");
30756
+ 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>`;
30420
30757
  };
30421
30758
  var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
30422
30759
  var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
@@ -30436,7 +30773,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
30436
30773
  const path = options.path ?? "/api/voice-trace-deliveries";
30437
30774
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
30438
30775
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
30439
- const routes = new Elysia48({
30776
+ const routes = new Elysia49({
30440
30777
  name: options.name ?? "absolutejs-voice-trace-deliveries"
30441
30778
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
30442
30779
  if (htmlPath !== false) {
@@ -30533,7 +30870,7 @@ var createVoiceMemoryStore = () => {
30533
30870
  return { get, getOrCreate, list, remove, set };
30534
30871
  };
30535
30872
  // src/opsWebhook.ts
30536
- import { Elysia as Elysia49 } from "elysia";
30873
+ import { Elysia as Elysia50 } from "elysia";
30537
30874
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
30538
30875
  var signVoiceOpsWebhookBody = async (input) => {
30539
30876
  const encoder = new TextEncoder;
@@ -30663,7 +31000,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
30663
31000
  };
30664
31001
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
30665
31002
  const path = options.path ?? "/api/voice-ops/webhook";
30666
- return new Elysia49().post(path, async ({ body, request, set }) => {
31003
+ return new Elysia50().post(path, async ({ body, request, set }) => {
30667
31004
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
30668
31005
  if (options.signingSecret) {
30669
31006
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -31118,7 +31455,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
31118
31455
  };
31119
31456
  };
31120
31457
  // src/postCallAnalysis.ts
31121
- import { Elysia as Elysia50 } from "elysia";
31458
+ import { Elysia as Elysia51 } from "elysia";
31122
31459
  var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
31123
31460
  var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
31124
31461
  var getPathValue3 = (source, path) => {
@@ -31297,7 +31634,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
31297
31634
  };
31298
31635
  var createVoicePostCallAnalysisRoutes = (options = {}) => {
31299
31636
  const path = options.path ?? "/api/voice/post-call-analysis";
31300
- const routes = new Elysia50({
31637
+ const routes = new Elysia51({
31301
31638
  name: options.name ?? "absolutejs-voice-post-call-analysis"
31302
31639
  });
31303
31640
  routes.get(path, async ({ query }) => {
@@ -31322,7 +31659,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
31322
31659
  return routes;
31323
31660
  };
31324
31661
  // src/guardrails.ts
31325
- import { Elysia as Elysia51 } from "elysia";
31662
+ import { Elysia as Elysia52 } from "elysia";
31326
31663
  var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
31327
31664
  var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
31328
31665
  var matchesRule = async (rule, input) => {
@@ -31624,7 +31961,7 @@ var resolveGuardrailReport = async (options, input) => {
31624
31961
  };
31625
31962
  var createVoiceGuardrailRoutes = (options = {}) => {
31626
31963
  const path = options.path ?? "/api/voice/guardrails";
31627
- const routes = new Elysia51({
31964
+ const routes = new Elysia52({
31628
31965
  name: options.name ?? "absolutejs-voice-guardrails"
31629
31966
  });
31630
31967
  routes.all(path, async ({ request }) => {
@@ -32120,6 +32457,7 @@ export {
32120
32457
  resolveVoiceOpsTaskAssignment,
32121
32458
  resolveVoiceOpsTaskAgeBucket,
32122
32459
  resolveVoiceOpsPreset,
32460
+ resolveVoiceMonitorIssue,
32123
32461
  resolveVoiceDiagnosticsTraceFilter,
32124
32462
  resolveVoiceAuditTrailFilter,
32125
32463
  resolveVoiceAuditDeliveryFilter,
@@ -32164,6 +32502,8 @@ export {
32164
32502
  renderVoiceOperationsRecordGuardrailMarkdown,
32165
32503
  renderVoiceObservabilityExportReplayHTML,
32166
32504
  renderVoiceObservabilityExportMarkdown,
32505
+ renderVoiceMonitorMarkdown,
32506
+ renderVoiceMonitorHTML,
32167
32507
  renderVoiceLiveLatencyHTML,
32168
32508
  renderVoiceLatencySLOMarkdown,
32169
32509
  renderVoiceHandoffHealthHTML,
@@ -32206,6 +32546,7 @@ export {
32206
32546
  pruneVoiceIncidentBundleArtifacts,
32207
32547
  parseVoiceTelephonyWebhookEvent,
32208
32548
  normalizeVoiceProofTrendReport,
32549
+ muteVoiceMonitorIssue,
32209
32550
  matchesVoiceOpsTaskAssignmentRule,
32210
32551
  markVoiceOpsTaskSLABreached,
32211
32552
  loadVoiceObservabilityExportReplaySource,
@@ -32254,6 +32595,7 @@ export {
32254
32595
  encodeTwilioMulawBase64,
32255
32596
  deliverVoiceTraceEventsToSinks,
32256
32597
  deliverVoiceObservabilityExport,
32598
+ deliverVoiceMonitorIssueNotifications,
32257
32599
  deliverVoiceIntegrationEventToSinks,
32258
32600
  deliverVoiceIntegrationEvent,
32259
32601
  deliverVoiceHandoffDelivery,
@@ -32408,10 +32750,14 @@ export {
32408
32750
  createVoiceObservabilityExportSchema,
32409
32751
  createVoiceObservabilityExportRoutes,
32410
32752
  createVoiceObservabilityExportReplayRoutes,
32753
+ createVoiceMonitorWebhookNotifier,
32754
+ createVoiceMonitorRoutes,
32411
32755
  createVoiceMemoryTraceSinkDeliveryStore,
32412
32756
  createVoiceMemoryTraceEventStore,
32413
32757
  createVoiceMemoryStore,
32414
32758
  createVoiceMemoryObservabilityExportDeliveryReceiptStore,
32759
+ createVoiceMemoryMonitorNotifierDeliveryReceiptStore,
32760
+ createVoiceMemoryMonitorIssueStore,
32415
32761
  createVoiceMemoryLiveOpsControlStore,
32416
32762
  createVoiceMemoryIncidentBundleStore,
32417
32763
  createVoiceMemoryHandoffDeliveryStore,
@@ -32559,6 +32905,7 @@ export {
32559
32905
  buildVoiceObservabilityExportDeliveryHistory,
32560
32906
  buildVoiceObservabilityExport,
32561
32907
  buildVoiceObservabilityArtifactIndex,
32908
+ buildVoiceMonitorRunReport,
32562
32909
  buildVoiceLiveOpsControlState,
32563
32910
  buildVoiceLatencySLOGate,
32564
32911
  buildVoiceIncidentBundle,
@@ -32611,6 +32958,7 @@ export {
32611
32958
  applyVoiceCampaignTelephonyOutcome,
32612
32959
  applyRiskTieredPhraseHintCorrections,
32613
32960
  applyPhraseHintCorrections,
32961
+ acknowledgeVoiceMonitorIssue,
32614
32962
  VOICE_LIVE_OPS_ACTIONS,
32615
32963
  TURN_PROFILE_DEFAULTS,
32616
32964
  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 { VoiceMonitorNotifierDeliveryReport, 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,8 @@ export type VoiceProductionReadinessReport = {
118
119
  operationsRecords?: string;
119
120
  observabilityExport?: string;
120
121
  observabilityExportDeliveries?: string;
122
+ monitoring?: string;
123
+ monitoringNotifierDelivery?: string;
121
124
  opsActions?: string;
122
125
  opsRecovery?: string;
123
126
  phoneAgentSmoke?: string;
@@ -176,6 +179,19 @@ export type VoiceProductionReadinessReport = {
176
179
  total: number;
177
180
  warnings: number;
178
181
  };
182
+ monitoring?: {
183
+ criticalOpen: number;
184
+ open: number;
185
+ status: VoiceProductionReadinessStatus;
186
+ total: number;
187
+ };
188
+ monitoringNotifierDelivery?: {
189
+ failed: number;
190
+ notifiers: number;
191
+ sent: number;
192
+ status: VoiceProductionReadinessStatus;
193
+ total: number;
194
+ };
179
195
  opsActionHistory?: VoiceProductionReadinessOpsActionHistorySummary;
180
196
  opsRecovery?: {
181
197
  issues: number;
@@ -393,6 +409,14 @@ export type VoiceProductionReadinessRoutesOptions = {
393
409
  links?: VoiceProductionReadinessReport['links'];
394
410
  llmProviders?: readonly string[];
395
411
  name?: string;
412
+ monitoring?: false | VoiceMonitorRunReport | ((input: {
413
+ query: Record<string, unknown>;
414
+ request: Request;
415
+ }) => Promise<VoiceMonitorRunReport> | VoiceMonitorRunReport);
416
+ monitoringNotifierDelivery?: false | VoiceMonitorNotifierDeliveryReport | ((input: {
417
+ query: Record<string, unknown>;
418
+ request: Request;
419
+ }) => Promise<VoiceMonitorNotifierDeliveryReport> | VoiceMonitorNotifierDeliveryReport);
396
420
  opsActionHistory?: false | VoiceProductionReadinessOpsActionHistoryOptions;
397
421
  opsRecovery?: false | VoiceOpsRecoveryReport | ((input: {
398
422
  query: Record<string, unknown>;
@@ -0,0 +1,325 @@
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 VoiceMonitorNotifier = {
59
+ deliver: (input: VoiceMonitorNotifierDeliveryInput) => Promise<VoiceMonitorNotifierDeliveryResult> | VoiceMonitorNotifierDeliveryResult;
60
+ id: string;
61
+ label: string;
62
+ };
63
+ export type VoiceMonitorNotifierDeliveryInput = {
64
+ issue: VoiceMonitorIssue;
65
+ now: number;
66
+ };
67
+ export type VoiceMonitorNotifierDeliveryResult = {
68
+ detail?: string;
69
+ status: 'failed' | 'sent' | 'skipped';
70
+ };
71
+ export type VoiceMonitorNotifierDeliveryReceipt = {
72
+ detail?: string;
73
+ id: string;
74
+ issueId: string;
75
+ notifierId: string;
76
+ notifierLabel: string;
77
+ sentAt: number;
78
+ status: 'failed' | 'sent' | 'skipped';
79
+ };
80
+ export type VoiceMonitorNotifierDeliveryReceiptStore = {
81
+ list: () => Promise<VoiceMonitorNotifierDeliveryReceipt[]> | VoiceMonitorNotifierDeliveryReceipt[];
82
+ set: (id: string, receipt: VoiceMonitorNotifierDeliveryReceipt) => Promise<VoiceMonitorNotifierDeliveryReceipt> | VoiceMonitorNotifierDeliveryReceipt;
83
+ };
84
+ export type VoiceMonitorNotifierDeliveryReport = {
85
+ checkedAt: number;
86
+ receipts: VoiceMonitorNotifierDeliveryReceipt[];
87
+ status: VoiceMonitorStatus;
88
+ summary: {
89
+ failed: number;
90
+ notifiers: number;
91
+ sent: number;
92
+ skipped: number;
93
+ total: number;
94
+ };
95
+ };
96
+ export type VoiceMonitorRunReport = {
97
+ checkedAt: number;
98
+ issues: VoiceMonitorIssue[];
99
+ runs: VoiceMonitorRun[];
100
+ status: VoiceMonitorStatus;
101
+ summary: {
102
+ acknowledged: number;
103
+ criticalOpen: number;
104
+ failed: number;
105
+ muted: number;
106
+ open: number;
107
+ passed: number;
108
+ resolved: number;
109
+ total: number;
110
+ warned: number;
111
+ };
112
+ };
113
+ export type VoiceMonitorRunOptions<TEvidence = unknown> = {
114
+ evidence: TEvidence;
115
+ issueStore?: VoiceMonitorIssueStore;
116
+ monitors: readonly VoiceMonitorDefinition<TEvidence>[];
117
+ now?: number;
118
+ };
119
+ export type VoiceMonitorNotifierDeliveryOptions = {
120
+ issueStore: VoiceMonitorIssueStore;
121
+ notifiers: readonly VoiceMonitorNotifier[];
122
+ now?: number;
123
+ receiptStore?: VoiceMonitorNotifierDeliveryReceiptStore;
124
+ statuses?: readonly VoiceMonitorIssueStatus[];
125
+ };
126
+ export type VoiceMonitorWebhookNotifierOptions = {
127
+ fetch?: typeof fetch;
128
+ headers?: HeadersInit;
129
+ id: string;
130
+ label?: string;
131
+ mapIssue?: (issue: VoiceMonitorIssue) => unknown;
132
+ url: string;
133
+ };
134
+ export type VoiceMonitorRoutesOptions<TEvidence = unknown> = VoiceMonitorRunOptions<TEvidence> & {
135
+ headers?: HeadersInit;
136
+ htmlPath?: false | string;
137
+ issuePath?: string;
138
+ name?: string;
139
+ notifierPath?: false | string;
140
+ notifiers?: readonly VoiceMonitorNotifier[];
141
+ path?: string;
142
+ receiptStore?: VoiceMonitorNotifierDeliveryReceiptStore;
143
+ render?: (report: VoiceMonitorRunReport) => Promise<string> | string;
144
+ title?: string;
145
+ };
146
+ export declare const createVoiceMemoryMonitorIssueStore: (initial?: readonly VoiceMonitorIssue[]) => VoiceMonitorIssueStore;
147
+ export declare const createVoiceMemoryMonitorNotifierDeliveryReceiptStore: (initial?: readonly VoiceMonitorNotifierDeliveryReceipt[]) => VoiceMonitorNotifierDeliveryReceiptStore;
148
+ export declare const buildVoiceMonitorRunReport: <TEvidence = unknown>(options: VoiceMonitorRunOptions<TEvidence>) => Promise<VoiceMonitorRunReport>;
149
+ export declare const acknowledgeVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
150
+ actorId?: string;
151
+ now?: number;
152
+ }) => Promise<VoiceMonitorIssue | undefined>;
153
+ export declare const resolveVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
154
+ actorId?: string;
155
+ now?: number;
156
+ }) => Promise<VoiceMonitorIssue | undefined>;
157
+ export declare const muteVoiceMonitorIssue: (store: VoiceMonitorIssueStore, id: string, input?: {
158
+ actorId?: string;
159
+ now?: number;
160
+ }) => Promise<VoiceMonitorIssue | undefined>;
161
+ export declare const createVoiceMonitorWebhookNotifier: (options: VoiceMonitorWebhookNotifierOptions) => VoiceMonitorNotifier;
162
+ export declare const deliverVoiceMonitorIssueNotifications: (options: VoiceMonitorNotifierDeliveryOptions) => Promise<VoiceMonitorNotifierDeliveryReport>;
163
+ export declare const renderVoiceMonitorMarkdown: (report: VoiceMonitorRunReport) => string;
164
+ export declare const renderVoiceMonitorHTML: (report: VoiceMonitorRunReport, options?: {
165
+ title?: string;
166
+ }) => string;
167
+ export declare const createVoiceMonitorRoutes: <TEvidence = unknown>(options: VoiceMonitorRoutesOptions<TEvidence>) => Elysia<"", {
168
+ decorator: {};
169
+ store: {};
170
+ derive: {};
171
+ resolve: {};
172
+ }, {
173
+ typebox: {};
174
+ error: {};
175
+ }, {
176
+ schema: {};
177
+ standaloneSchema: {};
178
+ macro: {};
179
+ macroFn: {};
180
+ parser: {};
181
+ response: {};
182
+ }, {
183
+ [x: string]: {
184
+ get: {
185
+ body: unknown;
186
+ params: {};
187
+ query: unknown;
188
+ headers: unknown;
189
+ response: {
190
+ 200: VoiceMonitorRunReport;
191
+ };
192
+ };
193
+ };
194
+ } & {
195
+ [x: `${string}.md`]: {
196
+ get: {
197
+ body: unknown;
198
+ params: {};
199
+ query: unknown;
200
+ headers: unknown;
201
+ response: {
202
+ 200: Response;
203
+ };
204
+ };
205
+ };
206
+ } & {
207
+ [x: string]: {
208
+ get: {
209
+ body: unknown;
210
+ params: {};
211
+ query: unknown;
212
+ headers: unknown;
213
+ response: {
214
+ 200: VoiceMonitorIssue[];
215
+ };
216
+ };
217
+ };
218
+ } & {
219
+ [x: string]: {
220
+ notifications: {
221
+ get: {
222
+ body: unknown;
223
+ params: {};
224
+ query: unknown;
225
+ headers: unknown;
226
+ response: {
227
+ 200: VoiceMonitorNotifierDeliveryReceipt[];
228
+ };
229
+ };
230
+ };
231
+ };
232
+ } & {
233
+ [x: string]: {
234
+ ":id": {
235
+ acknowledge: {
236
+ post: {
237
+ body: unknown;
238
+ params: {
239
+ id: string;
240
+ } & {};
241
+ query: unknown;
242
+ headers: unknown;
243
+ response: {
244
+ 200: Response | VoiceMonitorIssue;
245
+ 422: {
246
+ type: "validation";
247
+ on: string;
248
+ summary?: string;
249
+ message?: string;
250
+ found?: unknown;
251
+ property?: string;
252
+ expected?: string;
253
+ };
254
+ };
255
+ };
256
+ };
257
+ };
258
+ };
259
+ } & {
260
+ [x: string]: {
261
+ ":id": {
262
+ resolve: {
263
+ post: {
264
+ body: unknown;
265
+ params: {
266
+ id: string;
267
+ } & {};
268
+ query: unknown;
269
+ headers: unknown;
270
+ response: {
271
+ 200: Response | VoiceMonitorIssue;
272
+ 422: {
273
+ type: "validation";
274
+ on: string;
275
+ summary?: string;
276
+ message?: string;
277
+ found?: unknown;
278
+ property?: string;
279
+ expected?: string;
280
+ };
281
+ };
282
+ };
283
+ };
284
+ };
285
+ };
286
+ } & {
287
+ [x: string]: {
288
+ ":id": {
289
+ mute: {
290
+ post: {
291
+ body: unknown;
292
+ params: {
293
+ id: string;
294
+ } & {};
295
+ query: unknown;
296
+ headers: unknown;
297
+ response: {
298
+ 200: Response | VoiceMonitorIssue;
299
+ 422: {
300
+ type: "validation";
301
+ on: string;
302
+ summary?: string;
303
+ message?: string;
304
+ found?: unknown;
305
+ property?: string;
306
+ expected?: string;
307
+ };
308
+ };
309
+ };
310
+ };
311
+ };
312
+ };
313
+ }, {
314
+ derive: {};
315
+ resolve: {};
316
+ schema: {};
317
+ standaloneSchema: {};
318
+ response: {};
319
+ }, {
320
+ derive: {};
321
+ resolve: {};
322
+ schema: {};
323
+ standaloneSchema: {};
324
+ response: {};
325
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.277",
3
+ "version": "0.0.22-beta.279",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",