@memberjunction/ai-openai 5.40.2 → 5.41.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/models/openAIRealtime.d.ts +256 -0
- package/dist/models/openAIRealtime.d.ts.map +1 -0
- package/dist/models/openAIRealtime.js +439 -0
- package/dist/models/openAIRealtime.js.map +1 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { BaseRealtimeModel, IRealtimeSession, RealtimeSessionParams, RealtimeToolDefinition, RealtimeTranscript, RealtimeToolCall, RealtimeUsage, RealtimeSessionError } from '@memberjunction/ai';
|
|
2
|
+
import { ClientRealtimeSessionConfig } from '@memberjunction/ai';
|
|
3
|
+
import { OpenAI } from 'openai';
|
|
4
|
+
import type { OpenAIRealtimeError } from 'openai/realtime/index';
|
|
5
|
+
import type { RealtimeClientEvent, RealtimeServerEvent } from 'openai/resources/realtime/realtime';
|
|
6
|
+
import type { ClientSecretCreateParams, ClientSecretCreateResponse } from 'openai/resources/realtime/client-secrets';
|
|
7
|
+
/**
|
|
8
|
+
* Minimal connection surface the {@link OpenAIRealtime} driver depends on.
|
|
9
|
+
*
|
|
10
|
+
* This is the **injectable seam** for testing. It is a structural subset of the SDK's
|
|
11
|
+
* `OpenAIRealtimeWebSocket` (which extends `OpenAIRealtimeEmitter`): the driver only ever
|
|
12
|
+
* uses `on`, `off`, `send`, and `close`. Because the driver creates its connection through the
|
|
13
|
+
* overridable {@link OpenAIRealtime.createConnection} method, unit tests subclass the driver and
|
|
14
|
+
* return a fake connection implementing this interface — no network and no real WebSocket.
|
|
15
|
+
*/
|
|
16
|
+
export interface IOpenAIRealtimeConnection {
|
|
17
|
+
/**
|
|
18
|
+
* Registers a listener for a server event type (`'event'` for the catch-all firehose).
|
|
19
|
+
*
|
|
20
|
+
* Return type is `void` because the driver never uses the chained return value, even though the
|
|
21
|
+
* SDK's `EventEmitter` returns `this` for chaining. A void-returning method is assignable from a
|
|
22
|
+
* value-returning one, so a real `OpenAIRealtimeWebSocket` still satisfies this interface.
|
|
23
|
+
*/
|
|
24
|
+
on(event: 'event', listener: (event: RealtimeServerEvent) => void): void;
|
|
25
|
+
/**
|
|
26
|
+
* Registers a listener for connection errors. The SDK routes BOTH transport-level failures
|
|
27
|
+
* (socket error, unparseable frame, failed send — `error.error` is undefined) and provider
|
|
28
|
+
* `error` server frames (`error.error` carries the payload) through this channel; the driver
|
|
29
|
+
* classifies fatality from that distinction.
|
|
30
|
+
*/
|
|
31
|
+
on(event: 'error', listener: (error: OpenAIRealtimeError) => void): void;
|
|
32
|
+
/** Removes a previously-registered listener. See {@link IOpenAIRealtimeConnection.on} re: return type. */
|
|
33
|
+
off(event: 'event', listener: (event: RealtimeServerEvent) => void): void;
|
|
34
|
+
/** Removes a previously-registered error listener. */
|
|
35
|
+
off(event: 'error', listener: (error: OpenAIRealtimeError) => void): void;
|
|
36
|
+
/** Sends a client event to the realtime API. */
|
|
37
|
+
send(event: RealtimeClientEvent): void;
|
|
38
|
+
/** Closes the underlying socket. */
|
|
39
|
+
close(props?: {
|
|
40
|
+
code: number;
|
|
41
|
+
reason: string;
|
|
42
|
+
}): void;
|
|
43
|
+
/**
|
|
44
|
+
* Optional raw WebSocket surface (present on the real `OpenAIRealtimeWebSocket`, which exposes
|
|
45
|
+
* its underlying `socket`). Used solely to detect UNEXPECTED closure — the SDK emitter has no
|
|
46
|
+
* close event of its own. The driver feature-detects; fakes may omit it.
|
|
47
|
+
*/
|
|
48
|
+
socket?: {
|
|
49
|
+
addEventListener(type: 'close', listener: () => void): void;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* OpenAI implementation of the {@link BaseRealtimeModel} primitive, backed by OpenAI's
|
|
54
|
+
* Realtime API over a WebSocket (`OpenAIRealtimeWebSocket` from the `openai` SDK, v6.18.0).
|
|
55
|
+
*
|
|
56
|
+
* The driver opens a duplex session, configures it (system prompt + tools + optional initial
|
|
57
|
+
* context), and translates the provider's server-event stream into the modality-agnostic
|
|
58
|
+
* {@link IRealtimeSession} contract.
|
|
59
|
+
*
|
|
60
|
+
* **Tool results** complete the tool-call loop: the returned session implements the Core
|
|
61
|
+
* `IRealtimeSession.SendToolResult` contract method, which the agent layer calls after executing a
|
|
62
|
+
* tool to feed its result back to the model. See {@link OpenAIRealtimeSession.SendToolResult}.
|
|
63
|
+
*/
|
|
64
|
+
export declare class OpenAIRealtime extends BaseRealtimeModel {
|
|
65
|
+
private _openAI;
|
|
66
|
+
constructor(apiKey: string);
|
|
67
|
+
/** Read-only accessor for the underlying OpenAI SDK client. */
|
|
68
|
+
get OpenAI(): OpenAI;
|
|
69
|
+
/**
|
|
70
|
+
* Creates the realtime connection for a model. Overridable seam for testing.
|
|
71
|
+
*
|
|
72
|
+
* Production returns a real `OpenAIRealtimeWebSocket`. Unit tests override this to return a
|
|
73
|
+
* fake {@link IOpenAIRealtimeConnection} that emits OpenAI-shaped events and captures sends.
|
|
74
|
+
*
|
|
75
|
+
* @param model The provider realtime model id (e.g. `gpt-realtime`).
|
|
76
|
+
* @returns A connection implementing {@link IOpenAIRealtimeConnection}.
|
|
77
|
+
*/
|
|
78
|
+
protected createConnection(model: string): IOpenAIRealtimeConnection;
|
|
79
|
+
/**
|
|
80
|
+
* Opens a duplex realtime session, applies the session config, and returns the live handle.
|
|
81
|
+
*
|
|
82
|
+
* @param params Session configuration (model, system prompt, tools, initial context, config bag).
|
|
83
|
+
* @returns A promise resolving to the {@link IRealtimeSession} handle.
|
|
84
|
+
*/
|
|
85
|
+
StartSession(params: RealtimeSessionParams): Promise<IRealtimeSession>;
|
|
86
|
+
/**
|
|
87
|
+
* OpenAI supports the client-direct topology: the server mints a short-lived ephemeral
|
|
88
|
+
* client secret that the browser uses to open its OWN connection to OpenAI's Realtime API,
|
|
89
|
+
* while the server still controls the system prompt + tools via the returned SessionConfig.
|
|
90
|
+
*/
|
|
91
|
+
get SupportsClientDirect(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Mints the ephemeral client secret via OpenAI's Realtime client-secrets API. Overridable
|
|
94
|
+
* seam for testing — unit tests return a fake response so no network call is made.
|
|
95
|
+
*
|
|
96
|
+
* @param body The client-secret create request (carries the realtime session config).
|
|
97
|
+
* @returns The OpenAI client-secret create response (token value + expiry + echoed session).
|
|
98
|
+
*/
|
|
99
|
+
protected mintClientSecret(body: ClientSecretCreateParams): Promise<ClientSecretCreateResponse>;
|
|
100
|
+
/**
|
|
101
|
+
* Mints an ephemeral, server-scoped realtime session credential for a browser to open its
|
|
102
|
+
* own provider connection (client-direct topology). The server builds the session config
|
|
103
|
+
* (system prompt + tools + model) so it retains control of behavior even though the browser
|
|
104
|
+
* owns the socket.
|
|
105
|
+
*
|
|
106
|
+
* @param params Session configuration (model, system prompt, tools).
|
|
107
|
+
* @returns The minted {@link ClientRealtimeSessionConfig} the browser authenticates + applies.
|
|
108
|
+
*/
|
|
109
|
+
CreateClientSession(params: RealtimeSessionParams): Promise<ClientRealtimeSessionConfig>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Live {@link IRealtimeSession} backed by an {@link IOpenAIRealtimeConnection}.
|
|
113
|
+
*
|
|
114
|
+
* Holds the registered handlers and the single `'event'` listener that fans the provider's
|
|
115
|
+
* server-event stream out to the contract handlers via {@link OpenAIRealtimeSession.dispatch}.
|
|
116
|
+
*/
|
|
117
|
+
export declare class OpenAIRealtimeSession implements IRealtimeSession {
|
|
118
|
+
private connection;
|
|
119
|
+
private outputHandler?;
|
|
120
|
+
private transcriptHandler?;
|
|
121
|
+
private toolCallHandler?;
|
|
122
|
+
private interruptionHandler?;
|
|
123
|
+
private usageHandler?;
|
|
124
|
+
private errorHandler?;
|
|
125
|
+
private closeHandler?;
|
|
126
|
+
private eventListener;
|
|
127
|
+
private errorListener;
|
|
128
|
+
/** Set by {@link Close} so a consumer-initiated teardown never reports an "unexpected" close. */
|
|
129
|
+
private closedByConsumer;
|
|
130
|
+
/**
|
|
131
|
+
* Whether a model response is currently in flight. Minimal response tracking that mirrors the
|
|
132
|
+
* client driver's state machine: set on `response.created` (and eagerly whenever this session
|
|
133
|
+
* sends its own `response.create`, so back-to-back local triggers can't race the server event),
|
|
134
|
+
* cleared on `response.done` — which the API emits for every terminal status, including
|
|
135
|
+
* `cancelled` after barge-in, so the flag can never stick. Consumed by
|
|
136
|
+
* {@link OpenAIRealtimeSession.RequestSpokenUpdate} to skip (not collide with) an active
|
|
137
|
+
* response, since the API rejects overlapping `response.create` requests.
|
|
138
|
+
*/
|
|
139
|
+
private responseActive;
|
|
140
|
+
constructor(connection: IOpenAIRealtimeConnection);
|
|
141
|
+
/**
|
|
142
|
+
* Applies the initial session config: system prompt + tools via `session.update`, optional
|
|
143
|
+
* initial context as a user message. Called once by {@link OpenAIRealtime.StartSession}.
|
|
144
|
+
*
|
|
145
|
+
* @param params The session parameters.
|
|
146
|
+
*/
|
|
147
|
+
applyInitialConfig(params: RealtimeSessionParams): void;
|
|
148
|
+
/** @inheritdoc */
|
|
149
|
+
SendInput(chunk: ArrayBuffer): void;
|
|
150
|
+
/** @inheritdoc */
|
|
151
|
+
RegisterTools(tools: RealtimeToolDefinition[]): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* @inheritdoc
|
|
154
|
+
*
|
|
155
|
+
* Completes the tool-call loop for OpenAI: sends a `conversation.item.create` with a
|
|
156
|
+
* `function_call_output` item carrying the tool output, then a `response.create` so the model
|
|
157
|
+
* continues the turn with the result in context.
|
|
158
|
+
*
|
|
159
|
+
* @param callID The `CallID` from the originating {@link RealtimeToolCall}.
|
|
160
|
+
* @param output The tool's result as a JSON-stringified string.
|
|
161
|
+
*/
|
|
162
|
+
SendToolResult(callID: string, output: string): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* @inheritdoc
|
|
165
|
+
*
|
|
166
|
+
* Injects a **system-role** conversation item (`conversation.item.create`) the model can draw
|
|
167
|
+
* on the next time it speaks, WITHOUT a `response.create` — so no spoken reply is forced.
|
|
168
|
+
*
|
|
169
|
+
* NOTE: the role must be `'system'` — gpt-realtime rejects `'developer'` items ("Developer
|
|
170
|
+
* messages are only supported for quicksilver sessions"); same constraint the client-direct
|
|
171
|
+
* driver hit. Item creation is always safe mid-response on OpenAI, so no collision guard is
|
|
172
|
+
* needed here (unlike {@link OpenAIRealtimeSession.RequestSpokenUpdate}).
|
|
173
|
+
*
|
|
174
|
+
* @param text The context note to append to the conversation.
|
|
175
|
+
*/
|
|
176
|
+
SendContextNote(text: string): void;
|
|
177
|
+
/**
|
|
178
|
+
* @inheritdoc
|
|
179
|
+
*
|
|
180
|
+
* Triggers ONE short spoken update via `response.create` with per-response `instructions`.
|
|
181
|
+
*
|
|
182
|
+
* **Collision behavior: skip.** The Realtime API rejects a `response.create` while another
|
|
183
|
+
* response is active, so when {@link responseActive} is set the request is dropped — interim
|
|
184
|
+
* updates are disposable by contract (the next update or the final result supersedes them).
|
|
185
|
+
* When sent, the flag is set eagerly (before the server's `response.created` echo) so two
|
|
186
|
+
* back-to-back local triggers can't both fire.
|
|
187
|
+
*
|
|
188
|
+
* @param instructions Instructions for the single spoken update.
|
|
189
|
+
*/
|
|
190
|
+
RequestSpokenUpdate(instructions: string): void;
|
|
191
|
+
/** @inheritdoc */
|
|
192
|
+
OnOutput(handler: (chunk: ArrayBuffer) => void): void;
|
|
193
|
+
/** @inheritdoc */
|
|
194
|
+
OnTranscript(handler: (t: RealtimeTranscript) => void): void;
|
|
195
|
+
/** @inheritdoc */
|
|
196
|
+
OnToolCall(handler: (call: RealtimeToolCall) => void): void;
|
|
197
|
+
/** @inheritdoc */
|
|
198
|
+
OnInterruption(handler: () => void): void;
|
|
199
|
+
/** @inheritdoc */
|
|
200
|
+
OnUsage(handler: (u: RealtimeUsage) => void): void;
|
|
201
|
+
/** @inheritdoc */
|
|
202
|
+
OnError(handler: (error: RealtimeSessionError) => void): void;
|
|
203
|
+
/** @inheritdoc */
|
|
204
|
+
OnClose(handler: () => void): void;
|
|
205
|
+
/** @inheritdoc */
|
|
206
|
+
Close(): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* Routes a provider server event to the matching contract handler. Each branch delegates to a
|
|
209
|
+
* small, single-purpose handler to keep this dispatcher flat.
|
|
210
|
+
*
|
|
211
|
+
* @param event The OpenAI realtime server event.
|
|
212
|
+
*/
|
|
213
|
+
private dispatch;
|
|
214
|
+
/** Decodes a base64 audio delta and forwards it to the output handler. */
|
|
215
|
+
private handleAudioDelta;
|
|
216
|
+
/** Emits a transcript event to the transcript handler. */
|
|
217
|
+
private emitTranscript;
|
|
218
|
+
/** Forwards a completed function call to the tool-call handler. */
|
|
219
|
+
private handleFunctionCall;
|
|
220
|
+
/**
|
|
221
|
+
* Notifies the interruption handler of TRUE barge-in only: user speech that cut off an
|
|
222
|
+
* ACTIVE model response. A `speech_started` while the model is idle is just the user taking
|
|
223
|
+
* their normal turn — the {@link IRealtimeSession.OnInterruption} contract explicitly excludes
|
|
224
|
+
* it, so the raw frame is gated on {@link responseActive} (the server-bridged topology's proxy
|
|
225
|
+
* for "model output in flight"). The provider cancels its own turn and emits a terminal
|
|
226
|
+
* `response.done`, which clears the flag.
|
|
227
|
+
*/
|
|
228
|
+
private handleInterruption;
|
|
229
|
+
/**
|
|
230
|
+
* Classifies an SDK connection error and forwards it to the error handler. The SDK routes
|
|
231
|
+
* BOTH kinds through its `'error'` emitter: provider `error` server frames carry a payload in
|
|
232
|
+
* `error.error` (recoverable — the session stays open, `Fatal: false`) while transport-level
|
|
233
|
+
* failures (socket error, unparseable frame, failed send) have no payload (`Fatal: true` —
|
|
234
|
+
* including the credential/token-expiry case, which surfaces as a transport teardown).
|
|
235
|
+
*/
|
|
236
|
+
private handleConnectionError;
|
|
237
|
+
/**
|
|
238
|
+
* Handles the raw socket closing. A consumer-initiated {@link Close} is expected and silent;
|
|
239
|
+
* anything else (provider hangup, network drop, token death) is surfaced as a FATAL error —
|
|
240
|
+
* so consumers finalize instead of idling on a dead socket — followed by the close handler.
|
|
241
|
+
*/
|
|
242
|
+
private handleSocketClose;
|
|
243
|
+
/** Translates a response's usage block into a {@link RealtimeUsage} update. */
|
|
244
|
+
private handleResponseDone;
|
|
245
|
+
/** Sends the `session.update` that establishes instructions, input transcription, and tools. */
|
|
246
|
+
private sendSessionUpdate;
|
|
247
|
+
/** Seeds the conversation with initial context as a user text message. */
|
|
248
|
+
private sendInitialContext;
|
|
249
|
+
/** Maps Core tool definitions up to OpenAI's native function-tool schema (shared mapping). */
|
|
250
|
+
private mapTools;
|
|
251
|
+
/** Encodes a raw media frame as base64 for the provider's append event. */
|
|
252
|
+
private encodeBase64;
|
|
253
|
+
/** Decodes a base64 audio delta into a freshly-allocated `ArrayBuffer`. */
|
|
254
|
+
private decodeBase64;
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=openAIRealtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openAIRealtime.d.ts","sourceRoot":"","sources":["../../src/models/openAIRealtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
11
|
+
import { BaseRealtimeModel, } from '@memberjunction/ai';
|
|
12
|
+
import { OpenAI } from 'openai';
|
|
13
|
+
import { OpenAIRealtimeWebSocket } from 'openai/realtime/websocket';
|
|
14
|
+
/**
|
|
15
|
+
* The ASR model used to transcribe the USER's audio input. Realtime models accept audio
|
|
16
|
+
* natively, so input transcription is a separate pass that must be opted into — without it only
|
|
17
|
+
* assistant-side transcripts flow. Shared by BOTH topologies ({@link OpenAIRealtime.CreateClientSession}
|
|
18
|
+
* for client-direct and {@link OpenAIRealtimeSession.applyInitialConfig} for server-bridged) so the
|
|
19
|
+
* contract's promise of both-role transcripts holds everywhere.
|
|
20
|
+
*/
|
|
21
|
+
const OPENAI_INPUT_TRANSCRIPTION_MODEL = 'gpt-4o-mini-transcribe';
|
|
22
|
+
/**
|
|
23
|
+
* Maps Core {@link RealtimeToolDefinition}s up to OpenAI's native function-tool schema.
|
|
24
|
+
*
|
|
25
|
+
* The single mapping used everywhere a tool set is sent to the Realtime API: the live
|
|
26
|
+
* `session.update` path ({@link OpenAIRealtimeSession.mapTools}) and the client-direct
|
|
27
|
+
* ephemeral-secret path ({@link OpenAIRealtime.CreateClientSession}) both call this so the two
|
|
28
|
+
* topologies expose byte-for-byte identical tool schemas.
|
|
29
|
+
*
|
|
30
|
+
* @param tools The Core tool definitions to map.
|
|
31
|
+
* @returns The OpenAI realtime function-tool array.
|
|
32
|
+
*/
|
|
33
|
+
function mapRealtimeTools(tools) {
|
|
34
|
+
return tools.map((tool) => ({
|
|
35
|
+
type: 'function',
|
|
36
|
+
name: tool.Name,
|
|
37
|
+
description: tool.Description,
|
|
38
|
+
parameters: tool.ParametersSchema,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* OpenAI implementation of the {@link BaseRealtimeModel} primitive, backed by OpenAI's
|
|
43
|
+
* Realtime API over a WebSocket (`OpenAIRealtimeWebSocket` from the `openai` SDK, v6.18.0).
|
|
44
|
+
*
|
|
45
|
+
* The driver opens a duplex session, configures it (system prompt + tools + optional initial
|
|
46
|
+
* context), and translates the provider's server-event stream into the modality-agnostic
|
|
47
|
+
* {@link IRealtimeSession} contract.
|
|
48
|
+
*
|
|
49
|
+
* **Tool results** complete the tool-call loop: the returned session implements the Core
|
|
50
|
+
* `IRealtimeSession.SendToolResult` contract method, which the agent layer calls after executing a
|
|
51
|
+
* tool to feed its result back to the model. See {@link OpenAIRealtimeSession.SendToolResult}.
|
|
52
|
+
*/
|
|
53
|
+
let OpenAIRealtime = class OpenAIRealtime extends BaseRealtimeModel {
|
|
54
|
+
constructor(apiKey) {
|
|
55
|
+
super(apiKey);
|
|
56
|
+
this._openAI = new OpenAI({ apiKey });
|
|
57
|
+
}
|
|
58
|
+
/** Read-only accessor for the underlying OpenAI SDK client. */
|
|
59
|
+
get OpenAI() {
|
|
60
|
+
return this._openAI;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Creates the realtime connection for a model. Overridable seam for testing.
|
|
64
|
+
*
|
|
65
|
+
* Production returns a real `OpenAIRealtimeWebSocket`. Unit tests override this to return a
|
|
66
|
+
* fake {@link IOpenAIRealtimeConnection} that emits OpenAI-shaped events and captures sends.
|
|
67
|
+
*
|
|
68
|
+
* @param model The provider realtime model id (e.g. `gpt-realtime`).
|
|
69
|
+
* @returns A connection implementing {@link IOpenAIRealtimeConnection}.
|
|
70
|
+
*/
|
|
71
|
+
createConnection(model) {
|
|
72
|
+
return new OpenAIRealtimeWebSocket({ model }, this._openAI);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Opens a duplex realtime session, applies the session config, and returns the live handle.
|
|
76
|
+
*
|
|
77
|
+
* @param params Session configuration (model, system prompt, tools, initial context, config bag).
|
|
78
|
+
* @returns A promise resolving to the {@link IRealtimeSession} handle.
|
|
79
|
+
*/
|
|
80
|
+
async StartSession(params) {
|
|
81
|
+
const connection = this.createConnection(params.Model);
|
|
82
|
+
const session = new OpenAIRealtimeSession(connection);
|
|
83
|
+
session.applyInitialConfig(params);
|
|
84
|
+
return session;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* OpenAI supports the client-direct topology: the server mints a short-lived ephemeral
|
|
88
|
+
* client secret that the browser uses to open its OWN connection to OpenAI's Realtime API,
|
|
89
|
+
* while the server still controls the system prompt + tools via the returned SessionConfig.
|
|
90
|
+
*/
|
|
91
|
+
get SupportsClientDirect() {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Mints the ephemeral client secret via OpenAI's Realtime client-secrets API. Overridable
|
|
96
|
+
* seam for testing — unit tests return a fake response so no network call is made.
|
|
97
|
+
*
|
|
98
|
+
* @param body The client-secret create request (carries the realtime session config).
|
|
99
|
+
* @returns The OpenAI client-secret create response (token value + expiry + echoed session).
|
|
100
|
+
*/
|
|
101
|
+
async mintClientSecret(body) {
|
|
102
|
+
return this._openAI.realtime.clientSecrets.create(body);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Mints an ephemeral, server-scoped realtime session credential for a browser to open its
|
|
106
|
+
* own provider connection (client-direct topology). The server builds the session config
|
|
107
|
+
* (system prompt + tools + model) so it retains control of behavior even though the browser
|
|
108
|
+
* owns the socket.
|
|
109
|
+
*
|
|
110
|
+
* @param params Session configuration (model, system prompt, tools).
|
|
111
|
+
* @returns The minted {@link ClientRealtimeSessionConfig} the browser authenticates + applies.
|
|
112
|
+
*/
|
|
113
|
+
async CreateClientSession(params) {
|
|
114
|
+
const session = {
|
|
115
|
+
type: 'realtime',
|
|
116
|
+
model: params.Model,
|
|
117
|
+
instructions: params.SystemPrompt,
|
|
118
|
+
};
|
|
119
|
+
if (params.Tools && params.Tools.length > 0) {
|
|
120
|
+
session.tools = mapRealtimeTools(params.Tools);
|
|
121
|
+
}
|
|
122
|
+
// Enable transcription of the user's mic input so BOTH sides of the conversation are
|
|
123
|
+
// captured (live captions + persisted ConversationDetail turns). Realtime models accept
|
|
124
|
+
// audio natively, so input transcription is a separate ASR pass that must be opted into.
|
|
125
|
+
session.audio = { input: { transcription: { model: OPENAI_INPUT_TRANSCRIPTION_MODEL } } };
|
|
126
|
+
const response = await this.mintClientSecret({ session });
|
|
127
|
+
return {
|
|
128
|
+
Provider: 'openai',
|
|
129
|
+
Model: params.Model,
|
|
130
|
+
EphemeralToken: response.value,
|
|
131
|
+
ExpiresAt: new Date(response.expires_at * 1000).toISOString(),
|
|
132
|
+
// The provider-native session config the browser applies verbatim (plain JSON).
|
|
133
|
+
SessionConfig: JSON.parse(JSON.stringify(session)),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
OpenAIRealtime = __decorate([
|
|
138
|
+
RegisterClass(BaseRealtimeModel, 'OpenAIRealtime'),
|
|
139
|
+
__metadata("design:paramtypes", [String])
|
|
140
|
+
], OpenAIRealtime);
|
|
141
|
+
export { OpenAIRealtime };
|
|
142
|
+
/**
|
|
143
|
+
* Live {@link IRealtimeSession} backed by an {@link IOpenAIRealtimeConnection}.
|
|
144
|
+
*
|
|
145
|
+
* Holds the registered handlers and the single `'event'` listener that fans the provider's
|
|
146
|
+
* server-event stream out to the contract handlers via {@link OpenAIRealtimeSession.dispatch}.
|
|
147
|
+
*/
|
|
148
|
+
export class OpenAIRealtimeSession {
|
|
149
|
+
constructor(connection) {
|
|
150
|
+
/** Set by {@link Close} so a consumer-initiated teardown never reports an "unexpected" close. */
|
|
151
|
+
this.closedByConsumer = false;
|
|
152
|
+
/**
|
|
153
|
+
* Whether a model response is currently in flight. Minimal response tracking that mirrors the
|
|
154
|
+
* client driver's state machine: set on `response.created` (and eagerly whenever this session
|
|
155
|
+
* sends its own `response.create`, so back-to-back local triggers can't race the server event),
|
|
156
|
+
* cleared on `response.done` — which the API emits for every terminal status, including
|
|
157
|
+
* `cancelled` after barge-in, so the flag can never stick. Consumed by
|
|
158
|
+
* {@link OpenAIRealtimeSession.RequestSpokenUpdate} to skip (not collide with) an active
|
|
159
|
+
* response, since the API rejects overlapping `response.create` requests.
|
|
160
|
+
*/
|
|
161
|
+
this.responseActive = false;
|
|
162
|
+
this.connection = connection;
|
|
163
|
+
this.eventListener = (event) => this.dispatch(event);
|
|
164
|
+
this.connection.on('event', this.eventListener);
|
|
165
|
+
this.errorListener = (error) => this.handleConnectionError(error);
|
|
166
|
+
this.connection.on('error', this.errorListener);
|
|
167
|
+
// The SDK emitter has no close event; detect unexpected closure from the raw socket when
|
|
168
|
+
// the connection exposes it (the real OpenAIRealtimeWebSocket does; fakes may omit it).
|
|
169
|
+
this.connection.socket?.addEventListener('close', () => this.handleSocketClose());
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Applies the initial session config: system prompt + tools via `session.update`, optional
|
|
173
|
+
* initial context as a user message. Called once by {@link OpenAIRealtime.StartSession}.
|
|
174
|
+
*
|
|
175
|
+
* @param params The session parameters.
|
|
176
|
+
*/
|
|
177
|
+
applyInitialConfig(params) {
|
|
178
|
+
this.sendSessionUpdate(params.SystemPrompt, params.Tools, params.Config);
|
|
179
|
+
if (params.InitialContext && params.InitialContext.length > 0) {
|
|
180
|
+
this.sendInitialContext(params.InitialContext);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ---- IRealtimeSession outbound ----
|
|
184
|
+
/** @inheritdoc */
|
|
185
|
+
SendInput(chunk) {
|
|
186
|
+
this.connection.send({
|
|
187
|
+
type: 'input_audio_buffer.append',
|
|
188
|
+
audio: this.encodeBase64(chunk),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/** @inheritdoc */
|
|
192
|
+
async RegisterTools(tools) {
|
|
193
|
+
this.connection.send({
|
|
194
|
+
type: 'session.update',
|
|
195
|
+
session: { type: 'realtime', tools: this.mapTools(tools) },
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @inheritdoc
|
|
200
|
+
*
|
|
201
|
+
* Completes the tool-call loop for OpenAI: sends a `conversation.item.create` with a
|
|
202
|
+
* `function_call_output` item carrying the tool output, then a `response.create` so the model
|
|
203
|
+
* continues the turn with the result in context.
|
|
204
|
+
*
|
|
205
|
+
* @param callID The `CallID` from the originating {@link RealtimeToolCall}.
|
|
206
|
+
* @param output The tool's result as a JSON-stringified string.
|
|
207
|
+
*/
|
|
208
|
+
async SendToolResult(callID, output) {
|
|
209
|
+
const item = {
|
|
210
|
+
type: 'function_call_output',
|
|
211
|
+
call_id: callID,
|
|
212
|
+
output,
|
|
213
|
+
};
|
|
214
|
+
this.connection.send({ type: 'conversation.item.create', item });
|
|
215
|
+
this.connection.send({ type: 'response.create' });
|
|
216
|
+
// This deliberately triggers a response — mark it active eagerly so an interim
|
|
217
|
+
// RequestSpokenUpdate arriving before the server's response.created cannot collide.
|
|
218
|
+
this.responseActive = true;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* @inheritdoc
|
|
222
|
+
*
|
|
223
|
+
* Injects a **system-role** conversation item (`conversation.item.create`) the model can draw
|
|
224
|
+
* on the next time it speaks, WITHOUT a `response.create` — so no spoken reply is forced.
|
|
225
|
+
*
|
|
226
|
+
* NOTE: the role must be `'system'` — gpt-realtime rejects `'developer'` items ("Developer
|
|
227
|
+
* messages are only supported for quicksilver sessions"); same constraint the client-direct
|
|
228
|
+
* driver hit. Item creation is always safe mid-response on OpenAI, so no collision guard is
|
|
229
|
+
* needed here (unlike {@link OpenAIRealtimeSession.RequestSpokenUpdate}).
|
|
230
|
+
*
|
|
231
|
+
* @param text The context note to append to the conversation.
|
|
232
|
+
*/
|
|
233
|
+
SendContextNote(text) {
|
|
234
|
+
const item = {
|
|
235
|
+
type: 'message',
|
|
236
|
+
role: 'system',
|
|
237
|
+
content: [{ type: 'input_text', text }],
|
|
238
|
+
};
|
|
239
|
+
this.connection.send({ type: 'conversation.item.create', item });
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* @inheritdoc
|
|
243
|
+
*
|
|
244
|
+
* Triggers ONE short spoken update via `response.create` with per-response `instructions`.
|
|
245
|
+
*
|
|
246
|
+
* **Collision behavior: skip.** The Realtime API rejects a `response.create` while another
|
|
247
|
+
* response is active, so when {@link responseActive} is set the request is dropped — interim
|
|
248
|
+
* updates are disposable by contract (the next update or the final result supersedes them).
|
|
249
|
+
* When sent, the flag is set eagerly (before the server's `response.created` echo) so two
|
|
250
|
+
* back-to-back local triggers can't both fire.
|
|
251
|
+
*
|
|
252
|
+
* @param instructions Instructions for the single spoken update.
|
|
253
|
+
*/
|
|
254
|
+
RequestSpokenUpdate(instructions) {
|
|
255
|
+
if (this.responseActive) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
this.responseActive = true;
|
|
259
|
+
this.connection.send({ type: 'response.create', response: { instructions } });
|
|
260
|
+
}
|
|
261
|
+
// ---- IRealtimeSession handler registration ----
|
|
262
|
+
/** @inheritdoc */
|
|
263
|
+
OnOutput(handler) {
|
|
264
|
+
this.outputHandler = handler;
|
|
265
|
+
}
|
|
266
|
+
/** @inheritdoc */
|
|
267
|
+
OnTranscript(handler) {
|
|
268
|
+
this.transcriptHandler = handler;
|
|
269
|
+
}
|
|
270
|
+
/** @inheritdoc */
|
|
271
|
+
OnToolCall(handler) {
|
|
272
|
+
this.toolCallHandler = handler;
|
|
273
|
+
}
|
|
274
|
+
/** @inheritdoc */
|
|
275
|
+
OnInterruption(handler) {
|
|
276
|
+
this.interruptionHandler = handler;
|
|
277
|
+
}
|
|
278
|
+
/** @inheritdoc */
|
|
279
|
+
OnUsage(handler) {
|
|
280
|
+
this.usageHandler = handler;
|
|
281
|
+
}
|
|
282
|
+
/** @inheritdoc */
|
|
283
|
+
OnError(handler) {
|
|
284
|
+
this.errorHandler = handler;
|
|
285
|
+
}
|
|
286
|
+
/** @inheritdoc */
|
|
287
|
+
OnClose(handler) {
|
|
288
|
+
this.closeHandler = handler;
|
|
289
|
+
}
|
|
290
|
+
/** @inheritdoc */
|
|
291
|
+
async Close() {
|
|
292
|
+
this.closedByConsumer = true;
|
|
293
|
+
this.connection.off('event', this.eventListener);
|
|
294
|
+
this.connection.off('error', this.errorListener);
|
|
295
|
+
this.connection.close();
|
|
296
|
+
}
|
|
297
|
+
// ---- Inbound event translation ----
|
|
298
|
+
/**
|
|
299
|
+
* Routes a provider server event to the matching contract handler. Each branch delegates to a
|
|
300
|
+
* small, single-purpose handler to keep this dispatcher flat.
|
|
301
|
+
*
|
|
302
|
+
* @param event The OpenAI realtime server event.
|
|
303
|
+
*/
|
|
304
|
+
dispatch(event) {
|
|
305
|
+
switch (event.type) {
|
|
306
|
+
case 'response.output_audio.delta':
|
|
307
|
+
return this.handleAudioDelta(event.delta);
|
|
308
|
+
case 'response.output_audio_transcript.delta':
|
|
309
|
+
return this.emitTranscript('assistant', event.delta, false);
|
|
310
|
+
case 'response.output_audio_transcript.done':
|
|
311
|
+
return this.emitTranscript('assistant', event.transcript, true);
|
|
312
|
+
case 'conversation.item.input_audio_transcription.delta':
|
|
313
|
+
return this.emitTranscript('user', event.delta ?? '', false);
|
|
314
|
+
case 'conversation.item.input_audio_transcription.completed':
|
|
315
|
+
return this.emitTranscript('user', event.transcript, true);
|
|
316
|
+
case 'response.function_call_arguments.done':
|
|
317
|
+
return this.handleFunctionCall(event.call_id, event.name, event.arguments);
|
|
318
|
+
case 'input_audio_buffer.speech_started':
|
|
319
|
+
return this.handleInterruption();
|
|
320
|
+
case 'response.created':
|
|
321
|
+
// A response is in flight (whether server-VAD-triggered or locally triggered).
|
|
322
|
+
this.responseActive = true;
|
|
323
|
+
return;
|
|
324
|
+
case 'response.done':
|
|
325
|
+
// Emitted for every terminal status (completed, cancelled, failed) — always clears.
|
|
326
|
+
this.responseActive = false;
|
|
327
|
+
return this.handleResponseDone(event.response.usage);
|
|
328
|
+
default:
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/** Decodes a base64 audio delta and forwards it to the output handler. */
|
|
333
|
+
handleAudioDelta(deltaBase64) {
|
|
334
|
+
this.outputHandler?.(this.decodeBase64(deltaBase64));
|
|
335
|
+
}
|
|
336
|
+
/** Emits a transcript event to the transcript handler. */
|
|
337
|
+
emitTranscript(role, text, isFinal) {
|
|
338
|
+
this.transcriptHandler?.({ Role: role, Text: text, IsFinal: isFinal });
|
|
339
|
+
}
|
|
340
|
+
/** Forwards a completed function call to the tool-call handler. */
|
|
341
|
+
handleFunctionCall(callId, name, args) {
|
|
342
|
+
this.toolCallHandler?.({ CallID: callId, ToolName: name, Arguments: args });
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Notifies the interruption handler of TRUE barge-in only: user speech that cut off an
|
|
346
|
+
* ACTIVE model response. A `speech_started` while the model is idle is just the user taking
|
|
347
|
+
* their normal turn — the {@link IRealtimeSession.OnInterruption} contract explicitly excludes
|
|
348
|
+
* it, so the raw frame is gated on {@link responseActive} (the server-bridged topology's proxy
|
|
349
|
+
* for "model output in flight"). The provider cancels its own turn and emits a terminal
|
|
350
|
+
* `response.done`, which clears the flag.
|
|
351
|
+
*/
|
|
352
|
+
handleInterruption() {
|
|
353
|
+
if (!this.responseActive) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
this.interruptionHandler?.();
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Classifies an SDK connection error and forwards it to the error handler. The SDK routes
|
|
360
|
+
* BOTH kinds through its `'error'` emitter: provider `error` server frames carry a payload in
|
|
361
|
+
* `error.error` (recoverable — the session stays open, `Fatal: false`) while transport-level
|
|
362
|
+
* failures (socket error, unparseable frame, failed send) have no payload (`Fatal: true` —
|
|
363
|
+
* including the credential/token-expiry case, which surfaces as a transport teardown).
|
|
364
|
+
*/
|
|
365
|
+
handleConnectionError(error) {
|
|
366
|
+
const isProviderFrame = error.error != null;
|
|
367
|
+
this.errorHandler?.({
|
|
368
|
+
Message: error.message,
|
|
369
|
+
Code: error.error?.code ?? undefined,
|
|
370
|
+
Fatal: !isProviderFrame,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Handles the raw socket closing. A consumer-initiated {@link Close} is expected and silent;
|
|
375
|
+
* anything else (provider hangup, network drop, token death) is surfaced as a FATAL error —
|
|
376
|
+
* so consumers finalize instead of idling on a dead socket — followed by the close handler.
|
|
377
|
+
*/
|
|
378
|
+
handleSocketClose() {
|
|
379
|
+
if (this.closedByConsumer) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
this.errorHandler?.({ Message: 'OpenAI realtime connection closed unexpectedly', Fatal: true });
|
|
383
|
+
this.closeHandler?.();
|
|
384
|
+
}
|
|
385
|
+
/** Translates a response's usage block into a {@link RealtimeUsage} update. */
|
|
386
|
+
handleResponseDone(usage) {
|
|
387
|
+
if (!usage) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
this.usageHandler?.({
|
|
391
|
+
InputTokens: usage.input_tokens ?? 0,
|
|
392
|
+
OutputTokens: usage.output_tokens ?? 0,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
// ---- Config helpers ----
|
|
396
|
+
/** Sends the `session.update` that establishes instructions, input transcription, and tools. */
|
|
397
|
+
sendSessionUpdate(systemPrompt, tools, config) {
|
|
398
|
+
const session = {
|
|
399
|
+
type: 'realtime',
|
|
400
|
+
instructions: systemPrompt,
|
|
401
|
+
// Opt into USER input transcription — the same opt-in CreateClientSession applies for
|
|
402
|
+
// the client-direct topology — so user-role transcripts flow server-bridged too (the
|
|
403
|
+
// contract promises BOTH roles). The config bag spreads after this so a
|
|
404
|
+
// per-conversation override can still replace the audio block.
|
|
405
|
+
audio: { input: { transcription: { model: OPENAI_INPUT_TRANSCRIPTION_MODEL } } },
|
|
406
|
+
...config,
|
|
407
|
+
};
|
|
408
|
+
if (tools && tools.length > 0) {
|
|
409
|
+
session.tools = this.mapTools(tools);
|
|
410
|
+
}
|
|
411
|
+
this.connection.send({ type: 'session.update', session });
|
|
412
|
+
}
|
|
413
|
+
/** Seeds the conversation with initial context as a user text message. */
|
|
414
|
+
sendInitialContext(context) {
|
|
415
|
+
const item = {
|
|
416
|
+
type: 'message',
|
|
417
|
+
role: 'user',
|
|
418
|
+
content: [{ type: 'input_text', text: context }],
|
|
419
|
+
};
|
|
420
|
+
this.connection.send({ type: 'conversation.item.create', item });
|
|
421
|
+
}
|
|
422
|
+
/** Maps Core tool definitions up to OpenAI's native function-tool schema (shared mapping). */
|
|
423
|
+
mapTools(tools) {
|
|
424
|
+
return mapRealtimeTools(tools);
|
|
425
|
+
}
|
|
426
|
+
// ---- Encoding helpers ----
|
|
427
|
+
/** Encodes a raw media frame as base64 for the provider's append event. */
|
|
428
|
+
encodeBase64(chunk) {
|
|
429
|
+
return Buffer.from(chunk).toString('base64');
|
|
430
|
+
}
|
|
431
|
+
/** Decodes a base64 audio delta into a freshly-allocated `ArrayBuffer`. */
|
|
432
|
+
decodeBase64(data) {
|
|
433
|
+
const buffer = Buffer.from(data, 'base64');
|
|
434
|
+
const out = new ArrayBuffer(buffer.byteLength);
|
|
435
|
+
new Uint8Array(out).set(buffer);
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=openAIRealtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openAIRealtime.js","sourceRoot":"","sources":["../../src/models/openAIRealtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ai-openai",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.41.0",
|
|
5
5
|
"description": "MemberJunction Wrapper for OpenAI AI Models",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"typescript": "^5.9.3"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@memberjunction/ai": "5.
|
|
25
|
-
"@memberjunction/global": "5.
|
|
24
|
+
"@memberjunction/ai": "5.41.0",
|
|
25
|
+
"@memberjunction/global": "5.41.0",
|
|
26
26
|
"openai": "6.18.0"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|