@depup/openai 7.34.0-depup.0 → 7.36.0-depup.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/CHANGELOG.md +35 -0
- package/README.md +2 -2
- package/changes.json +1 -1
- package/client.d.mts +2 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +2 -2
- package/client.d.ts.map +1 -1
- package/client.js.map +1 -1
- package/client.mjs.map +1 -1
- package/internal/responses-ws-credentials.d.mts +4 -21
- package/internal/responses-ws-credentials.d.mts.map +1 -1
- package/internal/responses-ws-credentials.d.ts +4 -21
- package/internal/responses-ws-credentials.d.ts.map +1 -1
- package/internal/responses-ws-credentials.js +4 -100
- package/internal/responses-ws-credentials.js.map +1 -1
- package/internal/responses-ws-credentials.mjs +4 -100
- package/internal/responses-ws-credentials.mjs.map +1 -1
- package/internal/ws-connection-controller.d.mts +95 -0
- package/internal/ws-connection-controller.d.mts.map +1 -0
- package/internal/ws-connection-controller.d.ts +95 -0
- package/internal/ws-connection-controller.d.ts.map +1 -0
- package/internal/ws-connection-controller.js +457 -0
- package/internal/ws-connection-controller.js.map +1 -0
- package/internal/ws-connection-controller.mjs +453 -0
- package/internal/ws-connection-controller.mjs.map +1 -0
- package/internal/ws-connection.d.mts +18 -0
- package/internal/ws-connection.d.mts.map +1 -0
- package/internal/ws-connection.d.ts +18 -0
- package/internal/ws-connection.d.ts.map +1 -0
- package/internal/ws-connection.js +94 -0
- package/internal/ws-connection.js.map +1 -0
- package/internal/ws-connection.mjs +88 -0
- package/internal/ws-connection.mjs.map +1 -0
- package/internal/ws-credentials.d.mts +25 -0
- package/internal/ws-credentials.d.mts.map +1 -0
- package/internal/ws-credentials.d.ts +25 -0
- package/internal/ws-credentials.d.ts.map +1 -0
- package/internal/ws-credentials.js +109 -0
- package/internal/ws-credentials.js.map +1 -0
- package/internal/ws-credentials.mjs +105 -0
- package/internal/ws-credentials.mjs.map +1 -0
- package/lib/live/webrtc.d.mts +5 -1
- package/lib/live/webrtc.d.mts.map +1 -1
- package/lib/live/webrtc.d.ts +5 -1
- package/lib/live/webrtc.d.ts.map +1 -1
- package/lib/live/webrtc.js.map +1 -1
- package/lib/live/webrtc.mjs.map +1 -1
- package/package.json +3 -3
- package/resources/admin/organization/projects/api-keys.d.mts +28 -5
- package/resources/admin/organization/projects/api-keys.d.mts.map +1 -1
- package/resources/admin/organization/projects/api-keys.d.ts +28 -5
- package/resources/admin/organization/projects/api-keys.d.ts.map +1 -1
- package/resources/admin/organization/projects/api-keys.js +18 -3
- package/resources/admin/organization/projects/api-keys.js.map +1 -1
- package/resources/admin/organization/projects/api-keys.mjs +18 -3
- package/resources/admin/organization/projects/api-keys.mjs.map +1 -1
- package/resources/audio/speech.d.mts +2 -1
- package/resources/audio/speech.d.mts.map +1 -1
- package/resources/audio/speech.d.ts +2 -1
- package/resources/audio/speech.d.ts.map +1 -1
- package/resources/audio/voices.d.mts +47 -12
- package/resources/audio/voices.d.mts.map +1 -1
- package/resources/audio/voices.d.ts +47 -12
- package/resources/audio/voices.d.ts.map +1 -1
- package/resources/audio/voices.js +9 -9
- package/resources/audio/voices.mjs +9 -9
- package/resources/beta/realtime/realtime.d.mts +4 -0
- package/resources/beta/realtime/realtime.d.mts.map +1 -1
- package/resources/beta/realtime/realtime.d.ts +4 -0
- package/resources/beta/realtime/realtime.d.ts.map +1 -1
- package/resources/beta/realtime/realtime.js.map +1 -1
- package/resources/beta/realtime/realtime.mjs.map +1 -1
- package/resources/beta/responses/responses.d.mts +8 -0
- package/resources/beta/responses/responses.d.mts.map +1 -1
- package/resources/beta/responses/responses.d.ts +8 -0
- package/resources/beta/responses/responses.d.ts.map +1 -1
- package/resources/beta/responses/responses.js.map +1 -1
- package/resources/beta/responses/responses.mjs.map +1 -1
- package/resources/beta/responses/ws-base.d.mts +2 -24
- package/resources/beta/responses/ws-base.d.mts.map +1 -1
- package/resources/beta/responses/ws-base.d.ts +2 -24
- package/resources/beta/responses/ws-base.d.ts.map +1 -1
- package/resources/beta/responses/ws-base.js +93 -519
- package/resources/beta/responses/ws-base.js.map +1 -1
- package/resources/beta/responses/ws-base.mjs +94 -520
- package/resources/beta/responses/ws-base.mjs.map +1 -1
- package/resources/chat/completions/completions.d.mts +1 -1
- package/resources/chat/completions/completions.d.ts +1 -1
- package/resources/decisions.d.mts +68 -1
- package/resources/decisions.d.mts.map +1 -1
- package/resources/decisions.d.ts +68 -1
- package/resources/decisions.d.ts.map +1 -1
- package/resources/images.d.mts +42 -4
- package/resources/images.d.mts.map +1 -1
- package/resources/images.d.ts +42 -4
- package/resources/images.d.ts.map +1 -1
- package/resources/images.js +8 -2
- package/resources/images.js.map +1 -1
- package/resources/images.mjs +8 -2
- package/resources/images.mjs.map +1 -1
- package/resources/index.d.mts +1 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +1 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs.map +1 -1
- package/resources/live/forks/forks.d.mts +2 -2
- package/resources/live/forks/forks.d.mts.map +1 -1
- package/resources/live/forks/forks.d.ts +2 -2
- package/resources/live/forks/forks.d.ts.map +1 -1
- package/resources/live/forks/ws-base.d.mts +2 -23
- package/resources/live/forks/ws-base.d.mts.map +1 -1
- package/resources/live/forks/ws-base.d.ts +2 -23
- package/resources/live/forks/ws-base.d.ts.map +1 -1
- package/resources/live/forks/ws-base.js +84 -485
- package/resources/live/forks/ws-base.js.map +1 -1
- package/resources/live/forks/ws-base.mjs +83 -484
- package/resources/live/forks/ws-base.mjs.map +1 -1
- package/resources/live/live.d.mts +523 -29
- package/resources/live/live.d.mts.map +1 -1
- package/resources/live/live.d.ts +523 -29
- package/resources/live/live.d.ts.map +1 -1
- package/resources/live/live.js.map +1 -1
- package/resources/live/live.mjs.map +1 -1
- package/resources/live/sessions.d.mts +16 -4
- package/resources/live/sessions.d.mts.map +1 -1
- package/resources/live/sessions.d.ts +16 -4
- package/resources/live/sessions.d.ts.map +1 -1
- package/resources/live/sideband/sideband.d.mts +4 -4
- package/resources/live/sideband/sideband.d.mts.map +1 -1
- package/resources/live/sideband/sideband.d.ts +4 -4
- package/resources/live/sideband/sideband.d.ts.map +1 -1
- package/resources/live/sideband/ws-base.d.mts +2 -23
- package/resources/live/sideband/ws-base.d.mts.map +1 -1
- package/resources/live/sideband/ws-base.d.ts +2 -23
- package/resources/live/sideband/ws-base.d.ts.map +1 -1
- package/resources/live/sideband/ws-base.js +84 -485
- package/resources/live/sideband/ws-base.js.map +1 -1
- package/resources/live/sideband/ws-base.mjs +83 -484
- package/resources/live/sideband/ws-base.mjs.map +1 -1
- package/resources/live/ws-base.d.mts +2 -23
- package/resources/live/ws-base.d.mts.map +1 -1
- package/resources/live/ws-base.d.ts +2 -23
- package/resources/live/ws-base.d.ts.map +1 -1
- package/resources/live/ws-base.js +84 -485
- package/resources/live/ws-base.js.map +1 -1
- package/resources/live/ws-base.mjs +83 -484
- package/resources/live/ws-base.mjs.map +1 -1
- package/resources/realtime/realtime.d.mts +8 -2
- package/resources/realtime/realtime.d.mts.map +1 -1
- package/resources/realtime/realtime.d.ts +8 -2
- package/resources/realtime/realtime.d.ts.map +1 -1
- package/resources/realtime/realtime.js.map +1 -1
- package/resources/realtime/realtime.mjs.map +1 -1
- package/resources/responses/responses.d.mts +8 -0
- package/resources/responses/responses.d.mts.map +1 -1
- package/resources/responses/responses.d.ts +8 -0
- package/resources/responses/responses.d.ts.map +1 -1
- package/resources/responses/responses.js.map +1 -1
- package/resources/responses/responses.mjs.map +1 -1
- package/resources/responses/ws-base.d.mts +2 -24
- package/resources/responses/ws-base.d.mts.map +1 -1
- package/resources/responses/ws-base.d.ts +2 -24
- package/resources/responses/ws-base.d.ts.map +1 -1
- package/resources/responses/ws-base.js +93 -519
- package/resources/responses/ws-base.js.map +1 -1
- package/resources/responses/ws-base.mjs +94 -520
- package/resources/responses/ws-base.mjs.map +1 -1
- package/resources/shared.d.mts +7 -0
- package/resources/shared.d.mts.map +1 -1
- package/resources/shared.d.ts +7 -0
- package/resources/shared.d.ts.map +1 -1
- package/resources/videos.d.mts +8 -0
- package/resources/videos.d.mts.map +1 -1
- package/resources/videos.d.ts +8 -0
- package/resources/videos.d.ts.map +1 -1
- package/src/client.ts +2 -0
- package/src/internal/responses-ws-credentials.ts +5 -157
- package/src/internal/ws-connection-controller.ts +632 -0
- package/src/internal/ws-connection.ts +116 -0
- package/src/internal/ws-credentials.ts +165 -0
- package/src/lib/live/webrtc.ts +4 -1
- package/src/resources/admin/organization/projects/api-keys.ts +29 -5
- package/src/resources/audio/speech.ts +2 -1
- package/src/resources/audio/voices.ts +53 -12
- package/src/resources/beta/realtime/realtime.ts +5 -0
- package/src/resources/beta/responses/responses.ts +10 -0
- package/src/resources/beta/responses/ws-base.ts +106 -604
- package/src/resources/chat/completions/completions.ts +1 -1
- package/src/resources/decisions.ts +75 -0
- package/src/resources/images.ts +57 -6
- package/src/resources/index.ts +1 -0
- package/src/resources/live/api.md +12 -0
- package/src/resources/live/forks/forks.ts +9 -0
- package/src/resources/live/forks/ws-base.ts +98 -558
- package/src/resources/live/live.ts +668 -26
- package/src/resources/live/sessions.ts +19 -4
- package/src/resources/live/sideband/sideband.ts +11 -2
- package/src/resources/live/sideband/ws-base.ts +98 -562
- package/src/resources/live/ws-base.ts +98 -558
- package/src/resources/realtime/realtime.ts +9 -2
- package/src/resources/responses/responses.ts +10 -0
- package/src/resources/responses/ws-base.ts +106 -600
- package/src/resources/shared.ts +7 -0
- package/src/resources/videos.ts +10 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { OpenAIError } from '../core/error';
|
|
2
|
+
import { ReadyState } from './ws-adapter';
|
|
3
|
+
import type { WebSocketLike } from './ws-adapter';
|
|
4
|
+
import { flattenRawData } from './ws';
|
|
5
|
+
import type { RawWebSocketData, SendQueue } from './ws';
|
|
6
|
+
|
|
7
|
+
// Read the public socket on each access; callers may replace it through an accessor.
|
|
8
|
+
interface SocketOwner {
|
|
9
|
+
socket: WebSocketLike;
|
|
10
|
+
}
|
|
11
|
+
type OnError = (message: string, cause?: unknown) => void;
|
|
12
|
+
|
|
13
|
+
/** Sends or queues an application event using the existing connection state. */
|
|
14
|
+
export function sendWebSocketEvent<T>(
|
|
15
|
+
owner: SocketOwner,
|
|
16
|
+
event: T,
|
|
17
|
+
queue: SendQueue<T>,
|
|
18
|
+
isReconnecting: () => boolean,
|
|
19
|
+
onError: OnError,
|
|
20
|
+
): void {
|
|
21
|
+
if (!owner.socket) {
|
|
22
|
+
throw new OpenAIError('Internal error: failed to initialize socket. Please report this issue.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (isReconnecting() || owner.socket.readyState === ReadyState.CONNECTING) {
|
|
26
|
+
if (!queue.enqueue(event)) {
|
|
27
|
+
onError('send queue is full, message discarded');
|
|
28
|
+
}
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (owner.socket.readyState !== ReadyState.OPEN) {
|
|
32
|
+
onError('cannot send on a closed WebSocket');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
owner.socket.send(JSON.stringify(event));
|
|
37
|
+
} catch (error) {
|
|
38
|
+
onError('could not send data', error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Sends or snapshots a raw frame using the same admission rules as application events. */
|
|
43
|
+
export function sendRawWebSocketData<T>(
|
|
44
|
+
owner: SocketOwner,
|
|
45
|
+
data: RawWebSocketData,
|
|
46
|
+
queue: SendQueue<T>,
|
|
47
|
+
isReconnecting: () => boolean,
|
|
48
|
+
onError: OnError,
|
|
49
|
+
): void {
|
|
50
|
+
if (!owner.socket) {
|
|
51
|
+
throw new OpenAIError('Internal error: failed to initialize socket. Please report this issue.');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isReconnecting() || owner.socket.readyState === ReadyState.CONNECTING) {
|
|
55
|
+
if (!queue.enqueueRaw(data)) {
|
|
56
|
+
onError('send queue is full, message discarded');
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (owner.socket.readyState !== ReadyState.OPEN) {
|
|
61
|
+
onError('cannot send on a closed WebSocket');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
owner.socket.send(flattenRawData(data));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
onError('could not send data', error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Flushes queued frames with the caller's existing failed-send policy. */
|
|
72
|
+
export function flushWebSocketSendQueue<T>(
|
|
73
|
+
owner: SocketOwner,
|
|
74
|
+
queue: SendQueue<T>,
|
|
75
|
+
onError: OnError,
|
|
76
|
+
options?: { requeueFailed?: boolean },
|
|
77
|
+
): void {
|
|
78
|
+
if (!owner.socket) {
|
|
79
|
+
throw new OpenAIError('Internal error: failed to initialize socket. Please report this issue.');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
queue.flush((data) => owner.socket.send(flattenRawData(data)), options);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
onError('could not send queued data', error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Resolves when the socket opens, or rejects if it errors or closes first. */
|
|
90
|
+
export function waitForWebSocketOpen(socket: WebSocketLike): Promise<void> {
|
|
91
|
+
// oxlint-disable-next-line promise/avoid-new -- Convert the existing socket event callbacks into the connection attempt's promise.
|
|
92
|
+
return new Promise<void>((resolve, reject) => {
|
|
93
|
+
/* oxlint-disable eslint/no-use-before-define -- All mutually dependent callbacks are initialized before socket listeners are registered. */
|
|
94
|
+
const cleanup = () => {
|
|
95
|
+
socket.off('open', onOpen);
|
|
96
|
+
socket.off('error', onError);
|
|
97
|
+
socket.off('close', onFail);
|
|
98
|
+
};
|
|
99
|
+
/* oxlint-enable eslint/no-use-before-define */
|
|
100
|
+
const onOpen = () => {
|
|
101
|
+
cleanup();
|
|
102
|
+
resolve();
|
|
103
|
+
};
|
|
104
|
+
const onError = (error: Error) => {
|
|
105
|
+
cleanup();
|
|
106
|
+
reject(error);
|
|
107
|
+
};
|
|
108
|
+
const onFail = () => {
|
|
109
|
+
cleanup();
|
|
110
|
+
reject(new Error('socket closed before open'));
|
|
111
|
+
};
|
|
112
|
+
socket.once('open', onOpen);
|
|
113
|
+
socket.once('error', onError);
|
|
114
|
+
socket.once('close', onFail);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { OpenAIError } from '../core/error';
|
|
2
|
+
import type { OpenAI } from '../client';
|
|
3
|
+
import { resolveRealtimeAPIKey } from './realtime-credentials';
|
|
4
|
+
import {
|
|
5
|
+
buildWebSocketOptions,
|
|
6
|
+
mergeWebSocketAuthHeaders,
|
|
7
|
+
snapshotWebSocketCredentials,
|
|
8
|
+
WEBSOCKET_METADATA_HEADERS,
|
|
9
|
+
} from './ws';
|
|
10
|
+
import type { CredentialedWebSocketOptions } from './ws';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Keep caller credential admission distinct from the hook's final provider-key transform.
|
|
14
|
+
* The latter reuses captured base headers so no caller getters are reread after the refresh.
|
|
15
|
+
*/
|
|
16
|
+
function buildCredentialedWebSocketOptions<Options extends CredentialedWebSocketOptions>(
|
|
17
|
+
client: OpenAI,
|
|
18
|
+
authHeaders: Record<string, string>,
|
|
19
|
+
options: Options | null | undefined,
|
|
20
|
+
prepared?: {
|
|
21
|
+
options: ReturnType<typeof buildWebSocketOptions>;
|
|
22
|
+
removedHeaders: Set<string>;
|
|
23
|
+
apiKey?: string | null | undefined;
|
|
24
|
+
},
|
|
25
|
+
) {
|
|
26
|
+
if (prepared) {
|
|
27
|
+
return prepared.apiKey === undefined
|
|
28
|
+
? mergeWebSocketAuthHeaders(prepared.options, authHeaders, prepared.removedHeaders)
|
|
29
|
+
: buildWebSocketOptions(client, authHeaders, prepared.options, prepared.removedHeaders, true);
|
|
30
|
+
}
|
|
31
|
+
if (!client._hasApiKeyProvider()) {
|
|
32
|
+
return buildWebSocketOptions(client, authHeaders, options);
|
|
33
|
+
}
|
|
34
|
+
const removedHeaders = new Set<string>();
|
|
35
|
+
const provided = buildWebSocketOptions(client, {}, options, removedHeaders);
|
|
36
|
+
return snapshotWebSocketCredentials(provided, WEBSOCKET_METADATA_HEADERS)
|
|
37
|
+
? provided
|
|
38
|
+
: buildWebSocketOptions(client, authHeaders, provided, removedHeaders, true);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Classify reconnect credentials without treating the previous SDK key as a caller override.
|
|
43
|
+
* Capture routing and caller options before any asynchronous key refresh.
|
|
44
|
+
*/
|
|
45
|
+
function prepareWebSocketReconnect<Options extends CredentialedWebSocketOptions>(
|
|
46
|
+
client: OpenAI,
|
|
47
|
+
socketOptions: Options | null | undefined,
|
|
48
|
+
initialAuthUsedAPIKey: boolean,
|
|
49
|
+
) {
|
|
50
|
+
const removedHeaders = new Set<string>();
|
|
51
|
+
const options = buildWebSocketOptions(client, {}, socketOptions, removedHeaders);
|
|
52
|
+
let authentication: 'provided' | 'cached' | 'refresh';
|
|
53
|
+
if (snapshotWebSocketCredentials(options, WEBSOCKET_METADATA_HEADERS)) {
|
|
54
|
+
authentication = 'provided';
|
|
55
|
+
} else if (
|
|
56
|
+
removedHeaders.has('authorization') ||
|
|
57
|
+
options.headers?.['authorization'] !== undefined ||
|
|
58
|
+
!initialAuthUsedAPIKey
|
|
59
|
+
) {
|
|
60
|
+
authentication = 'cached';
|
|
61
|
+
} else {
|
|
62
|
+
authentication = 'refresh';
|
|
63
|
+
}
|
|
64
|
+
return { options, removedHeaders, authentication };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Per-connection credential snapshots shared by Node WebSocket bindings. */
|
|
68
|
+
export class WebSocketCredentials {
|
|
69
|
+
private readonly connectionName: string;
|
|
70
|
+
|
|
71
|
+
constructor(connectionName: string) {
|
|
72
|
+
this.connectionName = connectionName;
|
|
73
|
+
}
|
|
74
|
+
private initialAuthUsedAPIKey = false;
|
|
75
|
+
private initialAPIKey: string | undefined;
|
|
76
|
+
private prepared:
|
|
77
|
+
| {
|
|
78
|
+
options: ReturnType<typeof buildWebSocketOptions>;
|
|
79
|
+
removedHeaders: Set<string>;
|
|
80
|
+
apiKey?: string | null | undefined;
|
|
81
|
+
}
|
|
82
|
+
| undefined;
|
|
83
|
+
|
|
84
|
+
get preparedAPIKey(): string | null | undefined {
|
|
85
|
+
return this.prepared?.apiKey;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
trackInitialHeaders(client: OpenAI, headers: Record<string, string>, hasSocket: () => boolean): void {
|
|
89
|
+
if (!hasSocket() && client._hasApiKeyProvider()) {
|
|
90
|
+
this.initialAPIKey = headers['Authorization']?.slice('Bearer '.length);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
usesAPIKey(client: OpenAI, headers: Record<string, string>): boolean {
|
|
95
|
+
// Hooks can read the SDK key without delegating. Only use an ordinary cached property here:
|
|
96
|
+
// invoking custom/Bedrock getters could validate credentials a caller-owned socket never sends.
|
|
97
|
+
const apiKey =
|
|
98
|
+
this.initialAPIKey ??
|
|
99
|
+
(client._hasApiKeyProvider() ? Object.getOwnPropertyDescriptor(client, 'apiKey')?.value : undefined);
|
|
100
|
+
if (!apiKey) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
// Metadata containing a copy of a credential does not make it the socket's authentication.
|
|
104
|
+
return snapshotWebSocketCredentials(
|
|
105
|
+
{
|
|
106
|
+
headers: Object.fromEntries(
|
|
107
|
+
Object.entries(headers).map(([name, value]) => [name, value?.includes(apiKey) ? value : '']),
|
|
108
|
+
),
|
|
109
|
+
},
|
|
110
|
+
WEBSOCKET_METADATA_HEADERS,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
build<Options extends CredentialedWebSocketOptions>(
|
|
115
|
+
client: OpenAI,
|
|
116
|
+
authHeaders: Record<string, string>,
|
|
117
|
+
options: Options | null | undefined,
|
|
118
|
+
initialAuthUsedAPIKey?: boolean,
|
|
119
|
+
) {
|
|
120
|
+
if (initialAuthUsedAPIKey !== undefined) {
|
|
121
|
+
this.initialAuthUsedAPIKey = initialAuthUsedAPIKey;
|
|
122
|
+
this.initialAPIKey = undefined;
|
|
123
|
+
}
|
|
124
|
+
const socketOptions = buildCredentialedWebSocketOptions(client, authHeaders, options, this.prepared);
|
|
125
|
+
if (
|
|
126
|
+
client._hasApiKeyProvider() &&
|
|
127
|
+
!authHeaders['Authorization'] &&
|
|
128
|
+
!snapshotWebSocketCredentials(socketOptions, WEBSOCKET_METADATA_HEADERS)
|
|
129
|
+
) {
|
|
130
|
+
throw new OpenAIError(
|
|
131
|
+
`Cannot open a ${this.connectionName} WebSocket with an unresolved function-based apiKey. Resolve it before constructing the WebSocket or provide explicit WebSocket credentials.`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return socketOptions;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async prepare<Socket, Options extends CredentialedWebSocketOptions>(
|
|
138
|
+
client: OpenAI,
|
|
139
|
+
socketOptions: Options | null | undefined,
|
|
140
|
+
authHeaders: (apiKey?: string | null) => Record<string, string>,
|
|
141
|
+
createSocket: (url: URL, headers: Record<string, string>) => Socket,
|
|
142
|
+
): Promise<(url: URL) => Socket> {
|
|
143
|
+
const { options, removedHeaders, authentication } = prepareWebSocketReconnect(
|
|
144
|
+
client,
|
|
145
|
+
socketOptions,
|
|
146
|
+
this.initialAuthUsedAPIKey,
|
|
147
|
+
);
|
|
148
|
+
const createPreparedSocket = (url: URL, headers: Record<string, string>, apiKey?: string | null) => {
|
|
149
|
+
const previous = this.prepared;
|
|
150
|
+
this.prepared = { options, removedHeaders, apiKey };
|
|
151
|
+
try {
|
|
152
|
+
// Resolve headers inside the scope so legacy zero-argument overrides see this attempt's key.
|
|
153
|
+
return createSocket(url, apiKey === undefined ? headers : authHeaders(apiKey));
|
|
154
|
+
} finally {
|
|
155
|
+
this.prepared = previous;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
if (authentication !== 'refresh') {
|
|
159
|
+
const headers = authentication === 'provided' ? {} : authHeaders();
|
|
160
|
+
return (url) => createPreparedSocket(url, headers);
|
|
161
|
+
}
|
|
162
|
+
const { commit } = await resolveRealtimeAPIKey(client, true);
|
|
163
|
+
return (url) => createPreparedSocket(url, {}, commit());
|
|
164
|
+
}
|
|
165
|
+
}
|
package/src/lib/live/webrtc.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* oxlint-disable max-classes-per-file -- Both thin facades belong to the same public Live WebRTC entrypoint. */
|
|
2
2
|
import type {
|
|
3
|
-
ConnectClientEvent
|
|
3
|
+
ConnectClientEvent,
|
|
4
4
|
ConnectServerEvent as ServerEvent,
|
|
5
5
|
} from '../../resources/live/sideband/sideband';
|
|
6
6
|
import { WebRTCConnection } from '../webrtc/connection';
|
|
@@ -16,6 +16,9 @@ export type {
|
|
|
16
16
|
WebRTCState,
|
|
17
17
|
} from '../webrtc/types';
|
|
18
18
|
|
|
19
|
+
/** Fixture playback requires a primary WebSocket or server sideband. */
|
|
20
|
+
type ClientEvent = Exclude<ConnectClientEvent, { type: 'session.output_audio.fixture.play' }>;
|
|
21
|
+
|
|
19
22
|
/** Browser Live connection with application-owned SDP exchange and typed server-event subscriptions. */
|
|
20
23
|
export class OpenAILiveWebRTC extends WebRTCConnection<ClientEvent, ServerEvent> {}
|
|
21
24
|
|
|
@@ -153,8 +153,20 @@ export class APIKeys extends APIResource {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
|
-
* Updates the expiration of an existing API key in the project,
|
|
157
|
-
* service-account-owned key. Requires permission to write project API
|
|
156
|
+
* Updates the scopes and/or expiration of an existing API key in the project,
|
|
157
|
+
* including a service-account-owned key. Requires permission to write project API
|
|
158
|
+
* keys.
|
|
159
|
+
*
|
|
160
|
+
* Provide at least one of `scopes` or `expires_in_seconds`. Omitted fields stay
|
|
161
|
+
* unchanged; neither field accepts `null`. Both changes are saved together.
|
|
162
|
+
*
|
|
163
|
+
* `scopes` replaces the key's scope restrictions using the same scope identifiers
|
|
164
|
+
* as the dashboard. An empty array means All permissions, subject to the owner's
|
|
165
|
+
* effective access; it does not mean no access. Use `["api.all.read"]` for
|
|
166
|
+
* read-only access or specific scopes such as `["api.files.read"]` for restricted
|
|
167
|
+
* access. This does not change user or service-account roles or grant admin
|
|
168
|
+
* permissions. Scope changes follow the same authentication-cache propagation as
|
|
169
|
+
* dashboard edits.
|
|
158
170
|
*
|
|
159
171
|
* Provide `expires_in_seconds` to set the expiration relative to this request. The
|
|
160
172
|
* value must satisfy the organization's and project's expiry policies. Expired
|
|
@@ -166,7 +178,10 @@ export class APIKeys extends APIResource {
|
|
|
166
178
|
* const projectAPIKey =
|
|
167
179
|
* await client.admin.organization.projects.apiKeys.update(
|
|
168
180
|
* 'api_key_id',
|
|
169
|
-
* {
|
|
181
|
+
* {
|
|
182
|
+
* project_id: 'project_id',
|
|
183
|
+
* scopes: ['api.all.read'],
|
|
184
|
+
* },
|
|
170
185
|
* );
|
|
171
186
|
* ```
|
|
172
187
|
*/
|
|
@@ -486,9 +501,18 @@ export interface APIKeyUpdateParams {
|
|
|
486
501
|
/**
|
|
487
502
|
* Body param: Number of seconds from this request until the API key expires. Must
|
|
488
503
|
* comply with the organization and project expiry policies. Expired keys cannot be
|
|
489
|
-
* updated. Retrying resets the expiry relative to the new request.
|
|
504
|
+
* updated. Retrying resets the expiry relative to the new request. Omit to keep
|
|
505
|
+
* the current expiration.
|
|
506
|
+
*/
|
|
507
|
+
expires_in_seconds?: number;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Body param: Replace the API key scope restrictions. Omit to leave scopes
|
|
511
|
+
* unchanged. An empty array removes key restrictions (All permissions), subject to
|
|
512
|
+
* the owner's effective permissions. Use ["api.all.read"] for read-only access.
|
|
513
|
+
* Scopes do not change the owner's roles or grant administrative permissions.
|
|
490
514
|
*/
|
|
491
|
-
|
|
515
|
+
scopes?: Array<string>;
|
|
492
516
|
}
|
|
493
517
|
|
|
494
518
|
export interface APIKeyListParams extends ConversationCursorPageParams {
|
|
@@ -69,7 +69,8 @@ export interface SpeechCreateParams {
|
|
|
69
69
|
* object with an `id`, for example `{ "id": "voice_1234" }`. Previews of the
|
|
70
70
|
* voices are available in the
|
|
71
71
|
* [Text to speech guide](https://developers.openai.com/api/docs/guides/text-to-speech#voice-options).
|
|
72
|
-
* Custom voices must be created from audio samples.
|
|
72
|
+
* Custom voices must be created from audio samples. Voices created from text
|
|
73
|
+
* prompts are supported only in Live.
|
|
73
74
|
*/
|
|
74
75
|
voice:
|
|
75
76
|
| string
|
|
@@ -18,17 +18,17 @@ function resolveResourceRequestOptions(
|
|
|
18
18
|
*/
|
|
19
19
|
export class Voices extends APIResource {
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* previously uploaded consent recording.
|
|
21
|
+
* Creates a voice from a text prompt or from a consent recording and an audio
|
|
22
|
+
* sample.
|
|
24
23
|
*
|
|
25
|
-
*
|
|
26
|
-
* data.
|
|
24
|
+
* For prompt-based creation, send `type: "prompt"` with a `name` and `prompt` as
|
|
25
|
+
* JSON or multipart form data. For creation from an audio sample, send
|
|
26
|
+
* `type: "audio_sample"` with a `name`, `audio_sample`, and `consent` recording ID
|
|
27
|
+
* as multipart form data. The type defaults to `audio_sample` when omitted.
|
|
27
28
|
*
|
|
28
|
-
* Returns the saved voice's metadata.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* customers.
|
|
29
|
+
* Returns the saved voice's metadata. Voices created from text prompts are
|
|
30
|
+
* supported only in Live, not in Realtime or the speech endpoint. The response
|
|
31
|
+
* does not include preview audio.
|
|
32
32
|
*
|
|
33
33
|
* @example
|
|
34
34
|
* ```ts
|
|
@@ -50,7 +50,8 @@ export class Voices extends APIResource {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* A custom voice that can be used for audio output.
|
|
53
|
+
* A custom voice that can be used for audio output. Voices created from text
|
|
54
|
+
* prompts are supported only in Live.
|
|
54
55
|
*/
|
|
55
56
|
export interface Voice {
|
|
56
57
|
/**
|
|
@@ -76,10 +77,17 @@ export interface Voice {
|
|
|
76
77
|
/**
|
|
77
78
|
* How the voice was created.
|
|
78
79
|
*/
|
|
79
|
-
type: 'audio_sample';
|
|
80
|
+
type: 'audio_sample' | 'prompt';
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The original text prompt used to create the voice. Present for prompt-generated
|
|
84
|
+
* voices with a stored prompt; omitted for audio-sample voices and older voices
|
|
85
|
+
* without a stored prompt.
|
|
86
|
+
*/
|
|
87
|
+
prompt?: string;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
|
-
export type VoiceCreateParams = VoiceCreateParams.Consent;
|
|
90
|
+
export type VoiceCreateParams = VoiceCreateParams.Consent | VoiceCreateParams.Prompt;
|
|
83
91
|
|
|
84
92
|
export declare namespace VoiceCreateParams {
|
|
85
93
|
/**
|
|
@@ -110,6 +118,39 @@ export declare namespace VoiceCreateParams {
|
|
|
110
118
|
*/
|
|
111
119
|
type?: 'audio_sample';
|
|
112
120
|
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Creates a synthetic voice from a text description. Supports application/json or
|
|
124
|
+
* multipart/form-data.
|
|
125
|
+
*/
|
|
126
|
+
export interface Prompt {
|
|
127
|
+
/**
|
|
128
|
+
* The name of the new voice.
|
|
129
|
+
*/
|
|
130
|
+
name: string;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A description of the desired voice. Must not contain only whitespace.
|
|
134
|
+
*/
|
|
135
|
+
prompt: string;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set to `prompt` to create a voice from a text description.
|
|
139
|
+
*/
|
|
140
|
+
type: 'prompt';
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The voice creation model to use. Defaults to `auto`.
|
|
144
|
+
*/
|
|
145
|
+
model?: string | 'auto' | '2026-10-08';
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Optional text for the voice to speak during creation. If omitted, a script is
|
|
149
|
+
* generated from the prompt. Must not be blank after trimming whitespace; scripts
|
|
150
|
+
* that are too short are rejected.
|
|
151
|
+
*/
|
|
152
|
+
script_hint?: string;
|
|
153
|
+
}
|
|
113
154
|
}
|
|
114
155
|
|
|
115
156
|
export declare namespace Voices {
|
|
@@ -3706,6 +3706,16 @@ export interface BetaResponseError {
|
|
|
3706
3706
|
message: string;
|
|
3707
3707
|
|
|
3708
3708
|
misalignment?: BetaResponseError.Misalignment;
|
|
3709
|
+
|
|
3710
|
+
/**
|
|
3711
|
+
* The request parameter associated with the error, or null if none was recorded.
|
|
3712
|
+
*/
|
|
3713
|
+
param?: string | null;
|
|
3714
|
+
|
|
3715
|
+
/**
|
|
3716
|
+
* The original error type, or null if it was not recorded.
|
|
3717
|
+
*/
|
|
3718
|
+
type?: string | null;
|
|
3709
3719
|
}
|
|
3710
3720
|
|
|
3711
3721
|
export namespace BetaResponseError {
|