@absolutejs/voice 0.0.22-beta.497 → 0.0.22-beta.498

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.
@@ -59,7 +59,7 @@ export type VoiceAssistantExperimentOptions<TContext = unknown, TSession extends
59
59
  }) => VoiceAssistantVariant<TContext, TSession, TResult> | string | void;
60
60
  variants: Array<VoiceAssistantVariant<TContext, TSession, TResult>>;
61
61
  };
62
- type VoiceAssistantAgentSource<TContext, TSession extends VoiceSessionRecord, TResult> = {
62
+ export type VoiceAssistantAgentSource<TContext, TSession extends VoiceSessionRecord, TResult> = {
63
63
  agent: VoiceAgent<TContext, TSession, TResult>;
64
64
  agents?: never;
65
65
  defaultAgentId?: never;
@@ -140,4 +140,3 @@ export declare const summarizeVoiceAssistantRuns: (input: StoredVoiceTraceEvent[
140
140
  events?: StoredVoiceTraceEvent[];
141
141
  store?: VoiceTraceEventStore;
142
142
  }) => Promise<VoiceAssistantRunsSummary>;
143
- export {};
@@ -0,0 +1,54 @@
1
+ export type VoiceCallQuotaTier = {
2
+ burstAllowance?: number;
3
+ customerId: string;
4
+ monthlyMinutes?: number;
5
+ reservedConcurrent: number;
6
+ };
7
+ export type VoiceCallReservation = {
8
+ callId: string;
9
+ customerId: string;
10
+ release: () => Promise<void> | void;
11
+ reservedAt: number;
12
+ };
13
+ export type VoiceCallQuotaRejection = {
14
+ customerId: string;
15
+ reason: "concurrency-exceeded" | "customer-not-found" | "monthly-minutes-exceeded";
16
+ retryAfterMs?: number;
17
+ };
18
+ export type VoiceCallQuotaResult = {
19
+ ok: false;
20
+ rejection: VoiceCallQuotaRejection;
21
+ } | {
22
+ ok: true;
23
+ reservation: VoiceCallReservation;
24
+ };
25
+ export type VoiceCallQuota = {
26
+ describe: (customerId: string) => Promise<undefined | {
27
+ activeCalls: number;
28
+ burstAllowance: number;
29
+ monthlyMinutesUsed: number;
30
+ reservedConcurrent: number;
31
+ tier: VoiceCallQuotaTier;
32
+ }> | (undefined | {
33
+ activeCalls: number;
34
+ burstAllowance: number;
35
+ monthlyMinutesUsed: number;
36
+ reservedConcurrent: number;
37
+ tier: VoiceCallQuotaTier;
38
+ });
39
+ recordMinutes: (input: {
40
+ callId?: string;
41
+ customerId: string;
42
+ minutes: number;
43
+ }) => Promise<void> | void;
44
+ reserve: (input: {
45
+ callId: string;
46
+ customerId: string;
47
+ }) => Promise<VoiceCallQuotaResult> | VoiceCallQuotaResult;
48
+ };
49
+ export type CreateInMemoryVoiceCallQuotaOptions = {
50
+ /** When provided, treat any customer not in the map as denied with 'customer-not-found'. */
51
+ strict?: boolean;
52
+ tiers: VoiceCallQuotaTier[];
53
+ };
54
+ export declare const createInMemoryVoiceCallQuota: (options: CreateInMemoryVoiceCallQuotaOptions) => VoiceCallQuota;
@@ -0,0 +1,27 @@
1
+ import type { StoredVoiceTraceEvent } from "../trace";
2
+ export type VoiceCostDashboardBucket = {
3
+ bucketKey: string;
4
+ callCount: number;
5
+ llmUsd: number;
6
+ sttUsd: number;
7
+ telephonyMinutes: number;
8
+ telephonyUsd: number;
9
+ totalUsd: number;
10
+ ttsUsd: number;
11
+ };
12
+ export type VoiceCostDashboardReport = {
13
+ buckets: VoiceCostDashboardBucket[];
14
+ generatedAt: number;
15
+ grandTotal: VoiceCostDashboardBucket;
16
+ windowEndMs: number;
17
+ windowStartMs: number;
18
+ };
19
+ export type VoiceCostDashboardOptions = {
20
+ bucketBy?: "day" | "hour" | "month";
21
+ events: ReadonlyArray<StoredVoiceTraceEvent>;
22
+ /** Inclusive bucket start filter, epoch ms. */
23
+ fromMs?: number;
24
+ /** Inclusive bucket end filter, epoch ms. */
25
+ toMs?: number;
26
+ };
27
+ export declare const buildVoiceCostDashboardReport: (options: VoiceCostDashboardOptions) => VoiceCostDashboardReport;
@@ -0,0 +1,42 @@
1
+ import type { VoiceAgentUIState } from "../agentState";
2
+ export type LiveCallEventKind = "agent_audio" | "agent_text" | "lifecycle" | "transcript" | "tool";
3
+ export type LiveCallTimelineEvent = {
4
+ at: number;
5
+ detail?: string;
6
+ kind: LiveCallEventKind;
7
+ title: string;
8
+ };
9
+ export type LiveCallViewState = {
10
+ agentState: VoiceAgentUIState;
11
+ callDurationMs: number;
12
+ events: LiveCallTimelineEvent[];
13
+ isConnected: boolean;
14
+ isLiveListening: boolean;
15
+ lastAssistantAt?: number;
16
+ lastTranscriptAt?: number;
17
+ partialTranscript: string;
18
+ sessionId: string;
19
+ };
20
+ export type CreateLiveCallViewerOptions = {
21
+ bufferLimit?: number;
22
+ sessionId: string;
23
+ startedAt?: number;
24
+ };
25
+ export type LiveCallViewer = {
26
+ applyControl: (control: {
27
+ reason?: string;
28
+ type: string;
29
+ }) => void;
30
+ applyEvent: (event: LiveCallTimelineEvent) => void;
31
+ applyMonitorEvent: (event: {
32
+ payload: Record<string, unknown>;
33
+ type: string;
34
+ }) => void;
35
+ getState: () => LiveCallViewState;
36
+ noteAgentAudio: (at?: number) => void;
37
+ notePartial: (text: string, at?: number) => void;
38
+ noteTranscript: (text: string, at?: number) => void;
39
+ reset: (sessionId: string, startedAt?: number) => void;
40
+ subscribe: (subscriber: () => void) => () => void;
41
+ };
42
+ export declare const createLiveCallViewer: (options: CreateLiveCallViewerOptions) => LiveCallViewer;
@@ -0,0 +1,26 @@
1
+ import type { VoiceCallReviewArtifact } from "../testing/review";
2
+ export type ReplayTimelineEvent = {
3
+ at: number;
4
+ category: "agent" | "lifecycle" | "tool" | "user";
5
+ detail?: string;
6
+ durationMs?: number;
7
+ label: string;
8
+ };
9
+ export type ReplayTimelineReport = {
10
+ duration: number;
11
+ events: ReplayTimelineEvent[];
12
+ metadata: {
13
+ artifactId: string;
14
+ title: string;
15
+ };
16
+ startedAt: number;
17
+ summary: {
18
+ agentTurns: number;
19
+ toolCalls: number;
20
+ userTurns: number;
21
+ };
22
+ };
23
+ export type ReplayTimelineInput = {
24
+ artifact: VoiceCallReviewArtifact;
25
+ };
26
+ export declare const buildReplayTimelineReport: (input: ReplayTimelineInput) => ReplayTimelineReport;
@@ -0,0 +1,68 @@
1
+ import { type VoiceAssistant, type VoiceAssistantAgentSource, type VoiceAssistantGuardrails, type VoiceAssistantMemoryLifecycle } from "./assistant";
2
+ import type { AudioFormat, CreateVoiceSessionOptions, RealtimeAdapter, STTAdapter, TTSAdapter, VoiceLanguageStrategy, VoiceLexiconEntry, VoicePhraseHint, VoiceReconnectConfig, VoiceResolvedSTTFallbackConfig, VoiceResolvedAudioConditioningConfig, VoiceRouteConfig, VoiceSessionRecord, VoiceSessionRecordingConfig, VoiceSessionStore, VoiceSocket, VoiceSTTLifecycle, VoiceTTSProsody, VoiceTurnDetectionConfig } from "./types";
3
+ import type { VoiceAssistantMemoryOptions } from "./assistantMemory";
4
+ import type { VoiceAgentTool } from "./agent";
5
+ import type { VoiceAMDDetector } from "./amdDetector";
6
+ import type { VoiceCostAccountant } from "./costAccounting";
7
+ import type { VoiceTraceEventStore } from "./trace";
8
+ import type { VoiceTranscriptRedactor } from "./redaction";
9
+ import type { VoiceSemanticTurnDetector } from "./semanticTurn";
10
+ import type { VoiceAssistantMode } from "./assistantMode";
11
+ import type { VoiceRuntimeOpsConfig } from "./types";
12
+ export type VoiceAssistantVoiceConfig = {
13
+ prosody?: VoiceTTSProsody;
14
+ realtime?: RealtimeAdapter;
15
+ realtimeInputFormat?: AudioFormat;
16
+ stt?: STTAdapter;
17
+ sttFallback?: VoiceResolvedSTTFallbackConfig;
18
+ tts?: TTSAdapter;
19
+ };
20
+ export type VoiceAssistantObservabilityConfig = {
21
+ costAccountant?: VoiceCostAccountant;
22
+ costTelephony?: {
23
+ provider?: string;
24
+ };
25
+ recording?: VoiceSessionRecordingConfig;
26
+ trace?: VoiceTraceEventStore;
27
+ };
28
+ export type VoiceAssistantDefinition<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
29
+ agent: VoiceAssistantAgentSource<TContext, TSession, TResult>;
30
+ amd?: VoiceAMDDetector<TContext, TSession, TResult>;
31
+ assistantMode?: VoiceAssistantMode;
32
+ audioConditioning?: VoiceResolvedAudioConditioningConfig;
33
+ callSilenceTimeoutMs?: number;
34
+ guardrails?: VoiceAssistantGuardrails<TContext, TSession, TResult>;
35
+ id: string;
36
+ languageStrategy?: VoiceLanguageStrategy;
37
+ lexicon?: VoiceLexiconEntry[];
38
+ memory?: VoiceAssistantMemoryOptions<TContext, TSession>;
39
+ memoryLifecycle?: VoiceAssistantMemoryLifecycle<TContext, TSession, TResult>;
40
+ metadata?: Record<string, unknown>;
41
+ modalities?: ReadonlyArray<"audio" | "text">;
42
+ ops?: VoiceRuntimeOpsConfig<TContext, TSession, TResult>;
43
+ observability?: VoiceAssistantObservabilityConfig;
44
+ phraseHints?: VoicePhraseHint[];
45
+ redact?: VoiceTranscriptRedactor;
46
+ route?: Partial<VoiceRouteConfig<TContext, TSession, TResult>>;
47
+ semanticTurnDetector?: VoiceSemanticTurnDetector;
48
+ tools?: ReadonlyArray<VoiceAgentTool<TContext, TSession, Record<string, unknown>, unknown, TResult>>;
49
+ turnDetection?: VoiceTurnDetectionConfig;
50
+ voice: VoiceAssistantVoiceConfig;
51
+ };
52
+ export type VoiceAssistantSessionInput<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord> = {
53
+ context: TContext;
54
+ id: string;
55
+ reconnect?: Partial<VoiceReconnectConfig>;
56
+ scenarioId?: string;
57
+ sessionMetadata?: Record<string, unknown>;
58
+ socket: VoiceSocket;
59
+ sttLifecycle?: VoiceSTTLifecycle;
60
+ store: VoiceSessionStore<TSession>;
61
+ };
62
+ export type DefinedVoiceAssistant<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
63
+ assistant: VoiceAssistant<TContext, TSession, TResult>;
64
+ definition: VoiceAssistantDefinition<TContext, TSession, TResult>;
65
+ id: string;
66
+ toSessionOptions: (input: VoiceAssistantSessionInput<TContext, TSession>) => CreateVoiceSessionOptions<TContext, TSession, TResult>;
67
+ };
68
+ export declare const defineVoiceAssistant: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(definition: VoiceAssistantDefinition<TContext, TSession, TResult>) => DefinedVoiceAssistant<TContext, TSession, TResult>;
package/dist/index.d.ts CHANGED
@@ -75,6 +75,8 @@ export { createVoiceAIJudgeCompletion, createVoiceLLMJudge, } from "./llmJudge";
75
75
  export type { CreateVoiceAIJudgeCompletionOptions, CreateVoiceLLMJudgeOptions, VoiceLLMJudge, VoiceLLMJudgeCompletion, VoiceLLMJudgeCriterionVerdict, VoiceLLMJudgeInput, VoiceLLMJudgeRubric, VoiceLLMJudgeRubricCriterion, VoiceLLMJudgeVerdict, } from "./llmJudge";
76
76
  export { DEFAULT_VOICE_REDACTION_PATTERNS, createVoiceTranscriptRedactor, redactVoiceTranscript, } from "./redaction";
77
77
  export type { CreateVoiceTranscriptRedactorOptions, VoiceRedactionPattern, VoiceTranscriptRedactor, } from "./redaction";
78
+ export { deriveVoiceRecordingRedactionRanges } from "./recordingRedaction";
79
+ export type { DeriveVoiceRecordingRedactionRangesInput, VoiceRecordingRedactionRange, } from "./recordingRedaction";
78
80
  export { DEFAULT_VOICE_PRICE_BOOK, createVoiceCostAccountant, } from "./costAccounting";
79
81
  export type { CreateVoiceCostAccountantOptions, VoiceCostAccountant, VoiceCostBreakdown, VoiceCostLLMRecord, VoiceCostSTTRecord, VoiceCostTTSRecord, VoiceCostTelephonyRecord, VoicePriceBook, VoiceProviderRates, } from "./costAccounting";
80
82
  export { describeVoiceAssistantMode, resolveVoiceAssistantMode, } from "./assistantMode";
@@ -102,6 +104,20 @@ export type { MonologueAMDDetectorOptions, VoiceAMDDetector, VoiceAMDDetectorInp
102
104
  export { createVoiceRAGTool, extractVoiceRAGCitations } from "./ragTool";
103
105
  export type { VoiceRAGCitationSummary, VoiceRAGCollectionLike, VoiceRAGQueryResult, VoiceRAGSearchInput, VoiceRAGToolArgs, VoiceRAGToolOptions, VoiceRAGToolResult, } from "./ragTool";
104
106
  export { createVoiceApiRequestTool, createVoiceDTMFTool, createVoiceEndCallTool, createVoiceTransferCallTool, createVoiceVoicemailDetectionTool, } from "./agentTools";
107
+ export { defineVoiceAssistant } from "./defineVoiceAssistant";
108
+ export type { DefinedVoiceAssistant, VoiceAssistantDefinition, VoiceAssistantObservabilityConfig, VoiceAssistantSessionInput, VoiceAssistantVoiceConfig, } from "./defineVoiceAssistant";
109
+ export { createInMemoryVoiceCallQuota } from "./callQuota";
110
+ export type { CreateInMemoryVoiceCallQuotaOptions, VoiceCallQuota, VoiceCallQuotaRejection, VoiceCallQuotaResult, VoiceCallQuotaTier, VoiceCallReservation, } from "./callQuota";
111
+ export { createVoiceBearerAuthVerifier, createVoiceHMACAuthVerifier, createVoiceRouteAuth, } from "./routeAuth";
112
+ export type { VoiceRouteAuthDecision, VoiceRouteAuthInput, VoiceRouteAuthOptions, VoiceRouteAuthVerifier, } from "./routeAuth";
113
+ export { buildVoiceCostDashboardReport } from "./client/costDashboard";
114
+ export type { VoiceCostDashboardBucket, VoiceCostDashboardOptions, VoiceCostDashboardReport, } from "./client/costDashboard";
115
+ export { createLiveCallViewer } from "./client/liveCallViewer";
116
+ export type { CreateLiveCallViewerOptions, LiveCallEventKind, LiveCallTimelineEvent, LiveCallViewState, LiveCallViewer, } from "./client/liveCallViewer";
117
+ export { buildReplayTimelineReport } from "./client/replayTimeline";
118
+ export type { ReplayTimelineEvent, ReplayTimelineInput, ReplayTimelineReport, } from "./client/replayTimeline";
119
+ export { createVoiceRetentionScheduler, purgeVoiceRetentionStore, } from "./retention";
120
+ export type { CreateVoiceRetentionSchedulerOptions, VoicePurgeReport, VoiceRetentionPolicyOptions, VoiceRetentionScheduler, VoiceRetentionStore, } from "./retention";
105
121
  export { fromVapiAssistantConfig } from "./vapiAdapter";
106
122
  export type { VapiAssistantConfig, VapiAssistantConfigModel, VapiAssistantConfigTool, VapiAssistantConfigTranscriber, VapiAssistantConfigTransferDestination, VapiAssistantConfigVoice, VapiAssistantMessage, VoiceFromVapiAssistantOptions, VoiceFromVapiAssistantResult, VoiceFromVapiCustomToolFactory, VoiceFromVapiCustomToolInput, VoiceFromVapiDTMFFactory, VoiceFromVapiKnowledgeBase, VoiceFromVapiModelFactory, VoiceFromVapiModelFactoryInput, VoiceFromVapiRouteHints, VoiceFromVapiUnsupportedReason, } from "./vapiAdapter";
107
123
  export type { VoiceApiRequestToolArgs, VoiceApiRequestToolFetch, VoiceApiRequestToolHttpMethod, VoiceApiRequestToolOptions, VoiceApiRequestToolResult, VoiceDTMFToolArgs, VoiceDTMFToolOptions, VoiceDTMFToolResult, VoiceEndCallToolArgs, VoiceEndCallToolOptions, VoiceEndCallToolResult, VoiceTransferCallToolArgs, VoiceTransferCallToolDestination, VoiceTransferCallToolOptions, VoiceTransferCallToolResult, VoiceVoicemailDetectionToolArgs, VoiceVoicemailDetectionToolOptions, VoiceVoicemailDetectionToolResult, } from "./agentTools";
package/dist/index.js CHANGED
@@ -35232,6 +35232,44 @@ var createVoiceTranscriptRedactor = (options = {}) => {
35232
35232
  };
35233
35233
  };
35234
35234
  var redactVoiceTranscript = (transcript, patterns = DEFAULT_VOICE_REDACTION_PATTERNS) => createVoiceTranscriptRedactor({ patterns })(transcript);
35235
+ // src/recordingRedaction.ts
35236
+ var matchesAnyPattern = (text, patterns) => {
35237
+ for (const pattern of patterns) {
35238
+ pattern.regex.lastIndex = 0;
35239
+ if (pattern.regex.test(text)) {
35240
+ pattern.regex.lastIndex = 0;
35241
+ return pattern;
35242
+ }
35243
+ }
35244
+ return;
35245
+ };
35246
+ var deriveVoiceRecordingRedactionRanges = (input) => {
35247
+ const patterns = input.patterns ?? DEFAULT_VOICE_REDACTION_PATTERNS;
35248
+ const padding = Math.max(0, input.paddingMs ?? 100);
35249
+ const baseEpoch = input.recordingStartedAtEpochMs;
35250
+ const out = [];
35251
+ for (const transcript of input.transcripts) {
35252
+ if (!transcript.isFinal)
35253
+ continue;
35254
+ if (typeof transcript.startedAtMs !== "number")
35255
+ continue;
35256
+ if (typeof transcript.endedAtMs !== "number")
35257
+ continue;
35258
+ const matched = matchesAnyPattern(transcript.text, patterns);
35259
+ if (!matched)
35260
+ continue;
35261
+ const absStart = transcript.startedAtMs;
35262
+ const absEnd = transcript.endedAtMs;
35263
+ const start = typeof baseEpoch === "number" && absStart >= baseEpoch ? absStart - baseEpoch : absStart;
35264
+ const end = typeof baseEpoch === "number" && absEnd >= baseEpoch ? absEnd - baseEpoch : absEnd;
35265
+ out.push({
35266
+ endMs: end + padding,
35267
+ label: matched.label,
35268
+ startMs: Math.max(0, start - padding)
35269
+ });
35270
+ }
35271
+ return out;
35272
+ };
35235
35273
  // src/costAccounting.ts
35236
35274
  var DEFAULT_VOICE_PRICE_BOOK = {
35237
35275
  "anthropic:claude-opus-4-5": {
@@ -36481,6 +36519,524 @@ var createVoiceApiRequestTool = (options) => {
36481
36519
  resultToMessage: options.formatResult ?? ((result) => result.ok ? `API request ${options.name} succeeded (${String(result.status)}).` : `API request ${options.name} failed with status ${String(result.status)}.`)
36482
36520
  });
36483
36521
  };
36522
+ // src/defineVoiceAssistant.ts
36523
+ var DEFAULT_SPEECH_THRESHOLD2 = 0.015;
36524
+ var DEFAULT_SILENCE_MS2 = 700;
36525
+ var DEFAULT_TRANSCRIPT_STABILITY_MS2 = 200;
36526
+ var resolveTurnDetection = (input) => ({
36527
+ profile: input?.profile ?? "balanced",
36528
+ qualityProfile: input?.qualityProfile ?? "general",
36529
+ silenceMs: input?.silenceMs ?? DEFAULT_SILENCE_MS2,
36530
+ speechThreshold: input?.speechThreshold ?? DEFAULT_SPEECH_THRESHOLD2,
36531
+ transcriptStabilityMs: input?.transcriptStabilityMs ?? DEFAULT_TRANSCRIPT_STABILITY_MS2
36532
+ });
36533
+ var resolveReconnect = (input) => ({
36534
+ maxAttempts: input?.maxAttempts ?? 3,
36535
+ strategy: input?.strategy ?? "resume-last-turn",
36536
+ timeout: input?.timeout ?? 30000
36537
+ });
36538
+ var buildAssistantOptions = (def) => ({
36539
+ ...def.agent,
36540
+ guardrails: def.guardrails,
36541
+ id: def.id,
36542
+ memory: def.memory,
36543
+ memoryLifecycle: def.memoryLifecycle,
36544
+ ops: def.ops
36545
+ });
36546
+ var defineVoiceAssistant = (definition) => {
36547
+ const assistantOptions = buildAssistantOptions(definition);
36548
+ const assistant = createVoiceAssistant(assistantOptions);
36549
+ return {
36550
+ assistant,
36551
+ definition,
36552
+ id: definition.id,
36553
+ toSessionOptions: (input) => {
36554
+ const route = assistant.route(definition.route ?? {});
36555
+ const observability = definition.observability ?? {};
36556
+ return {
36557
+ amd: definition.amd,
36558
+ assistantMode: definition.assistantMode,
36559
+ audioConditioning: definition.audioConditioning,
36560
+ callSilenceTimeoutMs: definition.callSilenceTimeoutMs,
36561
+ context: input.context,
36562
+ costAccountant: observability.costAccountant,
36563
+ costTelephony: observability.costTelephony,
36564
+ id: input.id,
36565
+ languageStrategy: definition.languageStrategy,
36566
+ lexicon: definition.lexicon,
36567
+ modalities: definition.modalities,
36568
+ phraseHints: definition.phraseHints,
36569
+ prosody: definition.voice.prosody,
36570
+ realtime: definition.voice.realtime,
36571
+ realtimeInputFormat: definition.voice.realtimeInputFormat,
36572
+ reconnect: resolveReconnect(input.reconnect),
36573
+ recording: observability.recording,
36574
+ redact: definition.redact,
36575
+ route,
36576
+ scenarioId: input.scenarioId,
36577
+ semanticTurnDetector: definition.semanticTurnDetector,
36578
+ sessionMetadata: { ...definition.metadata, ...input.sessionMetadata },
36579
+ socket: input.socket,
36580
+ store: input.store,
36581
+ stt: definition.voice.stt,
36582
+ sttFallback: definition.voice.sttFallback,
36583
+ sttLifecycle: input.sttLifecycle ?? "continuous",
36584
+ trace: observability.trace,
36585
+ tts: definition.voice.tts,
36586
+ turnDetection: resolveTurnDetection(definition.turnDetection)
36587
+ };
36588
+ }
36589
+ };
36590
+ };
36591
+ // src/callQuota.ts
36592
+ var monthBucketKey = (epochMs) => {
36593
+ const date = new Date(epochMs);
36594
+ return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`;
36595
+ };
36596
+ var createInMemoryVoiceCallQuota = (options) => {
36597
+ const tiers = new Map(options.tiers.map((tier) => [tier.customerId, tier]));
36598
+ const activeCalls = new Map;
36599
+ const monthlyUsage = new Map;
36600
+ const usageFor = (customerId) => {
36601
+ const key = monthBucketKey(Date.now());
36602
+ let bucket = monthlyUsage.get(customerId);
36603
+ if (!bucket) {
36604
+ bucket = new Map;
36605
+ monthlyUsage.set(customerId, bucket);
36606
+ }
36607
+ return { bucket, key };
36608
+ };
36609
+ return {
36610
+ describe: (customerId) => {
36611
+ const tier = tiers.get(customerId);
36612
+ if (!tier)
36613
+ return;
36614
+ const active = activeCalls.get(customerId)?.size ?? 0;
36615
+ const { bucket, key } = usageFor(customerId);
36616
+ return {
36617
+ activeCalls: active,
36618
+ burstAllowance: tier.burstAllowance ?? 0,
36619
+ monthlyMinutesUsed: bucket.get(key) ?? 0,
36620
+ reservedConcurrent: tier.reservedConcurrent,
36621
+ tier
36622
+ };
36623
+ },
36624
+ recordMinutes: ({ customerId, minutes }) => {
36625
+ const { bucket, key } = usageFor(customerId);
36626
+ bucket.set(key, (bucket.get(key) ?? 0) + Math.max(0, minutes));
36627
+ },
36628
+ reserve: ({ callId, customerId }) => {
36629
+ const tier = tiers.get(customerId);
36630
+ if (!tier) {
36631
+ if (options.strict) {
36632
+ return {
36633
+ ok: false,
36634
+ rejection: { customerId, reason: "customer-not-found" }
36635
+ };
36636
+ }
36637
+ return {
36638
+ ok: true,
36639
+ reservation: {
36640
+ callId,
36641
+ customerId,
36642
+ release: () => {},
36643
+ reservedAt: Date.now()
36644
+ }
36645
+ };
36646
+ }
36647
+ const limit = tier.reservedConcurrent + (tier.burstAllowance ?? 0);
36648
+ const set = activeCalls.get(customerId) ?? new Set;
36649
+ if (set.size >= limit) {
36650
+ return {
36651
+ ok: false,
36652
+ rejection: {
36653
+ customerId,
36654
+ reason: "concurrency-exceeded",
36655
+ retryAfterMs: 30000
36656
+ }
36657
+ };
36658
+ }
36659
+ if (typeof tier.monthlyMinutes === "number") {
36660
+ const { bucket, key } = usageFor(customerId);
36661
+ if ((bucket.get(key) ?? 0) >= tier.monthlyMinutes) {
36662
+ return {
36663
+ ok: false,
36664
+ rejection: {
36665
+ customerId,
36666
+ reason: "monthly-minutes-exceeded"
36667
+ }
36668
+ };
36669
+ }
36670
+ }
36671
+ set.add(callId);
36672
+ activeCalls.set(customerId, set);
36673
+ return {
36674
+ ok: true,
36675
+ reservation: {
36676
+ callId,
36677
+ customerId,
36678
+ release: () => {
36679
+ set.delete(callId);
36680
+ if (set.size === 0)
36681
+ activeCalls.delete(customerId);
36682
+ },
36683
+ reservedAt: Date.now()
36684
+ }
36685
+ };
36686
+ }
36687
+ };
36688
+ };
36689
+ // src/routeAuth.ts
36690
+ import { Elysia as Elysia53 } from "elysia";
36691
+ var createVoiceBearerAuthVerifier = (input) => {
36692
+ const headerName = (input.headerName ?? "authorization").toLowerCase();
36693
+ const expected = `Bearer ${input.expectedToken}`;
36694
+ return ({ headers }) => {
36695
+ const value = headers.get(headerName);
36696
+ if (!value) {
36697
+ return { allow: false, reason: "missing-bearer", status: 401 };
36698
+ }
36699
+ if (value !== expected) {
36700
+ return { allow: false, reason: "bearer-mismatch", status: 401 };
36701
+ }
36702
+ return { allow: true };
36703
+ };
36704
+ };
36705
+ var createVoiceHMACAuthVerifier = (input) => {
36706
+ return async ({ body, headers }) => {
36707
+ const { signature, timestamp } = extractVoiceWebhookSignatureFromHeaders(headers);
36708
+ const result = await verifyVoiceWebhookSignature({
36709
+ body: body ?? "",
36710
+ secret: input.secret,
36711
+ signature,
36712
+ timestamp,
36713
+ toleranceMs: input.toleranceMs
36714
+ });
36715
+ if (!result.ok) {
36716
+ return { allow: false, reason: result.reason, status: 401 };
36717
+ }
36718
+ return { allow: true };
36719
+ };
36720
+ };
36721
+ var isBypassed = (bypassPaths, url) => {
36722
+ for (const path of bypassPaths) {
36723
+ if (url.includes(path))
36724
+ return true;
36725
+ }
36726
+ return false;
36727
+ };
36728
+ var createVoiceRouteAuth = (options) => {
36729
+ const bypassPaths = options.bypassPaths ?? [];
36730
+ return new Elysia53({ name: options.name ?? "voice-route-auth" }).onRequest(async ({ request, set }) => {
36731
+ const url = request.url;
36732
+ if (isBypassed(bypassPaths, url))
36733
+ return;
36734
+ const cloned = request.clone();
36735
+ const body = request.method === "GET" || request.method === "HEAD" ? "" : await cloned.text().catch(() => "");
36736
+ const decision = await Promise.resolve(options.verify({
36737
+ body,
36738
+ headers: request.headers,
36739
+ method: request.method,
36740
+ url
36741
+ }));
36742
+ if (!decision.allow) {
36743
+ set.status = decision.status ?? 401;
36744
+ return new Response(JSON.stringify({ error: decision.reason, ok: false }), {
36745
+ headers: { "content-type": "application/json" },
36746
+ status: decision.status ?? 401
36747
+ });
36748
+ }
36749
+ });
36750
+ };
36751
+ // src/client/costDashboard.ts
36752
+ var padTwo = (value) => String(value).padStart(2, "0");
36753
+ var formatBucketKey = (epochMs, bucketBy) => {
36754
+ const date = new Date(epochMs);
36755
+ const y = date.getUTCFullYear();
36756
+ const m = padTwo(date.getUTCMonth() + 1);
36757
+ const d = padTwo(date.getUTCDate());
36758
+ const h = padTwo(date.getUTCHours());
36759
+ if (bucketBy === "month")
36760
+ return `${y}-${m}`;
36761
+ if (bucketBy === "day")
36762
+ return `${y}-${m}-${d}`;
36763
+ return `${y}-${m}-${d}T${h}`;
36764
+ };
36765
+ var isCostBreakdown = (value) => Boolean(value) && typeof value === "object" && typeof value.totalUsd === "number";
36766
+ var emptyBucket = (bucketKey2) => ({
36767
+ bucketKey: bucketKey2,
36768
+ callCount: 0,
36769
+ llmUsd: 0,
36770
+ sttUsd: 0,
36771
+ telephonyMinutes: 0,
36772
+ telephonyUsd: 0,
36773
+ totalUsd: 0,
36774
+ ttsUsd: 0
36775
+ });
36776
+ var accumulate = (bucket, payload) => {
36777
+ bucket.callCount += 1;
36778
+ bucket.llmUsd += payload.llm.usd;
36779
+ bucket.sttUsd += payload.stt.usd;
36780
+ bucket.ttsUsd += payload.tts.usd;
36781
+ bucket.telephonyUsd += payload.telephony.usd;
36782
+ bucket.telephonyMinutes += payload.telephony.minutes;
36783
+ bucket.totalUsd += payload.totalUsd;
36784
+ };
36785
+ var roundCurrency = (bucket) => {
36786
+ bucket.llmUsd = Math.round(bucket.llmUsd * 1e6) / 1e6;
36787
+ bucket.sttUsd = Math.round(bucket.sttUsd * 1e6) / 1e6;
36788
+ bucket.ttsUsd = Math.round(bucket.ttsUsd * 1e6) / 1e6;
36789
+ bucket.telephonyUsd = Math.round(bucket.telephonyUsd * 1e6) / 1e6;
36790
+ bucket.totalUsd = Math.round(bucket.totalUsd * 1e6) / 1e6;
36791
+ };
36792
+ var buildVoiceCostDashboardReport = (options) => {
36793
+ const bucketBy = options.bucketBy ?? "day";
36794
+ const fromMs = options.fromMs ?? Number.NEGATIVE_INFINITY;
36795
+ const toMs = options.toMs ?? Number.POSITIVE_INFINITY;
36796
+ const buckets = new Map;
36797
+ const grandTotal = emptyBucket("total");
36798
+ let minMs = Number.POSITIVE_INFINITY;
36799
+ let maxMs = Number.NEGATIVE_INFINITY;
36800
+ for (const event of options.events) {
36801
+ if (event.type !== "cost.ready")
36802
+ continue;
36803
+ if (event.at < fromMs || event.at > toMs)
36804
+ continue;
36805
+ if (!isCostBreakdown(event.payload))
36806
+ continue;
36807
+ minMs = Math.min(minMs, event.at);
36808
+ maxMs = Math.max(maxMs, event.at);
36809
+ const bucketKey2 = formatBucketKey(event.at, bucketBy);
36810
+ let bucket = buckets.get(bucketKey2);
36811
+ if (!bucket) {
36812
+ bucket = emptyBucket(bucketKey2);
36813
+ buckets.set(bucketKey2, bucket);
36814
+ }
36815
+ accumulate(bucket, event.payload);
36816
+ accumulate(grandTotal, event.payload);
36817
+ }
36818
+ for (const bucket of buckets.values()) {
36819
+ roundCurrency(bucket);
36820
+ }
36821
+ roundCurrency(grandTotal);
36822
+ return {
36823
+ buckets: Array.from(buckets.values()).sort((a, b) => a.bucketKey.localeCompare(b.bucketKey)),
36824
+ generatedAt: Date.now(),
36825
+ grandTotal,
36826
+ windowEndMs: Number.isFinite(maxMs) ? maxMs : 0,
36827
+ windowStartMs: Number.isFinite(minMs) ? minMs : 0
36828
+ };
36829
+ };
36830
+ // src/client/liveCallViewer.ts
36831
+ var EVENT_BUFFER_LIMIT = 200;
36832
+ var createLiveCallViewer = (options) => {
36833
+ const bufferLimit = options.bufferLimit ?? EVENT_BUFFER_LIMIT;
36834
+ const subscribers = new Set;
36835
+ let state = {
36836
+ agentState: "idle",
36837
+ callDurationMs: 0,
36838
+ events: [],
36839
+ isConnected: true,
36840
+ isLiveListening: true,
36841
+ partialTranscript: "",
36842
+ sessionId: options.sessionId
36843
+ };
36844
+ const startedAt = options.startedAt ?? Date.now();
36845
+ const notify = () => {
36846
+ for (const subscriber of subscribers)
36847
+ subscriber();
36848
+ };
36849
+ const update = (next) => {
36850
+ state = { ...state, ...next };
36851
+ state.callDurationMs = Math.max(0, Date.now() - startedAt);
36852
+ state.agentState = deriveVoiceAgentUIState({
36853
+ hasActivePartial: state.partialTranscript.length > 0,
36854
+ isConnected: state.isConnected,
36855
+ isPlaying: false,
36856
+ isRecording: state.isLiveListening,
36857
+ lastAssistantAt: state.lastAssistantAt,
36858
+ lastTranscriptAt: state.lastTranscriptAt
36859
+ });
36860
+ notify();
36861
+ };
36862
+ const pushEvent = (event) => {
36863
+ const next = state.events.concat(event);
36864
+ if (next.length > bufferLimit) {
36865
+ next.splice(0, next.length - bufferLimit);
36866
+ }
36867
+ update({ events: next });
36868
+ };
36869
+ return {
36870
+ applyControl: (control) => {
36871
+ pushEvent({
36872
+ at: Date.now(),
36873
+ detail: control.reason,
36874
+ kind: "lifecycle",
36875
+ title: `control:${control.type}`
36876
+ });
36877
+ },
36878
+ applyEvent: pushEvent,
36879
+ applyMonitorEvent: ({ payload, type }) => {
36880
+ pushEvent({
36881
+ at: Date.now(),
36882
+ detail: JSON.stringify(payload).slice(0, 240),
36883
+ kind: type === "call.lifecycle" ? "lifecycle" : "lifecycle",
36884
+ title: type
36885
+ });
36886
+ },
36887
+ getState: () => state,
36888
+ noteAgentAudio: (at) => {
36889
+ const ts = at ?? Date.now();
36890
+ update({ lastAssistantAt: ts });
36891
+ pushEvent({
36892
+ at: ts,
36893
+ kind: "agent_audio",
36894
+ title: "Agent audio frame"
36895
+ });
36896
+ },
36897
+ notePartial: (text, at) => {
36898
+ update({ partialTranscript: text });
36899
+ if (text) {
36900
+ pushEvent({
36901
+ at: at ?? Date.now(),
36902
+ detail: text,
36903
+ kind: "transcript",
36904
+ title: "Partial"
36905
+ });
36906
+ }
36907
+ },
36908
+ noteTranscript: (text, at) => {
36909
+ const ts = at ?? Date.now();
36910
+ update({ lastTranscriptAt: ts, partialTranscript: "" });
36911
+ pushEvent({
36912
+ at: ts,
36913
+ detail: text,
36914
+ kind: "transcript",
36915
+ title: "Final transcript"
36916
+ });
36917
+ },
36918
+ reset: (sessionId, startedAtOverride) => {
36919
+ state = {
36920
+ agentState: "idle",
36921
+ callDurationMs: 0,
36922
+ events: [],
36923
+ isConnected: true,
36924
+ isLiveListening: true,
36925
+ partialTranscript: "",
36926
+ sessionId
36927
+ };
36928
+ if (typeof startedAtOverride === "number") {}
36929
+ notify();
36930
+ },
36931
+ subscribe: (subscriber) => {
36932
+ subscribers.add(subscriber);
36933
+ return () => subscribers.delete(subscriber);
36934
+ }
36935
+ };
36936
+ };
36937
+ // src/client/replayTimeline.ts
36938
+ var categorize = (entry) => {
36939
+ const event = entry.event.toLowerCase();
36940
+ if (event.startsWith("stt.") || event.includes("user"))
36941
+ return "user";
36942
+ if (event.startsWith("tts.") || event.includes("assistant") || event.includes("agent"))
36943
+ return "agent";
36944
+ if (event.startsWith("tool.") || event.includes("tool"))
36945
+ return "tool";
36946
+ return "lifecycle";
36947
+ };
36948
+ var buildReplayTimelineReport = (input) => {
36949
+ const events = [];
36950
+ let summaryAgentTurns = 0;
36951
+ let summaryUserTurns = 0;
36952
+ let summaryToolCalls = 0;
36953
+ for (const entry of input.artifact.timeline ?? []) {
36954
+ const category = categorize(entry);
36955
+ if (category === "user")
36956
+ summaryUserTurns += 1;
36957
+ if (category === "agent")
36958
+ summaryAgentTurns += 1;
36959
+ if (category === "tool")
36960
+ summaryToolCalls += 1;
36961
+ events.push({
36962
+ at: entry.atMs,
36963
+ category,
36964
+ detail: entry.text ?? entry.reason,
36965
+ durationMs: entry.chunkDurationMs,
36966
+ label: entry.event
36967
+ });
36968
+ }
36969
+ events.sort((a, b) => a.at - b.at);
36970
+ const first = events[0]?.at ?? 0;
36971
+ const last = events.at(-1)?.at ?? first;
36972
+ return {
36973
+ duration: last - first,
36974
+ events,
36975
+ metadata: {
36976
+ artifactId: input.artifact.id ?? "",
36977
+ title: input.artifact.title
36978
+ },
36979
+ startedAt: first,
36980
+ summary: {
36981
+ agentTurns: summaryAgentTurns,
36982
+ toolCalls: summaryToolCalls,
36983
+ userTurns: summaryUserTurns
36984
+ }
36985
+ };
36986
+ };
36987
+ // src/retention.ts
36988
+ var defaultResolveAt = (event) => {
36989
+ if (!event || typeof event !== "object")
36990
+ return;
36991
+ const value = event.at;
36992
+ return typeof value === "number" ? value : undefined;
36993
+ };
36994
+ var purgeVoiceRetentionStore = async (store, options, now = Date.now()) => {
36995
+ const resolveAt = options.resolveAt ?? defaultResolveAt;
36996
+ const cutoff = now - Math.max(0, options.maxAgeMs);
36997
+ const records = await Promise.resolve(store.list());
36998
+ const purgedIds = [];
36999
+ let attempted = 0;
37000
+ let removed = 0;
37001
+ let failed = 0;
37002
+ for (const record of records) {
37003
+ const at = resolveAt(record);
37004
+ if (typeof at !== "number" || at >= cutoff)
37005
+ continue;
37006
+ attempted += 1;
37007
+ try {
37008
+ await Promise.resolve(store.remove(record.id));
37009
+ purgedIds.push(record.id);
37010
+ removed += 1;
37011
+ } catch {
37012
+ failed += 1;
37013
+ }
37014
+ }
37015
+ return { attempted, failed, purgedIds, reason: "expired", removed };
37016
+ };
37017
+ var createVoiceRetentionScheduler = (options) => {
37018
+ const intervalMs = Math.max(60000, options.intervalMs ?? 6 * 60 * 60000);
37019
+ let timer;
37020
+ const run = async () => {
37021
+ const report = await purgeVoiceRetentionStore(options.store, options.policy);
37022
+ options.onReport?.(report);
37023
+ };
37024
+ return {
37025
+ start: () => {
37026
+ if (timer)
37027
+ return;
37028
+ timer = setInterval(() => {
37029
+ run();
37030
+ }, intervalMs);
37031
+ },
37032
+ stop: () => {
37033
+ if (!timer)
37034
+ return;
37035
+ clearInterval(timer);
37036
+ timer = undefined;
37037
+ }
37038
+ };
37039
+ };
36484
37040
  // src/vapiAdapter.ts
36485
37041
  var VAPI_BUILT_IN_VARIABLES = {
36486
37042
  date: () => new Date().toISOString().slice(0, 10),
@@ -37064,7 +37620,7 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
37064
37620
  return report;
37065
37621
  };
37066
37622
  // src/turnLatency.ts
37067
- import { Elysia as Elysia53 } from "elysia";
37623
+ import { Elysia as Elysia54 } from "elysia";
37068
37624
  var DEFAULT_WARN_AFTER_MS2 = 1800;
37069
37625
  var DEFAULT_FAIL_AFTER_MS2 = 3200;
37070
37626
  var escapeHtml50 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
@@ -37224,7 +37780,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
37224
37780
  var createVoiceTurnLatencyRoutes = (options) => {
37225
37781
  const path = options.path ?? "/api/turn-latency";
37226
37782
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
37227
- const routes = new Elysia53({
37783
+ const routes = new Elysia54({
37228
37784
  name: options.name ?? "absolutejs-voice-turn-latency"
37229
37785
  }).get(path, createVoiceTurnLatencyJSONHandler(options));
37230
37786
  if (htmlPath) {
@@ -37233,7 +37789,7 @@ var createVoiceTurnLatencyRoutes = (options) => {
37233
37789
  return routes;
37234
37790
  };
37235
37791
  // src/liveLatency.ts
37236
- import { Elysia as Elysia54 } from "elysia";
37792
+ import { Elysia as Elysia55 } from "elysia";
37237
37793
  var escapeHtml51 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37238
37794
  var percentile6 = (values, percentileValue) => {
37239
37795
  if (values.length === 0) {
@@ -37307,7 +37863,7 @@ await traceStore.append({
37307
37863
  var createVoiceLiveLatencyRoutes = (options) => {
37308
37864
  const path = options.path ?? "/api/live-latency";
37309
37865
  const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
37310
- const routes = new Elysia54({
37866
+ const routes = new Elysia55({
37311
37867
  name: options.name ?? "absolutejs-voice-live-latency"
37312
37868
  }).get(path, () => summarizeVoiceLiveLatency(options));
37313
37869
  if (htmlPath) {
@@ -37324,7 +37880,7 @@ var createVoiceLiveLatencyRoutes = (options) => {
37324
37880
  return routes;
37325
37881
  };
37326
37882
  // src/turnQuality.ts
37327
- import { Elysia as Elysia55 } from "elysia";
37883
+ import { Elysia as Elysia56 } from "elysia";
37328
37884
  var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
37329
37885
  var escapeHtml52 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37330
37886
  var getTurnLatencyMs = (turn) => {
@@ -37430,7 +37986,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
37430
37986
  var createVoiceTurnQualityRoutes = (options) => {
37431
37987
  const path = options.path ?? "/api/turn-quality";
37432
37988
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
37433
- const routes = new Elysia55({
37989
+ const routes = new Elysia56({
37434
37990
  name: options.name ?? "absolutejs-voice-turn-quality"
37435
37991
  }).get(path, createVoiceTurnQualityJSONHandler(options));
37436
37992
  if (htmlPath) {
@@ -37439,10 +37995,10 @@ var createVoiceTurnQualityRoutes = (options) => {
37439
37995
  return routes;
37440
37996
  };
37441
37997
  // src/phoneAgent.ts
37442
- import { Elysia as Elysia57 } from "elysia";
37998
+ import { Elysia as Elysia58 } from "elysia";
37443
37999
 
37444
38000
  // src/phoneAgentProductionSmoke.ts
37445
- import { Elysia as Elysia56 } from "elysia";
38001
+ import { Elysia as Elysia57 } from "elysia";
37446
38002
  var defaultRequirements = [
37447
38003
  "media-started",
37448
38004
  "transcript",
@@ -37585,7 +38141,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
37585
38141
  var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
37586
38142
  const path = options.path ?? "/api/voice/phone/smoke-contract";
37587
38143
  const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
37588
- const routes = new Elysia56({
38144
+ const routes = new Elysia57({
37589
38145
  name: options.name ?? "absolutejs-voice-phone-smoke-contract"
37590
38146
  }).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
37591
38147
  if (htmlPath) {
@@ -37916,7 +38472,7 @@ var createVoicePhoneAgent = (options) => {
37916
38472
  setupPath: resolveSetupPath(carrier),
37917
38473
  smokePath: resolveSmokePath(carrier)
37918
38474
  }));
37919
- const app = new Elysia57({
38475
+ const app = new Elysia58({
37920
38476
  name: options.name ?? "absolutejs-voice-phone-agent"
37921
38477
  });
37922
38478
  for (const carrier of options.carriers) {
@@ -39725,7 +40281,7 @@ var createOpenAIVoiceTTS = (options) => {
39725
40281
  };
39726
40282
  };
39727
40283
  // src/providerCapabilities.ts
39728
- import { Elysia as Elysia58 } from "elysia";
40284
+ import { Elysia as Elysia59 } from "elysia";
39729
40285
  var escapeHtml55 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39730
40286
  var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
39731
40287
  configured: true,
@@ -39828,7 +40384,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
39828
40384
  var createVoiceProviderCapabilityRoutes = (options) => {
39829
40385
  const path = options.path ?? "/api/provider-capabilities";
39830
40386
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
39831
- const routes = new Elysia58({
40387
+ const routes = new Elysia59({
39832
40388
  name: options.name ?? "absolutejs-voice-provider-capabilities"
39833
40389
  }).get(path, createVoiceProviderCapabilityJSONHandler(options));
39834
40390
  if (htmlPath) {
@@ -39837,7 +40393,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
39837
40393
  return routes;
39838
40394
  };
39839
40395
  // src/providerOrchestration.ts
39840
- import { Elysia as Elysia59 } from "elysia";
40396
+ import { Elysia as Elysia60 } from "elysia";
39841
40397
  var defaultRequirement = {
39842
40398
  minProviders: 1,
39843
40399
  requireBudgetPolicy: false,
@@ -40013,7 +40569,7 @@ var createVoiceProviderOrchestrationRoutes = (options) => {
40013
40569
  const path = options.path ?? "/api/voice/provider-orchestration";
40014
40570
  const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
40015
40571
  const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
40016
- const routes = new Elysia59({
40572
+ const routes = new Elysia60({
40017
40573
  name: options.name ?? "absolutejs-voice-provider-orchestration"
40018
40574
  }).get(path, () => buildVoiceProviderOrchestrationReport(options));
40019
40575
  if (htmlPath) {
@@ -40186,7 +40742,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
40186
40742
  return report;
40187
40743
  };
40188
40744
  // src/voiceMonitoring.ts
40189
- import { Elysia as Elysia60 } from "elysia";
40745
+ import { Elysia as Elysia61 } from "elysia";
40190
40746
  var escapeHtml57 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
40191
40747
  var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
40192
40748
  var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
@@ -40471,7 +41027,7 @@ var createVoiceMonitorRoutes = (options) => {
40471
41027
  monitors: options.monitors,
40472
41028
  now: options.now
40473
41029
  });
40474
- const routes = new Elysia60({
41030
+ const routes = new Elysia61({
40475
41031
  name: options.name ?? "absolutejs-voice-monitoring"
40476
41032
  }).get(path, report).get(`${path}.md`, async () => {
40477
41033
  return new Response(renderVoiceMonitorMarkdown(await report()), {
@@ -40518,7 +41074,7 @@ var createVoiceMonitorRoutes = (options) => {
40518
41074
  };
40519
41075
  var createVoiceMonitorRunnerRoutes = (options) => {
40520
41076
  const path = options.path ?? "/api/voice/monitor-runner";
40521
- return new Elysia60({
41077
+ return new Elysia61({
40522
41078
  name: options.name ?? "absolutejs-voice-monitor-runner"
40523
41079
  }).get(path, () => ({
40524
41080
  isRunning: options.runner.isRunning()
@@ -40906,7 +41462,7 @@ var recommendVoiceReadinessProfile = (options) => {
40906
41462
  };
40907
41463
  };
40908
41464
  // src/providerStackRecommendations.ts
40909
- import { Elysia as Elysia61 } from "elysia";
41465
+ import { Elysia as Elysia62 } from "elysia";
40910
41466
  var escapeHtml58 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
40911
41467
  var profileProviderPriorities = {
40912
41468
  "meeting-recorder": {
@@ -41268,7 +41824,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
41268
41824
  var createVoiceProviderContractMatrixRoutes = (options) => {
41269
41825
  const path = options.path ?? "/api/provider-contracts";
41270
41826
  const htmlPath = options.htmlPath ?? "/provider-contracts";
41271
- const routes = new Elysia61({
41827
+ const routes = new Elysia62({
41272
41828
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
41273
41829
  });
41274
41830
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -41386,7 +41942,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
41386
41942
  return assertion;
41387
41943
  };
41388
41944
  // src/opsConsoleRoutes.ts
41389
- import { Elysia as Elysia62 } from "elysia";
41945
+ import { Elysia as Elysia63 } from "elysia";
41390
41946
  var DEFAULT_LINKS = [
41391
41947
  {
41392
41948
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -41503,7 +42059,7 @@ var renderVoiceOpsConsoleHTML = (report, options = {}) => {
41503
42059
  };
41504
42060
  var createVoiceOpsConsoleRoutes = (options) => {
41505
42061
  const path = options.path ?? "/ops-console";
41506
- const routes = new Elysia62({
42062
+ const routes = new Elysia63({
41507
42063
  name: options.name ?? "absolutejs-voice-ops-console"
41508
42064
  });
41509
42065
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -41520,7 +42076,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
41520
42076
  return routes;
41521
42077
  };
41522
42078
  // src/incidentBundle.ts
41523
- import { Elysia as Elysia63 } from "elysia";
42079
+ import { Elysia as Elysia64 } from "elysia";
41524
42080
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
41525
42081
  if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
41526
42082
  return false;
@@ -41737,7 +42293,7 @@ var buildVoiceIncidentBundle = async (options) => {
41737
42293
  var createVoiceIncidentBundleRoutes = (options) => {
41738
42294
  const path = options.path ?? "/api/voice-incidents/:sessionId";
41739
42295
  const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
41740
- const routes = new Elysia63({
42296
+ const routes = new Elysia64({
41741
42297
  name: options.name ?? "absolutejs-voice-incident-bundle"
41742
42298
  });
41743
42299
  const getSessionId = (params) => params.sessionId ?? "";
@@ -41938,7 +42494,7 @@ var summarizeVoiceOpsStatus = async (options) => {
41938
42494
  };
41939
42495
  };
41940
42496
  // src/opsStatusRoutes.ts
41941
- import { Elysia as Elysia64 } from "elysia";
42497
+ import { Elysia as Elysia65 } from "elysia";
41942
42498
  var escapeHtml60 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
41943
42499
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
41944
42500
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
@@ -41950,7 +42506,7 @@ var renderVoiceOpsStatusHTML = (report, options = {}) => {
41950
42506
  };
41951
42507
  var createVoiceOpsStatusRoutes = (options) => {
41952
42508
  const path = options.path ?? "/api/voice/ops-status";
41953
- const routes = new Elysia64({
42509
+ const routes = new Elysia65({
41954
42510
  name: options.name ?? "absolutejs-voice-ops-status"
41955
42511
  });
41956
42512
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -42383,7 +42939,7 @@ var createVoiceTTSProviderRouter = (options) => {
42383
42939
  };
42384
42940
  };
42385
42941
  // src/traceDeliveryRoutes.ts
42386
- import { Elysia as Elysia65 } from "elysia";
42942
+ import { Elysia as Elysia66 } from "elysia";
42387
42943
  var escapeHtml61 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
42388
42944
  var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
42389
42945
  var getNumber12 = (value) => {
@@ -42492,7 +43048,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
42492
43048
  const path = options.path ?? "/api/voice-trace-deliveries";
42493
43049
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
42494
43050
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
42495
- const routes = new Elysia65({
43051
+ const routes = new Elysia66({
42496
43052
  name: options.name ?? "absolutejs-voice-trace-deliveries"
42497
43053
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
42498
43054
  if (htmlPath !== false) {
@@ -42645,7 +43201,7 @@ var createVoiceMemoryStore = () => {
42645
43201
  return { get, getOrCreate, list, remove, set };
42646
43202
  };
42647
43203
  // src/opsWebhook.ts
42648
- import { Elysia as Elysia66 } from "elysia";
43204
+ import { Elysia as Elysia67 } from "elysia";
42649
43205
  var toHex7 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
42650
43206
  var signVoiceOpsWebhookBody = async (input) => {
42651
43207
  const encoder2 = new TextEncoder;
@@ -42775,7 +43331,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
42775
43331
  };
42776
43332
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
42777
43333
  const path = options.path ?? "/api/voice-ops/webhook";
42778
- return new Elysia66().post(path, async ({ body, request, set }) => {
43334
+ return new Elysia67().post(path, async ({ body, request, set }) => {
42779
43335
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
42780
43336
  if (options.signingSecret) {
42781
43337
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -43230,7 +43786,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
43230
43786
  };
43231
43787
  };
43232
43788
  // src/postCallAnalysis.ts
43233
- import { Elysia as Elysia67 } from "elysia";
43789
+ import { Elysia as Elysia68 } from "elysia";
43234
43790
  var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
43235
43791
  var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
43236
43792
  var getPathValue3 = (source, path) => {
@@ -43409,7 +43965,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
43409
43965
  };
43410
43966
  var createVoicePostCallAnalysisRoutes = (options = {}) => {
43411
43967
  const path = options.path ?? "/api/voice/post-call-analysis";
43412
- const routes = new Elysia67({
43968
+ const routes = new Elysia68({
43413
43969
  name: options.name ?? "absolutejs-voice-post-call-analysis"
43414
43970
  });
43415
43971
  routes.get(path, async ({ query }) => {
@@ -43434,7 +43990,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
43434
43990
  return routes;
43435
43991
  };
43436
43992
  // src/guardrails.ts
43437
- import { Elysia as Elysia68 } from "elysia";
43993
+ import { Elysia as Elysia69 } from "elysia";
43438
43994
  var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
43439
43995
  var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
43440
43996
  var matchesRule = async (rule, input) => {
@@ -43736,7 +44292,7 @@ var resolveGuardrailReport = async (options, input) => {
43736
44292
  };
43737
44293
  var createVoiceGuardrailRoutes = (options = {}) => {
43738
44294
  const path = options.path ?? "/api/voice/guardrails";
43739
- const routes = new Elysia68({
44295
+ const routes = new Elysia69({
43740
44296
  name: options.name ?? "absolutejs-voice-guardrails"
43741
44297
  });
43742
44298
  routes.all(path, async ({ request }) => {
@@ -44515,7 +45071,7 @@ var shapeTelephonyAssistantText = (text, options = {}) => {
44515
45071
  return ensureTerminalPunctuation(normalizeWhitespace(limitedChars));
44516
45072
  };
44517
45073
  // src/proofPack.ts
44518
- import { Elysia as Elysia69 } from "elysia";
45074
+ import { Elysia as Elysia70 } from "elysia";
44519
45075
  import { mkdir as mkdir5 } from "fs/promises";
44520
45076
  import { dirname as dirname3, join as join4 } from "path";
44521
45077
  var toGeneratedAt = (value) => value === undefined ? new Date().toISOString() : typeof value === "number" ? new Date(value).toISOString() : value;
@@ -45101,7 +45657,7 @@ var createVoiceProofPackArtifacts = (input) => [
45101
45657
  var createVoiceProofPackRoutes = (options) => {
45102
45658
  const jsonPath = options.jsonPath ?? "/api/voice/proof-pack";
45103
45659
  const markdownPath = options.markdownPath ?? "/voice/proof-pack.md";
45104
- const app = new Elysia69({ name: options.name ?? "voice-proof-pack" });
45660
+ const app = new Elysia70({ name: options.name ?? "voice-proof-pack" });
45105
45661
  if (jsonPath !== false) {
45106
45662
  app.get(jsonPath, async () => new Response(JSON.stringify(await resolveProofPack(options.source), null, 2), {
45107
45663
  headers: {
@@ -46202,7 +46758,7 @@ var buildVoiceMultilingualProofReadinessCheck = (report, options = {}) => {
46202
46758
  };
46203
46759
  };
46204
46760
  // src/monitor.ts
46205
- import { Elysia as Elysia70 } from "elysia";
46761
+ import { Elysia as Elysia71 } from "elysia";
46206
46762
  var buildAudioFanout = () => {
46207
46763
  const handlers = new Set;
46208
46764
  return {
@@ -46491,7 +47047,7 @@ var createVoiceLiveMonitorRoutes = (options) => {
46491
47047
  transfer: options.controlHandlers?.transfer ?? buildDefaultControlHandler("transfer"),
46492
47048
  voicemail: options.controlHandlers?.voicemail ?? buildDefaultControlHandler("voicemail")
46493
47049
  };
46494
- const app = new Elysia70({ name: "absolutejs-voice-monitor" });
47050
+ const app = new Elysia71({ name: "absolutejs-voice-monitor" });
46495
47051
  const unsubscribers = new WeakMap;
46496
47052
  if (listenPath !== false && listenPath.length > 0) {
46497
47053
  app.ws(`/${listenPath.replace(/^\/+/, "")}`, {
@@ -46889,6 +47445,7 @@ export {
46889
47445
  recommendVoiceProviderStack,
46890
47446
  recommendVoiceProfileSwitch,
46891
47447
  readVoiceProofTrendReportFile,
47448
+ purgeVoiceRetentionStore,
46892
47449
  pruneVoiceTraceEvents,
46893
47450
  pruneVoiceIncidentBundleArtifacts,
46894
47451
  parseVoiceTelephonyWebhookEvent,
@@ -46969,6 +47526,7 @@ export {
46969
47526
  describeVoiceIVRPlan,
46970
47527
  describeVoiceAssistantMode,
46971
47528
  describeVoiceAgentUIState,
47529
+ deriveVoiceRecordingRedactionRanges,
46972
47530
  deriveVoiceAgentUIState,
46973
47531
  deliverVoiceTraceEventsToSinks,
46974
47532
  deliverVoiceObservabilityExport,
@@ -46978,6 +47536,7 @@ export {
46978
47536
  deliverVoiceHandoffDelivery,
46979
47537
  deliverVoiceHandoff,
46980
47538
  deliverVoiceAuditEventsToSinks,
47539
+ defineVoiceAssistant,
46981
47540
  decodeTwilioMulawBase64,
46982
47541
  deadLetterVoiceOpsTask,
46983
47542
  createVoiceZeroRetentionPolicy,
@@ -47077,7 +47636,9 @@ export {
47077
47636
  createVoiceS3RecordingStore,
47078
47637
  createVoiceS3DeliverySink,
47079
47638
  createVoiceRoutingDecisionSummary,
47639
+ createVoiceRouteAuth,
47080
47640
  createVoiceReviewSavedEvent,
47641
+ createVoiceRetentionScheduler,
47081
47642
  createVoiceResilienceRoutes,
47082
47643
  createVoiceRedisTelnyxWebhookEventStore,
47083
47644
  createVoiceRedisTelephonyWebhookIdempotencyStore,
@@ -47226,6 +47787,7 @@ export {
47226
47787
  createVoiceHandoffDeliveryWorkerLoop,
47227
47788
  createVoiceHandoffDeliveryWorker,
47228
47789
  createVoiceHandoffDeliveryRecord,
47790
+ createVoiceHMACAuthVerifier,
47229
47791
  createVoiceGuardrailRuntime,
47230
47792
  createVoiceGuardrailRoutes,
47231
47793
  createVoiceGuardrailPolicy,
@@ -47280,6 +47842,7 @@ export {
47280
47842
  createVoiceCRMActivitySink,
47281
47843
  createVoiceBrowserMediaRoutes,
47282
47844
  createVoiceBrowserCallProfileRoutes,
47845
+ createVoiceBearerAuthVerifier,
47283
47846
  createVoiceBargeInRoutes,
47284
47847
  createVoiceBackchannelDriver,
47285
47848
  createVoiceAuditTrailRoutes,
@@ -47330,7 +47893,9 @@ export {
47330
47893
  createMemoryVoiceTelnyxWebhookEventStore,
47331
47894
  createMemoryVoiceTelephonyWebhookIdempotencyStore,
47332
47895
  createMemoryVoicePlivoWebhookNonceStore,
47896
+ createLiveCallViewer,
47333
47897
  createJSONVoiceAssistantModel,
47898
+ createInMemoryVoiceCallQuota,
47334
47899
  createInMemoryDNCList,
47335
47900
  createId,
47336
47901
  createGeminiVoiceAssistantModel,
@@ -47424,6 +47989,7 @@ export {
47424
47989
  buildVoiceDeliveryRuntimeReport,
47425
47990
  buildVoiceDataRetentionPlan,
47426
47991
  buildVoiceDataControlReport,
47992
+ buildVoiceCostDashboardReport,
47427
47993
  buildVoiceCompetitiveCoverageReport,
47428
47994
  buildVoiceCampaignObservabilityReport,
47429
47995
  buildVoiceCallerMemoryNamespace,
@@ -47432,6 +47998,7 @@ export {
47432
47998
  buildVoiceAuditTrailReport,
47433
47999
  buildVoiceAuditExport,
47434
48000
  buildVoiceAuditDeliveryReport,
48001
+ buildReplayTimelineReport,
47435
48002
  buildOTELTraceId,
47436
48003
  buildOTELSpanId,
47437
48004
  buildEmptyVoiceProofTrendReport,
@@ -0,0 +1,18 @@
1
+ import type { Transcript } from "./types";
2
+ import { type VoiceRedactionPattern } from "./redaction";
3
+ export type VoiceRecordingRedactionRange = {
4
+ endMs: number;
5
+ label?: string;
6
+ startMs: number;
7
+ };
8
+ export type DeriveVoiceRecordingRedactionRangesInput = {
9
+ /** When the recording starts in epoch ms; used to convert absolute timestamps if transcripts use them. */
10
+ recordingStartedAtEpochMs?: number;
11
+ /** Optional padding around redaction ranges, in ms (default 100). */
12
+ paddingMs?: number;
13
+ /** Patterns to test against transcripts. Defaults to DEFAULT_VOICE_REDACTION_PATTERNS. */
14
+ patterns?: ReadonlyArray<VoiceRedactionPattern>;
15
+ /** Transcripts to scan. */
16
+ transcripts: ReadonlyArray<Transcript>;
17
+ };
18
+ export declare const deriveVoiceRecordingRedactionRanges: (input: DeriveVoiceRecordingRedactionRangesInput) => VoiceRecordingRedactionRange[];
@@ -0,0 +1,37 @@
1
+ export type VoiceRetentionPolicyOptions = {
2
+ /** Maximum age in milliseconds; events older than this are eligible for purge. */
3
+ maxAgeMs: number;
4
+ /** Optional override that returns the timestamp for an event. Defaults to event.at. */
5
+ resolveAt?: (event: unknown) => number | undefined;
6
+ };
7
+ export type VoiceRetentionStore<TRecord extends {
8
+ id: string;
9
+ }> = {
10
+ list: (filter?: Record<string, unknown>) => Promise<TRecord[]> | TRecord[];
11
+ remove: (id: string) => Promise<void> | void;
12
+ };
13
+ export type VoicePurgeReport = {
14
+ attempted: number;
15
+ failed: number;
16
+ purgedIds: string[];
17
+ reason: "expired" | "manual";
18
+ removed: number;
19
+ };
20
+ export declare const purgeVoiceRetentionStore: <TRecord extends {
21
+ id: string;
22
+ }>(store: VoiceRetentionStore<TRecord>, options: VoiceRetentionPolicyOptions, now?: number) => Promise<VoicePurgeReport>;
23
+ export type VoiceRetentionScheduler = {
24
+ start: () => void;
25
+ stop: () => void;
26
+ };
27
+ export type CreateVoiceRetentionSchedulerOptions<TRecord extends {
28
+ id: string;
29
+ }> = {
30
+ intervalMs?: number;
31
+ onReport?: (report: VoicePurgeReport) => void;
32
+ policy: VoiceRetentionPolicyOptions;
33
+ store: VoiceRetentionStore<TRecord>;
34
+ };
35
+ export declare const createVoiceRetentionScheduler: <TRecord extends {
36
+ id: string;
37
+ }>(options: CreateVoiceRetentionSchedulerOptions<TRecord>) => VoiceRetentionScheduler;
@@ -0,0 +1,58 @@
1
+ import { Elysia } from "elysia";
2
+ export type VoiceRouteAuthDecision = {
3
+ allow: true;
4
+ } | {
5
+ allow: false;
6
+ reason: string;
7
+ status?: number;
8
+ };
9
+ export type VoiceRouteAuthInput = {
10
+ body?: string;
11
+ headers: Headers;
12
+ method: string;
13
+ url: string;
14
+ };
15
+ export type VoiceRouteAuthVerifier = (input: VoiceRouteAuthInput) => Promise<VoiceRouteAuthDecision> | VoiceRouteAuthDecision;
16
+ export type VoiceRouteAuthOptions = {
17
+ bypassPaths?: ReadonlyArray<string>;
18
+ name?: string;
19
+ verify: VoiceRouteAuthVerifier;
20
+ };
21
+ export declare const createVoiceBearerAuthVerifier: (input: {
22
+ expectedToken: string;
23
+ headerName?: string;
24
+ }) => VoiceRouteAuthVerifier;
25
+ export declare const createVoiceHMACAuthVerifier: (input: {
26
+ secret: string;
27
+ toleranceMs?: number;
28
+ }) => VoiceRouteAuthVerifier;
29
+ export declare const createVoiceRouteAuth: (options: VoiceRouteAuthOptions) => Elysia<"", {
30
+ decorator: {};
31
+ store: {};
32
+ derive: {};
33
+ resolve: {};
34
+ }, {
35
+ typebox: {};
36
+ error: {};
37
+ }, {
38
+ schema: {};
39
+ standaloneSchema: {};
40
+ macro: {};
41
+ macroFn: {};
42
+ parser: {};
43
+ response: {};
44
+ }, {}, {
45
+ derive: {};
46
+ resolve: {};
47
+ schema: {};
48
+ standaloneSchema: {};
49
+ response: {};
50
+ }, {
51
+ derive: {};
52
+ resolve: {};
53
+ schema: {};
54
+ standaloneSchema: {};
55
+ response: {
56
+ 200: Response;
57
+ };
58
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.497",
3
+ "version": "0.0.22-beta.498",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",