@absolutejs/voice 0.0.22-beta.217 → 0.0.22-beta.219

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/README.md CHANGED
@@ -2741,6 +2741,51 @@ app.use(
2741
2741
 
2742
2742
  Readiness emits the stable `voice.readiness.ops_recovery` gate code when unresolved recovery issues remain.
2743
2743
 
2744
+ ## Customer-Owned Observability Export
2745
+
2746
+ Use observability exports when a buyer wants the hosted-dashboard evidence graph, but inside their own storage, warehouse, SIEM, incident flow, or release notes. The export manifest links traces, audits, operations records, delivery queues, provider SLOs, readiness reports, screenshots, and proof-pack artifacts without making AbsoluteJS Voice the dashboard.
2747
+
2748
+ ```ts
2749
+ import {
2750
+ buildVoiceObservabilityExport,
2751
+ createVoiceObservabilityExportRoutes
2752
+ } from '@absolutejs/voice';
2753
+
2754
+ app.use(
2755
+ createVoiceObservabilityExportRoutes({
2756
+ artifacts: [
2757
+ {
2758
+ id: 'latest-proof-pack',
2759
+ kind: 'proof-pack',
2760
+ label: 'Latest proof pack',
2761
+ path: '.voice-runtime/proof-pack/latest.md'
2762
+ }
2763
+ ],
2764
+ audit: runtimeStorage.audit,
2765
+ auditDeliveries: runtimeStorage.auditDeliveries,
2766
+ links: {
2767
+ operationsRecord: (sessionId) => `/voice-operations/${sessionId}`
2768
+ },
2769
+ redact: true,
2770
+ store: runtimeStorage.traces,
2771
+ traceDeliveries: runtimeStorage.traceDeliveries
2772
+ })
2773
+ );
2774
+
2775
+ const exportReport = await buildVoiceObservabilityExport({
2776
+ audit: runtimeStorage.audit,
2777
+ auditDeliveries: runtimeStorage.auditDeliveries,
2778
+ links: {
2779
+ operationsRecord: (sessionId) => `/voice-operations/${sessionId}`
2780
+ },
2781
+ redact: true,
2782
+ store: runtimeStorage.traces,
2783
+ traceDeliveries: runtimeStorage.traceDeliveries
2784
+ });
2785
+ ```
2786
+
2787
+ The route helper exposes JSON at `/api/voice/observability-export`, Markdown at `/voice/observability-export.md`, and HTML at `/voice/observability-export`. Failed trace/audit deliveries fail the export report, pending deliveries warn, and every trace/audit envelope includes the linked operations-record URL when one is configured. This is the primitive to use when customers ask how voice evidence leaves the app without going through a hosted vendor dashboard.
2788
+
2744
2789
  ## Production Voice Ops
2745
2790
 
2746
2791
  The recommended production pattern is:
package/dist/index.d.ts CHANGED
@@ -53,6 +53,7 @@ export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './r
53
53
  export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
54
54
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
55
55
  export { buildVoiceOperationsRecord, createVoiceOperationsRecordRoutes, renderVoiceOperationsRecordHTML, renderVoiceOperationsRecordIncidentMarkdown } from './operationsRecord';
56
+ export { buildVoiceObservabilityExport, createVoiceObservabilityExportRoutes, renderVoiceObservabilityExportMarkdown } from './observabilityExport';
56
57
  export { buildVoiceOpsRecoveryReadinessCheck, buildVoiceOpsRecoveryReport, createVoiceOpsRecoveryRoutes, renderVoiceOpsRecoveryHTML, renderVoiceOpsRecoveryMarkdown } from './opsRecovery';
57
58
  export { buildVoiceIncidentBundle, createStoredVoiceIncidentBundleArtifact, createVoiceIncidentBundleRoutes, createVoiceMemoryIncidentBundleStore, pruneVoiceIncidentBundleArtifacts, saveVoiceIncidentBundleArtifact } from './incidentBundle';
58
59
  export { summarizeVoiceOpsStatus } from './opsStatus';
@@ -117,6 +118,7 @@ export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptio
117
118
  export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
118
119
  export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
119
120
  export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordIntegrationEventSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordProviderDecision, VoiceOperationsRecordReviewSummary, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTaskSummary, VoiceOperationsRecordTranscriptTurn, VoiceOperationsRecordTool } from './operationsRecord';
121
+ export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportStatus } from './observabilityExport';
120
122
  export type { VoiceOpsRecoveryFailedSession, VoiceOpsRecoveryInterventionSummary, VoiceOpsRecoveryIssue, VoiceOpsRecoveryIssueCode, VoiceOpsRecoveryLinks, VoiceOpsRecoveryProviderSummary, VoiceOpsRecoveryReport, VoiceOpsRecoveryReportOptions, VoiceOpsRecoveryRoutesOptions, VoiceOpsRecoveryStatus } from './opsRecovery';
121
123
  export type { StoredVoiceIncidentBundleArtifact, VoiceIncidentBundle, VoiceIncidentBundleArtifactOptions, VoiceIncidentBundleFormat, VoiceIncidentBundleOptions, VoiceIncidentBundleRetentionOptions, VoiceIncidentBundleRetentionReport, VoiceIncidentBundleRoutesOptions, VoiceIncidentBundleStore, VoiceIncidentBundleStoreFilter, VoiceIncidentBundleSummary } from './incidentBundle';
122
124
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
package/dist/index.js CHANGED
@@ -24901,8 +24901,266 @@ var createVoiceOperationsRecordRoutes = (options) => {
24901
24901
  }
24902
24902
  return routes;
24903
24903
  };
24904
- // src/incidentBundle.ts
24904
+ // src/observabilityExport.ts
24905
24905
  import { Elysia as Elysia42 } from "elysia";
24906
+ var isDeliveryStore = (value) => !Array.isArray(value) && typeof value.list === "function";
24907
+ var getString18 = (value) => typeof value === "string" ? value : undefined;
24908
+ var getProviderKind = (payload) => getString18(payload.kind) ?? getString18(payload.providerKind);
24909
+ var toSeverityFromTrace = (event) => {
24910
+ if (event.type === "session.error" || event.payload.status === "error" || event.payload.providerStatus === "error") {
24911
+ return "fail";
24912
+ }
24913
+ if (event.payload.status === "fallback" || event.payload.providerStatus === "fallback") {
24914
+ return "warn";
24915
+ }
24916
+ return "pass";
24917
+ };
24918
+ var toSeverityFromAudit = (event) => event.outcome === "error" ? "fail" : event.outcome === "skipped" ? "warn" : "pass";
24919
+ var createOperationArtifact = (record, href) => ({
24920
+ generatedAt: record.checkedAt,
24921
+ href,
24922
+ id: `operations-record:${record.sessionId}`,
24923
+ kind: "operations-record",
24924
+ label: `Operations record ${record.sessionId}`,
24925
+ sessionId: record.sessionId,
24926
+ status: record.status === "failed" ? "fail" : record.status === "warning" ? "warn" : "pass"
24927
+ });
24928
+ var unique2 = (values) => [...new Set(values)].sort();
24929
+ var collectSessionIds = (input) => unique2([
24930
+ ...input.sessionIds ?? [],
24931
+ ...input.events.map((event) => event.sessionId),
24932
+ ...input.auditEvents.map((event) => event.sessionId).filter((sessionId) => Boolean(sessionId)),
24933
+ ...input.operationsRecords.map((record) => record.sessionId)
24934
+ ]);
24935
+ var collectIssues = (input) => {
24936
+ const issues = [];
24937
+ const failedOperationsRecords = input.operationsRecords.filter((record) => record.status === "failed").length;
24938
+ if (input.totalEvidence === 0) {
24939
+ issues.push({
24940
+ code: "voice.observability.no_evidence",
24941
+ detail: "No traces, audits, operations records, or artifacts were included in the export manifest.",
24942
+ label: "Observability evidence",
24943
+ severity: "warn",
24944
+ value: 0
24945
+ });
24946
+ }
24947
+ if (failedOperationsRecords > 0) {
24948
+ issues.push({
24949
+ code: "voice.observability.operation_failed",
24950
+ label: "Failed operations records",
24951
+ severity: "fail",
24952
+ value: failedOperationsRecords
24953
+ });
24954
+ }
24955
+ if ((input.auditDeliveries?.failed ?? 0) > 0) {
24956
+ issues.push({
24957
+ code: "voice.observability.audit_delivery_failed",
24958
+ label: "Failed audit exports",
24959
+ severity: "fail",
24960
+ value: input.auditDeliveries?.failed
24961
+ });
24962
+ }
24963
+ if ((input.auditDeliveries?.pending ?? 0) > 0) {
24964
+ issues.push({
24965
+ code: "voice.observability.audit_delivery_pending",
24966
+ label: "Pending audit exports",
24967
+ severity: "warn",
24968
+ value: input.auditDeliveries?.pending
24969
+ });
24970
+ }
24971
+ if ((input.traceDeliveries?.failed ?? 0) > 0) {
24972
+ issues.push({
24973
+ code: "voice.observability.trace_delivery_failed",
24974
+ label: "Failed trace exports",
24975
+ severity: "fail",
24976
+ value: input.traceDeliveries?.failed
24977
+ });
24978
+ }
24979
+ if ((input.traceDeliveries?.pending ?? 0) > 0) {
24980
+ issues.push({
24981
+ code: "voice.observability.trace_delivery_pending",
24982
+ label: "Pending trace exports",
24983
+ severity: "warn",
24984
+ value: input.traceDeliveries?.pending
24985
+ });
24986
+ }
24987
+ return issues;
24988
+ };
24989
+ var buildTraceEnvelope = (event, operationsRecordHref) => ({
24990
+ at: event.at,
24991
+ eventId: event.id,
24992
+ eventType: event.type,
24993
+ kind: "trace",
24994
+ operationsRecordHref,
24995
+ provider: getString18(event.payload.provider),
24996
+ providerKind: getProviderKind(event.payload),
24997
+ scenarioId: event.scenarioId,
24998
+ sessionId: event.sessionId,
24999
+ severity: toSeverityFromTrace(event),
25000
+ traceId: event.traceId
25001
+ });
25002
+ var buildAuditEnvelope = (event, operationsRecordHref) => ({
25003
+ at: event.at,
25004
+ eventId: event.id,
25005
+ eventType: event.type,
25006
+ kind: "audit",
25007
+ operationsRecordHref,
25008
+ provider: getString18(event.payload?.provider),
25009
+ providerKind: getProviderKind(event.payload ?? {}),
25010
+ sessionId: event.sessionId,
25011
+ severity: toSeverityFromAudit(event),
25012
+ traceId: event.traceId
25013
+ });
25014
+ var buildVoiceObservabilityExport = async (options = {}) => {
25015
+ const events = options.events ?? await options.store?.list() ?? [];
25016
+ const auditEvents = options.audit ? await options.audit.list() : [];
25017
+ const baseOperationsRecords = options.operationsRecords ?? [];
25018
+ const sessionIds = collectSessionIds({
25019
+ auditEvents,
25020
+ events,
25021
+ operationsRecords: baseOperationsRecords,
25022
+ sessionIds: options.sessionIds
25023
+ });
25024
+ const shouldBuildOperationsRecords = options.includeOperationsRecords === true && options.store;
25025
+ const builtOperationsRecords = shouldBuildOperationsRecords ? await Promise.all(sessionIds.map((sessionId) => buildVoiceOperationsRecord({
25026
+ audit: options.audit,
25027
+ redact: options.redact,
25028
+ sessionId,
25029
+ store: options.store
25030
+ }))) : [];
25031
+ const operationsRecords = [
25032
+ ...baseOperationsRecords,
25033
+ ...builtOperationsRecords.filter((record) => !baseOperationsRecords.some((existing) => existing.sessionId === record.sessionId))
25034
+ ];
25035
+ const traceDeliveries = options.traceDeliveries ? isDeliveryStore(options.traceDeliveries) ? await options.traceDeliveries.list() : options.traceDeliveries : undefined;
25036
+ const auditDeliveries = options.auditDeliveries ? isDeliveryStore(options.auditDeliveries) ? await options.auditDeliveries.list() : options.auditDeliveries : undefined;
25037
+ const traceDeliverySummary = traceDeliveries ? await summarizeVoiceTraceSinkDeliveries(traceDeliveries) : undefined;
25038
+ const auditDeliverySummary = auditDeliveries ? await summarizeVoiceAuditSinkDeliveries(auditDeliveries) : undefined;
25039
+ const operationArtifacts = operationsRecords.map((record) => createOperationArtifact(record, options.links?.operationsRecord?.(record.sessionId)));
25040
+ const artifacts = [...operationArtifacts, ...options.artifacts ?? []];
25041
+ const operationHrefBySessionId = new Map(sessionIds.map((sessionId) => [
25042
+ sessionId,
25043
+ options.links?.operationsRecord?.(sessionId)
25044
+ ]));
25045
+ const envelopes = [
25046
+ ...events.map((event) => buildTraceEnvelope(event, operationHrefBySessionId.get(event.sessionId))),
25047
+ ...auditEvents.map((event) => buildAuditEnvelope(event, event.sessionId ? operationHrefBySessionId.get(event.sessionId) : undefined))
25048
+ ].sort((left, right) => left.at - right.at);
25049
+ const issues = collectIssues({
25050
+ auditDeliveries: auditDeliverySummary,
25051
+ operationsRecords,
25052
+ totalEvidence: events.length + auditEvents.length + operationsRecords.length + artifacts.length,
25053
+ traceDeliveries: traceDeliverySummary
25054
+ });
25055
+ const status = issues.some((issue) => issue.severity === "fail") ? "fail" : issues.some((issue) => issue.severity === "warn") ? "warn" : "pass";
25056
+ return {
25057
+ artifacts,
25058
+ checkedAt: Date.now(),
25059
+ deliveries: {
25060
+ audit: auditDeliverySummary,
25061
+ trace: traceDeliverySummary
25062
+ },
25063
+ envelopes,
25064
+ issues,
25065
+ operationsRecords,
25066
+ redaction: {
25067
+ enabled: Boolean(options.redact),
25068
+ mode: options.redact ? "redacted" : "none"
25069
+ },
25070
+ sessionIds,
25071
+ status,
25072
+ summary: {
25073
+ auditEvents: auditEvents.length,
25074
+ events: events.length + auditEvents.length,
25075
+ failedOperationsRecords: operationsRecords.filter((record) => record.status === "failed").length,
25076
+ trace: summarizeVoiceTrace(events),
25077
+ traceEvents: events.length
25078
+ }
25079
+ };
25080
+ };
25081
+ var renderVoiceObservabilityExportMarkdown = (report, options = {}) => {
25082
+ const title = options.title ?? "Voice Observability Export";
25083
+ const issues = report.issues.map((issue) => `- ${issue.severity}: ${issue.label}${issue.value !== undefined ? ` (${issue.value})` : ""}${issue.detail ? ` - ${issue.detail}` : ""}`).join(`
25084
+ `) || "No observability export issues.";
25085
+ const artifacts = report.artifacts.map((artifact) => `- ${artifact.label}: ${artifact.kind}${artifact.href ? ` (${artifact.href})` : ""}${artifact.status ? ` - ${artifact.status}` : ""}`).join(`
25086
+ `) || "No artifacts attached.";
25087
+ return `# ${title}
25088
+
25089
+ Generated: ${new Date(report.checkedAt).toISOString()}
25090
+
25091
+ Overall: **${report.status}**
25092
+
25093
+ Redaction: **${report.redaction.mode}**
25094
+
25095
+ Sessions: ${report.sessionIds.length}
25096
+
25097
+ Trace events: ${report.summary.traceEvents}
25098
+
25099
+ Audit events: ${report.summary.auditEvents}
25100
+
25101
+ Operations records: ${report.operationsRecords.length}
25102
+
25103
+ Artifacts: ${report.artifacts.length}
25104
+
25105
+ ## Delivery Summary
25106
+
25107
+ Trace deliveries: ${report.deliveries.trace ? `${report.deliveries.trace.delivered} delivered, ${report.deliveries.trace.pending} pending, ${report.deliveries.trace.failed} failed` : "not configured"}
25108
+
25109
+ Audit deliveries: ${report.deliveries.audit ? `${report.deliveries.audit.delivered} delivered, ${report.deliveries.audit.pending} pending, ${report.deliveries.audit.failed} failed` : "not configured"}
25110
+
25111
+ ## Artifacts
25112
+
25113
+ ${artifacts}
25114
+
25115
+ ## Issues
25116
+
25117
+ ${issues}
25118
+ `;
25119
+ };
25120
+ var createVoiceObservabilityExportRoutes = (options = {}) => {
25121
+ const path = options.path ?? "/api/voice/observability-export";
25122
+ const markdownPath = options.markdownPath ?? "/voice/observability-export.md";
25123
+ const htmlPath = options.htmlPath ?? "/voice/observability-export";
25124
+ const headers = {
25125
+ "cache-control": "no-store",
25126
+ ...options.headers ?? {}
25127
+ };
25128
+ const buildReport = () => buildVoiceObservabilityExport(options);
25129
+ const app = new Elysia42({
25130
+ name: options.name ?? "absolute-voice-observability-export"
25131
+ });
25132
+ app.get(path, async () => Response.json(await buildReport(), { headers }));
25133
+ if (markdownPath !== false) {
25134
+ app.get(markdownPath, async () => {
25135
+ const report = await buildReport();
25136
+ return new Response(renderVoiceObservabilityExportMarkdown(report, {
25137
+ title: options.title
25138
+ }), {
25139
+ headers: {
25140
+ ...headers,
25141
+ "content-type": "text/markdown; charset=utf-8"
25142
+ }
25143
+ });
25144
+ });
25145
+ }
25146
+ if (htmlPath !== false) {
25147
+ app.get(htmlPath, async () => {
25148
+ const report = await buildReport();
25149
+ const markdown = options.render ? await options.render(report) : renderVoiceObservabilityExportMarkdown(report, {
25150
+ title: options.title
25151
+ });
25152
+ return new Response(`<!doctype html><html><head><meta charset="utf-8" /><title>${options.title ?? "Voice Observability Export"}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:auto;max-width:920px;padding:32px;white-space:pre-wrap}</style></head><body>${markdown}</body></html>`, {
25153
+ headers: {
25154
+ ...headers,
25155
+ "content-type": "text/html; charset=utf-8"
25156
+ }
25157
+ });
25158
+ });
25159
+ }
25160
+ return app;
25161
+ };
25162
+ // src/incidentBundle.ts
25163
+ import { Elysia as Elysia43 } from "elysia";
24906
25164
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
24907
25165
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
24908
25166
  return false;
@@ -25101,7 +25359,7 @@ var buildVoiceIncidentBundle = async (options) => {
25101
25359
  var createVoiceIncidentBundleRoutes = (options) => {
25102
25360
  const path = options.path ?? "/api/voice-incidents/:sessionId";
25103
25361
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
25104
- const routes = new Elysia42({
25362
+ const routes = new Elysia43({
25105
25363
  name: options.name ?? "absolutejs-voice-incident-bundle"
25106
25364
  });
25107
25365
  const getSessionId = (params) => params.sessionId ?? "";
@@ -25302,7 +25560,7 @@ var summarizeVoiceOpsStatus = async (options) => {
25302
25560
  };
25303
25561
  };
25304
25562
  // src/opsStatusRoutes.ts
25305
- import { Elysia as Elysia43 } from "elysia";
25563
+ import { Elysia as Elysia44 } from "elysia";
25306
25564
  var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
25307
25565
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
25308
25566
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
@@ -25314,7 +25572,7 @@ var renderVoiceOpsStatusHTML = (report, options = {}) => {
25314
25572
  };
25315
25573
  var createVoiceOpsStatusRoutes = (options) => {
25316
25574
  const path = options.path ?? "/api/voice/ops-status";
25317
- const routes = new Elysia43({
25575
+ const routes = new Elysia44({
25318
25576
  name: options.name ?? "absolutejs-voice-ops-status"
25319
25577
  });
25320
25578
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -25747,9 +26005,9 @@ var createVoiceTTSProviderRouter = (options) => {
25747
26005
  };
25748
26006
  };
25749
26007
  // src/traceDeliveryRoutes.ts
25750
- import { Elysia as Elysia44 } from "elysia";
26008
+ import { Elysia as Elysia45 } from "elysia";
25751
26009
  var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
25752
- var getString18 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
26010
+ var getString19 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
25753
26011
  var getNumber11 = (value) => {
25754
26012
  if (typeof value === "number" && Number.isFinite(value)) {
25755
26013
  return value;
@@ -25761,13 +26019,13 @@ var getNumber11 = (value) => {
25761
26019
  return;
25762
26020
  };
25763
26021
  var parseStatus2 = (value) => {
25764
- const text = getString18(value);
26022
+ const text = getString19(value);
25765
26023
  return text === "pending" || text === "delivered" || text === "failed" || text === "skipped" || text === "all" ? text : undefined;
25766
26024
  };
25767
26025
  var resolveVoiceTraceDeliveryFilter = (query = {}, base = {}) => ({
25768
26026
  ...base,
25769
26027
  limit: getNumber11(query.limit) ?? base.limit,
25770
- q: getString18(query.q) ?? base.q,
26028
+ q: getString19(query.q) ?? base.q,
25771
26029
  status: parseStatus2(query.status) ?? base.status
25772
26030
  });
25773
26031
  var deliverySearchText2 = (delivery) => [
@@ -25856,7 +26114,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
25856
26114
  const path = options.path ?? "/api/voice-trace-deliveries";
25857
26115
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
25858
26116
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
25859
- const routes = new Elysia44({
26117
+ const routes = new Elysia45({
25860
26118
  name: options.name ?? "absolutejs-voice-trace-deliveries"
25861
26119
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
25862
26120
  if (htmlPath !== false) {
@@ -26480,7 +26738,7 @@ var createVoiceMemoryStore = () => {
26480
26738
  return { get, getOrCreate, list, remove, set };
26481
26739
  };
26482
26740
  // src/opsWebhook.ts
26483
- import { Elysia as Elysia45 } from "elysia";
26741
+ import { Elysia as Elysia46 } from "elysia";
26484
26742
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
26485
26743
  var signVoiceOpsWebhookBody = async (input) => {
26486
26744
  const encoder = new TextEncoder;
@@ -26610,7 +26868,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
26610
26868
  };
26611
26869
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
26612
26870
  const path = options.path ?? "/api/voice-ops/webhook";
26613
- return new Elysia45().post(path, async ({ body, request, set }) => {
26871
+ return new Elysia46().post(path, async ({ body, request, set }) => {
26614
26872
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
26615
26873
  if (options.signingSecret) {
26616
26874
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -27561,6 +27819,7 @@ export {
27561
27819
  renderVoiceOpsActionHistoryHTML,
27562
27820
  renderVoiceOperationsRecordIncidentMarkdown,
27563
27821
  renderVoiceOperationsRecordHTML,
27822
+ renderVoiceObservabilityExportMarkdown,
27564
27823
  renderVoiceLiveLatencyHTML,
27565
27824
  renderVoiceLatencySLOMarkdown,
27566
27825
  renderVoiceHandoffHealthHTML,
@@ -27759,6 +28018,7 @@ export {
27759
28018
  createVoiceOpsConsoleRoutes,
27760
28019
  createVoiceOpsActionAuditRoutes,
27761
28020
  createVoiceOperationsRecordRoutes,
28021
+ createVoiceObservabilityExportRoutes,
27762
28022
  createVoiceMemoryTraceSinkDeliveryStore,
27763
28023
  createVoiceMemoryTraceEventStore,
27764
28024
  createVoiceMemoryStore,
@@ -27895,6 +28155,7 @@ export {
27895
28155
  buildVoiceOpsConsoleReport,
27896
28156
  buildVoiceOpsActionHistoryReport,
27897
28157
  buildVoiceOperationsRecord,
28158
+ buildVoiceObservabilityExport,
27898
28159
  buildVoiceLiveOpsControlState,
27899
28160
  buildVoiceLatencySLOGate,
27900
28161
  buildVoiceIncidentBundle,
@@ -0,0 +1,123 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type VoiceAuditSinkDeliveryQueueSummary, type VoiceAuditSinkDeliveryRecord, type VoiceAuditSinkDeliveryStore } from './auditSinks';
3
+ import type { VoiceAuditEventStore, VoiceAuditEventType } from './audit';
4
+ import { type VoiceOperationsRecord } from './operationsRecord';
5
+ import { type VoiceTraceSinkDeliveryQueueSummary } from './queue';
6
+ import { type StoredVoiceTraceEvent, type VoiceTraceEventStore, type VoiceTraceEventType, type VoiceTraceRedactionConfig, type VoiceTraceSinkDeliveryRecord, type VoiceTraceSinkDeliveryStore, type VoiceTraceSummary } from './trace';
7
+ export type VoiceObservabilityExportStatus = 'fail' | 'pass' | 'warn';
8
+ export type VoiceObservabilityExportArtifactKind = 'incident' | 'markdown' | 'operations-record' | 'proof-pack' | 'readiness' | 'screenshot' | 'slo' | 'trace' | 'audit' | 'custom';
9
+ export type VoiceObservabilityExportArtifact = {
10
+ bytes?: number;
11
+ contentType?: string;
12
+ generatedAt?: number | string;
13
+ href?: string;
14
+ id: string;
15
+ kind: VoiceObservabilityExportArtifactKind;
16
+ label: string;
17
+ path?: string;
18
+ sessionId?: string;
19
+ status?: VoiceObservabilityExportStatus;
20
+ };
21
+ export type VoiceObservabilityExportEnvelope = {
22
+ at: number;
23
+ eventId: string;
24
+ eventType: VoiceTraceEventType | VoiceAuditEventType;
25
+ kind: 'audit' | 'trace';
26
+ operationsRecordHref?: string;
27
+ provider?: string;
28
+ providerKind?: string;
29
+ scenarioId?: string;
30
+ sessionId?: string;
31
+ severity: VoiceObservabilityExportStatus;
32
+ traceId?: string;
33
+ };
34
+ export type VoiceObservabilityExportIssueCode = 'voice.observability.no_evidence' | 'voice.observability.operation_failed' | 'voice.observability.audit_delivery_failed' | 'voice.observability.audit_delivery_pending' | 'voice.observability.trace_delivery_failed' | 'voice.observability.trace_delivery_pending';
35
+ export type VoiceObservabilityExportIssue = {
36
+ code: VoiceObservabilityExportIssueCode;
37
+ detail?: string;
38
+ label: string;
39
+ severity: Exclude<VoiceObservabilityExportStatus, 'pass'>;
40
+ value?: number | string;
41
+ };
42
+ export type VoiceObservabilityExportDeliverySummary = {
43
+ audit?: VoiceAuditSinkDeliveryQueueSummary;
44
+ trace?: VoiceTraceSinkDeliveryQueueSummary;
45
+ };
46
+ export type VoiceObservabilityExportRedactionSummary = {
47
+ enabled: boolean;
48
+ mode: 'none' | 'redacted';
49
+ };
50
+ export type VoiceObservabilityExportReport = {
51
+ artifacts: VoiceObservabilityExportArtifact[];
52
+ checkedAt: number;
53
+ deliveries: VoiceObservabilityExportDeliverySummary;
54
+ envelopes: VoiceObservabilityExportEnvelope[];
55
+ issues: VoiceObservabilityExportIssue[];
56
+ operationsRecords: VoiceOperationsRecord[];
57
+ redaction: VoiceObservabilityExportRedactionSummary;
58
+ sessionIds: string[];
59
+ status: VoiceObservabilityExportStatus;
60
+ summary: {
61
+ auditEvents: number;
62
+ events: number;
63
+ failedOperationsRecords: number;
64
+ trace: VoiceTraceSummary;
65
+ traceEvents: number;
66
+ };
67
+ };
68
+ export type VoiceObservabilityExportOptions = {
69
+ artifacts?: VoiceObservabilityExportArtifact[];
70
+ audit?: VoiceAuditEventStore;
71
+ auditDeliveries?: VoiceAuditSinkDeliveryRecord[] | VoiceAuditSinkDeliveryStore;
72
+ events?: StoredVoiceTraceEvent[];
73
+ includeOperationsRecords?: boolean;
74
+ links?: {
75
+ operationsRecord?: (sessionId: string) => string;
76
+ };
77
+ operationsRecords?: VoiceOperationsRecord[];
78
+ redact?: VoiceTraceRedactionConfig;
79
+ sessionIds?: string[];
80
+ store?: VoiceTraceEventStore;
81
+ traceDeliveries?: VoiceTraceSinkDeliveryRecord[] | VoiceTraceSinkDeliveryStore;
82
+ };
83
+ export type VoiceObservabilityExportRoutesOptions = VoiceObservabilityExportOptions & {
84
+ headers?: HeadersInit;
85
+ htmlPath?: false | string;
86
+ markdownPath?: false | string;
87
+ name?: string;
88
+ path?: string;
89
+ render?: (report: VoiceObservabilityExportReport) => string | Promise<string>;
90
+ title?: string;
91
+ };
92
+ export declare const buildVoiceObservabilityExport: (options?: VoiceObservabilityExportOptions) => Promise<VoiceObservabilityExportReport>;
93
+ export declare const renderVoiceObservabilityExportMarkdown: (report: VoiceObservabilityExportReport, options?: {
94
+ title?: string;
95
+ }) => string;
96
+ export declare const createVoiceObservabilityExportRoutes: (options?: VoiceObservabilityExportRoutesOptions) => Elysia<"", {
97
+ decorator: {};
98
+ store: {};
99
+ derive: {};
100
+ resolve: {};
101
+ }, {
102
+ typebox: {};
103
+ error: {};
104
+ }, {
105
+ schema: {};
106
+ standaloneSchema: {};
107
+ macro: {};
108
+ macroFn: {};
109
+ parser: {};
110
+ response: {};
111
+ }, {}, {
112
+ derive: {};
113
+ resolve: {};
114
+ schema: {};
115
+ standaloneSchema: {};
116
+ response: {};
117
+ }, {
118
+ derive: {};
119
+ resolve: {};
120
+ schema: {};
121
+ standaloneSchema: {};
122
+ response: {};
123
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.217",
3
+ "version": "0.0.22-beta.219",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",