voice-runtime 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -50,14 +50,8 @@ declare function counterIdGenerator<TId extends string = string>(prefix: string)
50
50
  declare function createDefaultIdGenerator(): IdGenerator;
51
51
 
52
52
  type ErrorCategory = "validation" | "auth" | "provider" | "network" | "timeout" | "rate_limit" | "cancelled" | "interrupted" | "tool" | "media" | "internal";
53
- /**
54
- * Canonical error names used on `NormalizedError.name` and by `tvicErrorFromJSON`
55
- * to identify errors after JSON round-trips (the `Symbol.for('tvic.error')`
56
- * marker on `TvicThrowableError` is lost in JSON).
57
- *
58
- * Frozen at module load so third parties cannot mutate the registry at
59
- * runtime.
60
- */
53
+ declare const MAX_ERROR_CODE_UTF8_BYTES = 128;
54
+ declare function isValidErrorCode(code: unknown): code is string;
61
55
  declare const TVIC_ERROR_NAMES: Readonly<{
62
56
  readonly AuthError: "AuthError";
63
57
  readonly RateLimitError: "RateLimitError";
@@ -76,11 +70,6 @@ declare const TVIC_ERROR_NAMES: Readonly<{
76
70
  }>;
77
71
  type TvicErrorName = (typeof TVIC_ERROR_NAMES)[keyof typeof TVIC_ERROR_NAMES];
78
72
  declare function isTvicErrorName(value: unknown): value is TvicErrorName;
79
- /**
80
- * The cross-realm marker for TVIC errors. Lives on the `TvicThrowableError`
81
- * class instance, not on `NormalizedError`, because `JSON.stringify` strips
82
- * symbol-keyed properties. Use `tvicErrorFromJSON()` to re-hydrate.
83
- */
84
73
  declare const TVIC_ERROR_MARKER: unique symbol;
85
74
  interface NormalizedError {
86
75
  readonly name: TvicErrorName;
@@ -101,20 +90,14 @@ interface ErrorFactoryOptions {
101
90
  }
102
91
  declare function isNormalizedError(value: unknown): value is NormalizedError;
103
92
  declare function unknownErrorMessage(error: unknown): string;
104
- /**
105
- * Recognizes the pre-v2 normalized shape that did not carry `name`, then
106
- * upgrades it to the canonical name for its category. This is deliberately
107
- * separate from `isNormalizedError`: new callers must still be able to tell
108
- * whether a value is already current, while compatibility boundaries can
109
- * preserve old provider/runtime errors instead of reclassifying them.
110
- */
111
- declare function normalizeLegacyError(value: unknown): NormalizedError | null;
112
- declare function normalizeUnknownError(error: unknown, options: {
93
+ type NormalizeUnknownErrorOptions = {
113
94
  readonly code: string;
114
95
  readonly category?: ErrorCategory;
115
96
  readonly provider?: string;
116
97
  readonly retriable?: boolean;
117
- }): NormalizedError;
98
+ };
99
+ declare function normalizeLegacyError(value: unknown): NormalizedError | null;
100
+ declare function normalizeUnknownError(error: unknown, options: NormalizeUnknownErrorOptions): NormalizedError;
118
101
  declare function normalizedError(code: string, message: string, options?: ErrorFactoryOptions): NormalizedError;
119
102
  declare function providerError(code: string, message: string, options?: Omit<ErrorFactoryOptions, "category">): NormalizedError;
120
103
  declare function mediaError(code: string, message?: string, options?: Omit<ErrorFactoryOptions, "category">): NormalizedError;
@@ -128,17 +111,6 @@ declare function signatureError(code: string, message: string, options?: Omit<Er
128
111
  declare function cancelledError(code: string, message: string, options?: Omit<ErrorFactoryOptions, "category" | "retriable">): NormalizedError;
129
112
  declare function interruptedError(code: string, message: string, options?: Omit<ErrorFactoryOptions, "category" | "retriable">): NormalizedError;
130
113
  declare function toolError(code: string, message: string, options?: Omit<ErrorFactoryOptions, "category">): NormalizedError;
131
- /**
132
- * A throwable Error that carries a `NormalizedError` and the cross-realm
133
- * `Symbol.for('tvic.error')` marker. Use `TvicThrowableError.from(value)`
134
- * to construct — it normalizes unknown values, preserves the original cause,
135
- * and reuses already-thrown `TvicThrowableError` instances.
136
- *
137
- * Note: the marker is lost in `JSON.stringify` because symbol-keyed
138
- * properties are dropped. Use `tvicErrorFromJSON()` to re-hydrate.
139
- * Error-like values from another realm in the same JavaScript agent are
140
- * recognized by their intrinsic Error tag, not only by `instanceof`.
141
- */
142
114
  declare class TvicThrowableError extends Error {
143
115
  readonly [TVIC_ERROR_MARKER]: true;
144
116
  readonly error: NormalizedError;
@@ -153,32 +125,9 @@ declare class TvicThrowableError extends Error {
153
125
  static from(value: unknown): TvicThrowableError;
154
126
  toJSON(): NormalizedError;
155
127
  }
156
- /**
157
- * Type guard that detects a `TvicThrowableError` instance *or* any object
158
- * that carries the cross-realm `Symbol.for('tvic.error')` marker. Works
159
- * across Web Workers, iframes, and `vm` contexts because `Symbol.for` is
160
- * the only symbol-sharing primitive within the same JavaScript agent. Separate
161
- * workers require JSON serialization or another explicit transport.
162
- *
163
- * The marker is an *identity tag*, not a security boundary: a hostile party
164
- * who can write into your realm can also fake the marker. The structural
165
- * companion to this guard is `isNormalizedError`, which checks the actual
166
- * `NormalizedError` field shape.
167
- *
168
- * Does NOT work across `JSON.parse` boundaries — use `tvicErrorFromJSON()`.
169
- */
128
+ declare function jsonSerializableNormalizedError(error: NormalizedError, transformString?: (value: string) => string): NormalizedError;
170
129
  declare function isTvicError(value: unknown): value is NormalizedError | TvicThrowableError;
171
- /**
172
- * Re-hydrate a `NormalizedError` after a `JSON.parse` round-trip. The
173
- * `Symbol.for('tvic.error')` marker is lost in JSON, so `isTvicError()`
174
- * returns `false` for parsed values. This factory validates the parsed
175
- * structural payload, including its canonical name/category pairing and
176
- * required field types.
177
- *
178
- * Returns `null` if the value cannot be re-hydrated to a valid
179
- * `NormalizedError` (unknown name, empty message, wrong field types).
180
- * Callers should always null-check the return value.
181
- */
130
+ declare function normalizedErrorFromTvicError(value: unknown): NormalizedError | null;
182
131
  declare function tvicErrorFromJSON(value: unknown): NormalizedError | null;
183
132
 
184
133
  type DurableErrorCode = "RECORD_NOT_FOUND" | "RECORD_CONFLICT" | "LEASE_UNAVAILABLE" | "LEASE_LOST" | "BACKEND_UNAVAILABLE" | "CORRUPT_RECORD" | "INVALID_ARGUMENT" | "MEMORY_BACKEND_UNAVAILABLE" | "MEMORY_ENTRY_TOO_LARGE" | "MEMORY_SESSION_QUOTA_EXCEEDED";
@@ -251,7 +200,7 @@ declare const TVIC_ERROR_CODES: Readonly<{
251
200
  readonly ttsTransportUnexpectedEof: "tts.transport.unexpected_eof";
252
201
  readonly llmProviderUnexpectedEof: "llm.provider.unexpected_eof";
253
202
  }>;
254
- /** One-release aliases accepted at provider and persisted-data boundaries. */
203
+ /** Legacy aliases accepted at provider and persisted-data boundaries. */
255
204
  declare const TVIC_ERROR_CODE_ALIASES: Readonly<{
256
205
  readonly "stt.provider.auth_failed": "provider.auth_failed";
257
206
  readonly "stt.provider.rate_limited": "provider.rate_limited";
@@ -343,11 +292,6 @@ declare const STT_ERROR_CODES: {
343
292
 
344
293
  type MediaDirection = "input" | "output" | "internal";
345
294
  type CallDirection = "inbound" | "outbound";
346
- /**
347
- * Channels TVIC 1.0 can actually execute. `sip` and `whatsapp` are intentionally
348
- * absent until a working transport exists — the union never claims a capability
349
- * the runtime cannot run.
350
- */
351
295
  type ChannelKind = "phone" | "web_audio" | "simulated";
352
296
 
353
297
  /**
@@ -410,6 +354,7 @@ interface IdempotencyPolicy {
410
354
  readonly enabled: boolean;
411
355
  readonly keyTemplate?: string;
412
356
  readonly ttlMs?: number;
357
+ readonly legacyKeyCompatibility?: boolean;
413
358
  }
414
359
 
415
360
  type MediaEventType = "media.stream.started" | "media.stream.ended" | "media.audio.chunk" | "media.audio.committed" | "media.turn.commit_requested" | "media.interrupt.requested" | "dtmf.received" | "media.error";
@@ -508,11 +453,6 @@ type MediaEvent = InputMediaEvent | OutputMediaEvent | InternalMediaEvent;
508
453
  */
509
454
  type WithoutMediaEventKind<T> = T extends MediaEvent ? Omit<T, "kind"> : never;
510
455
  type AnyMediaEventInit = WithoutMediaEventKind<MediaEvent>;
511
- /**
512
- * Adds the required coarse-grained category to a media event. The overload
513
- * keeps the correlated event type available to callers; the implementation
514
- * itself returns the complete `MediaEvent` union and contains no assertion.
515
- */
516
456
  declare function createMediaEvent<T extends AnyMediaEventInit>(init: T): Extract<MediaEvent, {
517
457
  readonly type: T["type"];
518
458
  readonly direction: T["direction"];
@@ -521,24 +461,17 @@ type InputAudioChunk = MediaAudioChunkEvent<"input">;
521
461
  type OutputAudioChunk = MediaAudioChunkEvent<"output">;
522
462
 
523
463
  type JsonSchemaDocument = Readonly<Record<string, unknown>>;
524
- /**
525
- * Optional tenant identity propagated into every tool execution. The runtime
526
- * populates this from the session attachment's `memoryUserId` /
527
- * `organizationId` / `workflowId`. The tool author reads `tenant.userId`
528
- * inside `execute` to enforce their own auth — TVIC ships no RBAC layer
529
- * (that is a tenant concern: the customer has an IdP).
530
- */
531
464
  interface ToolTenant {
532
465
  readonly userId?: UserId;
533
466
  readonly organizationId?: OrganizationId;
534
467
  readonly workflowId?: WorkflowId;
535
- /** Tenant-supplied scopes (e.g., "crm.read", "billing.write"). */
536
468
  readonly scopes?: readonly string[];
537
469
  }
538
470
  interface ToolExecutionContext {
539
471
  readonly sessionId: SessionId;
540
472
  readonly turnId: TurnId;
541
473
  readonly toolCallId: ToolCallId;
474
+ readonly idempotencyKey?: string;
542
475
  readonly attempt: number;
543
476
  readonly signal: AbortSignal;
544
477
  readonly logger: ToolLogger;
@@ -562,11 +495,8 @@ interface ToolDefinition<TInput = unknown, TOutput = unknown> {
562
495
  readonly retry: RetryPolicy;
563
496
  readonly idempotency: IdempotencyPolicy;
564
497
  /**
565
- * @deprecated Use `ctx.tenant` (the `ToolTenant` field on
566
- * `ToolExecutionContext`). The `authScope` field is kept as a no-op
567
- * typedef for one release; the runtime never enforced it. Migration:
568
- * read `ctx.tenant?.scopes` inside `execute` and enforce your own
569
- * auth.
498
+ * @deprecated This field is a no-op. Enforce authorization in `execute`
499
+ * using `ctx.tenant?.scopes`.
570
500
  */
571
501
  readonly authScope?: readonly string[];
572
502
  readonly tags?: readonly string[];
@@ -584,18 +514,20 @@ interface ToolIdempotencyRecord {
584
514
  readonly status: ToolIdempotencyStatus;
585
515
  readonly owner?: string;
586
516
  readonly claimedFence?: number;
517
+ readonly claimedGenerationId?: string;
587
518
  readonly expiresAtMs: number;
588
519
  readonly output?: unknown;
589
520
  readonly error?: NormalizedError;
590
521
  }
591
- /** Ownership context used to fence durable idempotency claims to a session. */
592
522
  interface ToolIdempotencyLease {
593
523
  readonly sessionId: SessionId;
594
524
  readonly holder: string;
595
525
  readonly fence: number;
526
+ readonly generationId: string;
596
527
  }
597
528
  interface ToolIdempotencyClaim {
598
529
  readonly key: string;
530
+ readonly sessionId?: SessionId;
599
531
  readonly lease?: ToolIdempotencyLease;
600
532
  readonly toolId?: ToolId;
601
533
  readonly toolVersion?: string;
@@ -609,25 +541,71 @@ type ToolIdempotencyClaimResult = {
609
541
  } | {
610
542
  readonly status: "succeeded";
611
543
  readonly record: ToolIdempotencyRecord;
544
+ } | {
545
+ readonly status: "terminal";
546
+ readonly record: ToolIdempotencyRecord;
612
547
  } | {
613
548
  readonly status: "in_progress";
614
549
  readonly record: ToolIdempotencyRecord;
615
550
  } | {
616
551
  readonly status: "conflict";
552
+ };
553
+ type ToolIdempotencyLookupResult = {
554
+ readonly status: "found";
617
555
  readonly record: ToolIdempotencyRecord;
556
+ } | {
557
+ readonly status: "conflict";
558
+ } | {
559
+ readonly status: "missing";
618
560
  };
619
561
  interface ToolIdempotencyOutcome {
620
562
  readonly status: Exclude<ToolIdempotencyStatus, "claimed">;
621
563
  readonly ttlMs: number;
622
564
  readonly owner: string;
565
+ readonly sessionId?: SessionId;
623
566
  readonly lease?: ToolIdempotencyLease;
624
567
  readonly output?: unknown;
625
568
  readonly error?: NormalizedError;
626
569
  }
570
+ interface ToolIdempotencyRelease {
571
+ readonly key: string;
572
+ readonly requestHash: string;
573
+ readonly owner: string;
574
+ readonly sessionId?: SessionId;
575
+ readonly lease?: ToolIdempotencyLease;
576
+ }
577
+ interface ToolIdempotencyQuarantine {
578
+ readonly key: string;
579
+ readonly sessionId: SessionId;
580
+ readonly lease: ToolIdempotencyLease;
581
+ readonly toolId: ToolId;
582
+ readonly toolVersion: string;
583
+ readonly requestHash: string;
584
+ readonly owner: string;
585
+ readonly ttlMs: number;
586
+ readonly error: NormalizedError;
587
+ }
588
+ type ToolIdempotencyQuarantineResult = {
589
+ readonly status: "quarantined";
590
+ readonly record: ToolIdempotencyRecord;
591
+ } | {
592
+ readonly status: "succeeded";
593
+ readonly record: ToolIdempotencyRecord;
594
+ } | {
595
+ readonly status: "terminal";
596
+ readonly record: ToolIdempotencyRecord;
597
+ } | {
598
+ readonly status: "in_progress";
599
+ readonly record: ToolIdempotencyRecord;
600
+ } | {
601
+ readonly status: "conflict";
602
+ };
627
603
  interface ToolIdempotencyStore {
628
- lookup(key: string, requestHash: string): Promise<ToolIdempotencyRecord | null>;
604
+ lookup(key: string, requestHash: string, sessionId?: SessionId, lease?: ToolIdempotencyLease): Promise<ToolIdempotencyLookupResult>;
629
605
  claim(input: ToolIdempotencyClaim): Promise<ToolIdempotencyClaimResult>;
606
+ releaseClaim(input: ToolIdempotencyRelease): Promise<boolean>;
630
607
  complete(key: string, requestHash: string, outcome: ToolIdempotencyOutcome): Promise<void>;
608
+ quarantine(input: ToolIdempotencyQuarantine): Promise<ToolIdempotencyQuarantineResult>;
631
609
  }
632
610
  interface ToolCallBase {
633
611
  readonly toolCallId: ToolCallId;
@@ -737,8 +715,8 @@ interface MemoryQuery {
737
715
  readonly tags?: readonly string[];
738
716
  readonly limit?: number;
739
717
  /**
740
- * v0.1 continuation token. Adapters must interpret this as a non-negative
741
- * decimal offset; opaque provider-specific cursors are not portable yet.
718
+ * Opaque continuation token. Built-in adapters use a non-negative decimal
719
+ * offset; callers must treat this value as opaque.
742
720
  */
743
721
  readonly cursor?: string;
744
722
  }
@@ -776,15 +754,7 @@ interface Memory {
776
754
  put<T = unknown>(ref: MemoryRef, key: string, kind: MemoryKind, value: T, options?: MemoryPutOptions): Promise<MemoryEntry<T>>;
777
755
  list<T = unknown>(ref: MemoryRef, query?: MemoryQuery): Promise<readonly MemoryEntry<T>[]>;
778
756
  delete(ref: MemoryRef, key: string, kind?: MemoryKind): Promise<boolean>;
779
- /** Delete every entry under the given `MemoryRef`. Returns the count deleted. */
780
757
  deleteAll(ref: MemoryRef): Promise<number>;
781
- /**
782
- * Delete user-owned data only: the user's `user` scope and session entries
783
- * explicitly attributed to that user by a trusted runtime write. Shared
784
- * organization/workflow scopes are never part of this cascade. This is a
785
- * destructive, privileged erasure primitive; the adapter does not authorize
786
- * the caller or prove that the supplied user id belongs to the requester.
787
- */
788
758
  deleteForUser(userId: UserId): Promise<number>;
789
759
  }
790
760
 
@@ -849,34 +819,22 @@ interface TurnOutput {
849
819
  readonly text?: string;
850
820
  readonly mediaEventIds: readonly MediaEventId[];
851
821
  readonly metadata?: Readonly<Record<string, unknown>>;
822
+ readonly delivery?: TurnOutputDelivery;
823
+ }
824
+ type AudioOutputDeliveryStatus = "not_attempted" | "not_accepted" | "partially_accepted" | "transport_accepted" | "playout_confirmed" | "playout_unconfirmed";
825
+ type TextOutputDeliveryStatus = "not_attempted" | "not_accepted" | "transport_accepted";
826
+ interface TurnOutputDelivery {
827
+ readonly audio: AudioOutputDeliveryStatus;
828
+ readonly text: TextOutputDeliveryStatus;
852
829
  }
853
- /**
854
- * Turn timing on the session's monotonic clock.
855
- *
856
- * Every stage measurement is anchored at the endpoint commit, the moment the runtime
857
- * decided the participant had finished speaking, rather than at internal turn setup.
858
- * That anchor is what a caller actually experiences as the start of waiting.
859
- *
860
- * `endpointMs` is measured before that anchor and is therefore additive: perceived
861
- * caller-to-audio delay is `endpointMs + firstAudioMs`. It is usually the largest
862
- * single contributor, so a report that omits it understates the wait.
863
- */
864
830
  interface TurnLatency {
865
- /** Participant speech start to endpoint commit. Requires a speech-start signal. */
866
831
  readonly listenedMs?: number;
867
- /** Last immutable final segment to endpoint commit, the endpoint wait itself. */
868
832
  readonly endpointMs?: number;
869
- /** Endpoint commit to the first model token. */
870
833
  readonly firstTokenMs?: number;
871
- /** Endpoint commit to the first audio frame accepted by the transport. */
872
834
  readonly firstAudioMs?: number;
873
- /** Total time spent in tool execution during the turn. */
874
835
  readonly toolMs?: number;
875
- /** Interruption decision to queued output being stopped. */
876
836
  readonly interruptionTailMs?: number;
877
- /** Endpoint commit to terminal turn state. */
878
837
  readonly totalMs?: number;
879
- /** Time without an owner during runtime reattachment; excluded from stage timings. */
880
838
  readonly recoveryGapMs?: number;
881
839
  }
882
840
  interface TurnBase {
@@ -972,6 +930,8 @@ interface ProviderCapabilities {
972
930
  readonly models?: readonly string[];
973
931
  readonly batchModels?: readonly string[];
974
932
  readonly voices?: readonly string[];
933
+ /** Whether an incremental TTS adapter can honor timestamp/alignment requests. */
934
+ readonly timestamps?: boolean;
975
935
  readonly turnDetection?: readonly TurnDetectionMode[];
976
936
  readonly tools?: ProviderToolCapabilities;
977
937
  readonly playout?: ProviderPlayoutCapabilities;
@@ -985,6 +945,14 @@ interface Provider {
985
945
  readonly kind: ProviderKind;
986
946
  readonly version: string;
987
947
  readonly capabilities: ProviderCapabilities;
948
+ readonly configuredModel?: string;
949
+ /** Skip local model-catalog validation; this does not imply vendor support. */
950
+ readonly allowUnknownModel?: boolean;
951
+ readonly configuredVoice?: string | undefined;
952
+ readonly configuredLanguage?: string | undefined;
953
+ readonly languageWasExplicitlyConfigured?: boolean;
954
+ readonly supportsLanguage?: (language: string, model?: string) => boolean;
955
+ readonly supportsVoice?: (voice: string, model?: string) => boolean;
988
956
  readonly region?: string;
989
957
  readonly metadata?: Readonly<Record<string, unknown>>;
990
958
  }
@@ -1046,22 +1014,12 @@ type InboundMediaEvent = InputMediaEvent | InternalMediaEvent;
1046
1014
  interface CallHandle {
1047
1015
  readonly callId: CallId;
1048
1016
  readonly events: AsyncIterable<InboundMediaEvent>;
1049
- /**
1050
- * Sends an outbound frame. Returns `true` if it reached the transport, `false`
1051
- * if the socket was closed/closing and the frame was dropped, so the caller can
1052
- * tell "delivered" from "silently swallowed" instead of assuming success.
1053
- */
1017
+ readonly remoteHangup?: Promise<void>;
1054
1018
  send(event: OutputMediaEvent): Promise<boolean>;
1055
- /** Delivers whole-turn assistant text to transports with a text channel. */
1056
1019
  deliverText?(turnId: TurnId, sequence: number, text: string): Promise<boolean>;
1057
1020
  clear(): Promise<void>;
1021
+ endInput?(reason: StreamEndReason): Promise<void>;
1058
1022
  close(reason: StreamEndReason): Promise<void>;
1059
- /**
1060
- * Resolves once the transport confirms the marked output was actually played out
1061
- * to the caller (e.g. a Twilio mark ack): `true` if heard, `false` if the call
1062
- * dropped before playout. Optional: providers that can't observe playout omit it,
1063
- * and callers then fall back to "reached transport" as their delivery signal.
1064
- */
1065
1023
  confirmPlayout?(markId: string, timeoutMs: number): Promise<boolean>;
1066
1024
  }
1067
1025
  interface TelephonyProvider extends Provider {
@@ -1232,9 +1190,7 @@ interface TtsStream {
1232
1190
  /** A single prosody-preserving synthesis context receiving incremental text. */
1233
1191
  interface TtsSession extends TtsStream {
1234
1192
  sendText(text: string): Promise<void>;
1235
- /** Resolves once the provider or transport accepts a synthesis boundary. */
1236
1193
  flush(): Promise<TtsFlushResult>;
1237
- /** Ends input; events continue until the provider emits its completion event. */
1238
1194
  finish(): Promise<void>;
1239
1195
  }
1240
1196
  interface TextToSpeechProvider extends Provider {
@@ -1327,14 +1283,8 @@ interface AgentMemoryPolicy {
1327
1283
  readonly maxBytesPerSession?: number;
1328
1284
  readonly readOnly?: boolean;
1329
1285
  /**
1330
- * If true (default), session-scoped memory is purged on session end. This
1331
- * is Vapi's Zero Data Retention posture: the call's ephemeral transcripts
1332
- * do not outlive the call. User-scoped, organization-scoped, and
1333
- * workflow-scoped memory are *not* affected — they persist across sessions.
1334
- *
1335
- * Pre-1.0, this field was named `deleteOnEnd`. That name was misleading:
1336
- * it sounded like it deleted *all* memory, but the implementation only
1337
- * purges the `session` scope. The rename is the contract-clarity fix.
1286
+ * If true (default), only session-scoped memory is purged on session end.
1287
+ * User, organization, and workflow memory remain available across sessions.
1338
1288
  */
1339
1289
  readonly deleteSessionScopeOnEnd?: boolean;
1340
1290
  /**
@@ -1424,27 +1374,42 @@ interface Agent {
1424
1374
  readonly metadata?: Readonly<Record<string, unknown>>;
1425
1375
  }
1426
1376
 
1377
+ declare const MAX_RECOVERY_PAGE_SIZE = 1000;
1378
+ declare const MAX_SAFE_LEASE_TIMESTAMP: number;
1379
+ declare function assertLeaseTtlMs(ttlMs: number): void;
1380
+ declare function assertLeaseFence(fence: number): void;
1381
+ declare function assertLeaseTimestampMs(timestampMs: number): void;
1382
+ declare function safeLeaseExpiryAt(nowMs: number, ttlMs: number): number;
1383
+ declare function assertRecoveryPageSize(limit: number): void;
1427
1384
  interface SessionLease {
1428
1385
  readonly sessionId: SessionId;
1429
1386
  readonly holder: string;
1430
1387
  readonly fence: number;
1388
+ readonly generationId: string;
1431
1389
  readonly acquiredAtMs: number;
1432
1390
  readonly renewedAtMs: number;
1433
1391
  readonly expiresAtMs: number;
1434
1392
  }
1393
+ interface SessionRecoveryCandidate {
1394
+ readonly sessionId: SessionId;
1395
+ readonly fence: number;
1396
+ readonly generationId: string;
1397
+ }
1435
1398
  interface SessionLeaseStore {
1436
1399
  acquire(sessionId: SessionId, holder: string, ttlMs: number): Promise<SessionLease | null>;
1437
- renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number): Promise<SessionLease | null>;
1438
- release(sessionId: SessionId, holder: string, fence: number): Promise<void>;
1400
+ renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number, generationId: string): Promise<SessionLease | null>;
1401
+ release(sessionId: SessionId, holder: string, fence: number, generationId: string): Promise<void>;
1439
1402
  get(sessionId: SessionId): Promise<SessionLease | null>;
1440
1403
  listRecoveryCandidates(options: {
1441
1404
  readonly nowMs: number;
1442
1405
  readonly limit: number;
1443
1406
  readonly cursor?: string;
1444
1407
  }): Promise<{
1445
- readonly sessionIds: readonly SessionId[];
1408
+ readonly candidates: readonly SessionRecoveryCandidate[];
1409
+ readonly corruptLeaseSessionIds?: readonly SessionId[];
1446
1410
  readonly nextCursor?: string;
1447
1411
  }>;
1412
+ acknowledgeRecoveryCandidate(candidate: SessionRecoveryCandidate): Promise<void>;
1448
1413
  close(): Promise<void>;
1449
1414
  }
1450
1415
  interface DurableOutboxEvent {
@@ -1452,6 +1417,7 @@ interface DurableOutboxEvent {
1452
1417
  readonly aggregateType: "session" | "turn" | "tool_call";
1453
1418
  readonly aggregateId: string;
1454
1419
  readonly sessionId: SessionId;
1420
+ readonly sessionIncarnation?: number;
1455
1421
  readonly version: number;
1456
1422
  readonly fence: number;
1457
1423
  readonly envelope: Readonly<Record<string, unknown>>;
@@ -1472,7 +1438,6 @@ interface ToolCallRuntimeMetadata {
1472
1438
  interface StoredSessionRecord {
1473
1439
  readonly session: Session;
1474
1440
  readonly runtime: SessionRuntimeMetadata;
1475
- /** Persistence-local aggregate version used for outbox ordering/fencing. */
1476
1441
  readonly version?: number;
1477
1442
  }
1478
1443
  interface StoredTurnRecord {
@@ -1526,28 +1491,9 @@ interface DurableRuntimeStore {
1526
1491
  readonly toolCalls: ToolCallStore;
1527
1492
  readonly leases: SessionLeaseStore;
1528
1493
  readonly toolIdempotencyStore?: ToolIdempotencyStore;
1529
- /**
1530
- * Closes adapter-owned resources and background workers. When present,
1531
- * Runtime.stop() delegates the complete durable-store shutdown to this
1532
- * method instead of closing the aggregate stores independently. Adapters
1533
- * that do not own background resources may omit it and retain the legacy
1534
- * component-close behavior.
1535
- */
1536
1494
  close?(): Promise<void>;
1537
- /**
1538
- * Atomically creates a session and acquires its first owner lease when the
1539
- * backend supports that transaction boundary. Runtimes use the fallback
1540
- * start-then-attach path only for adapters that do not implement it.
1541
- */
1542
1495
  createSessionWithLease?(record: StoredSessionRecord, holder: string, ttlMs: number, initialEvent?: (lease: SessionLease) => DurableOutboxEvent): Promise<SessionLease | null>;
1543
- runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
1544
- /**
1545
- * Serialized compatibility boundary for callers that intentionally operate
1546
- * without a live attachment. A store may provide rollback internally, but
1547
- * the legacy CRUD interfaces cannot guarantee atomic rollback for arbitrary
1548
- * custom stores. There is no ownership or fencing guarantee; realtime
1549
- * attached paths must use runSessionTransaction.
1550
- */
1496
+ runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence" | "generationId">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
1551
1497
  runUnfencedSessionTransaction?<T>(sessionId: SessionId, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
1552
1498
  }
1553
1499
 
@@ -1558,140 +1504,41 @@ interface RuntimeOptions {
1558
1504
  readonly clock?: Clock;
1559
1505
  readonly idGenerator?: IdGenerator;
1560
1506
  readonly durableStore?: DurableRuntimeStore;
1561
- /** Whether the runtime may close an injected durable store during stop. */
1562
1507
  readonly durableStoreOwnership?: "runtime" | "caller";
1563
- /** Overrides for the explicit defaults; omitted values use the safe defaults. */
1564
1508
  readonly durablePolicy?: Partial<DurableRuntimePolicy>;
1565
1509
  readonly toolIdempotencyStore?: ToolIdempotencyStore;
1566
1510
  readonly holderId?: string;
1567
1511
  readonly onDurableMetric?: (metric: DurableRuntimeMetric) => void;
1568
- /**
1569
- * Memory adapter used for cross-call memory. Defaults to `InMemoryMemory`
1570
- * (process-local) when omitted. For cross-call recall, wire a durable
1571
- * adapter (e.g., `@tvic/dal-postgres-memory`) or a third-party adapter
1572
- * (Mem0, Supermemory, etc.).
1573
- */
1574
1512
  readonly memory?: Memory;
1575
- /**
1576
- * Maximum time the runtime waits for already-admitted memory writes and the
1577
- * session-scope purge during terminalization. Timing out releases the
1578
- * caller while preserving write-before-purge ordering. The default is 1
1579
- * second; the adapter operation is not cancelled.
1580
- */
1581
1513
  readonly sessionMemoryFinalizeTimeoutMs?: number;
1582
- /**
1583
- * Maximum time the runtime waits for the best-effort `onSessionEnd` observer
1584
- * after the terminal event has been assembled. The default is 5 seconds;
1585
- * the observer is not cancelled when this budget expires.
1586
- */
1587
1514
  readonly sessionEndHookTimeoutMs?: number;
1588
- /**
1589
- * Pre-call context resolver. When a session is created or attached, the
1590
- * runtime calls this hook when a session is attached to populate the agent's
1591
- * context with memory entries for the relevant scopes AND with non-memory
1592
- * context (CRM, feature flags, tenant config). If omitted, the runtime uses a default
1593
- * resolver that reads from `options.memory` for the active `user` /
1594
- * `organization` / `workflow` scopes and returns an empty `static` map.
1595
- *
1596
- * Pre-1.0, this was named `preCallMemoryResolver` and returned a
1597
- * `PreCallMemoryContext`. The rename to `PreCallContextResolver` and
1598
- * the addition of the `static: ReadonlyMap<string, string>` sub-map
1599
- * fixes a real type lie: the customer previously had to stuff CRM
1600
- * data and feature flags into the `Memory` map as `kind: "fact"`
1601
- * entries. The `static` map is the typed input for non-memory context.
1602
- */
1603
1515
  readonly preCallContextResolver?: PreCallContextResolver;
1604
- /** Optional org/workflow ids carried on every session created by this runtime. */
1605
1516
  readonly defaultOrganizationId?: OrganizationId;
1606
1517
  readonly defaultWorkflowId?: WorkflowId;
1607
- /**
1608
- * Optional callback fired after a session is terminalized and after the
1609
- * runtime has made its best-effort memory-finalization attempt. The event
1610
- * reports whether session-scope deletion was skipped, completed, failed, or
1611
- * timed out. Best-effort: a throw or timeout from the hook does not affect
1612
- * the terminal session. The runtime does not retry; if you need durability,
1613
- * call an external system from inside the hook and have that system retry.
1614
- *
1615
- * The hook is the canonical place for: post-call LLM summarization,
1616
- * CRM sync, callback scheduling, escalation, transcript delivery to a
1617
- * CRM. The runtime does not own any of these — the user picks the LLM,
1618
- * the prompt, the schema.
1619
- */
1620
1518
  readonly onSessionEnd?: (event: SessionEndEvent) => void | Promise<void>;
1621
- /**
1622
- * Optional metrics recorder. The runtime emits one `record` call per
1623
- * observable event (session start, turn end, session end) and one
1624
- * `onTurn` call per terminal turn. The user provides the implementation
1625
- * (Earshot-shaped, console.log-shaped, OTel-shaped).
1626
- */
1627
1519
  readonly sessionMetricsRecorder?: SessionMetricsRecorder;
1628
- /**
1629
- * Optional health check consumed by `NodeMediaPlane.healthPath`. The
1630
- * user implements the readiness check (DB ping, recovery-coordinator
1631
- * liveness); the runtime reflects it on the HTTP endpoint. Returns
1632
- * `ok: true` when all checks pass; the runtime responds with HTTP 200.
1633
- */
1634
1520
  readonly healthCheck?: () => Promise<HealthSnapshot>;
1635
- /**
1636
- * Optional callback fired at the start of `runtime.stop()` so the
1637
- * user's deployment wiring (SIGTERM handler, kubernetes preStop hook)
1638
- * can drain the load balancer before the runtime detaches sessions
1639
- * and closes stores. Best-effort; the runtime proceeds after the
1640
- * promise settles or 5s, whichever comes first.
1641
- */
1642
1521
  readonly onShutdownStart?: (state: {
1643
1522
  readonly activeSessions: readonly SessionId[];
1644
1523
  }) => void | Promise<void>;
1645
- /**
1646
- * Optional async provider of the pre-call static context (CRM records,
1647
- * feature flags, tenant config). Called by the runtime when a session is
1648
- * attached; the result is merged into the pre-call context's `static`
1649
- * map. Best-effort: a throw or timeout produces a degraded `static`
1650
- * context (degraded flag set). This is a separate seam from
1651
- * `preCallContextResolver` so a custom resolver can choose to either
1652
- * (a) inline the static fetch into its own resolver, or (b) leave the
1653
- * fetch to the runtime and just augment the result.
1654
- */
1655
1524
  readonly preCallStaticProvider?: () => Promise<ReadonlyMap<string, string>>;
1656
1525
  }
1657
- /**
1658
- * Resolves the pre-call context for a session. The runtime calls this on
1659
- * `startAttachedSession` and `attachSession` after lease acquisition.
1660
- *
1661
- * Pre-1.0, this was named `PreCallMemoryResolver` and returned a
1662
- * `PreCallMemoryContext`. The rename to `PreCallContextResolver` and
1663
- * the addition of the `static` sub-map fixes the type lie.
1664
- */
1665
1526
  type PreCallContextResolver = (input: {
1666
1527
  readonly userId?: UserId;
1667
1528
  readonly organizationId?: OrganizationId;
1668
1529
  readonly workflowId?: WorkflowId;
1669
1530
  readonly sessionId: SessionId;
1670
1531
  readonly memory: Memory;
1671
- /** Wall-clock source supplied by the runtime for deterministic resolution. */
1672
1532
  readonly clock?: () => number;
1673
- /** Scopes permitted by the agent's memory policy for this call. */
1674
1533
  readonly scopes?: readonly MemoryScope[];
1675
- /** Optional kind filter from `memoryPolicy.preCallLoad`. */
1676
1534
  readonly kind?: MemoryKind;
1677
- /** Maximum memory entries the runtime should load from any one scope. */
1678
1535
  readonly maxEntries?: number;
1679
- /** Maximum rendered pre-call context bytes. */
1680
1536
  readonly maxBytes?: number;
1681
1537
  }) => Promise<PreCallContext>;
1682
1538
  interface PreCallContext {
1683
- /** Map of `${scope}:${scopeId}:${kind}:${key}` to entry. Empty on resolver error. */
1684
1539
  readonly memory: ReadonlyMap<string, MemoryEntry>;
1685
- /**
1686
- * Non-memory context: CRM records, feature flags, tenant config, anything
1687
- * the LLM should see in the system prompt that is *not* a memory entry.
1688
- * Rendered into a separate `<context>...</context>` block above the
1689
- * `<memory>...</memory>` block.
1690
- */
1691
1540
  readonly static: ReadonlyMap<string, string>;
1692
- /** When the resolver ran, wall-clock ms. */
1693
1541
  readonly resolvedAtMs: number;
1694
- /** Per-bucket degradation flag. */
1695
1542
  readonly degraded: {
1696
1543
  readonly memory: boolean;
1697
1544
  readonly static: boolean;
@@ -1713,26 +1560,11 @@ interface PreCallMemoryContext {
1713
1560
  readonly resolvedAtMs: number;
1714
1561
  readonly degraded: boolean;
1715
1562
  }
1716
- /**
1717
- * Carries the terminal session, the persisted snapshot, and a snapshot
1718
- * of the memory adapter's state at the moment of endSession. The
1719
- * memory snapshot is the source of truth for "what did we learn about
1720
- * this caller" — the runtime does not try to track per-write
1721
- * `MemoryChangeRecord`s, because most writes are within the session
1722
- * scope and are about to be deleted by `deleteSessionScopeOnEnd`. The
1723
- * snapshot the user actually wants is what survives into `user` /
1724
- * `organization` / `workflow` scopes.
1725
- */
1726
1563
  interface SessionEndEvent {
1727
1564
  readonly session: TerminalSession;
1728
1565
  readonly snapshot: SessionSnapshot;
1729
- /**
1730
- * Memory state at end-of-session, scoped to the user/org/workflow ids
1731
- * the runtime resolved for this session. Empty for sessions that wrote
1732
- * only to `session` scope (which is about to be deleted).
1733
- */
1566
+ readonly snapshotStatus?: "available" | "timed_out" | "unavailable";
1734
1567
  readonly finalMemorySnapshot: SessionEndMemorySnapshot;
1735
- /** Result of the ordered session-memory drain and optional purge. */
1736
1568
  readonly memoryFinalization: SessionMemoryFinalization;
1737
1569
  readonly wallClockMs: number;
1738
1570
  }
@@ -1754,17 +1586,73 @@ interface SessionEndMemorySnapshot {
1754
1586
  readonly organization?: ReadonlyMap<string, MemoryEntry>;
1755
1587
  readonly workflow?: ReadonlyMap<string, MemoryEntry>;
1756
1588
  }
1757
- /**
1758
- * Contract for an external observability consumer. The runtime emits
1759
- * one `record` per observable event and one `onTurn` per terminal
1760
- * turn. Implementations: Earshot-shaped (project into an `earshot.*`
1761
- * event), OTel-shaped (project into a span event), console.log-shaped.
1762
- */
1763
1589
  interface SessionMetricsRecorder {
1764
1590
  record(name: string, attributes?: Readonly<Record<string, string | number | boolean>>): void;
1765
1591
  onTurn(turn: TerminalTurn, sessionId: SessionId): void;
1592
+ onSessionTrace?(trace: RuntimeSessionTrace): void;
1766
1593
  onSessionEnd?(event: SessionEndEvent): void;
1767
1594
  }
1595
+ interface RuntimeTraceError {
1596
+ readonly code: string;
1597
+ readonly category: ErrorCategory;
1598
+ readonly retriable: boolean;
1599
+ }
1600
+ interface RuntimeSessionTrace {
1601
+ readonly schemaVersion: 1;
1602
+ readonly privacy: {
1603
+ readonly classification: "metadata_only";
1604
+ readonly excludes: readonly [
1605
+ "transcripts",
1606
+ "audio",
1607
+ "tool_names",
1608
+ "tool_arguments",
1609
+ "tool_results",
1610
+ "provider_error_messages",
1611
+ "session_metadata",
1612
+ "variables",
1613
+ "memory"
1614
+ ];
1615
+ };
1616
+ readonly session: {
1617
+ readonly id: SessionId;
1618
+ readonly callId?: CallId;
1619
+ readonly agentId: AgentId;
1620
+ readonly channel: ChannelKind;
1621
+ readonly status: TerminalSessionStatus;
1622
+ readonly terminalSource?: TerminalSource;
1623
+ readonly createdAt: Timestamp;
1624
+ readonly startedAt: Timestamp;
1625
+ readonly endedAt: Timestamp;
1626
+ readonly error?: RuntimeTraceError;
1627
+ };
1628
+ readonly snapshot: {
1629
+ readonly status: "available" | "timed_out" | "unavailable";
1630
+ readonly turnCount: number;
1631
+ readonly omittedTurnCount: number;
1632
+ readonly toolCallCount: number;
1633
+ readonly omittedToolCallCount: number;
1634
+ };
1635
+ readonly turns: readonly {
1636
+ readonly id: TurnId;
1637
+ readonly sequence: number;
1638
+ readonly status: TurnStatus;
1639
+ readonly startedAt: Timestamp;
1640
+ readonly endedAt?: Timestamp;
1641
+ readonly latency: TurnLatency;
1642
+ readonly delivery?: TurnOutputDelivery;
1643
+ readonly error?: RuntimeTraceError;
1644
+ }[];
1645
+ readonly toolCalls: readonly {
1646
+ readonly id: ToolCallId;
1647
+ readonly turnId: TurnId;
1648
+ readonly status: ToolCallStatus;
1649
+ readonly attempts: number;
1650
+ readonly queuedAt: Timestamp;
1651
+ readonly startedAt?: Timestamp;
1652
+ readonly endedAt?: Timestamp;
1653
+ readonly error?: RuntimeTraceError;
1654
+ }[];
1655
+ }
1768
1656
  interface HealthSnapshot {
1769
1657
  readonly ok: boolean;
1770
1658
  readonly checks?: Readonly<Record<string, HealthCheckResult>>;
@@ -1773,7 +1661,6 @@ interface HealthCheckResult {
1773
1661
  readonly ok: boolean;
1774
1662
  readonly latencyMs?: number;
1775
1663
  readonly message?: string;
1776
- /** Sanitized diagnostic details supplied by the owning subsystem. */
1777
1664
  readonly details?: Readonly<Record<string, unknown>>;
1778
1665
  }
1779
1666
  interface DurableRuntimeMetric {
@@ -1810,11 +1697,8 @@ interface StartSessionOptions {
1810
1697
  readonly call?: Call;
1811
1698
  readonly variables?: Readonly<Record<string, unknown>>;
1812
1699
  readonly metadata?: Readonly<Record<string, unknown>>;
1813
- /** User scope identity for cross-call memory recall. */
1814
1700
  readonly memoryUserId?: UserId;
1815
- /** Organization scope for cross-call memory recall. */
1816
1701
  readonly organizationId?: OrganizationId;
1817
- /** Workflow scope for cross-call memory recall. */
1818
1702
  readonly workflowId?: WorkflowId;
1819
1703
  }
1820
1704
  type EndSessionReason = "completed" | "cancelled" | "failed" | "timeout";
@@ -1873,41 +1757,19 @@ interface SessionAttachment {
1873
1757
  readonly signal: AbortSignal;
1874
1758
  readonly health: SessionAttachmentHealth;
1875
1759
  readonly detach: () => Promise<void>;
1876
- /**
1877
- * Pre-call context loaded from the runtime's pre-call context resolver
1878
- * before the call starts. Contains both memory entries (rendered as
1879
- * `<memory>...</memory>`) and non-memory static context (rendered as
1880
- * `<context>...</context>`). Pre-1.0, this was `preCallMemory` and
1881
- * carried only the memory entries. The rename is the contract-clarity
1882
- * fix; legacy callers reading `preCallMemory.entries` should switch
1883
- * to `preCallContext.memory`.
1884
- */
1885
1760
  readonly preCallContext?: PreCallContext;
1886
1761
  /**
1887
- * @deprecated Use `preCallContext`. The legacy `preCallMemory` field
1888
- * is kept as a typedef for one release and resolved to a shim that
1889
- * projects `preCallContext.memory`.
1762
+ * @deprecated Use `preCallContext`. This compatibility field projects
1763
+ * `preCallContext.memory`.
1890
1764
  */
1891
1765
  readonly preCallMemory?: PreCallMemoryContext;
1892
1766
  }
1893
1767
  interface RuntimeServiceLifecycle {
1894
- /** Starts the runtime. A runtime can be started once; create a new runtime after stop. */
1895
1768
  start(signal?: AbortSignal): Promise<void>;
1896
- /**
1897
- * Stops the runtime and closes its owned resources. The operation is
1898
- * idempotent and concurrent callers await the same teardown. A stopped
1899
- * runtime cannot be restarted because durable adapters are closed.
1900
- */
1901
1769
  stop(): Promise<void>;
1902
1770
  readonly isRunning: boolean;
1903
1771
  }
1904
1772
  interface Runtime extends RuntimeServiceLifecycle {
1905
- /**
1906
- * Optional execution seam for low-level pipeline users. Registered runs are
1907
- * cancelled and drained by `stop()` before the runtime closes its durable
1908
- * stores. Managed voice agents already provide their own higher-level
1909
- * lifecycle, but direct `PipelineVoiceLoop` callers need this ownership too.
1910
- */
1911
1773
  registerPipelineRun?(run: Promise<unknown>, cancel: () => void): () => void;
1912
1774
  startSession(agent: Agent, options: StartSessionOptions): Promise<ActiveSession>;
1913
1775
  startAttachedSession(agent: Agent, options: StartAttachedSessionOptions): Promise<SessionAttachment>;
@@ -1922,28 +1784,14 @@ interface Runtime extends RuntimeServiceLifecycle {
1922
1784
  startTurn(request: StartTurnRequest): Promise<Turn>;
1923
1785
  endTurn(sessionId: SessionId, turnId: TurnId, request: EndTurnRequest): Promise<TerminalTurn>;
1924
1786
  updateTurnStatus(sessionId: SessionId, turnId: TurnId, status: TurnStatus): Promise<Turn>;
1925
- /** Marks durable persistence health for the live attachment without changing lease ownership. */
1926
1787
  setPersistenceHealth(sessionId: SessionId, degraded: boolean): void;
1927
- /**
1928
- * Serializes memory writes and session-end purge for one session. Built-in
1929
- * runtimes provide this; custom runtimes may omit it for compatibility.
1930
- */
1931
1788
  runSessionMemoryOperation?<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T>;
1932
1789
  startToolCall(toolCall: QueuedToolCall): Promise<RunningToolCall>;
1933
1790
  finishToolCall(toolCall: TerminalToolCall): Promise<TerminalToolCall>;
1934
1791
  recoverToolCalls(sessionId: SessionId): Promise<readonly ToolCall[]>;
1935
1792
  checkpointTurnInterruption(sessionId: SessionId, turnId: TurnId, reason: TurnCancellationReason): Promise<Turn>;
1936
- /** Session-relative monotonic offset used for turn and media timing. */
1937
1793
  sessionClockMs(id: SessionId): number;
1938
- /** Persists a completed tool call as part of runtime session state. */
1939
1794
  recordToolCall(toolCall: ToolCall): Promise<void>;
1940
- /**
1941
- * Optional health check. The runtime exposes this so the
1942
- * `NodeMediaPlane` (or any other host) can surface readiness via
1943
- * `/healthz`. Returns `ok: true` when the underlying store + leases
1944
- * are healthy; the host responds with HTTP 200 vs 503. Best-effort:
1945
- * a throw produces `ok: false`.
1946
- */
1947
1795
  healthCheck(): Promise<HealthSnapshot>;
1948
1796
  inspectSession(id: SessionId): Promise<SessionSnapshot>;
1949
1797
  readonly durablePolicy?: DurableRuntimePolicy;
@@ -2047,7 +1895,6 @@ interface TwilioMediaStreamCallHandleOptions {
2047
1895
  readonly sessionId: SessionId;
2048
1896
  readonly inputFormat?: AudioFormat;
2049
1897
  readonly outputFormat?: AudioFormat;
2050
- /** Values authenticated by the host and expected in Twilio's start frame. */
2051
1898
  readonly expectedTwilioCallSid?: string;
2052
1899
  readonly expectedAccountSid?: string;
2053
1900
  readonly clock?: ProviderClock;
@@ -2057,11 +1904,13 @@ declare class TwilioMediaStreamCallHandle implements CallHandle {
2057
1904
  #private;
2058
1905
  readonly options: TwilioMediaStreamCallHandleOptions;
2059
1906
  readonly events: AsyncIterable<InboundMediaEvent>;
1907
+ readonly remoteHangup: Promise<void>;
2060
1908
  constructor(options: TwilioMediaStreamCallHandleOptions);
2061
1909
  readonly callId: CallId;
2062
1910
  send(event: OutputMediaEvent): Promise<boolean>;
2063
1911
  clear(): Promise<void>;
2064
1912
  close(reason: StreamEndReason): Promise<void>;
1913
+ endInput(reason: StreamEndReason): Promise<void>;
2065
1914
  confirmPlayout(markId: string, timeoutMs: number): Promise<boolean>;
2066
1915
  }
2067
1916
 
@@ -2110,22 +1959,25 @@ declare class TwilioMediaStreamsProvider implements TelephonyProvider {
2110
1959
  }
2111
1960
  declare function createTwilioMediaStreamsProvider(): TwilioMediaStreamsProvider;
2112
1961
 
2113
- declare const WEB_CLIENT_AUDIO_CLOSE_CODES: {
2114
- protocol: number;
2115
- heartbeatTimeout: number;
2116
- superseded: number;
2117
- maxDuration: number;
2118
- resourceLimit: number;
2119
- operatorTerminated: number;
2120
- };
2121
1962
  declare const WEB_CLIENT_AUDIO_DEFAULTS: {
2122
1963
  heartbeatIntervalMs: number;
2123
1964
  heartbeatTimeoutMs: number;
2124
1965
  maxSessionDurationMs: number;
1966
+ maxBinaryFrameBytes: number;
1967
+ maxInputBytesPerSecond: number;
2125
1968
  maxPendingEvents: number;
2126
1969
  maxInputFramesPerSecond: number;
2127
1970
  maxPendingAcks: number;
2128
1971
  };
1972
+
1973
+ declare const WEB_CLIENT_AUDIO_CLOSE_CODES: {
1974
+ protocol: number;
1975
+ heartbeatTimeout: number;
1976
+ superseded: number;
1977
+ maxDuration: number;
1978
+ resourceLimit: number;
1979
+ operatorTerminated: number;
1980
+ };
2129
1981
  declare const WEB_CLIENT_AUDIO_ACK_RETENTION_MS = 60000;
2130
1982
 
2131
1983
  interface WebClientAudioSocket {
@@ -2133,6 +1985,7 @@ interface WebClientAudioSocket {
2133
1985
  readonly bufferedAmount?: number;
2134
1986
  send(data: string | Buffer): void;
2135
1987
  close(code?: number, reason?: string): void;
1988
+ terminate?(): void;
2136
1989
  on(event: "message", handler: (data: WebSocket.RawData, isBinary: boolean) => void): this;
2137
1990
  on(event: "close", handler: (code: number, reason: Buffer) => void): this;
2138
1991
  on(event: "error", handler: (error: Error) => void): this;
@@ -2180,6 +2033,7 @@ interface WebClientAudioCallHandle extends CallHandle {
2180
2033
  send(event: OutputMediaEvent): Promise<boolean>;
2181
2034
  deliverText(turnId: TurnId, sequence: number, text: string): Promise<boolean>;
2182
2035
  clear(): Promise<void>;
2036
+ endInput(reason: StreamEndReason): Promise<void>;
2183
2037
  close(reason: StreamEndReason): Promise<void>;
2184
2038
  terminate(code: number, reason: string): void;
2185
2039
  confirmPlayout(markId: string, timeoutMs: number): Promise<boolean>;
@@ -2380,9 +2234,9 @@ interface SarvamTtsProviderOptions {
2380
2234
  readonly voiceId?: string;
2381
2235
  readonly modelId?: string;
2382
2236
  readonly language?: string;
2383
- /** Provider pace. Sarvam v3 accepts 0.5 through 2.0. */
2237
+ /** Provider pace. Sarvam Bulbul v3 and v4 Flash accept 0.5 through 2.0. */
2384
2238
  readonly pace?: number;
2385
- /** Provider temperature. Sarvam's streaming schema accepts 0.01 through 1.0. */
2239
+ /** Bulbul v3 temperature; Bulbul v4 Flash does not accept this option. */
2386
2240
  readonly temperature?: number;
2387
2241
  readonly minBufferSize?: number;
2388
2242
  readonly maxChunkLength?: number;
@@ -2397,7 +2251,7 @@ interface SarvamTtsStreamOptions {
2397
2251
  readonly language: string;
2398
2252
  readonly voice: string;
2399
2253
  readonly pace: number;
2400
- readonly temperature: number;
2254
+ readonly temperature?: number;
2401
2255
  readonly minBufferSize: number;
2402
2256
  readonly maxChunkLength: number;
2403
2257
  readonly pronunciationDictionaryId?: string;
@@ -2408,36 +2262,14 @@ declare class SarvamTtsProvider implements IncrementalTextToSpeechProvider {
2408
2262
  readonly name: "sarvam-tts";
2409
2263
  readonly kind = "tts";
2410
2264
  readonly version = "0.1.0";
2411
- readonly capabilities: {
2412
- streaming: {
2413
- input: true;
2414
- output: true;
2415
- native: true;
2416
- };
2417
- cancellation: {
2418
- request: true;
2419
- output: false;
2420
- buffer: false;
2421
- truncation: false;
2422
- };
2423
- transports: "websocket"[];
2424
- audio: {
2425
- output: {
2426
- readonly encoding: "pcm_s16le";
2427
- readonly sampleRateHz: 16000;
2428
- readonly channels: 1;
2429
- }[];
2430
- };
2431
- languages: readonly ["hi-IN", "bn-IN", "ta-IN", "te-IN", "gu-IN", "kn-IN", "ml-IN", "mr-IN", "pa-IN", "od-IN", "en-IN"];
2432
- models: readonly ["bulbul:v3"];
2433
- voices: readonly ["shubh", "aditya", "ritu", "priya", "neha", "rahul", "pooja", "rohan", "simran", "kavya", "amit", "dev", "ishita", "shreya", "ratan", "varun", "manan", "sumit", "roopa", "kabir", "aayan", "ashutosh", "advait", "anand", "tanya", "tarun", "sunny", "mani", "gokul", "vijay", "shruti", "suhani", "mohit", "kavitha", "rehan", "soham", "rupali"];
2434
- metadata: {
2435
- outputAudioCodec: string;
2436
- outputSampleRateHz: number;
2437
- completionEvent: string;
2438
- };
2439
- };
2265
+ readonly capabilities: ProviderCapabilities;
2440
2266
  constructor(options: SarvamTtsProviderOptions);
2267
+ get configuredModel(): string;
2268
+ get configuredLanguage(): string;
2269
+ get languageWasExplicitlyConfigured(): boolean;
2270
+ get configuredVoice(): string | undefined;
2271
+ supportsVoice(voice: string, model?: string): boolean;
2272
+ supportsLanguage(language: string, model?: string): boolean;
2441
2273
  synthesize(request: TtsSynthesisRequest): Promise<TtsStream>;
2442
2274
  openSession(request: TtsSessionOpenRequest): Promise<SarvamTtsStream>;
2443
2275
  }
@@ -2453,59 +2285,41 @@ declare class SarvamTtsStream implements TtsSession {
2453
2285
  }
2454
2286
  declare function createSarvamTtsProvider(options: SarvamTtsProviderOptions): SarvamTtsProvider;
2455
2287
 
2288
+ declare const SARVAM_TTS_V4_FLASH_MODEL: "bulbul:v4-flash";
2289
+
2456
2290
  interface SarvamTtsHttpProviderOptions {
2457
2291
  readonly apiKey: string;
2458
2292
  readonly url?: string;
2459
2293
  readonly voiceId?: string;
2460
2294
  readonly modelId?: string;
2461
2295
  readonly language?: string;
2462
- /** Provider pace. Sarvam Bulbul v3 accepts 0.5 through 2.0. */
2296
+ /** Provider pace. Sarvam Bulbul v3 and v4 Flash accept 0.5 through 2.0. */
2463
2297
  readonly pace?: number;
2464
- /** Provider temperature. Sarvam Bulbul v3 accepts 0.01 through 1.0. */
2298
+ /** HTTP temperature tuning for Sarvam Bulbul v3 and v4 Flash (0.01 through 1.0). */
2465
2299
  readonly temperature?: number;
2466
2300
  readonly pronunciationDictionaryId?: string;
2301
+ /** Maximum time allowed for request headers and the complete response. Defaults to 10 minutes. */
2302
+ readonly requestTimeoutMs?: number;
2303
+ /** Maximum wait for response progress after headers arrive. Defaults to 30 seconds. */
2304
+ readonly responseIdleTimeoutMs?: number;
2467
2305
  readonly clock?: ProviderClock;
2468
- /** Injectable fetch makes protocol and failure tests hermetic. */
2306
+ /** Fetch override for tests or custom transports. */
2469
2307
  readonly fetchImpl?: typeof fetch;
2470
2308
  }
2309
+
2471
2310
  declare class SarvamTtsRestProvider implements TextToSpeechProvider {
2472
2311
  #private;
2473
2312
  readonly name: "sarvam-tts";
2474
2313
  readonly kind = "tts";
2475
2314
  readonly version = "0.1.0";
2476
- readonly capabilities: {
2477
- streaming: {
2478
- input: false;
2479
- output: false;
2480
- native: false;
2481
- };
2482
- cancellation: {
2483
- request: true;
2484
- output: false;
2485
- buffer: false;
2486
- truncation: false;
2487
- };
2488
- transports: "http"[];
2489
- audio: {
2490
- output: {
2491
- readonly encoding: "pcm_s16le";
2492
- readonly sampleRateHz: 16000;
2493
- readonly channels: 1;
2494
- }[];
2495
- };
2496
- languages: readonly ["hi-IN", "bn-IN", "ta-IN", "te-IN", "gu-IN", "kn-IN", "ml-IN", "mr-IN", "pa-IN", "od-IN", "en-IN"];
2497
- models: readonly ["bulbul:v3"];
2498
- voices: readonly ["shubh", "aditya", "ritu", "priya", "neha", "rahul", "pooja", "rohan", "simran", "kavya", "amit", "dev", "ishita", "shreya", "ratan", "varun", "manan", "sumit", "roopa", "kabir", "aayan", "ashutosh", "advait", "anand", "tanya", "tarun", "sunny", "mani", "gokul", "vijay", "shruti", "suhani", "mohit", "kavitha", "rehan", "soham", "rupali"];
2499
- metadata: {
2500
- transport: string;
2501
- endpoint: string;
2502
- requestTextLimit: number;
2503
- wireOutputCodec: string;
2504
- normalizedOutput: string;
2505
- documentation: string;
2506
- };
2507
- };
2315
+ readonly capabilities: ProviderCapabilities;
2508
2316
  constructor(options: SarvamTtsHttpProviderOptions);
2317
+ get configuredModel(): string;
2318
+ get configuredLanguage(): string;
2319
+ get languageWasExplicitlyConfigured(): boolean;
2320
+ get configuredVoice(): string | undefined;
2321
+ supportsVoice(voice: string, model?: string): boolean;
2322
+ supportsLanguage(language: string, model?: string): boolean;
2509
2323
  synthesize(request: TtsSynthesisRequest): Promise<TtsStream>;
2510
2324
  }
2511
2325
  declare class SarvamTtsHttpStreamProvider implements TextToSpeechProvider {
@@ -2513,39 +2327,14 @@ declare class SarvamTtsHttpStreamProvider implements TextToSpeechProvider {
2513
2327
  readonly name: "sarvam-tts";
2514
2328
  readonly kind = "tts";
2515
2329
  readonly version = "0.1.0";
2516
- readonly capabilities: {
2517
- streaming: {
2518
- input: false;
2519
- output: true;
2520
- native: true;
2521
- };
2522
- cancellation: {
2523
- request: true;
2524
- output: true;
2525
- buffer: false;
2526
- truncation: false;
2527
- };
2528
- transports: "http"[];
2529
- audio: {
2530
- output: {
2531
- readonly encoding: "pcm_s16le";
2532
- readonly sampleRateHz: 16000;
2533
- readonly channels: 1;
2534
- }[];
2535
- };
2536
- languages: readonly ["hi-IN", "bn-IN", "ta-IN", "te-IN", "gu-IN", "kn-IN", "ml-IN", "mr-IN", "pa-IN", "od-IN", "en-IN"];
2537
- models: readonly ["bulbul:v3"];
2538
- voices: readonly ["shubh", "aditya", "ritu", "priya", "neha", "rahul", "pooja", "rohan", "simran", "kavya", "amit", "dev", "ishita", "shreya", "ratan", "varun", "manan", "sumit", "roopa", "kabir", "aayan", "ashutosh", "advait", "anand", "tanya", "tarun", "sunny", "mani", "gokul", "vijay", "shruti", "suhani", "mohit", "kavitha", "rehan", "soham", "rupali"];
2539
- metadata: {
2540
- transport: string;
2541
- endpoint: string;
2542
- requestTextLimit: number;
2543
- wireOutputCodec: string;
2544
- normalizedOutput: string;
2545
- documentation: string;
2546
- };
2547
- };
2330
+ readonly capabilities: ProviderCapabilities;
2548
2331
  constructor(options: SarvamTtsHttpProviderOptions);
2332
+ get configuredModel(): string;
2333
+ get configuredLanguage(): string;
2334
+ get languageWasExplicitlyConfigured(): boolean;
2335
+ get configuredVoice(): string | undefined;
2336
+ supportsVoice(voice: string, model?: string): boolean;
2337
+ supportsLanguage(language: string, model?: string): boolean;
2549
2338
  synthesize(request: TtsSynthesisRequest): Promise<TtsStream>;
2550
2339
  }
2551
2340
  declare function createSarvamTtsRestProvider(options: SarvamTtsHttpProviderOptions): SarvamTtsRestProvider;
@@ -2742,10 +2531,10 @@ declare const PROVIDER_CATALOG: {
2742
2531
  readonly models: readonly ["saaras:v3", "saaras:v4"];
2743
2532
  };
2744
2533
  readonly sarvamTts: {
2745
- readonly verifiedAt: "2026-09-25";
2746
- readonly source: "https://docs.sarvam.ai/api-reference/text-to-speech/convert";
2534
+ readonly verifiedAt: "2026-10-09";
2535
+ readonly source: "https://docs.sarvam.ai/api/getting-started/models/bulbul";
2747
2536
  readonly defaultModel: "bulbul:v3";
2748
- readonly models: readonly ["bulbul:v3"];
2537
+ readonly models: readonly ["bulbul:v3", "bulbul:v4-flash"];
2749
2538
  };
2750
2539
  readonly cartesia: {
2751
2540
  readonly verifiedAt: "2026-09-25";
@@ -3218,6 +3007,10 @@ declare class CartesiaTtsProvider implements IncrementalTextToSpeechProvider {
3218
3007
  models: readonly ["sonic-3.6", "sonic-3.6-2026-08-27", "sonic-preview", "sonic-3.5", "sonic-3.5-2026-05-04", "sonic-3", "sonic-3-2026-01-12"];
3219
3008
  };
3220
3009
  constructor(options: CartesiaTtsProviderOptions);
3010
+ get configuredModel(): string;
3011
+ get allowUnknownModel(): boolean;
3012
+ get configuredVoice(): string;
3013
+ get configuredLanguage(): string;
3221
3014
  synthesize(request: TtsSynthesisRequest): Promise<TtsStream>;
3222
3015
  openSession(request: TtsSessionOpenRequest): Promise<TtsSession>;
3223
3016
  }
@@ -3309,6 +3102,10 @@ declare class ElevenLabsTtsProvider implements IncrementalTextToSpeechProvider {
3309
3102
  models: readonly ["eleven_flash_v2_5", "eleven_flash_v2", "eleven_v3", "eleven_v3_conversational", "eleven_multilingual_v2", "eleven_turbo_v2_5", "eleven_turbo_v2"];
3310
3103
  };
3311
3104
  constructor(options: ElevenLabsTtsProviderOptions);
3105
+ get configuredModel(): string;
3106
+ get allowUnknownModel(): boolean;
3107
+ get configuredVoice(): string;
3108
+ get configuredLanguage(): string | undefined;
3312
3109
  synthesize(request: TtsSynthesisRequest): Promise<TtsStream>;
3313
3110
  openSession(request: TtsSessionOpenRequest): Promise<ElevenLabsTtsStream>;
3314
3111
  }
@@ -3317,9 +3114,7 @@ declare class ElevenLabsTtsStream implements TtsSession {
3317
3114
  readonly events: AsyncIterable<TtsEvent>;
3318
3115
  constructor(socket: WebSocket__default, request: TtsSessionOpenRequest, options: ElevenLabsStreamOptions);
3319
3116
  sendText(text: string, options?: ElevenLabsTtsSendTextOptions): Promise<void>;
3320
- /** Sends one incremental line in a Text-to-Dialogue session. */
3321
3117
  sendDialogueTurn(text: string, options?: ElevenLabsDialogueTurnOptions): Promise<void>;
3322
- /** Resets the provider receive timeout without causing a generation. */
3323
3118
  keepAlive(): Promise<void>;
3324
3119
  flush(): Promise<TtsFlushResult>;
3325
3120
  finish(): Promise<void>;
@@ -3355,7 +3150,6 @@ interface ElevenLabsDialogueSynthesisRequest extends Omit<TtsSynthesisRequest, "
3355
3150
  }
3356
3151
  interface ElevenLabsDialogueProvider extends TextToSpeechProvider {
3357
3152
  synthesizeDialogue(request: ElevenLabsDialogueSynthesisRequest): Promise<TtsStream>;
3358
- /** Forces the regular single-voice TTS HTTP endpoint, including for v3 models. */
3359
3153
  synthesizeSpeech(request: ElevenLabsTtsHttpSynthesisRequest): Promise<TtsStream>;
3360
3154
  }
3361
3155
  declare class ElevenLabsTtsRestProvider implements ElevenLabsDialogueProvider {
@@ -3365,6 +3159,10 @@ declare class ElevenLabsTtsRestProvider implements ElevenLabsDialogueProvider {
3365
3159
  readonly version = "0.1.0";
3366
3160
  readonly capabilities: ProviderCapabilities;
3367
3161
  constructor(options: ElevenLabsHttpTtsProviderOptions);
3162
+ get configuredModel(): string;
3163
+ get allowUnknownModel(): boolean;
3164
+ get configuredVoice(): string;
3165
+ get configuredLanguage(): string | undefined;
3368
3166
  get _httpOptions(): ElevenLabsHttpTtsProviderOptions;
3369
3167
  get _httpModelId(): string;
3370
3168
  get _httpAllowUnknownModel(): boolean;
@@ -3384,9 +3182,7 @@ declare class ElevenLabsTtsHttpStreamProvider extends ElevenLabsTtsRestProvider
3384
3182
  private executeStreamDialogue;
3385
3183
  private executeViaProtectedPath;
3386
3184
  }
3387
- /** The factory is the preferred entry point for complete HTTP responses. */
3388
3185
  declare function createElevenLabsTtsRestProvider(options: ElevenLabsHttpTtsProviderOptions): ElevenLabsTtsRestProvider;
3389
- /** The factory is the preferred entry point for chunked HTTP responses. */
3390
3186
  declare function createElevenLabsTtsHttpStreamProvider(options: ElevenLabsHttpTtsProviderOptions): ElevenLabsTtsHttpStreamProvider;
3391
3187
 
3392
3188
  /** The point at which the primary TTS provider became unavailable. */
@@ -3404,41 +3200,20 @@ interface TtsFailoverProviderOptions {
3404
3200
  readonly primary: TextToSpeechProvider;
3405
3201
  /** The provider used only after the failover policy accepts the error. */
3406
3202
  readonly fallback: TextToSpeechProvider;
3407
- /**
3408
- * Maps the primary request to the fallback provider's model and voice. The
3409
- * session, turn, signal, and output format must remain unchanged.
3410
- */
3203
+ /** Map provider-specific values; callers own their semantic equivalence. */
3411
3204
  readonly mapFallbackRequest?: (request: TtsSynthesisRequest, error: NormalizedError) => TtsSynthesisRequest;
3412
- /**
3413
- * Defaults to operational provider/network/timeout failures. Validation,
3414
- * authentication, protocol, identity, and cancellation errors do not fail
3415
- * over because retrying them on another provider usually hides a bug.
3416
- */
3205
+ /** Use only when the caller accepts a locale-to-language-code fallback mapping. */
3206
+ readonly languageMatch?: "exact" | "base-language";
3417
3207
  readonly shouldFallback?: (error: NormalizedError, request: TtsSynthesisRequest) => boolean;
3418
- /** Best-effort observability hook; observer failures never block fallback. */
3419
3208
  readonly onFallback?: (context: TtsFailoverContext) => void | PromiseLike<void>;
3420
3209
  readonly name?: string;
3421
3210
  }
3422
- /**
3423
- * Builds an explicit TTS failover provider for host-owned routing.
3424
- *
3425
- * Failover is attempted when the primary request fails before a stream is
3426
- * returned, or when its stream fails before any audio chunk is emitted. Once
3427
- * audio has been delivered, the original failure is propagated instead of
3428
- * replaying the whole response and risking duplicated speech.
3429
- */
3430
3211
  declare function createTtsFailoverProvider(options: TtsFailoverProviderOptions): TextToSpeechProvider;
3431
3212
 
3432
3213
  declare function bytesToBase64(bytes: Uint8Array): string;
3433
3214
  declare function base64ToBytes(value: string): Uint8Array;
3434
3215
  declare function mulawToPcm16le(mulaw: Uint8Array): Uint8Array;
3435
3216
  declare function pcm16leToMulaw(pcm: Uint8Array): Uint8Array;
3436
- /**
3437
- * v0.1 normalized audio is frozen to **pcm_s16le, mono**. The frame/duration/
3438
- * resample helpers below compute on interleaved-sample assumptions that only hold
3439
- * for a single channel, so a stereo format would silently corrupt timing. We
3440
- * reject it at the boundary rather than miscompute.
3441
- */
3442
3217
  declare function assertPcm16leFormat(format: AudioFormat): void;
3443
3218
  declare function resamplePcm16le(pcm: Uint8Array, fromSampleRateHz: number, toSampleRateHz: number): Uint8Array;
3444
3219
  declare function frameCountForPcm16le(bytes: Uint8Array): number;
@@ -3456,11 +3231,6 @@ declare class AsyncQueueConsumerError extends Error {
3456
3231
  }
3457
3232
  interface AsyncQueueOptions {
3458
3233
  readonly maxBuffered?: number;
3459
- /**
3460
- * Supplies the terminal error to deliver when a bounded queue is full. When
3461
- * omitted, `push()` keeps its non-throwing boolean-only contract and the
3462
- * caller remains responsible for handling `false`.
3463
- */
3464
3234
  readonly onOverflow?: () => unknown;
3465
3235
  }
3466
3236
  /**
@@ -3486,139 +3256,38 @@ interface AudioNormalizerOptions {
3486
3256
  interface AudioNormalizer {
3487
3257
  readonly inputFormat: AudioFormat;
3488
3258
  readonly outputFormat: AudioFormat;
3489
- /** Create an independent copy at the current sample-clock position. */
3490
3259
  fork(): AudioNormalizer;
3491
3260
  push(bytes: Uint8Array): Uint8Array;
3492
3261
  finishSegment(): Uint8Array;
3493
3262
  finish(): Uint8Array;
3494
3263
  }
3495
- /**
3496
- * Converts supported PCM source frames into PCM16LE mono while preserving
3497
- * sample-clock phase across arbitrary realtime chunk boundaries.
3498
- *
3499
- * The FIR is intentionally small and deterministic. It is causal with a
3500
- * bounded look-ahead: ordinary pushes emit only samples whose filter support is
3501
- * present, while an explicit segment/stream finish uses the final source sample
3502
- * as the endpoint. This prevents packet boundaries from becoming resampling
3503
- * boundaries.
3504
- */
3505
3264
  declare function createAudioNormalizer(options: AudioNormalizerOptions): AudioNormalizer;
3506
3265
 
3507
3266
  declare function isInputMediaEvent(event: MediaEvent): event is InputMediaEvent;
3508
3267
  declare function isOutputMediaEvent(event: MediaEvent): event is OutputMediaEvent;
3509
3268
 
3510
- /**
3511
- * A single param value or an array of repeated param values. Twilio sends
3512
- * each value as a separate URL-encoded occurrence in the POST body, so a
3513
- * key that appears N times in the request will appear N times here.
3514
- */
3515
3269
  type TwilioParamValue = string | readonly string[];
3516
- /**
3517
- * The set of POST parameters signed by Twilio. Twilio sorts by key (NOT by
3518
- * the order they appear in the body), and concatenates `key + value` for
3519
- * each entry, with no separator.
3520
- */
3521
3270
  type TwilioParams = Readonly<Record<string, TwilioParamValue>>;
3522
- /**
3523
- * The simplest form: a single string value per key. Most webhooks fit this
3524
- * shape; use `TwilioParams` directly only when you need to handle repeated
3525
- * keys.
3526
- */
3527
3271
  type TwilioFlatParams = Readonly<Record<string, string>>;
3528
3272
  interface VerifyTwilioOptions {
3529
- /** The X-Twilio-Signature header value. */
3530
3273
  readonly signature: string;
3531
- /** The full request URL (with query string). */
3532
3274
  readonly url: string;
3533
- /** The parsed POST params, as a key-value map. */
3534
3275
  readonly params: TwilioFlatParams | TwilioParams;
3535
- /**
3536
- * The Twilio auth token. Used as the HMAC key. Required.
3537
- *
3538
- * For token rotation, wrap the verifier yourself:
3539
- * const ok = verifyTwilioSignature({...authTokenA}) ||
3540
- * verifyTwilioSignature({...authTokenB});
3541
- */
3542
3276
  readonly authToken: string;
3543
3277
  }
3544
3278
  declare function canonicalizeTwilioData(url: string, params: TwilioFlatParams | TwilioParams): Buffer;
3545
- /**
3546
- * Compute the expected signature for a given auth token, URL, and params.
3547
- * Exposed for tests and golden fixtures. Production code should call
3548
- * `verifyTwilioSignature` instead.
3549
- */
3550
3279
  declare function computeTwilioSignature(authToken: string, url: string, params: TwilioFlatParams | TwilioParams): string;
3551
- /**
3552
- * Verify a Twilio X-Twilio-Signature header. Returns true if the signature
3553
- * matches the configured auth token.
3554
- *
3555
- * Returns false (does not throw) for malformed inputs:
3556
- * - missing or empty signature
3557
- * - signature is not valid base64 of length 28
3558
- * - signature decodes to a byte array that does not match the expected HMAC
3559
- *
3560
- * Throws (programmer error, not attacker error):
3561
- * - when `authToken` is empty string
3562
- *
3563
- * @remarks
3564
- * Twilio's signature does NOT include a timestamp or nonce. To prevent replay,
3565
- * the caller MUST enforce an idempotency check (e.g. dedupe by `CallSid` +
3566
- * `MessageSid` with a TTL).
3567
- *
3568
- * @example
3569
- * ```ts
3570
- * const sig = Array.isArray(req.headers["x-twilio-signature"])
3571
- * ? req.headers["x-twilio-signature"][0]
3572
- * : req.headers["x-twilio-signature"];
3573
- * const ok = verifyTwilioSignature({
3574
- * signature: sig,
3575
- * url: `https://example.com${req.url}`,
3576
- * params: parsedFormBody,
3577
- * authToken: process.env.TWILIO_AUTH_TOKEN!,
3578
- * });
3579
- * if (!ok) return new Response("invalid signature", { status: 403 });
3580
- * ```
3581
- */
3582
3280
  declare function verifyTwilioSignature(options: VerifyTwilioOptions): boolean;
3583
3281
 
3584
3282
  interface VerifyVoiceSessionTokenOptions {
3585
- /** The token from the WebSocket upgrade query string. */
3586
3283
  readonly token: string | null | undefined;
3587
- /** The expected session reference (e.g. "voice_<uuid>"). */
3588
3284
  readonly sessionRef: string;
3589
- /** The expiry as a string of non-negative integer milliseconds. */
3590
3285
  readonly exp: string | null | undefined;
3591
- /** The shared secret used to sign the token. */
3592
3286
  readonly secret: string;
3593
- /** Optional: current time in ms. Defaults to Date.now. Injected for tests. */
3594
3287
  readonly now?: () => number;
3595
- /**
3596
- * Optional: tolerance window in ms for the expiry check. Default 0.
3597
- * Use this if server and client clocks are skewed.
3598
- */
3599
3288
  readonly toleranceMs?: number;
3600
3289
  }
3601
- /**
3602
- * Compute the expected voice-session token for a given session ref
3603
- * and expiry. Exposed for tests and the example app's token generator.
3604
- */
3605
3290
  declare function signVoiceSessionToken(secret: string, sessionRef: string, expMs: number): string;
3606
- /**
3607
- * Verify a voice-session token. Returns true on success, false
3608
- * otherwise. Does NOT throw for invalid input — callers should branch
3609
- * on the boolean.
3610
- *
3611
- * @example
3612
- * ```ts
3613
- * const ok = verifyVoiceSessionToken({
3614
- * token: url.searchParams.get("token"),
3615
- * sessionRef: matchPathParams.url.sessionRef,
3616
- * exp: url.searchParams.get("exp"),
3617
- * secret: process.env.VOICE_TOKEN_SECRET!,
3618
- * });
3619
- * if (!ok) return new Response("invalid token", { status: 401 });
3620
- * ```
3621
- */
3622
3291
  declare function verifyVoiceSessionToken(options: VerifyVoiceSessionTokenOptions): boolean;
3623
3292
 
3624
3293
  type RuntimeProvider = TelephonyProvider | SpeechToTextProvider | TextToSpeechProvider | LLMProvider;
@@ -3628,7 +3297,7 @@ type ProviderForKind<K extends ProviderKind> = Extract<RuntimeProvider, {
3628
3297
  declare function isProviderKind<K extends ProviderKind>(provider: RuntimeProvider, kind: K): provider is ProviderForKind<K>;
3629
3298
  type AudioFormatDirection = "input" | "output";
3630
3299
  declare function supportsAudioFormat(provider: Provider, format: AudioFormat, direction: AudioFormatDirection): boolean;
3631
- declare function supportsLanguage(provider: Provider, language: string): boolean;
3300
+ declare function supportsLanguage(provider: Provider, language: string, model?: string): boolean;
3632
3301
  declare function supportsModel(provider: Provider, model: string): boolean;
3633
3302
  declare function supportsBatchModel(provider: Provider, model: string): boolean;
3634
3303
  declare function requireProviderKind<K extends ProviderKind>(provider: RuntimeProvider, kind: K): ProviderForKind<K>;
@@ -3643,6 +3312,10 @@ interface DefineToolInput<TInput, TOutput> {
3643
3312
  readonly timeout?: TimeoutPolicy;
3644
3313
  readonly retry?: RetryPolicy;
3645
3314
  readonly idempotency?: IdempotencyPolicy;
3315
+ /**
3316
+ * @deprecated This field is a no-op. Enforce authorization in `execute`
3317
+ * using `ctx.tenant?.scopes`.
3318
+ */
3646
3319
  readonly authScope?: readonly string[];
3647
3320
  readonly tags?: readonly string[];
3648
3321
  readonly metadata?: Readonly<Record<string, unknown>>;
@@ -3670,6 +3343,8 @@ declare function defineAgent(input: DefineAgentInput): Agent;
3670
3343
 
3671
3344
  declare function createRuntime(options?: RuntimeOptions): Runtime;
3672
3345
 
3346
+ declare function toRuntimeSessionTrace(event: SessionEndEvent): RuntimeSessionTrace;
3347
+
3673
3348
  interface ResolvePreCallContextInput {
3674
3349
  readonly memory: Memory;
3675
3350
  readonly resolver?: PreCallContextResolver;
@@ -3687,33 +3362,14 @@ interface ResolvePreCallContextInput {
3687
3362
  readonly maxEntries?: number;
3688
3363
  /** Maximum bytes rendered for the combined static and memory context. */
3689
3364
  readonly maxBytes?: number;
3690
- /**
3691
- * Optional provider of the static (non-memory) context. The default
3692
- * resolver returns an empty static map; the user-provided resolver
3693
- * (via `options.preCallContextResolver`) is the place to inject CRM,
3694
- * feature flags, and tenant config.
3695
- */
3696
3365
  readonly staticProvider?: () => Promise<ReadonlyMap<string, string>>;
3697
3366
  }
3698
3367
  declare function resolvePreCallContext(input: ResolvePreCallContextInput): Promise<PreCallContext>;
3699
- /**
3700
- * Format the pre-call context as a system-prompt block. Renders the
3701
- * `<memory>...</memory>` block and (if non-empty or degraded) the
3702
- * `<context>...</context>` block above it.
3703
- */
3704
3368
  declare function formatPreCallContextAsSystemBlock(context: PreCallContext, maxBytes?: number): string;
3705
- /**
3706
- * @deprecated Use `resolvePreCallContext` and `formatPreCallContextAsSystemBlock`.
3707
- * Kept for one compatibility release as a memory-only projection.
3708
- */
3369
+ /** @deprecated Use `resolvePreCallContext` and `formatPreCallContextAsSystemBlock`. */
3709
3370
  declare function resolvePreCallMemory(input: ResolvePreCallContextInput): Promise<PreCallMemoryContext>;
3710
3371
  declare function formatMemoryContextAsSystemBlock(context: PreCallMemoryContext, maxBytes?: number): string;
3711
3372
 
3712
- /**
3713
- * Fails before a live session starts when the configured memory adapter cannot
3714
- * provide the behavior the agent's policy promises. Memory adapters remain
3715
- * pluggable; the adapter's instance-level declaration is the source of truth.
3716
- */
3717
3373
  declare function assertMemoryPolicySupported(memory: Memory, policy: AgentMemoryPolicy): void;
3718
3374
  declare function assertMemoryCapability(memory: Memory, capability: "search.exact" | "write.explicit" | "write.implicit" | "write.sessionQuota" | "purge.perScope", operation: string): void;
3719
3375
 
@@ -3723,6 +3379,11 @@ interface SessionActivator {
3723
3379
  readonly agent: Agent;
3724
3380
  readonly attachment: SessionAttachment;
3725
3381
  }): Promise<void>;
3382
+ deactivate?(input: {
3383
+ readonly sessionId: SessionId;
3384
+ readonly agent: Agent;
3385
+ readonly attachment: SessionAttachment;
3386
+ }): Promise<void>;
3726
3387
  }
3727
3388
  interface SessionRecoveryCoordinatorOptions {
3728
3389
  readonly runtime: Runtime;
@@ -3738,6 +3399,7 @@ interface SessionRecoveryCoordinatorOptions {
3738
3399
  readonly name: string;
3739
3400
  readonly value: number;
3740
3401
  }) => void;
3402
+ readonly onError?: (error: unknown) => void;
3741
3403
  }
3742
3404
  interface RecoveryPollResult {
3743
3405
  readonly candidates: number;
@@ -3748,7 +3410,7 @@ declare class SessionRecoveryCoordinator {
3748
3410
  #private;
3749
3411
  constructor(options: SessionRecoveryCoordinatorOptions);
3750
3412
  start(): void;
3751
- stop(): Promise<void>;
3413
+ stop(): Promise<boolean>;
3752
3414
  pollOnce(): Promise<RecoveryPollResult>;
3753
3415
  }
3754
3416
  interface SessionReaperOptions {
@@ -3764,12 +3426,13 @@ interface SessionReaperOptions {
3764
3426
  readonly name: string;
3765
3427
  readonly value: number;
3766
3428
  }) => void;
3429
+ readonly onError?: (error: unknown) => void;
3767
3430
  }
3768
3431
  declare class SessionReaper {
3769
3432
  #private;
3770
3433
  constructor(options: SessionReaperOptions);
3771
3434
  start(): void;
3772
- stop(): Promise<void>;
3435
+ stop(): Promise<boolean>;
3773
3436
  reapOnce(): Promise<number>;
3774
3437
  }
3775
3438
 
@@ -3793,25 +3456,11 @@ declare class ConversationPolicy {
3793
3456
  #private;
3794
3457
  constructor(options: ConversationPolicyOptions);
3795
3458
  hydrateTurns(turns: readonly Turn[]): void;
3796
- /**
3797
- * Set the session-level system instruction. Pre-call context and variables
3798
- * remain attached because the system message is rebuilt from canonical state.
3799
- */
3800
3459
  replaceSystemInstruction(instruction: string): void;
3801
- /**
3802
- * Set or clear a per-turn instruction. Clearing it restores the session-level
3803
- * instruction without losing the tenant variables or pre-call context.
3804
- */
3805
3460
  setTurnSystemInstruction(instruction: string | undefined): void;
3806
- /**
3807
- * Replace the static variables map. Values are substituted into `{{name}}`
3808
- * placeholders and also rendered in a dedicated block so the model can see
3809
- * variables that the base instruction did not reference explicitly.
3810
- */
3811
3461
  setStaticVariables(variables: ReadonlyMap<string, string>): void;
3812
3462
  acceptTranscript(event: TranscriptEvent): string | null;
3813
3463
  get hasBufferedTranscript(): boolean;
3814
- /** Commits buffered final segments for an endpoint, timeout, or stream shutdown. */
3815
3464
  flushBufferedTranscript(): string | null;
3816
3465
  messagesForTranscript(transcript: string): readonly LlmMessage[];
3817
3466
  messagesForToolContinuation(messages: readonly LlmMessage[], assistantText: string, toolMessages: readonly LlmMessage[], assistantToolCalls?: readonly LlmInlineToolCall[]): readonly LlmMessage[];
@@ -3823,13 +3472,9 @@ declare class ConversationPolicy {
3823
3472
  interface SttCommandController {
3824
3473
  /** Resolves only when this controller reaches a terminal state. */
3825
3474
  readonly failure: Promise<never>;
3826
- /** Admit audio without waiting for provider I/O. */
3827
3475
  admitAudio(chunk: InputAudioChunk): Promise<void>;
3828
- /** Admit an ordered barrier and settle it after provider command acceptance. */
3829
3476
  admitCommit(): Promise<void>;
3830
- /** Drain admitted commands in order and then close the stream. */
3831
3477
  drain(): Promise<void>;
3832
- /** Abandon queued work and close the stream immediately. */
3833
3478
  abort(error?: unknown): Promise<void>;
3834
3479
  }
3835
3480
 
@@ -3859,11 +3504,6 @@ interface SttReconnectOptions {
3859
3504
  readonly audioWriteTimeoutMs?: number;
3860
3505
  readonly closeTimeoutMs?: number;
3861
3506
  }
3862
- /**
3863
- * Wraps one STT provider with bounded, best-effort reconnect and replay policy.
3864
- * The wrapper is deliberately runtime-owned: adapters only need to expose honest
3865
- * transport and timestamp semantics.
3866
- */
3867
3507
  declare function withSttReconnect(provider: SpeechToTextProvider, options?: SttReconnectOptions): SpeechToTextProvider;
3868
3508
 
3869
3509
  interface AssistantTextRecord {
@@ -3883,7 +3523,6 @@ interface TextDeliveryDecision {
3883
3523
  readonly hasTransport: boolean;
3884
3524
  readonly cancelledByBargeIn: boolean;
3885
3525
  }
3886
- /** Decides whether participant-visible text should be attempted for a terminal turn. */
3887
3526
  declare function shouldDeliverText(decision: TextDeliveryDecision): boolean;
3888
3527
  declare function deliverAssistantText(options: {
3889
3528
  readonly callHandle: CallHandle;
@@ -3896,16 +3535,6 @@ declare function deliverAssistantText(options: {
3896
3535
  readonly timeoutMs?: number;
3897
3536
  }): Promise<boolean | undefined>;
3898
3537
 
3899
- /**
3900
- * Public-facing event emitted by a voice pipeline run. A discriminated
3901
- * union of 8 kinds so consumers can `switch (event.kind)` without
3902
- * runtime guessing.
3903
- *
3904
- * The shape is intentionally a *friendlier* view than the internal
3905
- * `MediaEvent`. The runtime's `MediaEvent` includes IDs, sequence
3906
- * numbers, and provider metadata; `VoiceEvent` strips those and exposes
3907
- * the same data in a UX-friendly form.
3908
- */
3909
3538
  type VoiceEvent = {
3910
3539
  readonly kind: "transcript_delta";
3911
3540
  readonly text: string;
@@ -3925,6 +3554,7 @@ type VoiceEvent = {
3925
3554
  readonly turnId: TurnId;
3926
3555
  readonly status: "completed" | "cancelled" | "failed";
3927
3556
  readonly latencyMs: number;
3557
+ readonly delivery?: TurnOutputDelivery;
3928
3558
  } | {
3929
3559
  readonly kind: "tool_call";
3930
3560
  readonly toolCallId: ToolCallId;
@@ -3934,6 +3564,9 @@ type VoiceEvent = {
3934
3564
  readonly kind: "tool_result";
3935
3565
  readonly toolCallId: ToolCallId;
3936
3566
  readonly output: unknown;
3567
+ readonly status: "succeeded" | "failed" | "timed_out" | "cancelled";
3568
+ readonly error?: Pick<NormalizedError, "code" | "message">;
3569
+ readonly recoveryPolicy?: "do_not_replay";
3937
3570
  readonly latencyMs: number;
3938
3571
  } | {
3939
3572
  readonly kind: "error";
@@ -3944,26 +3577,11 @@ type VoiceEvent = {
3944
3577
  readonly reason: "completed" | "cancelled" | "failed" | "remote_hangup";
3945
3578
  readonly totalTurns: number;
3946
3579
  };
3947
- /**
3948
- * The result of starting a `PipelineVoiceLoop`. Dual-protocol: awaits
3949
- * to a final `PipelineVoiceLoopResult` with an explicit terminal reason and
3950
- * source, AND iterates the per-event
3951
- * stream.
3952
- *
3953
- * Implementation note: the class implements both `PromiseLike<PipelineVoiceLoopResult>`
3954
- * and `AsyncIterable<VoiceEvent>`. Awaiting and iterating are independent
3955
- * — the run starts on the first await/iteration. Subsequent awaits share
3956
- * the same promise. Iteration drains buffered events before completing.
3957
- */
3958
3580
  interface DualProtocolResult extends PromiseLike<PipelineVoiceLoopResult> {
3959
3581
  then<TResult1 = PipelineVoiceLoopResult, TResult2 = never>(onfulfilled?: ((value: PipelineVoiceLoopResult) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined): PromiseLike<TResult1 | TResult2>;
3960
3582
  catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null | undefined): PromiseLike<PipelineVoiceLoopResult | TResult>;
3961
3583
  finally(onfinally?: (() => void) | null | undefined): PromiseLike<PipelineVoiceLoopResult>;
3962
3584
  [Symbol.asyncIterator](): AsyncIterator<VoiceEvent>;
3963
- /**
3964
- * The session ID this result is for. Exposed for consumer convenience
3965
- * (e.g., logging).
3966
- */
3967
3585
  readonly sessionId: SessionId;
3968
3586
  }
3969
3587
  /**
@@ -3991,12 +3609,6 @@ type PipelineVoiceLoopResultLike = PipelineVoiceLoopResult;
3991
3609
  declare class PipelineVoiceLoopBuilder {
3992
3610
  #private;
3993
3611
  constructor(loop: PipelineVoiceLoopLike, overrideSignal?: AbortSignal);
3994
- /**
3995
- * Attach an `AbortSignal` that cancels the run when triggered. Composed
3996
- * with `attachment.signal` (both fire to cancel; the lease-loss reason
3997
- * on the attachment is preserved). Throws if called twice on the same
3998
- * builder.
3999
- */
4000
3612
  abortSignal(signal: AbortSignal): this;
4001
3613
  then<TResult1 = PipelineVoiceLoopResultLike, TResult2 = never>(onfulfilled?: ((value: PipelineVoiceLoopResultLike) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined): PromiseLike<TResult1 | TResult2>;
4002
3614
  catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null | undefined): PromiseLike<PipelineVoiceLoopResultLike | TResult>;
@@ -4013,7 +3625,6 @@ interface PipelineVoiceLoopLike {
4013
3625
  _startInternal(options: {
4014
3626
  readonly overrideSignal?: AbortSignal;
4015
3627
  readonly consumer?: "internal" | "public";
4016
- /** Internal lifecycle hook; does not observe or assimilate the thenable. */
4017
3628
  readonly onRunPromise?: (promise: Promise<PipelineVoiceLoopResult>) => void;
4018
3629
  }): DualProtocolResult;
4019
3630
  }
@@ -4037,7 +3648,6 @@ interface PipelineVoiceLoopOptions {
4037
3648
  readonly callHandle: CallHandle;
4038
3649
  readonly llmModel: string;
4039
3650
  readonly sttModel?: string;
4040
- /** Allows a custom/self-hosted STT endpoint to accept a model outside TVIC's dated catalog. */
4041
3651
  readonly sttAllowUnknownModel?: boolean;
4042
3652
  readonly sttReconnect?: boolean | SttReconnectOptions;
4043
3653
  readonly sttLanguage?: string;
@@ -4052,19 +3662,10 @@ interface PipelineVoiceLoopOptions {
4052
3662
  readonly preCallContext?: PreCallContext;
4053
3663
  readonly safetyIdentifier?: string;
4054
3664
  readonly textDelivery?: TextDeliveryMode;
4055
- /** Max ms a provider stream may stall (no events) before the turn fails. */
4056
3665
  readonly streamStallTimeoutMs?: number;
4057
- /** Inactivity debounce after the latest immutable final segment. */
4058
3666
  readonly turnEndpointTimeoutMs?: number;
4059
- /** Absolute cap from the first immutable final segment in one utterance. */
4060
3667
  readonly turnMaxDurationMs?: number;
4061
- /** Optional managed-owner source for an external cancellation signal. */
4062
3668
  readonly terminalSourceForCancellation?: () => LiveTerminalSource | undefined;
4063
- /**
4064
- * Receives one record per terminal turn. This is an observation seam, not part of
4065
- * execution: it is invoked after the turn is already terminal, its return value is
4066
- * ignored, and a throw from it is swallowed so an observer can never affect a call.
4067
- */
4068
3669
  readonly onTurnLatency?: (record: TurnLatencyRecord) => void;
4069
3670
  readonly onAssistantText?: (record: AssistantTextRecord) => void;
4070
3671
  readonly sessionMetricsRecorder?: SessionMetricsRecorder;
@@ -4076,45 +3677,21 @@ interface PipelineVoiceLoopResult {
4076
3677
  readonly interruptions: number;
4077
3678
  readonly turnsFailed: number;
4078
3679
  readonly firstTurnError: NormalizedError | null;
4079
- /**
4080
- * Terminal reason for RESOLVED runs (additive; existing readers ignore it).
4081
- * Precedence: cancelled (explicit cancel/abort won) > failed (one or more
4082
- * failed turns, or a timeout/error stream end) > remote_hangup >
4083
- * completed. Rejected runs carry their terminal in the rejection instead;
4084
- * unified cancel/remote arbitration with scheduler batches is joint T1
4085
- * work — this field reports the resolved outcome only.
4086
- */
4087
3680
  readonly terminalReason: PipelineVoiceLoopTerminalReason;
4088
3681
  readonly terminalSource: LiveTerminalSource;
4089
3682
  }
4090
- /**
4091
- * Runs a pipeline voice session: media -> STT -> LLM/tools -> TTS -> media.
4092
- * This module owns only live execution and failure handling; telemetry belongs
4093
- * outside the runtime's critical path.
4094
- */
4095
3683
  declare class PipelineVoiceLoop {
4096
3684
  #private;
4097
3685
  constructor(options: PipelineVoiceLoopOptions);
4098
- /** Start a call and expose an awaitable, iterable result. */
4099
3686
  start(options?: {
4100
3687
  readonly overrideSignal?: AbortSignal;
4101
3688
  }): PipelineVoiceLoopBuilder;
4102
- /**
4103
- * Legacy: returns `Promise<PipelineVoiceLoopResult>`. Equivalent to
4104
- * `await this.start(options)`. Convenience wrapper preserved for backward
4105
- * compatibility with the v0.0.x API.
4106
- */
4107
3689
  run(options?: {
4108
3690
  readonly overrideSignal?: AbortSignal;
4109
3691
  }): Promise<PipelineVoiceLoopResult>;
4110
- /**
4111
- * Implementation hook for {@link PipelineVoiceLoopBuilder}. Returns a
4112
- * `DualProtocolResult` that wraps the run promise and event queue.
4113
- */
4114
3692
  _startInternal(options: {
4115
3693
  readonly overrideSignal?: AbortSignal;
4116
3694
  readonly consumer?: "internal" | "public";
4117
- /** Internal lifecycle hook used by managed wrappers without thenable assimilation. */
4118
3695
  readonly onRunPromise?: (promise: Promise<PipelineVoiceLoopResult>) => void;
4119
3696
  }): DualProtocolResult;
4120
3697
  }
@@ -4202,36 +3779,28 @@ interface NodeMediaPlaneConnection<TContext = unknown> {
4202
3779
  readonly upgradeContext?: TContext;
4203
3780
  }
4204
3781
  type NodeMediaPlaneConnectionHandler<TContext = unknown> = (connection: NodeMediaPlaneConnection<TContext>) => Promise<void> | void;
4205
- type NodeMediaPlaneRequestHandler = (request: IncomingMessage, response: ServerResponse) => boolean | Promise<boolean>;
3782
+ type NodeMediaPlaneRequestHandler = (request: IncomingMessage, response: ServerResponse, signal: AbortSignal) => boolean | Promise<boolean>;
4206
3783
  type NodeMediaPlaneConnectionErrorHandler = (error: unknown, socket: WebSocket__default) => void | Promise<void>;
4207
3784
  interface NodeMediaPlaneOptions<TContext = unknown> {
4208
3785
  readonly host?: string;
4209
3786
  readonly port: number;
4210
3787
  readonly path: string;
4211
- /** Maximum inbound WebSocket frame accepted before the connection is closed. */
4212
3788
  readonly maxInboundFrameBytes?: number;
3789
+ readonly maxInboundFrameFragments?: number;
3790
+ readonly webSocketCloseTimeoutMs?: number;
4213
3791
  readonly healthPath?: string;
4214
- /**
4215
- * Optional health check. Called when the plane's `healthPath` endpoint
4216
- * is hit. The plane responds 200 with `{ ok: true }` if the check
4217
- * returns `ok: true`, and 503 with the check details otherwise. This
4218
- * is where the runtime's `RuntimeOptions.healthCheck` plugs in so
4219
- * the load balancer can drain traffic before a replica's Postgres
4220
- * becomes unreachable. See `docs/operations/multi-replica.md`.
4221
- */
4222
- readonly healthCheck?: () => Promise<{
3792
+ readonly healthCheck?: (signal: AbortSignal) => Promise<{
4223
3793
  readonly ok: boolean;
4224
3794
  readonly checks?: Readonly<Record<string, unknown>>;
4225
3795
  }>;
4226
3796
  readonly onConnection: NodeMediaPlaneConnectionHandler<TContext>;
4227
- /** Handle non-WebSocket HTTP requests (e.g. the Twilio TwiML webhook). Return true if handled. */
4228
3797
  readonly onRequest?: NodeMediaPlaneRequestHandler;
4229
- /** Routes failures from an async onConnection handler. Defaults to closing the socket. */
4230
3798
  readonly onConnectionError?: NodeMediaPlaneConnectionErrorHandler;
4231
- /** Synchronous, pre-handshake authorization. Throwing rejects with HTTP 500. */
4232
- readonly authorizeUpgrade?: (request: IncomingMessage, url: URL, params: Readonly<Record<string, string>>) => UpgradeAuthorization<TContext>;
4233
- /** Releases state reserved by a successful authorization if the handshake aborts. */
4234
- readonly onUpgradeAborted?: (context: TContext) => void;
3799
+ readonly authorizeUpgrade?: (request: IncomingMessage, url: URL, params: Readonly<Record<string, string>>, signal: AbortSignal) => UpgradeAuthorization<TContext> | PromiseLike<UpgradeAuthorization<TContext>>;
3800
+ readonly authorizationTimeoutMs?: number;
3801
+ readonly maxPendingAuthorizations?: number;
3802
+ readonly onUpgradeAborted?: (context: TContext) => void | PromiseLike<void>;
3803
+ readonly onUpgradeAbortedError?: (error: unknown, context: TContext) => void | PromiseLike<void>;
4235
3804
  }
4236
3805
  declare class NodeMediaPlane<TContext = unknown> {
4237
3806
  #private;
@@ -4280,7 +3849,6 @@ type OpenAiProviderConfig = Omit<OpenAiResponsesLlmProviderOptions, "apiKey"> &
4280
3849
  readonly provider: "openai" | "openai-responses";
4281
3850
  readonly apiKey?: string;
4282
3851
  readonly model?: string;
4283
- /** Allows a custom OpenAI-compatible endpoint to use a model outside TVIC's dated catalog. */
4284
3852
  readonly allowUnknownModel?: boolean;
4285
3853
  };
4286
3854
  type GroqProviderConfig = Omit<GroqChatLlmProviderOptions, "apiKey"> & {
@@ -4348,7 +3916,6 @@ interface CreateVoiceAgentOptions {
4348
3916
  readonly version?: string;
4349
3917
  readonly providers: VoiceAgentProviders;
4350
3918
  readonly models?: VoiceAgentModels;
4351
- /** Tool generics are intentionally erased at the heterogeneous agent boundary. */
4352
3919
  readonly tools?: readonly ToolDefinition<any, any>[];
4353
3920
  readonly audio?: Partial<AgentAudioPolicy>;
4354
3921
  readonly memoryPolicy?: AgentMemoryPolicy;
@@ -4357,13 +3924,7 @@ interface CreateVoiceAgentOptions {
4357
3924
  readonly runtime?: RuntimeOptions;
4358
3925
  }
4359
3926
  interface VoiceAgentRunOptions {
4360
- /**
4361
- * A handle created by a stable TVIC transport adapter or a custom adapter.
4362
- * A factory is useful for transports whose events must be stamped with the
4363
- * runtime-created session id; it runs after the session is created.
4364
- */
4365
3927
  readonly callHandle: CallHandle | VoiceAgentCallHandleFactory;
4366
- /** Optional complete call record. A safe inbound record is synthesized when omitted. */
4367
3928
  readonly call?: Call;
4368
3929
  readonly channel?: ChannelKind;
4369
3930
  readonly variables?: Readonly<Record<string, unknown>>;
@@ -4372,7 +3933,6 @@ interface VoiceAgentRunOptions {
4372
3933
  readonly organizationId?: OrganizationId;
4373
3934
  readonly workflowId?: WorkflowId;
4374
3935
  readonly signal?: AbortSignal;
4375
- /** Maximum time allowed to start the runtime, attach the call, and create the run. */
4376
3936
  readonly startupTimeoutMs?: number;
4377
3937
  readonly safetyIdentifier?: string;
4378
3938
  readonly sttReconnect?: boolean | SttReconnectOptions;
@@ -4384,10 +3944,8 @@ interface VoiceAgentRunOptions {
4384
3944
  }
4385
3945
  interface VoiceAgentCallHandleContext {
4386
3946
  readonly sessionId: SessionId;
4387
- /** A deeply frozen copy of the validated call supplied to start(). */
4388
3947
  readonly call: CallSnapshot;
4389
3948
  readonly channel: ChannelKind;
4390
- /** Aborts when the caller, startup deadline, or global agent shutdown wins. */
4391
3949
  readonly signal: AbortSignal;
4392
3950
  }
4393
3951
  type VoiceAgentCallHandleFactory = (context: VoiceAgentCallHandleContext) => CallHandle | PromiseLike<CallHandle>;
@@ -4397,6 +3955,11 @@ interface VoiceAgentSession {
4397
3955
  readonly sessionId: SessionId;
4398
3956
  readonly run: VoiceAgentRun;
4399
3957
  }
3958
+ interface ManagedVoiceAgentSession extends VoiceAgentSession {
3959
+ readonly finalSession: Promise<TerminalSession>;
3960
+ complete(): Promise<TerminalSession>;
3961
+ stop(): Promise<void>;
3962
+ }
4400
3963
  interface VoiceAgentProviderNames {
4401
3964
  readonly telephony: string;
4402
3965
  readonly stt: string;
@@ -4413,7 +3976,10 @@ interface VoiceAgent {
4413
3976
  stop(): Promise<void>;
4414
3977
  healthCheck(): Promise<HealthSnapshot>;
4415
3978
  }
4416
- declare function createVoiceAgent(options: CreateVoiceAgentOptions): VoiceAgent;
3979
+ interface VoiceAgentWithSessionLifecycle extends VoiceAgent {
3980
+ start(options: VoiceAgentRunOptions): Promise<ManagedVoiceAgentSession>;
3981
+ }
3982
+ declare function createVoiceAgent(options: CreateVoiceAgentOptions): VoiceAgentWithSessionLifecycle;
4417
3983
 
4418
3984
  declare class InMemorySessionStore implements SessionStore {
4419
3985
  #private;
@@ -4422,7 +3988,6 @@ declare class InMemorySessionStore implements SessionStore {
4422
3988
  put(record: StoredSessionRecord): Promise<void>;
4423
3989
  update(id: SessionId, updater: (record: StoredSessionRecord) => StoredSessionRecord): Promise<StoredSessionRecord>;
4424
3990
  close(): Promise<void>;
4425
- /** Internal aggregate-transaction rollback hook. */
4426
3991
  restore(id: SessionId, record: StoredSessionRecord | null): void;
4427
3992
  }
4428
3993
  declare function createInMemorySessionStore(): InMemorySessionStore;
@@ -4433,7 +3998,6 @@ declare class InMemoryTurnStore implements TurnStore {
4433
3998
  put(record: StoredTurnRecord): Promise<void>;
4434
3999
  update(sessionId: SessionId, id: TurnId, updater: (record: StoredTurnRecord) => StoredTurnRecord): Promise<StoredTurnRecord>;
4435
4000
  close(): Promise<void>;
4436
- /** Internal aggregate-transaction rollback hook. */
4437
4001
  restore(sessionId: SessionId, records: readonly StoredTurnRecord[]): void;
4438
4002
  }
4439
4003
  declare function createInMemoryTurnStore(): InMemoryTurnStore;
@@ -4444,7 +4008,6 @@ declare class InMemoryToolCallStore implements ToolCallStore {
4444
4008
  put(record: StoredToolCallRecord): Promise<void>;
4445
4009
  update(sessionId: SessionId, id: ToolCallId, updater: (record: StoredToolCallRecord) => StoredToolCallRecord): Promise<StoredToolCallRecord>;
4446
4010
  close(): Promise<void>;
4447
- /** Internal aggregate-transaction rollback hook. */
4448
4011
  restore(sessionId: SessionId, records: readonly StoredToolCallRecord[]): void;
4449
4012
  }
4450
4013
  declare function createInMemoryToolCallStore(): InMemoryToolCallStore;
@@ -4452,33 +4015,28 @@ declare class InMemorySessionLeaseStore implements SessionLeaseStore {
4452
4015
  #private;
4453
4016
  constructor(now?: () => number);
4454
4017
  acquire(sessionId: SessionId, holder: string, ttlMs: number): Promise<SessionLease | null>;
4455
- renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number): Promise<SessionLease | null>;
4456
- release(sessionId: SessionId, holder: string, fence: number): Promise<void>;
4018
+ renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number, generationId: string): Promise<SessionLease | null>;
4019
+ release(sessionId: SessionId, holder: string, fence: number, generationId: string): Promise<void>;
4020
+ getCurrent(sessionId: SessionId): SessionLease | null;
4457
4021
  get(sessionId: SessionId): Promise<SessionLease | null>;
4458
4022
  listRecoveryCandidates(options: {
4459
4023
  readonly nowMs: number;
4460
4024
  readonly limit: number;
4461
4025
  readonly cursor?: string;
4462
4026
  }): Promise<{
4463
- readonly sessionIds: readonly SessionId[];
4027
+ readonly candidates: readonly SessionRecoveryCandidate[];
4464
4028
  readonly nextCursor?: string;
4465
4029
  }>;
4030
+ acknowledgeRecoveryCandidate(candidate: SessionRecoveryCandidate): Promise<void>;
4466
4031
  close(): Promise<void>;
4467
4032
  }
4468
4033
 
4469
4034
  interface InMemoryDurableRuntimeStore extends DurableRuntimeStore {
4470
4035
  readonly outbox: readonly DurableOutboxEvent[];
4036
+ currentLease(sessionId: SessionId): SessionLease | null;
4471
4037
  }
4472
4038
  interface InMemoryDurableRuntimeStoreOptions {
4473
4039
  readonly nowMs?: () => number;
4474
- /**
4475
- * Legacy stores can be supplied while callers migrate to DurableRuntimeStore.
4476
- * The aggregate transaction facade serializes access to them and uses the
4477
- * optional internal restore hooks when the store provides one. Custom stores
4478
- * without those hooks receive ordering isolation but cannot receive a full
4479
- * rollback guarantee; production adapters should implement DurableRuntimeStore
4480
- * directly when atomicity is required.
4481
- */
4482
4040
  readonly sessionStore?: SessionStore;
4483
4041
  readonly turnStore?: TurnStore;
4484
4042
  readonly toolCallStore?: ToolCallStore;
@@ -4506,78 +4064,57 @@ declare class InMemoryMemory implements Memory {
4506
4064
  }
4507
4065
  declare function createInMemoryMemory(options?: InMemoryMemoryOptions): InMemoryMemory;
4508
4066
 
4067
+ declare function idempotencyKeyFor<TInput, TOutput>(input: ExecuteToolInput<TInput, TOutput>): string | null;
4068
+ declare function idempotencyRequestHashFor<TInput, TOutput>(input: ExecuteToolInput<TInput, TOutput>): string;
4069
+
4509
4070
  declare function stableStringify(value: unknown): string;
4510
4071
 
4511
4072
  interface SchemaValidationResult {
4512
4073
  readonly valid: boolean;
4513
4074
  readonly errors: readonly string[];
4514
4075
  }
4515
- /**
4516
- * Validates a value against a deliberately small, well-defined subset of JSON Schema
4517
- * (Draft-07 keywords): `type` (incl. "integer"), `enum`, `const`, object
4518
- * `properties` / `required` / `additionalProperties: false`, array `items` /
4519
- * `minItems` / `maxItems`, string `minLength` / `maxLength`, and numeric `minimum` /
4520
- * `maximum`. It is intentionally NOT a full validator: unsupported keywords are
4521
- * ignored. Swap in Ajv at the call site if full JSON Schema compliance is required.
4522
- */
4523
4076
  declare function validateJsonSchemaSubset(value: unknown, schema: Readonly<Record<string, unknown>>, path?: string): SchemaValidationResult;
4524
4077
 
4078
+ type InMemoryLeaseSnapshot = {
4079
+ readonly holder: string;
4080
+ readonly fence: number;
4081
+ readonly generationId: string;
4082
+ readonly expiresAtMs: number;
4083
+ };
4084
+ declare class InMemoryToolIdempotencyStore implements ToolIdempotencyStore {
4085
+ #private;
4086
+ constructor(now?: () => number, readLeaseSnapshot?: (sessionId: SessionId) => InMemoryLeaseSnapshot | null);
4087
+ pruneExpired(): number;
4088
+ lookup(key: string, requestHash: string, sessionId?: SessionId, lease?: ToolIdempotencyLease): Promise<ToolIdempotencyLookupResult>;
4089
+ claim(input: ToolIdempotencyClaim): Promise<ToolIdempotencyClaimResult>;
4090
+ releaseClaim(input: ToolIdempotencyRelease): Promise<boolean>;
4091
+ complete(key: string, requestHash: string, outcome: ToolIdempotencyOutcome): Promise<void>;
4092
+ quarantine(input: ToolIdempotencyQuarantine): Promise<ToolIdempotencyQuarantineResult>;
4093
+ }
4094
+
4525
4095
  interface ToolRegistry {
4526
4096
  register(tool: ToolDefinition): void;
4527
4097
  get(id: ToolId): ToolDefinition | null;
4528
4098
  list(): readonly ToolDefinition[];
4529
4099
  }
4530
4100
  declare function createToolRegistry(tools?: readonly ToolDefinition[]): ToolRegistry;
4531
- declare class InMemoryToolIdempotencyStore implements ToolIdempotencyStore {
4532
- #private;
4533
- constructor(now?: () => number, readLease?: (sessionId: SessionId) => Promise<{
4534
- readonly holder: string;
4535
- readonly fence: number;
4536
- readonly expiresAtMs: number;
4537
- } | null>);
4538
- lookup(key: string, requestHash: string): Promise<ToolIdempotencyRecord | null>;
4539
- claim(input: ToolIdempotencyClaim): Promise<ToolIdempotencyClaimResult>;
4540
- complete(key: string, requestHash: string, outcome: ToolIdempotencyOutcome): Promise<void>;
4541
- }
4101
+
4542
4102
  interface ExecuteToolInput<TInput, TOutput> {
4543
4103
  readonly tool: ToolDefinition<TInput, TOutput>;
4544
4104
  readonly input: TInput;
4545
4105
  readonly sessionId: SessionId;
4546
4106
  readonly turnId: TurnId;
4547
4107
  readonly toolCallId: ToolCallId;
4548
- /** Reuses the durable queue timestamp when the runtime has already persisted the call. */
4549
4108
  readonly queuedAt?: Timestamp;
4550
4109
  readonly attempt?: number;
4551
4110
  readonly logger?: ToolLogger;
4552
4111
  readonly now?: () => Date;
4553
- /** Aborts the tool call (e.g. on barge-in). The tool's ctx.signal mirrors this. */
4554
4112
  readonly signal?: AbortSignal;
4555
- /** Current process lease used to fence durable idempotency operations. */
4556
4113
  readonly lease?: ToolIdempotencyLease;
4557
- /** Honours the tool's idempotency policy when provided. */
4558
4114
  readonly idempotencyStore?: ToolIdempotencyStore;
4559
- /**
4560
- * Tenant identity propagated into the tool's `ctx.tenant`. The runtime
4561
- * populates this from the session attachment's `memoryUserId` /
4562
- * `organizationId` / `workflowId` so the tool can enforce its own
4563
- * auth/RBAC. TVIC ships no auth layer; the tool author reads
4564
- * `ctx.tenant` and decides.
4565
- */
4566
4115
  readonly tenant?: ToolTenant;
4567
4116
  }
4568
- /**
4569
- * Performs the input checks that must complete before a tool call reaches a
4570
- * durable store. Keeping this at the tools boundary lets the runtime reject
4571
- * provider-produced values before it creates queued/running records.
4572
- */
4573
4117
  declare function toolInputError(value: unknown, schema: Readonly<Record<string, unknown>>): NormalizedError | null;
4574
- declare function idempotencyKeyFor<TInput, TOutput>(input: ExecuteToolInput<TInput, TOutput>): string | null;
4575
- /**
4576
- * The request hash paired with idempotencyKeyFor. Keep this beside the key
4577
- * builder so execution and crash recovery cannot silently hash different
4578
- * request shapes.
4579
- */
4580
- declare function idempotencyRequestHashFor<TInput, TOutput>(input: ExecuteToolInput<TInput, TOutput>): string;
4581
4118
  declare function executeTool<TInput = unknown, TOutput = unknown>(input: ExecuteToolInput<TInput, TOutput>): Promise<ToolCall>;
4582
4119
 
4583
4120
  interface PersistedErrorCompatibilityDiagnostic {
@@ -4595,9 +4132,31 @@ declare class PostgresToolIdempotencyStore implements ToolIdempotencyStore {
4595
4132
  constructor(client: SqlClient$1, options?: {
4596
4133
  readonly onCompatibilityDiagnostic?: (diagnostic: PersistedErrorCompatibilityDiagnostic) => void;
4597
4134
  });
4598
- lookup(key: string, requestHash: string): Promise<ToolIdempotencyRecord | null>;
4135
+ lookup(key: string, requestHash: string, sessionId?: SessionId, lease?: NonNullable<ToolIdempotencyClaim["lease"]>): Promise<ToolIdempotencyLookupResult>;
4599
4136
  claim(input: ToolIdempotencyClaim): Promise<ToolIdempotencyClaimResult>;
4137
+ releaseClaim(input: ToolIdempotencyRelease): Promise<boolean>;
4600
4138
  complete(key: string, requestHash: string, outcome: ToolIdempotencyOutcome): Promise<void>;
4139
+ quarantine(input: ToolIdempotencyQuarantine): Promise<ToolIdempotencyQuarantineResult>;
4140
+ }
4141
+
4142
+ declare class PostgresSessionLeaseStore implements SessionLeaseStore {
4143
+ readonly client: SqlPool$1;
4144
+ constructor(client: SqlPool$1);
4145
+ acquire(sessionId: SessionId, holder: string, ttlMs: number): Promise<SessionLease | null>;
4146
+ renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number, generationId: string): Promise<SessionLease | null>;
4147
+ release(sessionId: SessionId, holder: string, fence: number, generationId: string): Promise<void>;
4148
+ get(sessionId: SessionId): Promise<SessionLease | null>;
4149
+ listRecoveryCandidates(options: {
4150
+ readonly nowMs: number;
4151
+ readonly limit: number;
4152
+ readonly cursor?: string;
4153
+ }): Promise<{
4154
+ readonly candidates: readonly SessionRecoveryCandidate[];
4155
+ readonly corruptLeaseSessionIds?: readonly SessionId[];
4156
+ readonly nextCursor?: string;
4157
+ }>;
4158
+ acknowledgeRecoveryCandidate(candidate: SessionRecoveryCandidate): Promise<void>;
4159
+ close(): Promise<void>;
4601
4160
  }
4602
4161
 
4603
4162
  interface PostgresOutboxWorkerOptions {
@@ -4612,12 +4171,37 @@ interface PostgresOutboxWorkerOptions {
4612
4171
  }) => void;
4613
4172
  }
4614
4173
 
4174
+ interface PostgresRetentionSessionIdentity {
4175
+ readonly sessionId: string;
4176
+ readonly incarnation: number | string;
4177
+ readonly version: number | string;
4178
+ readonly fence: number | string;
4179
+ }
4180
+ interface PostgresRetentionJobOptions {
4181
+ readonly pool: SqlPool$1;
4182
+ readonly terminalRetentionMs: number;
4183
+ readonly outboxRetentionMs?: number;
4184
+ readonly hasLegalHold: (sessionId: string) => Promise<boolean>;
4185
+ readonly archive?: (sessionId: string) => Promise<void>;
4186
+ readonly beforeSessionDelete?: (candidate: PostgresRetentionSessionIdentity, purgeToken: string) => Promise<void>;
4187
+ readonly afterSessionDeleteFailure?: (candidate: PostgresRetentionSessionIdentity, purgeToken: string) => Promise<void>;
4188
+ }
4189
+ interface RetentionRunResult {
4190
+ readonly sessionsDeleted: number;
4191
+ readonly outboxDeleted: number;
4192
+ readonly idempotencyDeleted: number;
4193
+ }
4194
+ declare class PostgresRetentionJob {
4195
+ #private;
4196
+ constructor(options: PostgresRetentionJobOptions);
4197
+ runOnce(): Promise<RetentionRunResult>;
4198
+ }
4199
+
4615
4200
  interface PostgresMigration$1 {
4616
4201
  readonly version: number;
4617
4202
  readonly name: string;
4618
4203
  readonly sql: string;
4619
4204
  }
4620
- /** Runs the ordered SQL files exactly once and records the applied filename. */
4621
4205
  declare function runPostgresMigrations(pool: SqlPool$1, migrations?: readonly PostgresMigration$1[]): Promise<readonly number[]>;
4622
4206
 
4623
4207
  interface SqlResult<Row extends Record<string, unknown> = Record<string, unknown>> {
@@ -4631,9 +4215,12 @@ interface SqlPool$1 extends SqlClient$1 {
4631
4215
  connect(): Promise<SqlClient$1 & {
4632
4216
  readonly release: () => void;
4633
4217
  }>;
4634
- /** If provided, the durable store owns this pool and calls it once on close. */
4635
4218
  end?(): Promise<void>;
4636
4219
  }
4220
+ interface PostgresSessionChildPage<RecordType> {
4221
+ readonly records: readonly RecordType[];
4222
+ readonly nextCursor: string | undefined;
4223
+ }
4637
4224
  interface PostgresDurableStoreOptions {
4638
4225
  readonly pool: SqlPool$1;
4639
4226
  }
@@ -4651,6 +4238,7 @@ declare class PostgresTurnStore implements TurnStore {
4651
4238
  constructor(client: SqlClient$1);
4652
4239
  get(sessionId: SessionId, id: TurnId): Promise<StoredTurnRecord | null>;
4653
4240
  listBySession(sessionId: SessionId): Promise<readonly StoredTurnRecord[]>;
4241
+ listBySessionPage(sessionId: SessionId, afterId?: string, pageSize?: number): Promise<PostgresSessionChildPage<StoredTurnRecord>>;
4654
4242
  put(record: StoredTurnRecord): Promise<void>;
4655
4243
  update(sessionId: SessionId, id: TurnId, updater: (record: StoredTurnRecord) => StoredTurnRecord): Promise<StoredTurnRecord>;
4656
4244
  close(): Promise<void>;
@@ -4660,27 +4248,11 @@ declare class PostgresToolCallStore implements ToolCallStore {
4660
4248
  constructor(client: SqlClient$1);
4661
4249
  get(sessionId: SessionId, id: ToolCallId): Promise<StoredToolCallRecord | null>;
4662
4250
  listBySession(sessionId: SessionId): Promise<readonly StoredToolCallRecord[]>;
4251
+ listBySessionPage(sessionId: SessionId, afterId?: string, pageSize?: number): Promise<PostgresSessionChildPage<StoredToolCallRecord>>;
4663
4252
  put(record: StoredToolCallRecord): Promise<void>;
4664
4253
  update(sessionId: SessionId, id: ToolCallId, updater: (record: StoredToolCallRecord) => StoredToolCallRecord): Promise<StoredToolCallRecord>;
4665
4254
  close(): Promise<void>;
4666
4255
  }
4667
- declare class PostgresSessionLeaseStore implements SessionLeaseStore {
4668
- readonly client: SqlPool$1;
4669
- constructor(client: SqlPool$1);
4670
- acquire(sessionId: SessionId, holder: string, ttlMs: number): Promise<SessionLease | null>;
4671
- renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number): Promise<SessionLease | null>;
4672
- release(sessionId: SessionId, holder: string, fence: number): Promise<void>;
4673
- get(sessionId: SessionId): Promise<SessionLease | null>;
4674
- listRecoveryCandidates(options: {
4675
- readonly nowMs: number;
4676
- readonly limit: number;
4677
- readonly cursor?: string;
4678
- }): Promise<{
4679
- readonly sessionIds: readonly SessionId[];
4680
- readonly nextCursor?: string;
4681
- }>;
4682
- close(): Promise<void>;
4683
- }
4684
4256
  declare class PostgresDurableRuntimeStore implements DurableRuntimeStore {
4685
4257
  #private;
4686
4258
  readonly pool: SqlPool$1;
@@ -4691,7 +4263,7 @@ declare class PostgresDurableRuntimeStore implements DurableRuntimeStore {
4691
4263
  readonly toolIdempotencyStore: PostgresToolIdempotencyStore;
4692
4264
  constructor(pool: SqlPool$1);
4693
4265
  createSessionWithLease(record: StoredSessionRecord, holder: string, ttlMs: number, initialEvent?: (lease: SessionLease) => DurableOutboxEvent): Promise<SessionLease | null>;
4694
- runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4266
+ runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence" | "generationId">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4695
4267
  runUnfencedSessionTransaction<T>(sessionId: SessionId, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4696
4268
  close(): Promise<void>;
4697
4269
  }
@@ -4701,23 +4273,70 @@ declare class RedisToolIdempotencyStore implements ToolIdempotencyStore {
4701
4273
  #private;
4702
4274
  readonly client: RedisClient;
4703
4275
  constructor(client: RedisClient, options?: RedisStoreOptions);
4704
- lookup(key: string, _requestHash: string): Promise<ToolIdempotencyRecord | null>;
4276
+ lookup(key: string, requestHash: string, sessionId?: SessionId, lease?: ToolIdempotencyClaim["lease"]): Promise<ToolIdempotencyLookupResult>;
4705
4277
  claim(input: ToolIdempotencyClaim): Promise<ToolIdempotencyClaimResult>;
4278
+ releaseClaim(input: ToolIdempotencyRelease): Promise<boolean>;
4706
4279
  complete(key: string, requestHash: string, outcome: ToolIdempotencyOutcome): Promise<void>;
4280
+ quarantine(input: ToolIdempotencyQuarantine): Promise<ToolIdempotencyQuarantineResult>;
4281
+ pruneExpiredIdempotencyPage(cursor?: string, limit?: number): Promise<{
4282
+ readonly cursor: string;
4283
+ readonly scanned: number;
4284
+ readonly deleted: number;
4285
+ }>;
4707
4286
  }
4708
4287
 
4709
- /**
4710
- * Applies Postgres outbox events to Redis as a version/fence guarded cache.
4711
- * Redis is intentionally not a second runtime authority: a cache event can be
4712
- * replayed, duplicated, or delivered out of order without replacing a newer
4713
- * value. Postgres remains the source of truth and the outbox worker supplies
4714
- * the retry boundary.
4715
- */
4288
+ declare class RedisSessionStore implements SessionStore {
4289
+ readonly client: RedisClient;
4290
+ readonly options: RedisStoreOptions;
4291
+ constructor(client: RedisClient, options?: RedisStoreOptions);
4292
+ get(id: SessionId): Promise<StoredSessionRecord | null>;
4293
+ list(): Promise<readonly StoredSessionRecord[]>;
4294
+ put(record: StoredSessionRecord): Promise<void>;
4295
+ update(id: SessionId, updater: (record: StoredSessionRecord) => StoredSessionRecord): Promise<StoredSessionRecord>;
4296
+ close(): Promise<void>;
4297
+ }
4298
+ declare class RedisTurnStore implements TurnStore {
4299
+ readonly client: RedisClient;
4300
+ readonly options: RedisStoreOptions;
4301
+ constructor(client: RedisClient, options?: RedisStoreOptions);
4302
+ get(sessionId: SessionId, id: TurnId): Promise<StoredTurnRecord | null>;
4303
+ listBySession(sessionId: SessionId): Promise<readonly StoredTurnRecord[]>;
4304
+ put(record: StoredTurnRecord): Promise<void>;
4305
+ update(sessionId: SessionId, id: TurnId, updater: (record: StoredTurnRecord) => StoredTurnRecord): Promise<StoredTurnRecord>;
4306
+ close(): Promise<void>;
4307
+ }
4308
+ declare class RedisToolCallStore implements ToolCallStore {
4309
+ readonly client: RedisClient;
4310
+ readonly options: RedisStoreOptions;
4311
+ constructor(client: RedisClient, options?: RedisStoreOptions);
4312
+ get(sessionId: SessionId, id: ToolCallId): Promise<StoredToolCallRecord | null>;
4313
+ listBySession(sessionId: SessionId): Promise<readonly StoredToolCallRecord[]>;
4314
+ put(record: StoredToolCallRecord): Promise<void>;
4315
+ update(sessionId: SessionId, id: ToolCallId, updater: (record: StoredToolCallRecord) => StoredToolCallRecord): Promise<StoredToolCallRecord>;
4316
+ close(): Promise<void>;
4317
+ }
4318
+
4319
+ interface ProjectedSessionRetentionIdentity {
4320
+ readonly sessionId: SessionId;
4321
+ readonly incarnation: number | string;
4322
+ readonly version: number | string;
4323
+ readonly fence: number | string;
4324
+ }
4325
+ interface ProjectedSessionCacheSnapshot {
4326
+ readonly session: StoredSessionRecord;
4327
+ readonly turns: Iterable<StoredTurnRecord> | AsyncIterable<StoredTurnRecord>;
4328
+ readonly toolCalls: Iterable<StoredToolCallRecord> | AsyncIterable<StoredToolCallRecord>;
4329
+ }
4716
4330
  declare class RedisOutboxCacheProjector {
4331
+ #private;
4717
4332
  readonly client: RedisClient;
4718
4333
  readonly options: RedisStoreOptions;
4719
4334
  constructor(client: RedisClient, options?: RedisStoreOptions);
4720
4335
  apply(event: DurableOutboxEvent): Promise<void>;
4336
+ purgeSession(identity: ProjectedSessionRetentionIdentity, purgeToken: string): Promise<void>;
4337
+ resumeSessionPurge(identity: ProjectedSessionRetentionIdentity, purgeToken: string): Promise<boolean>;
4338
+ getSessionPurgeToken(identity: Pick<ProjectedSessionRetentionIdentity, "sessionId" | "incarnation">): Promise<string | null>;
4339
+ restoreSessionProjection(identity: ProjectedSessionRetentionIdentity, purgeToken: string, snapshot: ProjectedSessionCacheSnapshot): Promise<void>;
4721
4340
  }
4722
4341
 
4723
4342
  type RedisSetResult = "OK" | "ok" | boolean | null;
@@ -4729,6 +4348,7 @@ interface RedisClient {
4729
4348
  get(key: string): Promise<string | null>;
4730
4349
  set(key: string, value: string, options?: {
4731
4350
  readonly NX?: boolean;
4351
+ readonly PX?: number;
4732
4352
  }): Promise<RedisSetResult>;
4733
4353
  del(...keys: readonly string[]): Promise<number>;
4734
4354
  eval(script: string, keys: readonly string[], args: readonly string[]): Promise<unknown>;
@@ -4742,7 +4362,9 @@ interface RedisClient {
4742
4362
  quit?(): Promise<void>;
4743
4363
  }
4744
4364
  interface RedisMulti {
4745
- set(key: string, value: string): RedisMulti;
4365
+ set(key: string, value: string, options?: {
4366
+ readonly PX?: number;
4367
+ }): RedisMulti;
4746
4368
  del(...keys: readonly string[]): RedisMulti;
4747
4369
  exec(): Promise<readonly unknown[] | null>;
4748
4370
  }
@@ -4754,52 +4376,24 @@ interface RedisStoreOptions {
4754
4376
  readonly onCompatibilityDiagnostic?: (diagnostic: PersistedErrorCompatibilityDiagnostic) => void;
4755
4377
  }
4756
4378
 
4757
- declare class RedisSessionStore implements SessionStore {
4758
- readonly client: RedisClient;
4759
- readonly options: RedisStoreOptions;
4760
- constructor(client: RedisClient, options?: RedisStoreOptions);
4761
- get(id: SessionId): Promise<StoredSessionRecord | null>;
4762
- list(): Promise<readonly StoredSessionRecord[]>;
4763
- put(record: StoredSessionRecord): Promise<void>;
4764
- update(id: SessionId, updater: (record: StoredSessionRecord) => StoredSessionRecord): Promise<StoredSessionRecord>;
4765
- close(): Promise<void>;
4766
- }
4767
- declare class RedisTurnStore implements TurnStore {
4768
- readonly client: RedisClient;
4769
- readonly options: RedisStoreOptions;
4770
- constructor(client: RedisClient, options?: RedisStoreOptions);
4771
- get(sessionId: SessionId, id: TurnId): Promise<StoredTurnRecord | null>;
4772
- listBySession(sessionId: SessionId): Promise<readonly StoredTurnRecord[]>;
4773
- put(record: StoredTurnRecord): Promise<void>;
4774
- update(sessionId: SessionId, id: TurnId, updater: (record: StoredTurnRecord) => StoredTurnRecord): Promise<StoredTurnRecord>;
4775
- close(): Promise<void>;
4776
- }
4777
- declare class RedisToolCallStore implements ToolCallStore {
4778
- readonly client: RedisClient;
4779
- readonly options: RedisStoreOptions;
4780
- constructor(client: RedisClient, options?: RedisStoreOptions);
4781
- get(sessionId: SessionId, id: ToolCallId): Promise<StoredToolCallRecord | null>;
4782
- listBySession(sessionId: SessionId): Promise<readonly StoredToolCallRecord[]>;
4783
- put(record: StoredToolCallRecord): Promise<void>;
4784
- update(sessionId: SessionId, id: ToolCallId, updater: (record: StoredToolCallRecord) => StoredToolCallRecord): Promise<StoredToolCallRecord>;
4785
- close(): Promise<void>;
4786
- }
4787
4379
  declare class RedisSessionLeaseStore implements SessionLeaseStore {
4788
4380
  #private;
4789
4381
  readonly client: RedisClient;
4790
4382
  constructor(client: RedisClient, options?: RedisStoreOptions);
4791
4383
  acquire(sessionId: SessionId, holder: string, ttlMs: number): Promise<SessionLease | null>;
4792
- renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number): Promise<SessionLease | null>;
4793
- release(sessionId: SessionId, holder: string, fence: number): Promise<void>;
4384
+ renew(sessionId: SessionId, holder: string, fence: number, ttlMs: number, generationId: string): Promise<SessionLease | null>;
4385
+ release(sessionId: SessionId, holder: string, fence: number, generationId: string): Promise<void>;
4794
4386
  get(sessionId: SessionId): Promise<SessionLease | null>;
4795
4387
  listRecoveryCandidates(options: {
4796
4388
  readonly nowMs: number;
4797
4389
  readonly limit: number;
4798
4390
  readonly cursor?: string;
4799
4391
  }): Promise<{
4800
- readonly sessionIds: readonly SessionId[];
4392
+ readonly candidates: readonly SessionRecoveryCandidate[];
4393
+ readonly corruptLeaseSessionIds?: readonly SessionId[];
4801
4394
  readonly nextCursor?: string;
4802
4395
  }>;
4396
+ acknowledgeRecoveryCandidate(candidate: SessionRecoveryCandidate): Promise<void>;
4803
4397
  close(): Promise<void>;
4804
4398
  }
4805
4399
  declare class RedisDurableRuntimeStore implements DurableRuntimeStore {
@@ -4811,7 +4405,7 @@ declare class RedisDurableRuntimeStore implements DurableRuntimeStore {
4811
4405
  readonly toolIdempotencyStore: RedisToolIdempotencyStore;
4812
4406
  constructor(client: RedisClient, options?: RedisStoreOptions);
4813
4407
  createSessionWithLease(record: StoredSessionRecord, holder: string, ttlMs: number, initialEvent?: (lease: SessionLease) => DurableOutboxEvent): Promise<SessionLease | null>;
4814
- runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4408
+ runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence" | "generationId">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4815
4409
  runUnfencedSessionTransaction<T>(sessionId: SessionId, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4816
4410
  close(): Promise<void>;
4817
4411
  }
@@ -4822,12 +4416,6 @@ interface PostgresRedisDurableStoreOptions {
4822
4416
  readonly redis: RedisClient;
4823
4417
  readonly redisOptions?: RedisStoreOptions;
4824
4418
  }
4825
- /**
4826
- * The production composition: PostgreSQL owns all mutations, leases,
4827
- * idempotency, and reads; the outbox asynchronously projects committed
4828
- * envelopes into Redis. A Redis outage therefore cannot turn a committed
4829
- * runtime mutation into a failed domain operation.
4830
- */
4831
4419
  declare class PostgresRedisDurableRuntimeStore implements DurableRuntimeStore {
4832
4420
  #private;
4833
4421
  readonly primary: PostgresDurableRuntimeStore;
@@ -4839,9 +4427,10 @@ declare class PostgresRedisDurableRuntimeStore implements DurableRuntimeStore {
4839
4427
  readonly toolIdempotencyStore: ToolIdempotencyStore;
4840
4428
  constructor(options: PostgresRedisDurableStoreOptions);
4841
4429
  createSessionWithLease(record: StoredSessionRecord, holder: string, ttlMs: number, initialEvent?: (lease: SessionLease) => DurableOutboxEvent): Promise<SessionLease | null>;
4842
- runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4430
+ runSessionTransaction<T>(sessionId: SessionId, lease: Pick<SessionLease, "holder" | "fence" | "generationId">, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4843
4431
  runUnfencedSessionTransaction<T>(sessionId: SessionId, operation: (tx: DurableSessionTransaction) => Promise<T>): Promise<T>;
4844
4432
  startOutboxWorker(options: Omit<PostgresOutboxWorkerOptions, "pool" | "deliver">): void;
4433
+ createRetentionJob(options: Omit<PostgresRetentionJobOptions, "pool">): PostgresRetentionJob;
4845
4434
  stopOutboxWorker(): Promise<void>;
4846
4435
  close(): Promise<void>;
4847
4436
  }
@@ -4897,5 +4486,5 @@ declare class PostgresMemory implements Memory {
4897
4486
  }
4898
4487
  declare function createPostgresMemory(options: PostgresMemoryOptions): PostgresMemory;
4899
4488
 
4900
- export { ADAPTER_DEFAULTS, AssemblyAiSttProvider, AsyncQueue, AsyncQueueConsumerError, BackendUnavailableError, CartesiaSttProvider, CartesiaTtsProvider, ConversationPolicy, CorruptRecordError, DEFAULT_DURABLE_RUNTIME_POLICY, DTMF_DIGITS, DeepgramSttProvider, DurableError, EVENT_KIND_MAP, ElevenLabsSttProvider, ElevenLabsTtsHttpStreamProvider, ElevenLabsTtsProvider, ElevenLabsTtsRestProvider, InMemoryMemory, InMemorySessionLeaseStore, InMemorySessionStore, InMemoryToolCallStore, InMemoryToolIdempotencyStore, InMemoryTurnStore, InvalidArgumentError, LeaseLostError, LeaseUnavailableError, MAX_CARTESIA_INPUT_UTF16_CODE_UNITS, MAX_CARTESIA_INPUT_UTF8_BYTES, MAX_PROVIDER_AUDIO_OFFSET_MS, MemoryBackendUnavailableError, MemoryEntryTooLargeError, MemorySessionQuotaExceededError, NodeMediaPlane, PCM16_16K_MONO, PCM16_8K_MONO, PROVIDER_API_VERSIONS, PROVIDER_CATALOG, PROVIDER_ERROR_CODES, PROVIDER_NAMES, PROVIDER_STABILITY, PROVIDER_STABILITY_LEVELS, PipelineVoiceLoop, PipelineVoiceLoopBuilder, RUNTIME_SAMPLE_RATE_HZ, RecordConflictError, RecordNotFoundError, STT_ERROR_CODES, STT_STREAM_ENDED_REASON, SarvamSttProvider, SarvamTtsHttpStreamProvider, SarvamTtsProvider, SarvamTtsRestProvider, SessionReaper, SessionRecoveryCoordinator, SonioxSttProvider, TELEPHONY_SAMPLE_RATE_HZ, TVIC_ERROR_CODES, TVIC_ERROR_CODE_ALIASES, TVIC_ERROR_MARKER, TVIC_ERROR_NAMES, TWILIO_MAX_AUDIO_EVENT_BYTES, TvicThrowableError, TwilioMediaStreamCallHandle, TwilioMediaStreamsProvider, VoiceRuntimeFinalizationError, WEB_CLIENT_AUDIO_ACK_RETENTION_MS, WEB_CLIENT_AUDIO_CLOSE_CODES, WEB_CLIENT_AUDIO_DEFAULTS, WebClientAudioCallHandle, WebClientAudioProvider, assertMemoryCapability, assertMemoryPolicySupported, assertPcm16leFormat, authError, base64ToBytes, bytesToBase64, cancelledError, canonicalizeTwilioData, computeTwilioSignature, connectionError, counterIdGenerator, createAssemblyAiSttProvider, createAudioNormalizer, createCartesiaSttProvider, createCartesiaTtsProvider, createDeepgramSttProvider, createDefaultIdGenerator, createElevenLabsSttProvider, createElevenLabsTtsHttpStreamProvider, createElevenLabsTtsProvider, createElevenLabsTtsRestProvider, createGroqChatLlmProvider, createInMemoryDurableRuntimeStore, createInMemoryMemory, createInMemorySessionStore, createInMemoryToolCallStore, createInMemoryTurnStore, createMediaEvent, createNodeMediaPlane, createOpenAiResponsesLlmProvider, createPostgresDurableRuntimeStore, createPostgresMemory, createPostgresRedisDurableRuntimeStore, createRedisDurableRuntimeStore, createRuntime, createSarvamSttProvider, createSarvamTtsHttpStreamProvider, createSarvamTtsProvider, createSarvamTtsRestProvider, createSonioxSttProvider, createSttSession, createSystemClock, createToolRegistry, createTtsFailoverProvider, createTwilioMediaStreamsProvider, createVoiceAgent, createWebClientAudioProvider, defineAgent, defineTool, deliverAssistantText, durationMsForPcm16le, evaluateProviderCompatibility, executeTool, formatMemoryContextAsSystemBlock, formatPreCallContextAsSystemBlock, frameCountForPcm16le, getSttRecoveryControl, idempotencyKeyFor, idempotencyRequestHashFor, internalError, interruptedError, isDtmfDigit, isIncrementalTextToSpeechProvider, isInputMediaEvent, isNormalizedError, isOutputMediaEvent, isProviderKind, isReconstructableAudioFormat, isSampleRateHz, isTerminalSession, isTerminalTurn, isTranscriptSegmentEvent, isTvicError, isTvicErrorName, kindForMediaEvent, matchPath, mediaError, monotonicOffsetMs, mulawToPcm16le, normalizeLegacyError, normalizeUnknownError, normalizedError, nowTimestamp, pcm16leToMulaw, providerError, rateLimitError, requireProviderKind, resamplePcm16le, resolvePreCallContext, resolvePreCallMemory, runPostgresMemoryMigrations, runPostgresMigrations, sameAudioFormat, shouldDeliverText, signVoiceSessionToken, signatureError, splitPcm16leFrames, stableStringify, supportsAudioFormat, supportsBatchModel, supportsLanguage, supportsModel, terminalSessionFromRequest, terminalSourceForRequest, terminalTurnFromRequest, timeoutError, toTimestamp, toolError, toolInputError, tvicErrorFromJSON, unknownErrorMessage, validateJsonSchemaSubset, validationError, verifyTwilioSignature, verifyVoiceSessionToken, withSttReconnect };
4901
- export type { ActiveSession, ActiveTurn, Agent, AgentAudioPolicy, AgentContextPolicy, AgentId, AgentMemoryPolicy, AgentProviders, AnyMediaEventInit, AssemblyAiProviderConfig, AssemblyAiSttProviderOptions, AssistantTextRecord, AudioFormat, AudioNormalizationMode, AudioNormalizer, AudioNormalizerOptions, AudioPayload, BackoffStrategy, Brand, Call, CallControlCapability, CallDirection, CallHandle, CallId, CallSnapshot, CallStatus, CancelledSession, CancelledTurn, CartesiaGenerationConfig, CartesiaProviderConfig, CartesiaSttMode, CartesiaSttProviderConfig, CartesiaSttProviderOptions, CartesiaTtsProviderOptions, ChannelKind, ChannelLayout, CleanupErrorSummary, CleanupStage, Clock, CompletedSession, CompletedTurn, ConnectedCall, ConnectionObservabilityEvent, ConversationPolicyOptions, CounterIdGenerator, CreateVoiceAgentOptions, CreatedCall, CreatedSession, DeepgramProviderConfig, DeepgramSttProviderOptions, DefineAgentInput, DefineToolInput, DtmfDigit, DtmfReceivedEvent, DualProtocolResult, DurableErrorCode, DurableOutboxEvent, DurableRuntimeMetric, DurableRuntimePolicy, DurableRuntimeStore, DurableSessionTransaction, ElevenLabsBatchSttRequest, ElevenLabsBatchSttResult, ElevenLabsBatchTimestampGranularity, ElevenLabsDialogueInput, ElevenLabsDialogueProvider, ElevenLabsDialogueSynthesisRequest, ElevenLabsDialogueTurnOptions, ElevenLabsEntityDetection, ElevenLabsHttpTtsProviderOptions, ElevenLabsPronunciationDictionaryLocator, ElevenLabsSttCommitStrategy, ElevenLabsSttProviderConfig, ElevenLabsSttProviderOptions, ElevenLabsTextNormalization, ElevenLabsTtsHttpSynthesisRequest, ElevenLabsTtsProviderConfig, ElevenLabsTtsProviderOptions, ElevenLabsTtsSendTextOptions, EndSessionReason, EndSessionRequest, EndTurnRequest, EndedCall, ErrorCategory, ExecuteToolInput, FailedCall, FailedSession, FailedToolCall, FailedToolCallStatus, FailedTurn, GroqChatLlmProviderOptions, GroqProviderConfig, HealthCheckResult, HealthSnapshot, IdGenerator, IdempotencyPolicy, InMemoryDurableRuntimeStore, InMemoryDurableRuntimeStoreOptions, InMemoryMemoryOptions, InboundCallContext, InboundMediaEvent, IncrementalTextToSpeechProvider, InputAudioChunk, InputMediaEvent, InternalMediaEvent, InterruptRequestedEvent, InterruptionMode, InterruptionPolicy, JsonSchemaDocument, JsonValue, LLMProvider, LiveTerminalSource, LlmCompletion, LlmCompletionRequest, LlmInlineToolCall, LlmMessage, LlmMessageRole, LlmProviderConfig, LlmStreamEvent, LlmUsage, MediaAudioChunkEvent, MediaAudioCommittedEvent, MediaDirection, MediaErrorEvent, MediaEvent, MediaEventId, MediaEventKind, MediaEventType, MediaStreamEndedEvent, MediaStreamStartedEvent, MediaTransport, MediaTransportKind, Memory, MemoryCapabilities, MemoryEntry, MemoryEntryId, MemoryKind, MemoryPutOptions, MemoryQuery, MemoryRef, MemoryScope, NodeMediaPlaneConnection, NodeMediaPlaneConnectionErrorHandler, NodeMediaPlaneConnectionHandler, NodeMediaPlaneOptions, NodeMediaPlaneRequestHandler, NormalizedAudioEncoding, NormalizedError, OpenAiProviderConfig, OpenAiResponsesLlmProviderOptions, OrganizationId, OutboundCallRequest, OutputAudioChunk, OutputMediaEvent, PersonaConfig, PipelineVoiceLoopOptions, PipelineVoiceLoopResult, PostgresDurableStoreOptions, PostgresMemoryOptions, PostgresMigration, PostgresRedisDurableStoreOptions, PreCallContext, PreCallContextResolver, PreCallMemoryContext, PreCallMemoryResolver, Provider, ProviderAudioCapabilities, ProviderBatchCapabilities, ProviderCancellationCapabilities, ProviderCapabilities, ProviderCatalogEntry, ProviderClock, ProviderCompatibility, ProviderCompatibilityIssue, ProviderCompatibilityIssueCode, ProviderDataPolicy, ProviderEventId, ProviderForKind, ProviderKind, ProviderPlayoutCapabilities, ProviderRequirements, ProviderStability, ProviderStreamingCapabilities, ProviderToolCapabilities, ProviderTransport, QueuedToolCall, RecoveryPollResult, RedisClient, RedisMulti, RedisScanOptions, RedisSetResult, RedisStoreOptions, RequiredProviderCapabilities, RetryPolicy, RingingCall, RunningToolCall, Runtime, RuntimeOptions, RuntimeProvider, RuntimeServiceLifecycle, SampleRateHz, SarvamOutputMode, SarvamProviderConfig, SarvamSttProviderOptions, SarvamTtsHttpProviderOptions, SarvamTtsProviderConfig, SarvamTtsProviderOptions, SchemaValidationResult, Session, SessionAttachment, SessionAttachmentHealth, SessionCancellationReason, SessionEndEvent, SessionEndMemorySnapshot, SessionId, SessionLease, SessionLeaseStore, SessionMemoryFinalization, SessionMetricsRecorder, SessionReaperOptions, SessionRecoveryCoordinatorOptions, SessionRuntimeMetadata, SessionSnapshot, SessionState, SessionStatus, SessionStore, SonioxProviderConfig, SonioxStructuredContext, SonioxSttProviderOptions, SpeechToTextProvider, SqlClient$1 as SqlClient, SqlPool$1 as SqlPool, SqlResult, StartAttachedSessionOptions, StartSessionOptions, StartTurnRequest, StartingSession, StoredSessionRecord, StoredToolCallRecord, StoredTurnRecord, StreamEndReason, SttBatchTimestampGranularity, SttBatchTranscription, SttBatchTranscriptionRequest, SttBatchWord, SttCommitMode, SttOpenRequest, SttProviderConfig, SttReconnectOptions, SttRecoveryControl, SttRecoveryState, SttSession, SttSessionInputOptions, SttSessionOptions, SttStream, SttTimestampOrigin, SucceededToolCall, TelephonyProvider, TelephonyProviderConfig, TerminalSession, TerminalSessionDraft, TerminalSessionStatus, TerminalSource, TerminalToolCall, TerminalTurn, TextDeliveryMode, TextToSpeechProvider, TimeoutAction, TimeoutPolicy, Timestamp, ToolCall, ToolCallId, ToolCallRuntimeMetadata, ToolCallStatus, ToolCallStore, ToolDefinition, ToolExecutionContext, ToolExecutor, ToolId, ToolIdempotencyClaim, ToolIdempotencyClaimResult, ToolIdempotencyLease, ToolIdempotencyOutcome, ToolIdempotencyRecord, ToolIdempotencyStatus, ToolIdempotencyStore, ToolLogger, ToolName, ToolRegistry, ToolTenant, TranscriptEndpointEvent, TranscriptEndpointReason, TranscriptEvent, TranscriptEventType, TranscriptSegmentEvent, TranscriptSegmentEventType, TranscriptSpeechStartedEvent, TransportAudioEncoding, TransportAudioFormat, TtsAlignmentEvent, TtsAlignmentUnit, TtsEvent, TtsFailoverContext, TtsFailoverPhase, TtsFailoverProviderOptions, TtsFlushAcknowledgement, TtsFlushCompletedEvent, TtsFlushId, TtsFlushResult, TtsProviderConfig, TtsSession, TtsSessionOpenRequest, TtsStream, TtsSynthesisRequest, Turn, TurnCancellationReason, TurnCommitRequestedEvent, TurnDetectionMode, TurnId, TurnInput, TurnLatency, TurnLatencyRecord, TurnOutput, TurnRuntimeMetadata, TurnStatus, TurnStore, TvicErrorName, TwilioFlatParams, TwilioMediaStreamCallHandleOptions, TwilioMediaStreamSocket, TwilioParamValue, TwilioParams, UpgradeAuthorization, UserId, VerifyTwilioOptions, VerifyVoiceSessionTokenOptions, VoiceAgent, VoiceAgentCallHandleContext, VoiceAgentCallHandleFactory, VoiceAgentModels, VoiceAgentProviderNames, VoiceAgentProviders, VoiceAgentRun, VoiceAgentRunOptions, VoiceAgentSession, VoiceEvent, VoiceRuntimeFailureMetadata, WebClientAudioCallHandleOptions, WebClientAudioConnectionEvent, WebClientAudioProviderOptions, WebClientAudioSocket, WorkflowId };
4489
+ export { ADAPTER_DEFAULTS, AssemblyAiSttProvider, AsyncQueue, AsyncQueueConsumerError, BackendUnavailableError, CartesiaSttProvider, CartesiaTtsProvider, ConversationPolicy, CorruptRecordError, DEFAULT_DURABLE_RUNTIME_POLICY, DTMF_DIGITS, DeepgramSttProvider, DurableError, EVENT_KIND_MAP, ElevenLabsSttProvider, ElevenLabsTtsHttpStreamProvider, ElevenLabsTtsProvider, ElevenLabsTtsRestProvider, InMemoryMemory, InMemorySessionLeaseStore, InMemorySessionStore, InMemoryToolCallStore, InMemoryToolIdempotencyStore, InMemoryTurnStore, InvalidArgumentError, LeaseLostError, LeaseUnavailableError, MAX_CARTESIA_INPUT_UTF16_CODE_UNITS, MAX_CARTESIA_INPUT_UTF8_BYTES, MAX_ERROR_CODE_UTF8_BYTES, MAX_PROVIDER_AUDIO_OFFSET_MS, MAX_RECOVERY_PAGE_SIZE, MAX_SAFE_LEASE_TIMESTAMP, MemoryBackendUnavailableError, MemoryEntryTooLargeError, MemorySessionQuotaExceededError, NodeMediaPlane, PCM16_16K_MONO, PCM16_8K_MONO, PROVIDER_API_VERSIONS, PROVIDER_CATALOG, PROVIDER_ERROR_CODES, PROVIDER_NAMES, PROVIDER_STABILITY, PROVIDER_STABILITY_LEVELS, PipelineVoiceLoop, PipelineVoiceLoopBuilder, RUNTIME_SAMPLE_RATE_HZ, RecordConflictError, RecordNotFoundError, SARVAM_TTS_V4_FLASH_MODEL, STT_ERROR_CODES, STT_STREAM_ENDED_REASON, SarvamSttProvider, SarvamTtsHttpStreamProvider, SarvamTtsProvider, SarvamTtsRestProvider, SessionReaper, SessionRecoveryCoordinator, SonioxSttProvider, TELEPHONY_SAMPLE_RATE_HZ, TVIC_ERROR_CODES, TVIC_ERROR_CODE_ALIASES, TVIC_ERROR_MARKER, TVIC_ERROR_NAMES, TWILIO_MAX_AUDIO_EVENT_BYTES, TvicThrowableError, TwilioMediaStreamCallHandle, TwilioMediaStreamsProvider, VoiceRuntimeFinalizationError, WEB_CLIENT_AUDIO_ACK_RETENTION_MS, WEB_CLIENT_AUDIO_CLOSE_CODES, WEB_CLIENT_AUDIO_DEFAULTS, WebClientAudioCallHandle, WebClientAudioProvider, assertLeaseFence, assertLeaseTimestampMs, assertLeaseTtlMs, assertMemoryCapability, assertMemoryPolicySupported, assertPcm16leFormat, assertRecoveryPageSize, authError, base64ToBytes, bytesToBase64, cancelledError, canonicalizeTwilioData, computeTwilioSignature, connectionError, counterIdGenerator, createAssemblyAiSttProvider, createAudioNormalizer, createCartesiaSttProvider, createCartesiaTtsProvider, createDeepgramSttProvider, createDefaultIdGenerator, createElevenLabsSttProvider, createElevenLabsTtsHttpStreamProvider, createElevenLabsTtsProvider, createElevenLabsTtsRestProvider, createGroqChatLlmProvider, createInMemoryDurableRuntimeStore, createInMemoryMemory, createInMemorySessionStore, createInMemoryToolCallStore, createInMemoryTurnStore, createMediaEvent, createNodeMediaPlane, createOpenAiResponsesLlmProvider, createPostgresDurableRuntimeStore, createPostgresMemory, createPostgresRedisDurableRuntimeStore, createRedisDurableRuntimeStore, createRuntime, createSarvamSttProvider, createSarvamTtsHttpStreamProvider, createSarvamTtsProvider, createSarvamTtsRestProvider, createSonioxSttProvider, createSttSession, createSystemClock, createToolRegistry, createTtsFailoverProvider, createTwilioMediaStreamsProvider, createVoiceAgent, createWebClientAudioProvider, defineAgent, defineTool, deliverAssistantText, durationMsForPcm16le, evaluateProviderCompatibility, executeTool, formatMemoryContextAsSystemBlock, formatPreCallContextAsSystemBlock, frameCountForPcm16le, getSttRecoveryControl, idempotencyKeyFor, idempotencyRequestHashFor, internalError, interruptedError, isDtmfDigit, isIncrementalTextToSpeechProvider, isInputMediaEvent, isNormalizedError, isOutputMediaEvent, isProviderKind, isReconstructableAudioFormat, isSampleRateHz, isTerminalSession, isTerminalTurn, isTranscriptSegmentEvent, isTvicError, isTvicErrorName, isValidErrorCode, jsonSerializableNormalizedError, kindForMediaEvent, matchPath, mediaError, monotonicOffsetMs, mulawToPcm16le, normalizeLegacyError, normalizeUnknownError, normalizedError, normalizedErrorFromTvicError, nowTimestamp, pcm16leToMulaw, providerError, rateLimitError, requireProviderKind, resamplePcm16le, resolvePreCallContext, resolvePreCallMemory, runPostgresMemoryMigrations, runPostgresMigrations, safeLeaseExpiryAt, sameAudioFormat, shouldDeliverText, signVoiceSessionToken, signatureError, splitPcm16leFrames, stableStringify, supportsAudioFormat, supportsBatchModel, supportsLanguage, supportsModel, terminalSessionFromRequest, terminalSourceForRequest, terminalTurnFromRequest, timeoutError, toRuntimeSessionTrace, toTimestamp, toolError, toolInputError, tvicErrorFromJSON, unknownErrorMessage, validateJsonSchemaSubset, validationError, verifyTwilioSignature, verifyVoiceSessionToken, withSttReconnect };
4490
+ export type { ActiveSession, ActiveTurn, Agent, AgentAudioPolicy, AgentContextPolicy, AgentId, AgentMemoryPolicy, AgentProviders, AnyMediaEventInit, AssemblyAiProviderConfig, AssemblyAiSttProviderOptions, AssistantTextRecord, AudioFormat, AudioNormalizationMode, AudioNormalizer, AudioNormalizerOptions, AudioOutputDeliveryStatus, AudioPayload, BackoffStrategy, Brand, Call, CallControlCapability, CallDirection, CallHandle, CallId, CallSnapshot, CallStatus, CancelledSession, CancelledTurn, CartesiaGenerationConfig, CartesiaProviderConfig, CartesiaSttMode, CartesiaSttProviderConfig, CartesiaSttProviderOptions, CartesiaTtsProviderOptions, ChannelKind, ChannelLayout, CleanupErrorSummary, CleanupStage, Clock, CompletedSession, CompletedTurn, ConnectedCall, ConnectionObservabilityEvent, ConversationPolicyOptions, CounterIdGenerator, CreateVoiceAgentOptions, CreatedCall, CreatedSession, DeepgramProviderConfig, DeepgramSttProviderOptions, DefineAgentInput, DefineToolInput, DtmfDigit, DtmfReceivedEvent, DualProtocolResult, DurableErrorCode, DurableOutboxEvent, DurableRuntimeMetric, DurableRuntimePolicy, DurableRuntimeStore, DurableSessionTransaction, ElevenLabsBatchSttRequest, ElevenLabsBatchSttResult, ElevenLabsBatchTimestampGranularity, ElevenLabsDialogueInput, ElevenLabsDialogueProvider, ElevenLabsDialogueSynthesisRequest, ElevenLabsDialogueTurnOptions, ElevenLabsEntityDetection, ElevenLabsHttpTtsProviderOptions, ElevenLabsPronunciationDictionaryLocator, ElevenLabsSttCommitStrategy, ElevenLabsSttProviderConfig, ElevenLabsSttProviderOptions, ElevenLabsTextNormalization, ElevenLabsTtsHttpSynthesisRequest, ElevenLabsTtsProviderConfig, ElevenLabsTtsProviderOptions, ElevenLabsTtsSendTextOptions, EndSessionReason, EndSessionRequest, EndTurnRequest, EndedCall, ErrorCategory, ExecuteToolInput, FailedCall, FailedSession, FailedToolCall, FailedToolCallStatus, FailedTurn, GroqChatLlmProviderOptions, GroqProviderConfig, HealthCheckResult, HealthSnapshot, IdGenerator, IdempotencyPolicy, InMemoryDurableRuntimeStore, InMemoryDurableRuntimeStoreOptions, InMemoryMemoryOptions, InboundCallContext, InboundMediaEvent, IncrementalTextToSpeechProvider, InputAudioChunk, InputMediaEvent, InternalMediaEvent, InterruptRequestedEvent, InterruptionMode, InterruptionPolicy, JsonSchemaDocument, JsonValue, LLMProvider, LiveTerminalSource, LlmCompletion, LlmCompletionRequest, LlmInlineToolCall, LlmMessage, LlmMessageRole, LlmProviderConfig, LlmStreamEvent, LlmUsage, ManagedVoiceAgentSession, MediaAudioChunkEvent, MediaAudioCommittedEvent, MediaDirection, MediaErrorEvent, MediaEvent, MediaEventId, MediaEventKind, MediaEventType, MediaStreamEndedEvent, MediaStreamStartedEvent, MediaTransport, MediaTransportKind, Memory, MemoryCapabilities, MemoryEntry, MemoryEntryId, MemoryKind, MemoryPutOptions, MemoryQuery, MemoryRef, MemoryScope, NodeMediaPlaneConnection, NodeMediaPlaneConnectionErrorHandler, NodeMediaPlaneConnectionHandler, NodeMediaPlaneOptions, NodeMediaPlaneRequestHandler, NormalizedAudioEncoding, NormalizedError, OpenAiProviderConfig, OpenAiResponsesLlmProviderOptions, OrganizationId, OutboundCallRequest, OutputAudioChunk, OutputMediaEvent, PersonaConfig, PipelineVoiceLoopOptions, PipelineVoiceLoopResult, PostgresDurableStoreOptions, PostgresMemoryOptions, PostgresMigration, PostgresRedisDurableStoreOptions, PreCallContext, PreCallContextResolver, PreCallMemoryContext, PreCallMemoryResolver, Provider, ProviderAudioCapabilities, ProviderBatchCapabilities, ProviderCancellationCapabilities, ProviderCapabilities, ProviderCatalogEntry, ProviderClock, ProviderCompatibility, ProviderCompatibilityIssue, ProviderCompatibilityIssueCode, ProviderDataPolicy, ProviderEventId, ProviderForKind, ProviderKind, ProviderPlayoutCapabilities, ProviderRequirements, ProviderStability, ProviderStreamingCapabilities, ProviderToolCapabilities, ProviderTransport, QueuedToolCall, RecoveryPollResult, RedisClient, RedisMulti, RedisScanOptions, RedisSetResult, RedisStoreOptions, RequiredProviderCapabilities, RetryPolicy, RingingCall, RunningToolCall, Runtime, RuntimeOptions, RuntimeProvider, RuntimeServiceLifecycle, RuntimeSessionTrace, RuntimeTraceError, SampleRateHz, SarvamOutputMode, SarvamProviderConfig, SarvamSttProviderOptions, SarvamTtsHttpProviderOptions, SarvamTtsProviderConfig, SarvamTtsProviderOptions, SchemaValidationResult, Session, SessionAttachment, SessionAttachmentHealth, SessionCancellationReason, SessionEndEvent, SessionEndMemorySnapshot, SessionId, SessionLease, SessionLeaseStore, SessionMemoryFinalization, SessionMetricsRecorder, SessionReaperOptions, SessionRecoveryCandidate, SessionRecoveryCoordinatorOptions, SessionRuntimeMetadata, SessionSnapshot, SessionState, SessionStatus, SessionStore, SonioxProviderConfig, SonioxStructuredContext, SonioxSttProviderOptions, SpeechToTextProvider, SqlClient$1 as SqlClient, SqlPool$1 as SqlPool, SqlResult, StartAttachedSessionOptions, StartSessionOptions, StartTurnRequest, StartingSession, StoredSessionRecord, StoredToolCallRecord, StoredTurnRecord, StreamEndReason, SttBatchTimestampGranularity, SttBatchTranscription, SttBatchTranscriptionRequest, SttBatchWord, SttCommitMode, SttOpenRequest, SttProviderConfig, SttReconnectOptions, SttRecoveryControl, SttRecoveryState, SttSession, SttSessionInputOptions, SttSessionOptions, SttStream, SttTimestampOrigin, SucceededToolCall, TelephonyProvider, TelephonyProviderConfig, TerminalSession, TerminalSessionDraft, TerminalSessionStatus, TerminalSource, TerminalToolCall, TerminalTurn, TextDeliveryMode, TextOutputDeliveryStatus, TextToSpeechProvider, TimeoutAction, TimeoutPolicy, Timestamp, ToolCall, ToolCallId, ToolCallRuntimeMetadata, ToolCallStatus, ToolCallStore, ToolDefinition, ToolExecutionContext, ToolExecutor, ToolId, ToolIdempotencyClaim, ToolIdempotencyClaimResult, ToolIdempotencyLease, ToolIdempotencyLookupResult, ToolIdempotencyOutcome, ToolIdempotencyQuarantine, ToolIdempotencyQuarantineResult, ToolIdempotencyRecord, ToolIdempotencyRelease, ToolIdempotencyStatus, ToolIdempotencyStore, ToolLogger, ToolName, ToolRegistry, ToolTenant, TranscriptEndpointEvent, TranscriptEndpointReason, TranscriptEvent, TranscriptEventType, TranscriptSegmentEvent, TranscriptSegmentEventType, TranscriptSpeechStartedEvent, TransportAudioEncoding, TransportAudioFormat, TtsAlignmentEvent, TtsAlignmentUnit, TtsEvent, TtsFailoverContext, TtsFailoverPhase, TtsFailoverProviderOptions, TtsFlushAcknowledgement, TtsFlushCompletedEvent, TtsFlushId, TtsFlushResult, TtsProviderConfig, TtsSession, TtsSessionOpenRequest, TtsStream, TtsSynthesisRequest, Turn, TurnCancellationReason, TurnCommitRequestedEvent, TurnDetectionMode, TurnId, TurnInput, TurnLatency, TurnLatencyRecord, TurnOutput, TurnOutputDelivery, TurnRuntimeMetadata, TurnStatus, TurnStore, TvicErrorName, TwilioFlatParams, TwilioMediaStreamCallHandleOptions, TwilioMediaStreamSocket, TwilioParamValue, TwilioParams, UpgradeAuthorization, UserId, VerifyTwilioOptions, VerifyVoiceSessionTokenOptions, VoiceAgent, VoiceAgentCallHandleContext, VoiceAgentCallHandleFactory, VoiceAgentModels, VoiceAgentProviderNames, VoiceAgentProviders, VoiceAgentRun, VoiceAgentRunOptions, VoiceAgentSession, VoiceAgentWithSessionLifecycle, VoiceEvent, VoiceRuntimeFailureMetadata, WebClientAudioCallHandleOptions, WebClientAudioConnectionEvent, WebClientAudioProviderOptions, WebClientAudioSocket, WorkflowId };