@livekit/agents 1.0.27 → 1.0.31

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.
Files changed (100) hide show
  1. package/dist/connection_pool.cjs +242 -0
  2. package/dist/connection_pool.cjs.map +1 -0
  3. package/dist/connection_pool.d.cts +123 -0
  4. package/dist/connection_pool.d.ts +123 -0
  5. package/dist/connection_pool.d.ts.map +1 -0
  6. package/dist/connection_pool.js +218 -0
  7. package/dist/connection_pool.js.map +1 -0
  8. package/dist/connection_pool.test.cjs +256 -0
  9. package/dist/connection_pool.test.cjs.map +1 -0
  10. package/dist/connection_pool.test.js +255 -0
  11. package/dist/connection_pool.test.js.map +1 -0
  12. package/dist/index.cjs +2 -0
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +1 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/inference/tts.cjs +172 -56
  20. package/dist/inference/tts.cjs.map +1 -1
  21. package/dist/inference/tts.d.cts +3 -0
  22. package/dist/inference/tts.d.ts +3 -0
  23. package/dist/inference/tts.d.ts.map +1 -1
  24. package/dist/inference/tts.js +173 -57
  25. package/dist/inference/tts.js.map +1 -1
  26. package/dist/utils.cjs +20 -0
  27. package/dist/utils.cjs.map +1 -1
  28. package/dist/utils.d.cts +7 -0
  29. package/dist/utils.d.ts +7 -0
  30. package/dist/utils.d.ts.map +1 -1
  31. package/dist/utils.js +19 -0
  32. package/dist/utils.js.map +1 -1
  33. package/dist/voice/agent_activity.cjs +3 -1
  34. package/dist/voice/agent_activity.cjs.map +1 -1
  35. package/dist/voice/agent_activity.d.ts.map +1 -1
  36. package/dist/voice/agent_activity.js +3 -1
  37. package/dist/voice/agent_activity.js.map +1 -1
  38. package/dist/voice/agent_session.cjs +4 -1
  39. package/dist/voice/agent_session.cjs.map +1 -1
  40. package/dist/voice/agent_session.d.ts.map +1 -1
  41. package/dist/voice/agent_session.js +4 -1
  42. package/dist/voice/agent_session.js.map +1 -1
  43. package/dist/voice/avatar/datastream_io.cjs +1 -1
  44. package/dist/voice/avatar/datastream_io.cjs.map +1 -1
  45. package/dist/voice/avatar/datastream_io.js +1 -1
  46. package/dist/voice/avatar/datastream_io.js.map +1 -1
  47. package/dist/voice/background_audio.cjs +77 -37
  48. package/dist/voice/background_audio.cjs.map +1 -1
  49. package/dist/voice/background_audio.d.cts +10 -3
  50. package/dist/voice/background_audio.d.ts +10 -3
  51. package/dist/voice/background_audio.d.ts.map +1 -1
  52. package/dist/voice/background_audio.js +78 -37
  53. package/dist/voice/background_audio.js.map +1 -1
  54. package/dist/voice/index.cjs +1 -0
  55. package/dist/voice/index.cjs.map +1 -1
  56. package/dist/voice/index.d.cts +1 -0
  57. package/dist/voice/index.d.ts +1 -0
  58. package/dist/voice/index.d.ts.map +1 -1
  59. package/dist/voice/index.js +1 -0
  60. package/dist/voice/index.js.map +1 -1
  61. package/dist/voice/io.cjs +10 -1
  62. package/dist/voice/io.cjs.map +1 -1
  63. package/dist/voice/io.d.cts +18 -1
  64. package/dist/voice/io.d.ts +18 -1
  65. package/dist/voice/io.d.ts.map +1 -1
  66. package/dist/voice/io.js +10 -1
  67. package/dist/voice/io.js.map +1 -1
  68. package/dist/voice/recorder_io/recorder_io.cjs +1 -1
  69. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -1
  70. package/dist/voice/recorder_io/recorder_io.js +1 -1
  71. package/dist/voice/recorder_io/recorder_io.js.map +1 -1
  72. package/dist/voice/room_io/_output.cjs +1 -1
  73. package/dist/voice/room_io/_output.cjs.map +1 -1
  74. package/dist/voice/room_io/_output.js +1 -1
  75. package/dist/voice/room_io/_output.js.map +1 -1
  76. package/dist/voice/transcription/synchronizer.cjs +1 -1
  77. package/dist/voice/transcription/synchronizer.cjs.map +1 -1
  78. package/dist/voice/transcription/synchronizer.js +1 -1
  79. package/dist/voice/transcription/synchronizer.js.map +1 -1
  80. package/dist/worker.cjs +4 -6
  81. package/dist/worker.cjs.map +1 -1
  82. package/dist/worker.d.ts.map +1 -1
  83. package/dist/worker.js +4 -6
  84. package/dist/worker.js.map +1 -1
  85. package/package.json +3 -3
  86. package/src/connection_pool.test.ts +346 -0
  87. package/src/connection_pool.ts +307 -0
  88. package/src/index.ts +1 -0
  89. package/src/inference/tts.ts +206 -63
  90. package/src/utils.ts +25 -0
  91. package/src/voice/agent_activity.ts +7 -1
  92. package/src/voice/agent_session.ts +4 -1
  93. package/src/voice/avatar/datastream_io.ts +1 -1
  94. package/src/voice/background_audio.ts +95 -55
  95. package/src/voice/index.ts +1 -0
  96. package/src/voice/io.ts +24 -0
  97. package/src/voice/recorder_io/recorder_io.ts +1 -1
  98. package/src/voice/room_io/_output.ts +1 -1
  99. package/src/voice/transcription/synchronizer.ts +1 -1
  100. package/src/worker.ts +4 -7
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var connection_pool_exports = {};
20
+ __export(connection_pool_exports, {
21
+ ConnectionPool: () => ConnectionPool
22
+ });
23
+ module.exports = __toCommonJS(connection_pool_exports);
24
+ var import_mutex = require("@livekit/mutex");
25
+ var import_utils = require("./utils.cjs");
26
+ class ConnectionPool {
27
+ maxSessionDuration;
28
+ markRefreshedOnGet;
29
+ connectCb;
30
+ closeCb;
31
+ connectTimeout;
32
+ // Track connections and their creation timestamps
33
+ connections = /* @__PURE__ */ new Map();
34
+ // Available connections ready for reuse
35
+ available = /* @__PURE__ */ new Set();
36
+ // Connections queued for closing
37
+ toClose = /* @__PURE__ */ new Set();
38
+ // Mutex for connection operations
39
+ connectLock = new import_mutex.Mutex();
40
+ // Prewarm task reference
41
+ prewarmController;
42
+ constructor(options) {
43
+ this.maxSessionDuration = options.maxSessionDuration;
44
+ this.markRefreshedOnGet = options.markRefreshedOnGet ?? false;
45
+ this.connectCb = options.connectCb;
46
+ this.closeCb = options.closeCb;
47
+ this.connectTimeout = options.connectTimeout ?? 1e4;
48
+ }
49
+ /**
50
+ * Create a new connection.
51
+ *
52
+ * @param timeout - Connection timeout in milliseconds
53
+ * @returns The new connection object
54
+ * @throws If connectCb is not provided or connection fails
55
+ */
56
+ async _connect(timeout) {
57
+ const connection = await this.connectCb(timeout);
58
+ this.connections.set(connection, Date.now());
59
+ return connection;
60
+ }
61
+ /**
62
+ * Drain and close all connections queued for closing.
63
+ */
64
+ async _drainToClose() {
65
+ const connectionsToClose = Array.from(this.toClose);
66
+ this.toClose.clear();
67
+ for (const conn of connectionsToClose) {
68
+ await this._maybeCloseConnection(conn);
69
+ }
70
+ }
71
+ /**
72
+ * Close a connection if closeCb is provided.
73
+ *
74
+ * @param conn - The connection to close
75
+ */
76
+ async _maybeCloseConnection(conn) {
77
+ if (this.closeCb) {
78
+ await this.closeCb(conn);
79
+ }
80
+ }
81
+ _abortError() {
82
+ const error = new Error("The operation was aborted.");
83
+ error.name = "AbortError";
84
+ return error;
85
+ }
86
+ /**
87
+ * Get an available connection or create a new one if needed.
88
+ *
89
+ * @param timeout - Connection timeout in milliseconds
90
+ * @returns An active connection object
91
+ */
92
+ async get(timeout) {
93
+ const unlock = await this.connectLock.lock();
94
+ try {
95
+ await this._drainToClose();
96
+ const now = Date.now();
97
+ while (this.available.size > 0) {
98
+ const conn = this.available.values().next().value;
99
+ this.available.delete(conn);
100
+ if (this.maxSessionDuration === void 0 || now - (this.connections.get(conn) ?? 0) <= this.maxSessionDuration) {
101
+ if (this.markRefreshedOnGet) {
102
+ this.connections.set(conn, now);
103
+ }
104
+ return conn;
105
+ }
106
+ if (this.connections.has(conn)) {
107
+ this.connections.delete(conn);
108
+ }
109
+ this.toClose.delete(conn);
110
+ await this._maybeCloseConnection(conn);
111
+ }
112
+ return await this._connect(timeout ?? this.connectTimeout);
113
+ } finally {
114
+ unlock();
115
+ }
116
+ }
117
+ /**
118
+ * Mark a connection as available for reuse.
119
+ *
120
+ * If connection has been removed, it will not be added to the pool.
121
+ *
122
+ * @param conn - The connection to make available
123
+ */
124
+ put(conn) {
125
+ if (this.connections.has(conn)) {
126
+ this.available.add(conn);
127
+ return;
128
+ }
129
+ }
130
+ /**
131
+ * Remove a specific connection from the pool.
132
+ *
133
+ * Marks the connection to be closed during the next drain cycle.
134
+ *
135
+ * @param conn - The connection to remove
136
+ */
137
+ remove(conn) {
138
+ this.available.delete(conn);
139
+ if (this.connections.has(conn)) {
140
+ this.toClose.add(conn);
141
+ this.connections.delete(conn);
142
+ void (async () => {
143
+ const unlock = await this.connectLock.lock();
144
+ try {
145
+ if (!this.toClose.has(conn)) return;
146
+ await this._maybeCloseConnection(conn);
147
+ this.toClose.delete(conn);
148
+ } finally {
149
+ unlock();
150
+ }
151
+ })();
152
+ }
153
+ }
154
+ /**
155
+ * Clear all existing connections.
156
+ *
157
+ * Marks all current connections to be closed during the next drain cycle.
158
+ */
159
+ invalidate() {
160
+ for (const conn of this.connections.keys()) {
161
+ this.toClose.add(conn);
162
+ }
163
+ this.connections.clear();
164
+ this.available.clear();
165
+ }
166
+ /**
167
+ * Initiate prewarming of the connection pool without blocking.
168
+ *
169
+ * This method starts a background task that creates a new connection if none exist.
170
+ * The task automatically cleans itself up when the connection pool is closed.
171
+ */
172
+ prewarm() {
173
+ if (this.prewarmController || this.connections.size > 0) {
174
+ return;
175
+ }
176
+ const controller = new AbortController();
177
+ this.prewarmController = controller;
178
+ this._prewarmImpl(controller.signal).catch(() => {
179
+ });
180
+ }
181
+ async _prewarmImpl(signal) {
182
+ const unlock = await this.connectLock.lock();
183
+ try {
184
+ if (signal.aborted) {
185
+ return;
186
+ }
187
+ if (this.connections.size === 0) {
188
+ const conn = await this._connect(this.connectTimeout);
189
+ this.available.add(conn);
190
+ }
191
+ } finally {
192
+ unlock();
193
+ }
194
+ }
195
+ /**
196
+ * Get a connection from the pool and automatically return it when done.
197
+ * Handles abort signals and ensures proper cleanup.
198
+ *
199
+ * @param fn - Function to execute with the connection
200
+ * @param options - Options including timeout and abort signal
201
+ * @returns The result of the function
202
+ */
203
+ async withConnection(fn, options) {
204
+ var _a;
205
+ if ((_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.aborted) {
206
+ throw this._abortError();
207
+ }
208
+ const conn = await this.get(options == null ? void 0 : options.timeout);
209
+ const signal = options == null ? void 0 : options.signal;
210
+ try {
211
+ const fnPromise = fn(conn);
212
+ const result = signal ? await Promise.race([
213
+ fnPromise.then((value) => ({ type: "result", value })),
214
+ (0, import_utils.waitForAbort)(signal).then(() => ({ type: "abort" }))
215
+ ]).then((r) => {
216
+ if (r.type === "abort") throw this._abortError();
217
+ return r.value;
218
+ }) : await fnPromise;
219
+ this.put(conn);
220
+ return result;
221
+ } catch (error) {
222
+ this.remove(conn);
223
+ throw error;
224
+ }
225
+ }
226
+ /**
227
+ * Close all connections, draining any pending connection closures.
228
+ */
229
+ async close() {
230
+ if (this.prewarmController) {
231
+ this.prewarmController.abort();
232
+ this.prewarmController = void 0;
233
+ }
234
+ this.invalidate();
235
+ await this._drainToClose();
236
+ }
237
+ }
238
+ // Annotate the CommonJS export names for ESM import in node:
239
+ 0 && (module.exports = {
240
+ ConnectionPool
241
+ });
242
+ //# sourceMappingURL=connection_pool.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection_pool.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport { waitForAbort } from './utils.js';\n\n/**\n * Helper class to manage persistent connections like websockets.\n */\nexport interface ConnectionPoolOptions<T> {\n /**\n * Maximum duration in milliseconds before forcing reconnection.\n * If not set, connections will never expire based on duration.\n */\n maxSessionDuration?: number;\n\n /**\n * If true, the session will be marked as fresh when get() is called.\n * Only used when maxSessionDuration is set.\n */\n markRefreshedOnGet?: boolean;\n\n /**\n * Async callback to create new connections.\n * @param timeout - Connection timeout in milliseconds\n * @returns A new connection object\n */\n connectCb: (timeout: number) => Promise<T>;\n\n /**\n * Optional async callback to close connections.\n * @param conn - The connection to close\n */\n closeCb?: (conn: T) => Promise<void>;\n\n /**\n * Default connection timeout in milliseconds.\n * Defaults to 10000 (10 seconds).\n */\n connectTimeout?: number;\n}\n\n/**\n * Connection pool for managing persistent WebSocket connections.\n *\n * Reuses connections efficiently and automatically refreshes them after max duration.\n * Prevents creating too many connections in a single conversation.\n */\nexport class ConnectionPool<T> {\n private readonly maxSessionDuration?: number;\n private readonly markRefreshedOnGet: boolean;\n private readonly connectCb: (timeout: number) => Promise<T>;\n private readonly closeCb?: (conn: T) => Promise<void>;\n private readonly connectTimeout: number;\n\n // Track connections and their creation timestamps\n private readonly connections: Map<T, number> = new Map();\n // Available connections ready for reuse\n private readonly available: Set<T> = new Set();\n // Connections queued for closing\n private readonly toClose: Set<T> = new Set();\n // Mutex for connection operations\n private readonly connectLock = new Mutex();\n // Prewarm task reference\n private prewarmController?: AbortController;\n\n constructor(options: ConnectionPoolOptions<T>) {\n this.maxSessionDuration = options.maxSessionDuration;\n this.markRefreshedOnGet = options.markRefreshedOnGet ?? false;\n this.connectCb = options.connectCb;\n this.closeCb = options.closeCb;\n this.connectTimeout = options.connectTimeout ?? 10_000;\n }\n\n /**\n * Create a new connection.\n *\n * @param timeout - Connection timeout in milliseconds\n * @returns The new connection object\n * @throws If connectCb is not provided or connection fails\n */\n private async _connect(timeout: number): Promise<T> {\n const connection = await this.connectCb(timeout);\n this.connections.set(connection, Date.now());\n return connection;\n }\n\n /**\n * Drain and close all connections queued for closing.\n */\n private async _drainToClose(): Promise<void> {\n const connectionsToClose = Array.from(this.toClose);\n this.toClose.clear();\n\n for (const conn of connectionsToClose) {\n await this._maybeCloseConnection(conn);\n }\n }\n\n /**\n * Close a connection if closeCb is provided.\n *\n * @param conn - The connection to close\n */\n private async _maybeCloseConnection(conn: T): Promise<void> {\n if (this.closeCb) {\n await this.closeCb(conn);\n }\n }\n\n private _abortError(): Error {\n const error = new Error('The operation was aborted.');\n error.name = 'AbortError';\n return error;\n }\n\n /**\n * Get an available connection or create a new one if needed.\n *\n * @param timeout - Connection timeout in milliseconds\n * @returns An active connection object\n */\n async get(timeout?: number): Promise<T> {\n const unlock = await this.connectLock.lock();\n try {\n await this._drainToClose();\n const now = Date.now();\n\n // Try to reuse an available connection that hasn't expired\n while (this.available.size > 0) {\n const conn = this.available.values().next().value as T;\n this.available.delete(conn);\n\n if (\n this.maxSessionDuration === undefined ||\n now - (this.connections.get(conn) ?? 0) <= this.maxSessionDuration\n ) {\n if (this.markRefreshedOnGet) {\n this.connections.set(conn, now);\n }\n return conn;\n }\n\n // Connection expired; close it now so callers observing get() see it closed promptly.\n // (Also makes tests deterministic: closeCb should have been called by the time get() resolves.)\n if (this.connections.has(conn)) {\n this.connections.delete(conn);\n }\n this.toClose.delete(conn);\n await this._maybeCloseConnection(conn);\n }\n\n return await this._connect(timeout ?? this.connectTimeout);\n } finally {\n unlock();\n }\n }\n\n /**\n * Mark a connection as available for reuse.\n *\n * If connection has been removed, it will not be added to the pool.\n *\n * @param conn - The connection to make available\n */\n put(conn: T): void {\n if (this.connections.has(conn)) {\n this.available.add(conn);\n return;\n }\n }\n\n /**\n * Remove a specific connection from the pool.\n *\n * Marks the connection to be closed during the next drain cycle.\n *\n * @param conn - The connection to remove\n */\n remove(conn: T): void {\n this.available.delete(conn);\n if (this.connections.has(conn)) {\n this.toClose.add(conn);\n this.connections.delete(conn);\n // Important for Node websockets: if we just \"mark to close later\" but remove listeners,\n // the ws library can buffer incoming frames in memory. Close ASAP in background.\n void (async () => {\n const unlock = await this.connectLock.lock();\n try {\n if (!this.toClose.has(conn)) return;\n await this._maybeCloseConnection(conn);\n this.toClose.delete(conn);\n } finally {\n unlock();\n }\n })();\n }\n }\n\n /**\n * Clear all existing connections.\n *\n * Marks all current connections to be closed during the next drain cycle.\n */\n invalidate(): void {\n for (const conn of this.connections.keys()) {\n this.toClose.add(conn);\n }\n this.connections.clear();\n this.available.clear();\n }\n\n /**\n * Initiate prewarming of the connection pool without blocking.\n *\n * This method starts a background task that creates a new connection if none exist.\n * The task automatically cleans itself up when the connection pool is closed.\n */\n prewarm(): void {\n if (this.prewarmController || this.connections.size > 0) {\n return;\n }\n\n const controller = new AbortController();\n this.prewarmController = controller;\n\n // Start prewarm in background\n this._prewarmImpl(controller.signal).catch(() => {\n // Ignore errors during prewarm\n });\n }\n\n private async _prewarmImpl(signal: AbortSignal): Promise<void> {\n const unlock = await this.connectLock.lock();\n try {\n if (signal.aborted) {\n return;\n }\n\n if (this.connections.size === 0) {\n const conn = await this._connect(this.connectTimeout);\n this.available.add(conn);\n }\n } finally {\n unlock();\n }\n }\n\n /**\n * Get a connection from the pool and automatically return it when done.\n * Handles abort signals and ensures proper cleanup.\n *\n * @param fn - Function to execute with the connection\n * @param options - Options including timeout and abort signal\n * @returns The result of the function\n */\n async withConnection<R>(\n fn: (conn: T) => Promise<R>,\n options?: {\n timeout?: number;\n signal?: AbortSignal;\n },\n ): Promise<R> {\n // Check if already aborted before getting connection\n if (options?.signal?.aborted) {\n throw this._abortError();\n }\n\n const conn = await this.get(options?.timeout);\n\n const signal = options?.signal;\n\n try {\n const fnPromise = fn(conn);\n const result = signal\n ? await Promise.race([\n fnPromise.then((value) => ({ type: 'result' as const, value })),\n waitForAbort(signal).then(() => ({ type: 'abort' as const })),\n ]).then((r) => {\n if (r.type === 'abort') throw this._abortError();\n return r.value;\n })\n : await fnPromise;\n // Return connection to pool on success\n this.put(conn);\n return result;\n } catch (error) {\n // Remove connection from pool on error (don't return it)\n this.remove(conn);\n throw error;\n }\n }\n\n /**\n * Close all connections, draining any pending connection closures.\n */\n async close(): Promise<void> {\n // Cancel prewarm task if running\n if (this.prewarmController) {\n this.prewarmController.abort();\n this.prewarmController = undefined;\n }\n\n this.invalidate();\n await this._drainToClose();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Helper class to manage persistent connections like websockets.
3
+ */
4
+ export interface ConnectionPoolOptions<T> {
5
+ /**
6
+ * Maximum duration in milliseconds before forcing reconnection.
7
+ * If not set, connections will never expire based on duration.
8
+ */
9
+ maxSessionDuration?: number;
10
+ /**
11
+ * If true, the session will be marked as fresh when get() is called.
12
+ * Only used when maxSessionDuration is set.
13
+ */
14
+ markRefreshedOnGet?: boolean;
15
+ /**
16
+ * Async callback to create new connections.
17
+ * @param timeout - Connection timeout in milliseconds
18
+ * @returns A new connection object
19
+ */
20
+ connectCb: (timeout: number) => Promise<T>;
21
+ /**
22
+ * Optional async callback to close connections.
23
+ * @param conn - The connection to close
24
+ */
25
+ closeCb?: (conn: T) => Promise<void>;
26
+ /**
27
+ * Default connection timeout in milliseconds.
28
+ * Defaults to 10000 (10 seconds).
29
+ */
30
+ connectTimeout?: number;
31
+ }
32
+ /**
33
+ * Connection pool for managing persistent WebSocket connections.
34
+ *
35
+ * Reuses connections efficiently and automatically refreshes them after max duration.
36
+ * Prevents creating too many connections in a single conversation.
37
+ */
38
+ export declare class ConnectionPool<T> {
39
+ private readonly maxSessionDuration?;
40
+ private readonly markRefreshedOnGet;
41
+ private readonly connectCb;
42
+ private readonly closeCb?;
43
+ private readonly connectTimeout;
44
+ private readonly connections;
45
+ private readonly available;
46
+ private readonly toClose;
47
+ private readonly connectLock;
48
+ private prewarmController?;
49
+ constructor(options: ConnectionPoolOptions<T>);
50
+ /**
51
+ * Create a new connection.
52
+ *
53
+ * @param timeout - Connection timeout in milliseconds
54
+ * @returns The new connection object
55
+ * @throws If connectCb is not provided or connection fails
56
+ */
57
+ private _connect;
58
+ /**
59
+ * Drain and close all connections queued for closing.
60
+ */
61
+ private _drainToClose;
62
+ /**
63
+ * Close a connection if closeCb is provided.
64
+ *
65
+ * @param conn - The connection to close
66
+ */
67
+ private _maybeCloseConnection;
68
+ private _abortError;
69
+ /**
70
+ * Get an available connection or create a new one if needed.
71
+ *
72
+ * @param timeout - Connection timeout in milliseconds
73
+ * @returns An active connection object
74
+ */
75
+ get(timeout?: number): Promise<T>;
76
+ /**
77
+ * Mark a connection as available for reuse.
78
+ *
79
+ * If connection has been removed, it will not be added to the pool.
80
+ *
81
+ * @param conn - The connection to make available
82
+ */
83
+ put(conn: T): void;
84
+ /**
85
+ * Remove a specific connection from the pool.
86
+ *
87
+ * Marks the connection to be closed during the next drain cycle.
88
+ *
89
+ * @param conn - The connection to remove
90
+ */
91
+ remove(conn: T): void;
92
+ /**
93
+ * Clear all existing connections.
94
+ *
95
+ * Marks all current connections to be closed during the next drain cycle.
96
+ */
97
+ invalidate(): void;
98
+ /**
99
+ * Initiate prewarming of the connection pool without blocking.
100
+ *
101
+ * This method starts a background task that creates a new connection if none exist.
102
+ * The task automatically cleans itself up when the connection pool is closed.
103
+ */
104
+ prewarm(): void;
105
+ private _prewarmImpl;
106
+ /**
107
+ * Get a connection from the pool and automatically return it when done.
108
+ * Handles abort signals and ensures proper cleanup.
109
+ *
110
+ * @param fn - Function to execute with the connection
111
+ * @param options - Options including timeout and abort signal
112
+ * @returns The result of the function
113
+ */
114
+ withConnection<R>(fn: (conn: T) => Promise<R>, options?: {
115
+ timeout?: number;
116
+ signal?: AbortSignal;
117
+ }): Promise<R>;
118
+ /**
119
+ * Close all connections, draining any pending connection closures.
120
+ */
121
+ close(): Promise<void>;
122
+ }
123
+ //# sourceMappingURL=connection_pool.d.ts.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Helper class to manage persistent connections like websockets.
3
+ */
4
+ export interface ConnectionPoolOptions<T> {
5
+ /**
6
+ * Maximum duration in milliseconds before forcing reconnection.
7
+ * If not set, connections will never expire based on duration.
8
+ */
9
+ maxSessionDuration?: number;
10
+ /**
11
+ * If true, the session will be marked as fresh when get() is called.
12
+ * Only used when maxSessionDuration is set.
13
+ */
14
+ markRefreshedOnGet?: boolean;
15
+ /**
16
+ * Async callback to create new connections.
17
+ * @param timeout - Connection timeout in milliseconds
18
+ * @returns A new connection object
19
+ */
20
+ connectCb: (timeout: number) => Promise<T>;
21
+ /**
22
+ * Optional async callback to close connections.
23
+ * @param conn - The connection to close
24
+ */
25
+ closeCb?: (conn: T) => Promise<void>;
26
+ /**
27
+ * Default connection timeout in milliseconds.
28
+ * Defaults to 10000 (10 seconds).
29
+ */
30
+ connectTimeout?: number;
31
+ }
32
+ /**
33
+ * Connection pool for managing persistent WebSocket connections.
34
+ *
35
+ * Reuses connections efficiently and automatically refreshes them after max duration.
36
+ * Prevents creating too many connections in a single conversation.
37
+ */
38
+ export declare class ConnectionPool<T> {
39
+ private readonly maxSessionDuration?;
40
+ private readonly markRefreshedOnGet;
41
+ private readonly connectCb;
42
+ private readonly closeCb?;
43
+ private readonly connectTimeout;
44
+ private readonly connections;
45
+ private readonly available;
46
+ private readonly toClose;
47
+ private readonly connectLock;
48
+ private prewarmController?;
49
+ constructor(options: ConnectionPoolOptions<T>);
50
+ /**
51
+ * Create a new connection.
52
+ *
53
+ * @param timeout - Connection timeout in milliseconds
54
+ * @returns The new connection object
55
+ * @throws If connectCb is not provided or connection fails
56
+ */
57
+ private _connect;
58
+ /**
59
+ * Drain and close all connections queued for closing.
60
+ */
61
+ private _drainToClose;
62
+ /**
63
+ * Close a connection if closeCb is provided.
64
+ *
65
+ * @param conn - The connection to close
66
+ */
67
+ private _maybeCloseConnection;
68
+ private _abortError;
69
+ /**
70
+ * Get an available connection or create a new one if needed.
71
+ *
72
+ * @param timeout - Connection timeout in milliseconds
73
+ * @returns An active connection object
74
+ */
75
+ get(timeout?: number): Promise<T>;
76
+ /**
77
+ * Mark a connection as available for reuse.
78
+ *
79
+ * If connection has been removed, it will not be added to the pool.
80
+ *
81
+ * @param conn - The connection to make available
82
+ */
83
+ put(conn: T): void;
84
+ /**
85
+ * Remove a specific connection from the pool.
86
+ *
87
+ * Marks the connection to be closed during the next drain cycle.
88
+ *
89
+ * @param conn - The connection to remove
90
+ */
91
+ remove(conn: T): void;
92
+ /**
93
+ * Clear all existing connections.
94
+ *
95
+ * Marks all current connections to be closed during the next drain cycle.
96
+ */
97
+ invalidate(): void;
98
+ /**
99
+ * Initiate prewarming of the connection pool without blocking.
100
+ *
101
+ * This method starts a background task that creates a new connection if none exist.
102
+ * The task automatically cleans itself up when the connection pool is closed.
103
+ */
104
+ prewarm(): void;
105
+ private _prewarmImpl;
106
+ /**
107
+ * Get a connection from the pool and automatically return it when done.
108
+ * Handles abort signals and ensures proper cleanup.
109
+ *
110
+ * @param fn - Function to execute with the connection
111
+ * @param options - Options including timeout and abort signal
112
+ * @returns The result of the function
113
+ */
114
+ withConnection<R>(fn: (conn: T) => Promise<R>, options?: {
115
+ timeout?: number;
116
+ signal?: AbortSignal;
117
+ }): Promise<R>;
118
+ /**
119
+ * Close all connections, draining any pending connection closures.
120
+ */
121
+ close(): Promise<void>;
122
+ }
123
+ //# sourceMappingURL=connection_pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection_pool.d.ts","sourceRoot":"","sources":["../src/connection_pool.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;OAIG;IACH,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAGxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAE/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAE3C,OAAO,CAAC,iBAAiB,CAAC,CAAkB;gBAEhC,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAQ7C;;;;;;OAMG;YACW,QAAQ;IAMtB;;OAEG;YACW,aAAa;IAS3B;;;;OAIG;YACW,qBAAqB;IAMnC,OAAO,CAAC,WAAW;IAMnB;;;;;OAKG;IACG,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAoCvC;;;;;;OAMG;IACH,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAOlB;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAoBrB;;;;OAIG;IACH,UAAU,IAAI,IAAI;IAQlB;;;;;OAKG;IACH,OAAO,IAAI,IAAI;YAcD,YAAY;IAgB1B;;;;;;;OAOG;IACG,cAAc,CAAC,CAAC,EACpB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GACA,OAAO,CAAC,CAAC,CAAC;IA+Bb;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU7B"}