openai 7.15.0 → 7.16.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/CHANGELOG.md +34 -0
- package/README.md +6 -0
- package/bedrock.d.mts.map +1 -1
- package/bedrock.d.ts.map +1 -1
- package/bedrock.js +9 -6
- package/bedrock.js.map +1 -1
- package/bedrock.mjs +9 -6
- package/bedrock.mjs.map +1 -1
- package/client.d.mts +13 -3
- package/client.d.mts.map +1 -1
- package/client.d.ts +13 -3
- package/client.d.ts.map +1 -1
- package/client.js +37 -20
- package/client.js.map +1 -1
- package/client.mjs +37 -20
- package/client.mjs.map +1 -1
- package/internal/realtime-credentials.d.mts +1 -1
- package/internal/realtime-credentials.d.ts +1 -1
- package/internal/realtime-credentials.js +1 -1
- package/internal/realtime-credentials.mjs +1 -1
- package/internal/utils/abort.d.mts +11 -0
- package/internal/utils/abort.d.mts.map +1 -0
- package/internal/utils/abort.d.ts +11 -0
- package/internal/utils/abort.d.ts.map +1 -0
- package/internal/utils/abort.js +87 -0
- package/internal/utils/abort.js.map +1 -0
- package/internal/utils/abort.mjs +83 -0
- package/internal/utils/abort.mjs.map +1 -0
- package/internal/ws.d.mts +13 -0
- package/internal/ws.d.mts.map +1 -1
- package/internal/ws.d.ts +13 -0
- package/internal/ws.d.ts.map +1 -1
- package/internal/ws.js +10 -0
- package/internal/ws.js.map +1 -1
- package/internal/ws.mjs +9 -0
- package/internal/ws.mjs.map +1 -1
- package/lib/live/transcript-grouping.d.mts +2 -2
- package/lib/live/transcript-grouping.d.mts.map +1 -1
- package/lib/live/transcript-grouping.d.ts +2 -2
- package/lib/live/transcript-grouping.d.ts.map +1 -1
- package/lib/live/transcript-grouping.js +44 -22
- package/lib/live/transcript-grouping.js.map +1 -1
- package/lib/live/transcript-grouping.mjs +44 -22
- package/lib/live/transcript-grouping.mjs.map +1 -1
- package/package.json +1 -1
- package/resources/beta/responses/internal-base.d.mts.map +1 -1
- package/resources/beta/responses/internal-base.d.ts.map +1 -1
- package/resources/beta/responses/internal-base.js +6 -0
- package/resources/beta/responses/internal-base.js.map +1 -1
- package/resources/beta/responses/internal-base.mjs +6 -0
- package/resources/beta/responses/internal-base.mjs.map +1 -1
- package/resources/beta/responses/ws-base.d.mts +13 -8
- package/resources/beta/responses/ws-base.d.mts.map +1 -1
- package/resources/beta/responses/ws-base.d.ts +13 -8
- package/resources/beta/responses/ws-base.d.ts.map +1 -1
- package/resources/beta/responses/ws-base.js +85 -14
- package/resources/beta/responses/ws-base.js.map +1 -1
- package/resources/beta/responses/ws-base.mjs +87 -16
- package/resources/beta/responses/ws-base.mjs.map +1 -1
- package/resources/beta/responses/ws.d.mts +1 -0
- package/resources/beta/responses/ws.d.mts.map +1 -1
- package/resources/beta/responses/ws.d.ts +1 -0
- package/resources/beta/responses/ws.d.ts.map +1 -1
- package/resources/beta/responses/ws.js.map +1 -1
- package/resources/beta/responses/ws.mjs.map +1 -1
- package/resources/live/forks/ws-base.d.mts +13 -8
- package/resources/live/forks/ws-base.d.mts.map +1 -1
- package/resources/live/forks/ws-base.d.ts +13 -8
- package/resources/live/forks/ws-base.d.ts.map +1 -1
- package/resources/live/forks/ws-base.js +85 -14
- package/resources/live/forks/ws-base.js.map +1 -1
- package/resources/live/forks/ws-base.mjs +87 -16
- package/resources/live/forks/ws-base.mjs.map +1 -1
- package/resources/live/forks/ws.d.mts +1 -0
- package/resources/live/forks/ws.d.mts.map +1 -1
- package/resources/live/forks/ws.d.ts +1 -0
- package/resources/live/forks/ws.d.ts.map +1 -1
- package/resources/live/forks/ws.js.map +1 -1
- package/resources/live/forks/ws.mjs.map +1 -1
- package/resources/live/sideband/ws-base.d.mts +13 -8
- package/resources/live/sideband/ws-base.d.mts.map +1 -1
- package/resources/live/sideband/ws-base.d.ts +13 -8
- package/resources/live/sideband/ws-base.d.ts.map +1 -1
- package/resources/live/sideband/ws-base.js +85 -14
- package/resources/live/sideband/ws-base.js.map +1 -1
- package/resources/live/sideband/ws-base.mjs +87 -16
- package/resources/live/sideband/ws-base.mjs.map +1 -1
- package/resources/live/sideband/ws.d.mts +1 -0
- package/resources/live/sideband/ws.d.mts.map +1 -1
- package/resources/live/sideband/ws.d.ts +1 -0
- package/resources/live/sideband/ws.d.ts.map +1 -1
- package/resources/live/sideband/ws.js.map +1 -1
- package/resources/live/sideband/ws.mjs.map +1 -1
- package/resources/live/ws-base.d.mts +13 -8
- package/resources/live/ws-base.d.mts.map +1 -1
- package/resources/live/ws-base.d.ts +13 -8
- package/resources/live/ws-base.d.ts.map +1 -1
- package/resources/live/ws-base.js +85 -14
- package/resources/live/ws-base.js.map +1 -1
- package/resources/live/ws-base.mjs +87 -16
- package/resources/live/ws-base.mjs.map +1 -1
- package/resources/live/ws.d.mts +1 -0
- package/resources/live/ws.d.mts.map +1 -1
- package/resources/live/ws.d.ts +1 -0
- package/resources/live/ws.d.ts.map +1 -1
- package/resources/live/ws.js.map +1 -1
- package/resources/live/ws.mjs.map +1 -1
- package/resources/responses/internal-base.d.mts.map +1 -1
- package/resources/responses/internal-base.d.ts.map +1 -1
- package/resources/responses/internal-base.js +6 -0
- package/resources/responses/internal-base.js.map +1 -1
- package/resources/responses/internal-base.mjs +6 -0
- package/resources/responses/internal-base.mjs.map +1 -1
- package/resources/responses/ws-base.d.mts +13 -8
- package/resources/responses/ws-base.d.mts.map +1 -1
- package/resources/responses/ws-base.d.ts +13 -8
- package/resources/responses/ws-base.d.ts.map +1 -1
- package/resources/responses/ws-base.js +85 -14
- package/resources/responses/ws-base.js.map +1 -1
- package/resources/responses/ws-base.mjs +87 -16
- package/resources/responses/ws-base.mjs.map +1 -1
- package/resources/responses/ws.d.mts +1 -0
- package/resources/responses/ws.d.mts.map +1 -1
- package/resources/responses/ws.d.ts +1 -0
- package/resources/responses/ws.d.ts.map +1 -1
- package/resources/responses/ws.js.map +1 -1
- package/resources/responses/ws.mjs.map +1 -1
- package/src/bedrock.ts +18 -7
- package/src/client.ts +43 -19
- package/src/internal/realtime-credentials.ts +1 -1
- package/src/internal/utils/abort.ts +111 -0
- package/src/internal/ws.ts +22 -0
- package/src/lib/live/transcript-grouping.ts +59 -27
- package/src/resources/beta/responses/internal-base.ts +5 -0
- package/src/resources/beta/responses/ws-base.ts +110 -21
- package/src/resources/beta/responses/ws.ts +2 -0
- package/src/resources/live/forks/ws-base.ts +110 -21
- package/src/resources/live/forks/ws.ts +2 -0
- package/src/resources/live/sideband/ws-base.ts +110 -21
- package/src/resources/live/sideband/ws.ts +2 -0
- package/src/resources/live/ws-base.ts +110 -21
- package/src/resources/live/ws.ts +2 -0
- package/src/resources/responses/internal-base.ts +5 -0
- package/src/resources/responses/ws-base.ts +110 -21
- package/src/resources/responses/ws.ts +2 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -6,6 +6,8 @@ import { sleep } from '../../internal/utils/sleep';
|
|
|
6
6
|
import { type WebSocketLike, ReadyState } from '../../internal/ws-adapter';
|
|
7
7
|
import {
|
|
8
8
|
SendQueue,
|
|
9
|
+
getMaxBufferedEvents,
|
|
10
|
+
type WebSocketStreamOptions,
|
|
9
11
|
flattenRawData,
|
|
10
12
|
isRecoverableClose,
|
|
11
13
|
type RawWebSocketData,
|
|
@@ -51,11 +53,11 @@ export interface LiveWSBaseOptions {
|
|
|
51
53
|
reconnect?: LiveWSReconnectOptions | null | undefined;
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* Default: 1
|
|
56
|
+
* Byte budget for outgoing messages queued while the socket is connecting
|
|
57
|
+
* or reconnecting. An empty queue accepts one message even if it exceeds
|
|
58
|
+
* this budget. Further messages are discarded and an `error` event is emitted
|
|
59
|
+
* if the total queued size would exceed the budget.
|
|
60
|
+
* Default: 1 MiB (1,048,576 bytes).
|
|
59
61
|
*/
|
|
60
62
|
maxQueueSize?: number | undefined;
|
|
61
63
|
}
|
|
@@ -165,6 +167,11 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
165
167
|
* The iterator will exit if the socket closes but exiting the iterator
|
|
166
168
|
* does not close the socket.
|
|
167
169
|
*
|
|
170
|
+
* Pass `maxBufferedEvents` to limit queued records for this iterator, including
|
|
171
|
+
* lifecycle events. Overflow discards its backlog and rejects `next()` with a
|
|
172
|
+
* WebSocketError; the shared socket and other iterators remain active.
|
|
173
|
+
* Omitted means unlimited. This is an event-count limit, not a byte limit.
|
|
174
|
+
*
|
|
168
175
|
* @example
|
|
169
176
|
* ```ts
|
|
170
177
|
* for await (const event of client.stream()) {
|
|
@@ -182,26 +189,59 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
182
189
|
* }
|
|
183
190
|
* ```
|
|
184
191
|
*/
|
|
185
|
-
stream(): AsyncIterableIterator<LiveStreamMessage> {
|
|
186
|
-
return this[Symbol.asyncIterator]();
|
|
192
|
+
stream(options?: WebSocketStreamOptions): AsyncIterableIterator<LiveStreamMessage> {
|
|
193
|
+
return options === undefined ? this[Symbol.asyncIterator]() : this[Symbol.asyncIterator](options);
|
|
187
194
|
}
|
|
188
195
|
|
|
189
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<LiveStreamMessage> {
|
|
196
|
+
[Symbol.asyncIterator](options?: WebSocketStreamOptions): AsyncIterableIterator<LiveStreamMessage> {
|
|
190
197
|
if (!this.socket) {
|
|
191
198
|
throw new OpenAIError('Internal error: failed to initialize socket. Please report this issue.');
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
const maxBufferedEvents = getMaxBufferedEvents(options);
|
|
202
|
+
|
|
194
203
|
// Two-queue async iterator: `queue` buffers incoming messages,
|
|
195
204
|
// `resolvers` buffers waiting next() calls. A push wakes the
|
|
196
205
|
// oldest next(); a next() drains the oldest message.
|
|
197
|
-
const queue: LiveStreamMessage[] = [];
|
|
198
|
-
const resolvers: (() => void)[] = [];
|
|
206
|
+
const queue: (LiveStreamMessage | undefined)[] = [];
|
|
207
|
+
const resolvers: ((() => void) | undefined)[] = [];
|
|
208
|
+
let queueHead = 0;
|
|
209
|
+
let resolverHead = 0;
|
|
199
210
|
let done = false;
|
|
211
|
+
let failure: WebSocketError | undefined;
|
|
200
212
|
let currentSocket = this.socket;
|
|
201
213
|
|
|
214
|
+
const wakeResolver = () => {
|
|
215
|
+
if (resolverHead >= resolvers.length) return;
|
|
216
|
+
|
|
217
|
+
const resolver = resolvers[resolverHead];
|
|
218
|
+
resolvers[resolverHead] = undefined;
|
|
219
|
+
resolverHead += 1;
|
|
220
|
+
if (resolverHead >= 64 && resolverHead * 2 >= resolvers.length) {
|
|
221
|
+
resolvers.splice(0, resolverHead);
|
|
222
|
+
resolverHead = 0;
|
|
223
|
+
}
|
|
224
|
+
resolver?.();
|
|
225
|
+
};
|
|
226
|
+
|
|
202
227
|
const push = (msg: LiveStreamMessage) => {
|
|
228
|
+
if (done) return;
|
|
229
|
+
|
|
230
|
+
if (maxBufferedEvents !== undefined && queue.length - queueHead >= maxBufferedEvents) {
|
|
231
|
+
failure = new WebSocketError(
|
|
232
|
+
`WebSocket stream exceeded maxBufferedEvents (${maxBufferedEvents})`,
|
|
233
|
+
null,
|
|
234
|
+
);
|
|
235
|
+
done = true;
|
|
236
|
+
queue.length = 0;
|
|
237
|
+
queueHead = 0;
|
|
238
|
+
cleanup();
|
|
239
|
+
flushResolvers();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
203
243
|
queue.push(msg);
|
|
204
|
-
|
|
244
|
+
wakeResolver();
|
|
205
245
|
};
|
|
206
246
|
|
|
207
247
|
const onEvent = (event: LiveAPI.ServerEvent) => {
|
|
@@ -231,9 +271,14 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
231
271
|
};
|
|
232
272
|
|
|
233
273
|
const flushResolvers = () => {
|
|
234
|
-
|
|
235
|
-
resolver
|
|
274
|
+
while (resolverHead < resolvers.length) {
|
|
275
|
+
const resolver = resolvers[resolverHead];
|
|
276
|
+
resolvers[resolverHead] = undefined;
|
|
277
|
+
resolverHead += 1;
|
|
278
|
+
resolver?.();
|
|
236
279
|
}
|
|
280
|
+
resolvers.length = 0;
|
|
281
|
+
resolverHead = 0;
|
|
237
282
|
};
|
|
238
283
|
|
|
239
284
|
const onClose = (code: number, reason: string, unsent: UnsentMessage<LiveAPI.ClientEvent>[]) => {
|
|
@@ -243,8 +288,9 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
243
288
|
cleanup();
|
|
244
289
|
};
|
|
245
290
|
|
|
246
|
-
const onSocketSwap = (
|
|
247
|
-
|
|
291
|
+
const onSocketSwap = (_oldSocket: TSocket, newSocket: TSocket) => {
|
|
292
|
+
if (currentSocket === newSocket) return;
|
|
293
|
+
currentSocket.off('open', onOpen);
|
|
248
294
|
newSocket.on('open', onOpen);
|
|
249
295
|
currentSocket = newSocket;
|
|
250
296
|
};
|
|
@@ -301,9 +347,21 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
301
347
|
}
|
|
302
348
|
}
|
|
303
349
|
|
|
304
|
-
const resolve = (
|
|
305
|
-
|
|
306
|
-
|
|
350
|
+
const resolve = (
|
|
351
|
+
res: (value: IteratorResult<LiveStreamMessage>) => void,
|
|
352
|
+
reject: (error: WebSocketError) => void,
|
|
353
|
+
) => {
|
|
354
|
+
if (failure) {
|
|
355
|
+
reject(failure);
|
|
356
|
+
} else if (queueHead < queue.length) {
|
|
357
|
+
const queued = queue[queueHead]!;
|
|
358
|
+
queue[queueHead] = undefined;
|
|
359
|
+
queueHead += 1;
|
|
360
|
+
if (queueHead >= 64 && queueHead * 2 >= queue.length) {
|
|
361
|
+
queue.splice(0, queueHead);
|
|
362
|
+
queueHead = 0;
|
|
363
|
+
}
|
|
364
|
+
res({ value: queued, done: false });
|
|
307
365
|
} else if (done) {
|
|
308
366
|
res({ value: undefined, done: true });
|
|
309
367
|
} else {
|
|
@@ -313,10 +371,10 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
313
371
|
};
|
|
314
372
|
|
|
315
373
|
const next = (): Promise<IteratorResult<LiveStreamMessage>> =>
|
|
316
|
-
new Promise((res) => {
|
|
317
|
-
if (resolve(res)) return;
|
|
374
|
+
new Promise((res, reject) => {
|
|
375
|
+
if (resolve(res, reject)) return;
|
|
318
376
|
resolvers.push(() => {
|
|
319
|
-
resolve(res);
|
|
377
|
+
resolve(res, reject);
|
|
320
378
|
});
|
|
321
379
|
});
|
|
322
380
|
|
|
@@ -324,6 +382,8 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
324
382
|
next,
|
|
325
383
|
return: (): Promise<IteratorReturnResult<undefined>> => {
|
|
326
384
|
done = true;
|
|
385
|
+
queue.length = 0;
|
|
386
|
+
queueHead = 0;
|
|
327
387
|
cleanup();
|
|
328
388
|
flushResolvers();
|
|
329
389
|
return Promise.resolve({ value: undefined, done: true });
|
|
@@ -356,6 +416,35 @@ export abstract class LiveWSBase<TSocket extends WebSocketLike> extends LiveEmit
|
|
|
356
416
|
return;
|
|
357
417
|
}
|
|
358
418
|
|
|
419
|
+
if (
|
|
420
|
+
event === null ||
|
|
421
|
+
typeof event !== 'object' ||
|
|
422
|
+
Array.isArray(event) ||
|
|
423
|
+
!Object.prototype.hasOwnProperty.call(event, 'type') ||
|
|
424
|
+
typeof event.type !== 'string'
|
|
425
|
+
) {
|
|
426
|
+
this._onError(
|
|
427
|
+
null,
|
|
428
|
+
'received invalid WebSocket event: expected an object with an own string type',
|
|
429
|
+
undefined,
|
|
430
|
+
);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const eventType: string = event.type;
|
|
435
|
+
const reservedEventType =
|
|
436
|
+
eventType === 'raw' ||
|
|
437
|
+
eventType === 'close' ||
|
|
438
|
+
eventType === 'event' ||
|
|
439
|
+
eventType === 'reconnecting' ||
|
|
440
|
+
eventType === 'reconnected' ||
|
|
441
|
+
eventType === 'open' ||
|
|
442
|
+
eventType === 'error';
|
|
443
|
+
if (reservedEventType && eventType !== 'error') {
|
|
444
|
+
this._onError(null, 'received reserved WebSocket event type', undefined);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
359
448
|
this._emit('event', event);
|
|
360
449
|
|
|
361
450
|
if (event.type === 'error') {
|
package/src/resources/live/ws.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { LiveWSBase, type LiveWSBaseOptions } from './ws-base';
|
|
|
6
6
|
import { OpenAI } from '../../client';
|
|
7
7
|
import { VERSION } from '../../version';
|
|
8
8
|
|
|
9
|
+
export type { WebSocketStreamOptions } from '../../internal/ws';
|
|
10
|
+
|
|
9
11
|
export type { LiveWSReconnectOptions } from './ws-base';
|
|
10
12
|
|
|
11
13
|
export interface LiveWSClientOptions extends WS.ClientOptions, LiveWSBaseOptions {}
|
|
@@ -75,6 +75,11 @@ export abstract class ResponsesEmitter extends EventEmitter<WebSocketEvents> {
|
|
|
75
75
|
protected _onError(event: WebSocketErrorEvent | null, message?: string | undefined, cause?: any): void {
|
|
76
76
|
const eventMessage = event && ('error' in event ? event.error?.message : event.message);
|
|
77
77
|
message = message ?? eventMessage ?? safeJSONStringify(event) ?? 'unknown error';
|
|
78
|
+
try {
|
|
79
|
+
message = String(message);
|
|
80
|
+
} catch {
|
|
81
|
+
message = '[unserializable error value]';
|
|
82
|
+
}
|
|
78
83
|
|
|
79
84
|
if (!this._hasListener('error')) {
|
|
80
85
|
const error = new WebSocketError(
|
|
@@ -6,6 +6,8 @@ import { sleep } from '../../internal/utils/sleep';
|
|
|
6
6
|
import { type WebSocketLike, ReadyState } from '../../internal/ws-adapter';
|
|
7
7
|
import {
|
|
8
8
|
SendQueue,
|
|
9
|
+
getMaxBufferedEvents,
|
|
10
|
+
type WebSocketStreamOptions,
|
|
9
11
|
flattenRawData,
|
|
10
12
|
isRecoverableClose,
|
|
11
13
|
type RawWebSocketData,
|
|
@@ -51,11 +53,11 @@ export interface ResponsesWSBaseOptions {
|
|
|
51
53
|
reconnect?: ResponsesWSReconnectOptions | null | undefined;
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* Default: 1
|
|
56
|
+
* Byte budget for outgoing messages queued while the socket is connecting
|
|
57
|
+
* or reconnecting. An empty queue accepts one message even if it exceeds
|
|
58
|
+
* this budget. Further messages are discarded and an `error` event is emitted
|
|
59
|
+
* if the total queued size would exceed the budget.
|
|
60
|
+
* Default: 1 MiB (1,048,576 bytes).
|
|
59
61
|
*/
|
|
60
62
|
maxQueueSize?: number | undefined;
|
|
61
63
|
}
|
|
@@ -165,6 +167,11 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
165
167
|
* The iterator will exit if the socket closes but exiting the iterator
|
|
166
168
|
* does not close the socket.
|
|
167
169
|
*
|
|
170
|
+
* Pass `maxBufferedEvents` to limit queued records for this iterator, including
|
|
171
|
+
* lifecycle events. Overflow discards its backlog and rejects `next()` with a
|
|
172
|
+
* WebSocketError; the shared socket and other iterators remain active.
|
|
173
|
+
* Omitted means unlimited. This is an event-count limit, not a byte limit.
|
|
174
|
+
*
|
|
168
175
|
* @example
|
|
169
176
|
* ```ts
|
|
170
177
|
* for await (const event of client.stream()) {
|
|
@@ -182,26 +189,59 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
182
189
|
* }
|
|
183
190
|
* ```
|
|
184
191
|
*/
|
|
185
|
-
stream(): AsyncIterableIterator<ResponsesStreamMessage> {
|
|
186
|
-
return this[Symbol.asyncIterator]();
|
|
192
|
+
stream(options?: WebSocketStreamOptions): AsyncIterableIterator<ResponsesStreamMessage> {
|
|
193
|
+
return options === undefined ? this[Symbol.asyncIterator]() : this[Symbol.asyncIterator](options);
|
|
187
194
|
}
|
|
188
195
|
|
|
189
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<ResponsesStreamMessage> {
|
|
196
|
+
[Symbol.asyncIterator](options?: WebSocketStreamOptions): AsyncIterableIterator<ResponsesStreamMessage> {
|
|
190
197
|
if (!this.socket) {
|
|
191
198
|
throw new OpenAIError('Internal error: failed to initialize socket. Please report this issue.');
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
const maxBufferedEvents = getMaxBufferedEvents(options);
|
|
202
|
+
|
|
194
203
|
// Two-queue async iterator: `queue` buffers incoming messages,
|
|
195
204
|
// `resolvers` buffers waiting next() calls. A push wakes the
|
|
196
205
|
// oldest next(); a next() drains the oldest message.
|
|
197
|
-
const queue: ResponsesStreamMessage[] = [];
|
|
198
|
-
const resolvers: (() => void)[] = [];
|
|
206
|
+
const queue: (ResponsesStreamMessage | undefined)[] = [];
|
|
207
|
+
const resolvers: ((() => void) | undefined)[] = [];
|
|
208
|
+
let queueHead = 0;
|
|
209
|
+
let resolverHead = 0;
|
|
199
210
|
let done = false;
|
|
211
|
+
let failure: WebSocketError | undefined;
|
|
200
212
|
let currentSocket = this.socket;
|
|
201
213
|
|
|
214
|
+
const wakeResolver = () => {
|
|
215
|
+
if (resolverHead >= resolvers.length) return;
|
|
216
|
+
|
|
217
|
+
const resolver = resolvers[resolverHead];
|
|
218
|
+
resolvers[resolverHead] = undefined;
|
|
219
|
+
resolverHead += 1;
|
|
220
|
+
if (resolverHead >= 64 && resolverHead * 2 >= resolvers.length) {
|
|
221
|
+
resolvers.splice(0, resolverHead);
|
|
222
|
+
resolverHead = 0;
|
|
223
|
+
}
|
|
224
|
+
resolver?.();
|
|
225
|
+
};
|
|
226
|
+
|
|
202
227
|
const push = (msg: ResponsesStreamMessage) => {
|
|
228
|
+
if (done) return;
|
|
229
|
+
|
|
230
|
+
if (maxBufferedEvents !== undefined && queue.length - queueHead >= maxBufferedEvents) {
|
|
231
|
+
failure = new WebSocketError(
|
|
232
|
+
`WebSocket stream exceeded maxBufferedEvents (${maxBufferedEvents})`,
|
|
233
|
+
null,
|
|
234
|
+
);
|
|
235
|
+
done = true;
|
|
236
|
+
queue.length = 0;
|
|
237
|
+
queueHead = 0;
|
|
238
|
+
cleanup();
|
|
239
|
+
flushResolvers();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
203
243
|
queue.push(msg);
|
|
204
|
-
|
|
244
|
+
wakeResolver();
|
|
205
245
|
};
|
|
206
246
|
|
|
207
247
|
const onEvent = (event: ResponsesAPI.ResponsesServerEvent) => {
|
|
@@ -231,9 +271,14 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
231
271
|
};
|
|
232
272
|
|
|
233
273
|
const flushResolvers = () => {
|
|
234
|
-
|
|
235
|
-
resolver
|
|
274
|
+
while (resolverHead < resolvers.length) {
|
|
275
|
+
const resolver = resolvers[resolverHead];
|
|
276
|
+
resolvers[resolverHead] = undefined;
|
|
277
|
+
resolverHead += 1;
|
|
278
|
+
resolver?.();
|
|
236
279
|
}
|
|
280
|
+
resolvers.length = 0;
|
|
281
|
+
resolverHead = 0;
|
|
237
282
|
};
|
|
238
283
|
|
|
239
284
|
const onClose = (
|
|
@@ -247,8 +292,9 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
247
292
|
cleanup();
|
|
248
293
|
};
|
|
249
294
|
|
|
250
|
-
const onSocketSwap = (
|
|
251
|
-
|
|
295
|
+
const onSocketSwap = (_oldSocket: TSocket, newSocket: TSocket) => {
|
|
296
|
+
if (currentSocket === newSocket) return;
|
|
297
|
+
currentSocket.off('open', onOpen);
|
|
252
298
|
newSocket.on('open', onOpen);
|
|
253
299
|
currentSocket = newSocket;
|
|
254
300
|
};
|
|
@@ -305,9 +351,21 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
305
351
|
}
|
|
306
352
|
}
|
|
307
353
|
|
|
308
|
-
const resolve = (
|
|
309
|
-
|
|
310
|
-
|
|
354
|
+
const resolve = (
|
|
355
|
+
res: (value: IteratorResult<ResponsesStreamMessage>) => void,
|
|
356
|
+
reject: (error: WebSocketError) => void,
|
|
357
|
+
) => {
|
|
358
|
+
if (failure) {
|
|
359
|
+
reject(failure);
|
|
360
|
+
} else if (queueHead < queue.length) {
|
|
361
|
+
const queued = queue[queueHead]!;
|
|
362
|
+
queue[queueHead] = undefined;
|
|
363
|
+
queueHead += 1;
|
|
364
|
+
if (queueHead >= 64 && queueHead * 2 >= queue.length) {
|
|
365
|
+
queue.splice(0, queueHead);
|
|
366
|
+
queueHead = 0;
|
|
367
|
+
}
|
|
368
|
+
res({ value: queued, done: false });
|
|
311
369
|
} else if (done) {
|
|
312
370
|
res({ value: undefined, done: true });
|
|
313
371
|
} else {
|
|
@@ -317,10 +375,10 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
317
375
|
};
|
|
318
376
|
|
|
319
377
|
const next = (): Promise<IteratorResult<ResponsesStreamMessage>> =>
|
|
320
|
-
new Promise((res) => {
|
|
321
|
-
if (resolve(res)) return;
|
|
378
|
+
new Promise((res, reject) => {
|
|
379
|
+
if (resolve(res, reject)) return;
|
|
322
380
|
resolvers.push(() => {
|
|
323
|
-
resolve(res);
|
|
381
|
+
resolve(res, reject);
|
|
324
382
|
});
|
|
325
383
|
});
|
|
326
384
|
|
|
@@ -328,6 +386,8 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
328
386
|
next,
|
|
329
387
|
return: (): Promise<IteratorReturnResult<undefined>> => {
|
|
330
388
|
done = true;
|
|
389
|
+
queue.length = 0;
|
|
390
|
+
queueHead = 0;
|
|
331
391
|
cleanup();
|
|
332
392
|
flushResolvers();
|
|
333
393
|
return Promise.resolve({ value: undefined, done: true });
|
|
@@ -360,6 +420,35 @@ export abstract class ResponsesWSBase<TSocket extends WebSocketLike> extends Res
|
|
|
360
420
|
return;
|
|
361
421
|
}
|
|
362
422
|
|
|
423
|
+
if (
|
|
424
|
+
event === null ||
|
|
425
|
+
typeof event !== 'object' ||
|
|
426
|
+
Array.isArray(event) ||
|
|
427
|
+
!Object.prototype.hasOwnProperty.call(event, 'type') ||
|
|
428
|
+
typeof event.type !== 'string'
|
|
429
|
+
) {
|
|
430
|
+
this._onError(
|
|
431
|
+
null,
|
|
432
|
+
'received invalid WebSocket event: expected an object with an own string type',
|
|
433
|
+
undefined,
|
|
434
|
+
);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const eventType: string = event.type;
|
|
439
|
+
const reservedEventType =
|
|
440
|
+
eventType === 'raw' ||
|
|
441
|
+
eventType === 'close' ||
|
|
442
|
+
eventType === 'event' ||
|
|
443
|
+
eventType === 'reconnecting' ||
|
|
444
|
+
eventType === 'reconnected' ||
|
|
445
|
+
eventType === 'open' ||
|
|
446
|
+
eventType === 'error';
|
|
447
|
+
if (reservedEventType && eventType !== 'error') {
|
|
448
|
+
this._onError(null, 'received reserved WebSocket event type', undefined);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
363
452
|
this._emit('event', event);
|
|
364
453
|
|
|
365
454
|
if (event.type === 'error') {
|
|
@@ -6,6 +6,8 @@ import { ResponsesWSBase, type ResponsesWSBaseOptions } from './ws-base';
|
|
|
6
6
|
import { OpenAI } from '../../client';
|
|
7
7
|
import { VERSION } from '../../version';
|
|
8
8
|
|
|
9
|
+
export type { WebSocketStreamOptions } from '../../internal/ws';
|
|
10
|
+
|
|
9
11
|
export type { ResponsesWSReconnectOptions } from './ws-base';
|
|
10
12
|
|
|
11
13
|
export interface ResponsesWSClientOptions extends WS.ClientOptions, ResponsesWSBaseOptions {}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Version of the installed OpenAI SDK package. */
|
|
2
|
-
export const VERSION = '7.
|
|
2
|
+
export const VERSION = '7.16.0'; // x-release-please-version
|
package/version.d.mts
CHANGED
package/version.d.ts
CHANGED
package/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** Version of the installed OpenAI SDK package. */
|
|
5
|
-
exports.VERSION = '7.
|
|
5
|
+
exports.VERSION = '7.16.0'; // x-release-please-version
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/version.mjs
CHANGED