@absolutejs/voice 0.0.22-beta.277 → 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": {
@@ -28862,8 +29081,8 @@ var recommendVoiceReadinessProfile = (options) => {
28862
29081
  };
28863
29082
  };
28864
29083
  // 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;");
29084
+ import { Elysia as Elysia45 } from "elysia";
29085
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
28867
29086
  var profileProviderPriorities = {
28868
29087
  "meeting-recorder": {
28869
29088
  llm: ["openai", "anthropic", "gemini"],
@@ -29182,17 +29401,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
29182
29401
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
29183
29402
  const title = options.title ?? "Voice Provider Contract Matrix";
29184
29403
  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)}">
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)}">
29187
29406
  <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>
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>
29191
29410
  </div>
29192
29411
  <ul>${checks}</ul>
29193
29412
  </article>`;
29194
29413
  }).join("");
29195
- const snippet = escapeHtml41(`const providerContracts = () =>
29414
+ const snippet = escapeHtml42(`const providerContracts = () =>
29196
29415
  createVoiceProviderContractMatrixPreset('phone-agent', {
29197
29416
  env: process.env,
29198
29417
  providers: {
@@ -29213,7 +29432,7 @@ createVoiceProductionReadinessRoutes({
29213
29432
  providerContractMatrix: () =>
29214
29433
  buildVoiceProviderContractMatrix(providerContracts())
29215
29434
  });`);
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>`;
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>`;
29217
29436
  };
29218
29437
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
29219
29438
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -29228,7 +29447,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
29228
29447
  var createVoiceProviderContractMatrixRoutes = (options) => {
29229
29448
  const path = options.path ?? "/api/provider-contracts";
29230
29449
  const htmlPath = options.htmlPath ?? "/provider-contracts";
29231
- const routes = new Elysia44({
29450
+ const routes = new Elysia45({
29232
29451
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
29233
29452
  });
29234
29453
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -29346,7 +29565,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
29346
29565
  return assertion;
29347
29566
  };
29348
29567
  // src/opsConsoleRoutes.ts
29349
- import { Elysia as Elysia45 } from "elysia";
29568
+ import { Elysia as Elysia46 } from "elysia";
29350
29569
  var DEFAULT_LINKS = [
29351
29570
  {
29352
29571
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -29381,7 +29600,7 @@ var DEFAULT_LINKS = [
29381
29600
  label: "Handoffs"
29382
29601
  }
29383
29602
  ];
29384
- 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;");
29385
29604
  var countProviderStatuses = (providers) => {
29386
29605
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
29387
29606
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -29450,20 +29669,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
29450
29669
  trace
29451
29670
  };
29452
29671
  };
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>`;
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>`;
29454
29673
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
29455
29674
  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>
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>
29458
29677
  </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>';
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>';
29461
29680
  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>`;
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>`;
29463
29682
  };
29464
29683
  var createVoiceOpsConsoleRoutes = (options) => {
29465
29684
  const path = options.path ?? "/ops-console";
29466
- const routes = new Elysia45({
29685
+ const routes = new Elysia46({
29467
29686
  name: options.name ?? "absolutejs-voice-ops-console"
29468
29687
  });
29469
29688
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -29480,7 +29699,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
29480
29699
  return routes;
29481
29700
  };
29482
29701
  // src/incidentBundle.ts
29483
- import { Elysia as Elysia46 } from "elysia";
29702
+ import { Elysia as Elysia47 } from "elysia";
29484
29703
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
29485
29704
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
29486
29705
  return false;
@@ -29681,7 +29900,7 @@ var buildVoiceIncidentBundle = async (options) => {
29681
29900
  var createVoiceIncidentBundleRoutes = (options) => {
29682
29901
  const path = options.path ?? "/api/voice-incidents/:sessionId";
29683
29902
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
29684
- const routes = new Elysia46({
29903
+ const routes = new Elysia47({
29685
29904
  name: options.name ?? "absolutejs-voice-incident-bundle"
29686
29905
  });
29687
29906
  const getSessionId = (params) => params.sessionId ?? "";
@@ -29882,19 +30101,19 @@ var summarizeVoiceOpsStatus = async (options) => {
29882
30101
  };
29883
30102
  };
29884
30103
  // 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;");
30104
+ import { Elysia as Elysia48 } from "elysia";
30105
+ var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29887
30106
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
29888
30107
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
29889
30108
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
29890
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;
29891
- 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>`;
29892
30111
  }).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>`;
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>`;
29894
30113
  };
29895
30114
  var createVoiceOpsStatusRoutes = (options) => {
29896
30115
  const path = options.path ?? "/api/voice/ops-status";
29897
- const routes = new Elysia47({
30116
+ const routes = new Elysia48({
29898
30117
  name: options.name ?? "absolutejs-voice-ops-status"
29899
30118
  });
29900
30119
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -30327,8 +30546,8 @@ var createVoiceTTSProviderRouter = (options) => {
30327
30546
  };
30328
30547
  };
30329
30548
  // 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;");
30549
+ import { Elysia as Elysia49 } from "elysia";
30550
+ var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
30332
30551
  var getString19 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
30333
30552
  var getNumber11 = (value) => {
30334
30553
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -30409,14 +30628,14 @@ var renderSinkResults2 = (delivery) => {
30409
30628
  if (entries.length === 0) {
30410
30629
  return "<p>No sink delivery attempts recorded yet.</p>";
30411
30630
  }
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>`;
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>`;
30413
30632
  };
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>`;
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>`;
30415
30634
  var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
30416
30635
  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>`;
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>`;
30420
30639
  };
30421
30640
  var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
30422
30641
  var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
@@ -30436,7 +30655,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
30436
30655
  const path = options.path ?? "/api/voice-trace-deliveries";
30437
30656
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
30438
30657
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
30439
- const routes = new Elysia48({
30658
+ const routes = new Elysia49({
30440
30659
  name: options.name ?? "absolutejs-voice-trace-deliveries"
30441
30660
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
30442
30661
  if (htmlPath !== false) {
@@ -30533,7 +30752,7 @@ var createVoiceMemoryStore = () => {
30533
30752
  return { get, getOrCreate, list, remove, set };
30534
30753
  };
30535
30754
  // src/opsWebhook.ts
30536
- import { Elysia as Elysia49 } from "elysia";
30755
+ import { Elysia as Elysia50 } from "elysia";
30537
30756
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
30538
30757
  var signVoiceOpsWebhookBody = async (input) => {
30539
30758
  const encoder = new TextEncoder;
@@ -30663,7 +30882,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
30663
30882
  };
30664
30883
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
30665
30884
  const path = options.path ?? "/api/voice-ops/webhook";
30666
- return new Elysia49().post(path, async ({ body, request, set }) => {
30885
+ return new Elysia50().post(path, async ({ body, request, set }) => {
30667
30886
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
30668
30887
  if (options.signingSecret) {
30669
30888
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -31118,7 +31337,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
31118
31337
  };
31119
31338
  };
31120
31339
  // src/postCallAnalysis.ts
31121
- import { Elysia as Elysia50 } from "elysia";
31340
+ import { Elysia as Elysia51 } from "elysia";
31122
31341
  var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
31123
31342
  var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
31124
31343
  var getPathValue3 = (source, path) => {
@@ -31297,7 +31516,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
31297
31516
  };
31298
31517
  var createVoicePostCallAnalysisRoutes = (options = {}) => {
31299
31518
  const path = options.path ?? "/api/voice/post-call-analysis";
31300
- const routes = new Elysia50({
31519
+ const routes = new Elysia51({
31301
31520
  name: options.name ?? "absolutejs-voice-post-call-analysis"
31302
31521
  });
31303
31522
  routes.get(path, async ({ query }) => {
@@ -31322,7 +31541,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
31322
31541
  return routes;
31323
31542
  };
31324
31543
  // src/guardrails.ts
31325
- import { Elysia as Elysia51 } from "elysia";
31544
+ import { Elysia as Elysia52 } from "elysia";
31326
31545
  var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
31327
31546
  var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
31328
31547
  var matchesRule = async (rule, input) => {
@@ -31624,7 +31843,7 @@ var resolveGuardrailReport = async (options, input) => {
31624
31843
  };
31625
31844
  var createVoiceGuardrailRoutes = (options = {}) => {
31626
31845
  const path = options.path ?? "/api/voice/guardrails";
31627
- const routes = new Elysia51({
31846
+ const routes = new Elysia52({
31628
31847
  name: options.name ?? "absolutejs-voice-guardrails"
31629
31848
  });
31630
31849
  routes.all(path, async ({ request }) => {
@@ -32120,6 +32339,7 @@ export {
32120
32339
  resolveVoiceOpsTaskAssignment,
32121
32340
  resolveVoiceOpsTaskAgeBucket,
32122
32341
  resolveVoiceOpsPreset,
32342
+ resolveVoiceMonitorIssue,
32123
32343
  resolveVoiceDiagnosticsTraceFilter,
32124
32344
  resolveVoiceAuditTrailFilter,
32125
32345
  resolveVoiceAuditDeliveryFilter,
@@ -32164,6 +32384,8 @@ export {
32164
32384
  renderVoiceOperationsRecordGuardrailMarkdown,
32165
32385
  renderVoiceObservabilityExportReplayHTML,
32166
32386
  renderVoiceObservabilityExportMarkdown,
32387
+ renderVoiceMonitorMarkdown,
32388
+ renderVoiceMonitorHTML,
32167
32389
  renderVoiceLiveLatencyHTML,
32168
32390
  renderVoiceLatencySLOMarkdown,
32169
32391
  renderVoiceHandoffHealthHTML,
@@ -32206,6 +32428,7 @@ export {
32206
32428
  pruneVoiceIncidentBundleArtifacts,
32207
32429
  parseVoiceTelephonyWebhookEvent,
32208
32430
  normalizeVoiceProofTrendReport,
32431
+ muteVoiceMonitorIssue,
32209
32432
  matchesVoiceOpsTaskAssignmentRule,
32210
32433
  markVoiceOpsTaskSLABreached,
32211
32434
  loadVoiceObservabilityExportReplaySource,
@@ -32408,10 +32631,12 @@ export {
32408
32631
  createVoiceObservabilityExportSchema,
32409
32632
  createVoiceObservabilityExportRoutes,
32410
32633
  createVoiceObservabilityExportReplayRoutes,
32634
+ createVoiceMonitorRoutes,
32411
32635
  createVoiceMemoryTraceSinkDeliveryStore,
32412
32636
  createVoiceMemoryTraceEventStore,
32413
32637
  createVoiceMemoryStore,
32414
32638
  createVoiceMemoryObservabilityExportDeliveryReceiptStore,
32639
+ createVoiceMemoryMonitorIssueStore,
32415
32640
  createVoiceMemoryLiveOpsControlStore,
32416
32641
  createVoiceMemoryIncidentBundleStore,
32417
32642
  createVoiceMemoryHandoffDeliveryStore,
@@ -32559,6 +32784,7 @@ export {
32559
32784
  buildVoiceObservabilityExportDeliveryHistory,
32560
32785
  buildVoiceObservabilityExport,
32561
32786
  buildVoiceObservabilityArtifactIndex,
32787
+ buildVoiceMonitorRunReport,
32562
32788
  buildVoiceLiveOpsControlState,
32563
32789
  buildVoiceLatencySLOGate,
32564
32790
  buildVoiceIncidentBundle,
@@ -32611,6 +32837,7 @@ export {
32611
32837
  applyVoiceCampaignTelephonyOutcome,
32612
32838
  applyRiskTieredPhraseHintCorrections,
32613
32839
  applyPhraseHintCorrections,
32840
+ acknowledgeVoiceMonitorIssue,
32614
32841
  VOICE_LIVE_OPS_ACTIONS,
32615
32842
  TURN_PROFILE_DEFAULTS,
32616
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>;
@@ -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.277",
3
+ "version": "0.0.22-beta.278",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",