diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a1a6f4a3a..402862bfb 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.53.2"
+ ".": "4.54.0"
}
diff --git a/.stats.yml b/.stats.yml
index 4e4cb5509..6cc775763 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
configured_endpoints: 68
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-77cfff37114bc9f141c7e6107eb5f1b38d8cc99bc3d4ce03a066db2b6b649c69.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-b04761ffd2adad3cc19a6dc6fc696ac445878219972f891881a967340fa9a6b0.yml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0569806c..a285f7d15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,26 @@
# Changelog
+## 4.54.0 (2024-08-02)
+
+Full Changelog: [v4.53.2...v4.54.0](https://github.com/openai/openai-node/compare/v4.53.2...v4.54.0)
+
+### Features
+
+* extract out `ImageModel`, `AudioModel`, `SpeechModel` ([#964](https://github.com/openai/openai-node/issues/964)) ([1edf957](https://github.com/openai/openai-node/commit/1edf957e1cb86c2a7b2d29e28f2b8f428ea0cd7d))
+* make enums not nominal ([#965](https://github.com/openai/openai-node/issues/965)) ([0dd0cd1](https://github.com/openai/openai-node/commit/0dd0cd158d6765c3a04ac983aad03c2ecad14502))
+
+
+### Chores
+
+* **ci:** correctly tag pre-release npm packages ([#963](https://github.com/openai/openai-node/issues/963)) ([f1a4a68](https://github.com/openai/openai-node/commit/f1a4a686bbf4a38919b8597f008d895d1b99d8df))
+* **internal:** add constant for default timeout ([#960](https://github.com/openai/openai-node/issues/960)) ([55c01f4](https://github.com/openai/openai-node/commit/55c01f4dc5d132c21713f9e8606b95abc76fcd44))
+* **internal:** cleanup event stream helpers ([#950](https://github.com/openai/openai-node/issues/950)) ([8f49956](https://github.com/openai/openai-node/commit/8f499566c47bd7d4799a8cbe0d980553348b8f48))
+
+
+### Documentation
+
+* **README:** link Lifecycle in Polling Helpers section ([#962](https://github.com/openai/openai-node/issues/962)) ([c610c81](https://github.com/openai/openai-node/commit/c610c813e8d7f96b5b8315ae194e0a9ff565f43d))
+
## 4.53.2 (2024-07-26)
Full Changelog: [v4.53.1...v4.53.2](https://github.com/openai/openai-node/compare/v4.53.1...v4.53.2)
diff --git a/README.md b/README.md
index 5fed94642..ea1d54f5b 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ You can import in Deno via:
```ts
-import OpenAI from 'https://deno.land/x/openai@v4.53.2/mod.ts';
+import OpenAI from 'https://deno.land/x/openai@v4.54.0/mod.ts';
```
@@ -115,7 +115,7 @@ const run = await openai.beta.threads.runs.createAndPoll(thread.id, {
});
```
-More information on the lifecycle of a Run can be found in the [Run Lifecycle Documentation](https://platform.openai.com/docs/assistants/how-it-works/run-lifecycle)
+More information on the lifecycle of a Run can be found in the [Run Lifecycle Documentation](https://platform.openai.com/docs/assistants/deep-dive/run-lifecycle)
### Bulk Upload Helpers
diff --git a/api.md b/api.md
index ddc9fce38..acae0b8e8 100644
--- a/api.md
+++ b/api.md
@@ -88,6 +88,7 @@ Methods:
Types:
- Image
+- ImageModel
- ImagesResponse
Methods:
@@ -98,6 +99,10 @@ Methods:
# Audio
+Types:
+
+- AudioModel
+
## Transcriptions
Types:
@@ -120,6 +125,10 @@ Methods:
## Speech
+Types:
+
+- SpeechModel
+
Methods:
- client.audio.speech.create({ ...params }) -> Response
@@ -129,6 +138,7 @@ Methods:
Types:
- Moderation
+- ModerationModel
- ModerationCreateResponse
Methods:
diff --git a/bin/publish-npm b/bin/publish-npm
index 4d6c9f357..4c21181bb 100644
--- a/bin/publish-npm
+++ b/bin/publish-npm
@@ -2,8 +2,24 @@
set -eux
-npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN
+npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN"
+# Build the project
yarn build
+
+# Navigate to the dist directory
cd dist
-yarn publish --access public
+
+# Get the version from package.json
+VERSION="$(node -p "require('./package.json').version")"
+
+# Extract the pre-release tag if it exists
+if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then
+ # Extract the part before any dot in the pre-release identifier
+ TAG="${BASH_REMATCH[1]}"
+else
+ TAG="latest"
+fi
+
+# Publish with the appropriate tag
+yarn publish --access public --tag "$TAG"
diff --git a/package.json b/package.json
index 5eaac9d39..3f6c722d1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "openai",
- "version": "4.53.2",
+ "version": "4.54.0",
"description": "The official TypeScript library for the OpenAI API",
"author": "OpenAI ",
"types": "dist/index.d.ts",
diff --git a/scripts/build-deno b/scripts/build-deno
index 9ab99752c..438b11e6f 100755
--- a/scripts/build-deno
+++ b/scripts/build-deno
@@ -16,7 +16,7 @@ This is a build produced from https://github.com/openai/openai-node – please g
Usage:
\`\`\`ts
-import OpenAI from "https://deno.land/x/openai@v4.53.2/mod.ts";
+import OpenAI from "https://deno.land/x/openai@v4.54.0/mod.ts";
const client = new OpenAI();
\`\`\`
diff --git a/src/index.ts b/src/index.ts
index 7e5df0505..cd0dd67b3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -184,6 +184,7 @@ export class OpenAI extends Core.APIClient {
}
static OpenAI = this;
+ static DEFAULT_TIMEOUT = 600000; // 10 minutes
static OpenAIError = Errors.OpenAIError;
static APIError = Errors.APIError;
@@ -281,15 +282,18 @@ export namespace OpenAI {
export import Images = API.Images;
export import Image = API.Image;
+ export import ImageModel = API.ImageModel;
export import ImagesResponse = API.ImagesResponse;
export import ImageCreateVariationParams = API.ImageCreateVariationParams;
export import ImageEditParams = API.ImageEditParams;
export import ImageGenerateParams = API.ImageGenerateParams;
export import Audio = API.Audio;
+ export import AudioModel = API.AudioModel;
export import Moderations = API.Moderations;
export import Moderation = API.Moderation;
+ export import ModerationModel = API.ModerationModel;
export import ModerationCreateResponse = API.ModerationCreateResponse;
export import ModerationCreateParams = API.ModerationCreateParams;
diff --git a/src/lib/AbstractChatCompletionRunner.ts b/src/lib/AbstractChatCompletionRunner.ts
index 5764b85b2..590013aa6 100644
--- a/src/lib/AbstractChatCompletionRunner.ts
+++ b/src/lib/AbstractChatCompletionRunner.ts
@@ -8,7 +8,7 @@ import {
type ChatCompletionCreateParams,
type ChatCompletionTool,
} from 'openai/resources/chat/completions';
-import { APIUserAbortError, OpenAIError } from 'openai/error';
+import { OpenAIError } from 'openai/error';
import {
type RunnableFunction,
isRunnableFunctionWithParse,
@@ -20,6 +20,7 @@ import {
ChatCompletionStreamingToolRunnerParams,
} from './ChatCompletionStreamingRunner';
import { isAssistantMessage, isFunctionMessage, isToolMessage } from './chatCompletionUtils';
+import { BaseEvents, EventStream } from './EventStream';
const DEFAULT_MAX_CHAT_COMPLETIONS = 10;
export interface RunnerOptions extends Core.RequestOptions {
@@ -27,60 +28,16 @@ export interface RunnerOptions extends Core.RequestOptions {
maxChatCompletions?: number;
}
-export abstract class AbstractChatCompletionRunner<
- Events extends CustomEvents = AbstractChatCompletionRunnerEvents,
-> {
- controller: AbortController = new AbortController();
-
- #connectedPromise: Promise;
- #resolveConnectedPromise: () => void = () => {};
- #rejectConnectedPromise: (error: OpenAIError) => void = () => {};
-
- #endPromise: Promise;
- #resolveEndPromise: () => void = () => {};
- #rejectEndPromise: (error: OpenAIError) => void = () => {};
-
- #listeners: { [Event in keyof Events]?: ListenersForEvent } = {};
-
+export class AbstractChatCompletionRunner<
+ EventTypes extends AbstractChatCompletionRunnerEvents,
+> extends EventStream {
protected _chatCompletions: ChatCompletion[] = [];
messages: ChatCompletionMessageParam[] = [];
- #ended = false;
- #errored = false;
- #aborted = false;
- #catchingPromiseCreated = false;
-
- constructor() {
- this.#connectedPromise = new Promise((resolve, reject) => {
- this.#resolveConnectedPromise = resolve;
- this.#rejectConnectedPromise = reject;
- });
-
- this.#endPromise = new Promise((resolve, reject) => {
- this.#resolveEndPromise = resolve;
- this.#rejectEndPromise = reject;
- });
-
- // Don't let these promises cause unhandled rejection errors.
- // we will manually cause an unhandled rejection error later
- // if the user hasn't registered any error listener or called
- // any promise-returning method.
- this.#connectedPromise.catch(() => {});
- this.#endPromise.catch(() => {});
- }
-
- protected _run(executor: () => Promise) {
- // Unfortunately if we call `executor()` immediately we get runtime errors about
- // references to `this` before the `super()` constructor call returns.
- setTimeout(() => {
- executor().then(() => {
- this._emitFinal();
- this._emit('end');
- }, this.#handleError);
- }, 0);
- }
-
- protected _addChatCompletion(chatCompletion: ChatCompletion): ChatCompletion {
+ protected _addChatCompletion(
+ this: AbstractChatCompletionRunner,
+ chatCompletion: ChatCompletion,
+ ): ChatCompletion {
this._chatCompletions.push(chatCompletion);
this._emit('chatCompletion', chatCompletion);
const message = chatCompletion.choices[0]?.message;
@@ -88,7 +45,11 @@ export abstract class AbstractChatCompletionRunner<
return chatCompletion;
}
- protected _addMessage(message: ChatCompletionMessageParam, emit = true) {
+ protected _addMessage(
+ this: AbstractChatCompletionRunner,
+ message: ChatCompletionMessageParam,
+ emit = true,
+ ) {
if (!('content' in message)) message.content = null;
this.messages.push(message);
@@ -110,99 +71,6 @@ export abstract class AbstractChatCompletionRunner<
}
}
- protected _connected() {
- if (this.ended) return;
- this.#resolveConnectedPromise();
- this._emit('connect');
- }
-
- get ended(): boolean {
- return this.#ended;
- }
-
- get errored(): boolean {
- return this.#errored;
- }
-
- get aborted(): boolean {
- return this.#aborted;
- }
-
- abort() {
- this.controller.abort();
- }
-
- /**
- * Adds the listener function to the end of the listeners array for the event.
- * No checks are made to see if the listener has already been added. Multiple calls passing
- * the same combination of event and listener will result in the listener being added, and
- * called, multiple times.
- * @returns this ChatCompletionStream, so that calls can be chained
- */
- on(event: Event, listener: ListenerForEvent): this {
- const listeners: ListenersForEvent =
- this.#listeners[event] || (this.#listeners[event] = []);
- listeners.push({ listener });
- return this;
- }
-
- /**
- * Removes the specified listener from the listener array for the event.
- * off() will remove, at most, one instance of a listener from the listener array. If any single
- * listener has been added multiple times to the listener array for the specified event, then
- * off() must be called multiple times to remove each instance.
- * @returns this ChatCompletionStream, so that calls can be chained
- */
- off(event: Event, listener: ListenerForEvent): this {
- const listeners = this.#listeners[event];
- if (!listeners) return this;
- const index = listeners.findIndex((l) => l.listener === listener);
- if (index >= 0) listeners.splice(index, 1);
- return this;
- }
-
- /**
- * Adds a one-time listener function for the event. The next time the event is triggered,
- * this listener is removed and then invoked.
- * @returns this ChatCompletionStream, so that calls can be chained
- */
- once(event: Event, listener: ListenerForEvent): this {
- const listeners: ListenersForEvent =
- this.#listeners[event] || (this.#listeners[event] = []);
- listeners.push({ listener, once: true });
- return this;
- }
-
- /**
- * This is similar to `.once()`, but returns a Promise that resolves the next time
- * the event is triggered, instead of calling a listener callback.
- * @returns a Promise that resolves the next time given event is triggered,
- * or rejects if an error is emitted. (If you request the 'error' event,
- * returns a promise that resolves with the error).
- *
- * Example:
- *
- * const message = await stream.emitted('message') // rejects if the stream errors
- */
- emitted(
- event: Event,
- ): Promise<
- EventParameters extends [infer Param] ? Param
- : EventParameters extends [] ? void
- : EventParameters
- > {
- return new Promise((resolve, reject) => {
- this.#catchingPromiseCreated = true;
- if (event !== 'error') this.once('error', reject);
- this.once(event, resolve as any);
- });
- }
-
- async done(): Promise {
- this.#catchingPromiseCreated = true;
- await this.#endPromise;
- }
-
/**
* @returns a promise that resolves with the final ChatCompletion, or rejects
* if an error occurred or the stream ended prematurely without producing a ChatCompletion.
@@ -327,75 +195,7 @@ export abstract class AbstractChatCompletionRunner<
return [...this._chatCompletions];
}
- #handleError = (error: unknown) => {
- this.#errored = true;
- if (error instanceof Error && error.name === 'AbortError') {
- error = new APIUserAbortError();
- }
- if (error instanceof APIUserAbortError) {
- this.#aborted = true;
- return this._emit('abort', error);
- }
- if (error instanceof OpenAIError) {
- return this._emit('error', error);
- }
- if (error instanceof Error) {
- const openAIError: OpenAIError = new OpenAIError(error.message);
- // @ts-ignore
- openAIError.cause = error;
- return this._emit('error', openAIError);
- }
- return this._emit('error', new OpenAIError(String(error)));
- };
-
- protected _emit(event: Event, ...args: EventParameters) {
- // make sure we don't emit any events after end
- if (this.#ended) {
- return;
- }
-
- if (event === 'end') {
- this.#ended = true;
- this.#resolveEndPromise();
- }
-
- const listeners: ListenersForEvent | undefined = this.#listeners[event];
- if (listeners) {
- this.#listeners[event] = listeners.filter((l) => !l.once) as any;
- listeners.forEach(({ listener }: any) => listener(...args));
- }
-
- if (event === 'abort') {
- const error = args[0] as APIUserAbortError;
- if (!this.#catchingPromiseCreated && !listeners?.length) {
- Promise.reject(error);
- }
- this.#rejectConnectedPromise(error);
- this.#rejectEndPromise(error);
- this._emit('end');
- return;
- }
-
- if (event === 'error') {
- // NOTE: _emit('error', error) should only be called from #handleError().
-
- const error = args[0] as OpenAIError;
- if (!this.#catchingPromiseCreated && !listeners?.length) {
- // Trigger an unhandled rejection if the user hasn't registered any error handlers.
- // If you are seeing stack traces here, make sure to handle errors via either:
- // - runner.on('error', () => ...)
- // - await runner.done()
- // - await runner.finalChatCompletion()
- // - etc.
- Promise.reject(error);
- }
- this.#rejectConnectedPromise(error);
- this.#rejectEndPromise(error);
- this._emit('end');
- }
- }
-
- protected _emitFinal() {
+ protected override _emitFinal(this: AbstractChatCompletionRunner) {
const completion = this._chatCompletions[this._chatCompletions.length - 1];
if (completion) this._emit('finalChatCompletion', completion);
const finalMessage = this.#getFinalMessage();
@@ -650,27 +450,7 @@ export abstract class AbstractChatCompletionRunner<
}
}
-type CustomEvents = {
- [k in Event]: k extends keyof AbstractChatCompletionRunnerEvents ? AbstractChatCompletionRunnerEvents[k]
- : (...args: any[]) => void;
-};
-
-type ListenerForEvent, Event extends keyof Events> = Event extends (
- keyof AbstractChatCompletionRunnerEvents
-) ?
- AbstractChatCompletionRunnerEvents[Event]
-: Events[Event];
-
-type ListenersForEvent, Event extends keyof Events> = Array<{
- listener: ListenerForEvent;
- once?: boolean;
-}>;
-type EventParameters, Event extends keyof Events> = Parameters<
- ListenerForEvent
->;
-
-export interface AbstractChatCompletionRunnerEvents {
- connect: () => void;
+export interface AbstractChatCompletionRunnerEvents extends BaseEvents {
functionCall: (functionCall: ChatCompletionMessage.FunctionCall) => void;
message: (message: ChatCompletionMessageParam) => void;
chatCompletion: (completion: ChatCompletion) => void;
@@ -680,8 +460,5 @@ export interface AbstractChatCompletionRunnerEvents {
finalFunctionCall: (functionCall: ChatCompletionMessage.FunctionCall) => void;
functionCallResult: (content: string) => void;
finalFunctionCallResult: (content: string) => void;
- error: (error: OpenAIError) => void;
- abort: (error: APIUserAbortError) => void;
- end: () => void;
totalUsage: (usage: CompletionUsage) => void;
}
diff --git a/src/lib/AssistantStream.ts b/src/lib/AssistantStream.ts
index de7511b5d..0f88530b3 100644
--- a/src/lib/AssistantStream.ts
+++ b/src/lib/AssistantStream.ts
@@ -19,10 +19,6 @@ import {
RunSubmitToolOutputsParamsBase,
RunSubmitToolOutputsParamsStreaming,
} from 'openai/resources/beta/threads/runs/runs';
-import {
- AbstractAssistantRunnerEvents,
- AbstractAssistantStreamRunner,
-} from './AbstractAssistantStreamRunner';
import { type ReadableStream } from 'openai/_shims/index';
import { Stream } from 'openai/streaming';
import { APIUserAbortError, OpenAIError } from 'openai/error';
@@ -34,9 +30,12 @@ import {
} from 'openai/resources/beta/assistants';
import { RunStep, RunStepDelta, ToolCall, ToolCallDelta } from 'openai/resources/beta/threads/runs/steps';
import { ThreadCreateAndRunParamsBase, Threads } from 'openai/resources/beta/threads/threads';
+import { BaseEvents, EventStream } from './EventStream';
import MessageDelta = Messages.MessageDelta;
-export interface AssistantStreamEvents extends AbstractAssistantRunnerEvents {
+export interface AssistantStreamEvents extends BaseEvents {
+ run: (run: Run) => void;
+
//New event structure
messageCreated: (message: Message) => void;
messageDelta: (message: MessageDelta, snapshot: Message) => void;
@@ -57,8 +56,6 @@ export interface AssistantStreamEvents extends AbstractAssistantRunnerEvents {
//No created or delta as this is not streamed
imageFileDone: (content: ImageFile, snapshot: Message) => void;
- end: () => void;
-
event: (event: AssistantStreamEvent) => void;
}
@@ -75,7 +72,7 @@ export type RunSubmitToolOutputsParamsStream = Omit
+ extends EventStream
implements AsyncIterable
{
//Track all events in a single list for reference
@@ -207,7 +204,7 @@ export class AssistantStream
return runner;
}
- protected override async _createToolAssistantStream(
+ protected async _createToolAssistantStream(
run: Runs,
threadId: string,
runId: string,
@@ -304,7 +301,7 @@ export class AssistantStream
return this.#finalRun;
}
- protected override async _createThreadAssistantStream(
+ protected async _createThreadAssistantStream(
thread: Threads,
params: ThreadCreateAndRunParamsBase,
options?: Core.RequestOptions,
@@ -330,7 +327,7 @@ export class AssistantStream
return this._addRun(this.#endRequest());
}
- protected override async _createAssistantStream(
+ protected async _createAssistantStream(
run: Runs,
threadId: string,
params: RunCreateParamsBase,
@@ -417,7 +414,7 @@ export class AssistantStream
return this.#finalRun;
}
- #handleMessage(event: MessageStreamEvent) {
+ #handleMessage(this: AssistantStream, event: MessageStreamEvent) {
const [accumulatedMessage, newContent] = this.#accumulateMessage(event, this.#messageSnapshot);
this.#messageSnapshot = accumulatedMessage;
this.#messageSnapshots[accumulatedMessage.id] = accumulatedMessage;
@@ -500,7 +497,7 @@ export class AssistantStream
}
}
- #handleRunStep(event: RunStepStreamEvent) {
+ #handleRunStep(this: AssistantStream, event: RunStepStreamEvent) {
const accumulatedRunStep = this.#accumulateRunStep(event);
this.#currentRunStepSnapshot = accumulatedRunStep;
@@ -556,7 +553,7 @@ export class AssistantStream
}
}
- #handleEvent(event: AssistantStreamEvent) {
+ #handleEvent(this: AssistantStream, event: AssistantStreamEvent) {
this.#events.push(event);
this._emit('event', event);
}
@@ -696,7 +693,7 @@ export class AssistantStream
return acc;
}
- #handleRun(event: RunStreamEvent) {
+ #handleRun(this: AssistantStream, event: RunStreamEvent) {
this.#currentRunSnapshot = event.data;
switch (event.event) {
case 'thread.run.created':
@@ -720,4 +717,35 @@ export class AssistantStream
break;
}
}
+
+ protected _addRun(run: Run): Run {
+ return run;
+ }
+
+ protected async _threadAssistantStream(
+ body: ThreadCreateAndRunParamsBase,
+ thread: Threads,
+ options?: Core.RequestOptions,
+ ): Promise {
+ return await this._createThreadAssistantStream(thread, body, options);
+ }
+
+ protected async _runAssistantStream(
+ threadId: string,
+ runs: Runs,
+ params: RunCreateParamsBase,
+ options?: Core.RequestOptions,
+ ): Promise {
+ return await this._createAssistantStream(runs, threadId, params, options);
+ }
+
+ protected async _runToolAssistantStream(
+ threadId: string,
+ runId: string,
+ runs: Runs,
+ params: RunSubmitToolOutputsParamsStream,
+ options?: Core.RequestOptions,
+ ): Promise {
+ return await this._createToolAssistantStream(runs, threadId, runId, params, options);
+ }
}
diff --git a/src/lib/ChatCompletionRunner.ts b/src/lib/ChatCompletionRunner.ts
index a110f0192..c756919b0 100644
--- a/src/lib/ChatCompletionRunner.ts
+++ b/src/lib/ChatCompletionRunner.ts
@@ -59,7 +59,7 @@ export class ChatCompletionRunner extends AbstractChatCompletionRunner {
+ [Symbol.asyncIterator](this: ChatCompletionStream): AsyncIterator {
const pushQueue: ChatCompletionChunk[] = [];
const readQueue: {
resolve: (chunk: ChatCompletionChunk | undefined) => void;
diff --git a/src/lib/AbstractAssistantStreamRunner.ts b/src/lib/EventStream.ts
similarity index 55%
rename from src/lib/AbstractAssistantStreamRunner.ts
rename to src/lib/EventStream.ts
index b600f0df3..a18c771dd 100644
--- a/src/lib/AbstractAssistantStreamRunner.ts
+++ b/src/lib/EventStream.ts
@@ -1,12 +1,6 @@
-import * as Core from 'openai/core';
import { APIUserAbortError, OpenAIError } from 'openai/error';
-import { Run, RunSubmitToolOutputsParamsBase } from 'openai/resources/beta/threads/runs/runs';
-import { RunCreateParamsBase, Runs } from 'openai/resources/beta/threads/runs/runs';
-import { ThreadCreateAndRunParamsBase, Threads } from 'openai/resources/beta/threads/threads';
-export abstract class AbstractAssistantStreamRunner<
- Events extends CustomEvents = AbstractAssistantRunnerEvents,
-> {
+export class EventStream {
controller: AbortController = new AbortController();
#connectedPromise: Promise;
@@ -17,7 +11,9 @@ export abstract class AbstractAssistantStreamRunner<
#resolveEndPromise: () => void = () => {};
#rejectEndPromise: (error: OpenAIError) => void = () => {};
- #listeners: { [Event in keyof Events]?: ListenersForEvent } = {};
+ #listeners: {
+ [Event in keyof EventTypes]?: EventListeners;
+ } = {};
#ended = false;
#errored = false;
@@ -43,22 +39,18 @@ export abstract class AbstractAssistantStreamRunner<
this.#endPromise.catch(() => {});
}
- protected _run(executor: () => Promise) {
+ protected _run(this: EventStream, executor: () => Promise) {
// Unfortunately if we call `executor()` immediately we get runtime errors about
// references to `this` before the `super()` constructor call returns.
setTimeout(() => {
executor().then(() => {
- // this._emitFinal();
+ this._emitFinal();
this._emit('end');
- }, this.#handleError);
+ }, this.#handleError.bind(this));
}, 0);
}
- protected _addRun(run: Run): Run {
- return run;
- }
-
- protected _connected() {
+ protected _connected(this: EventStream) {
if (this.ended) return;
this.#resolveConnectedPromise();
this._emit('connect');
@@ -87,8 +79,8 @@ export abstract class AbstractAssistantStreamRunner<
* called, multiple times.
* @returns this ChatCompletionStream, so that calls can be chained
*/
- on(event: Event, listener: ListenerForEvent): this {
- const listeners: ListenersForEvent =
+ on(event: Event, listener: EventListener): this {
+ const listeners: EventListeners =
this.#listeners[event] || (this.#listeners[event] = []);
listeners.push({ listener });
return this;
@@ -101,7 +93,7 @@ export abstract class AbstractAssistantStreamRunner<
* off() must be called multiple times to remove each instance.
* @returns this ChatCompletionStream, so that calls can be chained
*/
- off(event: Event, listener: ListenerForEvent): this {
+ off(event: Event, listener: EventListener): this {
const listeners = this.#listeners[event];
if (!listeners) return this;
const index = listeners.findIndex((l) => l.listener === listener);
@@ -114,8 +106,8 @@ export abstract class AbstractAssistantStreamRunner<
* this listener is removed and then invoked.
* @returns this ChatCompletionStream, so that calls can be chained
*/
- once(event: Event, listener: ListenerForEvent): this {
- const listeners: ListenersForEvent =
+ once(event: Event, listener: EventListener): this {
+ const listeners: EventListeners =
this.#listeners[event] || (this.#listeners[event] = []);
listeners.push({ listener, once: true });
return this;
@@ -132,12 +124,12 @@ export abstract class AbstractAssistantStreamRunner<
*
* const message = await stream.emitted('message') // rejects if the stream errors
*/
- emitted(
+ emitted(
event: Event,
): Promise<
- EventParameters extends [infer Param] ? Param
- : EventParameters extends [] ? void
- : EventParameters
+ EventParameters extends [infer Param] ? Param
+ : EventParameters extends [] ? void
+ : EventParameters
> {
return new Promise((resolve, reject) => {
this.#catchingPromiseCreated = true;
@@ -151,7 +143,7 @@ export abstract class AbstractAssistantStreamRunner<
await this.#endPromise;
}
- #handleError = (error: unknown) => {
+ #handleError(this: EventStream, error: unknown) {
this.#errored = true;
if (error instanceof Error && error.name === 'AbortError') {
error = new APIUserAbortError();
@@ -170,9 +162,15 @@ export abstract class AbstractAssistantStreamRunner<
return this._emit('error', openAIError);
}
return this._emit('error', new OpenAIError(String(error)));
- };
+ }
- protected _emit(event: Event, ...args: EventParameters) {
+ _emit(event: Event, ...args: EventParameters): void;
+ _emit(event: Event, ...args: EventParameters): void;
+ _emit(
+ this: EventStream,
+ event: Event,
+ ...args: EventParameters
+ ) {
// make sure we don't emit any events after end
if (this.#ended) {
return;
@@ -183,10 +181,10 @@ export abstract class AbstractAssistantStreamRunner<
this.#resolveEndPromise();
}
- const listeners: ListenersForEvent | undefined = this.#listeners[event];
+ const listeners: EventListeners | undefined = this.#listeners[event];
if (listeners) {
this.#listeners[event] = listeners.filter((l) => !l.once) as any;
- listeners.forEach(({ listener }: any) => listener(...args));
+ listeners.forEach(({ listener }: any) => listener(...(args as any)));
}
if (event === 'abort') {
@@ -219,121 +217,22 @@ export abstract class AbstractAssistantStreamRunner<
}
}
- protected async _threadAssistantStream(
- body: ThreadCreateAndRunParamsBase,
- thread: Threads,
- options?: Core.RequestOptions,
- ): Promise {
- return await this._createThreadAssistantStream(thread, body, options);
- }
-
- protected async _runAssistantStream(
- threadId: string,
- runs: Runs,
- params: RunCreateParamsBase,
- options?: Core.RequestOptions,
- ): Promise {
- return await this._createAssistantStream(runs, threadId, params, options);
- }
-
- protected async _runToolAssistantStream(
- threadId: string,
- runId: string,
- runs: Runs,
- params: RunSubmitToolOutputsParamsBase,
- options?: Core.RequestOptions,
- ): Promise {
- return await this._createToolAssistantStream(runs, threadId, runId, params, options);
- }
-
- protected async _createThreadAssistantStream(
- thread: Threads,
- body: ThreadCreateAndRunParamsBase,
- options?: Core.RequestOptions,
- ): Promise {
- const signal = options?.signal;
- if (signal) {
- if (signal.aborted) this.controller.abort();
- signal.addEventListener('abort', () => this.controller.abort());
- }
- // this.#validateParams(params);
-
- const runResult = await thread.createAndRun(
- { ...body, stream: false },
- { ...options, signal: this.controller.signal },
- );
- this._connected();
- return this._addRun(runResult as Run);
- }
-
- protected async _createToolAssistantStream(
- run: Runs,
- threadId: string,
- runId: string,
- params: RunSubmitToolOutputsParamsBase,
- options?: Core.RequestOptions,
- ): Promise {
- const signal = options?.signal;
- if (signal) {
- if (signal.aborted) this.controller.abort();
- signal.addEventListener('abort', () => this.controller.abort());
- }
-
- const runResult = await run.submitToolOutputs(
- threadId,
- runId,
- { ...params, stream: false },
- { ...options, signal: this.controller.signal },
- );
- this._connected();
- return this._addRun(runResult as Run);
- }
-
- protected async _createAssistantStream(
- run: Runs,
- threadId: string,
- params: RunCreateParamsBase,
- options?: Core.RequestOptions,
- ): Promise {
- const signal = options?.signal;
- if (signal) {
- if (signal.aborted) this.controller.abort();
- signal.addEventListener('abort', () => this.controller.abort());
- }
- // this.#validateParams(params);
-
- const runResult = await run.create(
- threadId,
- { ...params, stream: false },
- { ...options, signal: this.controller.signal },
- );
- this._connected();
- return this._addRun(runResult as Run);
- }
+ protected _emitFinal(): void {}
}
-type CustomEvents = {
- [k in Event]: k extends keyof AbstractAssistantRunnerEvents ? AbstractAssistantRunnerEvents[k]
- : (...args: any[]) => void;
-};
+type EventListener = Events[EventType];
-type ListenerForEvent, Event extends keyof Events> = Event extends (
- keyof AbstractAssistantRunnerEvents
-) ?
- AbstractAssistantRunnerEvents[Event]
-: Events[Event];
-
-type ListenersForEvent, Event extends keyof Events> = Array<{
- listener: ListenerForEvent;
+type EventListeners = Array<{
+ listener: EventListener;
once?: boolean;
}>;
-type EventParameters, Event extends keyof Events> = Parameters<
- ListenerForEvent
->;
-export interface AbstractAssistantRunnerEvents {
+export type EventParameters = {
+ [Event in EventType]: EventListener extends (...args: infer P) => any ? P : never;
+}[EventType];
+
+export interface BaseEvents {
connect: () => void;
- run: (run: Run) => void;
error: (error: OpenAIError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
diff --git a/src/resources/audio/audio.ts b/src/resources/audio/audio.ts
index a89bf0102..1f0269d03 100644
--- a/src/resources/audio/audio.ts
+++ b/src/resources/audio/audio.ts
@@ -1,6 +1,7 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
import { APIResource } from '../../resource';
+import * as AudioAPI from './audio';
import * as SpeechAPI from './speech';
import * as TranscriptionsAPI from './transcriptions';
import * as TranslationsAPI from './translations';
@@ -11,7 +12,10 @@ export class Audio extends APIResource {
speech: SpeechAPI.Speech = new SpeechAPI.Speech(this._client);
}
+export type AudioModel = 'whisper-1';
+
export namespace Audio {
+ export import AudioModel = AudioAPI.AudioModel;
export import Transcriptions = TranscriptionsAPI.Transcriptions;
export import Transcription = TranscriptionsAPI.Transcription;
export import TranscriptionCreateParams = TranscriptionsAPI.TranscriptionCreateParams;
@@ -19,5 +23,6 @@ export namespace Audio {
export import Translation = TranslationsAPI.Translation;
export import TranslationCreateParams = TranslationsAPI.TranslationCreateParams;
export import Speech = SpeechAPI.Speech;
+ export import SpeechModel = SpeechAPI.SpeechModel;
export import SpeechCreateParams = SpeechAPI.SpeechCreateParams;
}
diff --git a/src/resources/audio/index.ts b/src/resources/audio/index.ts
index 31732a267..a7f935964 100644
--- a/src/resources/audio/index.ts
+++ b/src/resources/audio/index.ts
@@ -1,6 +1,6 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-export { Audio } from './audio';
-export { SpeechCreateParams, Speech } from './speech';
+export { AudioModel, Audio } from './audio';
+export { SpeechModel, SpeechCreateParams, Speech } from './speech';
export { Transcription, TranscriptionCreateParams, Transcriptions } from './transcriptions';
export { Translation, TranslationCreateParams, Translations } from './translations';
diff --git a/src/resources/audio/speech.ts b/src/resources/audio/speech.ts
index d0a6e7f31..34fb26b02 100644
--- a/src/resources/audio/speech.ts
+++ b/src/resources/audio/speech.ts
@@ -14,6 +14,8 @@ export class Speech extends APIResource {
}
}
+export type SpeechModel = 'tts-1' | 'tts-1-hd';
+
export interface SpeechCreateParams {
/**
* The text to generate audio for. The maximum length is 4096 characters.
@@ -24,7 +26,7 @@ export interface SpeechCreateParams {
* One of the available [TTS models](https://platform.openai.com/docs/models/tts):
* `tts-1` or `tts-1-hd`
*/
- model: (string & {}) | 'tts-1' | 'tts-1-hd';
+ model: (string & {}) | SpeechModel;
/**
* The voice to use when generating the audio. Supported voices are `alloy`,
@@ -48,5 +50,6 @@ export interface SpeechCreateParams {
}
export namespace Speech {
+ export import SpeechModel = SpeechAPI.SpeechModel;
export import SpeechCreateParams = SpeechAPI.SpeechCreateParams;
}
diff --git a/src/resources/audio/transcriptions.ts b/src/resources/audio/transcriptions.ts
index 0eb4e4b7c..5c30d6c59 100644
--- a/src/resources/audio/transcriptions.ts
+++ b/src/resources/audio/transcriptions.ts
@@ -3,6 +3,7 @@
import { APIResource } from '../../resource';
import * as Core from '../../core';
import * as TranscriptionsAPI from './transcriptions';
+import * as AudioAPI from './audio';
export class Transcriptions extends APIResource {
/**
@@ -35,7 +36,7 @@ export interface TranscriptionCreateParams {
* ID of the model to use. Only `whisper-1` (which is powered by our open source
* Whisper V2 model) is currently available.
*/
- model: (string & {}) | 'whisper-1';
+ model: (string & {}) | AudioAPI.AudioModel;
/**
* The language of the input audio. Supplying the input language in
diff --git a/src/resources/audio/translations.ts b/src/resources/audio/translations.ts
index 48fddc2ee..dedc15b65 100644
--- a/src/resources/audio/translations.ts
+++ b/src/resources/audio/translations.ts
@@ -3,6 +3,7 @@
import { APIResource } from '../../resource';
import * as Core from '../../core';
import * as TranslationsAPI from './translations';
+import * as AudioAPI from './audio';
export class Translations extends APIResource {
/**
@@ -28,7 +29,7 @@ export interface TranslationCreateParams {
* ID of the model to use. Only `whisper-1` (which is powered by our open source
* Whisper V2 model) is currently available.
*/
- model: (string & {}) | 'whisper-1';
+ model: (string & {}) | AudioAPI.AudioModel;
/**
* An optional text to guide the model's style or continue a previous audio
diff --git a/src/resources/beta/assistants.ts b/src/resources/beta/assistants.ts
index abacfd06e..d66b03768 100644
--- a/src/resources/beta/assistants.ts
+++ b/src/resources/beta/assistants.ts
@@ -5,6 +5,7 @@ import { isRequestOptions } from '../../core';
import * as Core from '../../core';
import * as AssistantsAPI from './assistants';
import * as Shared from '../shared';
+import * as ChatAPI from '../chat/chat';
import * as MessagesAPI from './threads/messages';
import * as ThreadsAPI from './threads/threads';
import * as RunsAPI from './threads/runs/runs';
@@ -1053,30 +1054,7 @@ export interface AssistantCreateParams {
* [Model overview](https://platform.openai.com/docs/models/overview) for
* descriptions of them.
*/
- model:
- | (string & {})
- | 'gpt-4o'
- | 'gpt-4o-2024-05-13'
- | 'gpt-4o-mini'
- | 'gpt-4o-mini-2024-07-18'
- | 'gpt-4-turbo'
- | 'gpt-4-turbo-2024-04-09'
- | 'gpt-4-0125-preview'
- | 'gpt-4-turbo-preview'
- | 'gpt-4-1106-preview'
- | 'gpt-4-vision-preview'
- | 'gpt-4'
- | 'gpt-4-0314'
- | 'gpt-4-0613'
- | 'gpt-4-32k'
- | 'gpt-4-32k-0314'
- | 'gpt-4-32k-0613'
- | 'gpt-3.5-turbo'
- | 'gpt-3.5-turbo-16k'
- | 'gpt-3.5-turbo-0613'
- | 'gpt-3.5-turbo-1106'
- | 'gpt-3.5-turbo-0125'
- | 'gpt-3.5-turbo-16k-0613';
+ model: (string & {}) | ChatAPI.ChatModel;
/**
* The description of the assistant. The maximum length is 512 characters.
diff --git a/src/resources/beta/threads/runs/runs.ts b/src/resources/beta/threads/runs/runs.ts
index 24b6ce4a2..db9827616 100644
--- a/src/resources/beta/threads/runs/runs.ts
+++ b/src/resources/beta/threads/runs/runs.ts
@@ -9,6 +9,7 @@ import { sleep } from '../../../../core';
import { RunSubmitToolOutputsParamsStream } from '../../../../lib/AssistantStream';
import * as RunsAPI from './runs';
import * as AssistantsAPI from '../../assistants';
+import * as ChatAPI from '../../../chat/chat';
import * as MessagesAPI from '../messages';
import * as ThreadsAPI from '../threads';
import * as StepsAPI from './steps';
@@ -668,31 +669,7 @@ export interface RunCreateParamsBase {
* model associated with the assistant. If not, the model associated with the
* assistant will be used.
*/
- model?:
- | (string & {})
- | 'gpt-4o'
- | 'gpt-4o-2024-05-13'
- | 'gpt-4o-mini'
- | 'gpt-4o-mini-2024-07-18'
- | 'gpt-4-turbo'
- | 'gpt-4-turbo-2024-04-09'
- | 'gpt-4-0125-preview'
- | 'gpt-4-turbo-preview'
- | 'gpt-4-1106-preview'
- | 'gpt-4-vision-preview'
- | 'gpt-4'
- | 'gpt-4-0314'
- | 'gpt-4-0613'
- | 'gpt-4-32k'
- | 'gpt-4-32k-0314'
- | 'gpt-4-32k-0613'
- | 'gpt-3.5-turbo'
- | 'gpt-3.5-turbo-16k'
- | 'gpt-3.5-turbo-0613'
- | 'gpt-3.5-turbo-1106'
- | 'gpt-3.5-turbo-0125'
- | 'gpt-3.5-turbo-16k-0613'
- | null;
+ model?: (string & {}) | ChatAPI.ChatModel | null;
/**
* Whether to enable
diff --git a/src/resources/beta/threads/threads.ts b/src/resources/beta/threads/threads.ts
index 04ce7b57d..0b931a911 100644
--- a/src/resources/beta/threads/threads.ts
+++ b/src/resources/beta/threads/threads.ts
@@ -7,6 +7,7 @@ import { APIPromise } from '../../../core';
import * as Core from '../../../core';
import * as ThreadsAPI from './threads';
import * as AssistantsAPI from '../assistants';
+import * as ChatAPI from '../../chat/chat';
import * as MessagesAPI from './messages';
import * as RunsAPI from './runs/runs';
import { Stream } from '../../../streaming';
@@ -545,31 +546,7 @@ export interface ThreadCreateAndRunParamsBase {
* model associated with the assistant. If not, the model associated with the
* assistant will be used.
*/
- model?:
- | (string & {})
- | 'gpt-4o'
- | 'gpt-4o-2024-05-13'
- | 'gpt-4o-mini'
- | 'gpt-4o-mini-2024-07-18'
- | 'gpt-4-turbo'
- | 'gpt-4-turbo-2024-04-09'
- | 'gpt-4-0125-preview'
- | 'gpt-4-turbo-preview'
- | 'gpt-4-1106-preview'
- | 'gpt-4-vision-preview'
- | 'gpt-4'
- | 'gpt-4-0314'
- | 'gpt-4-0613'
- | 'gpt-4-32k'
- | 'gpt-4-32k-0314'
- | 'gpt-4-32k-0613'
- | 'gpt-3.5-turbo'
- | 'gpt-3.5-turbo-16k'
- | 'gpt-3.5-turbo-0613'
- | 'gpt-3.5-turbo-1106'
- | 'gpt-3.5-turbo-0125'
- | 'gpt-3.5-turbo-16k-0613'
- | null;
+ model?: (string & {}) | ChatAPI.ChatModel | null;
/**
* Whether to enable
diff --git a/src/resources/images.ts b/src/resources/images.ts
index 24af635b2..fdd0b8881 100644
--- a/src/resources/images.ts
+++ b/src/resources/images.ts
@@ -52,6 +52,8 @@ export interface Image {
url?: string;
}
+export type ImageModel = 'dall-e-2' | 'dall-e-3';
+
export interface ImagesResponse {
created: number;
@@ -69,7 +71,7 @@ export interface ImageCreateVariationParams {
* The model to use for image generation. Only `dall-e-2` is supported at this
* time.
*/
- model?: (string & {}) | 'dall-e-2' | null;
+ model?: (string & {}) | ImageModel | null;
/**
* The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only
@@ -122,7 +124,7 @@ export interface ImageEditParams {
* The model to use for image generation. Only `dall-e-2` is supported at this
* time.
*/
- model?: (string & {}) | 'dall-e-2' | null;
+ model?: (string & {}) | ImageModel | null;
/**
* The number of images to generate. Must be between 1 and 10.
@@ -160,7 +162,7 @@ export interface ImageGenerateParams {
/**
* The model to use for image generation.
*/
- model?: (string & {}) | 'dall-e-2' | 'dall-e-3' | null;
+ model?: (string & {}) | ImageModel | null;
/**
* The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only
@@ -207,6 +209,7 @@ export interface ImageGenerateParams {
export namespace Images {
export import Image = ImagesAPI.Image;
+ export import ImageModel = ImagesAPI.ImageModel;
export import ImagesResponse = ImagesAPI.ImagesResponse;
export import ImageCreateVariationParams = ImagesAPI.ImageCreateVariationParams;
export import ImageEditParams = ImagesAPI.ImageEditParams;
diff --git a/src/resources/index.ts b/src/resources/index.ts
index 9f2a3cbe7..8d952e2db 100644
--- a/src/resources/index.ts
+++ b/src/resources/index.ts
@@ -2,7 +2,7 @@
export * from './chat/index';
export * from './shared';
-export { Audio } from './audio/audio';
+export { AudioModel, Audio } from './audio/audio';
export {
Batch,
BatchError,
@@ -35,6 +35,7 @@ export {
export { FineTuning } from './fine-tuning/fine-tuning';
export {
Image,
+ ImageModel,
ImagesResponse,
ImageCreateVariationParams,
ImageEditParams,
@@ -42,5 +43,11 @@ export {
Images,
} from './images';
export { Model, ModelDeleted, ModelsPage, Models } from './models';
-export { Moderation, ModerationCreateResponse, ModerationCreateParams, Moderations } from './moderations';
+export {
+ Moderation,
+ ModerationModel,
+ ModerationCreateResponse,
+ ModerationCreateParams,
+ Moderations,
+} from './moderations';
export { Upload, UploadCreateParams, UploadCompleteParams, Uploads } from './uploads/uploads';
diff --git a/src/resources/moderations.ts b/src/resources/moderations.ts
index 86fbbc6b2..f80bc7acb 100644
--- a/src/resources/moderations.ts
+++ b/src/resources/moderations.ts
@@ -168,6 +168,8 @@ export namespace Moderation {
}
}
+export type ModerationModel = 'text-moderation-latest' | 'text-moderation-stable';
+
/**
* Represents if a given text input is potentially harmful.
*/
@@ -204,11 +206,12 @@ export interface ModerationCreateParams {
* model. Accuracy of `text-moderation-stable` may be slightly lower than for
* `text-moderation-latest`.
*/
- model?: (string & {}) | 'text-moderation-latest' | 'text-moderation-stable';
+ model?: (string & {}) | ModerationModel;
}
export namespace Moderations {
export import Moderation = ModerationsAPI.Moderation;
+ export import ModerationModel = ModerationsAPI.ModerationModel;
export import ModerationCreateResponse = ModerationsAPI.ModerationCreateResponse;
export import ModerationCreateParams = ModerationsAPI.ModerationCreateParams;
}
diff --git a/src/version.ts b/src/version.ts
index 3bfe73d03..bca401fd1 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '4.53.2'; // x-release-please-version
+export const VERSION = '4.54.0'; // x-release-please-version