@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 +2 -0
- package/dist/index.js +267 -40
- package/dist/productionReadiness.d.ts +12 -0
- package/dist/voiceMonitoring.d.ts +252 -0
- package/package.json +1 -1
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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
|
|
28866
|
-
var
|
|
29084
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
29085
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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="${
|
|
29186
|
-
return `<article class="row ${
|
|
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">${
|
|
29189
|
-
<h2>${
|
|
29190
|
-
<p class="status ${
|
|
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 =
|
|
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>${
|
|
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
|
|
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
|
|
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
|
|
29603
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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>${
|
|
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>${
|
|
29457
|
-
<p><a href="${
|
|
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>${
|
|
29460
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
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>${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
29886
|
-
var
|
|
30104
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
30105
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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 ${
|
|
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>${
|
|
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
|
|
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
|
|
30331
|
-
var
|
|
30549
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
30550
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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>${
|
|
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>${
|
|
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="${
|
|
30418
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
30419
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
+
}>;
|