@absolutejs/voice 0.0.22-beta.145 → 0.0.22-beta.147

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.
@@ -1,3 +1,4 @@
1
+ import type { S3Client, S3Options } from 'bun';
1
2
  import type { StoredVoiceAuditEvent, VoiceAuditEventStore, VoiceAuditEventType } from './audit';
2
3
  import type { VoiceIdempotencyStore, VoiceRedisTaskLeaseCoordinator } from './queue';
3
4
  import type { VoiceTraceRedactionConfig } from './trace';
@@ -59,6 +60,22 @@ export type VoiceAuditHTTPSinkOptions<TBody extends Record<string, unknown> = Re
59
60
  timeoutMs?: number;
60
61
  url: string;
61
62
  };
63
+ export type VoiceS3AuditSinkFile = {
64
+ write: (data: string, options?: BlobPropertyBag) => Promise<number> | number;
65
+ };
66
+ export type VoiceS3AuditSinkClient = Pick<S3Client, 'file'>;
67
+ export type VoiceAuditS3SinkOptions<TBody extends Record<string, unknown> = Record<string, unknown>> = S3Options & {
68
+ body?: (input: {
69
+ events: StoredVoiceAuditEvent[];
70
+ key: string;
71
+ }) => Promise<TBody> | TBody;
72
+ client?: VoiceS3AuditSinkClient;
73
+ contentType?: string;
74
+ eventTypes?: VoiceAuditEventType[];
75
+ id: string;
76
+ keyPrefix?: string;
77
+ kind?: string;
78
+ };
62
79
  export type VoiceAuditSinkStoreOptions<TEvent extends StoredVoiceAuditEvent = StoredVoiceAuditEvent> = {
63
80
  awaitDelivery?: boolean;
64
81
  deliveryQueue?: VoiceAuditSinkDeliveryStore;
@@ -117,6 +134,7 @@ export declare const createVoiceAuditSinkDeliveryRecord: (input: {
117
134
  id?: string;
118
135
  } & Partial<Omit<VoiceAuditSinkDeliveryRecord, "createdAt" | "events" | "id">>) => VoiceAuditSinkDeliveryRecord;
119
136
  export declare const createVoiceAuditHTTPSink: <TBody extends Record<string, unknown> = Record<string, unknown>>(options: VoiceAuditHTTPSinkOptions<TBody>) => VoiceAuditSink;
137
+ export declare const createVoiceAuditS3Sink: <TBody extends Record<string, unknown> = Record<string, unknown>>(options: VoiceAuditS3SinkOptions<TBody>) => VoiceAuditSink;
120
138
  export declare const deliverVoiceAuditEventsToSinks: (input: {
121
139
  events: StoredVoiceAuditEvent[];
122
140
  redact?: VoiceTraceRedactionConfig;
@@ -0,0 +1,35 @@
1
+ import { createVoiceAuditSinkDeliveryWorker, type VoiceAuditSinkDeliveryQueueSummary, type VoiceAuditSinkDeliveryRecord, type VoiceAuditSinkDeliveryWorkerOptions, type VoiceAuditSinkDeliveryWorkerResult } from './auditSinks';
2
+ import { createVoiceTraceSinkDeliveryWorker, type VoiceTraceSinkDeliveryQueueSummary, type VoiceTraceSinkDeliveryWorkerOptions, type VoiceTraceSinkDeliveryWorkerResult } from './queue';
3
+ import type { VoiceTraceSinkDeliveryRecord } from './trace';
4
+ export type VoiceDeliveryRuntimeAuditConfig<TDelivery extends VoiceAuditSinkDeliveryRecord = VoiceAuditSinkDeliveryRecord> = VoiceAuditSinkDeliveryWorkerOptions<TDelivery> & {
5
+ autoStart?: boolean;
6
+ onError?: (error: unknown) => Promise<void> | void;
7
+ pollIntervalMs?: number;
8
+ };
9
+ export type VoiceDeliveryRuntimeTraceConfig<TDelivery extends VoiceTraceSinkDeliveryRecord = VoiceTraceSinkDeliveryRecord> = VoiceTraceSinkDeliveryWorkerOptions<TDelivery> & {
10
+ autoStart?: boolean;
11
+ onError?: (error: unknown) => Promise<void> | void;
12
+ pollIntervalMs?: number;
13
+ };
14
+ export type VoiceDeliveryRuntimeConfig<TAuditDelivery extends VoiceAuditSinkDeliveryRecord = VoiceAuditSinkDeliveryRecord, TTraceDelivery extends VoiceTraceSinkDeliveryRecord = VoiceTraceSinkDeliveryRecord> = {
15
+ audit?: VoiceDeliveryRuntimeAuditConfig<TAuditDelivery>;
16
+ trace?: VoiceDeliveryRuntimeTraceConfig<TTraceDelivery>;
17
+ };
18
+ export type VoiceDeliveryRuntimeTickResult = {
19
+ audit?: VoiceAuditSinkDeliveryWorkerResult;
20
+ trace?: VoiceTraceSinkDeliveryWorkerResult;
21
+ };
22
+ export type VoiceDeliveryRuntimeSummary = {
23
+ audit?: VoiceAuditSinkDeliveryQueueSummary;
24
+ trace?: VoiceTraceSinkDeliveryQueueSummary;
25
+ };
26
+ export type VoiceDeliveryRuntime = {
27
+ audit?: ReturnType<typeof createVoiceAuditSinkDeliveryWorker>;
28
+ isRunning: () => boolean;
29
+ start: () => void;
30
+ stop: () => void;
31
+ summarize: () => Promise<VoiceDeliveryRuntimeSummary>;
32
+ tick: () => Promise<VoiceDeliveryRuntimeTickResult>;
33
+ trace?: ReturnType<typeof createVoiceTraceSinkDeliveryWorker>;
34
+ };
35
+ export declare const createVoiceDeliveryRuntime: <TAuditDelivery extends VoiceAuditSinkDeliveryRecord = VoiceAuditSinkDeliveryRecord, TTraceDelivery extends VoiceTraceSinkDeliveryRecord = VoiceTraceSinkDeliveryRecord>(config: VoiceDeliveryRuntimeConfig<TAuditDelivery, TTraceDelivery>) => VoiceDeliveryRuntime;
package/dist/index.d.ts CHANGED
@@ -6,17 +6,19 @@ export { createVoiceAssistantHealthHTMLHandler, createVoiceAssistantHealthJSONHa
6
6
  export { createVoiceAuditEvent, createVoiceAuditLogger, createVoiceMemoryAuditEventStore, filterVoiceAuditEvents, recordVoiceAuditEvent, recordVoiceHandoffAuditEvent, recordVoiceOperatorAuditEvent, recordVoiceProviderAuditEvent, recordVoiceRetentionAuditEvent, recordVoiceToolAuditEvent } from './audit';
7
7
  export { buildVoiceAuditTrailReport, createVoiceAuditTrailRoutes, renderVoiceAuditTrailHTML, resolveVoiceAuditTrailFilter, summarizeVoiceAuditTrail } from './auditRoutes';
8
8
  export { buildVoiceAuditExport, exportVoiceAuditTrail, redactVoiceAuditEvent, redactVoiceAuditEvents, renderVoiceAuditHTML, renderVoiceAuditMarkdown } from './auditExport';
9
- export { createVoiceAuditHTTPSink, createVoiceAuditSinkDeliveryId, createVoiceAuditSinkDeliveryRecord, createVoiceAuditSinkDeliveryWorker, createVoiceAuditSinkDeliveryWorkerLoop, createVoiceAuditSinkStore, createVoiceMemoryAuditSinkDeliveryStore, deliverVoiceAuditEventsToSinks, summarizeVoiceAuditSinkDeliveries } from './auditSinks';
9
+ export { createVoiceAuditHTTPSink, createVoiceAuditS3Sink, createVoiceAuditSinkDeliveryId, createVoiceAuditSinkDeliveryRecord, createVoiceAuditSinkDeliveryWorker, createVoiceAuditSinkDeliveryWorkerLoop, createVoiceAuditSinkStore, createVoiceMemoryAuditSinkDeliveryStore, deliverVoiceAuditEventsToSinks, summarizeVoiceAuditSinkDeliveries } from './auditSinks';
10
10
  export { buildVoiceAuditDeliveryReport, createVoiceAuditDeliveryHTMLHandler, createVoiceAuditDeliveryJSONHandler, createVoiceAuditDeliveryRoutes, renderVoiceAuditDeliveryHTML, resolveVoiceAuditDeliveryFilter } from './auditDeliveryRoutes';
11
11
  export { createVoiceBargeInRoutes, renderVoiceBargeInHTML, summarizeVoiceBargeIn } from './bargeInRoutes';
12
12
  export { createVoiceReconnectContractRoutes, renderVoiceReconnectContractHTML, summarizeVoiceReconnectContractSnapshots, runVoiceReconnectContract } from './reconnectContract';
13
13
  export { buildVoiceDiagnosticsMarkdown, createVoiceDiagnosticsRoutes, resolveVoiceDiagnosticsTraceFilter } from './diagnosticsRoutes';
14
14
  export { buildVoiceDemoReadyReport, createVoiceDemoReadyRoutes, renderVoiceDemoReadyHTML } from './demoReadyRoutes';
15
15
  export { buildVoiceDeliverySinkReport, createVoiceDeliverySinkDescriptor, createVoiceDeliverySinkPair, createVoiceDeliverySinkRoutes, createVoiceFileDeliverySink, createVoicePostgresDeliverySink, createVoiceS3DeliverySink, createVoiceSQLiteDeliverySink, createVoiceWebhookDeliverySink, renderVoiceDeliverySinkHTML } from './deliverySinkRoutes';
16
+ export { createVoiceDeliveryRuntime } from './deliveryRuntime';
16
17
  export { applyVoiceDataRetentionPolicy, buildVoiceDataRetentionPlan } from './dataControl';
17
18
  export type { VoiceDataRetentionPolicy, VoiceDataRetentionReport, VoiceDataRetentionScope, VoiceDataRetentionScopeReport, VoiceDataRetentionStores } from './dataControl';
18
19
  export type { VoiceDemoReadyReport, VoiceDemoReadyRoutesOptions, VoiceDemoReadySection, VoiceDemoReadyStatus } from './demoReadyRoutes';
19
20
  export type { VoiceDeliverySinkDescriptor, VoiceDeliverySinkDescriptorInput, VoiceDeliverySinkKind, VoiceDeliverySinkPairOptions, VoiceDeliverySinkReport, VoiceDeliverySinkRoutesOptions, VoiceTraceDeliverySinkSurface } from './deliverySinkRoutes';
21
+ export type { VoiceDeliveryRuntime, VoiceDeliveryRuntimeAuditConfig, VoiceDeliveryRuntimeConfig, VoiceDeliveryRuntimeSummary, VoiceDeliveryRuntimeTickResult, VoiceDeliveryRuntimeTraceConfig } from './deliveryRuntime';
20
22
  export { compareVoiceEvalBaseline, createVoiceFileEvalBaselineStore, createVoiceFileScenarioFixtureStore, createVoiceEvalRoutes, renderVoiceEvalBaselineHTML, renderVoiceEvalHTML, renderVoiceScenarioEvalHTML, renderVoiceScenarioFixtureEvalHTML, runVoiceScenarioEvals, runVoiceScenarioFixtureEvals, runVoiceSessionEvals } from './evalRoutes';
21
23
  export { createVoiceSimulationSuiteRoutes, renderVoiceSimulationSuiteHTML, runVoiceSimulationSuite } from './simulationSuite';
22
24
  export { createVoiceWorkflowContract, createVoiceWorkflowContractHandler, createVoiceWorkflowContractPreset, createVoiceWorkflowScenario, recordVoiceWorkflowContractTrace, validateVoiceWorkflowRouteResult } from './workflowContract';
@@ -47,7 +49,7 @@ export { createVoiceOpsStatusRoutes, renderVoiceOpsStatusHTML } from './opsStatu
47
49
  export { createVoiceQualityRoutes, evaluateVoiceQuality, renderVoiceQualityHTML } from './qualityRoutes';
48
50
  export { createVoiceResilienceRoutes, createVoiceRoutingDecisionSummary, listVoiceRoutingEvents, renderVoiceResilienceHTML, summarizeVoiceRoutingDecision, summarizeVoiceRoutingSessions } from './resilienceRoutes';
49
51
  export { createVoiceSTTProviderRouter, createVoiceTTSProviderRouter } from './providerAdapters';
50
- export { buildVoiceTraceReplay, createVoiceMemoryTraceSinkDeliveryStore, createVoiceTraceHTTPSink, createVoiceMemoryTraceEventStore, createVoiceTraceSinkDeliveryId, createVoiceTraceSinkDeliveryRecord, createVoiceTraceSinkStore, createVoiceTraceEvent, createVoiceTraceEventId, deliverVoiceTraceEventsToSinks, evaluateVoiceTrace, exportVoiceTrace, filterVoiceTraceEvents, pruneVoiceTraceEvents, redactVoiceTraceEvent, redactVoiceTraceEvents, redactVoiceTraceText, renderVoiceTraceHTML, renderVoiceTraceMarkdown, resolveVoiceTraceRedactionOptions, selectVoiceTraceEventsForPrune, summarizeVoiceTrace } from './trace';
52
+ export { buildVoiceTraceReplay, createVoiceMemoryTraceSinkDeliveryStore, createVoiceTraceHTTPSink, createVoiceTraceS3Sink, createVoiceMemoryTraceEventStore, createVoiceTraceSinkDeliveryId, createVoiceTraceSinkDeliveryRecord, createVoiceTraceSinkStore, createVoiceTraceEvent, createVoiceTraceEventId, deliverVoiceTraceEventsToSinks, evaluateVoiceTrace, exportVoiceTrace, filterVoiceTraceEvents, pruneVoiceTraceEvents, redactVoiceTraceEvent, redactVoiceTraceEvents, redactVoiceTraceText, renderVoiceTraceHTML, renderVoiceTraceMarkdown, resolveVoiceTraceRedactionOptions, selectVoiceTraceEventsForPrune, summarizeVoiceTrace } from './trace';
51
53
  export { buildVoiceTraceDeliveryReport, createVoiceTraceDeliveryHTMLHandler, createVoiceTraceDeliveryJSONHandler, createVoiceTraceDeliveryRoutes, renderVoiceTraceDeliveryHTML, resolveVoiceTraceDeliveryFilter } from './traceDeliveryRoutes';
52
54
  export { createVoiceTraceTimelineRoutes, renderVoiceTraceTimelineHTML, renderVoiceTraceTimelineSessionHTML, summarizeVoiceTraceTimeline } from './traceTimeline';
53
55
  export { createVoiceSQLiteAuditEventStore, createVoiceSQLiteAuditSinkDeliveryStore, createVoiceSQLiteCampaignStore, createVoiceSQLiteExternalObjectMapStore, createVoiceSQLiteIntegrationEventStore, createVoiceSQLiteReviewStore, createVoiceSQLiteRuntimeStorage, createVoiceSQLiteSessionStore, createVoiceSQLiteTaskStore, createVoiceSQLiteTelephonyWebhookIdempotencyStore, createVoiceSQLiteTraceSinkDeliveryStore, createVoiceSQLiteTraceEventStore } from './sqliteStore';
@@ -117,10 +119,10 @@ export type { StoredVoiceCallReviewArtifact, VoiceCallReviewArtifact, VoiceCallR
117
119
  export type { StoredVoiceAuditEvent, VoiceAuditActor, VoiceAuditEvent, VoiceAuditEventFilter, VoiceAuditEventStore, VoiceAuditEventType, VoiceAuditLogger, VoiceAuditOutcome, VoiceAuditResource, VoiceHandoffAuditEventInput, VoiceOperatorAuditEventInput, VoiceProviderAuditEventInput, VoiceRetentionAuditEventInput, VoiceToolAuditEventInput } from './audit';
118
120
  export type { VoiceAuditTrailOptions, VoiceAuditTrailReport, VoiceAuditTrailRoutesOptions, VoiceAuditTrailSummary } from './auditRoutes';
119
121
  export type { VoiceAuditExport } from './auditExport';
120
- export type { VoiceAuditHTTPSinkOptions, VoiceAuditSink, VoiceAuditSinkDeliveryQueueStatus, VoiceAuditSinkDeliveryQueueSummary, VoiceAuditSinkDeliveryRecord, VoiceAuditSinkDeliveryResult, VoiceAuditSinkDeliveryStatus, VoiceAuditSinkDeliveryStore, VoiceAuditSinkDeliveryWorkerLoop, VoiceAuditSinkDeliveryWorkerLoopOptions, VoiceAuditSinkDeliveryWorkerOptions, VoiceAuditSinkDeliveryWorkerResult, VoiceAuditSinkFanoutResult, VoiceAuditSinkStoreOptions } from './auditSinks';
122
+ export type { VoiceAuditHTTPSinkOptions, VoiceAuditS3SinkOptions, VoiceS3AuditSinkClient, VoiceS3AuditSinkFile, VoiceAuditSink, VoiceAuditSinkDeliveryQueueStatus, VoiceAuditSinkDeliveryQueueSummary, VoiceAuditSinkDeliveryRecord, VoiceAuditSinkDeliveryResult, VoiceAuditSinkDeliveryStatus, VoiceAuditSinkDeliveryStore, VoiceAuditSinkDeliveryWorkerLoop, VoiceAuditSinkDeliveryWorkerLoopOptions, VoiceAuditSinkDeliveryWorkerOptions, VoiceAuditSinkDeliveryWorkerResult, VoiceAuditSinkFanoutResult, VoiceAuditSinkStoreOptions } from './auditSinks';
121
123
  export type { VoiceAuditDeliveryDrainReport, VoiceAuditDeliveryDrainWorker, VoiceAuditDeliveryFilter, VoiceAuditDeliveryReport, VoiceAuditDeliveryRoutesOptions } from './auditDeliveryRoutes';
122
124
  export type { VoiceFileRuntimeStorage, VoiceFileStoreOptions } from './fileStore';
123
- export type { StoredVoiceTraceEvent, VoiceTraceEvaluation, VoiceTraceEvaluationOptions, VoiceTraceEvent, VoiceTraceEventFilter, VoiceTraceEventStore, VoiceTraceEventType, VoiceTraceIssue, VoiceTraceIssueSeverity, VoiceTraceHTTPSinkOptions, VoiceTracePruneFilter, VoiceTracePruneOptions, VoiceTracePruneResult, VoiceTraceRedactionConfig, VoiceTraceRedactionOptions, VoiceTraceRedactionReplacement, VoiceResolvedTraceRedactionOptions, VoiceTraceSink, VoiceTraceSinkDeliveryQueueStatus, VoiceTraceSinkDeliveryRecord, VoiceTraceSinkDeliveryResult, VoiceTraceSinkDeliveryStatus, VoiceTraceSinkDeliveryStore, VoiceTraceSinkFanoutResult, VoiceTraceSinkStoreOptions, VoiceTraceSummary } from './trace';
125
+ export type { StoredVoiceTraceEvent, VoiceTraceEvaluation, VoiceTraceEvaluationOptions, VoiceTraceEvent, VoiceTraceEventFilter, VoiceTraceEventStore, VoiceTraceEventType, VoiceTraceIssue, VoiceTraceIssueSeverity, VoiceTraceHTTPSinkOptions, VoiceTraceS3SinkOptions, VoiceTracePruneFilter, VoiceTracePruneOptions, VoiceTracePruneResult, VoiceTraceRedactionConfig, VoiceTraceRedactionOptions, VoiceTraceRedactionReplacement, VoiceResolvedTraceRedactionOptions, VoiceTraceSink, VoiceTraceSinkDeliveryQueueStatus, VoiceTraceSinkDeliveryRecord, VoiceTraceSinkDeliveryResult, VoiceTraceSinkDeliveryStatus, VoiceTraceSinkDeliveryStore, VoiceTraceSinkFanoutResult, VoiceTraceSinkStoreOptions, VoiceTraceSummary, VoiceS3TraceSinkClient, VoiceS3TraceSinkFile } from './trace';
124
126
  export type { VoiceTraceDeliveryDrainReport, VoiceTraceDeliveryDrainWorker, VoiceTraceDeliveryFilter, VoiceTraceDeliveryReport, VoiceTraceDeliveryRoutesOptions } from './traceDeliveryRoutes';
125
127
  export type { VoiceTraceTimelineEvent, VoiceTraceTimelineProviderSummary, VoiceTraceTimelineReport, VoiceTraceTimelineRoutesOptions, VoiceTraceTimelineSession } from './traceTimeline';
126
128
  export type { VoicePostgresClient, VoicePostgresRuntimeStorage, VoicePostgresStoreOptions } from './postgresStore';
package/dist/index.js CHANGED
@@ -8534,6 +8534,17 @@ var createVoiceTraceSinkDeliveryError = (input) => {
8534
8534
  }
8535
8535
  return `Attempt ${input.attempt} failed: ${String(input.error)}`;
8536
8536
  };
8537
+ var normalizeVoiceTraceS3KeyPrefix = (prefix) => prefix?.trim().replace(/^\/+|\/+$/g, "") ?? "voice/trace-deliveries";
8538
+ var createVoiceTraceS3ObjectKey = (prefix, events) => {
8539
+ const firstEvent = events[0];
8540
+ const safeSessionId = encodeURIComponent(firstEvent?.sessionId ?? "trace");
8541
+ const safeEventId = encodeURIComponent(firstEvent?.id ?? crypto.randomUUID());
8542
+ return `${prefix}/${safeSessionId}/${Date.now()}-${safeEventId}.json`;
8543
+ };
8544
+ var resolveVoiceS3DeliveredTo = (options, key) => {
8545
+ const bucket = options.bucket;
8546
+ return bucket ? `s3://${bucket}/${key}` : `s3://${key}`;
8547
+ };
8537
8548
  var aggregateVoiceTraceSinkDeliveryStatus = (deliveries) => {
8538
8549
  const statuses = Object.values(deliveries).map((delivery) => delivery.status);
8539
8550
  if (statuses.length === 0 || statuses.every((status) => status === "skipped")) {
@@ -8639,6 +8650,46 @@ var createVoiceTraceHTTPSink = (options) => ({
8639
8650
  id: options.id,
8640
8651
  kind: options.kind ?? "http"
8641
8652
  });
8653
+ var createVoiceTraceS3Sink = (options) => {
8654
+ const client = options.client ?? new Bun.S3Client(options);
8655
+ const keyPrefix = normalizeVoiceTraceS3KeyPrefix(options.keyPrefix);
8656
+ return {
8657
+ deliver: async ({ events }) => {
8658
+ const key = createVoiceTraceS3ObjectKey(keyPrefix, events);
8659
+ const payload = options.body ? await options.body({ events, key }) : {
8660
+ eventCount: events.length,
8661
+ events,
8662
+ key,
8663
+ source: "absolutejs-voice"
8664
+ };
8665
+ try {
8666
+ const file = client.file(key, options);
8667
+ await file.write(JSON.stringify(payload), {
8668
+ type: options.contentType ?? "application/json"
8669
+ });
8670
+ return {
8671
+ attempts: 1,
8672
+ deliveredAt: Date.now(),
8673
+ deliveredTo: resolveVoiceS3DeliveredTo(options, key),
8674
+ eventCount: events.length,
8675
+ responseBody: { key },
8676
+ status: "delivered"
8677
+ };
8678
+ } catch (error) {
8679
+ return {
8680
+ attempts: 1,
8681
+ deliveredTo: resolveVoiceS3DeliveredTo(options, key),
8682
+ error: error instanceof Error ? error.message : String(error),
8683
+ eventCount: events.length,
8684
+ status: "failed"
8685
+ };
8686
+ }
8687
+ },
8688
+ eventTypes: options.eventTypes,
8689
+ id: options.id,
8690
+ kind: options.kind ?? "s3"
8691
+ };
8692
+ };
8642
8693
  var deliverVoiceTraceEventsToSinks = async (input) => {
8643
8694
  const events = input.redact ? redactVoiceTraceEvents(input.events, input.redact) : input.events;
8644
8695
  const sinkDeliveries = {};
@@ -9431,6 +9482,17 @@ var createVoiceAuditSinkDeliveryError = (input) => {
9431
9482
  }
9432
9483
  return `Attempt ${input.attempt} failed: ${String(input.error)}`;
9433
9484
  };
9485
+ var normalizeVoiceAuditS3KeyPrefix = (prefix) => prefix?.trim().replace(/^\/+|\/+$/g, "") ?? "voice/audit-deliveries";
9486
+ var createVoiceAuditS3ObjectKey = (prefix, events) => {
9487
+ const firstEvent = events[0];
9488
+ const safeSessionId = encodeURIComponent(firstEvent?.sessionId ?? "audit");
9489
+ const safeEventId = encodeURIComponent(firstEvent?.id ?? crypto.randomUUID());
9490
+ return `${prefix}/${safeSessionId}/${Date.now()}-${safeEventId}.json`;
9491
+ };
9492
+ var resolveVoiceS3DeliveredTo2 = (options, key) => {
9493
+ const bucket = options.bucket;
9494
+ return bucket ? `s3://${bucket}/${key}` : `s3://${key}`;
9495
+ };
9434
9496
  var aggregateVoiceAuditSinkDeliveryStatus = (deliveries) => {
9435
9497
  const statuses = Object.values(deliveries).map((delivery) => delivery.status);
9436
9498
  if (statuses.length === 0 || statuses.every((status) => status === "skipped")) {
@@ -9559,6 +9621,46 @@ var createVoiceAuditHTTPSink = (options) => ({
9559
9621
  id: options.id,
9560
9622
  kind: options.kind ?? "http"
9561
9623
  });
9624
+ var createVoiceAuditS3Sink = (options) => {
9625
+ const client = options.client ?? new Bun.S3Client(options);
9626
+ const keyPrefix = normalizeVoiceAuditS3KeyPrefix(options.keyPrefix);
9627
+ return {
9628
+ deliver: async ({ events }) => {
9629
+ const key = createVoiceAuditS3ObjectKey(keyPrefix, events);
9630
+ const payload = options.body ? await options.body({ events, key }) : {
9631
+ eventCount: events.length,
9632
+ events,
9633
+ key,
9634
+ source: "absolutejs-voice"
9635
+ };
9636
+ try {
9637
+ const file = client.file(key, options);
9638
+ await file.write(JSON.stringify(payload), {
9639
+ type: options.contentType ?? "application/json"
9640
+ });
9641
+ return {
9642
+ attempts: 1,
9643
+ deliveredAt: Date.now(),
9644
+ deliveredTo: resolveVoiceS3DeliveredTo2(options, key),
9645
+ eventCount: events.length,
9646
+ responseBody: { key },
9647
+ status: "delivered"
9648
+ };
9649
+ } catch (error) {
9650
+ return {
9651
+ attempts: 1,
9652
+ deliveredTo: resolveVoiceS3DeliveredTo2(options, key),
9653
+ error: error instanceof Error ? error.message : String(error),
9654
+ eventCount: events.length,
9655
+ status: "failed"
9656
+ };
9657
+ }
9658
+ },
9659
+ eventTypes: options.eventTypes,
9660
+ id: options.id,
9661
+ kind: options.kind ?? "s3"
9662
+ };
9663
+ };
9562
9664
  var deliverVoiceAuditEventsToSinks = async (input) => {
9563
9665
  const events = input.redact === false ? input.events : redactVoiceAuditEvents(input.events, input.redact ?? true);
9564
9666
  const sinkDeliveries = {};
@@ -11462,6 +11564,68 @@ var createVoiceDeliverySinkRoutes = (options) => {
11462
11564
  }
11463
11565
  return routes;
11464
11566
  };
11567
+ // src/deliveryRuntime.ts
11568
+ var createVoiceDeliveryRuntime = (config) => {
11569
+ const audit = config.audit ? createVoiceAuditSinkDeliveryWorker(config.audit) : undefined;
11570
+ const trace = config.trace ? createVoiceTraceSinkDeliveryWorker(config.trace) : undefined;
11571
+ let auditLoop;
11572
+ let traceLoop;
11573
+ if (audit && config.audit) {
11574
+ auditLoop = createVoiceAuditSinkDeliveryWorkerLoop({
11575
+ onError: config.audit.onError,
11576
+ pollIntervalMs: config.audit.pollIntervalMs,
11577
+ worker: audit
11578
+ });
11579
+ }
11580
+ if (trace && config.trace) {
11581
+ traceLoop = createVoiceTraceSinkDeliveryWorkerLoop({
11582
+ onError: config.trace.onError,
11583
+ pollIntervalMs: config.trace.pollIntervalMs,
11584
+ worker: trace
11585
+ });
11586
+ }
11587
+ return {
11588
+ audit,
11589
+ isRunning: () => Boolean(auditLoop?.isRunning() || traceLoop?.isRunning()),
11590
+ start: () => {
11591
+ if (config.audit?.autoStart) {
11592
+ auditLoop?.start();
11593
+ }
11594
+ if (config.trace?.autoStart) {
11595
+ traceLoop?.start();
11596
+ }
11597
+ },
11598
+ stop: () => {
11599
+ auditLoop?.stop();
11600
+ traceLoop?.stop();
11601
+ },
11602
+ summarize: async () => {
11603
+ const summary = {};
11604
+ if (config.audit) {
11605
+ summary.audit = await summarizeVoiceAuditSinkDeliveries(await config.audit.deliveries.list(), {
11606
+ deadLetters: config.audit.deadLetters
11607
+ });
11608
+ }
11609
+ if (config.trace) {
11610
+ summary.trace = await summarizeVoiceTraceSinkDeliveries(await config.trace.deliveries.list(), {
11611
+ deadLetters: config.trace.deadLetters
11612
+ });
11613
+ }
11614
+ return summary;
11615
+ },
11616
+ tick: async () => {
11617
+ const result = {};
11618
+ if (auditLoop) {
11619
+ result.audit = await auditLoop.tick();
11620
+ }
11621
+ if (traceLoop) {
11622
+ result.trace = await traceLoop.tick();
11623
+ }
11624
+ return result;
11625
+ },
11626
+ trace
11627
+ };
11628
+ };
11465
11629
  // src/dataControl.ts
11466
11630
  var allRetentionScopes = [
11467
11631
  "auditDeliveries",
@@ -23130,6 +23294,7 @@ export {
23130
23294
  createVoiceTraceSinkDeliveryWorker,
23131
23295
  createVoiceTraceSinkDeliveryRecord,
23132
23296
  createVoiceTraceSinkDeliveryId,
23297
+ createVoiceTraceS3Sink,
23133
23298
  createVoiceTraceHTTPSink,
23134
23299
  createVoiceTraceEventId,
23135
23300
  createVoiceTraceEvent,
@@ -23275,6 +23440,7 @@ export {
23275
23440
  createVoiceDeliverySinkRoutes,
23276
23441
  createVoiceDeliverySinkPair,
23277
23442
  createVoiceDeliverySinkDescriptor,
23443
+ createVoiceDeliveryRuntime,
23278
23444
  createVoiceCampaignWorkerLoop,
23279
23445
  createVoiceCampaignWorker,
23280
23446
  createVoiceCampaignTelephonyOutcomeHandler,
@@ -23292,6 +23458,7 @@ export {
23292
23458
  createVoiceAuditSinkDeliveryWorker,
23293
23459
  createVoiceAuditSinkDeliveryRecord,
23294
23460
  createVoiceAuditSinkDeliveryId,
23461
+ createVoiceAuditS3Sink,
23295
23462
  createVoiceAuditLogger,
23296
23463
  createVoiceAuditHTTPSink,
23297
23464
  createVoiceAuditEvent,
package/dist/trace.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { S3Client, S3Options } from 'bun';
1
2
  export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'client.live_latency' | 'client.reconnect' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
2
3
  export type VoiceTraceEvent<TPayload extends Record<string, unknown> = Record<string, unknown>> = {
3
4
  at: number;
@@ -101,6 +102,22 @@ export type VoiceTraceHTTPSinkOptions<TBody extends Record<string, unknown> = Re
101
102
  timeoutMs?: number;
102
103
  url: string;
103
104
  };
105
+ export type VoiceS3TraceSinkFile = {
106
+ write: (data: string, options?: BlobPropertyBag) => Promise<number> | number;
107
+ };
108
+ export type VoiceS3TraceSinkClient = Pick<S3Client, 'file'>;
109
+ export type VoiceTraceS3SinkOptions<TBody extends Record<string, unknown> = Record<string, unknown>> = S3Options & {
110
+ body?: (input: {
111
+ events: StoredVoiceTraceEvent[];
112
+ key: string;
113
+ }) => Promise<TBody> | TBody;
114
+ client?: VoiceS3TraceSinkClient;
115
+ contentType?: string;
116
+ eventTypes?: VoiceTraceEventType[];
117
+ id: string;
118
+ keyPrefix?: string;
119
+ kind?: string;
120
+ };
104
121
  export type VoiceTraceSinkStoreOptions<TEvent extends StoredVoiceTraceEvent = StoredVoiceTraceEvent> = {
105
122
  awaitDelivery?: boolean;
106
123
  deliveryQueue?: VoiceTraceSinkDeliveryStore;
@@ -187,6 +204,7 @@ export declare const filterVoiceTraceEvents: <TEvent extends StoredVoiceTraceEve
187
204
  export declare const selectVoiceTraceEventsForPrune: <TEvent extends StoredVoiceTraceEvent = StoredVoiceTraceEvent>(events: TEvent[], options?: Omit<VoiceTracePruneOptions, "store">) => TEvent[];
188
205
  export declare const pruneVoiceTraceEvents: (options: VoiceTracePruneOptions) => Promise<VoiceTracePruneResult>;
189
206
  export declare const createVoiceTraceHTTPSink: <TBody extends Record<string, unknown> = Record<string, unknown>>(options: VoiceTraceHTTPSinkOptions<TBody>) => VoiceTraceSink;
207
+ export declare const createVoiceTraceS3Sink: <TBody extends Record<string, unknown> = Record<string, unknown>>(options: VoiceTraceS3SinkOptions<TBody>) => VoiceTraceSink;
190
208
  export declare const deliverVoiceTraceEventsToSinks: (input: {
191
209
  events: StoredVoiceTraceEvent[];
192
210
  redact?: VoiceTraceRedactionConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.145",
3
+ "version": "0.0.22-beta.147",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",