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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -52,6 +52,7 @@ export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './r
52
52
  export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
53
53
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
54
54
  export { buildVoiceOperationsRecord, createVoiceOperationsRecordRoutes, renderVoiceOperationsRecordHTML } from './operationsRecord';
55
+ export { buildVoiceOpsRecoveryReadinessCheck, buildVoiceOpsRecoveryReport, createVoiceOpsRecoveryRoutes, renderVoiceOpsRecoveryHTML, renderVoiceOpsRecoveryMarkdown } from './opsRecovery';
55
56
  export { buildVoiceIncidentBundle, createStoredVoiceIncidentBundleArtifact, createVoiceIncidentBundleRoutes, createVoiceMemoryIncidentBundleStore, pruneVoiceIncidentBundleArtifacts, saveVoiceIncidentBundleArtifact } from './incidentBundle';
56
57
  export { summarizeVoiceOpsStatus } from './opsStatus';
57
58
  export { createVoiceOpsStatusRoutes, renderVoiceOpsStatusHTML } from './opsStatusRoutes';
@@ -114,6 +115,7 @@ export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptio
114
115
  export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
115
116
  export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
116
117
  export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordIntegrationEventSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordReviewSummary, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTaskSummary, VoiceOperationsRecordTool } from './operationsRecord';
118
+ export type { VoiceOpsRecoveryFailedSession, VoiceOpsRecoveryInterventionSummary, VoiceOpsRecoveryIssue, VoiceOpsRecoveryIssueCode, VoiceOpsRecoveryLinks, VoiceOpsRecoveryProviderSummary, VoiceOpsRecoveryReport, VoiceOpsRecoveryReportOptions, VoiceOpsRecoveryRoutesOptions, VoiceOpsRecoveryStatus } from './opsRecovery';
117
119
  export type { StoredVoiceIncidentBundleArtifact, VoiceIncidentBundle, VoiceIncidentBundleArtifactOptions, VoiceIncidentBundleFormat, VoiceIncidentBundleOptions, VoiceIncidentBundleRetentionOptions, VoiceIncidentBundleRetentionReport, VoiceIncidentBundleRoutesOptions, VoiceIncidentBundleStore, VoiceIncidentBundleStoreFilter, VoiceIncidentBundleSummary } from './incidentBundle';
118
120
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
119
121
  export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
package/dist/index.js CHANGED
@@ -24008,8 +24008,248 @@ var createVoiceOperationsRecordRoutes = (options) => {
24008
24008
  }
24009
24009
  return routes;
24010
24010
  };
24011
- // src/incidentBundle.ts
24011
+ // src/opsRecovery.ts
24012
24012
  import { Elysia as Elysia40 } from "elysia";
24013
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24014
+ var getString16 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
24015
+ var hrefForSession = (value, sessionId) => typeof value === "function" ? value(sessionId) : value;
24016
+ var rollupStatus3 = (issues) => issues.some((issue) => issue.severity === "fail") ? "fail" : issues.some((issue) => issue.severity === "warn") ? "warn" : "pass";
24017
+ var providerUnresolved = (provider) => provider.status === "degraded" || provider.status === "rate-limited" || provider.status === "suppressed";
24018
+ var collectFailedSessions = (events, limit) => events.filter((event) => {
24019
+ if (event.type !== "session.error") {
24020
+ return false;
24021
+ }
24022
+ const providerStatus = event.payload.providerStatus;
24023
+ return providerStatus !== "success" && providerStatus !== "fallback";
24024
+ }).sort((left, right) => right.at - left.at).slice(0, limit).map((event) => ({
24025
+ at: event.at,
24026
+ error: getString16(event.payload.error),
24027
+ provider: getString16(event.payload.provider),
24028
+ sessionId: event.sessionId,
24029
+ traceId: event.traceId
24030
+ }));
24031
+ var collectInterventions = (events, limit) => {
24032
+ const interventionEvents = events.filter((event) => event.type === "operator.action").sort((left, right) => right.at - left.at);
24033
+ return {
24034
+ events: interventionEvents.slice(0, limit).map((event) => ({
24035
+ action: getString16(event.payload.action),
24036
+ at: event.at,
24037
+ operatorId: getString16(event.payload.operatorId) ?? getString16(event.payload.actorId),
24038
+ sessionId: event.sessionId,
24039
+ traceId: event.traceId
24040
+ })),
24041
+ total: interventionEvents.length
24042
+ };
24043
+ };
24044
+ var addDeliveryIssues = (issues, input) => {
24045
+ if (!input.summary) {
24046
+ return;
24047
+ }
24048
+ const failed = input.summary.failed + input.summary.deadLettered;
24049
+ if (failed > 0) {
24050
+ issues.push({
24051
+ code: input.failedCode,
24052
+ detail: `${failed} failed or dead-lettered delivery record(s).`,
24053
+ href: input.href,
24054
+ label: input.failedLabel,
24055
+ severity: "fail",
24056
+ value: failed
24057
+ });
24058
+ }
24059
+ const pending = input.summary.pending + input.summary.retryEligible;
24060
+ if (pending > 0) {
24061
+ issues.push({
24062
+ code: input.pendingCode,
24063
+ detail: `${pending} pending or retry-eligible delivery record(s).`,
24064
+ href: input.href,
24065
+ label: input.pendingLabel,
24066
+ severity: "warn",
24067
+ value: pending
24068
+ });
24069
+ }
24070
+ };
24071
+ var buildVoiceOpsRecoveryReport = async (options = {}) => {
24072
+ const limit = options.limit ?? 50;
24073
+ const events = options.events ?? await options.traces?.list({ limit: Math.max(limit, 500) }) ?? [];
24074
+ const providers = await summarizeVoiceProviderHealth({
24075
+ events,
24076
+ providers: options.providers
24077
+ });
24078
+ const auditDeliveries = options.auditDeliveries ? await summarizeVoiceAuditSinkDeliveries(await options.auditDeliveries.list(), {
24079
+ deadLetters: options.auditDeliveryDeadLetters
24080
+ }) : undefined;
24081
+ const traceDeliveries = options.traceDeliveries ? await summarizeVoiceTraceSinkDeliveries(await options.traceDeliveries.list(), {
24082
+ deadLetters: options.traceDeliveryDeadLetters
24083
+ }) : undefined;
24084
+ const handoffDeliveries = options.handoffDeliveries ? await summarizeVoiceHandoffDeliveries(await options.handoffDeliveries.list(), {
24085
+ deadLetters: options.handoffDeliveryDeadLetters
24086
+ }) : undefined;
24087
+ const latency = options.latency === false ? undefined : await buildVoiceLatencySLOGate({
24088
+ events,
24089
+ ...options.latency ?? {}
24090
+ });
24091
+ const failedSessions = collectFailedSessions(events, limit);
24092
+ const interventions = collectInterventions(events, limit);
24093
+ const issues = [];
24094
+ const unresolvedProviders = providers.filter(providerUnresolved);
24095
+ for (const provider of unresolvedProviders) {
24096
+ issues.push({
24097
+ code: "voice.ops_recovery.provider_unresolved_failure",
24098
+ detail: provider.lastError ?? `${provider.provider} status is ${provider.status}.`,
24099
+ href: options.links?.providers,
24100
+ label: `Provider ${provider.provider} needs recovery`,
24101
+ severity: "fail",
24102
+ value: provider.status
24103
+ });
24104
+ }
24105
+ addDeliveryIssues(issues, {
24106
+ failedCode: "voice.ops_recovery.audit_delivery_failed",
24107
+ failedLabel: "Audit delivery failures",
24108
+ href: options.links?.auditDeliveries,
24109
+ pendingCode: "voice.ops_recovery.audit_delivery_pending",
24110
+ pendingLabel: "Audit delivery backlog",
24111
+ summary: auditDeliveries
24112
+ });
24113
+ addDeliveryIssues(issues, {
24114
+ failedCode: "voice.ops_recovery.trace_delivery_failed",
24115
+ failedLabel: "Trace delivery failures",
24116
+ href: options.links?.traceDeliveries,
24117
+ pendingCode: "voice.ops_recovery.trace_delivery_pending",
24118
+ pendingLabel: "Trace delivery backlog",
24119
+ summary: traceDeliveries
24120
+ });
24121
+ addDeliveryIssues(issues, {
24122
+ failedCode: "voice.ops_recovery.handoff_failed",
24123
+ failedLabel: "Handoff delivery failures",
24124
+ href: options.links?.handoffs,
24125
+ pendingCode: "voice.ops_recovery.handoff_pending",
24126
+ pendingLabel: "Handoff delivery backlog",
24127
+ summary: handoffDeliveries
24128
+ });
24129
+ if (latency?.failed) {
24130
+ issues.push({
24131
+ code: "voice.ops_recovery.latency_slo_failed",
24132
+ detail: `${latency.failed} latency SLO measurement(s) failed.`,
24133
+ href: options.links?.traces ? hrefForSession(options.links.traces, latency.measurements[0]?.sessionId ?? "") : undefined,
24134
+ label: "Latency SLO failures",
24135
+ severity: "fail",
24136
+ value: latency.failed
24137
+ });
24138
+ } else if (latency?.warnings) {
24139
+ issues.push({
24140
+ code: "voice.ops_recovery.latency_slo_warn",
24141
+ detail: `${latency.warnings} latency SLO measurement(s) are warning.`,
24142
+ label: "Latency SLO warnings",
24143
+ severity: "warn",
24144
+ value: latency.warnings
24145
+ });
24146
+ }
24147
+ return {
24148
+ auditDeliveries,
24149
+ checkedAt: Date.now(),
24150
+ failedSessions,
24151
+ handoffDeliveries,
24152
+ interventions,
24153
+ issues,
24154
+ latency,
24155
+ providers: {
24156
+ healthy: providers.filter((provider) => provider.status === "healthy").length,
24157
+ providers,
24158
+ recoveredFallbacks: providers.reduce((total, provider) => total + provider.fallbackCount, 0),
24159
+ unresolvedFailures: unresolvedProviders.length
24160
+ },
24161
+ status: rollupStatus3(issues),
24162
+ traceDeliveries
24163
+ };
24164
+ };
24165
+ var buildVoiceOpsRecoveryReadinessCheck = (report, options = {}) => ({
24166
+ detail: report.status === "pass" ? `${report.providers.recoveredFallbacks} recovered fallback(s), ${report.interventions.total} operator intervention(s), and no unresolved recovery issues.` : `${report.issues.length} recovery issue(s) require attention.`,
24167
+ href: options.href,
24168
+ label: options.label ?? "Ops recovery",
24169
+ status: report.status,
24170
+ value: report.issues.length
24171
+ });
24172
+ var renderVoiceOpsRecoveryMarkdown = (report, options = {}) => {
24173
+ const title = options.title ?? "Voice Ops Recovery";
24174
+ const issueRows = report.issues.map((issue) => `| ${issue.severity} | ${issue.code} | ${issue.label} | ${issue.value ?? ""} | ${issue.detail ?? ""} |`).join(`
24175
+ `);
24176
+ const providers = report.providers.providers.map((provider) => `| ${provider.provider} | ${provider.status} | ${provider.runCount} | ${provider.errorCount} | ${provider.fallbackCount} | ${provider.lastError ?? ""} |`).join(`
24177
+ `);
24178
+ const failedSessions = report.failedSessions.map((session) => `- ${session.sessionId}${session.provider ? ` via ${session.provider}` : ""}${session.error ? `: ${session.error}` : ""}`).join(`
24179
+ `);
24180
+ return `# ${title}
24181
+
24182
+ Status: ${report.status}
24183
+
24184
+ Checked at: ${new Date(report.checkedAt).toISOString()}
24185
+
24186
+ Recovered fallbacks: ${report.providers.recoveredFallbacks}
24187
+ Unresolved provider failures: ${report.providers.unresolvedFailures}
24188
+ Operator interventions: ${report.interventions.total}
24189
+
24190
+ ## Issues
24191
+
24192
+ | Severity | Code | Label | Value | Detail |
24193
+ | --- | --- | --- | ---: | --- |
24194
+ ${issueRows || "| pass | none | No recovery issues | 0 | |"}
24195
+
24196
+ ## Providers
24197
+
24198
+ | Provider | Status | Runs | Errors | Fallbacks | Last error |
24199
+ | --- | --- | ---: | ---: | ---: | --- |
24200
+ ${providers || "| none | idle | 0 | 0 | 0 | |"}
24201
+
24202
+ ## Failed Sessions
24203
+
24204
+ ${failedSessions || "None."}
24205
+
24206
+ ## Latency
24207
+
24208
+ ${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
24209
+ `;
24210
+ };
24211
+ var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml41(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml41(label)}</span><strong>not configured</strong></article>`;
24212
+ var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
24213
+ const title = options.title ?? "Voice Ops Recovery";
24214
+ const issues = report.issues.map((issue) => `<tr><td>${escapeHtml41(issue.severity)}</td><td><code>${escapeHtml41(issue.code)}</code></td><td>${escapeHtml41(issue.label)}</td><td>${escapeHtml41(String(issue.value ?? ""))}</td><td>${escapeHtml41(issue.detail ?? "")}</td></tr>`).join("");
24215
+ const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml41(provider.provider)}</td><td>${escapeHtml41(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml41(provider.lastError ?? "")}</td></tr>`).join("");
24216
+ const failedSessions = report.failedSessions.map((session) => `<li>${escapeHtml41(session.sessionId)}${session.provider ? ` via ${escapeHtml41(session.provider)}` : ""}${session.error ? `: ${escapeHtml41(session.error)}` : ""}</li>`).join("");
24217
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml41(title)}</h1><p><span class="status">${escapeHtml41(report.status)}</span> Checked ${escapeHtml41(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml41(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
24218
+ };
24219
+ var createVoiceOpsRecoveryRoutes = (options = {}) => {
24220
+ const path = options.path ?? "/api/voice/ops-recovery";
24221
+ const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
24222
+ const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
24223
+ const routes = new Elysia40({
24224
+ name: options.name ?? "absolutejs-voice-ops-recovery"
24225
+ }).get(path, async () => buildVoiceOpsRecoveryReport(options));
24226
+ if (htmlPath) {
24227
+ routes.get(htmlPath, async () => {
24228
+ const report = await buildVoiceOpsRecoveryReport(options);
24229
+ const render = options.render ?? renderVoiceOpsRecoveryHTML;
24230
+ return new Response(await render(report), {
24231
+ headers: {
24232
+ "content-type": "text/html; charset=utf-8",
24233
+ ...options.headers
24234
+ }
24235
+ });
24236
+ });
24237
+ }
24238
+ if (markdownPath) {
24239
+ routes.get(markdownPath, async () => {
24240
+ const report = await buildVoiceOpsRecoveryReport(options);
24241
+ return new Response(renderVoiceOpsRecoveryMarkdown(report, { title: options.title }), {
24242
+ headers: {
24243
+ "content-type": "text/markdown; charset=utf-8",
24244
+ ...options.headers
24245
+ }
24246
+ });
24247
+ });
24248
+ }
24249
+ return routes;
24250
+ };
24251
+ // src/incidentBundle.ts
24252
+ import { Elysia as Elysia41 } from "elysia";
24013
24253
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
24014
24254
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
24015
24255
  return false;
@@ -24208,7 +24448,7 @@ var buildVoiceIncidentBundle = async (options) => {
24208
24448
  var createVoiceIncidentBundleRoutes = (options) => {
24209
24449
  const path = options.path ?? "/api/voice-incidents/:sessionId";
24210
24450
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
24211
- const routes = new Elysia40({
24451
+ const routes = new Elysia41({
24212
24452
  name: options.name ?? "absolutejs-voice-incident-bundle"
24213
24453
  });
24214
24454
  const getSessionId = (params) => params.sessionId ?? "";
@@ -24409,19 +24649,19 @@ var summarizeVoiceOpsStatus = async (options) => {
24409
24649
  };
24410
24650
  };
24411
24651
  // src/opsStatusRoutes.ts
24412
- import { Elysia as Elysia41 } from "elysia";
24413
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24652
+ import { Elysia as Elysia42 } from "elysia";
24653
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24414
24654
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
24415
24655
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
24416
24656
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
24417
24657
  const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("auditTotal" in surface) ? `${surface.auditTotal + surface.traceTotal} deliveries` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
24418
- return `<article class="surface ${escapeHtml41(surface.status)}"><span>${escapeHtml41(surface.status.toUpperCase())}</span><h2>${escapeHtml41(key)}</h2><strong>${escapeHtml41(value)}</strong></article>`;
24658
+ return `<article class="surface ${escapeHtml42(surface.status)}"><span>${escapeHtml42(surface.status.toUpperCase())}</span><h2>${escapeHtml42(key)}</h2><strong>${escapeHtml42(value)}</strong></article>`;
24419
24659
  }).join("");
24420
- 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:#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>${escapeHtml41(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml41(report.status)}">Overall: ${escapeHtml41(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
24660
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#0d141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.surfaces{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.surface{background:#151d26;border:1px solid #283544;border-radius:20px;padding:18px}.surface span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.surface strong{font-size:1.5rem}.pass{border-color:rgba(34,197,94,.55)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Ops status</p><h1>${escapeHtml42(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
24421
24661
  };
24422
24662
  var createVoiceOpsStatusRoutes = (options) => {
24423
24663
  const path = options.path ?? "/api/voice/ops-status";
24424
- const routes = new Elysia41({
24664
+ const routes = new Elysia42({
24425
24665
  name: options.name ?? "absolutejs-voice-ops-status"
24426
24666
  });
24427
24667
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -24854,9 +25094,9 @@ var createVoiceTTSProviderRouter = (options) => {
24854
25094
  };
24855
25095
  };
24856
25096
  // src/traceDeliveryRoutes.ts
24857
- import { Elysia as Elysia42 } from "elysia";
24858
- var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
24859
- var getString16 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
25097
+ import { Elysia as Elysia43 } from "elysia";
25098
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
25099
+ var getString17 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
24860
25100
  var getNumber11 = (value) => {
24861
25101
  if (typeof value === "number" && Number.isFinite(value)) {
24862
25102
  return value;
@@ -24868,13 +25108,13 @@ var getNumber11 = (value) => {
24868
25108
  return;
24869
25109
  };
24870
25110
  var parseStatus2 = (value) => {
24871
- const text = getString16(value);
25111
+ const text = getString17(value);
24872
25112
  return text === "pending" || text === "delivered" || text === "failed" || text === "skipped" || text === "all" ? text : undefined;
24873
25113
  };
24874
25114
  var resolveVoiceTraceDeliveryFilter = (query = {}, base = {}) => ({
24875
25115
  ...base,
24876
25116
  limit: getNumber11(query.limit) ?? base.limit,
24877
- q: getString16(query.q) ?? base.q,
25117
+ q: getString17(query.q) ?? base.q,
24878
25118
  status: parseStatus2(query.status) ?? base.status
24879
25119
  });
24880
25120
  var deliverySearchText2 = (delivery) => [
@@ -24936,14 +25176,14 @@ var renderSinkResults2 = (delivery) => {
24936
25176
  if (entries.length === 0) {
24937
25177
  return "<p>No sink delivery attempts recorded yet.</p>";
24938
25178
  }
24939
- return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml42(sinkId)}</strong>: ${escapeHtml42(result.status)}${result.deliveredTo ? ` to ${escapeHtml42(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml42(result.error)})` : ""}</li>`).join("")}</ul>`;
25179
+ return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml43(sinkId)}</strong>: ${escapeHtml43(result.status)}${result.deliveredTo ? ` to ${escapeHtml43(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml43(result.error)})` : ""}</li>`).join("")}</ul>`;
24940
25180
  };
24941
- var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml42(event.type)} <small>${escapeHtml42(event.id)}</small>${event.sessionId ? ` session=${escapeHtml42(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
25181
+ var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml43(event.type)} <small>${escapeHtml43(event.id)}</small>${event.sessionId ? ` session=${escapeHtml43(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
24942
25182
  var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
24943
25183
  const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
24944
- const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml42(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
24945
- const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml42(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml42(delivery.deliveryStatus)}</span><h2>${escapeHtml42(delivery.id)}</h2><p>${escapeHtml42(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml42(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml42(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
24946
- 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:#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>${escapeHtml42(title)}</h1><p>Checked ${escapeHtml42(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid3(report)}<section class="deliveries">${rows || "<p>No trace deliveries match this filter.</p>"}</section></main></body></html>`;
25184
+ const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml43(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
25185
+ const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml43(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml43(delivery.deliveryStatus)}</span><h2>${escapeHtml43(delivery.id)}</h2><p>${escapeHtml43(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml43(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml43(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
25186
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#0f1318;color:#f4efe1;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(14,165,233,.14));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#86efac;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.grid{display:grid;gap:12px;grid-template-columns:repeat(4,1fr);margin-bottom:16px}.grid article,.delivery{background:#151b22;border:1px solid #26313d;border-radius:22px;padding:18px}.grid span,.delivery span{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.grid strong{display:block;font-size:2rem}.deliveries{display:grid;gap:14px}.delivery.failed{border-color:rgba(239,68,68,.75)}.delivery.pending{border-color:rgba(245,158,11,.7)}.delivery.delivered{border-color:rgba(34,197,94,.55)}.delivery.skipped{border-color:rgba(148,163,184,.6)}.head{align-items:start;display:flex;gap:14px;justify-content:space-between}.delivery h2{font-size:1.05rem;margin:.3rem 0;overflow-wrap:anywhere}.delivery h3{margin:1rem 0 .3rem}.delivery p,.delivery li{color:#c8d0d8}.error{color:#fecaca!important}button{background:#86efac;border:0;border-radius:999px;color:#07111f;cursor:pointer;font-weight:900;margin-top:12px;padding:10px 14px}@media(max-width:760px){main{padding:20px}.grid{grid-template-columns:1fr 1fr}.head{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Trace export health</p><h1>${escapeHtml43(title)}</h1><p>Checked ${escapeHtml43(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid3(report)}<section class="deliveries">${rows || "<p>No trace deliveries match this filter.</p>"}</section></main></body></html>`;
24947
25187
  };
24948
25188
  var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
24949
25189
  var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
@@ -24963,7 +25203,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
24963
25203
  const path = options.path ?? "/api/voice-trace-deliveries";
24964
25204
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
24965
25205
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
24966
- const routes = new Elysia42({
25206
+ const routes = new Elysia43({
24967
25207
  name: options.name ?? "absolutejs-voice-trace-deliveries"
24968
25208
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
24969
25209
  if (htmlPath !== false) {
@@ -25587,7 +25827,7 @@ var createVoiceMemoryStore = () => {
25587
25827
  return { get, getOrCreate, list, remove, set };
25588
25828
  };
25589
25829
  // src/opsWebhook.ts
25590
- import { Elysia as Elysia43 } from "elysia";
25830
+ import { Elysia as Elysia44 } from "elysia";
25591
25831
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
25592
25832
  var signVoiceOpsWebhookBody = async (input) => {
25593
25833
  const encoder = new TextEncoder;
@@ -25717,7 +25957,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
25717
25957
  };
25718
25958
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
25719
25959
  const path = options.path ?? "/api/voice-ops/webhook";
25720
- return new Elysia43().post(path, async ({ body, request, set }) => {
25960
+ return new Elysia44().post(path, async ({ body, request, set }) => {
25721
25961
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
25722
25962
  if (options.signingSecret) {
25723
25963
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -26660,6 +26900,8 @@ export {
26660
26900
  renderVoicePhoneAgentProductionSmokeHTML,
26661
26901
  renderVoiceOutcomeContractHTML,
26662
26902
  renderVoiceOpsStatusHTML,
26903
+ renderVoiceOpsRecoveryMarkdown,
26904
+ renderVoiceOpsRecoveryHTML,
26663
26905
  renderVoiceOpsConsoleHTML,
26664
26906
  renderVoiceOpsActionHistoryHTML,
26665
26907
  renderVoiceOperationsRecordHTML,
@@ -26856,6 +27098,7 @@ export {
26856
27098
  createVoiceOpsTaskProcessorWorker,
26857
27099
  createVoiceOpsStatusRoutes,
26858
27100
  createVoiceOpsRuntime,
27101
+ createVoiceOpsRecoveryRoutes,
26859
27102
  createVoiceOpsConsoleRoutes,
26860
27103
  createVoiceOpsActionAuditRoutes,
26861
27104
  createVoiceOperationsRecordRoutes,
@@ -26989,6 +27232,8 @@ export {
26989
27232
  buildVoiceProductionReadinessGate,
26990
27233
  buildVoiceOpsTaskFromSLABreach,
26991
27234
  buildVoiceOpsTaskFromReview,
27235
+ buildVoiceOpsRecoveryReport,
27236
+ buildVoiceOpsRecoveryReadinessCheck,
26992
27237
  buildVoiceOpsConsoleReport,
26993
27238
  buildVoiceOpsActionHistoryReport,
26994
27239
  buildVoiceOperationsRecord,
@@ -0,0 +1,136 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type VoiceAuditSinkDeliveryQueueSummary, type VoiceAuditSinkDeliveryStore } from './auditSinks';
3
+ import { type VoiceLatencySLOGateOptions, type VoiceLatencySLOGateReport } from './latencySlo';
4
+ import { type VoiceHandoffDeliveryQueueSummary, type VoiceTraceSinkDeliveryQueueSummary } from './queue';
5
+ import { type VoiceProviderHealthSummary } from './providerHealth';
6
+ import type { VoiceProductionReadinessCheck } from './productionReadiness';
7
+ import type { VoiceHandoffDeliveryStore } from './types';
8
+ import type { StoredVoiceTraceEvent, VoiceTraceEventStore, VoiceTraceSinkDeliveryStore } from './trace';
9
+ export type VoiceOpsRecoveryStatus = 'fail' | 'pass' | 'warn';
10
+ export type VoiceOpsRecoveryIssueCode = 'voice.ops_recovery.audit_delivery_failed' | 'voice.ops_recovery.audit_delivery_pending' | 'voice.ops_recovery.handoff_failed' | 'voice.ops_recovery.handoff_pending' | 'voice.ops_recovery.latency_slo_failed' | 'voice.ops_recovery.latency_slo_warn' | 'voice.ops_recovery.provider_unresolved_failure' | 'voice.ops_recovery.trace_delivery_failed' | 'voice.ops_recovery.trace_delivery_pending';
11
+ export type VoiceOpsRecoveryIssue = {
12
+ code: VoiceOpsRecoveryIssueCode;
13
+ detail?: string;
14
+ href?: string;
15
+ label: string;
16
+ severity: Exclude<VoiceOpsRecoveryStatus, 'pass'>;
17
+ value?: number | string;
18
+ };
19
+ export type VoiceOpsRecoveryProviderSummary<TProvider extends string = string> = {
20
+ healthy: number;
21
+ providers: VoiceProviderHealthSummary<TProvider>[];
22
+ recoveredFallbacks: number;
23
+ unresolvedFailures: number;
24
+ };
25
+ export type VoiceOpsRecoveryInterventionSummary = {
26
+ events: Array<{
27
+ action?: string;
28
+ at: number;
29
+ operatorId?: string;
30
+ sessionId: string;
31
+ traceId?: string;
32
+ }>;
33
+ total: number;
34
+ };
35
+ export type VoiceOpsRecoveryFailedSession = {
36
+ at: number;
37
+ error?: string;
38
+ provider?: string;
39
+ sessionId: string;
40
+ traceId?: string;
41
+ };
42
+ export type VoiceOpsRecoveryReport<TProvider extends string = string> = {
43
+ auditDeliveries?: VoiceAuditSinkDeliveryQueueSummary;
44
+ checkedAt: number;
45
+ failedSessions: VoiceOpsRecoveryFailedSession[];
46
+ handoffDeliveries?: VoiceHandoffDeliveryQueueSummary;
47
+ interventions: VoiceOpsRecoveryInterventionSummary;
48
+ issues: VoiceOpsRecoveryIssue[];
49
+ latency?: VoiceLatencySLOGateReport;
50
+ providers: VoiceOpsRecoveryProviderSummary<TProvider>;
51
+ status: VoiceOpsRecoveryStatus;
52
+ traceDeliveries?: VoiceTraceSinkDeliveryQueueSummary;
53
+ };
54
+ export type VoiceOpsRecoveryLinks = {
55
+ auditDeliveries?: string;
56
+ handoffs?: string;
57
+ operationsRecords?: string | ((sessionId: string) => string);
58
+ providers?: string;
59
+ sessions?: string | ((sessionId: string) => string);
60
+ traceDeliveries?: string;
61
+ traces?: string | ((sessionId: string) => string);
62
+ };
63
+ export type VoiceOpsRecoveryReportOptions<TProvider extends string = string> = {
64
+ auditDeliveryDeadLetters?: VoiceAuditSinkDeliveryStore;
65
+ auditDeliveries?: VoiceAuditSinkDeliveryStore;
66
+ events?: StoredVoiceTraceEvent[];
67
+ handoffDeliveryDeadLetters?: VoiceHandoffDeliveryStore;
68
+ handoffDeliveries?: VoiceHandoffDeliveryStore;
69
+ latency?: VoiceLatencySLOGateOptions | false;
70
+ limit?: number;
71
+ links?: VoiceOpsRecoveryLinks;
72
+ providers?: readonly TProvider[];
73
+ traceDeliveryDeadLetters?: VoiceTraceSinkDeliveryStore;
74
+ traceDeliveries?: VoiceTraceSinkDeliveryStore;
75
+ traces?: VoiceTraceEventStore;
76
+ };
77
+ export type VoiceOpsRecoveryRoutesOptions<TProvider extends string = string> = VoiceOpsRecoveryReportOptions<TProvider> & {
78
+ headers?: HeadersInit;
79
+ htmlPath?: false | string;
80
+ markdownPath?: false | string;
81
+ name?: string;
82
+ path?: string;
83
+ render?: (report: VoiceOpsRecoveryReport<TProvider>) => string | Promise<string>;
84
+ title?: string;
85
+ };
86
+ export declare const buildVoiceOpsRecoveryReport: <TProvider extends string = string>(options?: VoiceOpsRecoveryReportOptions<TProvider>) => Promise<VoiceOpsRecoveryReport<TProvider>>;
87
+ export declare const buildVoiceOpsRecoveryReadinessCheck: (report: VoiceOpsRecoveryReport, options?: {
88
+ href?: string;
89
+ label?: string;
90
+ }) => VoiceProductionReadinessCheck;
91
+ export declare const renderVoiceOpsRecoveryMarkdown: (report: VoiceOpsRecoveryReport, options?: {
92
+ title?: string;
93
+ }) => string;
94
+ export declare const renderVoiceOpsRecoveryHTML: (report: VoiceOpsRecoveryReport, options?: {
95
+ title?: string;
96
+ }) => string;
97
+ export declare const createVoiceOpsRecoveryRoutes: <TProvider extends string = string>(options?: VoiceOpsRecoveryRoutesOptions<TProvider>) => Elysia<"", {
98
+ decorator: {};
99
+ store: {};
100
+ derive: {};
101
+ resolve: {};
102
+ }, {
103
+ typebox: {};
104
+ error: {};
105
+ }, {
106
+ schema: {};
107
+ standaloneSchema: {};
108
+ macro: {};
109
+ macroFn: {};
110
+ parser: {};
111
+ response: {};
112
+ }, {
113
+ [x: string]: {
114
+ get: {
115
+ body: unknown;
116
+ params: {};
117
+ query: unknown;
118
+ headers: unknown;
119
+ response: {
120
+ 200: VoiceOpsRecoveryReport<TProvider>;
121
+ };
122
+ };
123
+ };
124
+ }, {
125
+ derive: {};
126
+ resolve: {};
127
+ schema: {};
128
+ standaloneSchema: {};
129
+ response: {};
130
+ }, {
131
+ derive: {};
132
+ resolve: {};
133
+ schema: {};
134
+ standaloneSchema: {};
135
+ response: {};
136
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.195",
3
+ "version": "0.0.22-beta.196",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",