openai 7.25.0 → 7.26.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 +31 -0
- package/client.d.mts +5 -6
- package/client.d.mts.map +1 -1
- package/client.d.ts +5 -6
- package/client.d.ts.map +1 -1
- package/client.js +38 -10
- package/client.js.map +1 -1
- package/client.mjs +39 -11
- package/client.mjs.map +1 -1
- package/core/streaming.d.mts +4 -0
- package/core/streaming.d.mts.map +1 -1
- package/core/streaming.d.ts +4 -0
- package/core/streaming.d.ts.map +1 -1
- package/core/streaming.js +6 -0
- package/core/streaming.js.map +1 -1
- package/core/streaming.mjs +6 -0
- package/core/streaming.mjs.map +1 -1
- package/helpers/beta/agents/standard-schema.d.mts +7 -0
- package/helpers/beta/agents/standard-schema.d.mts.map +1 -0
- package/helpers/beta/agents/standard-schema.d.ts +7 -0
- package/helpers/beta/agents/standard-schema.d.ts.map +1 -0
- package/helpers/beta/agents/standard-schema.js +12 -0
- package/helpers/beta/agents/standard-schema.js.map +1 -0
- package/helpers/beta/agents/standard-schema.mjs +9 -0
- package/helpers/beta/agents/standard-schema.mjs.map +1 -0
- package/helpers/beta/agents/zod.d.mts +10 -0
- package/helpers/beta/agents/zod.d.mts.map +1 -0
- package/helpers/beta/agents/zod.d.ts +10 -0
- package/helpers/beta/agents/zod.d.ts.map +1 -0
- package/helpers/beta/agents/zod.js +12 -0
- package/helpers/beta/agents/zod.js.map +1 -0
- package/helpers/beta/agents/zod.mjs +9 -0
- package/helpers/beta/agents/zod.mjs.map +1 -0
- package/internal/realtime-credentials.d.mts +22 -1
- package/internal/realtime-credentials.d.mts.map +1 -1
- package/internal/realtime-credentials.d.ts +22 -1
- package/internal/realtime-credentials.d.ts.map +1 -1
- package/internal/realtime-credentials.js +48 -4
- package/internal/realtime-credentials.js.map +1 -1
- package/internal/realtime-credentials.mjs +45 -4
- package/internal/realtime-credentials.mjs.map +1 -1
- package/internal/responses-ws-credentials.d.mts +23 -0
- package/internal/responses-ws-credentials.d.mts.map +1 -0
- package/internal/responses-ws-credentials.d.ts +23 -0
- package/internal/responses-ws-credentials.d.ts.map +1 -0
- package/internal/responses-ws-credentials.js +108 -0
- package/internal/responses-ws-credentials.js.map +1 -0
- package/internal/responses-ws-credentials.mjs +104 -0
- package/internal/responses-ws-credentials.mjs.map +1 -0
- package/internal/ws-adapter-node.d.mts +4 -0
- package/internal/ws-adapter-node.d.mts.map +1 -1
- package/internal/ws-adapter-node.d.ts +4 -0
- package/internal/ws-adapter-node.d.ts.map +1 -1
- package/internal/ws-adapter-node.js +56 -0
- package/internal/ws-adapter-node.js.map +1 -1
- package/internal/ws-adapter-node.mjs +55 -0
- package/internal/ws-adapter-node.mjs.map +1 -1
- package/internal/ws.d.mts +27 -4
- package/internal/ws.d.mts.map +1 -1
- package/internal/ws.d.ts +27 -4
- package/internal/ws.d.ts.map +1 -1
- package/internal/ws.js +105 -5
- package/internal/ws.js.map +1 -1
- package/internal/ws.mjs +102 -4
- package/internal/ws.mjs.map +1 -1
- package/lib/agents/agent-session-stream.d.mts +13 -4
- package/lib/agents/agent-session-stream.d.mts.map +1 -1
- package/lib/agents/agent-session-stream.d.ts +13 -4
- package/lib/agents/agent-session-stream.d.ts.map +1 -1
- package/lib/agents/agent-session-stream.js +24 -21
- package/lib/agents/agent-session-stream.js.map +1 -1
- package/lib/agents/agent-session-stream.mjs +24 -21
- package/lib/agents/agent-session-stream.mjs.map +1 -1
- package/lib/beta/agents/agent-session-create-stream.d.mts +15 -0
- package/lib/beta/agents/agent-session-create-stream.d.mts.map +1 -0
- package/lib/beta/agents/agent-session-create-stream.d.ts +15 -0
- package/lib/beta/agents/agent-session-create-stream.d.ts.map +1 -0
- package/lib/beta/agents/agent-session-create-stream.js +25 -0
- package/lib/beta/agents/agent-session-create-stream.js.map +1 -0
- package/lib/beta/agents/agent-session-create-stream.mjs +22 -0
- package/lib/beta/agents/agent-session-create-stream.mjs.map +1 -0
- package/lib/beta/agents/agent-turn-result-collector.d.mts +17 -0
- package/lib/beta/agents/agent-turn-result-collector.d.mts.map +1 -0
- package/lib/beta/agents/agent-turn-result-collector.d.ts +17 -0
- package/lib/beta/agents/agent-turn-result-collector.d.ts.map +1 -0
- package/lib/beta/agents/agent-turn-result-collector.js +99 -0
- package/lib/beta/agents/agent-turn-result-collector.js.map +1 -0
- package/lib/beta/agents/agent-turn-result-collector.mjs +95 -0
- package/lib/beta/agents/agent-turn-result-collector.mjs.map +1 -0
- package/lib/beta/agents/agent-turn-result-error.d.mts +16 -0
- package/lib/beta/agents/agent-turn-result-error.d.mts.map +1 -0
- package/lib/beta/agents/agent-turn-result-error.d.ts +16 -0
- package/lib/beta/agents/agent-turn-result-error.d.ts.map +1 -0
- package/lib/beta/agents/agent-turn-result-error.js +22 -0
- package/lib/beta/agents/agent-turn-result-error.js.map +1 -0
- package/lib/beta/agents/agent-turn-result-error.mjs +18 -0
- package/lib/beta/agents/agent-turn-result-error.mjs.map +1 -0
- package/lib/beta/agents/agent-turn-result.d.mts +12 -0
- package/lib/beta/agents/agent-turn-result.d.mts.map +1 -0
- package/lib/beta/agents/agent-turn-result.d.ts +12 -0
- package/lib/beta/agents/agent-turn-result.d.ts.map +1 -0
- package/lib/beta/agents/agent-turn-result.js +22 -0
- package/lib/beta/agents/agent-turn-result.js.map +1 -0
- package/lib/beta/agents/agent-turn-result.mjs +18 -0
- package/lib/beta/agents/agent-turn-result.mjs.map +1 -0
- package/lib/beta/agents/function-tool.d.mts +27 -0
- package/lib/beta/agents/function-tool.d.mts.map +1 -0
- package/lib/beta/agents/function-tool.d.ts +27 -0
- package/lib/beta/agents/function-tool.d.ts.map +1 -0
- package/lib/beta/agents/function-tool.js +48 -0
- package/lib/beta/agents/function-tool.js.map +1 -0
- package/lib/beta/agents/function-tool.mjs +45 -0
- package/lib/beta/agents/function-tool.mjs.map +1 -0
- package/lib/beta/agents/output-format-types.d.mts +11 -0
- package/lib/beta/agents/output-format-types.d.mts.map +1 -0
- package/lib/beta/agents/output-format-types.d.ts +11 -0
- package/lib/beta/agents/output-format-types.d.ts.map +1 -0
- package/lib/beta/agents/output-format-types.js +3 -0
- package/lib/beta/agents/output-format-types.js.map +1 -0
- package/lib/beta/agents/output-format-types.mjs +2 -0
- package/lib/beta/agents/output-format-types.mjs.map +1 -0
- package/lib/beta/agents/output-format.d.mts +8 -0
- package/lib/beta/agents/output-format.d.mts.map +1 -0
- package/lib/beta/agents/output-format.d.ts +8 -0
- package/lib/beta/agents/output-format.d.ts.map +1 -0
- package/lib/beta/agents/output-format.js +20 -0
- package/lib/beta/agents/output-format.js.map +1 -0
- package/lib/beta/agents/output-format.mjs +14 -0
- package/lib/beta/agents/output-format.mjs.map +1 -0
- package/lib/beta/agents/output-parse-error.d.mts +11 -0
- package/lib/beta/agents/output-parse-error.d.mts.map +1 -0
- package/lib/beta/agents/output-parse-error.d.ts +11 -0
- package/lib/beta/agents/output-parse-error.d.ts.map +1 -0
- package/lib/beta/agents/output-parse-error.js +22 -0
- package/lib/beta/agents/output-parse-error.js.map +1 -0
- package/lib/beta/agents/output-parse-error.mjs +18 -0
- package/lib/beta/agents/output-parse-error.mjs.map +1 -0
- package/lib/beta/agents/parse-result.d.mts +95 -0
- package/lib/beta/agents/parse-result.d.mts.map +1 -0
- package/lib/beta/agents/parse-result.d.ts +95 -0
- package/lib/beta/agents/parse-result.d.ts.map +1 -0
- package/lib/beta/agents/parse-result.js +116 -0
- package/lib/beta/agents/parse-result.js.map +1 -0
- package/lib/beta/agents/parse-result.mjs +110 -0
- package/lib/beta/agents/parse-result.mjs.map +1 -0
- package/lib/beta/agents/parsed-agent-turn-result.d.mts +8 -0
- package/lib/beta/agents/parsed-agent-turn-result.d.mts.map +1 -0
- package/lib/beta/agents/parsed-agent-turn-result.d.ts +8 -0
- package/lib/beta/agents/parsed-agent-turn-result.d.ts.map +1 -0
- package/lib/beta/agents/parsed-agent-turn-result.js +14 -0
- package/lib/beta/agents/parsed-agent-turn-result.js.map +1 -0
- package/lib/beta/agents/parsed-agent-turn-result.mjs +10 -0
- package/lib/beta/agents/parsed-agent-turn-result.mjs.map +1 -0
- package/lib/beta/agents/result-collection.d.mts +15 -0
- package/lib/beta/agents/result-collection.d.mts.map +1 -0
- package/lib/beta/agents/result-collection.d.ts +15 -0
- package/lib/beta/agents/result-collection.d.ts.map +1 -0
- package/lib/beta/agents/result-collection.js +110 -0
- package/lib/beta/agents/result-collection.js.map +1 -0
- package/lib/beta/agents/result-collection.mjs +106 -0
- package/lib/beta/agents/result-collection.mjs.map +1 -0
- package/lib/beta/agents/tool-output.d.mts +7 -0
- package/lib/beta/agents/tool-output.d.mts.map +1 -0
- package/lib/beta/agents/tool-output.d.ts +7 -0
- package/lib/beta/agents/tool-output.d.ts.map +1 -0
- package/lib/beta/agents/tool-output.js +26 -0
- package/lib/beta/agents/tool-output.js.map +1 -0
- package/lib/beta/agents/tool-output.mjs +23 -0
- package/lib/beta/agents/tool-output.mjs.map +1 -0
- package/lib/responses/responses-websocket-session.d.mts +1 -1
- package/lib/responses/responses-websocket-session.d.mts.map +1 -1
- package/lib/responses/responses-websocket-session.d.ts +1 -1
- package/lib/responses/responses-websocket-session.d.ts.map +1 -1
- package/lib/responses/responses-websocket-session.js +12 -2
- package/lib/responses/responses-websocket-session.js.map +1 -1
- package/lib/responses/responses-websocket-session.mjs +12 -2
- package/lib/responses/responses-websocket-session.mjs.map +1 -1
- package/package.json +1 -1
- package/resources/beta/agents/agents.d.mts +9 -0
- package/resources/beta/agents/agents.d.mts.map +1 -1
- package/resources/beta/agents/agents.d.ts +9 -0
- package/resources/beta/agents/agents.d.ts.map +1 -1
- package/resources/beta/agents/agents.js.map +1 -1
- package/resources/beta/agents/agents.mjs.map +1 -1
- package/resources/beta/agents/sessions/events.d.mts +6 -5
- package/resources/beta/agents/sessions/events.d.mts.map +1 -1
- package/resources/beta/agents/sessions/events.d.ts +6 -5
- package/resources/beta/agents/sessions/events.d.ts.map +1 -1
- package/resources/beta/agents/sessions/events.js +6 -5
- package/resources/beta/agents/sessions/events.js.map +1 -1
- package/resources/beta/agents/sessions/events.mjs +6 -5
- package/resources/beta/agents/sessions/events.mjs.map +1 -1
- package/resources/beta/agents/sessions/index.d.mts +1 -0
- package/resources/beta/agents/sessions/index.d.mts.map +1 -1
- package/resources/beta/agents/sessions/index.d.ts +1 -0
- package/resources/beta/agents/sessions/index.d.ts.map +1 -1
- package/resources/beta/agents/sessions/index.js +3 -1
- package/resources/beta/agents/sessions/index.js.map +1 -1
- package/resources/beta/agents/sessions/index.mjs +1 -0
- package/resources/beta/agents/sessions/index.mjs.map +1 -1
- package/resources/beta/agents/sessions/sessions.d.mts +16 -4
- package/resources/beta/agents/sessions/sessions.d.mts.map +1 -1
- package/resources/beta/agents/sessions/sessions.d.ts +16 -4
- package/resources/beta/agents/sessions/sessions.d.ts.map +1 -1
- package/resources/beta/agents/sessions/sessions.js +17 -4
- package/resources/beta/agents/sessions/sessions.js.map +1 -1
- package/resources/beta/agents/sessions/sessions.mjs +17 -4
- package/resources/beta/agents/sessions/sessions.mjs.map +1 -1
- package/resources/beta/agents/sessions/traces.d.mts +68 -0
- package/resources/beta/agents/sessions/traces.d.mts.map +1 -0
- package/resources/beta/agents/sessions/traces.d.ts +68 -0
- package/resources/beta/agents/sessions/traces.d.ts.map +1 -0
- package/resources/beta/agents/sessions/traces.js +81 -0
- package/resources/beta/agents/sessions/traces.js.map +1 -0
- package/resources/beta/agents/sessions/traces.mjs +77 -0
- package/resources/beta/agents/sessions/traces.mjs.map +1 -0
- package/resources/beta/responses/ws-base.d.mts +3 -1
- package/resources/beta/responses/ws-base.d.mts.map +1 -1
- package/resources/beta/responses/ws-base.d.ts +3 -1
- package/resources/beta/responses/ws-base.d.ts.map +1 -1
- package/resources/beta/responses/ws-base.js +35 -6
- package/resources/beta/responses/ws-base.js.map +1 -1
- package/resources/beta/responses/ws-base.mjs +35 -6
- package/resources/beta/responses/ws-base.mjs.map +1 -1
- package/resources/beta/responses/ws.d.mts +10 -0
- package/resources/beta/responses/ws.d.mts.map +1 -1
- package/resources/beta/responses/ws.d.ts +10 -0
- package/resources/beta/responses/ws.d.ts.map +1 -1
- package/resources/beta/responses/ws.js +23 -22
- package/resources/beta/responses/ws.js.map +1 -1
- package/resources/beta/responses/ws.mjs +24 -23
- package/resources/beta/responses/ws.mjs.map +1 -1
- package/resources/chat/completions/completions.d.mts +1 -1
- package/resources/chat/completions/completions.d.mts.map +1 -1
- package/resources/chat/completions/completions.d.ts +1 -1
- package/resources/chat/completions/completions.d.ts.map +1 -1
- package/resources/evals/runs/runs.js +1 -1
- package/resources/evals/runs/runs.js.map +1 -1
- package/resources/evals/runs/runs.mjs +1 -1
- package/resources/evals/runs/runs.mjs.map +1 -1
- package/resources/live/forks/forks.d.mts +5 -1
- package/resources/live/forks/forks.d.mts.map +1 -1
- package/resources/live/forks/forks.d.ts +5 -1
- package/resources/live/forks/forks.d.ts.map +1 -1
- package/resources/live/live.d.mts +5 -1
- package/resources/live/live.d.mts.map +1 -1
- package/resources/live/live.d.ts +5 -1
- 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/responses/ws-base.d.mts +3 -1
- package/resources/responses/ws-base.d.mts.map +1 -1
- package/resources/responses/ws-base.d.ts +3 -1
- package/resources/responses/ws-base.d.ts.map +1 -1
- package/resources/responses/ws-base.js +35 -6
- package/resources/responses/ws-base.js.map +1 -1
- package/resources/responses/ws-base.mjs +35 -6
- package/resources/responses/ws-base.mjs.map +1 -1
- package/resources/responses/ws.d.mts +10 -0
- package/resources/responses/ws.d.mts.map +1 -1
- package/resources/responses/ws.d.ts +10 -0
- package/resources/responses/ws.d.ts.map +1 -1
- package/resources/responses/ws.js +23 -22
- package/resources/responses/ws.js.map +1 -1
- package/resources/responses/ws.mjs +24 -23
- package/resources/responses/ws.mjs.map +1 -1
- package/src/client.ts +55 -19
- package/src/core/streaming.ts +9 -0
- package/src/helpers/beta/agents/standard-schema.ts +13 -0
- package/src/helpers/beta/agents/zod.ts +10 -0
- package/src/internal/realtime-credentials.ts +70 -4
- package/src/internal/responses-ws-credentials.ts +160 -0
- package/src/internal/ws-adapter-node.ts +66 -0
- package/src/internal/ws.ts +139 -11
- package/src/lib/agents/agent-session-stream.ts +36 -24
- package/src/lib/beta/agents/agent-session-create-stream.ts +36 -0
- package/src/lib/beta/agents/agent-turn-result-collector.ts +122 -0
- package/src/lib/beta/agents/agent-turn-result-error.ts +33 -0
- package/src/lib/beta/agents/agent-turn-result.ts +22 -0
- package/src/lib/beta/agents/function-tool.ts +60 -0
- package/src/lib/beta/agents/output-format-types.ts +12 -0
- package/src/lib/beta/agents/output-format.ts +20 -0
- package/src/lib/beta/agents/output-parse-error.ts +16 -0
- package/src/lib/beta/agents/parse-result.ts +133 -0
- package/src/lib/beta/agents/parsed-agent-turn-result.ts +12 -0
- package/src/lib/beta/agents/result-collection.ts +115 -0
- package/src/lib/beta/agents/tool-output.ts +22 -0
- package/src/lib/responses/responses-websocket-session.ts +14 -3
- package/src/resources/beta/agents/agents.ts +11 -0
- package/src/resources/beta/agents/sessions/events.ts +6 -5
- package/src/resources/beta/agents/sessions/index.ts +1 -0
- package/src/resources/beta/agents/sessions/sessions.ts +48 -18
- package/src/resources/beta/agents/sessions/traces.ts +298 -0
- package/src/resources/beta/responses/ws-base.ts +40 -6
- package/src/resources/beta/responses/ws.ts +37 -27
- package/src/resources/chat/completions/completions.ts +1 -1
- package/src/resources/evals/runs/runs.ts +1 -1
- package/src/resources/live/forks/forks.ts +6 -1
- package/src/resources/live/live.ts +6 -1
- package/src/resources/responses/ws-base.ts +40 -6
- package/src/resources/responses/ws.ts +37 -27
- package/src/tsconfig.dist-src-node.d.ts +7 -0
- package/src/tsconfig.dist-src.d.ts +3 -1
- 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
|
@@ -6,8 +6,7 @@ const tslib_1 = require("../../internal/tslib.js");
|
|
|
6
6
|
const WS = tslib_1.__importStar(require("ws"));
|
|
7
7
|
const ws_adapter_node_1 = require("../../internal/ws-adapter-node.js");
|
|
8
8
|
const ws_base_1 = require("./ws-base.js");
|
|
9
|
-
const
|
|
10
|
-
const ws_1 = require("../../internal/ws.js");
|
|
9
|
+
const responses_ws_credentials_1 = require("../../internal/responses-ws-credentials.js");
|
|
11
10
|
class ResponsesWS extends ws_base_1.ResponsesWSBase {
|
|
12
11
|
constructor(client, options) {
|
|
13
12
|
if (!WS?.WebSocket) {
|
|
@@ -15,32 +14,34 @@ class ResponsesWS extends ws_base_1.ResponsesWSBase {
|
|
|
15
14
|
}
|
|
16
15
|
const { reconnect, maxQueueSize, ...wsOptions } = options ?? {};
|
|
17
16
|
super(client, { reconnect, maxQueueSize });
|
|
17
|
+
this._credentials = new responses_ws_credentials_1.ResponsesWebSocketCredentials();
|
|
18
18
|
this._wsOptions = wsOptions;
|
|
19
19
|
this._connectInitial();
|
|
20
20
|
}
|
|
21
|
+
_authHeaders(apiKey) {
|
|
22
|
+
const headers = super._authHeaders(apiKey === undefined ? this._credentials.preparedAPIKey : apiKey);
|
|
23
|
+
this._credentials.trackInitialHeaders(this._client, headers, () => !!this.socket);
|
|
24
|
+
return headers;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether credentials passed to the Node transport use the SDK key.
|
|
28
|
+
* The SDK recognizes its key, including copies and additions in credential headers.
|
|
29
|
+
* Override and return true if your socket hook signs or otherwise irreversibly transforms it.
|
|
30
|
+
* Explicit caller options and header removals still take precedence on reconnect.
|
|
31
|
+
*/
|
|
32
|
+
_usesSDKAPIKey(authHeaders) {
|
|
33
|
+
return this._credentials.usesAPIKey(this._client, authHeaders);
|
|
34
|
+
}
|
|
21
35
|
_createSocket(url, authHeaders) {
|
|
22
36
|
const capturedAuthHeaders = { ...authHeaders };
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
headers.set(name.toLowerCase(), value);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
const socketOptions = {
|
|
33
|
-
...this._wsOptions,
|
|
34
|
-
headers: Object.fromEntries(headers),
|
|
35
|
-
followRedirects: false,
|
|
36
|
-
};
|
|
37
|
-
if (this._client._hasApiKeyProvider() &&
|
|
38
|
-
!capturedAuthHeaders['Authorization'] &&
|
|
39
|
-
!(0, ws_1.snapshotWebSocketCredentials)(socketOptions)) {
|
|
40
|
-
throw new error_1.OpenAIError('Cannot open a Responses WebSocket with an unresolved function-based apiKey. Resolve it before constructing the WebSocket or provide explicit WebSocket credentials.');
|
|
37
|
+
const socketOptions = this._credentials.build(this._client, capturedAuthHeaders, this._wsOptions, !this.socket ? this._usesSDKAPIKey(capturedAuthHeaders) : undefined);
|
|
38
|
+
return new ws_adapter_node_1.NodeWebSocket(new WS.WebSocket(url, socketOptions));
|
|
39
|
+
}
|
|
40
|
+
async _prepareReconnectSocket() {
|
|
41
|
+
if (!this._client._hasApiKeyProvider()) {
|
|
42
|
+
return super._prepareReconnectSocket();
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
return new ws_adapter_node_1.NodeWebSocket(ws);
|
|
44
|
+
return this._credentials.prepare(this._client, (0, ws_adapter_node_1.snapshotNodeWebSocketOptions)(this._wsOptions), (...args) => this._authHeaders(...args), (url, headers) => this._createSocket(url, headers));
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
exports.ResponsesWS = ResponsesWS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../../src/resources/responses/ws.ts"],"names":[],"mappings":";AAAA,qFAAqF;;;;AAErF,+CAAyB;AACzB,
|
|
1
|
+
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../../src/resources/responses/ws.ts"],"names":[],"mappings":";AAAA,qFAAqF;;;;AAErF,+CAAyB;AACzB,uEAA6F;AAC7F,0CAAyE;AAEzE,yFAAwF;AAWxF,MAAa,WAAY,SAAQ,yBAA8B;IAI7D,YAAY,MAAc,EAAE,OAAqD;QAC/E,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,wGAAwG,CACzG,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAChE,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;QATrC,iBAAY,GAAG,IAAI,wDAA6B,EAAE,CAAC;QAUzD,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAEkB,YAAY,CAAC,MAAsB;QACpD,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrG,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACO,cAAc,CAAC,WAAmC;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC;IAES,aAAa,CAAC,GAAQ,EAAE,WAAmC;QACnE,MAAM,mBAAmB,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAC3C,IAAI,CAAC,OAAO,EACZ,mBAAmB,EACnB,IAAI,CAAC,UAAU,EACf,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CACpE,CAAC;QACF,OAAO,IAAI,+BAAa,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC;IACjE,CAAC;IAEkB,KAAK,CAAC,uBAAuB;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC,uBAAuB,EAAE,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAC9B,IAAI,CAAC,OAAO,EACZ,IAAA,8CAA4B,EAAC,IAAI,CAAC,UAAU,CAAC,EAC7C,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,EACvC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CACnD,CAAC;IACJ,CAAC;CACF;AAtDD,kCAsDC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details.
|
|
2
2
|
import * as WS from 'ws';
|
|
3
|
-
import { NodeWebSocket } from "../../internal/ws-adapter-node.mjs";
|
|
3
|
+
import { NodeWebSocket, snapshotNodeWebSocketOptions } from "../../internal/ws-adapter-node.mjs";
|
|
4
4
|
import { ResponsesWSBase } from "./ws-base.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { snapshotWebSocketCredentials } from "../../internal/ws.mjs";
|
|
5
|
+
import { ResponsesWebSocketCredentials } from "../../internal/responses-ws-credentials.mjs";
|
|
7
6
|
export class ResponsesWS extends ResponsesWSBase {
|
|
8
7
|
constructor(client, options) {
|
|
9
8
|
if (!WS?.WebSocket) {
|
|
@@ -11,32 +10,34 @@ export class ResponsesWS extends ResponsesWSBase {
|
|
|
11
10
|
}
|
|
12
11
|
const { reconnect, maxQueueSize, ...wsOptions } = options ?? {};
|
|
13
12
|
super(client, { reconnect, maxQueueSize });
|
|
13
|
+
this._credentials = new ResponsesWebSocketCredentials();
|
|
14
14
|
this._wsOptions = wsOptions;
|
|
15
15
|
this._connectInitial();
|
|
16
16
|
}
|
|
17
|
+
_authHeaders(apiKey) {
|
|
18
|
+
const headers = super._authHeaders(apiKey === undefined ? this._credentials.preparedAPIKey : apiKey);
|
|
19
|
+
this._credentials.trackInitialHeaders(this._client, headers, () => !!this.socket);
|
|
20
|
+
return headers;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether credentials passed to the Node transport use the SDK key.
|
|
24
|
+
* The SDK recognizes its key, including copies and additions in credential headers.
|
|
25
|
+
* Override and return true if your socket hook signs or otherwise irreversibly transforms it.
|
|
26
|
+
* Explicit caller options and header removals still take precedence on reconnect.
|
|
27
|
+
*/
|
|
28
|
+
_usesSDKAPIKey(authHeaders) {
|
|
29
|
+
return this._credentials.usesAPIKey(this._client, authHeaders);
|
|
30
|
+
}
|
|
17
31
|
_createSocket(url, authHeaders) {
|
|
18
32
|
const capturedAuthHeaders = { ...authHeaders };
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
headers.set(name.toLowerCase(), value);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const socketOptions = {
|
|
29
|
-
...this._wsOptions,
|
|
30
|
-
headers: Object.fromEntries(headers),
|
|
31
|
-
followRedirects: false,
|
|
32
|
-
};
|
|
33
|
-
if (this._client._hasApiKeyProvider() &&
|
|
34
|
-
!capturedAuthHeaders['Authorization'] &&
|
|
35
|
-
!snapshotWebSocketCredentials(socketOptions)) {
|
|
36
|
-
throw new OpenAIError('Cannot open a Responses WebSocket with an unresolved function-based apiKey. Resolve it before constructing the WebSocket or provide explicit WebSocket credentials.');
|
|
33
|
+
const socketOptions = this._credentials.build(this._client, capturedAuthHeaders, this._wsOptions, !this.socket ? this._usesSDKAPIKey(capturedAuthHeaders) : undefined);
|
|
34
|
+
return new NodeWebSocket(new WS.WebSocket(url, socketOptions));
|
|
35
|
+
}
|
|
36
|
+
async _prepareReconnectSocket() {
|
|
37
|
+
if (!this._client._hasApiKeyProvider()) {
|
|
38
|
+
return super._prepareReconnectSocket();
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
return new NodeWebSocket(ws);
|
|
40
|
+
return this._credentials.prepare(this._client, snapshotNodeWebSocketOptions(this._wsOptions), (...args) => this._authHeaders(...args), (url, headers) => this._createSocket(url, headers));
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
//# sourceMappingURL=ws.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.mjs","sourceRoot":"","sources":["../../src/resources/responses/ws.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,2CAAuC;
|
|
1
|
+
{"version":3,"file":"ws.mjs","sourceRoot":"","sources":["../../src/resources/responses/ws.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,2CAAuC;AAC7F,OAAO,EAAE,eAAe,EAA+B,sBAAkB;AAEzE,OAAO,EAAE,6BAA6B,EAAE,oDAAgD;AAWxF,MAAM,OAAO,WAAY,SAAQ,eAA8B;IAI7D,YAAY,MAAc,EAAE,OAAqD;QAC/E,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,wGAAwG,CACzG,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAChE,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;QATrC,iBAAY,GAAG,IAAI,6BAA6B,EAAE,CAAC;QAUzD,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAEkB,YAAY,CAAC,MAAsB;QACpD,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrG,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACO,cAAc,CAAC,WAAmC;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC;IAES,aAAa,CAAC,GAAQ,EAAE,WAAmC;QACnE,MAAM,mBAAmB,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAC3C,IAAI,CAAC,OAAO,EACZ,mBAAmB,EACnB,IAAI,CAAC,UAAU,EACf,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CACpE,CAAC;QACF,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC;IACjE,CAAC;IAEkB,KAAK,CAAC,uBAAuB;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC,uBAAuB,EAAE,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAC9B,IAAI,CAAC,OAAO,EACZ,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC,EAC7C,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,EACvC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CACnD,CAAC;IACJ,CAAC;CACF"}
|
package/src/client.ts
CHANGED
|
@@ -48,7 +48,11 @@ import {
|
|
|
48
48
|
import * as Uploads from './core/uploads';
|
|
49
49
|
import * as API from './resources/index';
|
|
50
50
|
import { APIPromise } from './core/api-promise';
|
|
51
|
-
import {
|
|
51
|
+
import {
|
|
52
|
+
getDeferredRealtimeAPIKeyCache,
|
|
53
|
+
resolveRealtimeAPIKey,
|
|
54
|
+
validateCapturedAPIKey,
|
|
55
|
+
} from './internal/realtime-credentials';
|
|
52
56
|
import {
|
|
53
57
|
Batch,
|
|
54
58
|
BatchCreateParams,
|
|
@@ -258,6 +262,7 @@ import {
|
|
|
258
262
|
import { type Fetch } from './internal/builtin-types';
|
|
259
263
|
import { isRunningInBrowser } from './internal/detect-platform';
|
|
260
264
|
import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
|
|
265
|
+
import { mergeWebSocketAuthHeaders, webSocketHeaderRemovals } from './internal/ws';
|
|
261
266
|
import { configureProvider, type Provider, type ProviderRuntime } from './internal/provider';
|
|
262
267
|
import { FinalRequestOptions, RequestOptions } from './internal/request-options';
|
|
263
268
|
import { readEnv } from './internal/utils/env';
|
|
@@ -490,6 +495,8 @@ export class OpenAI {
|
|
|
490
495
|
protected idempotencyHeader?: string;
|
|
491
496
|
protected _options: ClientOptions;
|
|
492
497
|
private _provider: ProviderRuntime | undefined;
|
|
498
|
+
private _apiKeyInvocation = 0;
|
|
499
|
+
private _lastCachedAPIKeyInvocation = 0;
|
|
493
500
|
private _workloadIdentityAuth?: WorkloadIdentityAuth | X509WorkloadIdentityAuth;
|
|
494
501
|
|
|
495
502
|
/**
|
|
@@ -741,18 +748,33 @@ export class OpenAI {
|
|
|
741
748
|
}
|
|
742
749
|
|
|
743
750
|
/** @internal Client request headers for each new WebSocket handshake. */
|
|
744
|
-
_buildWebSocketHeaders(
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
},
|
|
751
|
+
_buildWebSocketHeaders(
|
|
752
|
+
authHeaders: Record<string, string>,
|
|
753
|
+
removedHeaders?: Set<string>,
|
|
754
|
+
): Record<string, string> {
|
|
755
|
+
const context = webSocketHeaderRemovals.get(this);
|
|
756
|
+
if (context?.baseHeaders) {
|
|
757
|
+
return mergeWebSocketAuthHeaders(
|
|
758
|
+
{ headers: context.baseHeaders },
|
|
752
759
|
authHeaders,
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
760
|
+
context.removedHeaders ?? new Set(),
|
|
761
|
+
).headers;
|
|
762
|
+
}
|
|
763
|
+
const headers = buildHeaders([
|
|
764
|
+
{
|
|
765
|
+
'User-Agent': this.getUserAgent(),
|
|
766
|
+
'OpenAI-Organization': this.organization,
|
|
767
|
+
'OpenAI-Project': this.project,
|
|
768
|
+
},
|
|
769
|
+
authHeaders,
|
|
770
|
+
this._options.defaultHeaders,
|
|
771
|
+
]);
|
|
772
|
+
headers.nulls.forEach((name) => (removedHeaders ?? context?.removedHeaders)?.add(name));
|
|
773
|
+
const result = Object.fromEntries(headers.values);
|
|
774
|
+
if (context) {
|
|
775
|
+
context.baseHeaders = { ...result };
|
|
776
|
+
}
|
|
777
|
+
return result;
|
|
756
778
|
}
|
|
757
779
|
|
|
758
780
|
protected validateHeaders(
|
|
@@ -877,11 +899,8 @@ export class OpenAI {
|
|
|
877
899
|
}
|
|
878
900
|
|
|
879
901
|
/**
|
|
880
|
-
* Resolves a
|
|
881
|
-
*
|
|
882
|
-
* invocation's key before another request updates the shared `apiKey` property.
|
|
883
|
-
* Overrides should forward `capture` or invoke it with their own resolved key
|
|
884
|
-
* to preserve invocation-local credentials in concurrent requests and Realtime factories.
|
|
902
|
+
* Resolves and retains a provider key, returning whether a provider was invoked.
|
|
903
|
+
* Overrides should forward `capture` (or call it with their resolved key) for local credentials.
|
|
885
904
|
* @internal
|
|
886
905
|
*/
|
|
887
906
|
async _callApiKey(capture?: (apiKey: string | null) => void): Promise<boolean> {
|
|
@@ -896,6 +915,8 @@ export class OpenAI {
|
|
|
896
915
|
return false;
|
|
897
916
|
}
|
|
898
917
|
|
|
918
|
+
const deferredCache = getDeferredRealtimeAPIKeyCache(this);
|
|
919
|
+
const invocation = ++this._apiKeyInvocation;
|
|
899
920
|
let token: unknown;
|
|
900
921
|
try {
|
|
901
922
|
token = await apiKey();
|
|
@@ -913,8 +934,23 @@ export class OpenAI {
|
|
|
913
934
|
`Expected 'apiKey' function argument to return a string but it returned ${token}`,
|
|
914
935
|
);
|
|
915
936
|
}
|
|
916
|
-
|
|
917
|
-
|
|
937
|
+
const resolvedToken = token;
|
|
938
|
+
const commit = () => {
|
|
939
|
+
if (capture) validateCapturedAPIKey(this, resolvedToken);
|
|
940
|
+
if (invocation < this._lastCachedAPIKeyInvocation) {
|
|
941
|
+
return resolvedToken;
|
|
942
|
+
}
|
|
943
|
+
this.apiKey = resolvedToken;
|
|
944
|
+
const cached = capture ? this.apiKey : resolvedToken;
|
|
945
|
+
this._lastCachedAPIKeyInvocation = invocation;
|
|
946
|
+
return cached;
|
|
947
|
+
};
|
|
948
|
+
if (deferredCache) {
|
|
949
|
+
deferredCache.providerKey = resolvedToken;
|
|
950
|
+
deferredCache.commit = commit;
|
|
951
|
+
}
|
|
952
|
+
const cached = deferredCache ? validateCapturedAPIKey(this, resolvedToken) : commit();
|
|
953
|
+
capture?.(cached);
|
|
918
954
|
return true;
|
|
919
955
|
}
|
|
920
956
|
|
package/src/core/streaming.ts
CHANGED
|
@@ -301,6 +301,15 @@ export class Stream<Item> implements AsyncIterable<Item> {
|
|
|
301
301
|
return this.iterator();
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
/** Beta-only iterator decoration for Agents helpers, preserving custom stream identity.
|
|
305
|
+
* @internal
|
|
306
|
+
*/
|
|
307
|
+
__betaTransformIterator(
|
|
308
|
+
transform: (iterator: () => AsyncIterator<Item>) => () => AsyncIterator<Item>,
|
|
309
|
+
): void {
|
|
310
|
+
this.iterator = transform(this.iterator.bind(this));
|
|
311
|
+
}
|
|
312
|
+
|
|
304
313
|
/**
|
|
305
314
|
* Splits the stream into two streams which can be
|
|
306
315
|
* independently read from at different speeds.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { standardTextFormat } from '../../standard-schema';
|
|
2
|
+
import type { JSONSchema } from '../../../lib/jsonschema';
|
|
3
|
+
import { agentOutputFormat } from '../../../lib/beta/agents/output-format';
|
|
4
|
+
|
|
5
|
+
/** Beta: bind a synchronous Standard Schema validator to Agents output. */
|
|
6
|
+
export function standardAgentTextFormat<S extends Parameters<typeof standardTextFormat>[0]>(
|
|
7
|
+
schema: S,
|
|
8
|
+
jsonSchema?: JSONSchema,
|
|
9
|
+
) {
|
|
10
|
+
const format = standardTextFormat(schema, 'agent_output', { schema: jsonSchema });
|
|
11
|
+
// SAFETY: The native Responses helper owns Standard Schema conversion and validation.
|
|
12
|
+
return agentOutputFormat(format.schema as JSONSchema, format.$parseRaw);
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { zodTextFormat } from '../../zod';
|
|
2
|
+
import type { JSONSchema } from '../../../lib/jsonschema';
|
|
3
|
+
import { agentOutputFormat } from '../../../lib/beta/agents/output-format';
|
|
4
|
+
|
|
5
|
+
/** Beta: bind a Zod v3/v4/Mini schema to an Agents text format and completed result. */
|
|
6
|
+
export function zodAgentTextFormat<S extends Parameters<typeof zodTextFormat>[0]>(schema: S) {
|
|
7
|
+
const format = zodTextFormat(schema, 'agent_output');
|
|
8
|
+
// SAFETY: The native Responses helper owns Zod schema conversion and validation.
|
|
9
|
+
return agentOutputFormat(format.schema as JSONSchema, format.$parseRaw);
|
|
10
|
+
}
|
|
@@ -1,4 +1,44 @@
|
|
|
1
1
|
import type { OpenAI } from '../client';
|
|
2
|
+
import { assertValidBedrockBearerCredential, brand_privateBedrockClient } from './bedrock';
|
|
3
|
+
|
|
4
|
+
type CaptureAPIKey = (apiKey: string | null) => void;
|
|
5
|
+
export interface DeferredAPIKeyCache {
|
|
6
|
+
client: Pick<OpenAI, 'apiKey'>;
|
|
7
|
+
providerKey?: string;
|
|
8
|
+
commit: () => string | null;
|
|
9
|
+
}
|
|
10
|
+
interface RealtimeAPIKeyCacheContext {
|
|
11
|
+
run: <T>(cache: DeferredAPIKeyCache | undefined, operation: () => T) => T;
|
|
12
|
+
getStore: () => DeferredAPIKeyCache | undefined;
|
|
13
|
+
}
|
|
14
|
+
// Only the key crosses module formats: the context belongs to each participating client.
|
|
15
|
+
const realtimeCacheContext = Symbol.for('openai.realtimeAPIKeyCacheContext');
|
|
16
|
+
type CredentialClient = Pick<OpenAI, 'apiKey'> & {
|
|
17
|
+
[realtimeCacheContext]?: RealtimeAPIKeyCacheContext;
|
|
18
|
+
};
|
|
19
|
+
let cacheContext: RealtimeAPIKeyCacheContext | undefined;
|
|
20
|
+
|
|
21
|
+
/** Installs the Node transport's invocation context without loading Node in the base client. @internal */
|
|
22
|
+
export function setRealtimeAPIKeyCacheContext(context: RealtimeAPIKeyCacheContext): void {
|
|
23
|
+
cacheContext = context;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Reserves a deferred commit when the base hook is entered for this invocation. @internal */
|
|
27
|
+
export function getDeferredRealtimeAPIKeyCache(client: CredentialClient): DeferredAPIKeyCache | undefined {
|
|
28
|
+
const deferred = client[realtimeCacheContext]?.getStore();
|
|
29
|
+
return deferred?.client === client ? deferred : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Applies the Bedrock getter's validation when a captured credential does not enter the cache. @internal */
|
|
33
|
+
export function validateCapturedAPIKey(
|
|
34
|
+
client: Pick<OpenAI, 'apiKey'>,
|
|
35
|
+
credential: string | null,
|
|
36
|
+
): string | null {
|
|
37
|
+
if (credential !== null && brand_privateBedrockClient in client) {
|
|
38
|
+
assertValidBedrockBearerCredential(credential);
|
|
39
|
+
}
|
|
40
|
+
return credential;
|
|
41
|
+
}
|
|
2
42
|
|
|
3
43
|
/** Selects a captured credential without treating an explicit null as absent. @internal */
|
|
4
44
|
export function getRealtimeAPIKey(
|
|
@@ -15,13 +55,39 @@ export function getRealtimeAPIKey(
|
|
|
15
55
|
* synchronizing concurrent credential updates.
|
|
16
56
|
* @internal
|
|
17
57
|
*/
|
|
18
|
-
export async function resolveRealtimeAPIKey(
|
|
58
|
+
export async function resolveRealtimeAPIKey(
|
|
59
|
+
client: CredentialClient & Pick<OpenAI, '_callApiKey'>,
|
|
60
|
+
deferCache = false,
|
|
61
|
+
): Promise<{
|
|
19
62
|
apiKey: string | null;
|
|
20
63
|
isProvider: boolean;
|
|
64
|
+
commit: () => string | null;
|
|
21
65
|
}> {
|
|
22
66
|
let apiKey: string | null | undefined;
|
|
23
|
-
const
|
|
67
|
+
const current: DeferredAPIKeyCache = {
|
|
68
|
+
client,
|
|
69
|
+
commit: () => (apiKey === undefined ? client.apiKey : apiKey),
|
|
70
|
+
};
|
|
71
|
+
const capture: CaptureAPIKey = (resolved) => {
|
|
24
72
|
apiKey = resolved;
|
|
25
|
-
}
|
|
26
|
-
|
|
73
|
+
};
|
|
74
|
+
const invoke = () => client._callApiKey(capture);
|
|
75
|
+
const context = client[realtimeCacheContext] ?? cacheContext;
|
|
76
|
+
if (deferCache && context && !client[realtimeCacheContext]) {
|
|
77
|
+
Object.defineProperty(client, realtimeCacheContext, { value: context });
|
|
78
|
+
}
|
|
79
|
+
// An HTTP or ordinary Realtime request nested inside a WebSocket hook owns its own cache writes.
|
|
80
|
+
const isProvider = await (context ? context.run(deferCache ? current : undefined, invoke) : invoke());
|
|
81
|
+
return {
|
|
82
|
+
apiKey: apiKey === undefined ? client.apiKey : apiKey,
|
|
83
|
+
isProvider,
|
|
84
|
+
commit: () => {
|
|
85
|
+
const hookKey =
|
|
86
|
+
current.providerKey !== undefined && apiKey !== undefined && apiKey !== current.providerKey
|
|
87
|
+
? validateCapturedAPIKey(client, apiKey)
|
|
88
|
+
: undefined;
|
|
89
|
+
const cached = current.commit();
|
|
90
|
+
return hookKey === undefined ? validateCapturedAPIKey(client, cached) : hookKey;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
27
93
|
}
|
|
@@ -0,0 +1,160 @@
|
|
|
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 buildResponsesWebSocketOptions<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 prepareResponsesWebSocketReconnect<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 Responses credential state shared by the stable and beta Node transports. */
|
|
68
|
+
export class ResponsesWebSocketCredentials {
|
|
69
|
+
private initialAuthUsedAPIKey = false;
|
|
70
|
+
private initialAPIKey: string | undefined;
|
|
71
|
+
private prepared:
|
|
72
|
+
| {
|
|
73
|
+
options: ReturnType<typeof buildWebSocketOptions>;
|
|
74
|
+
removedHeaders: Set<string>;
|
|
75
|
+
apiKey?: string | null | undefined;
|
|
76
|
+
}
|
|
77
|
+
| undefined;
|
|
78
|
+
|
|
79
|
+
get preparedAPIKey(): string | null | undefined {
|
|
80
|
+
return this.prepared?.apiKey;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
trackInitialHeaders(client: OpenAI, headers: Record<string, string>, hasSocket: () => boolean): void {
|
|
84
|
+
if (!hasSocket() && client._hasApiKeyProvider()) {
|
|
85
|
+
this.initialAPIKey = headers['Authorization']?.slice('Bearer '.length);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
usesAPIKey(client: OpenAI, headers: Record<string, string>): boolean {
|
|
90
|
+
// Hooks can read the SDK key without delegating. Only use an ordinary cached property here:
|
|
91
|
+
// invoking custom/Bedrock getters could validate credentials a caller-owned socket never sends.
|
|
92
|
+
const apiKey =
|
|
93
|
+
this.initialAPIKey ??
|
|
94
|
+
(client._hasApiKeyProvider() ? Object.getOwnPropertyDescriptor(client, 'apiKey')?.value : undefined);
|
|
95
|
+
if (!apiKey) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
// Metadata containing a copy of a credential does not make it the socket's authentication.
|
|
99
|
+
return snapshotWebSocketCredentials(
|
|
100
|
+
{
|
|
101
|
+
headers: Object.fromEntries(
|
|
102
|
+
Object.entries(headers).map(([name, value]) => [name, value?.includes(apiKey) ? value : '']),
|
|
103
|
+
),
|
|
104
|
+
},
|
|
105
|
+
WEBSOCKET_METADATA_HEADERS,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
build<Options extends CredentialedWebSocketOptions>(
|
|
110
|
+
client: OpenAI,
|
|
111
|
+
authHeaders: Record<string, string>,
|
|
112
|
+
options: Options | null | undefined,
|
|
113
|
+
initialAuthUsedAPIKey?: boolean,
|
|
114
|
+
) {
|
|
115
|
+
if (initialAuthUsedAPIKey !== undefined) {
|
|
116
|
+
this.initialAuthUsedAPIKey = initialAuthUsedAPIKey;
|
|
117
|
+
this.initialAPIKey = undefined;
|
|
118
|
+
}
|
|
119
|
+
const socketOptions = buildResponsesWebSocketOptions(client, authHeaders, options, this.prepared);
|
|
120
|
+
if (
|
|
121
|
+
client._hasApiKeyProvider() &&
|
|
122
|
+
!authHeaders['Authorization'] &&
|
|
123
|
+
!snapshotWebSocketCredentials(socketOptions, WEBSOCKET_METADATA_HEADERS)
|
|
124
|
+
) {
|
|
125
|
+
throw new OpenAIError(
|
|
126
|
+
'Cannot open a Responses WebSocket with an unresolved function-based apiKey. Resolve it before constructing the WebSocket or provide explicit WebSocket credentials.',
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return socketOptions;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async prepare<Socket, Options extends CredentialedWebSocketOptions>(
|
|
133
|
+
client: OpenAI,
|
|
134
|
+
socketOptions: Options | null | undefined,
|
|
135
|
+
authHeaders: (apiKey?: string | null) => Record<string, string>,
|
|
136
|
+
createSocket: (url: URL, headers: Record<string, string>) => Socket,
|
|
137
|
+
): Promise<(url: URL) => Socket> {
|
|
138
|
+
const { options, removedHeaders, authentication } = prepareResponsesWebSocketReconnect(
|
|
139
|
+
client,
|
|
140
|
+
socketOptions,
|
|
141
|
+
this.initialAuthUsedAPIKey,
|
|
142
|
+
);
|
|
143
|
+
const createPreparedSocket = (url: URL, headers: Record<string, string>, apiKey?: string | null) => {
|
|
144
|
+
const previous = this.prepared;
|
|
145
|
+
this.prepared = { options, removedHeaders, apiKey };
|
|
146
|
+
try {
|
|
147
|
+
// Resolve headers inside the scope so legacy zero-argument overrides see this attempt's key.
|
|
148
|
+
return createSocket(url, apiKey === undefined ? headers : authHeaders(apiKey));
|
|
149
|
+
} finally {
|
|
150
|
+
this.prepared = previous;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
if (authentication !== 'refresh') {
|
|
154
|
+
const headers = authentication === 'provided' ? {} : authHeaders();
|
|
155
|
+
return (url) => createPreparedSocket(url, headers);
|
|
156
|
+
}
|
|
157
|
+
const { commit } = await resolveRealtimeAPIKey(client, true);
|
|
158
|
+
return (url) => createPreparedSocket(url, {}, commit());
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -1,10 +1,76 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
1
2
|
import type * as WS from 'ws';
|
|
2
3
|
import type { WebSocketLike } from './ws-adapter';
|
|
3
4
|
import { protectWebSocketOptionsFromCredentialRedirects } from './ws';
|
|
5
|
+
import { setRealtimeAPIKeyCacheContext } from './realtime-credentials';
|
|
6
|
+
import type { DeferredAPIKeyCache } from './realtime-credentials';
|
|
7
|
+
|
|
8
|
+
setRealtimeAPIKeyCacheContext(new AsyncLocalStorage<DeferredAPIKeyCache | undefined>());
|
|
4
9
|
|
|
5
10
|
/** A generic event listener callback. */
|
|
6
11
|
type Listener = (...args: any[]) => void;
|
|
7
12
|
|
|
13
|
+
function copyTLSMaterial(value: string | Buffer): string | Buffer {
|
|
14
|
+
return ArrayBuffer.isView(value)
|
|
15
|
+
? Buffer.from(new Uint8Array(value.buffer, value.byteOffset, value.byteLength))
|
|
16
|
+
: value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Snapshot caller headers and TLS identity before an async reconnect credential refresh. */
|
|
20
|
+
export function snapshotNodeWebSocketOptions(
|
|
21
|
+
options: WS.ClientOptions | null | undefined,
|
|
22
|
+
): Omit<WS.ClientOptions, 'headers'> & { headers: Record<string, string | string[]> } {
|
|
23
|
+
const captured = {
|
|
24
|
+
...options,
|
|
25
|
+
headers: Object.fromEntries(
|
|
26
|
+
Object.entries(options?.headers ?? {}).map(([name, value]) => [
|
|
27
|
+
name,
|
|
28
|
+
Array.isArray(value) ? [...value] : value,
|
|
29
|
+
]),
|
|
30
|
+
),
|
|
31
|
+
};
|
|
32
|
+
const { ca, cert, crl, key, pfx } = captured;
|
|
33
|
+
if (ca !== undefined) {
|
|
34
|
+
captured.ca = Array.isArray(ca) ? ca.map(copyTLSMaterial) : copyTLSMaterial(ca);
|
|
35
|
+
}
|
|
36
|
+
if (cert !== undefined) {
|
|
37
|
+
captured.cert = Array.isArray(cert) ? cert.map(copyTLSMaterial) : copyTLSMaterial(cert);
|
|
38
|
+
}
|
|
39
|
+
if (crl !== undefined) {
|
|
40
|
+
captured.crl = Array.isArray(crl) ? crl.map(copyTLSMaterial) : copyTLSMaterial(crl);
|
|
41
|
+
}
|
|
42
|
+
if (key !== undefined) {
|
|
43
|
+
captured.key = Array.isArray(key)
|
|
44
|
+
? key.map((value) =>
|
|
45
|
+
typeof value === 'string' || ArrayBuffer.isView(value)
|
|
46
|
+
? copyTLSMaterial(value)
|
|
47
|
+
: { ...value, pem: copyTLSMaterial(value.pem) },
|
|
48
|
+
)
|
|
49
|
+
: copyTLSMaterial(key);
|
|
50
|
+
}
|
|
51
|
+
if (pfx !== undefined) {
|
|
52
|
+
captured.pfx = Array.isArray(pfx)
|
|
53
|
+
? pfx.map((value) =>
|
|
54
|
+
typeof value === 'string' || ArrayBuffer.isView(value)
|
|
55
|
+
? copyTLSMaterial(value)
|
|
56
|
+
: { ...value, buf: copyTLSMaterial(value.buf) },
|
|
57
|
+
)
|
|
58
|
+
: copyTLSMaterial(pfx);
|
|
59
|
+
}
|
|
60
|
+
if ('session' in captured && Buffer.isBuffer(captured.session)) {
|
|
61
|
+
captured.session = Buffer.from(captured.session);
|
|
62
|
+
}
|
|
63
|
+
if ('ALPNProtocols' in captured) {
|
|
64
|
+
if (Array.isArray(captured.ALPNProtocols)) {
|
|
65
|
+
captured.ALPNProtocols = [...captured.ALPNProtocols];
|
|
66
|
+
} else if (ArrayBuffer.isView(captured.ALPNProtocols)) {
|
|
67
|
+
const { buffer, byteOffset, byteLength } = captured.ALPNProtocols;
|
|
68
|
+
captured.ALPNProtocols = Buffer.from(new Uint8Array(buffer, byteOffset, byteLength));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return captured;
|
|
72
|
+
}
|
|
73
|
+
|
|
8
74
|
/**
|
|
9
75
|
* Adapts a Node.js `ws` socket to the SDK's platform-neutral WebSocket API.
|
|
10
76
|
*
|