openai 7.5.0 → 7.6.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 +105 -0
- package/README.md +46 -2
- package/auth/index.d.mts +1 -1
- package/auth/index.d.mts.map +1 -1
- package/auth/index.d.ts +1 -1
- package/auth/index.d.ts.map +1 -1
- package/auth/index.js.map +1 -1
- package/auth/index.mjs.map +1 -1
- package/auth/subject-token-providers.d.mts.map +1 -1
- package/auth/subject-token-providers.d.ts.map +1 -1
- package/auth/subject-token-providers.js +176 -4
- package/auth/subject-token-providers.js.map +1 -1
- package/auth/subject-token-providers.mjs +176 -4
- package/auth/subject-token-providers.mjs.map +1 -1
- package/auth/types.d.mts +17 -0
- package/auth/types.d.mts.map +1 -1
- package/auth/types.d.ts +17 -0
- package/auth/types.d.ts.map +1 -1
- package/auth/workload-identity-auth.d.mts.map +1 -1
- package/auth/workload-identity-auth.d.ts.map +1 -1
- package/auth/workload-identity-auth.js +80 -7
- package/auth/workload-identity-auth.js.map +1 -1
- package/auth/workload-identity-auth.mjs +80 -7
- package/auth/workload-identity-auth.mjs.map +1 -1
- package/auth/x509-transport.d.mts +5 -0
- package/auth/x509-transport.d.mts.map +1 -0
- package/auth/x509-transport.d.ts +5 -0
- package/auth/x509-transport.d.ts.map +1 -0
- package/auth/x509-transport.js +39 -0
- package/auth/x509-transport.js.map +1 -0
- package/auth/x509-transport.mjs +36 -0
- package/auth/x509-transport.mjs.map +1 -0
- package/azure.d.mts +11 -2
- package/azure.d.mts.map +1 -1
- package/azure.d.ts +11 -2
- package/azure.d.ts.map +1 -1
- package/azure.js +7 -1
- package/azure.js.map +1 -1
- package/azure.mjs +7 -1
- package/azure.mjs.map +1 -1
- package/bedrock.d.mts +6 -2
- package/bedrock.d.mts.map +1 -1
- package/bedrock.d.ts +6 -2
- package/bedrock.d.ts.map +1 -1
- package/bedrock.js +34 -4
- package/bedrock.js.map +1 -1
- package/bedrock.mjs +35 -5
- package/bedrock.mjs.map +1 -1
- package/beta/realtime/internal-base.d.mts +2 -0
- package/beta/realtime/internal-base.d.mts.map +1 -1
- package/beta/realtime/internal-base.d.ts +2 -0
- package/beta/realtime/internal-base.d.ts.map +1 -1
- package/beta/realtime/internal-base.js +15 -0
- package/beta/realtime/internal-base.js.map +1 -1
- package/beta/realtime/internal-base.mjs +14 -0
- package/beta/realtime/internal-base.mjs.map +1 -1
- package/beta/realtime/websocket.d.mts +11 -5
- package/beta/realtime/websocket.d.mts.map +1 -1
- package/beta/realtime/websocket.d.ts +11 -5
- package/beta/realtime/websocket.d.ts.map +1 -1
- package/beta/realtime/websocket.js +106 -31
- package/beta/realtime/websocket.js.map +1 -1
- package/beta/realtime/websocket.mjs +107 -32
- package/beta/realtime/websocket.mjs.map +1 -1
- package/beta/realtime/ws.d.mts +0 -2
- package/beta/realtime/ws.d.mts.map +1 -1
- package/beta/realtime/ws.d.ts +0 -2
- package/beta/realtime/ws.d.ts.map +1 -1
- package/beta/realtime/ws.js +24 -5
- package/beta/realtime/ws.js.map +1 -1
- package/beta/realtime/ws.mjs +25 -6
- package/beta/realtime/ws.mjs.map +1 -1
- package/client.d.mts +17 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +17 -2
- package/client.d.ts.map +1 -1
- package/client.js +422 -70
- package/client.js.map +1 -1
- package/client.mjs +423 -71
- package/client.mjs.map +1 -1
- package/core/EventEmitter.d.mts.map +1 -1
- package/core/EventEmitter.d.ts.map +1 -1
- package/core/EventEmitter.js +67 -9
- package/core/EventEmitter.js.map +1 -1
- package/core/EventEmitter.mjs +68 -10
- package/core/EventEmitter.mjs.map +1 -1
- package/core/streaming.d.mts +1 -0
- package/core/streaming.d.mts.map +1 -1
- package/core/streaming.d.ts +1 -0
- package/core/streaming.d.ts.map +1 -1
- package/core/streaming.js +58 -19
- package/core/streaming.js.map +1 -1
- package/core/streaming.mjs +58 -19
- package/core/streaming.mjs.map +1 -1
- package/helpers/audio.d.mts +5 -5
- package/helpers/audio.d.mts.map +1 -1
- package/helpers/audio.d.ts +5 -5
- package/helpers/audio.d.ts.map +1 -1
- package/helpers/audio.js +93 -22
- package/helpers/audio.js.map +1 -1
- package/helpers/audio.mjs +93 -22
- package/helpers/audio.mjs.map +1 -1
- package/helpers/standard-schema.d.mts.map +1 -1
- package/helpers/standard-schema.d.ts.map +1 -1
- package/helpers/standard-schema.js +34 -14
- package/helpers/standard-schema.js.map +1 -1
- package/helpers/standard-schema.mjs +35 -15
- package/helpers/standard-schema.mjs.map +1 -1
- package/helpers/zod-v3-strict-schema.d.mts +7 -0
- package/helpers/zod-v3-strict-schema.d.mts.map +1 -0
- package/helpers/zod-v3-strict-schema.d.ts +7 -0
- package/helpers/zod-v3-strict-schema.d.ts.map +1 -0
- package/helpers/zod-v3-strict-schema.js +403 -0
- package/helpers/zod-v3-strict-schema.js.map +1 -0
- package/helpers/zod-v3-strict-schema.mjs +399 -0
- package/helpers/zod-v3-strict-schema.mjs.map +1 -0
- package/helpers/zod.d.mts.map +1 -1
- package/helpers/zod.d.ts.map +1 -1
- package/helpers/zod.js +11 -3
- package/helpers/zod.js.map +1 -1
- package/helpers/zod.mjs +12 -4
- package/helpers/zod.mjs.map +1 -1
- package/index.d.mts +1 -1
- package/index.d.mts.map +1 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js.map +1 -1
- package/index.mjs.map +1 -1
- package/internal/assistant-stream-delta.d.mts.map +1 -1
- package/internal/assistant-stream-delta.d.ts.map +1 -1
- package/internal/assistant-stream-delta.js +28 -8
- package/internal/assistant-stream-delta.js.map +1 -1
- package/internal/assistant-stream-delta.mjs +28 -8
- package/internal/assistant-stream-delta.mjs.map +1 -1
- package/internal/auth/x509-token-exchange.d.mts +16 -0
- package/internal/auth/x509-token-exchange.d.mts.map +1 -0
- package/internal/auth/x509-token-exchange.d.ts +16 -0
- package/internal/auth/x509-token-exchange.d.ts.map +1 -0
- package/internal/auth/x509-token-exchange.js +246 -0
- package/internal/auth/x509-token-exchange.js.map +1 -0
- package/internal/auth/x509-token-exchange.mjs +243 -0
- package/internal/auth/x509-token-exchange.mjs.map +1 -0
- package/internal/auth/x509-transport-capability.d.mts +37 -0
- package/internal/auth/x509-transport-capability.d.mts.map +1 -0
- package/internal/auth/x509-transport-capability.d.ts +37 -0
- package/internal/auth/x509-transport-capability.d.ts.map +1 -0
- package/internal/auth/x509-transport-capability.js +169 -0
- package/internal/auth/x509-transport-capability.js.map +1 -0
- package/internal/auth/x509-transport-capability.mjs +164 -0
- package/internal/auth/x509-transport-capability.mjs.map +1 -0
- package/internal/auth/x509-transport-registry.d.mts +63 -0
- package/internal/auth/x509-transport-registry.d.mts.map +1 -0
- package/internal/auth/x509-transport-registry.d.ts +63 -0
- package/internal/auth/x509-transport-registry.d.ts.map +1 -0
- package/internal/auth/x509-transport-registry.js +53 -0
- package/internal/auth/x509-transport-registry.js.map +1 -0
- package/internal/auth/x509-transport-registry.mjs +48 -0
- package/internal/auth/x509-transport-registry.mjs.map +1 -0
- package/internal/auth/x509-transport-state-browser.d.mts +21 -0
- package/internal/auth/x509-transport-state-browser.d.mts.map +1 -0
- package/internal/auth/x509-transport-state-browser.d.ts +21 -0
- package/internal/auth/x509-transport-state-browser.d.ts.map +1 -0
- package/internal/auth/x509-transport-state-browser.js +30 -0
- package/internal/auth/x509-transport-state-browser.js.map +1 -0
- package/internal/auth/x509-transport-state-browser.mjs +27 -0
- package/internal/auth/x509-transport-state-browser.mjs.map +1 -0
- package/internal/auth/x509-transport-state.cjs +30 -0
- package/internal/auth/x509-transport-state.cjs.map +1 -0
- package/internal/auth/x509-transport-state.d.cts +21 -0
- package/internal/auth/x509-transport-state.d.cts.map +1 -0
- package/internal/auth/x509-workload-identity-auth.d.mts +128 -0
- package/internal/auth/x509-workload-identity-auth.d.mts.map +1 -0
- package/internal/auth/x509-workload-identity-auth.d.ts +128 -0
- package/internal/auth/x509-workload-identity-auth.d.ts.map +1 -0
- package/internal/auth/x509-workload-identity-auth.js +767 -0
- package/internal/auth/x509-workload-identity-auth.js.map +1 -0
- package/internal/auth/x509-workload-identity-auth.mjs +757 -0
- package/internal/auth/x509-workload-identity-auth.mjs.map +1 -0
- package/internal/bedrock.d.mts +2 -0
- package/internal/bedrock.d.mts.map +1 -1
- package/internal/bedrock.d.ts +2 -0
- package/internal/bedrock.d.ts.map +1 -1
- package/internal/bedrock.js +169 -5
- package/internal/bedrock.js.map +1 -1
- package/internal/bedrock.mjs +168 -5
- package/internal/bedrock.mjs.map +1 -1
- package/internal/data-residency.d.mts +12 -0
- package/internal/data-residency.d.mts.map +1 -0
- package/internal/data-residency.d.ts +12 -0
- package/internal/data-residency.d.ts.map +1 -0
- package/internal/data-residency.js +34 -0
- package/internal/data-residency.js.map +1 -0
- package/internal/data-residency.mjs +30 -0
- package/internal/data-residency.mjs.map +1 -0
- package/internal/multipart-encoding.d.mts +8 -0
- package/internal/multipart-encoding.d.mts.map +1 -0
- package/internal/multipart-encoding.d.ts +8 -0
- package/internal/multipart-encoding.d.ts.map +1 -0
- package/internal/multipart-encoding.js +51 -0
- package/internal/multipart-encoding.js.map +1 -0
- package/internal/multipart-encoding.mjs +48 -0
- package/internal/multipart-encoding.mjs.map +1 -0
- package/internal/qs/utils.d.mts.map +1 -1
- package/internal/qs/utils.d.ts.map +1 -1
- package/internal/qs/utils.js +307 -10
- package/internal/qs/utils.js.map +1 -1
- package/internal/qs/utils.mjs +307 -10
- package/internal/qs/utils.mjs.map +1 -1
- package/internal/request-options.d.mts +7 -0
- package/internal/request-options.d.mts.map +1 -1
- package/internal/request-options.d.ts +7 -0
- package/internal/request-options.d.ts.map +1 -1
- package/internal/request-options.js +43 -1
- package/internal/request-options.js.map +1 -1
- package/internal/request-options.mjs +42 -1
- package/internal/request-options.mjs.map +1 -1
- package/internal/responses/canonical-output-text.js +3 -3
- package/internal/responses/canonical-output-text.js.map +1 -1
- package/internal/responses/canonical-output-text.mjs +3 -3
- package/internal/responses/canonical-output-text.mjs.map +1 -1
- package/internal/responses/response-accumulator.d.mts +1 -1
- package/internal/responses/response-accumulator.d.mts.map +1 -1
- package/internal/responses/response-accumulator.d.ts +1 -1
- package/internal/responses/response-accumulator.d.ts.map +1 -1
- package/internal/responses/response-accumulator.js +331 -25
- package/internal/responses/response-accumulator.js.map +1 -1
- package/internal/responses/response-accumulator.mjs +331 -25
- package/internal/responses/response-accumulator.mjs.map +1 -1
- package/internal/tslib.js +6 -0
- package/internal/tslib.mjs +6 -1
- package/internal/uploads.d.mts +10 -6
- package/internal/uploads.d.mts.map +1 -1
- package/internal/uploads.d.ts +10 -6
- package/internal/uploads.d.ts.map +1 -1
- package/internal/uploads.js +65 -24
- package/internal/uploads.js.map +1 -1
- package/internal/uploads.mjs +65 -24
- package/internal/uploads.mjs.map +1 -1
- package/internal/utils/env.d.mts.map +1 -1
- package/internal/utils/env.d.ts.map +1 -1
- package/internal/utils/env.js +9 -4
- package/internal/utils/env.js.map +1 -1
- package/internal/utils/env.mjs +9 -4
- package/internal/utils/env.mjs.map +1 -1
- package/internal/ws.d.mts.map +1 -1
- package/internal/ws.d.ts.map +1 -1
- package/internal/ws.js +23 -1
- package/internal/ws.js.map +1 -1
- package/internal/ws.mjs +23 -1
- package/internal/ws.mjs.map +1 -1
- package/lib/AbstractChatCompletionRunner.d.mts.map +1 -1
- package/lib/AbstractChatCompletionRunner.d.ts.map +1 -1
- package/lib/AbstractChatCompletionRunner.js +32 -7
- package/lib/AbstractChatCompletionRunner.js.map +1 -1
- package/lib/AbstractChatCompletionRunner.mjs +34 -9
- package/lib/AbstractChatCompletionRunner.mjs.map +1 -1
- package/lib/AssistantStream.d.mts.map +1 -1
- package/lib/AssistantStream.d.ts.map +1 -1
- package/lib/AssistantStream.js +211 -23
- package/lib/AssistantStream.js.map +1 -1
- package/lib/AssistantStream.mjs +211 -23
- package/lib/AssistantStream.mjs.map +1 -1
- package/lib/ChatCompletionStream.d.mts +1 -1
- package/lib/ChatCompletionStream.d.mts.map +1 -1
- package/lib/ChatCompletionStream.d.ts +1 -1
- package/lib/ChatCompletionStream.d.ts.map +1 -1
- package/lib/ChatCompletionStream.js +1118 -67
- package/lib/ChatCompletionStream.js.map +1 -1
- package/lib/ChatCompletionStream.mjs +1119 -68
- package/lib/ChatCompletionStream.mjs.map +1 -1
- package/lib/EventEmitter.d.mts.map +1 -1
- package/lib/EventEmitter.d.ts.map +1 -1
- package/lib/EventEmitter.js +67 -9
- package/lib/EventEmitter.js.map +1 -1
- package/lib/EventEmitter.mjs +68 -10
- package/lib/EventEmitter.mjs.map +1 -1
- package/lib/EventStream.d.mts +4 -0
- package/lib/EventStream.d.mts.map +1 -1
- package/lib/EventStream.d.ts +4 -0
- package/lib/EventStream.d.ts.map +1 -1
- package/lib/EventStream.js +1096 -11
- package/lib/EventStream.js.map +1 -1
- package/lib/EventStream.mjs +1097 -12
- package/lib/EventStream.mjs.map +1 -1
- package/lib/ResponsesParser.d.mts.map +1 -1
- package/lib/ResponsesParser.d.ts.map +1 -1
- package/lib/ResponsesParser.js +1 -1
- package/lib/ResponsesParser.js.map +1 -1
- package/lib/ResponsesParser.mjs +1 -1
- package/lib/ResponsesParser.mjs.map +1 -1
- package/lib/Util.d.mts +2 -0
- package/lib/Util.d.mts.map +1 -1
- package/lib/Util.d.ts +2 -0
- package/lib/Util.d.ts.map +1 -1
- package/lib/Util.js +7 -4
- package/lib/Util.js.map +1 -1
- package/lib/Util.mjs +7 -4
- package/lib/Util.mjs.map +1 -1
- package/lib/assistant-run-polling.d.mts +12 -0
- package/lib/assistant-run-polling.d.mts.map +1 -0
- package/lib/assistant-run-polling.d.ts +12 -0
- package/lib/assistant-run-polling.d.ts.map +1 -0
- package/lib/assistant-run-polling.js +17 -0
- package/lib/assistant-run-polling.js.map +1 -0
- package/lib/assistant-run-polling.mjs +14 -0
- package/lib/assistant-run-polling.mjs.map +1 -0
- package/lib/embeddings.d.mts +18 -0
- package/lib/embeddings.d.mts.map +1 -0
- package/lib/embeddings.d.ts +18 -0
- package/lib/embeddings.d.ts.map +1 -0
- package/lib/embeddings.js +50 -0
- package/lib/embeddings.js.map +1 -0
- package/lib/embeddings.mjs +47 -0
- package/lib/embeddings.mjs.map +1 -0
- package/lib/file-processing.d.mts +10 -0
- package/lib/file-processing.d.mts.map +1 -0
- package/lib/file-processing.d.ts +10 -0
- package/lib/file-processing.d.ts.map +1 -0
- package/lib/file-processing.js +30 -0
- package/lib/file-processing.js.map +1 -0
- package/lib/file-processing.mjs +27 -0
- package/lib/file-processing.mjs.map +1 -0
- package/lib/parser.d.mts.map +1 -1
- package/lib/parser.d.ts.map +1 -1
- package/lib/parser.js +16 -4
- package/lib/parser.js.map +1 -1
- package/lib/parser.mjs +16 -4
- package/lib/parser.mjs.map +1 -1
- package/lib/polling.d.mts +20 -0
- package/lib/polling.d.mts.map +1 -0
- package/lib/polling.d.ts +20 -0
- package/lib/polling.d.ts.map +1 -0
- package/lib/polling.js +130 -0
- package/lib/polling.js.map +1 -0
- package/lib/polling.mjs +127 -0
- package/lib/polling.mjs.map +1 -0
- package/lib/responses/ResponseStream.d.mts.map +1 -1
- package/lib/responses/ResponseStream.d.ts.map +1 -1
- package/lib/responses/ResponseStream.js +21 -11
- package/lib/responses/ResponseStream.js.map +1 -1
- package/lib/responses/ResponseStream.mjs +21 -11
- package/lib/responses/ResponseStream.mjs.map +1 -1
- package/lib/vector-store-polling.d.mts +22 -0
- package/lib/vector-store-polling.d.mts.map +1 -0
- package/lib/vector-store-polling.d.ts +22 -0
- package/lib/vector-store-polling.d.ts.map +1 -0
- package/lib/vector-store-polling.js +24 -0
- package/lib/vector-store-polling.js.map +1 -0
- package/lib/vector-store-polling.mjs +20 -0
- package/lib/vector-store-polling.mjs.map +1 -0
- package/lib/vector-store-upload.d.mts +17 -0
- package/lib/vector-store-upload.d.mts.map +1 -0
- package/lib/vector-store-upload.d.ts +17 -0
- package/lib/vector-store-upload.d.ts.map +1 -0
- package/lib/vector-store-upload.js +37 -0
- package/lib/vector-store-upload.js.map +1 -0
- package/lib/vector-store-upload.mjs +34 -0
- package/lib/vector-store-upload.mjs.map +1 -0
- package/lib/webhook-signature.d.mts +15 -0
- package/lib/webhook-signature.d.mts.map +1 -0
- package/lib/webhook-signature.d.ts +15 -0
- package/lib/webhook-signature.d.ts.map +1 -0
- package/lib/webhook-signature.js +125 -0
- package/lib/webhook-signature.js.map +1 -0
- package/lib/webhook-signature.mjs +121 -0
- package/lib/webhook-signature.mjs.map +1 -0
- package/package.json +14 -1
- package/realtime/internal-base.d.mts +2 -0
- package/realtime/internal-base.d.mts.map +1 -1
- package/realtime/internal-base.d.ts +2 -0
- package/realtime/internal-base.d.ts.map +1 -1
- package/realtime/internal-base.js +15 -0
- package/realtime/internal-base.js.map +1 -1
- package/realtime/internal-base.mjs +14 -0
- package/realtime/internal-base.mjs.map +1 -1
- package/realtime/websocket.d.mts +3 -2
- package/realtime/websocket.d.mts.map +1 -1
- package/realtime/websocket.d.ts +3 -2
- package/realtime/websocket.d.ts.map +1 -1
- package/realtime/websocket.js +90 -26
- package/realtime/websocket.js.map +1 -1
- package/realtime/websocket.mjs +91 -27
- package/realtime/websocket.mjs.map +1 -1
- package/realtime/ws.d.mts.map +1 -1
- package/realtime/ws.d.ts.map +1 -1
- package/realtime/ws.js +9 -1
- package/realtime/ws.js.map +1 -1
- package/realtime/ws.mjs +10 -2
- package/realtime/ws.mjs.map +1 -1
- package/resources/admin/organization/index.d.mts +2 -2
- package/resources/admin/organization/index.d.mts.map +1 -1
- package/resources/admin/organization/index.d.ts +2 -2
- package/resources/admin/organization/index.d.ts.map +1 -1
- package/resources/admin/organization/index.js.map +1 -1
- package/resources/admin/organization/index.mjs.map +1 -1
- package/resources/admin/organization/organization.d.mts +4 -4
- package/resources/admin/organization/organization.d.mts.map +1 -1
- package/resources/admin/organization/organization.d.ts +4 -4
- package/resources/admin/organization/organization.d.ts.map +1 -1
- package/resources/admin/organization/organization.js.map +1 -1
- package/resources/admin/organization/organization.mjs.map +1 -1
- package/resources/admin/organization/projects/index.d.mts +1 -1
- package/resources/admin/organization/projects/index.d.mts.map +1 -1
- package/resources/admin/organization/projects/index.d.ts +1 -1
- package/resources/admin/organization/projects/index.d.ts.map +1 -1
- package/resources/admin/organization/projects/index.js.map +1 -1
- package/resources/admin/organization/projects/index.mjs.map +1 -1
- package/resources/admin/organization/projects/projects.d.mts +22 -5
- package/resources/admin/organization/projects/projects.d.mts.map +1 -1
- package/resources/admin/organization/projects/projects.d.ts +22 -5
- package/resources/admin/organization/projects/projects.d.ts.map +1 -1
- package/resources/admin/organization/projects/projects.js.map +1 -1
- package/resources/admin/organization/projects/projects.mjs.map +1 -1
- package/resources/admin/organization/usage.d.mts +62 -1
- package/resources/admin/organization/usage.d.mts.map +1 -1
- package/resources/admin/organization/usage.d.ts +62 -1
- package/resources/admin/organization/usage.d.ts.map +1 -1
- package/resources/admin/organization/usage.js.map +1 -1
- package/resources/admin/organization/usage.mjs.map +1 -1
- package/resources/beta/responses/internal-base.d.mts.map +1 -1
- package/resources/beta/responses/internal-base.d.ts.map +1 -1
- package/resources/beta/responses/internal-base.js +2 -0
- package/resources/beta/responses/internal-base.js.map +1 -1
- package/resources/beta/responses/internal-base.mjs +2 -0
- package/resources/beta/responses/internal-base.mjs.map +1 -1
- package/resources/beta/responses/responses.d.mts +9 -12
- package/resources/beta/responses/responses.d.mts.map +1 -1
- package/resources/beta/responses/responses.d.ts +9 -12
- package/resources/beta/responses/responses.d.ts.map +1 -1
- package/resources/beta/responses/responses.js.map +1 -1
- package/resources/beta/responses/responses.mjs.map +1 -1
- package/resources/beta/threads/runs/index.d.mts +1 -1
- package/resources/beta/threads/runs/index.d.mts.map +1 -1
- package/resources/beta/threads/runs/index.d.ts +1 -1
- package/resources/beta/threads/runs/index.d.ts.map +1 -1
- package/resources/beta/threads/runs/runs.d.mts.map +1 -1
- package/resources/beta/threads/runs/runs.d.ts.map +1 -1
- package/resources/beta/threads/runs/runs.js +2 -43
- package/resources/beta/threads/runs/runs.js.map +1 -1
- package/resources/beta/threads/runs/runs.mjs +2 -43
- package/resources/beta/threads/runs/runs.mjs.map +1 -1
- package/resources/chat/completions/completions.d.mts +6 -0
- package/resources/chat/completions/completions.d.mts.map +1 -1
- package/resources/chat/completions/completions.d.ts +6 -0
- package/resources/chat/completions/completions.d.ts.map +1 -1
- package/resources/chat/completions/completions.js.map +1 -1
- package/resources/chat/completions/completions.mjs.map +1 -1
- package/resources/embeddings.d.mts.map +1 -1
- package/resources/embeddings.d.ts.map +1 -1
- package/resources/embeddings.js +2 -36
- package/resources/embeddings.js.map +1 -1
- package/resources/embeddings.mjs +2 -36
- package/resources/embeddings.mjs.map +1 -1
- package/resources/files.d.mts.map +1 -1
- package/resources/files.d.ts.map +1 -1
- package/resources/files.js +2 -15
- package/resources/files.js.map +1 -1
- package/resources/files.mjs +2 -15
- package/resources/files.mjs.map +1 -1
- package/resources/images.d.mts +12 -22
- package/resources/images.d.mts.map +1 -1
- package/resources/images.d.ts +12 -22
- package/resources/images.d.ts.map +1 -1
- package/resources/realtime/calls.d.mts +23 -1
- package/resources/realtime/calls.d.mts.map +1 -1
- package/resources/realtime/calls.d.ts +23 -1
- package/resources/realtime/calls.d.ts.map +1 -1
- package/resources/realtime/calls.js +24 -0
- package/resources/realtime/calls.js.map +1 -1
- package/resources/realtime/calls.mjs +24 -0
- package/resources/realtime/calls.mjs.map +1 -1
- package/resources/realtime/index.d.mts +1 -1
- package/resources/realtime/index.d.mts.map +1 -1
- package/resources/realtime/index.d.ts +1 -1
- package/resources/realtime/index.d.ts.map +1 -1
- package/resources/realtime/index.js.map +1 -1
- package/resources/realtime/index.mjs +1 -1
- package/resources/realtime/index.mjs.map +1 -1
- package/resources/realtime/realtime.d.mts +5 -4
- package/resources/realtime/realtime.d.mts.map +1 -1
- package/resources/realtime/realtime.d.ts +5 -4
- package/resources/realtime/realtime.d.ts.map +1 -1
- package/resources/realtime/realtime.js.map +1 -1
- package/resources/realtime/realtime.mjs.map +1 -1
- package/resources/responses/internal-base.d.mts.map +1 -1
- package/resources/responses/internal-base.d.ts.map +1 -1
- package/resources/responses/internal-base.js +2 -0
- package/resources/responses/internal-base.js.map +1 -1
- package/resources/responses/internal-base.mjs +2 -0
- package/resources/responses/internal-base.mjs.map +1 -1
- package/resources/responses/responses.d.mts +9 -12
- package/resources/responses/responses.d.mts.map +1 -1
- package/resources/responses/responses.d.ts +9 -12
- package/resources/responses/responses.d.ts.map +1 -1
- package/resources/responses/responses.js.map +1 -1
- package/resources/responses/responses.mjs.map +1 -1
- package/resources/vector-stores/file-batches.d.mts.map +1 -1
- package/resources/vector-stores/file-batches.d.ts.map +1 -1
- package/resources/vector-stores/file-batches.js +4 -61
- package/resources/vector-stores/file-batches.js.map +1 -1
- package/resources/vector-stores/file-batches.mjs +4 -61
- package/resources/vector-stores/file-batches.mjs.map +1 -1
- package/resources/vector-stores/files.d.mts +1 -1
- package/resources/vector-stores/files.d.mts.map +1 -1
- package/resources/vector-stores/files.d.ts +1 -1
- package/resources/vector-stores/files.d.ts.map +1 -1
- package/resources/vector-stores/files.js +2 -35
- package/resources/vector-stores/files.js.map +1 -1
- package/resources/vector-stores/files.mjs +2 -35
- package/resources/vector-stores/files.mjs.map +1 -1
- package/resources/webhooks/webhooks.d.mts.map +1 -1
- package/resources/webhooks/webhooks.d.ts.map +1 -1
- package/resources/webhooks/webhooks.js +5 -43
- package/resources/webhooks/webhooks.js.map +1 -1
- package/resources/webhooks/webhooks.mjs +5 -43
- package/resources/webhooks/webhooks.mjs.map +1 -1
- package/src/auth/index.ts +6 -1
- package/src/auth/subject-token-providers.ts +196 -4
- package/src/auth/types.ts +24 -0
- package/src/auth/workload-identity-auth.ts +104 -7
- package/src/auth/x509-transport.ts +49 -0
- package/src/azure.ts +22 -1
- package/src/bedrock.ts +49 -5
- package/src/beta/realtime/internal-base.ts +15 -0
- package/src/beta/realtime/websocket.ts +148 -40
- package/src/beta/realtime/ws.ts +31 -13
- package/src/client.ts +536 -92
- package/src/core/EventEmitter.ts +91 -7
- package/src/core/streaming.ts +71 -20
- package/src/helpers/audio.ts +93 -22
- package/src/helpers/standard-schema.ts +50 -16
- package/src/helpers/zod-v3-strict-schema.ts +514 -0
- package/src/helpers/zod.ts +17 -4
- package/src/index.ts +1 -1
- package/src/internal/assistant-stream-delta.ts +33 -10
- package/src/internal/auth/x509-token-exchange.ts +310 -0
- package/src/internal/auth/x509-transport-capability.ts +219 -0
- package/src/internal/auth/x509-transport-registry.ts +118 -0
- package/src/internal/auth/x509-transport-state-browser.ts +36 -0
- package/src/internal/auth/x509-transport-state.cts +36 -0
- package/src/internal/auth/x509-workload-identity-auth.ts +958 -0
- package/src/internal/bedrock.ts +182 -5
- package/src/internal/data-residency.ts +44 -0
- package/src/internal/multipart-encoding.ts +53 -0
- package/src/internal/qs/utils.ts +375 -13
- package/src/internal/request-options.ts +52 -1
- package/src/internal/responses/canonical-output-text.ts +3 -3
- package/src/internal/responses/response-accumulator.ts +411 -24
- package/src/internal/uploads.ts +81 -26
- package/src/internal/utils/env.ts +9 -5
- package/src/internal/ws.ts +24 -3
- package/src/lib/AbstractChatCompletionRunner.ts +33 -6
- package/src/lib/AssistantStream.ts +262 -22
- package/src/lib/ChatCompletionStream.ts +1467 -103
- package/src/lib/EventEmitter.ts +91 -7
- package/src/lib/EventStream.ts +1483 -10
- package/src/lib/ResponsesParser.ts +4 -1
- package/src/lib/Util.ts +7 -5
- package/src/lib/assistant-run-polling.ts +27 -0
- package/src/lib/embeddings.ts +65 -0
- package/src/lib/file-processing.ts +36 -0
- package/src/lib/parser.ts +19 -4
- package/src/lib/polling.ts +144 -0
- package/src/lib/responses/ResponseStream.ts +22 -10
- package/src/lib/vector-store-polling.ts +46 -0
- package/src/lib/vector-store-upload.ts +53 -0
- package/src/lib/webhook-signature.ts +164 -0
- package/src/realtime/internal-base.ts +15 -0
- package/src/realtime/websocket.ts +130 -27
- package/src/realtime/ws.ts +15 -2
- package/src/resources/admin/organization/index.ts +2 -0
- package/src/resources/admin/organization/organization.ts +4 -0
- package/src/resources/admin/organization/projects/index.ts +1 -0
- package/src/resources/admin/organization/projects/projects.ts +37 -4
- package/src/resources/admin/organization/usage.ts +83 -0
- package/src/resources/beta/responses/internal-base.ts +2 -0
- package/src/resources/beta/responses/responses.ts +9 -12
- package/src/resources/beta/threads/runs/index.ts +1 -1
- package/src/resources/beta/threads/runs/runs.ts +2 -45
- package/src/resources/chat/completions/completions.ts +7 -0
- package/src/resources/embeddings.ts +2 -42
- package/src/resources/files.ts +2 -19
- package/src/resources/images.ts +12 -22
- package/src/resources/realtime/api.md +1 -0
- package/src/resources/realtime/calls.ts +46 -0
- package/src/resources/realtime/index.ts +7 -1
- package/src/resources/realtime/realtime.ts +5 -3
- package/src/resources/responses/internal-base.ts +2 -0
- package/src/resources/responses/responses.ts +9 -12
- package/src/resources/vector-stores/file-batches.ts +8 -77
- package/src/resources/vector-stores/files.ts +3 -43
- package/src/resources/webhooks/webhooks.ts +5 -61
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APIConnectionError,
|
|
3
|
+
APIConnectionTimeoutError,
|
|
4
|
+
APIError,
|
|
5
|
+
OAuthError,
|
|
6
|
+
OpenAIError,
|
|
7
|
+
} from '../../core/error';
|
|
8
|
+
import { hasOwn } from '../utils/values';
|
|
9
|
+
import { sendX509Request } from './x509-transport-capability';
|
|
10
|
+
import { isRetryableX509TransportFailure } from './x509-transport-registry';
|
|
11
|
+
import {
|
|
12
|
+
isTransientX509ConnectionError,
|
|
13
|
+
markRetryableX509IssuerError,
|
|
14
|
+
markTransientX509ConnectionError,
|
|
15
|
+
rememberX509OAuthError,
|
|
16
|
+
} from '#x509-transport-state';
|
|
17
|
+
import type { X509ExchangedToken, X509Transport } from './x509-transport-registry';
|
|
18
|
+
|
|
19
|
+
export type { X509ExchangedToken } from './x509-transport-registry';
|
|
20
|
+
|
|
21
|
+
const TOKEN_EXCHANGE_URL = new URL('https://mtls.auth.openai.com/oauth/token');
|
|
22
|
+
const TOKEN_EXCHANGE_GRANT = 'urn:ietf:params:oauth:grant-type:token-exchange';
|
|
23
|
+
const X509_SUBJECT_TOKEN = 'urn:openai:params:oauth:token-type:x509';
|
|
24
|
+
const ACCESS_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token';
|
|
25
|
+
const SAFE_ACCESS_TOKEN = /^[A-Za-z0-9._~+/-]+=*$/u;
|
|
26
|
+
const SAFE_OAUTH_ERRORS = new Set(['invalid_grant', 'invalid_subject_token', 'token_exchange_server_error']);
|
|
27
|
+
const SAFE_RESPONSE_HEADERS = ['retry-after', 'retry-after-ms', 'x-should-retry', 'x-request-id'];
|
|
28
|
+
const MAX_TOKEN_EXCHANGE_DURATION_MS = 5000;
|
|
29
|
+
|
|
30
|
+
function transientConnectionError(message: string, failure: unknown): APIConnectionError {
|
|
31
|
+
const error = new APIConnectionError({ message });
|
|
32
|
+
if (isRetryableX509TransportFailure(failure)) {
|
|
33
|
+
markTransientX509ConnectionError(error);
|
|
34
|
+
}
|
|
35
|
+
return error;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Parameters for one certificate-authenticated OAuth exchange. */
|
|
39
|
+
export interface X509TokenExchangeOptions {
|
|
40
|
+
/** Frozen, caller-owned certificate transport shared with the eventual API request. */
|
|
41
|
+
transport: X509Transport;
|
|
42
|
+
|
|
43
|
+
/** Identity provider enrolled for the workload certificate. */
|
|
44
|
+
identityProviderId: string;
|
|
45
|
+
|
|
46
|
+
/** OpenAI service account selected for the verified certificate identity. */
|
|
47
|
+
serviceAccountId: string;
|
|
48
|
+
|
|
49
|
+
/** Optional caller cancellation propagated through request and response consumption. */
|
|
50
|
+
signal?: AbortSignal | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function cancelReader(
|
|
54
|
+
reader: ReadableStreamDefaultReader<Uint8Array>,
|
|
55
|
+
reason?: unknown,
|
|
56
|
+
): Promise<void> {
|
|
57
|
+
try {
|
|
58
|
+
await reader.cancel(reason);
|
|
59
|
+
} catch {
|
|
60
|
+
// Response retirement is best-effort and must never replace the sanitized exchange result.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function cancelResponseBody(response: Response): void {
|
|
65
|
+
if (!response.body) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const reader = response.body.getReader();
|
|
70
|
+
try {
|
|
71
|
+
void cancelReader(reader);
|
|
72
|
+
} finally {
|
|
73
|
+
reader.releaseLock();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function readResponseBody(response: Response, signal?: AbortSignal): Promise<unknown> {
|
|
78
|
+
if (!response.body) {
|
|
79
|
+
throw new OpenAIError('X.509 workload identity token exchange returned invalid JSON.');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const reader = response.body.getReader();
|
|
83
|
+
const chunks: Uint8Array[] = [];
|
|
84
|
+
let totalBytes = 0;
|
|
85
|
+
const cancel = () => {
|
|
86
|
+
void cancelReader(reader, signal?.reason);
|
|
87
|
+
};
|
|
88
|
+
signal?.addEventListener('abort', cancel, { once: true });
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
while (true) {
|
|
92
|
+
signal?.throwIfAborted();
|
|
93
|
+
// oxlint-disable-next-line no-await-in-loop -- Token-response chunks must be consumed in wire order.
|
|
94
|
+
const chunk = await reader.read();
|
|
95
|
+
signal?.throwIfAborted();
|
|
96
|
+
if (chunk.done) {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
chunks.push(chunk.value);
|
|
100
|
+
totalBytes += chunk.value.byteLength;
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
cancel();
|
|
104
|
+
if (signal?.aborted) {
|
|
105
|
+
signal.throwIfAborted();
|
|
106
|
+
}
|
|
107
|
+
throw transientConnectionError('X.509 workload identity token response could not be read.', error);
|
|
108
|
+
} finally {
|
|
109
|
+
signal?.removeEventListener('abort', cancel);
|
|
110
|
+
reader.releaseLock();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const bytes = new Uint8Array(totalBytes);
|
|
114
|
+
let offset = 0;
|
|
115
|
+
for (const chunk of chunks) {
|
|
116
|
+
bytes.set(chunk, offset);
|
|
117
|
+
offset += chunk.byteLength;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
|
|
122
|
+
} catch {
|
|
123
|
+
throw new OpenAIError('X.509 workload identity token exchange returned invalid JSON.');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function validateTokenResponse(value: unknown): X509ExchangedToken {
|
|
128
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
129
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid token response.');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const response = value as Record<string, unknown>;
|
|
133
|
+
if (
|
|
134
|
+
!hasOwn(response, 'access_token') ||
|
|
135
|
+
typeof response['access_token'] !== 'string' ||
|
|
136
|
+
!SAFE_ACCESS_TOKEN.test(response['access_token'])
|
|
137
|
+
) {
|
|
138
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid access token.');
|
|
139
|
+
}
|
|
140
|
+
if (!hasOwn(response, 'token_type') || !hasOwn(response, 'issued_token_type')) {
|
|
141
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid token type.');
|
|
142
|
+
}
|
|
143
|
+
const tokenType = response['token_type'];
|
|
144
|
+
if (
|
|
145
|
+
typeof tokenType !== 'string' ||
|
|
146
|
+
tokenType.toLowerCase() !== 'bearer' ||
|
|
147
|
+
response['issued_token_type'] !== ACCESS_TOKEN_TYPE
|
|
148
|
+
) {
|
|
149
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid token type.');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!hasOwn(response, 'expires_in')) {
|
|
153
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid token lifetime.');
|
|
154
|
+
}
|
|
155
|
+
const expiresIn = response['expires_in'];
|
|
156
|
+
if (typeof expiresIn !== 'number' || !Number.isFinite(expiresIn) || expiresIn <= 0 || expiresIn > 3600) {
|
|
157
|
+
throw new OpenAIError('X.509 workload identity token exchange returned an invalid token lifetime.');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { accessToken: response['access_token'], expiresIn };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function safeResponseHeaders(response: Response, includeRetryHints = false): Headers {
|
|
164
|
+
const headers = new Headers();
|
|
165
|
+
for (const name of SAFE_RESPONSE_HEADERS) {
|
|
166
|
+
if (name !== 'x-request-id' && !includeRetryHints) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const value = response.headers.get(name);
|
|
170
|
+
if (value !== null) {
|
|
171
|
+
headers.set(name, value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return headers;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function readOAuthErrorCode(value: unknown): string | undefined {
|
|
178
|
+
if (typeof value === 'string') {
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
if (typeof value === 'object' && value !== null && hasOwn(value, 'code')) {
|
|
182
|
+
const code: unknown = Object.getOwnPropertyDescriptor(value, 'code')?.value;
|
|
183
|
+
return typeof code === 'string' ? code : undefined;
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function oauthError(
|
|
189
|
+
response: Response,
|
|
190
|
+
signal?: AbortSignal,
|
|
191
|
+
callerSignal?: AbortSignal,
|
|
192
|
+
): Promise<OAuthError> {
|
|
193
|
+
let errorCode: { error: string } | undefined;
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const parsed = await readResponseBody(response, signal);
|
|
197
|
+
if (typeof parsed === 'object' && parsed !== null && hasOwn(parsed, 'error')) {
|
|
198
|
+
const code = readOAuthErrorCode(Object.getOwnPropertyDescriptor(parsed, 'error')?.value);
|
|
199
|
+
if (code !== undefined && SAFE_OAUTH_ERRORS.has(code)) {
|
|
200
|
+
errorCode = { error: code };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch {
|
|
204
|
+
callerSignal?.throwIfAborted();
|
|
205
|
+
if (
|
|
206
|
+
signal?.aborted &&
|
|
207
|
+
!(signal.reason instanceof APIConnectionTimeoutError && isTransientX509ConnectionError(signal.reason))
|
|
208
|
+
) {
|
|
209
|
+
signal.throwIfAborted();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const { status } = response;
|
|
214
|
+
if (status !== 400 && status !== 401 && status !== 403) {
|
|
215
|
+
throw new OpenAIError('X.509 workload identity received an invalid OAuth error status.');
|
|
216
|
+
}
|
|
217
|
+
const headers = safeResponseHeaders(response);
|
|
218
|
+
const error = new OAuthError(status, errorCode, headers);
|
|
219
|
+
rememberX509OAuthError(error, { status, error: errorCode, headers });
|
|
220
|
+
return error;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Exchanges one enrolled client certificate for a validated OpenAI workload access token. */
|
|
224
|
+
export async function exchangeX509Token(options: X509TokenExchangeOptions): Promise<X509ExchangedToken> {
|
|
225
|
+
const { signal: callerSignal } = options;
|
|
226
|
+
callerSignal?.throwIfAborted();
|
|
227
|
+
const { identityProviderId, serviceAccountId, transport } = options;
|
|
228
|
+
if (
|
|
229
|
+
typeof identityProviderId !== 'string' ||
|
|
230
|
+
identityProviderId.trim().length === 0 ||
|
|
231
|
+
typeof serviceAccountId !== 'string' ||
|
|
232
|
+
serviceAccountId.trim().length === 0
|
|
233
|
+
) {
|
|
234
|
+
throw new OpenAIError(
|
|
235
|
+
'X.509 workload identity requires nonempty provider and service-account identifiers.',
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const timeoutController = new AbortController();
|
|
240
|
+
const signal = callerSignal
|
|
241
|
+
? AbortSignal.any([callerSignal, timeoutController.signal])
|
|
242
|
+
: timeoutController.signal;
|
|
243
|
+
const timeout = setTimeout(() => {
|
|
244
|
+
const error = new APIConnectionTimeoutError({
|
|
245
|
+
message: 'X.509 workload identity token exchange timed out.',
|
|
246
|
+
});
|
|
247
|
+
markTransientX509ConnectionError(error);
|
|
248
|
+
timeoutController.abort(error);
|
|
249
|
+
}, MAX_TOKEN_EXCHANGE_DURATION_MS);
|
|
250
|
+
timeout.unref();
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
const body = JSON.stringify({
|
|
254
|
+
grant_type: TOKEN_EXCHANGE_GRANT,
|
|
255
|
+
subject_token_type: X509_SUBJECT_TOKEN,
|
|
256
|
+
identity_provider_id: identityProviderId,
|
|
257
|
+
service_account_id: serviceAccountId,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
let response: Response;
|
|
261
|
+
try {
|
|
262
|
+
response = await sendX509Request(transport, TOKEN_EXCHANGE_URL, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
headers: { 'Content-Type': 'application/json' },
|
|
265
|
+
body,
|
|
266
|
+
redirect: 'manual',
|
|
267
|
+
signal,
|
|
268
|
+
});
|
|
269
|
+
} catch (error) {
|
|
270
|
+
signal.throwIfAborted();
|
|
271
|
+
throw transientConnectionError('X.509 workload identity token exchange connection failed.', error);
|
|
272
|
+
}
|
|
273
|
+
signal.throwIfAborted();
|
|
274
|
+
|
|
275
|
+
if (response.ok) {
|
|
276
|
+
try {
|
|
277
|
+
return validateTokenResponse(await readResponseBody(response, signal));
|
|
278
|
+
} catch (error) {
|
|
279
|
+
signal.throwIfAborted();
|
|
280
|
+
if (error instanceof APIConnectionError) {
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
if (error instanceof OpenAIError) {
|
|
284
|
+
throw APIError.generate(response.status, undefined, error.message, safeResponseHeaders(response));
|
|
285
|
+
}
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (response.status === 400 || response.status === 401 || response.status === 403) {
|
|
290
|
+
throw await oauthError(response, signal, callerSignal);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
cancelResponseBody(response);
|
|
294
|
+
const retryableStatus =
|
|
295
|
+
response.status === 408 || response.status === 409 || response.status === 429 || response.status >= 500;
|
|
296
|
+
const headers = safeResponseHeaders(response, retryableStatus);
|
|
297
|
+
const error = APIError.generate(
|
|
298
|
+
response.status,
|
|
299
|
+
undefined,
|
|
300
|
+
'X.509 workload identity token exchange failed.',
|
|
301
|
+
headers,
|
|
302
|
+
);
|
|
303
|
+
if (retryableStatus && headers.get('x-should-retry') !== 'false') {
|
|
304
|
+
markRetryableX509IssuerError(error);
|
|
305
|
+
}
|
|
306
|
+
throw error;
|
|
307
|
+
} finally {
|
|
308
|
+
clearTimeout(timeout);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { types } from 'node:util';
|
|
2
|
+
import { Agent, ProxyAgent, Request, fetch } from 'undici';
|
|
3
|
+
import { OpenAIError } from '../../core/error';
|
|
4
|
+
import { x509TransportBrand } from './x509-transport-registry';
|
|
5
|
+
import type { RegisteredX509Transport, X509Transport } from './x509-transport-registry';
|
|
6
|
+
import { findRegisteredX509Transport, rememberRegisteredX509Transport } from '#x509-transport-state';
|
|
7
|
+
|
|
8
|
+
export type { X509Transport } from './x509-transport-registry';
|
|
9
|
+
|
|
10
|
+
/** Explicitly supported, application-owned Undici proxy configurations. */
|
|
11
|
+
export type X509ProxyMode = 'direct' | 'http-connect' | 'https-connect';
|
|
12
|
+
|
|
13
|
+
/** Application attestation for one caller-owned static-certificate Undici transport. */
|
|
14
|
+
export interface X509TransportOptions {
|
|
15
|
+
/** X.509 transport currently supports genuine Node.js runtimes only. */
|
|
16
|
+
runtime: 'node';
|
|
17
|
+
|
|
18
|
+
/** Caller-owned Undici Agent or ProxyAgent; the SDK never closes or inspects it. */
|
|
19
|
+
dispatcher: Agent | ProxyAgent;
|
|
20
|
+
|
|
21
|
+
/** Attests that the dispatcher uses one static workload-certificate identity. */
|
|
22
|
+
certificateIdentity: 'static';
|
|
23
|
+
|
|
24
|
+
/** Attests that proxy TLS and CONNECT credentials are independently configured. */
|
|
25
|
+
proxy: X509ProxyMode;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const allowedOptionNames = new Set(['runtime', 'dispatcher', 'certificateIdentity', 'proxy']);
|
|
29
|
+
const transportBrand: typeof x509TransportBrand = x509TransportBrand;
|
|
30
|
+
|
|
31
|
+
class NodeX509Transport implements X509Transport {
|
|
32
|
+
declare readonly [transportBrand]: true;
|
|
33
|
+
|
|
34
|
+
readonly #dispatcher: Agent | ProxyAgent;
|
|
35
|
+
|
|
36
|
+
constructor(dispatcher: Agent | ProxyAgent) {
|
|
37
|
+
this.#dispatcher = dispatcher;
|
|
38
|
+
Object.freeze(this);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static dispatcher(value: object): Agent | ProxyAgent | undefined {
|
|
42
|
+
return #dispatcher in value ? value.#dispatcher : undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Registers only a genuine frozen capability whose JavaScript private dispatcher cannot be forged. */
|
|
47
|
+
export function registerX509Transport(transport: X509Transport, registered: RegisteredX509Transport): void {
|
|
48
|
+
if (
|
|
49
|
+
!transport ||
|
|
50
|
+
typeof transport !== 'object' ||
|
|
51
|
+
types.isProxy(transport) ||
|
|
52
|
+
!Object.isFrozen(transport) ||
|
|
53
|
+
!NodeX509Transport.dispatcher(transport)
|
|
54
|
+
) {
|
|
55
|
+
throw new OpenAIError('Only a genuine frozen X.509 transport capability can be registered.');
|
|
56
|
+
}
|
|
57
|
+
if (findRegisteredX509Transport(transport)) {
|
|
58
|
+
throw new OpenAIError('An approved X.509 transport capability cannot be registered more than once.');
|
|
59
|
+
}
|
|
60
|
+
rememberRegisteredX509Transport(transport, Object.freeze(registered));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function dataOption(options: X509TransportOptions, name: keyof X509TransportOptions): unknown {
|
|
64
|
+
const descriptor = Object.getOwnPropertyDescriptor(options, name);
|
|
65
|
+
if (!descriptor || !('value' in descriptor)) {
|
|
66
|
+
throw new Error(`X.509 transport option \`${name}\` must be an own plain data property.`);
|
|
67
|
+
}
|
|
68
|
+
return descriptor.value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function assertNodeRuntime(): void {
|
|
72
|
+
if (
|
|
73
|
+
typeof process === 'undefined' ||
|
|
74
|
+
process.release.name !== 'node' ||
|
|
75
|
+
'bun' in process.versions ||
|
|
76
|
+
'Bun' in globalThis ||
|
|
77
|
+
'Deno' in globalThis
|
|
78
|
+
) {
|
|
79
|
+
throw new Error('X.509 transport requires a genuine Node.js runtime.');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function attestedDispatcher(options: X509TransportOptions): Agent | ProxyAgent {
|
|
84
|
+
const dispatcher = dataOption(options, 'dispatcher');
|
|
85
|
+
if (!dispatcher || typeof dispatcher !== 'object') {
|
|
86
|
+
throw new Error('X.509 transport requires a caller-owned Undici Agent or ProxyAgent.');
|
|
87
|
+
}
|
|
88
|
+
if (types.isProxy(dispatcher)) {
|
|
89
|
+
throw new Error('X.509 transport does not accept a dispatcher proxy.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const isDirect = dispatcher instanceof Agent;
|
|
93
|
+
const isConnect = dispatcher instanceof ProxyAgent;
|
|
94
|
+
if (!isDirect && !isConnect) {
|
|
95
|
+
throw new Error('X.509 transport requires a caller-owned Undici Agent or ProxyAgent.');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const proxy = dataOption(options, 'proxy');
|
|
99
|
+
if (proxy !== 'direct' && proxy !== 'http-connect' && proxy !== 'https-connect') {
|
|
100
|
+
throw new Error('X.509 transport requires an explicitly supported proxy mode.');
|
|
101
|
+
}
|
|
102
|
+
if ((proxy === 'direct') !== isDirect) {
|
|
103
|
+
throw new Error('An X.509 CONNECT proxy requires an Undici ProxyAgent.');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return dispatcher;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function assertRequestDispatcherSupport(dispatcher: Agent | ProxyAgent): void {
|
|
110
|
+
let observesRequestDispatcher = false;
|
|
111
|
+
|
|
112
|
+
// about:blank never reaches the network; the getter checks the actual fetch contract.
|
|
113
|
+
void Promise.allSettled([
|
|
114
|
+
fetch('about:blank', {
|
|
115
|
+
get dispatcher() {
|
|
116
|
+
observesRequestDispatcher = true;
|
|
117
|
+
return dispatcher;
|
|
118
|
+
},
|
|
119
|
+
}),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
if (!observesRequestDispatcher) {
|
|
123
|
+
throw new Error('X.509 transport requires Undici 5.2.0 or later with per-request dispatcher support.');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function assertConnectProxySupport(): void {
|
|
128
|
+
const targetOrigin = 'https://127.0.0.1:65535';
|
|
129
|
+
let routedOrigin: string | undefined;
|
|
130
|
+
const probe = new ProxyAgent({
|
|
131
|
+
uri: 'http://127.0.0.1:1',
|
|
132
|
+
factory(origin) {
|
|
133
|
+
routedOrigin = String(origin);
|
|
134
|
+
throw new Error('X.509 CONNECT capability probe');
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// The throwing factory reveals the actual routing decision before any socket opens.
|
|
139
|
+
const request = fetch(targetOrigin, { dispatcher: probe });
|
|
140
|
+
void Promise.allSettled([request, probe.close()]);
|
|
141
|
+
|
|
142
|
+
if (routedOrigin !== targetOrigin) {
|
|
143
|
+
throw new Error('X.509 CONNECT proxy requires Undici 5.5.1 or later with target TLS tunneling.');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Creates a frozen, opaque capability for one caller-owned Undici transport.
|
|
149
|
+
*
|
|
150
|
+
* `certificateIdentity: 'static'` is an application attestation: the SDK does
|
|
151
|
+
* not inspect certificates, private dispatcher internals, callbacks, or TLS
|
|
152
|
+
* options and cannot cryptographically prove certificate selection. Configure
|
|
153
|
+
* one static identity without custom dispatcher factories. For HTTPS CONNECT,
|
|
154
|
+
* independently configure `proxyTls` and `requestTls` so workload credentials
|
|
155
|
+
* never reach the proxy. Rotation requires creating a fresh dispatcher and
|
|
156
|
+
* capability; the application remains responsible for draining the old one.
|
|
157
|
+
*
|
|
158
|
+
* This Node-only preview entrypoint requires the optional `undici` peer at
|
|
159
|
+
* version 5.2.0 or later. CONNECT proxy modes require version 5.5.1 or
|
|
160
|
+
* later; ordinary SDK clients retain broader compatibility.
|
|
161
|
+
*/
|
|
162
|
+
export function createX509Transport(options: X509TransportOptions): X509Transport {
|
|
163
|
+
assertNodeRuntime();
|
|
164
|
+
|
|
165
|
+
if (!options || typeof options !== 'object' || types.isProxy(options)) {
|
|
166
|
+
throw new Error('X.509 transport configuration must be a non-proxy object.');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const name of Reflect.ownKeys(options)) {
|
|
170
|
+
if (typeof name !== 'string' || !allowedOptionNames.has(name)) {
|
|
171
|
+
throw new Error(`Unsupported X.509 transport option: \`${String(name)}\`.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (dataOption(options, 'runtime') !== 'node') {
|
|
176
|
+
throw new Error('X.509 transport requires an explicitly attested Node.js runtime.');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (dataOption(options, 'certificateIdentity') !== 'static') {
|
|
180
|
+
throw new Error('X.509 transport requires an explicitly attested static client certificate.');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const dispatcher = attestedDispatcher(options);
|
|
184
|
+
assertRequestDispatcherSupport(dispatcher);
|
|
185
|
+
if (dispatcher instanceof ProxyAgent) {
|
|
186
|
+
assertConnectProxySupport();
|
|
187
|
+
}
|
|
188
|
+
return new NodeX509Transport(dispatcher);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Dispatches through the opaque attested transport without accepting replacement dispatchers. */
|
|
192
|
+
export async function sendX509Request(
|
|
193
|
+
transport: X509Transport,
|
|
194
|
+
target: URL,
|
|
195
|
+
options: RequestInit,
|
|
196
|
+
): Promise<Response> {
|
|
197
|
+
if (!transport || typeof transport !== 'object' || types.isProxy(transport)) {
|
|
198
|
+
throw new Error('Invalid X.509 transport capability.');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const dispatcher = NodeX509Transport.dispatcher(transport);
|
|
202
|
+
if (!dispatcher) {
|
|
203
|
+
throw new Error('Invalid X.509 transport capability.');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const normalizedTarget = new URL(target.href);
|
|
207
|
+
if (normalizedTarget.protocol !== 'https:') {
|
|
208
|
+
throw new Error('X.509 transport requires an HTTPS destination.');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (Object.getOwnPropertyDescriptor(options, 'dispatcher')) {
|
|
212
|
+
throw new Error('X.509 transport does not allow a per-request dispatcher override.');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const requestOptions: Omit<RequestInit, 'dispatcher'> = options;
|
|
216
|
+
const request = new Request(normalizedTarget, requestOptions);
|
|
217
|
+
const response = await fetch(request, { dispatcher, redirect: 'manual' });
|
|
218
|
+
return response;
|
|
219
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { OpenAIError } from '../../core/error';
|
|
2
|
+
import type { NullableHeaders } from '../headers';
|
|
3
|
+
import type { ReadableStream } from '../shim-types';
|
|
4
|
+
import type { MergedRequestInit } from '../types';
|
|
5
|
+
import { findRegisteredX509Transport } from '#x509-transport-state';
|
|
6
|
+
|
|
7
|
+
const transientX509TransportCodes = new Set([
|
|
8
|
+
'ECONNRESET',
|
|
9
|
+
'ECONNREFUSED',
|
|
10
|
+
'ENETUNREACH',
|
|
11
|
+
'EHOSTUNREACH',
|
|
12
|
+
'ENETDOWN',
|
|
13
|
+
'EPIPE',
|
|
14
|
+
'ETIMEDOUT',
|
|
15
|
+
'EAI_AGAIN',
|
|
16
|
+
'UND_ERR_CONNECT_TIMEOUT',
|
|
17
|
+
'UND_ERR_HEADERS_TIMEOUT',
|
|
18
|
+
'UND_ERR_BODY_TIMEOUT',
|
|
19
|
+
'UND_ERR_SOCKET',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
/** Retries only known temporary failures when neither error layer reports a permanent code. */
|
|
23
|
+
export function isRetryableX509TransportFailure(failure: unknown): boolean {
|
|
24
|
+
const cause =
|
|
25
|
+
typeof failure === 'object' && failure !== null
|
|
26
|
+
? Object.getOwnPropertyDescriptor(failure, 'cause')?.value
|
|
27
|
+
: undefined;
|
|
28
|
+
let retryable = false;
|
|
29
|
+
for (const candidate of [failure, cause]) {
|
|
30
|
+
const code =
|
|
31
|
+
typeof candidate === 'object' && candidate !== null
|
|
32
|
+
? Object.getOwnPropertyDescriptor(candidate, 'code')?.value
|
|
33
|
+
: undefined;
|
|
34
|
+
if (typeof code === 'string') {
|
|
35
|
+
if (!transientX509TransportCodes.has(code)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
retryable = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return retryable;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const x509TransportBrand: unique symbol = Symbol('X.509 transport capability');
|
|
45
|
+
|
|
46
|
+
/** Opaque identity of one frozen, caller-owned, explicitly attested X.509 transport. */
|
|
47
|
+
export interface X509Transport {
|
|
48
|
+
/** Prevents ordinary objects from satisfying the transport capability contract. */
|
|
49
|
+
readonly [x509TransportBrand]: true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Validated short-lived token exchanged using a registered certificate identity. */
|
|
53
|
+
export interface X509ExchangedToken {
|
|
54
|
+
/** Header-safe, in-memory OpenAI bearer credential. */
|
|
55
|
+
accessToken: string;
|
|
56
|
+
|
|
57
|
+
/** Issuer-approved positive token lifetime in seconds. */
|
|
58
|
+
expiresIn: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** One logical certificate-authenticated operation and its immutable starting deadline. */
|
|
62
|
+
export interface X509RequestScope {
|
|
63
|
+
wallStartedAt: number;
|
|
64
|
+
monotonicStartedAt: number;
|
|
65
|
+
deadlineArmed?: boolean;
|
|
66
|
+
request?: { signal: AbortSignal | null | undefined; timeout: number; fetchOptions: MergedRequestInit };
|
|
67
|
+
phase?: 'planning' | 'authorizing';
|
|
68
|
+
effectiveSignal?: AbortSignal;
|
|
69
|
+
materializedBody?: ReadableStream;
|
|
70
|
+
owner?: object;
|
|
71
|
+
requestOwner?: object;
|
|
72
|
+
apiURL?: string;
|
|
73
|
+
tenant?: { organization: string | null; project: string | null };
|
|
74
|
+
defaultHeaders?: NullableHeaders;
|
|
75
|
+
requestHeaders?: NullableHeaders;
|
|
76
|
+
token?: string;
|
|
77
|
+
tokenGeneration?: number;
|
|
78
|
+
headers?: Headers;
|
|
79
|
+
authorization?: string | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Private, peer-independent operations attached to one approved transport generation. */
|
|
83
|
+
export interface RegisteredX509Transport {
|
|
84
|
+
/** Dispatches one request through the exact frozen certificate capability. */
|
|
85
|
+
dispatch: (target: URL, options: RequestInit) => Promise<Response>;
|
|
86
|
+
|
|
87
|
+
/** Exchanges the same certificate identity for an OpenAI service-account bearer. */
|
|
88
|
+
exchange: (
|
|
89
|
+
identityProviderId: string,
|
|
90
|
+
serviceAccountId: string,
|
|
91
|
+
signal?: AbortSignal,
|
|
92
|
+
) => Promise<X509ExchangedToken>;
|
|
93
|
+
|
|
94
|
+
/** Establishes one isolated Node async context without exposing Node dependencies to the root SDK. */
|
|
95
|
+
run: <T>(operation: () => T) => T;
|
|
96
|
+
|
|
97
|
+
/** Resolves only the current logical request's private certificate-authentication scope. */
|
|
98
|
+
current: () => X509RequestScope | undefined;
|
|
99
|
+
|
|
100
|
+
/** Re-enters the original request scope when response parsing resumes outside its promise chain. */
|
|
101
|
+
resume: <T>(scope: X509RequestScope, operation: () => T) => T;
|
|
102
|
+
|
|
103
|
+
/** Waits for retry backoff using an abortable timer that keeps an active request alive. */
|
|
104
|
+
sleep: (duration: number, signal?: AbortSignal | null) => Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Resolves a previously registered opaque capability without importing an optional transport peer. */
|
|
108
|
+
export function resolveX509Transport(value: unknown): RegisteredX509Transport {
|
|
109
|
+
if (!value || typeof value !== 'object') {
|
|
110
|
+
throw new OpenAIError('X.509 workload identity requires an approved X.509 transport capability.');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const registered: RegisteredX509Transport | undefined = findRegisteredX509Transport(value);
|
|
114
|
+
if (!registered) {
|
|
115
|
+
throw new OpenAIError('X.509 workload identity requires an approved X.509 transport capability.');
|
|
116
|
+
}
|
|
117
|
+
return registered;
|
|
118
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Browser-safe capability state keeps CommonJS outside the ordinary SDK ESM graph. */
|
|
2
|
+
const registeredX509Transports = new WeakMap();
|
|
3
|
+
const transientX509ConnectionErrors = new WeakSet();
|
|
4
|
+
const retryableX509IssuerErrors = new WeakSet();
|
|
5
|
+
const approvedX509Clients = new WeakSet();
|
|
6
|
+
const approvedX509OAuthErrors = new WeakMap();
|
|
7
|
+
|
|
8
|
+
/** Looks up an opaque capability without exposing the registry itself. */
|
|
9
|
+
export const findRegisteredX509Transport = WeakMap.prototype.get.bind(registeredX509Transports);
|
|
10
|
+
|
|
11
|
+
/** Records a capability only after its Node-only factory validates the private dispatcher. */
|
|
12
|
+
export const rememberRegisteredX509Transport = WeakMap.prototype.set.bind(registeredX509Transports);
|
|
13
|
+
|
|
14
|
+
/** Privately classifies sanitized issuer errors without exposing transport details. */
|
|
15
|
+
export const markTransientX509ConnectionError = WeakSet.prototype.add.bind(transientX509ConnectionErrors);
|
|
16
|
+
|
|
17
|
+
/** Checks the private transient classification without retaining caller-owned errors. */
|
|
18
|
+
export const isTransientX509ConnectionError = WeakSet.prototype.has.bind(transientX509ConnectionErrors);
|
|
19
|
+
|
|
20
|
+
/** Privately brands retryable issuer failures without exposing classification state. */
|
|
21
|
+
export const markRetryableX509IssuerError = WeakSet.prototype.add.bind(retryableX509IssuerErrors);
|
|
22
|
+
|
|
23
|
+
/** Recognizes trusted issuer failures without evaluating caller-controlled properties. */
|
|
24
|
+
export const isRetryableX509IssuerError = WeakSet.prototype.has.bind(retryableX509IssuerErrors);
|
|
25
|
+
|
|
26
|
+
/** Brands validated clients without exposing their mutable options or authentication fields. */
|
|
27
|
+
export const markApprovedX509Client = WeakSet.prototype.add.bind(approvedX509Clients);
|
|
28
|
+
|
|
29
|
+
/** Recognizes private client ownership without caller-visible markers. */
|
|
30
|
+
export const isApprovedX509Client = WeakSet.prototype.has.bind(approvedX509Clients);
|
|
31
|
+
|
|
32
|
+
/** Stores trusted OAuth metadata without exposing it to unrelated callers. */
|
|
33
|
+
export const rememberX509OAuthError = WeakMap.prototype.set.bind(approvedX509OAuthErrors);
|
|
34
|
+
|
|
35
|
+
/** Retrieves trusted metadata when public OAuth errors cross module formats. */
|
|
36
|
+
export const findX509OAuthError = WeakMap.prototype.get.bind(approvedX509OAuthErrors);
|