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.
Files changed (597) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +46 -2
  3. package/auth/index.d.mts +1 -1
  4. package/auth/index.d.mts.map +1 -1
  5. package/auth/index.d.ts +1 -1
  6. package/auth/index.d.ts.map +1 -1
  7. package/auth/index.js.map +1 -1
  8. package/auth/index.mjs.map +1 -1
  9. package/auth/subject-token-providers.d.mts.map +1 -1
  10. package/auth/subject-token-providers.d.ts.map +1 -1
  11. package/auth/subject-token-providers.js +176 -4
  12. package/auth/subject-token-providers.js.map +1 -1
  13. package/auth/subject-token-providers.mjs +176 -4
  14. package/auth/subject-token-providers.mjs.map +1 -1
  15. package/auth/types.d.mts +17 -0
  16. package/auth/types.d.mts.map +1 -1
  17. package/auth/types.d.ts +17 -0
  18. package/auth/types.d.ts.map +1 -1
  19. package/auth/workload-identity-auth.d.mts.map +1 -1
  20. package/auth/workload-identity-auth.d.ts.map +1 -1
  21. package/auth/workload-identity-auth.js +80 -7
  22. package/auth/workload-identity-auth.js.map +1 -1
  23. package/auth/workload-identity-auth.mjs +80 -7
  24. package/auth/workload-identity-auth.mjs.map +1 -1
  25. package/auth/x509-transport.d.mts +5 -0
  26. package/auth/x509-transport.d.mts.map +1 -0
  27. package/auth/x509-transport.d.ts +5 -0
  28. package/auth/x509-transport.d.ts.map +1 -0
  29. package/auth/x509-transport.js +39 -0
  30. package/auth/x509-transport.js.map +1 -0
  31. package/auth/x509-transport.mjs +36 -0
  32. package/auth/x509-transport.mjs.map +1 -0
  33. package/azure.d.mts +11 -2
  34. package/azure.d.mts.map +1 -1
  35. package/azure.d.ts +11 -2
  36. package/azure.d.ts.map +1 -1
  37. package/azure.js +7 -1
  38. package/azure.js.map +1 -1
  39. package/azure.mjs +7 -1
  40. package/azure.mjs.map +1 -1
  41. package/bedrock.d.mts +6 -2
  42. package/bedrock.d.mts.map +1 -1
  43. package/bedrock.d.ts +6 -2
  44. package/bedrock.d.ts.map +1 -1
  45. package/bedrock.js +34 -4
  46. package/bedrock.js.map +1 -1
  47. package/bedrock.mjs +35 -5
  48. package/bedrock.mjs.map +1 -1
  49. package/beta/realtime/internal-base.d.mts +2 -0
  50. package/beta/realtime/internal-base.d.mts.map +1 -1
  51. package/beta/realtime/internal-base.d.ts +2 -0
  52. package/beta/realtime/internal-base.d.ts.map +1 -1
  53. package/beta/realtime/internal-base.js +15 -0
  54. package/beta/realtime/internal-base.js.map +1 -1
  55. package/beta/realtime/internal-base.mjs +14 -0
  56. package/beta/realtime/internal-base.mjs.map +1 -1
  57. package/beta/realtime/websocket.d.mts +11 -5
  58. package/beta/realtime/websocket.d.mts.map +1 -1
  59. package/beta/realtime/websocket.d.ts +11 -5
  60. package/beta/realtime/websocket.d.ts.map +1 -1
  61. package/beta/realtime/websocket.js +106 -31
  62. package/beta/realtime/websocket.js.map +1 -1
  63. package/beta/realtime/websocket.mjs +107 -32
  64. package/beta/realtime/websocket.mjs.map +1 -1
  65. package/beta/realtime/ws.d.mts +0 -2
  66. package/beta/realtime/ws.d.mts.map +1 -1
  67. package/beta/realtime/ws.d.ts +0 -2
  68. package/beta/realtime/ws.d.ts.map +1 -1
  69. package/beta/realtime/ws.js +24 -5
  70. package/beta/realtime/ws.js.map +1 -1
  71. package/beta/realtime/ws.mjs +25 -6
  72. package/beta/realtime/ws.mjs.map +1 -1
  73. package/client.d.mts +17 -2
  74. package/client.d.mts.map +1 -1
  75. package/client.d.ts +17 -2
  76. package/client.d.ts.map +1 -1
  77. package/client.js +422 -70
  78. package/client.js.map +1 -1
  79. package/client.mjs +423 -71
  80. package/client.mjs.map +1 -1
  81. package/core/EventEmitter.d.mts.map +1 -1
  82. package/core/EventEmitter.d.ts.map +1 -1
  83. package/core/EventEmitter.js +67 -9
  84. package/core/EventEmitter.js.map +1 -1
  85. package/core/EventEmitter.mjs +68 -10
  86. package/core/EventEmitter.mjs.map +1 -1
  87. package/core/streaming.d.mts +1 -0
  88. package/core/streaming.d.mts.map +1 -1
  89. package/core/streaming.d.ts +1 -0
  90. package/core/streaming.d.ts.map +1 -1
  91. package/core/streaming.js +58 -19
  92. package/core/streaming.js.map +1 -1
  93. package/core/streaming.mjs +58 -19
  94. package/core/streaming.mjs.map +1 -1
  95. package/helpers/audio.d.mts +5 -5
  96. package/helpers/audio.d.mts.map +1 -1
  97. package/helpers/audio.d.ts +5 -5
  98. package/helpers/audio.d.ts.map +1 -1
  99. package/helpers/audio.js +93 -22
  100. package/helpers/audio.js.map +1 -1
  101. package/helpers/audio.mjs +93 -22
  102. package/helpers/audio.mjs.map +1 -1
  103. package/helpers/standard-schema.d.mts.map +1 -1
  104. package/helpers/standard-schema.d.ts.map +1 -1
  105. package/helpers/standard-schema.js +34 -14
  106. package/helpers/standard-schema.js.map +1 -1
  107. package/helpers/standard-schema.mjs +35 -15
  108. package/helpers/standard-schema.mjs.map +1 -1
  109. package/helpers/zod-v3-strict-schema.d.mts +7 -0
  110. package/helpers/zod-v3-strict-schema.d.mts.map +1 -0
  111. package/helpers/zod-v3-strict-schema.d.ts +7 -0
  112. package/helpers/zod-v3-strict-schema.d.ts.map +1 -0
  113. package/helpers/zod-v3-strict-schema.js +403 -0
  114. package/helpers/zod-v3-strict-schema.js.map +1 -0
  115. package/helpers/zod-v3-strict-schema.mjs +399 -0
  116. package/helpers/zod-v3-strict-schema.mjs.map +1 -0
  117. package/helpers/zod.d.mts.map +1 -1
  118. package/helpers/zod.d.ts.map +1 -1
  119. package/helpers/zod.js +11 -3
  120. package/helpers/zod.js.map +1 -1
  121. package/helpers/zod.mjs +12 -4
  122. package/helpers/zod.mjs.map +1 -1
  123. package/index.d.mts +1 -1
  124. package/index.d.mts.map +1 -1
  125. package/index.d.ts +1 -1
  126. package/index.d.ts.map +1 -1
  127. package/index.js.map +1 -1
  128. package/index.mjs.map +1 -1
  129. package/internal/assistant-stream-delta.d.mts.map +1 -1
  130. package/internal/assistant-stream-delta.d.ts.map +1 -1
  131. package/internal/assistant-stream-delta.js +28 -8
  132. package/internal/assistant-stream-delta.js.map +1 -1
  133. package/internal/assistant-stream-delta.mjs +28 -8
  134. package/internal/assistant-stream-delta.mjs.map +1 -1
  135. package/internal/auth/x509-token-exchange.d.mts +16 -0
  136. package/internal/auth/x509-token-exchange.d.mts.map +1 -0
  137. package/internal/auth/x509-token-exchange.d.ts +16 -0
  138. package/internal/auth/x509-token-exchange.d.ts.map +1 -0
  139. package/internal/auth/x509-token-exchange.js +246 -0
  140. package/internal/auth/x509-token-exchange.js.map +1 -0
  141. package/internal/auth/x509-token-exchange.mjs +243 -0
  142. package/internal/auth/x509-token-exchange.mjs.map +1 -0
  143. package/internal/auth/x509-transport-capability.d.mts +37 -0
  144. package/internal/auth/x509-transport-capability.d.mts.map +1 -0
  145. package/internal/auth/x509-transport-capability.d.ts +37 -0
  146. package/internal/auth/x509-transport-capability.d.ts.map +1 -0
  147. package/internal/auth/x509-transport-capability.js +169 -0
  148. package/internal/auth/x509-transport-capability.js.map +1 -0
  149. package/internal/auth/x509-transport-capability.mjs +164 -0
  150. package/internal/auth/x509-transport-capability.mjs.map +1 -0
  151. package/internal/auth/x509-transport-registry.d.mts +63 -0
  152. package/internal/auth/x509-transport-registry.d.mts.map +1 -0
  153. package/internal/auth/x509-transport-registry.d.ts +63 -0
  154. package/internal/auth/x509-transport-registry.d.ts.map +1 -0
  155. package/internal/auth/x509-transport-registry.js +53 -0
  156. package/internal/auth/x509-transport-registry.js.map +1 -0
  157. package/internal/auth/x509-transport-registry.mjs +48 -0
  158. package/internal/auth/x509-transport-registry.mjs.map +1 -0
  159. package/internal/auth/x509-transport-state-browser.d.mts +21 -0
  160. package/internal/auth/x509-transport-state-browser.d.mts.map +1 -0
  161. package/internal/auth/x509-transport-state-browser.d.ts +21 -0
  162. package/internal/auth/x509-transport-state-browser.d.ts.map +1 -0
  163. package/internal/auth/x509-transport-state-browser.js +30 -0
  164. package/internal/auth/x509-transport-state-browser.js.map +1 -0
  165. package/internal/auth/x509-transport-state-browser.mjs +27 -0
  166. package/internal/auth/x509-transport-state-browser.mjs.map +1 -0
  167. package/internal/auth/x509-transport-state.cjs +30 -0
  168. package/internal/auth/x509-transport-state.cjs.map +1 -0
  169. package/internal/auth/x509-transport-state.d.cts +21 -0
  170. package/internal/auth/x509-transport-state.d.cts.map +1 -0
  171. package/internal/auth/x509-workload-identity-auth.d.mts +128 -0
  172. package/internal/auth/x509-workload-identity-auth.d.mts.map +1 -0
  173. package/internal/auth/x509-workload-identity-auth.d.ts +128 -0
  174. package/internal/auth/x509-workload-identity-auth.d.ts.map +1 -0
  175. package/internal/auth/x509-workload-identity-auth.js +767 -0
  176. package/internal/auth/x509-workload-identity-auth.js.map +1 -0
  177. package/internal/auth/x509-workload-identity-auth.mjs +757 -0
  178. package/internal/auth/x509-workload-identity-auth.mjs.map +1 -0
  179. package/internal/bedrock.d.mts +2 -0
  180. package/internal/bedrock.d.mts.map +1 -1
  181. package/internal/bedrock.d.ts +2 -0
  182. package/internal/bedrock.d.ts.map +1 -1
  183. package/internal/bedrock.js +169 -5
  184. package/internal/bedrock.js.map +1 -1
  185. package/internal/bedrock.mjs +168 -5
  186. package/internal/bedrock.mjs.map +1 -1
  187. package/internal/data-residency.d.mts +12 -0
  188. package/internal/data-residency.d.mts.map +1 -0
  189. package/internal/data-residency.d.ts +12 -0
  190. package/internal/data-residency.d.ts.map +1 -0
  191. package/internal/data-residency.js +34 -0
  192. package/internal/data-residency.js.map +1 -0
  193. package/internal/data-residency.mjs +30 -0
  194. package/internal/data-residency.mjs.map +1 -0
  195. package/internal/multipart-encoding.d.mts +8 -0
  196. package/internal/multipart-encoding.d.mts.map +1 -0
  197. package/internal/multipart-encoding.d.ts +8 -0
  198. package/internal/multipart-encoding.d.ts.map +1 -0
  199. package/internal/multipart-encoding.js +51 -0
  200. package/internal/multipart-encoding.js.map +1 -0
  201. package/internal/multipart-encoding.mjs +48 -0
  202. package/internal/multipart-encoding.mjs.map +1 -0
  203. package/internal/qs/utils.d.mts.map +1 -1
  204. package/internal/qs/utils.d.ts.map +1 -1
  205. package/internal/qs/utils.js +307 -10
  206. package/internal/qs/utils.js.map +1 -1
  207. package/internal/qs/utils.mjs +307 -10
  208. package/internal/qs/utils.mjs.map +1 -1
  209. package/internal/request-options.d.mts +7 -0
  210. package/internal/request-options.d.mts.map +1 -1
  211. package/internal/request-options.d.ts +7 -0
  212. package/internal/request-options.d.ts.map +1 -1
  213. package/internal/request-options.js +43 -1
  214. package/internal/request-options.js.map +1 -1
  215. package/internal/request-options.mjs +42 -1
  216. package/internal/request-options.mjs.map +1 -1
  217. package/internal/responses/canonical-output-text.js +3 -3
  218. package/internal/responses/canonical-output-text.js.map +1 -1
  219. package/internal/responses/canonical-output-text.mjs +3 -3
  220. package/internal/responses/canonical-output-text.mjs.map +1 -1
  221. package/internal/responses/response-accumulator.d.mts +1 -1
  222. package/internal/responses/response-accumulator.d.mts.map +1 -1
  223. package/internal/responses/response-accumulator.d.ts +1 -1
  224. package/internal/responses/response-accumulator.d.ts.map +1 -1
  225. package/internal/responses/response-accumulator.js +331 -25
  226. package/internal/responses/response-accumulator.js.map +1 -1
  227. package/internal/responses/response-accumulator.mjs +331 -25
  228. package/internal/responses/response-accumulator.mjs.map +1 -1
  229. package/internal/tslib.js +6 -0
  230. package/internal/tslib.mjs +6 -1
  231. package/internal/uploads.d.mts +10 -6
  232. package/internal/uploads.d.mts.map +1 -1
  233. package/internal/uploads.d.ts +10 -6
  234. package/internal/uploads.d.ts.map +1 -1
  235. package/internal/uploads.js +65 -24
  236. package/internal/uploads.js.map +1 -1
  237. package/internal/uploads.mjs +65 -24
  238. package/internal/uploads.mjs.map +1 -1
  239. package/internal/utils/env.d.mts.map +1 -1
  240. package/internal/utils/env.d.ts.map +1 -1
  241. package/internal/utils/env.js +9 -4
  242. package/internal/utils/env.js.map +1 -1
  243. package/internal/utils/env.mjs +9 -4
  244. package/internal/utils/env.mjs.map +1 -1
  245. package/internal/ws.d.mts.map +1 -1
  246. package/internal/ws.d.ts.map +1 -1
  247. package/internal/ws.js +23 -1
  248. package/internal/ws.js.map +1 -1
  249. package/internal/ws.mjs +23 -1
  250. package/internal/ws.mjs.map +1 -1
  251. package/lib/AbstractChatCompletionRunner.d.mts.map +1 -1
  252. package/lib/AbstractChatCompletionRunner.d.ts.map +1 -1
  253. package/lib/AbstractChatCompletionRunner.js +32 -7
  254. package/lib/AbstractChatCompletionRunner.js.map +1 -1
  255. package/lib/AbstractChatCompletionRunner.mjs +34 -9
  256. package/lib/AbstractChatCompletionRunner.mjs.map +1 -1
  257. package/lib/AssistantStream.d.mts.map +1 -1
  258. package/lib/AssistantStream.d.ts.map +1 -1
  259. package/lib/AssistantStream.js +211 -23
  260. package/lib/AssistantStream.js.map +1 -1
  261. package/lib/AssistantStream.mjs +211 -23
  262. package/lib/AssistantStream.mjs.map +1 -1
  263. package/lib/ChatCompletionStream.d.mts +1 -1
  264. package/lib/ChatCompletionStream.d.mts.map +1 -1
  265. package/lib/ChatCompletionStream.d.ts +1 -1
  266. package/lib/ChatCompletionStream.d.ts.map +1 -1
  267. package/lib/ChatCompletionStream.js +1118 -67
  268. package/lib/ChatCompletionStream.js.map +1 -1
  269. package/lib/ChatCompletionStream.mjs +1119 -68
  270. package/lib/ChatCompletionStream.mjs.map +1 -1
  271. package/lib/EventEmitter.d.mts.map +1 -1
  272. package/lib/EventEmitter.d.ts.map +1 -1
  273. package/lib/EventEmitter.js +67 -9
  274. package/lib/EventEmitter.js.map +1 -1
  275. package/lib/EventEmitter.mjs +68 -10
  276. package/lib/EventEmitter.mjs.map +1 -1
  277. package/lib/EventStream.d.mts +4 -0
  278. package/lib/EventStream.d.mts.map +1 -1
  279. package/lib/EventStream.d.ts +4 -0
  280. package/lib/EventStream.d.ts.map +1 -1
  281. package/lib/EventStream.js +1096 -11
  282. package/lib/EventStream.js.map +1 -1
  283. package/lib/EventStream.mjs +1097 -12
  284. package/lib/EventStream.mjs.map +1 -1
  285. package/lib/ResponsesParser.d.mts.map +1 -1
  286. package/lib/ResponsesParser.d.ts.map +1 -1
  287. package/lib/ResponsesParser.js +1 -1
  288. package/lib/ResponsesParser.js.map +1 -1
  289. package/lib/ResponsesParser.mjs +1 -1
  290. package/lib/ResponsesParser.mjs.map +1 -1
  291. package/lib/Util.d.mts +2 -0
  292. package/lib/Util.d.mts.map +1 -1
  293. package/lib/Util.d.ts +2 -0
  294. package/lib/Util.d.ts.map +1 -1
  295. package/lib/Util.js +7 -4
  296. package/lib/Util.js.map +1 -1
  297. package/lib/Util.mjs +7 -4
  298. package/lib/Util.mjs.map +1 -1
  299. package/lib/assistant-run-polling.d.mts +12 -0
  300. package/lib/assistant-run-polling.d.mts.map +1 -0
  301. package/lib/assistant-run-polling.d.ts +12 -0
  302. package/lib/assistant-run-polling.d.ts.map +1 -0
  303. package/lib/assistant-run-polling.js +17 -0
  304. package/lib/assistant-run-polling.js.map +1 -0
  305. package/lib/assistant-run-polling.mjs +14 -0
  306. package/lib/assistant-run-polling.mjs.map +1 -0
  307. package/lib/embeddings.d.mts +18 -0
  308. package/lib/embeddings.d.mts.map +1 -0
  309. package/lib/embeddings.d.ts +18 -0
  310. package/lib/embeddings.d.ts.map +1 -0
  311. package/lib/embeddings.js +50 -0
  312. package/lib/embeddings.js.map +1 -0
  313. package/lib/embeddings.mjs +47 -0
  314. package/lib/embeddings.mjs.map +1 -0
  315. package/lib/file-processing.d.mts +10 -0
  316. package/lib/file-processing.d.mts.map +1 -0
  317. package/lib/file-processing.d.ts +10 -0
  318. package/lib/file-processing.d.ts.map +1 -0
  319. package/lib/file-processing.js +30 -0
  320. package/lib/file-processing.js.map +1 -0
  321. package/lib/file-processing.mjs +27 -0
  322. package/lib/file-processing.mjs.map +1 -0
  323. package/lib/parser.d.mts.map +1 -1
  324. package/lib/parser.d.ts.map +1 -1
  325. package/lib/parser.js +16 -4
  326. package/lib/parser.js.map +1 -1
  327. package/lib/parser.mjs +16 -4
  328. package/lib/parser.mjs.map +1 -1
  329. package/lib/polling.d.mts +20 -0
  330. package/lib/polling.d.mts.map +1 -0
  331. package/lib/polling.d.ts +20 -0
  332. package/lib/polling.d.ts.map +1 -0
  333. package/lib/polling.js +130 -0
  334. package/lib/polling.js.map +1 -0
  335. package/lib/polling.mjs +127 -0
  336. package/lib/polling.mjs.map +1 -0
  337. package/lib/responses/ResponseStream.d.mts.map +1 -1
  338. package/lib/responses/ResponseStream.d.ts.map +1 -1
  339. package/lib/responses/ResponseStream.js +21 -11
  340. package/lib/responses/ResponseStream.js.map +1 -1
  341. package/lib/responses/ResponseStream.mjs +21 -11
  342. package/lib/responses/ResponseStream.mjs.map +1 -1
  343. package/lib/vector-store-polling.d.mts +22 -0
  344. package/lib/vector-store-polling.d.mts.map +1 -0
  345. package/lib/vector-store-polling.d.ts +22 -0
  346. package/lib/vector-store-polling.d.ts.map +1 -0
  347. package/lib/vector-store-polling.js +24 -0
  348. package/lib/vector-store-polling.js.map +1 -0
  349. package/lib/vector-store-polling.mjs +20 -0
  350. package/lib/vector-store-polling.mjs.map +1 -0
  351. package/lib/vector-store-upload.d.mts +17 -0
  352. package/lib/vector-store-upload.d.mts.map +1 -0
  353. package/lib/vector-store-upload.d.ts +17 -0
  354. package/lib/vector-store-upload.d.ts.map +1 -0
  355. package/lib/vector-store-upload.js +37 -0
  356. package/lib/vector-store-upload.js.map +1 -0
  357. package/lib/vector-store-upload.mjs +34 -0
  358. package/lib/vector-store-upload.mjs.map +1 -0
  359. package/lib/webhook-signature.d.mts +15 -0
  360. package/lib/webhook-signature.d.mts.map +1 -0
  361. package/lib/webhook-signature.d.ts +15 -0
  362. package/lib/webhook-signature.d.ts.map +1 -0
  363. package/lib/webhook-signature.js +125 -0
  364. package/lib/webhook-signature.js.map +1 -0
  365. package/lib/webhook-signature.mjs +121 -0
  366. package/lib/webhook-signature.mjs.map +1 -0
  367. package/package.json +14 -1
  368. package/realtime/internal-base.d.mts +2 -0
  369. package/realtime/internal-base.d.mts.map +1 -1
  370. package/realtime/internal-base.d.ts +2 -0
  371. package/realtime/internal-base.d.ts.map +1 -1
  372. package/realtime/internal-base.js +15 -0
  373. package/realtime/internal-base.js.map +1 -1
  374. package/realtime/internal-base.mjs +14 -0
  375. package/realtime/internal-base.mjs.map +1 -1
  376. package/realtime/websocket.d.mts +3 -2
  377. package/realtime/websocket.d.mts.map +1 -1
  378. package/realtime/websocket.d.ts +3 -2
  379. package/realtime/websocket.d.ts.map +1 -1
  380. package/realtime/websocket.js +90 -26
  381. package/realtime/websocket.js.map +1 -1
  382. package/realtime/websocket.mjs +91 -27
  383. package/realtime/websocket.mjs.map +1 -1
  384. package/realtime/ws.d.mts.map +1 -1
  385. package/realtime/ws.d.ts.map +1 -1
  386. package/realtime/ws.js +9 -1
  387. package/realtime/ws.js.map +1 -1
  388. package/realtime/ws.mjs +10 -2
  389. package/realtime/ws.mjs.map +1 -1
  390. package/resources/admin/organization/index.d.mts +2 -2
  391. package/resources/admin/organization/index.d.mts.map +1 -1
  392. package/resources/admin/organization/index.d.ts +2 -2
  393. package/resources/admin/organization/index.d.ts.map +1 -1
  394. package/resources/admin/organization/index.js.map +1 -1
  395. package/resources/admin/organization/index.mjs.map +1 -1
  396. package/resources/admin/organization/organization.d.mts +4 -4
  397. package/resources/admin/organization/organization.d.mts.map +1 -1
  398. package/resources/admin/organization/organization.d.ts +4 -4
  399. package/resources/admin/organization/organization.d.ts.map +1 -1
  400. package/resources/admin/organization/organization.js.map +1 -1
  401. package/resources/admin/organization/organization.mjs.map +1 -1
  402. package/resources/admin/organization/projects/index.d.mts +1 -1
  403. package/resources/admin/organization/projects/index.d.mts.map +1 -1
  404. package/resources/admin/organization/projects/index.d.ts +1 -1
  405. package/resources/admin/organization/projects/index.d.ts.map +1 -1
  406. package/resources/admin/organization/projects/index.js.map +1 -1
  407. package/resources/admin/organization/projects/index.mjs.map +1 -1
  408. package/resources/admin/organization/projects/projects.d.mts +22 -5
  409. package/resources/admin/organization/projects/projects.d.mts.map +1 -1
  410. package/resources/admin/organization/projects/projects.d.ts +22 -5
  411. package/resources/admin/organization/projects/projects.d.ts.map +1 -1
  412. package/resources/admin/organization/projects/projects.js.map +1 -1
  413. package/resources/admin/organization/projects/projects.mjs.map +1 -1
  414. package/resources/admin/organization/usage.d.mts +62 -1
  415. package/resources/admin/organization/usage.d.mts.map +1 -1
  416. package/resources/admin/organization/usage.d.ts +62 -1
  417. package/resources/admin/organization/usage.d.ts.map +1 -1
  418. package/resources/admin/organization/usage.js.map +1 -1
  419. package/resources/admin/organization/usage.mjs.map +1 -1
  420. package/resources/beta/responses/internal-base.d.mts.map +1 -1
  421. package/resources/beta/responses/internal-base.d.ts.map +1 -1
  422. package/resources/beta/responses/internal-base.js +2 -0
  423. package/resources/beta/responses/internal-base.js.map +1 -1
  424. package/resources/beta/responses/internal-base.mjs +2 -0
  425. package/resources/beta/responses/internal-base.mjs.map +1 -1
  426. package/resources/beta/responses/responses.d.mts +9 -12
  427. package/resources/beta/responses/responses.d.mts.map +1 -1
  428. package/resources/beta/responses/responses.d.ts +9 -12
  429. package/resources/beta/responses/responses.d.ts.map +1 -1
  430. package/resources/beta/responses/responses.js.map +1 -1
  431. package/resources/beta/responses/responses.mjs.map +1 -1
  432. package/resources/beta/threads/runs/index.d.mts +1 -1
  433. package/resources/beta/threads/runs/index.d.mts.map +1 -1
  434. package/resources/beta/threads/runs/index.d.ts +1 -1
  435. package/resources/beta/threads/runs/index.d.ts.map +1 -1
  436. package/resources/beta/threads/runs/runs.d.mts.map +1 -1
  437. package/resources/beta/threads/runs/runs.d.ts.map +1 -1
  438. package/resources/beta/threads/runs/runs.js +2 -43
  439. package/resources/beta/threads/runs/runs.js.map +1 -1
  440. package/resources/beta/threads/runs/runs.mjs +2 -43
  441. package/resources/beta/threads/runs/runs.mjs.map +1 -1
  442. package/resources/chat/completions/completions.d.mts +6 -0
  443. package/resources/chat/completions/completions.d.mts.map +1 -1
  444. package/resources/chat/completions/completions.d.ts +6 -0
  445. package/resources/chat/completions/completions.d.ts.map +1 -1
  446. package/resources/chat/completions/completions.js.map +1 -1
  447. package/resources/chat/completions/completions.mjs.map +1 -1
  448. package/resources/embeddings.d.mts.map +1 -1
  449. package/resources/embeddings.d.ts.map +1 -1
  450. package/resources/embeddings.js +2 -36
  451. package/resources/embeddings.js.map +1 -1
  452. package/resources/embeddings.mjs +2 -36
  453. package/resources/embeddings.mjs.map +1 -1
  454. package/resources/files.d.mts.map +1 -1
  455. package/resources/files.d.ts.map +1 -1
  456. package/resources/files.js +2 -15
  457. package/resources/files.js.map +1 -1
  458. package/resources/files.mjs +2 -15
  459. package/resources/files.mjs.map +1 -1
  460. package/resources/images.d.mts +12 -22
  461. package/resources/images.d.mts.map +1 -1
  462. package/resources/images.d.ts +12 -22
  463. package/resources/images.d.ts.map +1 -1
  464. package/resources/realtime/calls.d.mts +23 -1
  465. package/resources/realtime/calls.d.mts.map +1 -1
  466. package/resources/realtime/calls.d.ts +23 -1
  467. package/resources/realtime/calls.d.ts.map +1 -1
  468. package/resources/realtime/calls.js +24 -0
  469. package/resources/realtime/calls.js.map +1 -1
  470. package/resources/realtime/calls.mjs +24 -0
  471. package/resources/realtime/calls.mjs.map +1 -1
  472. package/resources/realtime/index.d.mts +1 -1
  473. package/resources/realtime/index.d.mts.map +1 -1
  474. package/resources/realtime/index.d.ts +1 -1
  475. package/resources/realtime/index.d.ts.map +1 -1
  476. package/resources/realtime/index.js.map +1 -1
  477. package/resources/realtime/index.mjs +1 -1
  478. package/resources/realtime/index.mjs.map +1 -1
  479. package/resources/realtime/realtime.d.mts +5 -4
  480. package/resources/realtime/realtime.d.mts.map +1 -1
  481. package/resources/realtime/realtime.d.ts +5 -4
  482. package/resources/realtime/realtime.d.ts.map +1 -1
  483. package/resources/realtime/realtime.js.map +1 -1
  484. package/resources/realtime/realtime.mjs.map +1 -1
  485. package/resources/responses/internal-base.d.mts.map +1 -1
  486. package/resources/responses/internal-base.d.ts.map +1 -1
  487. package/resources/responses/internal-base.js +2 -0
  488. package/resources/responses/internal-base.js.map +1 -1
  489. package/resources/responses/internal-base.mjs +2 -0
  490. package/resources/responses/internal-base.mjs.map +1 -1
  491. package/resources/responses/responses.d.mts +9 -12
  492. package/resources/responses/responses.d.mts.map +1 -1
  493. package/resources/responses/responses.d.ts +9 -12
  494. package/resources/responses/responses.d.ts.map +1 -1
  495. package/resources/responses/responses.js.map +1 -1
  496. package/resources/responses/responses.mjs.map +1 -1
  497. package/resources/vector-stores/file-batches.d.mts.map +1 -1
  498. package/resources/vector-stores/file-batches.d.ts.map +1 -1
  499. package/resources/vector-stores/file-batches.js +4 -61
  500. package/resources/vector-stores/file-batches.js.map +1 -1
  501. package/resources/vector-stores/file-batches.mjs +4 -61
  502. package/resources/vector-stores/file-batches.mjs.map +1 -1
  503. package/resources/vector-stores/files.d.mts +1 -1
  504. package/resources/vector-stores/files.d.mts.map +1 -1
  505. package/resources/vector-stores/files.d.ts +1 -1
  506. package/resources/vector-stores/files.d.ts.map +1 -1
  507. package/resources/vector-stores/files.js +2 -35
  508. package/resources/vector-stores/files.js.map +1 -1
  509. package/resources/vector-stores/files.mjs +2 -35
  510. package/resources/vector-stores/files.mjs.map +1 -1
  511. package/resources/webhooks/webhooks.d.mts.map +1 -1
  512. package/resources/webhooks/webhooks.d.ts.map +1 -1
  513. package/resources/webhooks/webhooks.js +5 -43
  514. package/resources/webhooks/webhooks.js.map +1 -1
  515. package/resources/webhooks/webhooks.mjs +5 -43
  516. package/resources/webhooks/webhooks.mjs.map +1 -1
  517. package/src/auth/index.ts +6 -1
  518. package/src/auth/subject-token-providers.ts +196 -4
  519. package/src/auth/types.ts +24 -0
  520. package/src/auth/workload-identity-auth.ts +104 -7
  521. package/src/auth/x509-transport.ts +49 -0
  522. package/src/azure.ts +22 -1
  523. package/src/bedrock.ts +49 -5
  524. package/src/beta/realtime/internal-base.ts +15 -0
  525. package/src/beta/realtime/websocket.ts +148 -40
  526. package/src/beta/realtime/ws.ts +31 -13
  527. package/src/client.ts +536 -92
  528. package/src/core/EventEmitter.ts +91 -7
  529. package/src/core/streaming.ts +71 -20
  530. package/src/helpers/audio.ts +93 -22
  531. package/src/helpers/standard-schema.ts +50 -16
  532. package/src/helpers/zod-v3-strict-schema.ts +514 -0
  533. package/src/helpers/zod.ts +17 -4
  534. package/src/index.ts +1 -1
  535. package/src/internal/assistant-stream-delta.ts +33 -10
  536. package/src/internal/auth/x509-token-exchange.ts +310 -0
  537. package/src/internal/auth/x509-transport-capability.ts +219 -0
  538. package/src/internal/auth/x509-transport-registry.ts +118 -0
  539. package/src/internal/auth/x509-transport-state-browser.ts +36 -0
  540. package/src/internal/auth/x509-transport-state.cts +36 -0
  541. package/src/internal/auth/x509-workload-identity-auth.ts +958 -0
  542. package/src/internal/bedrock.ts +182 -5
  543. package/src/internal/data-residency.ts +44 -0
  544. package/src/internal/multipart-encoding.ts +53 -0
  545. package/src/internal/qs/utils.ts +375 -13
  546. package/src/internal/request-options.ts +52 -1
  547. package/src/internal/responses/canonical-output-text.ts +3 -3
  548. package/src/internal/responses/response-accumulator.ts +411 -24
  549. package/src/internal/uploads.ts +81 -26
  550. package/src/internal/utils/env.ts +9 -5
  551. package/src/internal/ws.ts +24 -3
  552. package/src/lib/AbstractChatCompletionRunner.ts +33 -6
  553. package/src/lib/AssistantStream.ts +262 -22
  554. package/src/lib/ChatCompletionStream.ts +1467 -103
  555. package/src/lib/EventEmitter.ts +91 -7
  556. package/src/lib/EventStream.ts +1483 -10
  557. package/src/lib/ResponsesParser.ts +4 -1
  558. package/src/lib/Util.ts +7 -5
  559. package/src/lib/assistant-run-polling.ts +27 -0
  560. package/src/lib/embeddings.ts +65 -0
  561. package/src/lib/file-processing.ts +36 -0
  562. package/src/lib/parser.ts +19 -4
  563. package/src/lib/polling.ts +144 -0
  564. package/src/lib/responses/ResponseStream.ts +22 -10
  565. package/src/lib/vector-store-polling.ts +46 -0
  566. package/src/lib/vector-store-upload.ts +53 -0
  567. package/src/lib/webhook-signature.ts +164 -0
  568. package/src/realtime/internal-base.ts +15 -0
  569. package/src/realtime/websocket.ts +130 -27
  570. package/src/realtime/ws.ts +15 -2
  571. package/src/resources/admin/organization/index.ts +2 -0
  572. package/src/resources/admin/organization/organization.ts +4 -0
  573. package/src/resources/admin/organization/projects/index.ts +1 -0
  574. package/src/resources/admin/organization/projects/projects.ts +37 -4
  575. package/src/resources/admin/organization/usage.ts +83 -0
  576. package/src/resources/beta/responses/internal-base.ts +2 -0
  577. package/src/resources/beta/responses/responses.ts +9 -12
  578. package/src/resources/beta/threads/runs/index.ts +1 -1
  579. package/src/resources/beta/threads/runs/runs.ts +2 -45
  580. package/src/resources/chat/completions/completions.ts +7 -0
  581. package/src/resources/embeddings.ts +2 -42
  582. package/src/resources/files.ts +2 -19
  583. package/src/resources/images.ts +12 -22
  584. package/src/resources/realtime/api.md +1 -0
  585. package/src/resources/realtime/calls.ts +46 -0
  586. package/src/resources/realtime/index.ts +7 -1
  587. package/src/resources/realtime/realtime.ts +5 -3
  588. package/src/resources/responses/internal-base.ts +2 -0
  589. package/src/resources/responses/responses.ts +9 -12
  590. package/src/resources/vector-stores/file-batches.ts +8 -77
  591. package/src/resources/vector-stores/files.ts +3 -43
  592. package/src/resources/webhooks/webhooks.ts +5 -61
  593. package/src/version.ts +1 -1
  594. package/version.d.mts +1 -1
  595. package/version.d.ts +1 -1
  596. package/version.js +1 -1
  597. package/version.mjs +1 -1
@@ -0,0 +1,958 @@
1
+ import { APIConnectionTimeoutError, APIUserAbortError, OAuthError, OpenAIError } from '../../core/error';
2
+ import type { WorkloadIdentity, X509WorkloadIdentity } from '../../auth/types';
3
+ import type { Fetch } from '../builtin-types';
4
+ import { buildHeaders } from '../headers';
5
+ import type { HeadersLike, NullableHeaders } from '../headers';
6
+ import type { FinalRequestOptions } from '../request-options';
7
+ import { CancelReadableStream } from '../shims';
8
+ import type { MergedRequestInit } from '../types';
9
+ import { hasOwn } from '../utils/values';
10
+ import { resolveX509Transport } from './x509-transport-registry';
11
+ import {
12
+ isApprovedX509Client,
13
+ findX509OAuthError,
14
+ isRetryableX509IssuerError,
15
+ isTransientX509ConnectionError,
16
+ } from '#x509-transport-state';
17
+ import type {
18
+ RegisteredX509Transport,
19
+ X509ExchangedToken,
20
+ X509RequestScope,
21
+ X509Transport,
22
+ } from './x509-transport-registry';
23
+
24
+ /** Sole API authority approved for OpenAI X.509 workload-identity federation. */
25
+ export const X509_API_BASE_URL = 'https://mtls.api.openai.com/v1';
26
+
27
+ const X509_API_ORIGIN = 'https://mtls.api.openai.com';
28
+ const FORBIDDEN_TRANSPORT_OPTIONS = ['dispatcher', 'agent', 'client', 'tls', 'proxy'];
29
+ const headerValue = (headers: Headers, name: string): string | null =>
30
+ Headers.prototype.get.call(headers, name);
31
+ const DEFAULT_REFRESH_BUFFER_MS = 20 * 60 * 1000;
32
+ const FAILED_REFRESH_COOLDOWN_MS = 1000;
33
+ const userAbortError = (signal: AbortSignal): APIUserAbortError => {
34
+ const error = new APIUserAbortError();
35
+ Object.defineProperty(error, 'cause', { value: signal.reason, writable: true, configurable: true });
36
+ return error;
37
+ };
38
+
39
+ function assertSafeHeaders(headers: Headers): void {
40
+ for (const name of Headers.prototype.keys.call(headers)) {
41
+ const canonical = name.toLowerCase().split('_').join('-');
42
+ if (
43
+ canonical === 'api-key' ||
44
+ canonical === 'x-api-key' ||
45
+ canonical === 'proxy-authorization' ||
46
+ canonical === 'host'
47
+ ) {
48
+ throw new OpenAIError('X.509 workload identity cannot send conflicting authentication credentials.');
49
+ }
50
+ }
51
+ }
52
+
53
+ function exchangeDeadline(
54
+ timeout: number | undefined,
55
+ callerSignal: AbortSignal | null | undefined,
56
+ ): { signal: AbortSignal; dispose: () => void } {
57
+ const deadline = new AbortController();
58
+ const timer =
59
+ timeout === undefined
60
+ ? undefined
61
+ : setTimeout(() => deadline.abort(new APIConnectionTimeoutError()), timeout);
62
+ const timerHandle: unknown = timer;
63
+ if (
64
+ typeof timerHandle === 'object' &&
65
+ timerHandle !== null &&
66
+ 'unref' in timerHandle &&
67
+ typeof timerHandle.unref === 'function'
68
+ ) {
69
+ timerHandle.unref();
70
+ }
71
+ const cancel = () => deadline.abort(callerSignal?.reason);
72
+ callerSignal?.addEventListener('abort', cancel, { once: true });
73
+ if (callerSignal?.aborted) {
74
+ cancel();
75
+ }
76
+ return {
77
+ signal: deadline.signal,
78
+ dispose: () => {
79
+ callerSignal?.removeEventListener('abort', cancel);
80
+ if (timer) {
81
+ clearTimeout(timer);
82
+ }
83
+ },
84
+ };
85
+ }
86
+
87
+ interface CachedX509Token {
88
+ accessToken: string;
89
+ generation: number;
90
+ expiresAt: number;
91
+ refreshAt: number;
92
+ wallExpiresAt: number;
93
+ wallRefreshAt: number;
94
+ }
95
+
96
+ interface X509RefreshAttempt {
97
+ controller: AbortController;
98
+ generation: number;
99
+ promise: Promise<X509ExchangedToken>;
100
+ waiters: number;
101
+ }
102
+
103
+ interface X509TokenRequestContext {
104
+ apiURL: string;
105
+ defaultHeaders: HeadersLike | undefined;
106
+ requestHeaders: HeadersLike;
107
+ signal: AbortSignal | null | undefined;
108
+ organization: string | null;
109
+ project: string | null;
110
+ timeout: number;
111
+ fetchOptions: MergedRequestInit;
112
+ }
113
+
114
+ function waitForRefresh(
115
+ attempt: X509RefreshAttempt,
116
+ signal: AbortSignal,
117
+ ): { result: Promise<X509ExchangedToken>; dispose: () => void } {
118
+ let abort: (() => void) | undefined;
119
+ // AbortSignal remains callback-only on supported TypeScript/runtime combinations.
120
+ // oxlint-disable-next-line promise/avoid-new -- A callback-only AbortSignal must race a shared refresh.
121
+ const canceled = new Promise<never>((_resolve, reject) => {
122
+ abort = () => reject(signal.reason);
123
+ signal.addEventListener('abort', abort, { once: true });
124
+ if (signal.aborted) {
125
+ abort();
126
+ }
127
+ });
128
+ return {
129
+ result: Promise.race([attempt.promise, canceled]),
130
+ dispose: () => {
131
+ if (abort) {
132
+ signal.removeEventListener('abort', abort);
133
+ }
134
+ },
135
+ };
136
+ }
137
+
138
+ /** Distinguishes true certificate identities from extensible legacy subject-token identities. */
139
+ export function isX509WorkloadIdentity(
140
+ identity: WorkloadIdentity | X509WorkloadIdentity | undefined,
141
+ ): identity is X509WorkloadIdentity {
142
+ if (!identity || typeof identity !== 'object') {
143
+ return false;
144
+ }
145
+
146
+ let providerOwner: object | null = identity;
147
+ while (providerOwner !== null && providerOwner !== Object.prototype) {
148
+ const provider = Object.getOwnPropertyDescriptor(providerOwner, 'provider');
149
+ if (provider) {
150
+ if (!('value' in provider) || provider.value !== undefined) {
151
+ return false;
152
+ }
153
+ break;
154
+ }
155
+ providerOwner = Object.getPrototypeOf(providerOwner) as object | null;
156
+ }
157
+
158
+ let current: object | null = identity;
159
+ while (current !== null && current !== Object.prototype) {
160
+ const discriminator = Object.getOwnPropertyDescriptor(current, 'type');
161
+ if (discriminator) {
162
+ if (!('value' in discriminator)) {
163
+ throw new OpenAIError('X.509 workload identity type must be a plain data property.');
164
+ }
165
+ return discriminator.value === 'x509';
166
+ }
167
+ current = Object.getPrototypeOf(current) as object | null;
168
+ }
169
+ return false;
170
+ }
171
+
172
+ /** Rejects unsupported WebSocket authentication before any connection or credential side effect. */
173
+ export function assertX509WebSocketSupported(client: unknown): void {
174
+ if (!client || typeof client !== 'object') {
175
+ return;
176
+ }
177
+
178
+ if (isApprovedX509Client(client)) {
179
+ throw new OpenAIError('X.509 workload identity does not support WebSocket connections.');
180
+ }
181
+ }
182
+
183
+ /** Rejects every destination outside the sole enrolled, global X.509 API authority. */
184
+ export function assertX509APIOrigin(value: string | URL): URL {
185
+ let target: URL;
186
+ try {
187
+ target = new URL(value);
188
+ } catch {
189
+ throw new OpenAIError('X.509 workload identity requires the approved global mTLS API origin.');
190
+ }
191
+
192
+ if (target.origin !== X509_API_ORIGIN || target.username || target.password) {
193
+ throw new OpenAIError('X.509 workload identity requires the approved global mTLS API origin.');
194
+ }
195
+ return target;
196
+ }
197
+
198
+ /** Prevents caller options from replacing the immutable transport selected at construction. */
199
+ export function assertX509FetchOptions(options: MergedRequestInit | RequestInit | undefined): void {
200
+ if (!options) {
201
+ return;
202
+ }
203
+
204
+ for (const name of FORBIDDEN_TRANSPORT_OPTIONS) {
205
+ if (hasOwn(options, name)) {
206
+ throw new OpenAIError('X.509 workload identity cannot override its approved transport capability.');
207
+ }
208
+ }
209
+ const redirect: unknown = Object.getOwnPropertyDescriptor(options, 'redirect')?.value;
210
+ if (redirect !== undefined && redirect !== 'manual') {
211
+ throw new OpenAIError('X.509 workload identity requests require manual redirects.');
212
+ }
213
+ }
214
+
215
+ /** Rejects caller overrides while allowing the SDK-owned fields on the final RequestInit. */
216
+ export function assertX509RequestOptions(options: MergedRequestInit | RequestInit | undefined): void {
217
+ assertX509FetchOptions(options);
218
+ if (options && ['body', 'headers', 'method', 'signal'].some((name) => hasOwn(options, name))) {
219
+ throw new OpenAIError(
220
+ 'X.509 workload identity cannot override its request body, headers, method, or signal through fetch options.',
221
+ );
222
+ }
223
+ }
224
+
225
+ /** Validates and snapshots the exact caller options that will reach authenticated dispatch. */
226
+ export function snapshotX509RequestOptions(options: MergedRequestInit | undefined): MergedRequestInit {
227
+ assertX509RequestOptions(options);
228
+ const snapshot = { ...options };
229
+ assertX509RequestOptions(snapshot);
230
+ return snapshot;
231
+ }
232
+
233
+ /** Bridges certificate authentication into existing OpenAI auth and fetch hooks without optional peers. */
234
+ export class X509WorkloadIdentityAuth {
235
+ readonly #identityProviderId: string;
236
+ readonly #serviceAccountId: string;
237
+ readonly #configuredRefreshBufferMs: number | undefined;
238
+ readonly #organization: string | null;
239
+ readonly #project: string | null;
240
+ readonly #transport: RegisteredX509Transport;
241
+ readonly #refreshBufferMs: number;
242
+ #cachedToken: CachedX509Token | undefined;
243
+ #refresh: X509RefreshAttempt | undefined;
244
+ #tokenGeneration = 0;
245
+
246
+ /** Captures one registered, immutable certificate identity and its enrolled selectors. */
247
+ constructor(
248
+ identity: X509WorkloadIdentity,
249
+ transport: X509Transport | undefined,
250
+ organization: string | null,
251
+ project: string | null,
252
+ ) {
253
+ this.#transport = resolveX509Transport(transport);
254
+ this.#identityProviderId = identity.identityProviderId;
255
+ this.#serviceAccountId = identity.serviceAccountId;
256
+ this.#configuredRefreshBufferMs = identity.refreshBufferMs;
257
+ this.#organization = organization;
258
+ this.#project = project;
259
+ if (
260
+ this.#configuredRefreshBufferMs !== undefined &&
261
+ (!Number.isSafeInteger(this.#configuredRefreshBufferMs) || this.#configuredRefreshBufferMs < 0)
262
+ ) {
263
+ throw new OpenAIError('X.509 workload identity requires a nonnegative integer refreshBufferMs.');
264
+ }
265
+ this.#refreshBufferMs = this.#configuredRefreshBufferMs ?? DEFAULT_REFRESH_BUFFER_MS;
266
+ }
267
+
268
+ /** Reconstructs the immutable selectors captured before caller-owned identity mutation. */
269
+ identitySnapshot(): X509WorkloadIdentity {
270
+ return {
271
+ type: 'x509',
272
+ identityProviderId: this.#identityProviderId,
273
+ serviceAccountId: this.#serviceAccountId,
274
+ ...(this.#configuredRefreshBufferMs === undefined
275
+ ? {}
276
+ : { refreshBufferMs: this.#configuredRefreshBufferMs }),
277
+ };
278
+ }
279
+
280
+ /** Preserves explicitly headerless requests without presenting a certificate to the issuer. */
281
+ static shouldAuthenticate(
282
+ options: FinalRequestOptions,
283
+ defaultHeaders: HeadersLike | undefined,
284
+ requestHeaders: HeadersLike = options.headers,
285
+ ): boolean {
286
+ return !buildHeaders([defaultHeaders, requestHeaders]).nulls.has('authorization');
287
+ }
288
+
289
+ /** Snapshots each caller-owned header layer once while preserving nulls and precedence. */
290
+ snapshotHeaders(
291
+ defaultHeaders: HeadersLike,
292
+ requestHeaders: HeadersLike,
293
+ ): { defaultHeaders: NullableHeaders; requestHeaders: NullableHeaders } {
294
+ const scope = this.#scope();
295
+ scope.defaultHeaders ??= buildHeaders([defaultHeaders]);
296
+ scope.requestHeaders ??= buildHeaders([requestHeaders]);
297
+ return this.headerSnapshots();
298
+ }
299
+
300
+ /** Returns the already rendered caller headers without touching mutable inputs again. */
301
+ headerSnapshots(): { defaultHeaders: NullableHeaders; requestHeaders: NullableHeaders } {
302
+ const { defaultHeaders, requestHeaders } = this.#scope();
303
+ if (!defaultHeaders || !requestHeaders) {
304
+ throw new OpenAIError('X.509 workload identity requires snapshotted request headers.');
305
+ }
306
+ return { defaultHeaders, requestHeaders };
307
+ }
308
+
309
+ /** Captures enrolled public tenant selectors once before certificate presentation. */
310
+ snapshotTenant(
311
+ organization: string | null,
312
+ project: string | null,
313
+ ): { organization: string | null; project: string | null } {
314
+ if (organization !== this.#organization || project !== this.#project) {
315
+ throw new OpenAIError('X.509 workload identity cannot override its enrolled organization or project.');
316
+ }
317
+ const scope = this.#scope();
318
+ scope.tenant = { organization, project };
319
+ return scope.tenant;
320
+ }
321
+
322
+ /** Returns the tenant selectors already approved for this logical request. */
323
+ tenantSnapshot(): { organization: string | null; project: string | null } {
324
+ const { tenant } = this.#scope();
325
+ if (!tenant) {
326
+ throw new OpenAIError('X.509 workload identity requires snapshotted tenant selectors.');
327
+ }
328
+ return tenant;
329
+ }
330
+
331
+ /** Validates and retains the exact destination that authenticated dispatch will use. */
332
+ snapshotAPIURL(value: string): void {
333
+ assertX509APIOrigin(value);
334
+ this.#scope().apiURL = value;
335
+ }
336
+
337
+ /** Reads the already-approved destination without rerendering caller-owned request options. */
338
+ requestAPIURL(): string {
339
+ const { apiURL } = this.#scope();
340
+ if (apiURL === undefined) {
341
+ throw new OpenAIError('X.509 workload identity requires a snapshotted API destination.');
342
+ }
343
+ return apiURL;
344
+ }
345
+
346
+ /** Captures the exact caller settings approved for authenticated dispatch. */
347
+ snapshotRequest(
348
+ signal: AbortSignal | null | undefined,
349
+ timeout: number,
350
+ fetchOptions: MergedRequestInit,
351
+ ): void {
352
+ this.#scope().request ??= { signal, timeout, fetchOptions };
353
+ }
354
+
355
+ /** Returns immutable request settings without invoking caller-owned accessors again. */
356
+ requestSnapshot(): {
357
+ signal: AbortSignal | null | undefined;
358
+ timeout: number;
359
+ fetchOptions: MergedRequestInit;
360
+ } {
361
+ const { request } = this.#scope();
362
+ if (!request) {
363
+ throw new OpenAIError('X.509 workload identity requires snapshotted request settings.');
364
+ }
365
+ return request;
366
+ }
367
+
368
+ /** Begins local request construction without charging protected hook latency to the network. */
369
+ beginRequestPlanning(): void {
370
+ this.#scope().phase = 'planning';
371
+ }
372
+
373
+ /** Arms one absolute network deadline only after all local request preparation completes. */
374
+ beginRequestNetwork(): void {
375
+ const scope = this.#scope();
376
+ if (!scope.deadlineArmed) {
377
+ scope.wallStartedAt = Date.now();
378
+ scope.monotonicStartedAt = performance.now();
379
+ scope.deadlineArmed = true;
380
+ }
381
+ }
382
+
383
+ /** Keeps certificate authentication outside overridable request construction. */
384
+ isPlanningRequest(): boolean {
385
+ return this.#scope().phase === 'planning';
386
+ }
387
+
388
+ /** Approves the final overridden destination and transport before minting a bearer. */
389
+ authorizePlannedRequest(url: string, request: RequestInit, timeout: number, allowHookSignal = false): void {
390
+ const scope = this.#scope();
391
+ const headers = Object.getOwnPropertyDescriptor(request, 'headers');
392
+ const body = Object.getOwnPropertyDescriptor(request, 'body');
393
+ const signal = Object.getOwnPropertyDescriptor(request, 'signal');
394
+ const redirect = Object.getOwnPropertyDescriptor(request, 'redirect');
395
+ if (
396
+ scope.phase !== 'planning' ||
397
+ !headers ||
398
+ !(headers.value instanceof Headers) ||
399
+ (!body && 'body' in request) ||
400
+ [body, signal, redirect].some((descriptor) => descriptor && !('value' in descriptor))
401
+ ) {
402
+ throw new OpenAIError('X.509 workload identity requires an approved final request.');
403
+ }
404
+ this.snapshotAPIURL(url);
405
+ assertX509FetchOptions(request);
406
+ try {
407
+ assertSafeHeaders(headers.value);
408
+ } catch {
409
+ throw new OpenAIError('X.509 workload identity cannot use caller-supplied authentication credentials.');
410
+ }
411
+ if (headerValue(headers.value, 'Authorization') !== null) {
412
+ throw new OpenAIError('X.509 workload identity cannot use caller-supplied authorization credentials.');
413
+ }
414
+ this.#assertTenantHeaders(headers.value);
415
+ if (!allowHookSignal && (signal?.value ?? undefined) !== (this.requestSnapshot().signal ?? undefined)) {
416
+ throw new OpenAIError('X.509 workload identity must preserve its approved request signal.');
417
+ }
418
+ const approved = this.requestSnapshot();
419
+ scope.request = { ...approved, timeout: Math.min(approved.timeout, timeout) };
420
+ scope.phase = 'authorizing';
421
+ }
422
+
423
+ /** Owns only SDK-created iterator adapters until authenticated dispatch takes responsibility. */
424
+ ownRequestBody(body: unknown, source: unknown): void {
425
+ if (body instanceof ReadableStream && body !== source) {
426
+ this.#scope().materializedBody = body;
427
+ }
428
+ }
429
+
430
+ /** Recognizes every one-shot upload before issuer authentication or request replay. */
431
+ static isStreamingRequestBody(body: unknown): boolean {
432
+ return (
433
+ (globalThis.ReadableStream !== undefined && body instanceof globalThis.ReadableStream) ||
434
+ (typeof body === 'object' &&
435
+ body !== null &&
436
+ (Symbol.asyncIterator in body ||
437
+ (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')))
438
+ );
439
+ }
440
+
441
+ /** Retires abandoned upload adapters without masking or blocking their authentication failure. */
442
+ retireRequestBody(): void {
443
+ const scope = this.#scope();
444
+ const body = scope.materializedBody;
445
+ delete scope.materializedBody;
446
+ if (body) {
447
+ void X509WorkloadIdentityAuth.#cancelRequestBody(body);
448
+ }
449
+ }
450
+
451
+ static async #cancelRequestBody(body: ReadableStream): Promise<void> {
452
+ try {
453
+ await CancelReadableStream(body);
454
+ } catch {
455
+ // Upload retirement must never replace the original authentication failure.
456
+ }
457
+ }
458
+
459
+ /** Transfers the dispatched upload while retiring any SDK-owned body replaced by a hook. */
460
+ releaseRequestBody(body: unknown): void {
461
+ const scope = this.#scope();
462
+ if (scope.materializedBody === body) {
463
+ delete scope.materializedBody;
464
+ } else {
465
+ this.retireRequestBody();
466
+ }
467
+ }
468
+
469
+ /** Retains caller-only cancellation separately from SDK-created deadline controllers. */
470
+ setEffectiveSignal(signal: AbortSignal | undefined): void {
471
+ if (signal) {
472
+ this.#scope().effectiveSignal = signal;
473
+ } else {
474
+ delete this.#scope().effectiveSignal;
475
+ }
476
+ }
477
+
478
+ /** Uses protected-hook cancellation when an authenticated attempt enters retry backoff. */
479
+ effectiveSignal(): AbortSignal | null | undefined {
480
+ const scope = this.#scope();
481
+ return scope.effectiveSignal ?? scope.request?.signal;
482
+ }
483
+
484
+ /** Establishes an independent scope even when concurrent requests share caller options. */
485
+ runRequest<T>(operation: () => Promise<T>, requestOwner: object): Promise<T> {
486
+ return this.#transport.run(async () => {
487
+ const scope = this.#transport.current();
488
+ if (!scope) {
489
+ throw new OpenAIError('X.509 workload identity requires an active certificate request scope.');
490
+ }
491
+ scope.owner = this;
492
+ scope.requestOwner = requestOwner;
493
+ try {
494
+ return await operation();
495
+ } finally {
496
+ this.retireRequestBody();
497
+ this.releaseRequestCredentials();
498
+ delete scope.requestOwner;
499
+ delete scope.owner;
500
+ }
501
+ });
502
+ }
503
+
504
+ /** Reports whether a public request-building call already belongs to an active logical operation. */
505
+ inRequest(requestOwner: object): boolean {
506
+ const scope = this.#transport.current();
507
+ return scope?.owner === this && scope.requestOwner === requestOwner && scope.phase !== 'authorizing';
508
+ }
509
+
510
+ /** Shares a cache only when the complete, privately snapshotted credential identity matches. */
511
+ matches(other: X509WorkloadIdentityAuth): boolean {
512
+ return (
513
+ this.#transport === other.#transport &&
514
+ this.#identityProviderId === other.#identityProviderId &&
515
+ this.#serviceAccountId === other.#serviceAccountId &&
516
+ this.#organization === other.#organization &&
517
+ this.#project === other.#project &&
518
+ this.#refreshBufferMs === other.#refreshBufferMs
519
+ );
520
+ }
521
+
522
+ /** Binds deferred response parsing to the original logical request and its unchanged deadline. */
523
+ continuation(): <T>(operation: () => Promise<T>) => Promise<T> {
524
+ const { wallStartedAt, monotonicStartedAt, deadlineArmed, request, requestOwner, effectiveSignal } =
525
+ this.#scope();
526
+ const scope: X509RequestScope = {
527
+ wallStartedAt,
528
+ monotonicStartedAt,
529
+ owner: this,
530
+ ...(deadlineArmed ? { deadlineArmed } : {}),
531
+ ...(request ? { request } : {}),
532
+ ...(effectiveSignal ? { effectiveSignal } : {}),
533
+ ...(requestOwner ? { requestOwner } : {}),
534
+ };
535
+ return (operation) =>
536
+ this.#transport.resume(scope, async () => {
537
+ try {
538
+ return await operation();
539
+ } finally {
540
+ this.releaseRequestCredentials();
541
+ delete scope.requestOwner;
542
+ delete scope.owner;
543
+ }
544
+ });
545
+ }
546
+
547
+ /** Removes dispatched bearer material before settled request promises can retain their scope. */
548
+ releaseRequestCredentials(): void {
549
+ const scope = this.#scope();
550
+ delete scope.request;
551
+ delete scope.phase;
552
+ delete scope.deadlineArmed;
553
+ delete scope.effectiveSignal;
554
+ delete scope.materializedBody;
555
+ delete scope.apiURL;
556
+ delete scope.tenant;
557
+ delete scope.token;
558
+ delete scope.defaultHeaders;
559
+ delete scope.requestHeaders;
560
+ delete scope.tokenGeneration;
561
+ delete scope.headers;
562
+ delete scope.authorization;
563
+ }
564
+
565
+ /** Returns the original authentication start so response consumption shares its request deadline. */
566
+ requestStartedAt(_options: FinalRequestOptions): number | undefined {
567
+ return this.#transport.current()?.wallStartedAt;
568
+ }
569
+
570
+ /** Distinguishes issued workload credentials from independent admin or headerless requests. */
571
+ usedWorkloadToken(_options: FinalRequestOptions): boolean {
572
+ return this.#transport.current()?.token !== undefined;
573
+ }
574
+
575
+ /** Returns the budget left after certificate authentication without starting another timeout. */
576
+ remainingTimeout(_options: FinalRequestOptions, timeout: number): number {
577
+ const scope = this.#transport.current();
578
+ if (scope === undefined) {
579
+ return timeout;
580
+ }
581
+ const remaining = timeout - (performance.now() - scope.monotonicStartedAt);
582
+ if (remaining <= 0) {
583
+ throw new APIConnectionTimeoutError();
584
+ }
585
+ return remaining;
586
+ }
587
+
588
+ /** Cancels active retry timers promptly without changing public caller-abort semantics. */
589
+ async waitForRetry(duration: number, signal?: AbortSignal | null): Promise<void> {
590
+ try {
591
+ await this.#transport.sleep(duration, signal);
592
+ } catch (error) {
593
+ if (signal?.aborted) {
594
+ throw userAbortError(signal);
595
+ }
596
+ throw error;
597
+ }
598
+ }
599
+
600
+ /** Trusts only issuer or connection failures privately branded by the approved transport. */
601
+ static isRetryableFailure(error: unknown): boolean {
602
+ return (
603
+ typeof error === 'object' &&
604
+ error !== null &&
605
+ (isTransientX509ConnectionError(error) || isRetryableX509IssuerError(error))
606
+ );
607
+ }
608
+
609
+ /** Reads safe retry hints only from a privately branded, sanitized issuer response. */
610
+ static retryHeaders(error: unknown): Headers | undefined {
611
+ if (!error || typeof error !== 'object' || !isRetryableX509IssuerError(error)) {
612
+ return undefined;
613
+ }
614
+ const headers: unknown = Object.getOwnPropertyDescriptor(error, 'headers')?.value;
615
+ return headers instanceof Headers ? headers : undefined;
616
+ }
617
+
618
+ /** Exchanges the exact certificate capability selected for the matching API dispatch. */
619
+ async getToken(options?: FinalRequestOptions, context?: X509TokenRequestContext): Promise<string> {
620
+ const callerSignal = context ? context.signal : options?.signal;
621
+ if (callerSignal?.aborted) {
622
+ throw userAbortError(callerSignal);
623
+ }
624
+ if (options) {
625
+ assertX509RequestOptions(context ? context.fetchOptions : options.fetchOptions);
626
+ }
627
+ this.#preflight(context);
628
+
629
+ const scope = options ? this.#scope() : undefined;
630
+ const cached = this.#cachedToken;
631
+ if (cached && performance.now() < cached.refreshAt && Date.now() < cached.wallRefreshAt) {
632
+ return X509WorkloadIdentityAuth.#assignToken(scope, cached);
633
+ }
634
+
635
+ const remaining = context && options ? this.remainingTimeout(options, context.timeout) : context?.timeout;
636
+ const { signal, dispose } = exchangeDeadline(remaining, callerSignal);
637
+ if (callerSignal?.aborted) {
638
+ dispose();
639
+ throw userAbortError(callerSignal);
640
+ }
641
+ const attempt = this.#refresh ?? this.#beginRefresh();
642
+ attempt.waiters += 1;
643
+ const waiter = waitForRefresh(attempt, signal);
644
+
645
+ try {
646
+ const exchanged = await waiter.result;
647
+ const refreshed = this.#cachedToken;
648
+ if (!refreshed || refreshed.accessToken !== exchanged.accessToken) {
649
+ throw new APIUserAbortError();
650
+ }
651
+ return X509WorkloadIdentityAuth.#assignToken(scope, refreshed);
652
+ } catch (error) {
653
+ return await this.#recoverRefreshFailure(error, attempt, cached, scope, options, context);
654
+ } finally {
655
+ waiter.dispose();
656
+ dispose();
657
+ attempt.waiters -= 1;
658
+ this.#retireRefresh(attempt);
659
+ }
660
+ }
661
+
662
+ static #assignToken(scope: X509RequestScope | undefined, token: CachedX509Token): string {
663
+ if (scope) {
664
+ scope.token = token.accessToken;
665
+ scope.tokenGeneration = token.generation;
666
+ }
667
+ return token.accessToken;
668
+ }
669
+
670
+ async #recoverRefreshFailure(
671
+ error: unknown,
672
+ attempt: X509RefreshAttempt,
673
+ cached: CachedX509Token | undefined,
674
+ scope: X509RequestScope | undefined,
675
+ options: FinalRequestOptions | undefined,
676
+ context: X509TokenRequestContext | undefined,
677
+ ): Promise<string> {
678
+ const callerSignal = context ? context.signal : options?.signal;
679
+ if (callerSignal?.aborted) {
680
+ throw userAbortError(callerSignal);
681
+ }
682
+ if (attempt.controller.signal.aborted && attempt.generation !== this.#tokenGeneration) {
683
+ return await this.getToken(options, context);
684
+ }
685
+ const fallback = this.#fallbackToken(error, cached, scope);
686
+ if (fallback !== undefined) {
687
+ return fallback;
688
+ }
689
+ if (error && typeof error === 'object' && !(error instanceof OAuthError)) {
690
+ const oauth:
691
+ | { status: 400 | 401 | 403; error: { error: string } | undefined; headers: Headers }
692
+ | undefined = findX509OAuthError(error);
693
+ if (oauth) {
694
+ throw new OAuthError(oauth.status, oauth.error, oauth.headers);
695
+ }
696
+ }
697
+ throw error;
698
+ }
699
+
700
+ #fallbackToken(
701
+ error: unknown,
702
+ cached: CachedX509Token | undefined,
703
+ scope: X509RequestScope | undefined,
704
+ ): string | undefined {
705
+ if (
706
+ !cached ||
707
+ cached !== this.#cachedToken ||
708
+ performance.now() >= cached.expiresAt ||
709
+ Date.now() >= cached.wallExpiresAt ||
710
+ !X509WorkloadIdentityAuth.isRetryableFailure(error)
711
+ ) {
712
+ return undefined;
713
+ }
714
+ const headers = X509WorkloadIdentityAuth.retryHeaders(error);
715
+ const milliseconds = headers?.get('retry-after-ms');
716
+ let requested = milliseconds ? Number(milliseconds) : undefined;
717
+ const retryAfter = headers?.get('retry-after');
718
+ if (retryAfter && (requested === undefined || Number.isNaN(requested))) {
719
+ const seconds = Number(retryAfter);
720
+ requested = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1000;
721
+ }
722
+ const cooldown =
723
+ requested !== undefined && Number.isFinite(requested) && requested >= 0 && requested <= 60_000
724
+ ? Math.max(FAILED_REFRESH_COOLDOWN_MS, requested)
725
+ : FAILED_REFRESH_COOLDOWN_MS;
726
+ cached.refreshAt = Math.min(cached.expiresAt, performance.now() + cooldown);
727
+ cached.wallRefreshAt = Math.min(cached.wallExpiresAt, Date.now() + cooldown);
728
+ return X509WorkloadIdentityAuth.#assignToken(scope, cached);
729
+ }
730
+
731
+ #retireRefresh(attempt: X509RefreshAttempt): void {
732
+ if (attempt.waiters !== 0 || this.#refresh !== attempt) {
733
+ return;
734
+ }
735
+ queueMicrotask(() => {
736
+ if (attempt.waiters === 0 && this.#refresh === attempt) {
737
+ this.#refresh = undefined;
738
+ this.#tokenGeneration += 1;
739
+ attempt.controller.abort(new APIUserAbortError());
740
+ }
741
+ });
742
+ }
743
+
744
+ #beginRefresh(): X509RefreshAttempt {
745
+ const controller = new AbortController();
746
+ const generation = this.#tokenGeneration;
747
+ const attempt: X509RefreshAttempt = {
748
+ controller,
749
+ generation,
750
+ waiters: 0,
751
+ promise: this.#refreshToken(controller, generation),
752
+ };
753
+ this.#refresh = attempt;
754
+ return attempt;
755
+ }
756
+
757
+ async #refreshToken(controller: AbortController, generation: number): Promise<X509ExchangedToken> {
758
+ const startedAt = performance.now();
759
+ const wallStartedAt = Date.now();
760
+ try {
761
+ const token = await this.#transport.exchange(
762
+ this.#identityProviderId,
763
+ this.#serviceAccountId,
764
+ controller.signal,
765
+ );
766
+ const lifetime = token.expiresIn * 1000;
767
+ const expiresAt = startedAt + lifetime;
768
+ const wallExpiresAt = wallStartedAt + lifetime;
769
+ if (performance.now() >= expiresAt || Date.now() >= wallExpiresAt) {
770
+ throw new OpenAIError('X.509 workload identity token expired before its exchange completed.');
771
+ }
772
+ if (
773
+ this.#tokenGeneration !== generation ||
774
+ controller.signal.aborted ||
775
+ this.#refresh?.controller !== controller
776
+ ) {
777
+ throw new APIUserAbortError();
778
+ }
779
+ this.#tokenGeneration += 1;
780
+ this.#cachedToken = {
781
+ accessToken: token.accessToken,
782
+ generation: this.#tokenGeneration,
783
+ expiresAt,
784
+ refreshAt: expiresAt - Math.min(this.#refreshBufferMs, lifetime / 2),
785
+ wallExpiresAt,
786
+ wallRefreshAt: wallExpiresAt - Math.min(this.#refreshBufferMs, lifetime / 2),
787
+ };
788
+ return token;
789
+ } finally {
790
+ if (this.#refresh?.controller === controller) {
791
+ this.#refresh = undefined;
792
+ }
793
+ }
794
+ }
795
+
796
+ #preflight(context: X509TokenRequestContext | undefined): void {
797
+ if (!context) {
798
+ return;
799
+ }
800
+ if (context.organization !== this.#organization || context.project !== this.#project) {
801
+ throw new OpenAIError('X.509 workload identity cannot override its enrolled organization or project.');
802
+ }
803
+ assertX509APIOrigin(context.apiURL);
804
+ const supplied = buildHeaders([context.defaultHeaders, context.requestHeaders]);
805
+ if (
806
+ (this.#organization !== null && supplied.nulls.has('openai-organization')) ||
807
+ (this.#project !== null && supplied.nulls.has('openai-project'))
808
+ ) {
809
+ throw new OpenAIError('X.509 workload identity cannot omit its enrolled organization or project.');
810
+ }
811
+ for (const name of supplied.values.keys()) {
812
+ const canonical = name.toLowerCase().split('_').join('-');
813
+ if (
814
+ (canonical === 'openai-organization' || canonical === 'openai-project') &&
815
+ (name !== canonical ||
816
+ headerValue(supplied.values, name) !==
817
+ (canonical === 'openai-organization' ? context.organization : context.project))
818
+ ) {
819
+ throw new OpenAIError(
820
+ 'X.509 workload identity cannot override its enrolled organization or project.',
821
+ );
822
+ }
823
+ if (
824
+ canonical === 'authorization' ||
825
+ canonical === 'api-key' ||
826
+ canonical === 'x-api-key' ||
827
+ canonical === 'proxy-authorization' ||
828
+ canonical === 'host'
829
+ ) {
830
+ throw new OpenAIError(
831
+ 'X.509 workload identity cannot use caller-supplied authentication credentials.',
832
+ );
833
+ }
834
+ }
835
+ }
836
+
837
+ /** Invalidates only the workload-token generation actually rejected by the current request. */
838
+ invalidateToken(): void {
839
+ const rejected = this.#transport.current();
840
+ if (
841
+ !rejected?.token ||
842
+ this.#cachedToken?.accessToken !== rejected.token ||
843
+ this.#cachedToken.generation !== rejected.tokenGeneration
844
+ ) {
845
+ return;
846
+ }
847
+ this.#tokenGeneration += 1;
848
+ this.#cachedToken = undefined;
849
+ const refresh = this.#refresh;
850
+ this.#refresh = undefined;
851
+ refresh?.controller.abort(new APIUserAbortError());
852
+ }
853
+
854
+ #scope(): X509RequestScope {
855
+ const scope = this.#transport.current();
856
+ if (!scope || scope.owner !== this) {
857
+ throw new OpenAIError('X.509 workload identity requires an active certificate request scope.');
858
+ }
859
+ return scope;
860
+ }
861
+
862
+ /** Binds the minted credential to the original headers before protected request hooks run. */
863
+ bindRequest(options: FinalRequestOptions, request: RequestInit, adminAPIKey: string | null): void {
864
+ if (!(request.headers instanceof Headers)) {
865
+ throw new OpenAIError('X.509 workload identity requires the original workload authorization headers.');
866
+ }
867
+ const scope = this.#scope();
868
+ const { token } = scope;
869
+ const security = options.__security ?? { bearerAuth: true };
870
+ let approvedAuthorization = token ? `Bearer ${token}` : null;
871
+ if (
872
+ !token &&
873
+ security.adminAPIKeyAuth &&
874
+ adminAPIKey !== null &&
875
+ headerValue(request.headers, 'Authorization') !== null
876
+ ) {
877
+ approvedAuthorization = new Headers({ Authorization: `Bearer ${adminAPIKey}` }).get('Authorization');
878
+ }
879
+ scope.headers = request.headers;
880
+ scope.authorization = approvedAuthorization;
881
+ this.assertRequest(request);
882
+ }
883
+
884
+ /** Rebinds an equivalent protected-hook container without relaxing final dispatch identity checks. */
885
+ adoptRequestHeaders(request: RequestInit): void {
886
+ const scope = this.#scope();
887
+ const original = scope.headers;
888
+ if (!(original instanceof Headers) || !(request.headers instanceof Headers)) {
889
+ throw new OpenAIError('X.509 workload identity must preserve its issued workload authorization.');
890
+ }
891
+ scope.headers = request.headers;
892
+ try {
893
+ this.assertRequest(request);
894
+ } catch (error) {
895
+ scope.headers = original;
896
+ throw error;
897
+ }
898
+ }
899
+
900
+ /** Rejects request hooks that replace the selected bearer or its approved header identity. */
901
+ assertRequest(request: RequestInit): void {
902
+ const { headers } = request;
903
+ if (!(headers instanceof Headers)) {
904
+ throw new OpenAIError('X.509 workload identity must preserve its issued workload authorization.');
905
+ }
906
+ const scope = this.#transport.current();
907
+ if (
908
+ !scope ||
909
+ scope.headers !== headers ||
910
+ scope.authorization === undefined ||
911
+ headerValue(headers, 'Authorization') !== scope.authorization
912
+ ) {
913
+ throw new OpenAIError('X.509 workload identity must preserve its issued workload authorization.');
914
+ }
915
+ this.#assertTenantHeaders(headers);
916
+ assertSafeHeaders(headers);
917
+ }
918
+
919
+ /** Enforces the same enrolled selectors before certificate issuance and final dispatch. */
920
+ #assertTenantHeaders(headers: Headers): void {
921
+ if (
922
+ headerValue(headers, 'OpenAI-Organization') !== this.#organization ||
923
+ headerValue(headers, 'OpenAI-Project') !== this.#project
924
+ ) {
925
+ throw new OpenAIError('X.509 workload identity cannot override its enrolled organization or project.');
926
+ }
927
+ for (const name of Headers.prototype.keys.call(headers)) {
928
+ const canonical = name.toLowerCase().split('_').join('-');
929
+ if ((canonical === 'openai-organization' || canonical === 'openai-project') && name !== canonical) {
930
+ throw new OpenAIError(
931
+ 'X.509 workload identity cannot override its enrolled organization or project.',
932
+ );
933
+ }
934
+ }
935
+ }
936
+
937
+ /** Returns a guarded final dispatcher while preserving all existing request hook object identities. */
938
+ fetch(): Fetch {
939
+ return async (input, init = {}) => {
940
+ const target = assertX509APIOrigin(
941
+ typeof input === 'string' || input instanceof URL ? input : input.url,
942
+ );
943
+ assertX509FetchOptions(init);
944
+ this.assertRequest(init);
945
+
946
+ const approved = init.headers;
947
+ if (!(approved instanceof Headers)) {
948
+ throw new OpenAIError('X.509 workload identity must preserve its issued workload authorization.');
949
+ }
950
+ const headers = new Headers([...Headers.prototype.entries.call(approved)]);
951
+ assertSafeHeaders(headers);
952
+
953
+ init.headers = headers;
954
+ init.redirect = 'manual';
955
+ return await this.#transport.dispatch(target, init);
956
+ };
957
+ }
958
+ }