@memberjunction/ai-openai 5.40.1 → 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 CHANGED
@@ -3,4 +3,5 @@ export * from './models/openAIEmbedding.js';
3
3
  export * from './models/embeddingModels.types.js';
4
4
  export * from './models/tts.js';
5
5
  export * from './models/openAIImage.js';
6
+ export * from './models/openAIRealtime.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -3,4 +3,5 @@ export * from './models/openAIEmbedding.js';
3
3
  export * from './models/embeddingModels.types.js';
4
4
  export * from './models/tts.js';
5
5
  export * from './models/openAIImage.js';
6
+ export * from './models/openAIRealtime.js';
6
7
  //# sourceMappingURL=index.js.map
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.40.1",
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.40.1",
25
- "@memberjunction/global": "5.40.1",
24
+ "@memberjunction/ai": "5.41.0",
25
+ "@memberjunction/global": "5.41.0",
26
26
  "openai": "6.18.0"
27
27
  },
28
28
  "repository": {