From 55c01f4dc5d132c21713f9e8606b95abc76fcd44 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 19:47:25 +0000 Subject: [PATCH 1/7] chore(internal): add constant for default timeout (#960) --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 7e5df0505..ad8749ebb 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; From c610c813e8d7f96b5b8315ae194e0a9ff565f43d Mon Sep 17 00:00:00 2001 From: Guspan Tanadi <36249910+guspan-tanadi@users.noreply.github.com> Date: Tue, 30 Jul 2024 20:28:01 +0700 Subject: [PATCH 2/7] docs(README): link Lifecycle in Polling Helpers section (#962) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fed94642..c498880e0 100644 --- a/README.md +++ b/README.md @@ -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 From 8f499566c47bd7d4799a8cbe0d980553348b8f48 Mon Sep 17 00:00:00 2001 From: Robert Craigie Date: Tue, 30 Jul 2024 15:42:13 +0100 Subject: [PATCH 3/7] chore(internal): cleanup event stream helpers (#950) * [wip]: refactor * a solution * Bind this * fix formatting --------- Co-authored-by: Young-Jin Park --- src/lib/AbstractChatCompletionRunner.ts | 255 ++---------------- src/lib/AssistantStream.ts | 58 ++-- src/lib/ChatCompletionRunner.ts | 2 +- src/lib/ChatCompletionStream.ts | 4 +- ...ssistantStreamRunner.ts => EventStream.ts} | 175 +++--------- 5 files changed, 99 insertions(+), 395 deletions(-) rename src/lib/{AbstractAssistantStreamRunner.ts => EventStream.ts} (55%) 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; From f1a4a686bbf4a38919b8597f008d895d1b99d8df Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:31:55 +0000 Subject: [PATCH 4/7] chore(ci): correctly tag pre-release npm packages (#963) --- bin/publish-npm | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) 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" From 1edf957e1cb86c2a7b2d29e28f2b8f428ea0cd7d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 02:47:09 +0000 Subject: [PATCH 5/7] feat: extract out `ImageModel`, `AudioModel`, `SpeechModel` (#964) --- api.md | 10 +++++++++ src/index.ts | 3 +++ src/resources/audio/audio.ts | 5 +++++ src/resources/audio/index.ts | 4 ++-- src/resources/audio/speech.ts | 5 ++++- src/resources/audio/transcriptions.ts | 3 ++- src/resources/audio/translations.ts | 3 ++- src/resources/beta/assistants.ts | 26 ++---------------------- src/resources/beta/threads/runs/runs.ts | 27 ++----------------------- src/resources/beta/threads/threads.ts | 27 ++----------------------- src/resources/images.ts | 9 ++++++--- src/resources/index.ts | 11 ++++++++-- src/resources/moderations.ts | 5 ++++- 13 files changed, 53 insertions(+), 85 deletions(-) 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/src/index.ts b/src/index.ts index ad8749ebb..cd0dd67b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -282,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/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; } From 0dd0cd158d6765c3a04ac983aad03c2ecad14502 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 04:04:23 +0000 Subject: [PATCH 6/7] feat: make enums not nominal (#965) --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From d7a40827762efbbb50cdeea12866bfc9d522bc42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 04:04:49 +0000 Subject: [PATCH 7/7] release: 4.54.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 21 +++++++++++++++++++++ README.md | 2 +- package.json | 2 +- scripts/build-deno | 2 +- src/version.ts | 2 +- 6 files changed, 26 insertions(+), 5 deletions(-) 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/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 c498880e0..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'; ``` 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/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