diff --git a/src/client.ts b/src/client.ts index 88adc57bc..2042c6473 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,6 +795,13 @@ export class OpenAI { const security = options.__security ?? { bearerAuth: true }; const controller = new AbortController(); + const abort = this._makeAbort(controller); + let abortCleanup: (() => void) | undefined; + if (options.signal) { + options.signal.addEventListener('abort', abort); + abortCleanup = () => options.signal!.removeEventListener('abort', abort); + } + const response = await this.fetchWithAuth(url, req, timeout, controller, security).catch(castToError); const headersTime = Date.now(); @@ -949,7 +956,7 @@ export class OpenAI { }), ); - return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + return { response, options, controller, actionToRunOnComplete: abortCleanup, requestLogID, retryOfRequestLogID, startTime }; } getAPIList = Pagination.AbstractPage>( @@ -1008,7 +1015,6 @@ export class OpenAI { ): Promise { const { signal, method, ...options } = init || {}; const abort = this._makeAbort(controller); - if (signal) signal.addEventListener('abort', abort, { once: true }); const timeout = setTimeout(abort, ms); diff --git a/src/core/streaming.ts b/src/core/streaming.ts index d0abc1cff..a5d694182 100644 --- a/src/core/streaming.ts +++ b/src/core/streaming.ts @@ -33,6 +33,7 @@ export class Stream implements AsyncIterable { controller: AbortController, client?: OpenAI, synthesizeEventData?: boolean, + cleanup?: () => void, ): Stream { let consumed = false; const logger = client ? loggerFor(client) : console; diff --git a/src/internal/parse.ts b/src/internal/parse.ts index 47dd2cf08..5135c6e4a 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -13,6 +13,7 @@ export type APIResponseProps = { requestLogID: string; retryOfRequestLogID: string | undefined; startTime: number; + actionToRunOnComplete?: () => void; }; export async function defaultParseResponse( @@ -33,6 +34,7 @@ export async function defaultParseResponse( props.controller, client, props.options.__synthesizeEventData, + props.actionToRunOnComplete, ) as any; } @@ -41,6 +43,7 @@ export async function defaultParseResponse( props.controller, client, props.options.__synthesizeEventData, + props.actionToRunOnComplete, ) as any; } @@ -80,6 +83,9 @@ export async function defaultParseResponse( durationMs: Date.now() - startTime, }), ); + if (!props.options.stream && !props.options.__binaryResponse) { + props.actionToRunOnComplete?.(); + } return body; }