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
package/src/internal/ws.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { concatBytes, encodeUTF8 } from './utils/bytes';
|
|
2
2
|
import { OpenAIError } from '../core/error';
|
|
3
3
|
import type { WebSocketLike } from './ws-adapter';
|
|
4
|
+
import type { OpenAI } from '../client';
|
|
4
5
|
|
|
5
6
|
const webSocketErrors = new WeakMap<WebSocketLike, Error>();
|
|
6
7
|
|
|
@@ -73,7 +74,7 @@ export type ReconnectingOverrides<Parameters = Record<string, unknown>> =
|
|
|
73
74
|
*/
|
|
74
75
|
export type RawWebSocketData = string | ArrayBufferLike | ArrayBufferView | ArrayBufferView[];
|
|
75
76
|
|
|
76
|
-
interface CredentialedWebSocketOptions {
|
|
77
|
+
export interface CredentialedWebSocketOptions {
|
|
77
78
|
auth?: string | null | undefined;
|
|
78
79
|
followRedirects?: boolean | undefined;
|
|
79
80
|
headers?: object | null | undefined;
|
|
@@ -99,19 +100,57 @@ const REDIRECT_SAFE_WEBSOCKET_HEADERS = new Set([
|
|
|
99
100
|
'x-trace-id',
|
|
100
101
|
]);
|
|
101
102
|
|
|
103
|
+
const WEBSOCKET_METADATA_HEADER_NAMES = new Set([
|
|
104
|
+
'accept',
|
|
105
|
+
'accept-encoding',
|
|
106
|
+
'accept-language',
|
|
107
|
+
'content-type',
|
|
108
|
+
'x-request-id',
|
|
109
|
+
'x-client-request-id',
|
|
110
|
+
'x-correlation-id',
|
|
111
|
+
'traceparent',
|
|
112
|
+
'tracestate',
|
|
113
|
+
'sentry-trace',
|
|
114
|
+
'x-amzn-trace-id',
|
|
115
|
+
'x-cloud-trace-context',
|
|
116
|
+
'x-datadog-trace-id',
|
|
117
|
+
'x-datadog-parent-id',
|
|
118
|
+
'x-datadog-sampling-priority',
|
|
119
|
+
'x-datadog-origin',
|
|
120
|
+
'x-datadog-tags',
|
|
121
|
+
'baggage',
|
|
122
|
+
'b3',
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
// Request and tracing metadata do not authenticate a Responses socket, but remain protected on redirects.
|
|
126
|
+
export const WEBSOCKET_METADATA_HEADERS = {
|
|
127
|
+
has: (name: string, values: readonly unknown[]): boolean =>
|
|
128
|
+
WEBSOCKET_METADATA_HEADER_NAMES.has(name) ||
|
|
129
|
+
name.startsWith('x-b3-') ||
|
|
130
|
+
(name === 'sec-websocket-protocol' &&
|
|
131
|
+
!values.some(
|
|
132
|
+
(value) =>
|
|
133
|
+
typeof value === 'string' &&
|
|
134
|
+
value.split(',').some((protocol) => protocol.trim().startsWith('openai-insecure-api-key.')),
|
|
135
|
+
)),
|
|
136
|
+
};
|
|
137
|
+
|
|
102
138
|
function isWebSocketCredentialHeader(name: string): boolean {
|
|
103
139
|
return !REDIRECT_SAFE_WEBSOCKET_HEADERS.has(name.toLowerCase().split('_').join('-'));
|
|
104
140
|
}
|
|
105
141
|
|
|
106
142
|
/**
|
|
107
143
|
* Snapshots credential values in final socket options before validation and dispatch.
|
|
108
|
-
* Reports potential caller authentication,
|
|
109
|
-
* remains responsible for validating credentials. Noncredential headers are left intact.
|
|
144
|
+
* Reports potential caller authentication, excluding additional metadata when requested.
|
|
145
|
+
* The server remains responsible for validating credentials. Noncredential headers are left intact.
|
|
110
146
|
*/
|
|
111
|
-
export function snapshotWebSocketCredentials(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
147
|
+
export function snapshotWebSocketCredentials(
|
|
148
|
+
options: {
|
|
149
|
+
auth?: unknown;
|
|
150
|
+
headers?: Record<string, unknown> | undefined;
|
|
151
|
+
},
|
|
152
|
+
metadataHeaders?: { has: (name: string, values: readonly unknown[]) => boolean },
|
|
153
|
+
): boolean {
|
|
115
154
|
if (options.auth !== null && options.auth !== undefined) {
|
|
116
155
|
options.auth = String(options.auth);
|
|
117
156
|
}
|
|
@@ -135,10 +174,12 @@ export function snapshotWebSocketCredentials(options: {
|
|
|
135
174
|
}
|
|
136
175
|
headers[name] = snapshot;
|
|
137
176
|
const values = Array.isArray(snapshot) ? snapshot : [snapshot];
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
177
|
+
if (!metadataHeaders?.has(normalizedName, values)) {
|
|
178
|
+
credentials.set(
|
|
179
|
+
name.toLowerCase(),
|
|
180
|
+
values.some((item) => typeof item === 'string' && item.trim().length > 0),
|
|
181
|
+
);
|
|
182
|
+
}
|
|
142
183
|
}
|
|
143
184
|
// Node applies header names case-insensitively, and Authorization overrides Basic auth.
|
|
144
185
|
return (
|
|
@@ -147,6 +188,93 @@ export function snapshotWebSocketCredentials(options: {
|
|
|
147
188
|
);
|
|
148
189
|
}
|
|
149
190
|
|
|
191
|
+
/** Merge transport authentication before explicit caller overrides and header removals. */
|
|
192
|
+
export function mergeWebSocketAuthHeaders<Options extends CredentialedWebSocketOptions>(
|
|
193
|
+
options: Options,
|
|
194
|
+
authHeaders: Record<string, string>,
|
|
195
|
+
removedHeaders: ReadonlySet<string>,
|
|
196
|
+
) {
|
|
197
|
+
const headers = new Map(Object.entries(authHeaders).map(([name, value]) => [name.toLowerCase(), value]));
|
|
198
|
+
for (const name of removedHeaders) {
|
|
199
|
+
headers.delete(name);
|
|
200
|
+
}
|
|
201
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
202
|
+
headers.set(name, value);
|
|
203
|
+
}
|
|
204
|
+
return { ...options, headers: Object.fromEntries(headers) };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Removal sink for one synchronous header-hook call, including legacy one-argument overrides. */
|
|
208
|
+
export const webSocketHeaderRemovals = new WeakMap<
|
|
209
|
+
OpenAI,
|
|
210
|
+
{ removedHeaders: Set<string> | undefined; baseHeaders: Record<string, string> | undefined }
|
|
211
|
+
>();
|
|
212
|
+
const preparedWebSocketHeaders = new WeakMap<
|
|
213
|
+
object,
|
|
214
|
+
{ baseHeaders: Record<string, string> | undefined; transportHeaders: Map<string, boolean> }
|
|
215
|
+
>();
|
|
216
|
+
|
|
217
|
+
/** Build a WebSocket handshake with explicit caller headers applied after the client defaults. */
|
|
218
|
+
export function buildWebSocketOptions<Options extends Pick<CredentialedWebSocketOptions, 'headers'>>(
|
|
219
|
+
client: OpenAI,
|
|
220
|
+
authHeaders: Record<string, string>,
|
|
221
|
+
options: Options | null | undefined,
|
|
222
|
+
removedHeaders?: Set<string>,
|
|
223
|
+
usePreparedHeaders = false,
|
|
224
|
+
) {
|
|
225
|
+
// Capture the base result even through older overrides that forward only one argument.
|
|
226
|
+
const previous = webSocketHeaderRemovals.get(client);
|
|
227
|
+
const prepared = usePreparedHeaders && options ? preparedWebSocketHeaders.get(options) : undefined;
|
|
228
|
+
const context: NonNullable<ReturnType<typeof webSocketHeaderRemovals.get>> = {
|
|
229
|
+
removedHeaders,
|
|
230
|
+
baseHeaders: prepared?.baseHeaders,
|
|
231
|
+
};
|
|
232
|
+
webSocketHeaderRemovals.set(client, context);
|
|
233
|
+
let headers: Map<string, string>;
|
|
234
|
+
try {
|
|
235
|
+
headers = new Map(
|
|
236
|
+
Object.entries(client._buildWebSocketHeaders(authHeaders, removedHeaders)).map(([name, value]) => [
|
|
237
|
+
name.toLowerCase(),
|
|
238
|
+
value,
|
|
239
|
+
]),
|
|
240
|
+
);
|
|
241
|
+
} finally {
|
|
242
|
+
if (previous) {
|
|
243
|
+
webSocketHeaderRemovals.set(client, previous);
|
|
244
|
+
} else {
|
|
245
|
+
webSocketHeaderRemovals.delete(client);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// The first hook output is not a caller override of the final, credentialed hook.
|
|
249
|
+
// Save transport names and explicit nulls separately, then reuse their validated values.
|
|
250
|
+
const transportHeaders = new Map<string, boolean>();
|
|
251
|
+
const currentHeaders = new Map(Object.entries(options?.headers ?? {}));
|
|
252
|
+
const overrides = prepared
|
|
253
|
+
? [...prepared.transportHeaders].map(
|
|
254
|
+
([name, removed]) => [name, removed ? null : currentHeaders.get(name)] as const,
|
|
255
|
+
)
|
|
256
|
+
: currentHeaders;
|
|
257
|
+
for (const [name, value] of overrides) {
|
|
258
|
+
const normalizedName = name.toLowerCase();
|
|
259
|
+
if (value === null) {
|
|
260
|
+
headers.delete(normalizedName);
|
|
261
|
+
removedHeaders?.add(normalizedName);
|
|
262
|
+
transportHeaders.set(normalizedName, true);
|
|
263
|
+
} else if (value !== undefined) {
|
|
264
|
+
headers.set(normalizedName, value);
|
|
265
|
+
removedHeaders?.delete(normalizedName);
|
|
266
|
+
transportHeaders.set(normalizedName, false);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const result = {
|
|
270
|
+
...options,
|
|
271
|
+
headers: Object.fromEntries(headers),
|
|
272
|
+
followRedirects: false,
|
|
273
|
+
};
|
|
274
|
+
preparedWebSocketHeaders.set(result, { baseHeaders: context.baseHeaders, transportHeaders });
|
|
275
|
+
return result;
|
|
276
|
+
}
|
|
277
|
+
|
|
150
278
|
/** Prevents WebSocket redirects from forwarding caller or SDK credentials to another origin. */
|
|
151
279
|
export function protectWebSocketOptionsFromCredentialRedirects<Options extends CredentialedWebSocketOptions>(
|
|
152
280
|
options: Options,
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
import type { AgentOutputFormat, AgentResult } from '../beta/agents/output-format-types';
|
|
1
2
|
import { TurnState } from './turn-state';
|
|
3
|
+
import { agentFormatParser, parseAgentResultPromise } from '../beta/agents/parse-result';
|
|
4
|
+
import { ResultCollection } from '../beta/agents/result-collection';
|
|
2
5
|
import { APIUserAbortError, BadRequestError, OpenAIError } from '../../core/error';
|
|
3
6
|
import type { Stream } from '../../core/streaming';
|
|
4
7
|
import { buildHeaders } from '../../internal/headers';
|
|
5
8
|
import type { RequestOptions } from '../../internal/request-options';
|
|
6
9
|
import { uuid4 } from '../../internal/utils/uuid';
|
|
7
|
-
import {
|
|
10
|
+
import { isObj } from '../../internal/utils/values';
|
|
11
|
+
import { isInputContent } from '../beta/agents/tool-output';
|
|
8
12
|
import type {
|
|
9
13
|
AgentFunctionCallItem,
|
|
10
14
|
AgentFunctionCallOutputParam,
|
|
11
15
|
AgentSessionEvent,
|
|
12
16
|
AgentSessionInputMessageParam,
|
|
13
17
|
AgentSessionInputParam,
|
|
14
|
-
InputContentParam,
|
|
15
18
|
} from '../../resources/beta/agents/agents';
|
|
16
19
|
import type { Sessions } from '../../resources/beta/agents/sessions/sessions';
|
|
17
20
|
|
|
@@ -23,33 +26,19 @@ export type AgentToolHandler = (
|
|
|
23
26
|
) => AgentToolOutput | PromiseLike<AgentToolOutput>;
|
|
24
27
|
|
|
25
28
|
/** Input and optional sequential tool handlers for one turn on an idle session. */
|
|
26
|
-
export
|
|
29
|
+
export type AgentSessionStreamParams<T = never> = {
|
|
30
|
+
/** Beta: parse this turn locally; does not change the existing session schema. */
|
|
31
|
+
outputFormat?: AgentOutputFormat<T>;
|
|
27
32
|
/** User messages, or text normalized to a single user message. Must not be empty. */
|
|
28
33
|
input: string | AgentSessionInputMessageParam[];
|
|
29
34
|
/** Registered functions run after their call event is yielded; unknown functions remain manual. */
|
|
30
35
|
toolHandlers?: Record<string, AgentToolHandler>;
|
|
31
36
|
/** Key for the input submission only; request headers take precedence, case-insensitively. */
|
|
32
37
|
idempotencyKey?: string;
|
|
33
|
-
}
|
|
38
|
+
} & ([T] extends [never] ? unknown : { outputFormat: AgentOutputFormat<T> });
|
|
34
39
|
|
|
35
40
|
type ToolResult = AgentSessionInputParam.SessionInputParamAgentSessionInputToolResult;
|
|
36
41
|
|
|
37
|
-
function isInputContent(value: unknown): value is InputContentParam {
|
|
38
|
-
if (!isObj(value)) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
const content = value;
|
|
42
|
-
let field: string;
|
|
43
|
-
if (content['type'] === 'input_text') {
|
|
44
|
-
field = 'text';
|
|
45
|
-
} else if (content['type'] === 'input_image') {
|
|
46
|
-
field = 'image_url';
|
|
47
|
-
} else {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
return hasOwn(content, 'type') && hasOwn(content, field) && typeof content[field] === 'string';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
42
|
function normalizedOutput(value: unknown): AgentFunctionCallOutputParam | null {
|
|
54
43
|
if (value === null) {
|
|
55
44
|
return null;
|
|
@@ -98,10 +87,13 @@ async function cancelBody(response: Response | undefined): Promise<void> {
|
|
|
98
87
|
* idempotency key. Breaking iteration or calling abort closes local requests;
|
|
99
88
|
* neither cancels the backend turn. No work starts until iteration begins.
|
|
100
89
|
*/
|
|
101
|
-
export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
90
|
+
export class AgentSessionStream<T = never> implements AsyncIterable<AgentSessionEvent> {
|
|
102
91
|
/** Aborts local requests and iteration without cancelling the backend turn. */
|
|
103
92
|
readonly controller = new AbortController();
|
|
104
93
|
#consumed = false;
|
|
94
|
+
#format: AgentOutputFormat<T> | undefined;
|
|
95
|
+
#parsedResult: Promise<AgentResult<T>> | undefined;
|
|
96
|
+
#collection: ResultCollection;
|
|
105
97
|
#stream: Stream<AgentSessionEvent> | undefined;
|
|
106
98
|
#response: Response | undefined;
|
|
107
99
|
#reading = false;
|
|
@@ -116,7 +108,7 @@ export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
|
116
108
|
constructor(
|
|
117
109
|
sessions: Sessions,
|
|
118
110
|
sessionID: string,
|
|
119
|
-
params: AgentSessionStreamParams
|
|
111
|
+
params: AgentSessionStreamParams<T>,
|
|
120
112
|
options?: RequestOptions,
|
|
121
113
|
) {
|
|
122
114
|
const input: AgentSessionInputMessageParam[] =
|
|
@@ -126,6 +118,10 @@ export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
|
126
118
|
if (params.input.length === 0) {
|
|
127
119
|
throw new OpenAIError('input must not be empty');
|
|
128
120
|
}
|
|
121
|
+
this.#format = agentFormatParser<T>(params.outputFormat);
|
|
122
|
+
if (params.outputFormat && !this.#format) {
|
|
123
|
+
throw new OpenAIError('outputFormat must have its own parser function');
|
|
124
|
+
}
|
|
129
125
|
this.#sessions = sessions;
|
|
130
126
|
this.#sessionID = sessionID;
|
|
131
127
|
this.#input = { type: 'agent.session.input.message', input };
|
|
@@ -141,6 +137,11 @@ export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
|
141
137
|
headers.nulls.delete('idempotency-key');
|
|
142
138
|
const { idempotencyKey: _key, ...rest } = options ?? {};
|
|
143
139
|
this.#options = { ...rest, headers };
|
|
140
|
+
this.#collection = new ResultCollection(
|
|
141
|
+
() => this.#iterate(),
|
|
142
|
+
(name) => this.#handlers.has(name),
|
|
143
|
+
sessionID,
|
|
144
|
+
);
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
/** Closes local requests without cancelling the turn; an optional reason becomes the abort error's cause. */
|
|
@@ -158,7 +159,18 @@ export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
|
158
159
|
throw new OpenAIError('An AgentSessionStream can only be consumed once');
|
|
159
160
|
}
|
|
160
161
|
this.#consumed = true;
|
|
161
|
-
return this.#iterate();
|
|
162
|
+
return this.#collection.iterate();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Beta: opt into retaining completed final messages before iterating progress events. */
|
|
166
|
+
withResultCollection(): this {
|
|
167
|
+
this.#collection.enable();
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Beta: drain this turn, dispatch registered tools, and collect its final assistant messages. */
|
|
172
|
+
finalResult(): Promise<AgentResult<T>> {
|
|
173
|
+
return (this.#parsedResult ??= parseAgentResultPromise(this.#collection.finalResult(), this.#format));
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
async *#iterate(): AsyncGenerator<AgentSessionEvent> {
|
|
@@ -268,7 +280,7 @@ export class AgentSessionStream implements AsyncIterable<AgentSessionEvent> {
|
|
|
268
280
|
return error;
|
|
269
281
|
}
|
|
270
282
|
|
|
271
|
-
async #wait<
|
|
283
|
+
async #wait<Value>(action: () => Value | PromiseLike<Value>): Promise<Value> {
|
|
272
284
|
let onAbort: (() => void) | undefined;
|
|
273
285
|
// oxlint-disable-next-line promise/avoid-new -- Bridge the caller's AbortSignal while a handler or registration delay is pending.
|
|
274
286
|
const aborted = new Promise<never>((_resolve, reject) => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AgentOutputFormat, AgentResult } from './output-format-types';
|
|
2
|
+
import type { Stream } from '../../../core/streaming';
|
|
3
|
+
import type { AgentSessionEvent } from '../../../resources/beta/agents/agents';
|
|
4
|
+
import { parseAgentResultPromise } from './parse-result';
|
|
5
|
+
import { ResultCollection } from './result-collection';
|
|
6
|
+
|
|
7
|
+
/** Beta: the original creation stream with optional collection of its initial root turn. */
|
|
8
|
+
export type AgentSessionCreateStream<T = never> = Stream<AgentSessionEvent> & {
|
|
9
|
+
/** Drain through the selected turn's completion and idle event, then return its final messages. */
|
|
10
|
+
finalResult: () => Promise<AgentResult<T>>;
|
|
11
|
+
/** Opt into retaining completed final messages before iterating progress events. */
|
|
12
|
+
withResultCollection: () => AgentSessionCreateStream<T>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Add beta result collection without replacing custom stream instances.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export function withAgentTurnResult<T = never>(
|
|
19
|
+
stream: Stream<AgentSessionEvent>,
|
|
20
|
+
format?: AgentOutputFormat<T>,
|
|
21
|
+
): AgentSessionCreateStream<T> {
|
|
22
|
+
let collection: ResultCollection;
|
|
23
|
+
stream.__betaTransformIterator((source) => {
|
|
24
|
+
collection = new ResultCollection(source, undefined, undefined, stream.controller.signal);
|
|
25
|
+
return () => collection.iterate();
|
|
26
|
+
});
|
|
27
|
+
let parsed: Promise<AgentResult<T>> | undefined;
|
|
28
|
+
const result: AgentSessionCreateStream<T> = Object.assign(stream, {
|
|
29
|
+
finalResult: () => (parsed ??= parseAgentResultPromise(collection.finalResult(), format)),
|
|
30
|
+
withResultCollection: (): AgentSessionCreateStream<T> => {
|
|
31
|
+
collection.enable();
|
|
32
|
+
return result;
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentSession,
|
|
3
|
+
AgentSessionEvent,
|
|
4
|
+
AgentSessionAssistantMessage,
|
|
5
|
+
} from '../../../resources/beta/agents/agents';
|
|
6
|
+
import type { Turn } from '../../../resources/beta/agents/sessions/turns';
|
|
7
|
+
import { AgentTurnResult } from './agent-turn-result';
|
|
8
|
+
import { AgentTurnResultError } from './agent-turn-result-error';
|
|
9
|
+
|
|
10
|
+
/** Accumulates completed items independently of transport and tool execution.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export class AgentTurnResultCollector {
|
|
14
|
+
#sessionID: string | undefined;
|
|
15
|
+
#turn: Turn | undefined;
|
|
16
|
+
#messages = new Map<string, { index: number; message: AgentSessionAssistantMessage }>();
|
|
17
|
+
#requiredActions: AgentSession['required_actions'] = [];
|
|
18
|
+
#sessionFailed = false;
|
|
19
|
+
#terminal = false;
|
|
20
|
+
#idle = false;
|
|
21
|
+
|
|
22
|
+
constructor(sessionID?: string) {
|
|
23
|
+
this.#sessionID = sessionID;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
accept(event: AgentSessionEvent): void {
|
|
27
|
+
if (this.ready) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if ('session' in event) {
|
|
31
|
+
this.#sessionID ??= event.session.id;
|
|
32
|
+
this.#requiredActions = structuredClone(event.session.required_actions ?? []);
|
|
33
|
+
this.#sessionFailed ||= event.type === 'agent.session.failed';
|
|
34
|
+
this.#idle ||= event.type === 'agent.session.idle' && this.#terminal;
|
|
35
|
+
}
|
|
36
|
+
if (event.type === 'agent.session.turn.created' && event.turn.subagent_id === null && !this.#turn) {
|
|
37
|
+
this.#turn = structuredClone(event.turn);
|
|
38
|
+
this.#sessionID = event.turn.session_id;
|
|
39
|
+
}
|
|
40
|
+
let turnID = 'turn_id' in event ? event.turn_id : undefined;
|
|
41
|
+
if ('item' in event) {
|
|
42
|
+
turnID = event.item.turn_id;
|
|
43
|
+
}
|
|
44
|
+
if (!this.#turn || turnID !== this.#turn.id) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.#acceptTurn(event);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#acceptTurn(event: AgentSessionEvent): void {
|
|
51
|
+
if ('turn' in event) {
|
|
52
|
+
this.#turn = structuredClone(event.turn);
|
|
53
|
+
this.#terminal ||=
|
|
54
|
+
event.type === 'agent.session.turn.completed' ||
|
|
55
|
+
event.type === 'agent.session.turn.failed' ||
|
|
56
|
+
event.type === 'agent.session.turn.cancelled';
|
|
57
|
+
}
|
|
58
|
+
this.#acceptOutput(event);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#acceptOutput(event: AgentSessionEvent): void {
|
|
62
|
+
if (
|
|
63
|
+
event.type !== 'agent.session.turn.item.done' ||
|
|
64
|
+
event.item.type !== 'message' ||
|
|
65
|
+
event.item.status !== 'completed' ||
|
|
66
|
+
event.item.phase === 'commentary' ||
|
|
67
|
+
this.#messages.has(event.item.id)
|
|
68
|
+
) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.#messages.set(event.item.id, { index: event.output_index, message: structuredClone(event.item) });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#finalMessages(): AgentSessionAssistantMessage[] {
|
|
75
|
+
return (
|
|
76
|
+
[...this.#messages.values()]
|
|
77
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- Sort a fresh array; ES2020 declarations do not include toSorted.
|
|
78
|
+
.sort((a, b) => a.index - b.index)
|
|
79
|
+
.map(({ message }) => message)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
error(reason: AgentTurnResultError['reason'], cause?: unknown): AgentTurnResultError {
|
|
84
|
+
return new AgentTurnResultError(
|
|
85
|
+
reason,
|
|
86
|
+
this.#sessionID,
|
|
87
|
+
this.#turn,
|
|
88
|
+
this.#finalMessages(),
|
|
89
|
+
this.#requiredActions,
|
|
90
|
+
cause,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
checkAction(canHandle: (name: string) => boolean): void {
|
|
95
|
+
if (this.#sessionFailed || this.#turn?.status === 'failed') {
|
|
96
|
+
throw this.error('failed');
|
|
97
|
+
}
|
|
98
|
+
if (this.#turn?.status === 'cancelled') {
|
|
99
|
+
throw this.error('cancelled');
|
|
100
|
+
}
|
|
101
|
+
if (this.#requiredActions.some((action) => action.type !== 'function_call' || !canHandle(action.name))) {
|
|
102
|
+
throw this.error('requires_action');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get ready(): boolean {
|
|
107
|
+
return this.#terminal && this.#idle;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
release(): void {
|
|
111
|
+
this.#messages.clear();
|
|
112
|
+
this.#requiredActions = [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
finish(): AgentTurnResult {
|
|
116
|
+
this.checkAction(() => this.ready);
|
|
117
|
+
if (!this.#terminal || this.#turn?.status !== 'completed' || !this.#idle) {
|
|
118
|
+
throw this.error('observation');
|
|
119
|
+
}
|
|
120
|
+
return new AgentTurnResult(this.#turn, this.#finalMessages());
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { OpenAIError } from '../../../core/error';
|
|
2
|
+
import type { AgentSession, AgentSessionAssistantMessage } from '../../../resources/beta/agents/agents';
|
|
3
|
+
import type { Turn } from '../../../resources/beta/agents/sessions/turns';
|
|
4
|
+
|
|
5
|
+
/** Beta: final collection failed; partial state is evidence, not a successful result. */
|
|
6
|
+
export class AgentTurnResultError extends OpenAIError {
|
|
7
|
+
override name = 'AgentTurnResultError';
|
|
8
|
+
readonly reason: 'failed' | 'cancelled' | 'requires_action' | 'observation';
|
|
9
|
+
readonly session_id: string | undefined;
|
|
10
|
+
readonly turn: Turn | undefined;
|
|
11
|
+
readonly messages: AgentSessionAssistantMessage[];
|
|
12
|
+
readonly required_actions: AgentSession['required_actions'];
|
|
13
|
+
readonly cause: unknown;
|
|
14
|
+
constructor(
|
|
15
|
+
reason: 'failed' | 'cancelled' | 'requires_action' | 'observation',
|
|
16
|
+
session_id: string | undefined,
|
|
17
|
+
turn: Turn | undefined,
|
|
18
|
+
messages: AgentSessionAssistantMessage[],
|
|
19
|
+
required_actions: AgentSession['required_actions'] = [],
|
|
20
|
+
cause?: unknown,
|
|
21
|
+
) {
|
|
22
|
+
super(`Could not collect the agent turn result: ${reason}`);
|
|
23
|
+
this.reason = reason;
|
|
24
|
+
this.session_id = session_id;
|
|
25
|
+
this.turn = turn;
|
|
26
|
+
this.messages = messages;
|
|
27
|
+
this.required_actions = required_actions;
|
|
28
|
+
this.cause = cause;
|
|
29
|
+
}
|
|
30
|
+
get turn_id(): string | undefined {
|
|
31
|
+
return this.turn?.id;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AgentSessionAssistantMessage } from '../../../resources/beta/agents/agents';
|
|
2
|
+
import type { Turn } from '../../../resources/beta/agents/sessions/turns';
|
|
3
|
+
import { outputText } from '../../agents/output-text';
|
|
4
|
+
|
|
5
|
+
/** Beta: the completed final assistant messages from one hosted root turn. */
|
|
6
|
+
export class AgentTurnResult {
|
|
7
|
+
readonly turn: Turn;
|
|
8
|
+
readonly messages: AgentSessionAssistantMessage[];
|
|
9
|
+
constructor(turn: Turn, messages: AgentSessionAssistantMessage[]) {
|
|
10
|
+
this.turn = turn;
|
|
11
|
+
this.messages = messages;
|
|
12
|
+
}
|
|
13
|
+
get session_id(): string {
|
|
14
|
+
return this.turn.session_id;
|
|
15
|
+
}
|
|
16
|
+
get turn_id(): string {
|
|
17
|
+
return this.turn.id;
|
|
18
|
+
}
|
|
19
|
+
get output_text(): string {
|
|
20
|
+
return this.messages.map(outputText).join('');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { OpenAIError } from '../../../core/error';
|
|
2
|
+
import type { AgentToolHandler } from '../../agents/agent-session-stream';
|
|
3
|
+
import type { AutoParseableResponseTool } from '../../ResponsesParser';
|
|
4
|
+
import type { AgentToolParam } from '../../../resources/beta/agents/agents';
|
|
5
|
+
import { isInputContent } from './tool-output';
|
|
6
|
+
|
|
7
|
+
/** A beta Agents function definition paired with its local, validating handler. */
|
|
8
|
+
export interface AgentFunctionTool {
|
|
9
|
+
/** Model-visible function name, also used as the key in `toolHandlers`. */
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/** Hosted configuration for `agent.tools`; contains no local callback or parser. */
|
|
12
|
+
readonly definition: AgentToolParam.AgentToolConfigParamFunction;
|
|
13
|
+
/** Validates arguments before invoking the callback through the existing stream dispatcher. */
|
|
14
|
+
readonly handler: AgentToolHandler;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Adapts a `zodResponsesFunction` or `standardResponsesFunction` to beta Agents.
|
|
19
|
+
* Pass `definition` to `agent.tools` and register `handler` under `name` in
|
|
20
|
+
* `sessions.stream()`'s `toolHandlers`. Creating a definition does not execute it.
|
|
21
|
+
* The existing dispatcher handles callback results, failures, and submission retries.
|
|
22
|
+
* Scalar results and business-data arrays become JSON text; `undefined` becomes
|
|
23
|
+
* the text `undefined`. Supported text/image content arrays retain their format.
|
|
24
|
+
*
|
|
25
|
+
* @throws {OpenAIError} If the tool has no callback or argument schema.
|
|
26
|
+
*/
|
|
27
|
+
export function functionTool<Arguments>(
|
|
28
|
+
tool: AutoParseableResponseTool<{ name: string; arguments: Arguments }>,
|
|
29
|
+
): AgentFunctionTool {
|
|
30
|
+
const execute = tool.$callback;
|
|
31
|
+
const parse = tool.$parseRaw;
|
|
32
|
+
if (!execute || !tool.parameters) {
|
|
33
|
+
throw new OpenAIError('Agents function tools require a callback and argument schema');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
name: tool.name,
|
|
37
|
+
definition: {
|
|
38
|
+
type: 'function',
|
|
39
|
+
name: tool.name,
|
|
40
|
+
description: tool.description ?? '',
|
|
41
|
+
parameters: tool.parameters,
|
|
42
|
+
...(tool.defer_loading === undefined ? {} : { defer_loading: tool.defer_loading }),
|
|
43
|
+
},
|
|
44
|
+
handler: async (arguments_) => {
|
|
45
|
+
const result: unknown = await execute(parse(JSON.stringify(arguments_)));
|
|
46
|
+
if (Array.isArray(result)) {
|
|
47
|
+
return result.length > 0 && result.every(isInputContent) ? result : JSON.stringify(result);
|
|
48
|
+
}
|
|
49
|
+
// oxlint-disable-next-line anti-slop/no-runtime-typeof -- Existing schema-tool callbacks return arbitrary application values; adapt them to the Agents dispatcher's output contract.
|
|
50
|
+
if (typeof result === 'object' || typeof result === 'string') {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
const text = result === undefined ? 'undefined' : JSON.stringify(result);
|
|
54
|
+
if (text === undefined) {
|
|
55
|
+
throw new OpenAIError('Tool output must be JSON serializable');
|
|
56
|
+
}
|
|
57
|
+
return text;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TextFormatParam } from '../../../resources/beta/agents/agents';
|
|
2
|
+
import type { AgentTurnResult } from './agent-turn-result';
|
|
3
|
+
import type { ParsedAgentTurnResult } from './parsed-agent-turn-result';
|
|
4
|
+
|
|
5
|
+
/** Beta: an Agents JSON Schema format with a local output validator. */
|
|
6
|
+
export interface AgentOutputFormat<T> extends TextFormatParam.TextFormatParamJSONSchema {
|
|
7
|
+
/** SDK-only parser; omitted from serialized requests. */
|
|
8
|
+
$parseRaw: (text: string) => T;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Beta: raw results remain unchanged unless a typed format is supplied. */
|
|
12
|
+
export type AgentResult<T> = [T] extends [never] ? AgentTurnResult : ParsedAgentTurnResult<T>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentOutputFormat } from './output-format-types';
|
|
2
|
+
|
|
3
|
+
import type { JSONSchema } from '../../jsonschema';
|
|
4
|
+
|
|
5
|
+
export type { AgentOutputFormat, AgentResult } from './output-format-types';
|
|
6
|
+
|
|
7
|
+
export { ParsedAgentTurnResult } from './parsed-agent-turn-result';
|
|
8
|
+
export { AgentOutputParseError } from './output-parse-error';
|
|
9
|
+
|
|
10
|
+
/** Beta: bind a JSON schema to its local output parser; the API validates schema support. */
|
|
11
|
+
export function agentOutputFormat<T>(schema: JSONSchema, parse: (text: string) => T): AgentOutputFormat<T> {
|
|
12
|
+
// Keep spread-compatible parsing without exposing caller-owned serialization hooks.
|
|
13
|
+
const parser = Object.defineProperty((text: string) => parse(text), 'toJSON', {
|
|
14
|
+
value: () => {
|
|
15
|
+
/* Parser metadata is omitted from JSON requests. */
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
// SAFETY: The API schema type exposes JSON Schema keywords as a record; preserve the supplied schema unchanged.
|
|
19
|
+
return { type: 'json_schema', schema: schema as AgentOutputFormat<T>['schema'], $parseRaw: parser };
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OpenAIError } from '../../../core/error';
|
|
2
|
+
import type { AgentTurnResult } from './agent-turn-result';
|
|
3
|
+
|
|
4
|
+
/** Beta: hosted execution completed, but local output parsing failed. */
|
|
5
|
+
export class AgentOutputParseError extends OpenAIError {
|
|
6
|
+
override name = 'AgentOutputParseError';
|
|
7
|
+
readonly #rawResult: AgentTurnResult;
|
|
8
|
+
constructor(result: AgentTurnResult) {
|
|
9
|
+
super('The completed agent output could not be parsed');
|
|
10
|
+
this.#rawResult = result;
|
|
11
|
+
}
|
|
12
|
+
/** Inspect the completed output explicitly; ordinary error logging omits it. */
|
|
13
|
+
get raw_result(): AgentTurnResult {
|
|
14
|
+
return this.#rawResult;
|
|
15
|
+
}
|
|
16
|
+
}
|