openai 6.43.0 → 6.45.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 (317) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +85 -102
  3. package/_vendor/zod-to-json-schema/parseDef.d.mts.map +1 -1
  4. package/_vendor/zod-to-json-schema/parseDef.d.ts.map +1 -1
  5. package/_vendor/zod-to-json-schema/parseDef.js +41 -15
  6. package/_vendor/zod-to-json-schema/parseDef.js.map +1 -1
  7. package/_vendor/zod-to-json-schema/parseDef.mjs +41 -15
  8. package/_vendor/zod-to-json-schema/parseDef.mjs.map +1 -1
  9. package/_vendor/zod-to-json-schema/parsers/branded.d.mts +1 -1
  10. package/_vendor/zod-to-json-schema/parsers/branded.d.mts.map +1 -1
  11. package/_vendor/zod-to-json-schema/parsers/branded.d.ts +1 -1
  12. package/_vendor/zod-to-json-schema/parsers/branded.d.ts.map +1 -1
  13. package/_vendor/zod-to-json-schema/parsers/branded.js +2 -2
  14. package/_vendor/zod-to-json-schema/parsers/branded.js.map +1 -1
  15. package/_vendor/zod-to-json-schema/parsers/branded.mjs +2 -2
  16. package/_vendor/zod-to-json-schema/parsers/branded.mjs.map +1 -1
  17. package/_vendor/zod-to-json-schema/parsers/catch.d.mts +1 -1
  18. package/_vendor/zod-to-json-schema/parsers/catch.d.mts.map +1 -1
  19. package/_vendor/zod-to-json-schema/parsers/catch.d.ts +1 -1
  20. package/_vendor/zod-to-json-schema/parsers/catch.d.ts.map +1 -1
  21. package/_vendor/zod-to-json-schema/parsers/catch.js +2 -2
  22. package/_vendor/zod-to-json-schema/parsers/catch.js.map +1 -1
  23. package/_vendor/zod-to-json-schema/parsers/catch.mjs +2 -2
  24. package/_vendor/zod-to-json-schema/parsers/catch.mjs.map +1 -1
  25. package/_vendor/zod-to-json-schema/parsers/default.d.mts +1 -1
  26. package/_vendor/zod-to-json-schema/parsers/default.d.mts.map +1 -1
  27. package/_vendor/zod-to-json-schema/parsers/default.d.ts +1 -1
  28. package/_vendor/zod-to-json-schema/parsers/default.d.ts.map +1 -1
  29. package/_vendor/zod-to-json-schema/parsers/default.js +2 -2
  30. package/_vendor/zod-to-json-schema/parsers/default.js.map +1 -1
  31. package/_vendor/zod-to-json-schema/parsers/default.mjs +2 -2
  32. package/_vendor/zod-to-json-schema/parsers/default.mjs.map +1 -1
  33. package/_vendor/zod-to-json-schema/parsers/nullable.d.mts +1 -1
  34. package/_vendor/zod-to-json-schema/parsers/nullable.d.mts.map +1 -1
  35. package/_vendor/zod-to-json-schema/parsers/nullable.d.ts +1 -1
  36. package/_vendor/zod-to-json-schema/parsers/nullable.d.ts.map +1 -1
  37. package/_vendor/zod-to-json-schema/parsers/nullable.js +2 -2
  38. package/_vendor/zod-to-json-schema/parsers/nullable.js.map +1 -1
  39. package/_vendor/zod-to-json-schema/parsers/nullable.mjs +2 -2
  40. package/_vendor/zod-to-json-schema/parsers/nullable.mjs.map +1 -1
  41. package/_vendor/zod-to-json-schema/parsers/optional.d.mts +1 -1
  42. package/_vendor/zod-to-json-schema/parsers/optional.d.mts.map +1 -1
  43. package/_vendor/zod-to-json-schema/parsers/optional.d.ts +1 -1
  44. package/_vendor/zod-to-json-schema/parsers/optional.d.ts.map +1 -1
  45. package/_vendor/zod-to-json-schema/parsers/optional.js +3 -3
  46. package/_vendor/zod-to-json-schema/parsers/optional.js.map +1 -1
  47. package/_vendor/zod-to-json-schema/parsers/optional.mjs +3 -3
  48. package/_vendor/zod-to-json-schema/parsers/optional.mjs.map +1 -1
  49. package/_vendor/zod-to-json-schema/parsers/pipeline.d.mts +1 -1
  50. package/_vendor/zod-to-json-schema/parsers/pipeline.d.mts.map +1 -1
  51. package/_vendor/zod-to-json-schema/parsers/pipeline.d.ts +1 -1
  52. package/_vendor/zod-to-json-schema/parsers/pipeline.d.ts.map +1 -1
  53. package/_vendor/zod-to-json-schema/parsers/pipeline.js +3 -3
  54. package/_vendor/zod-to-json-schema/parsers/pipeline.js.map +1 -1
  55. package/_vendor/zod-to-json-schema/parsers/pipeline.mjs +3 -3
  56. package/_vendor/zod-to-json-schema/parsers/pipeline.mjs.map +1 -1
  57. package/_vendor/zod-to-json-schema/parsers/promise.d.mts +1 -1
  58. package/_vendor/zod-to-json-schema/parsers/promise.d.mts.map +1 -1
  59. package/_vendor/zod-to-json-schema/parsers/promise.d.ts +1 -1
  60. package/_vendor/zod-to-json-schema/parsers/promise.d.ts.map +1 -1
  61. package/_vendor/zod-to-json-schema/parsers/promise.js +2 -2
  62. package/_vendor/zod-to-json-schema/parsers/promise.js.map +1 -1
  63. package/_vendor/zod-to-json-schema/parsers/promise.mjs +2 -2
  64. package/_vendor/zod-to-json-schema/parsers/promise.mjs.map +1 -1
  65. package/_vendor/zod-to-json-schema/parsers/readonly.d.mts +1 -1
  66. package/_vendor/zod-to-json-schema/parsers/readonly.d.mts.map +1 -1
  67. package/_vendor/zod-to-json-schema/parsers/readonly.d.ts +1 -1
  68. package/_vendor/zod-to-json-schema/parsers/readonly.d.ts.map +1 -1
  69. package/_vendor/zod-to-json-schema/parsers/readonly.js +2 -2
  70. package/_vendor/zod-to-json-schema/parsers/readonly.js.map +1 -1
  71. package/_vendor/zod-to-json-schema/parsers/readonly.mjs +2 -2
  72. package/_vendor/zod-to-json-schema/parsers/readonly.mjs.map +1 -1
  73. package/auth/workload-identity-auth.d.mts.map +1 -1
  74. package/auth/workload-identity-auth.d.ts.map +1 -1
  75. package/auth/workload-identity-auth.js +12 -4
  76. package/auth/workload-identity-auth.js.map +1 -1
  77. package/auth/workload-identity-auth.mjs +13 -5
  78. package/auth/workload-identity-auth.mjs.map +1 -1
  79. package/azure.d.mts +3 -1
  80. package/azure.d.mts.map +1 -1
  81. package/azure.d.ts +3 -1
  82. package/azure.d.ts.map +1 -1
  83. package/azure.js.map +1 -1
  84. package/azure.mjs.map +1 -1
  85. package/beta/realtime/internal-base.d.mts +14 -1
  86. package/beta/realtime/internal-base.d.mts.map +1 -1
  87. package/beta/realtime/internal-base.d.ts +14 -1
  88. package/beta/realtime/internal-base.d.ts.map +1 -1
  89. package/beta/realtime/internal-base.js +21 -5
  90. package/beta/realtime/internal-base.js.map +1 -1
  91. package/beta/realtime/internal-base.mjs +21 -5
  92. package/beta/realtime/internal-base.mjs.map +1 -1
  93. package/beta/realtime/websocket.d.mts +3 -5
  94. package/beta/realtime/websocket.d.mts.map +1 -1
  95. package/beta/realtime/websocket.d.ts +3 -5
  96. package/beta/realtime/websocket.d.ts.map +1 -1
  97. package/beta/realtime/websocket.js +2 -3
  98. package/beta/realtime/websocket.js.map +1 -1
  99. package/beta/realtime/websocket.mjs +3 -4
  100. package/beta/realtime/websocket.mjs.map +1 -1
  101. package/beta/realtime/ws.d.mts +3 -5
  102. package/beta/realtime/ws.d.mts.map +1 -1
  103. package/beta/realtime/ws.d.ts +3 -5
  104. package/beta/realtime/ws.d.ts.map +1 -1
  105. package/beta/realtime/ws.js +2 -3
  106. package/beta/realtime/ws.js.map +1 -1
  107. package/beta/realtime/ws.mjs +3 -4
  108. package/beta/realtime/ws.mjs.map +1 -1
  109. package/client.d.mts +9 -1
  110. package/client.d.mts.map +1 -1
  111. package/client.d.ts +9 -1
  112. package/client.d.ts.map +1 -1
  113. package/client.js +56 -9
  114. package/client.js.map +1 -1
  115. package/client.mjs +56 -9
  116. package/client.mjs.map +1 -1
  117. package/helpers/zod.d.mts.map +1 -1
  118. package/helpers/zod.d.ts.map +1 -1
  119. package/helpers/zod.js +12 -0
  120. package/helpers/zod.js.map +1 -1
  121. package/helpers/zod.mjs +12 -0
  122. package/helpers/zod.mjs.map +1 -1
  123. package/internal/bedrock.d.mts +34 -0
  124. package/internal/bedrock.d.mts.map +1 -0
  125. package/internal/bedrock.d.ts +34 -0
  126. package/internal/bedrock.d.ts.map +1 -0
  127. package/internal/bedrock.js +107 -0
  128. package/internal/bedrock.js.map +1 -0
  129. package/internal/bedrock.mjs +99 -0
  130. package/internal/bedrock.mjs.map +1 -0
  131. package/internal/provider.d.mts +23 -0
  132. package/internal/provider.d.mts.map +1 -0
  133. package/internal/provider.d.ts +23 -0
  134. package/internal/provider.d.ts.map +1 -0
  135. package/internal/provider.js +36 -0
  136. package/internal/provider.js.map +1 -0
  137. package/internal/provider.mjs +32 -0
  138. package/internal/provider.mjs.map +1 -0
  139. package/internal/utils/log.d.mts.map +1 -1
  140. package/internal/utils/log.d.ts.map +1 -1
  141. package/internal/utils/log.js +1 -0
  142. package/internal/utils/log.js.map +1 -1
  143. package/internal/utils/log.mjs +1 -0
  144. package/internal/utils/log.mjs.map +1 -1
  145. package/lib/AbstractChatCompletionRunner.d.mts +15 -4
  146. package/lib/AbstractChatCompletionRunner.d.mts.map +1 -1
  147. package/lib/AbstractChatCompletionRunner.d.ts +15 -4
  148. package/lib/AbstractChatCompletionRunner.d.ts.map +1 -1
  149. package/lib/AbstractChatCompletionRunner.js +63 -40
  150. package/lib/AbstractChatCompletionRunner.js.map +1 -1
  151. package/lib/AbstractChatCompletionRunner.mjs +63 -40
  152. package/lib/AbstractChatCompletionRunner.mjs.map +1 -1
  153. package/lib/AssistantStream.d.mts.map +1 -1
  154. package/lib/AssistantStream.d.ts.map +1 -1
  155. package/lib/AssistantStream.js +4 -24
  156. package/lib/AssistantStream.js.map +1 -1
  157. package/lib/AssistantStream.mjs +4 -24
  158. package/lib/AssistantStream.mjs.map +1 -1
  159. package/lib/ChatCompletionRunner.js +1 -1
  160. package/lib/ChatCompletionRunner.js.map +1 -1
  161. package/lib/ChatCompletionRunner.mjs +1 -1
  162. package/lib/ChatCompletionRunner.mjs.map +1 -1
  163. package/lib/ChatCompletionStream.d.mts.map +1 -1
  164. package/lib/ChatCompletionStream.d.ts.map +1 -1
  165. package/lib/ChatCompletionStream.js +4 -13
  166. package/lib/ChatCompletionStream.js.map +1 -1
  167. package/lib/ChatCompletionStream.mjs +4 -13
  168. package/lib/ChatCompletionStream.mjs.map +1 -1
  169. package/lib/ChatCompletionStreamingRunner.js +1 -1
  170. package/lib/ChatCompletionStreamingRunner.js.map +1 -1
  171. package/lib/ChatCompletionStreamingRunner.mjs +1 -1
  172. package/lib/ChatCompletionStreamingRunner.mjs.map +1 -1
  173. package/lib/EventEmitter.d.mts.map +1 -1
  174. package/lib/EventEmitter.d.ts.map +1 -1
  175. package/lib/EventEmitter.js +12 -2
  176. package/lib/EventEmitter.js.map +1 -1
  177. package/lib/EventEmitter.mjs +12 -2
  178. package/lib/EventEmitter.mjs.map +1 -1
  179. package/lib/EventStream.d.mts +1 -0
  180. package/lib/EventStream.d.mts.map +1 -1
  181. package/lib/EventStream.d.ts +1 -0
  182. package/lib/EventStream.d.ts.map +1 -1
  183. package/lib/EventStream.js +19 -2
  184. package/lib/EventStream.js.map +1 -1
  185. package/lib/EventStream.mjs +19 -2
  186. package/lib/EventStream.mjs.map +1 -1
  187. package/lib/ResponsesParser.d.mts.map +1 -1
  188. package/lib/ResponsesParser.d.ts.map +1 -1
  189. package/lib/ResponsesParser.js +12 -4
  190. package/lib/ResponsesParser.js.map +1 -1
  191. package/lib/ResponsesParser.mjs +12 -4
  192. package/lib/ResponsesParser.mjs.map +1 -1
  193. package/lib/responses/ResponseAccumulator.d.mts +10 -0
  194. package/lib/responses/ResponseAccumulator.d.mts.map +1 -0
  195. package/lib/responses/ResponseAccumulator.d.ts +10 -0
  196. package/lib/responses/ResponseAccumulator.d.ts.map +1 -0
  197. package/lib/responses/ResponseAccumulator.js +402 -0
  198. package/lib/responses/ResponseAccumulator.js.map +1 -0
  199. package/lib/responses/ResponseAccumulator.mjs +399 -0
  200. package/lib/responses/ResponseAccumulator.mjs.map +1 -0
  201. package/lib/responses/ResponseInputItems.d.mts +19 -0
  202. package/lib/responses/ResponseInputItems.d.mts.map +1 -0
  203. package/lib/responses/ResponseInputItems.d.ts +19 -0
  204. package/lib/responses/ResponseInputItems.d.ts.map +1 -0
  205. package/lib/responses/ResponseInputItems.js +102 -0
  206. package/lib/responses/ResponseInputItems.js.map +1 -0
  207. package/lib/responses/ResponseInputItems.mjs +98 -0
  208. package/lib/responses/ResponseInputItems.mjs.map +1 -0
  209. package/lib/responses/ResponseStream.d.mts.map +1 -1
  210. package/lib/responses/ResponseStream.d.ts.map +1 -1
  211. package/lib/responses/ResponseStream.js +5 -90
  212. package/lib/responses/ResponseStream.js.map +1 -1
  213. package/lib/responses/ResponseStream.mjs +5 -90
  214. package/lib/responses/ResponseStream.mjs.map +1 -1
  215. package/package.json +24 -1
  216. package/providers/bedrock/aws.d.mts +24 -0
  217. package/providers/bedrock/aws.d.mts.map +1 -0
  218. package/providers/bedrock/aws.d.ts +24 -0
  219. package/providers/bedrock/aws.d.ts.map +1 -0
  220. package/providers/bedrock/aws.js +170 -0
  221. package/providers/bedrock/aws.js.map +1 -0
  222. package/providers/bedrock/aws.mjs +166 -0
  223. package/providers/bedrock/aws.mjs.map +1 -0
  224. package/providers/bedrock.d.mts +7 -0
  225. package/providers/bedrock.d.mts.map +1 -0
  226. package/providers/bedrock.d.ts +7 -0
  227. package/providers/bedrock.d.ts.map +1 -0
  228. package/providers/bedrock.js +26 -0
  229. package/providers/bedrock.js.map +1 -0
  230. package/providers/bedrock.mjs +22 -0
  231. package/providers/bedrock.mjs.map +1 -0
  232. package/realtime/internal-base.d.mts +28 -1
  233. package/realtime/internal-base.d.mts.map +1 -1
  234. package/realtime/internal-base.d.ts +28 -1
  235. package/realtime/internal-base.d.ts.map +1 -1
  236. package/realtime/internal-base.js +50 -7
  237. package/realtime/internal-base.js.map +1 -1
  238. package/realtime/internal-base.mjs +49 -7
  239. package/realtime/internal-base.mjs.map +1 -1
  240. package/realtime/websocket.d.mts +4 -7
  241. package/realtime/websocket.d.mts.map +1 -1
  242. package/realtime/websocket.d.ts +4 -7
  243. package/realtime/websocket.d.ts.map +1 -1
  244. package/realtime/websocket.js +4 -8
  245. package/realtime/websocket.js.map +1 -1
  246. package/realtime/websocket.mjs +5 -9
  247. package/realtime/websocket.mjs.map +1 -1
  248. package/realtime/ws.d.mts +4 -7
  249. package/realtime/ws.d.mts.map +1 -1
  250. package/realtime/ws.d.ts +4 -7
  251. package/realtime/ws.d.ts.map +1 -1
  252. package/realtime/ws.js +4 -8
  253. package/realtime/ws.js.map +1 -1
  254. package/realtime/ws.mjs +5 -9
  255. package/realtime/ws.mjs.map +1 -1
  256. package/resources/realtime/client-secrets.d.mts +9 -4
  257. package/resources/realtime/client-secrets.d.mts.map +1 -1
  258. package/resources/realtime/client-secrets.d.ts +9 -4
  259. package/resources/realtime/client-secrets.d.ts.map +1 -1
  260. package/resources/realtime/realtime.d.mts +18 -8
  261. package/resources/realtime/realtime.d.mts.map +1 -1
  262. package/resources/realtime/realtime.d.ts +18 -8
  263. package/resources/realtime/realtime.d.ts.map +1 -1
  264. package/resources/realtime/realtime.js.map +1 -1
  265. package/resources/realtime/realtime.mjs.map +1 -1
  266. package/resources/responses/responses.d.mts +9 -4
  267. package/resources/responses/responses.d.mts.map +1 -1
  268. package/resources/responses/responses.d.ts +9 -4
  269. package/resources/responses/responses.d.ts.map +1 -1
  270. package/resources/responses/responses.js.map +1 -1
  271. package/resources/responses/responses.mjs.map +1 -1
  272. package/resources/videos.d.mts +1 -1
  273. package/resources/videos.d.ts +1 -1
  274. package/src/_vendor/zod-to-json-schema/parseDef.ts +44 -16
  275. package/src/_vendor/zod-to-json-schema/parsers/branded.ts +2 -2
  276. package/src/_vendor/zod-to-json-schema/parsers/catch.ts +2 -2
  277. package/src/_vendor/zod-to-json-schema/parsers/default.ts +6 -2
  278. package/src/_vendor/zod-to-json-schema/parsers/nullable.ts +13 -5
  279. package/src/_vendor/zod-to-json-schema/parsers/optional.ts +14 -6
  280. package/src/_vendor/zod-to-json-schema/parsers/pipeline.ts +3 -2
  281. package/src/_vendor/zod-to-json-schema/parsers/promise.ts +6 -2
  282. package/src/_vendor/zod-to-json-schema/parsers/readonly.ts +2 -2
  283. package/src/auth/workload-identity-auth.ts +16 -5
  284. package/src/azure.ts +4 -1
  285. package/src/beta/realtime/internal-base.ts +43 -5
  286. package/src/beta/realtime/websocket.ts +10 -7
  287. package/src/beta/realtime/ws.ts +10 -7
  288. package/src/client.ts +80 -18
  289. package/src/helpers/zod.ts +16 -0
  290. package/src/internal/bedrock.ts +153 -0
  291. package/src/internal/provider.ts +60 -0
  292. package/src/internal/utils/log.ts +1 -0
  293. package/src/lib/AbstractChatCompletionRunner.ts +96 -45
  294. package/src/lib/AssistantStream.ts +4 -20
  295. package/src/lib/ChatCompletionRunner.ts +1 -1
  296. package/src/lib/ChatCompletionStream.ts +4 -11
  297. package/src/lib/ChatCompletionStreamingRunner.ts +1 -1
  298. package/src/lib/EventEmitter.ts +11 -2
  299. package/src/lib/EventStream.ts +20 -0
  300. package/src/lib/ResponsesParser.ts +18 -4
  301. package/src/lib/responses/ResponseAccumulator.ts +412 -0
  302. package/src/lib/responses/ResponseInputItems.ts +127 -0
  303. package/src/lib/responses/ResponseStream.ts +4 -93
  304. package/src/providers/bedrock/aws.ts +255 -0
  305. package/src/providers/bedrock.ts +33 -0
  306. package/src/realtime/internal-base.ts +90 -7
  307. package/src/realtime/websocket.ts +15 -13
  308. package/src/realtime/ws.ts +15 -13
  309. package/src/resources/realtime/client-secrets.ts +10 -4
  310. package/src/resources/realtime/realtime.ts +20 -8
  311. package/src/resources/responses/responses.ts +10 -4
  312. package/src/resources/videos.ts +1 -1
  313. package/src/version.ts +1 -1
  314. package/version.d.mts +1 -1
  315. package/version.d.ts +1 -1
  316. package/version.js +1 -1
  317. package/version.mjs +1 -1
@@ -6,11 +6,12 @@ import { JsonSchema7AllOfType } from './intersection';
6
6
  export const parsePipelineDef = (
7
7
  def: ZodPipelineDef<any, any>,
8
8
  refs: Refs,
9
+ forceResolution: boolean,
9
10
  ): JsonSchema7AllOfType | JsonSchema7Type | undefined => {
10
11
  if (refs.pipeStrategy === 'input') {
11
- return parseDef(def.in._def, refs);
12
+ return parseDef(def.in._def, refs, forceResolution);
12
13
  } else if (refs.pipeStrategy === 'output') {
13
- return parseDef(def.out._def, refs);
14
+ return parseDef(def.out._def, refs, forceResolution);
14
15
  }
15
16
 
16
17
  const a = parseDef(def.in._def, {
@@ -2,6 +2,10 @@ import { ZodPromiseDef } from 'zod/v3';
2
2
  import { JsonSchema7Type, parseDef } from '../parseDef';
3
3
  import { Refs } from '../Refs';
4
4
 
5
- export function parsePromiseDef(def: ZodPromiseDef, refs: Refs): JsonSchema7Type | undefined {
6
- return parseDef(def.type._def, refs);
5
+ export function parsePromiseDef(
6
+ def: ZodPromiseDef,
7
+ refs: Refs,
8
+ forceResolution: boolean,
9
+ ): JsonSchema7Type | undefined {
10
+ return parseDef(def.type._def, refs, forceResolution);
7
11
  }
@@ -2,6 +2,6 @@ import { ZodReadonlyDef } from 'zod/v3';
2
2
  import { parseDef } from '../parseDef';
3
3
  import { Refs } from '../Refs';
4
4
 
5
- export const parseReadonlyDef = (def: ZodReadonlyDef<any>, refs: Refs) => {
6
- return parseDef(def.innerType._def, refs);
5
+ export const parseReadonlyDef = (def: ZodReadonlyDef<any>, refs: Refs, forceResolution: boolean) => {
6
+ return parseDef(def.innerType._def, refs, forceResolution);
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import type { WorkloadIdentity, TokenExchangeResponse } from './types';
2
2
  import type { Fetch } from '../internal/builtin-types';
3
3
  import * as Shims from '../internal/shims';
4
- import { APIError, OAuthError } from '../core/error';
4
+ import { APIError, OAuthError, OpenAIError } from '../core/error';
5
5
 
6
6
  interface CachedToken {
7
7
  token: string;
@@ -93,16 +93,27 @@ export class WorkloadIdentityAuth {
93
93
  );
94
94
  }
95
95
 
96
- const tokenResponse = (await response.json()) as TokenExchangeResponse;
97
- const expiresIn = tokenResponse.expires_in || 3600;
96
+ const tokenResponse: unknown = await response.json();
97
+ if (
98
+ typeof tokenResponse !== 'object' ||
99
+ tokenResponse === null ||
100
+ !('access_token' in tokenResponse) ||
101
+ typeof tokenResponse.access_token !== 'string' ||
102
+ tokenResponse.access_token.trim().length === 0
103
+ ) {
104
+ throw new OpenAIError("Token exchange response missing 'access_token' field");
105
+ }
106
+
107
+ const accessToken = tokenResponse.access_token;
108
+ const expiresIn = (tokenResponse as Partial<TokenExchangeResponse>).expires_in ?? 3600;
98
109
  const expiresAt = Date.now() + expiresIn * 1000;
99
110
 
100
111
  this.cachedToken = {
101
- token: tokenResponse.access_token,
112
+ token: accessToken,
102
113
  expiresAt,
103
114
  };
104
115
 
105
- return tokenResponse.access_token;
116
+ return accessToken;
106
117
  }
107
118
 
108
119
  private isTokenExpired(cachedToken: CachedToken): boolean {
package/src/azure.ts CHANGED
@@ -8,7 +8,10 @@ import { OpenAI } from './client';
8
8
  import type { ClientOptions } from './client';
9
9
 
10
10
  /** API Client for interfacing with the Azure OpenAI API. */
11
- export interface AzureClientOptions extends ClientOptions {
11
+ export interface AzureClientOptions extends Omit<ClientOptions, 'provider'> {
12
+ /** AzureOpenAI does not support third-party provider configuration. */
13
+ provider?: never;
14
+
12
15
  /**
13
16
  * Defaults to process.env['OPENAI_API_VERSION'].
14
17
  */
@@ -78,16 +78,54 @@ export function isAzure(client: Pick<OpenAI, 'apiKey' | 'baseURL'>): client is A
78
78
  return client instanceof AzureOpenAI;
79
79
  }
80
80
 
81
- export function buildRealtimeURL(client: Pick<OpenAI, 'apiKey' | 'baseURL'>, model: string): URL {
82
- const path = '/realtime';
81
+ export type RealtimeConnectionConfig =
82
+ | {
83
+ /**
84
+ * Start a new Realtime session using the given model.
85
+ */
86
+ model: string;
87
+ callID?: undefined;
88
+ }
89
+ | {
90
+ model?: undefined;
91
+ /**
92
+ * Attach to an in-progress Realtime call over a sideband control connection.
93
+ */
94
+ callID: string;
95
+ };
96
+
97
+ export function buildRealtimeURL(
98
+ client: Pick<OpenAI, 'apiKey' | 'baseURL'>,
99
+ connection: string | RealtimeConnectionConfig,
100
+ ): URL {
101
+ const config: RealtimeConnectionConfig =
102
+ typeof connection === 'string' ? { model: connection } : connection;
83
103
  const baseURL = client.baseURL;
104
+ const azure = isAzure(client);
105
+ const hasModel = !!config.model;
106
+ const hasCallID = !!config.callID;
107
+
108
+ const path = '/realtime';
84
109
  const url = new URL(baseURL + (baseURL.endsWith('/') ? path.slice(1) : path));
110
+
111
+ if (hasModel === hasCallID) {
112
+ throw new Error('Pass exactly one of `model` or `callID` when opening a Realtime WebSocket.');
113
+ }
114
+
85
115
  url.protocol = 'wss';
86
- if (isAzure(client)) {
116
+ // Sideband control connections attach to an existing call via `call_id`.
117
+ if (azure) {
118
+ if (hasCallID) {
119
+ throw new Error('Azure `callID` connections require the stable Realtime helpers.');
120
+ }
87
121
  url.searchParams.set('api-version', client.apiVersion);
88
- url.searchParams.set('deployment', model);
122
+ url.searchParams.set('deployment', config.model!);
89
123
  } else {
90
- url.searchParams.set('model', model);
124
+ if (hasCallID) {
125
+ url.searchParams.set('call_id', config.callID!);
126
+ } else {
127
+ url.searchParams.set('model', config.model!);
128
+ }
91
129
  }
92
130
  return url;
93
131
  }
@@ -1,7 +1,12 @@
1
1
  import { AzureOpenAI, OpenAI } from '../../index';
2
2
  import { OpenAIError } from '../../error';
3
3
  import type { RealtimeClientEvent, RealtimeServerEvent } from '../../resources/beta/realtime/realtime';
4
- import { OpenAIRealtimeEmitter, buildRealtimeURL, isAzure } from './internal-base';
4
+ import {
5
+ OpenAIRealtimeEmitter,
6
+ buildRealtimeURL,
7
+ isAzure,
8
+ type RealtimeConnectionConfig,
9
+ } from './internal-base';
5
10
  import { isRunningInBrowser } from '../../internal/detect-platform';
6
11
 
7
12
  interface MessageEvent {
@@ -23,8 +28,7 @@ export class OpenAIRealtimeWebSocket extends OpenAIRealtimeEmitter {
23
28
  socket: _WebSocket;
24
29
 
25
30
  constructor(
26
- props: {
27
- model: string;
31
+ props: RealtimeConnectionConfig & {
28
32
  dangerouslyAllowBrowser?: boolean;
29
33
  /**
30
34
  * Callback to mutate the URL, needed for Azure.
@@ -54,13 +58,12 @@ export class OpenAIRealtimeWebSocket extends OpenAIRealtimeEmitter {
54
58
  throw new Error(
55
59
  [
56
60
  'Cannot open Realtime WebSocket with a function-based apiKey.',
57
- 'Use the .create() method so that the key is resolved before connecting:',
58
- 'await OpenAIRealtimeWebSocket.create(client, { model })',
61
+ 'Use the .create() method so that the key is resolved before connecting.',
59
62
  ].join('\n'),
60
63
  );
61
64
  }
62
65
 
63
- this.url = buildRealtimeURL(client, props.model);
66
+ this.url = buildRealtimeURL(client, props);
64
67
  props.onURL?.(this.url);
65
68
 
66
69
  // @ts-ignore
@@ -107,7 +110,7 @@ export class OpenAIRealtimeWebSocket extends OpenAIRealtimeEmitter {
107
110
 
108
111
  static async create(
109
112
  client: Pick<OpenAI, 'apiKey' | 'baseURL' | '_callApiKey'>,
110
- props: { model: string; dangerouslyAllowBrowser?: boolean },
113
+ props: RealtimeConnectionConfig & { dangerouslyAllowBrowser?: boolean },
111
114
  ): Promise<OpenAIRealtimeWebSocket> {
112
115
  return new OpenAIRealtimeWebSocket({ ...props, __resolvedApiKey: await client._callApiKey() }, client);
113
116
  }
@@ -1,15 +1,19 @@
1
1
  import * as WS from 'ws';
2
2
  import { AzureOpenAI, OpenAI } from '../../index';
3
3
  import type { RealtimeClientEvent, RealtimeServerEvent } from '../../resources/beta/realtime/realtime';
4
- import { OpenAIRealtimeEmitter, buildRealtimeURL, isAzure } from './internal-base';
4
+ import {
5
+ OpenAIRealtimeEmitter,
6
+ buildRealtimeURL,
7
+ isAzure,
8
+ type RealtimeConnectionConfig,
9
+ } from './internal-base';
5
10
 
6
11
  export class OpenAIRealtimeWS extends OpenAIRealtimeEmitter {
7
12
  url: URL;
8
13
  socket: WS.WebSocket;
9
14
 
10
15
  constructor(
11
- props: {
12
- model: string;
16
+ props: RealtimeConnectionConfig & {
13
17
  options?: WS.ClientOptions | undefined;
14
18
  /** @internal */ __resolvedApiKey?: boolean;
15
19
  },
@@ -22,12 +26,11 @@ export class OpenAIRealtimeWS extends OpenAIRealtimeEmitter {
22
26
  throw new Error(
23
27
  [
24
28
  'Cannot open Realtime WebSocket with a function-based apiKey.',
25
- 'Use the .create() method so that the key is resolved before connecting:',
26
- 'await OpenAIRealtimeWS.create(client, { model })',
29
+ 'Use the .create() method so that the key is resolved before connecting.',
27
30
  ].join('\n'),
28
31
  );
29
32
  }
30
- this.url = buildRealtimeURL(client, props.model);
33
+ this.url = buildRealtimeURL(client, props);
31
34
  this.socket = new WS.WebSocket(this.url, {
32
35
  ...props.options,
33
36
  headers: {
@@ -66,7 +69,7 @@ export class OpenAIRealtimeWS extends OpenAIRealtimeEmitter {
66
69
 
67
70
  static async create(
68
71
  client: Pick<OpenAI, 'apiKey' | 'baseURL' | '_callApiKey'>,
69
- props: { model: string; options?: WS.ClientOptions | undefined },
72
+ props: RealtimeConnectionConfig & { options?: WS.ClientOptions | undefined },
70
73
  ): Promise<OpenAIRealtimeWS> {
71
74
  return new OpenAIRealtimeWS({ ...props, __resolvedApiKey: await client._callApiKey() }, client);
72
75
  }
package/src/client.ts CHANGED
@@ -233,6 +233,7 @@ import {
233
233
  import { type Fetch } from './internal/builtin-types';
234
234
  import { isRunningInBrowser } from './internal/detect-platform';
235
235
  import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
236
+ import { configureProvider, type Provider, type ProviderRuntime } from './internal/provider';
236
237
  import { FinalRequestOptions, RequestOptions } from './internal/request-options';
237
238
  import { readEnv } from './internal/utils/env';
238
239
  import {
@@ -363,6 +364,12 @@ export interface ClientOptions {
363
364
  * Mutually exclusive with `apiKey`.
364
365
  */
365
366
  workloadIdentity?: WorkloadIdentity | undefined;
367
+
368
+ /**
369
+ * Configure this client to use a third-party API provider.
370
+ * Mutually exclusive with top-level authentication and `baseURL` options.
371
+ */
372
+ provider?: Provider | undefined;
366
373
  }
367
374
 
368
375
  /**
@@ -386,6 +393,7 @@ export class OpenAI {
386
393
  #encoder: Opts.RequestEncoder;
387
394
  protected idempotencyHeader?: string;
388
395
  protected _options: ClientOptions;
396
+ private _provider: ProviderRuntime | undefined;
389
397
  private _workloadIdentityAuth?: WorkloadIdentityAuth;
390
398
 
391
399
  /**
@@ -397,6 +405,7 @@ export class OpenAI {
397
405
  * @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]
398
406
  * @param {string | null | undefined} [opts.webhookSecret=process.env['OPENAI_WEBHOOK_SECRET'] ?? null]
399
407
  * @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.
408
+ * @param {Provider} [opts.provider] - Configure a third-party API provider. Mutually exclusive with top-level authentication and base URL options.
400
409
  * @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
401
410
  * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
402
411
  * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
@@ -405,16 +414,32 @@ export class OpenAI {
405
414
  * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
406
415
  * @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
407
416
  */
408
- constructor({
409
- baseURL = readEnv('OPENAI_BASE_URL'),
410
- apiKey = readEnv('OPENAI_API_KEY') ?? null,
411
- adminAPIKey = readEnv('OPENAI_ADMIN_KEY') ?? null,
412
- organization = readEnv('OPENAI_ORG_ID') ?? null,
413
- project = readEnv('OPENAI_PROJECT_ID') ?? null,
414
- webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null,
415
- workloadIdentity,
416
- ...opts
417
- }: ClientOptions = {}) {
417
+ constructor(clientOptions: ClientOptions = {}) {
418
+ const provider = clientOptions.provider;
419
+ if (provider) {
420
+ const conflictingOptions = (['apiKey', 'adminAPIKey', 'workloadIdentity', 'baseURL'] as const).filter(
421
+ (key) => clientOptions[key] != null,
422
+ );
423
+ if (conflictingOptions.length) {
424
+ throw new Errors.OpenAIError(
425
+ `The \`provider\` option cannot be used with ${conflictingOptions
426
+ .map((key) => `\`${key}\``)
427
+ .join(', ')}. Configure authentication and the base URL through the provider instead.`,
428
+ );
429
+ }
430
+ }
431
+
432
+ const {
433
+ baseURL = provider ? null : readEnv('OPENAI_BASE_URL'),
434
+ apiKey = provider ? null : readEnv('OPENAI_API_KEY') ?? null,
435
+ adminAPIKey = provider ? null : readEnv('OPENAI_ADMIN_KEY') ?? null,
436
+ organization = provider ? null : readEnv('OPENAI_ORG_ID') ?? null,
437
+ project = provider ? null : readEnv('OPENAI_PROJECT_ID') ?? null,
438
+ webhookSecret = readEnv('OPENAI_WEBHOOK_SECRET') ?? null,
439
+ workloadIdentity,
440
+ ...opts
441
+ } = clientOptions;
442
+ const providerRuntime = provider ? configureProvider(provider) : undefined;
418
443
  const options: ClientOptions = {
419
444
  apiKey,
420
445
  adminAPIKey,
@@ -422,15 +447,16 @@ export class OpenAI {
422
447
  project,
423
448
  webhookSecret,
424
449
  workloadIdentity,
450
+ provider,
425
451
  ...opts,
426
- baseURL: baseURL || `https://api.openai.com/v1`,
452
+ baseURL: providerRuntime?.baseURL ?? (baseURL || `https://api.openai.com/v1`),
427
453
  };
428
454
 
429
455
  if (apiKey && workloadIdentity) {
430
456
  throw new Errors.OpenAIError('The `apiKey` and `workloadIdentity` options are mutually exclusive');
431
457
  }
432
458
 
433
- if (!apiKey && !adminAPIKey && !workloadIdentity) {
459
+ if (!providerRuntime && !apiKey && !adminAPIKey && !workloadIdentity) {
434
460
  throw new Errors.OpenAIError(
435
461
  'Missing credentials. Please pass an `apiKey`, `workloadIdentity`, `adminAPIKey`, or set the `OPENAI_API_KEY` or `OPENAI_ADMIN_KEY` environment variable.',
436
462
  );
@@ -457,7 +483,7 @@ export class OpenAI {
457
483
  this.fetch = options.fetch ?? Shims.getDefaultFetch();
458
484
  this.#encoder = Opts.FallbackEncoder;
459
485
 
460
- const customHeadersEnv = readEnv('OPENAI_CUSTOM_HEADERS');
486
+ const customHeadersEnv = provider ? undefined : readEnv('OPENAI_CUSTOM_HEADERS');
461
487
  if (customHeadersEnv) {
462
488
  const parsed: Record<string, string> = {};
463
489
  for (const line of customHeadersEnv.split('\n')) {
@@ -470,6 +496,7 @@ export class OpenAI {
470
496
  }
471
497
 
472
498
  this._options = options;
499
+ this._provider = providerRuntime;
473
500
 
474
501
  if (workloadIdentity) {
475
502
  this._workloadIdentityAuth = new WorkloadIdentityAuth(workloadIdentity, this.fetch);
@@ -486,7 +513,9 @@ export class OpenAI {
486
513
  * Create a new client instance re-using the same options given to the current client with optional overriding.
487
514
  */
488
515
  withOptions(options: Partial<ClientOptions>): this {
489
- const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({
516
+ const inheritedProvider = this._options.provider;
517
+ const provider = options.provider ?? inheritedProvider;
518
+ const inheritedOptions: ClientOptions = {
490
519
  ...this._options,
491
520
  baseURL: this.baseURL,
492
521
  maxRetries: this.maxRetries,
@@ -501,7 +530,23 @@ export class OpenAI {
501
530
  organization: this.organization,
502
531
  project: this.project,
503
532
  webhookSecret: this.webhookSecret,
533
+ };
534
+ if (provider) {
535
+ delete inheritedOptions.apiKey;
536
+ delete inheritedOptions.adminAPIKey;
537
+ delete inheritedOptions.workloadIdentity;
538
+ delete inheritedOptions.baseURL;
539
+ if (provider !== inheritedProvider) {
540
+ delete inheritedOptions.organization;
541
+ delete inheritedOptions.project;
542
+ delete inheritedOptions.defaultHeaders;
543
+ }
544
+ }
545
+
546
+ const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({
547
+ ...inheritedOptions,
504
548
  ...options,
549
+ provider,
505
550
  });
506
551
  return client;
507
552
  }
@@ -510,7 +555,7 @@ export class OpenAI {
510
555
  * Check whether the base URL is set to its default.
511
556
  */
512
557
  #baseURLOverridden(): boolean {
513
- return this.baseURL !== 'https://api.openai.com/v1';
558
+ return this._provider !== undefined || this.baseURL !== 'https://api.openai.com/v1';
514
559
  }
515
560
 
516
561
  protected defaultQuery(): Record<string, string | undefined> | undefined {
@@ -592,6 +637,8 @@ export class OpenAI {
592
637
  }
593
638
 
594
639
  async _callApiKey(): Promise<boolean> {
640
+ if (this._provider) return false;
641
+
595
642
  const apiKey = this._options.apiKey;
596
643
  if (typeof apiKey !== 'function') return false;
597
644
 
@@ -644,6 +691,8 @@ export class OpenAI {
644
691
  * Used as a callback for mutating the given `FinalRequestOptions` object.
645
692
  */
646
693
  protected async prepareOptions(options: FinalRequestOptions): Promise<void> {
694
+ if (this._provider) return;
695
+
647
696
  const security = options.__security ?? { bearerAuth: true };
648
697
  if (security.bearerAuth) {
649
698
  await this._callApiKey();
@@ -718,6 +767,7 @@ export class OpenAI {
718
767
  });
719
768
 
720
769
  await this.prepareRequest(req, { url, options });
770
+ await this._provider?.prepareRequest?.(req, { url, options });
721
771
 
722
772
  /** Not an API request ID, just for correlating local log entries. */
723
773
  const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
@@ -1115,13 +1165,17 @@ export class OpenAI {
1115
1165
  'OpenAI-Organization': this.organization,
1116
1166
  'OpenAI-Project': this.project,
1117
1167
  },
1118
- await this.authHeaders(options, options.__security ?? { bearerAuth: true }),
1168
+ this._provider ? undefined : (
1169
+ await this.authHeaders(options, options.__security ?? { bearerAuth: true })
1170
+ ),
1119
1171
  this._options.defaultHeaders,
1120
1172
  bodyHeaders,
1121
1173
  options.headers,
1122
1174
  ]);
1123
1175
 
1124
- this.validateHeaders(headers, options.__security ?? { bearerAuth: true });
1176
+ if (!this._provider) {
1177
+ this.validateHeaders(headers, options.__security ?? { bearerAuth: true });
1178
+ }
1125
1179
 
1126
1180
  return headers.values;
1127
1181
  }
@@ -1132,12 +1186,20 @@ export class OpenAI {
1132
1186
  return () => controller.abort();
1133
1187
  }
1134
1188
 
1135
- private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
1189
+ private buildBody({ options }: { options: FinalRequestOptions }): {
1136
1190
  bodyHeaders: HeadersLike;
1137
1191
  body: BodyInit | undefined;
1138
1192
  isStreamingBody: boolean;
1139
1193
  } {
1194
+ const { body, headers: rawHeaders } = options;
1140
1195
  if (!body) {
1196
+ // A resource method always passes a `body` key when its operation defines a
1197
+ // request body, even if the caller omitted an optional body param. Keep the
1198
+ // content-type for those, and only elide it for operations with no body at
1199
+ // all (e.g. GET/DELETE).
1200
+ if (body === undefined && 'body' in options) {
1201
+ return { ...this.#encoder({ body, headers: buildHeaders([rawHeaders]) }), isStreamingBody: false };
1202
+ }
1141
1203
  return { bodyHeaders: undefined, body: undefined, isStreamingBody: false };
1142
1204
  }
1143
1205
  const headers = buildHeaders([rawHeaders]);
@@ -34,6 +34,22 @@ function zodV4ToJsonSchema(schema: z4.ZodType): Record<string, unknown> {
34
34
  return toStrictJsonSchema(
35
35
  z4.toJSONSchema(schema, {
36
36
  target: 'draft-7',
37
+ override: ({ zodSchema, jsonSchema }) => {
38
+ const def = zodSchema._zod.def;
39
+
40
+ if (def.type === 'union' && 'discriminator' in def && Array.isArray(jsonSchema.oneOf)) {
41
+ if (jsonSchema.anyOf !== undefined) {
42
+ throw new Error(
43
+ 'Zod discriminated union generated both `anyOf` and `oneOf`, which cannot be represented in an OpenAI strict schema',
44
+ );
45
+ }
46
+
47
+ // Discriminator values are mutually exclusive, so anyOf preserves the
48
+ // union while staying inside the API's supported JSON Schema subset.
49
+ jsonSchema.anyOf = jsonSchema.oneOf;
50
+ delete jsonSchema.oneOf;
51
+ }
52
+ },
37
53
  }) as JSONSchema,
38
54
  ) as Record<string, unknown>;
39
55
  }
@@ -0,0 +1,153 @@
1
+ import * as Errors from '../error';
2
+ import type { ApiKeySetter } from '../client';
3
+ import type { FinalizedRequestInit } from './types';
4
+ import type { ProviderRequestContext } from './provider';
5
+ import { readEnv } from './utils';
6
+
7
+ export interface BedrockEndpointOptions {
8
+ /** AWS region used to derive the default Mantle endpoint. */
9
+ region?: string | undefined;
10
+
11
+ /** Bedrock API root. Defaults to AWS_BEDROCK_BASE_URL or the regional Mantle endpoint. */
12
+ baseURL?: string | null | undefined;
13
+ }
14
+
15
+ export interface BedrockBearerOptions {
16
+ /** Explicit Bedrock bearer credential. Set to null to skip the environment bearer fallback. */
17
+ apiKey?: string | null | undefined;
18
+
19
+ /** A function that resolves a Bedrock bearer credential before every request attempt. */
20
+ tokenProvider?: ApiKeySetter | undefined;
21
+ }
22
+
23
+ export interface BedrockRequestAuth {
24
+ prepareRequest(request: FinalizedRequestInit, context: ProviderRequestContext): void | Promise<void>;
25
+ }
26
+
27
+ export type BedrockAuthFactory = () => BedrockRequestAuth;
28
+
29
+ export function errorWithCause(message: string, cause: unknown): Errors.OpenAIError {
30
+ const error = new Errors.OpenAIError(message) as Errors.OpenAIError & { cause?: unknown };
31
+ error.cause = cause;
32
+ return error;
33
+ }
34
+
35
+ export function normalizeOptionalString(value: string | null | undefined): string | undefined {
36
+ const normalized = typeof value === 'string' ? value.trim() : undefined;
37
+ return normalized ? normalized : undefined;
38
+ }
39
+
40
+ function normalizeBaseURL(baseURL: string): string {
41
+ const url = new URL(baseURL);
42
+ const responsesMatch = url.pathname.match(/\/responses(?:\/.*)?$/);
43
+ if (responsesMatch?.index !== undefined) {
44
+ url.pathname = url.pathname.slice(0, responsesMatch.index) || '/';
45
+ }
46
+ return url.toString().replace(/\/$/, '');
47
+ }
48
+
49
+ export function resolveBedrockEndpoint(options: BedrockEndpointOptions): {
50
+ region: string | undefined;
51
+ baseURL: string;
52
+ } {
53
+ if (options.region !== undefined && !normalizeOptionalString(options.region)) {
54
+ throw new Errors.OpenAIError('The Bedrock AWS `region` must not be empty.');
55
+ }
56
+ if (
57
+ options.baseURL !== undefined &&
58
+ options.baseURL !== null &&
59
+ !normalizeOptionalString(options.baseURL)
60
+ ) {
61
+ throw new Errors.OpenAIError('The Bedrock `baseURL` must not be empty.');
62
+ }
63
+
64
+ const region =
65
+ normalizeOptionalString(options.region) ??
66
+ normalizeOptionalString(readEnv('AWS_REGION')) ??
67
+ normalizeOptionalString(readEnv('AWS_DEFAULT_REGION'));
68
+ const configuredBaseURL =
69
+ options.baseURL === undefined ? normalizeOptionalString(readEnv('AWS_BEDROCK_BASE_URL'))
70
+ : options.baseURL === null ? undefined
71
+ : normalizeOptionalString(options.baseURL);
72
+
73
+ if (configuredBaseURL) return { region, baseURL: normalizeBaseURL(configuredBaseURL) };
74
+ if (!region) {
75
+ throw new Errors.OpenAIError(
76
+ 'Bedrock requires an AWS region. Pass `region` to `bedrock(...)`, or set `AWS_REGION` or `AWS_DEFAULT_REGION`.',
77
+ );
78
+ }
79
+ return { region, baseURL: `https://bedrock-mantle.${region}.api.aws/openai/v1` };
80
+ }
81
+
82
+ export function assertProviderOwnsAuthorization(headers: Headers): void {
83
+ if (headers.has('authorization')) {
84
+ throw new Errors.OpenAIError(
85
+ 'Bedrock provider authentication cannot be combined with a custom `Authorization` header.',
86
+ );
87
+ }
88
+ }
89
+
90
+ class BedrockBearerAuth implements BedrockRequestAuth {
91
+ constructor(private readonly tokenProvider: ApiKeySetter) {}
92
+
93
+ async prepareRequest(request: FinalizedRequestInit, _context: ProviderRequestContext): Promise<void> {
94
+ const headers = new Headers(request.headers);
95
+ assertProviderOwnsAuthorization(headers);
96
+
97
+ let token: unknown;
98
+ try {
99
+ token = await this.tokenProvider();
100
+ } catch (cause) {
101
+ throw errorWithCause('Failed to resolve a bearer credential for Bedrock.', cause);
102
+ }
103
+ if (typeof token !== 'string' || !token.trim()) {
104
+ throw new Errors.OpenAIError('The Bedrock bearer credential provider must return a non-empty string.');
105
+ }
106
+ headers.set('authorization', `Bearer ${token}`);
107
+ request.headers = headers;
108
+ }
109
+ }
110
+
111
+ export function resolveBedrockBearerAuth(
112
+ options: BedrockBearerOptions,
113
+ { allowEnvironment = true }: { allowEnvironment?: boolean } = {},
114
+ ): { factory: BedrockAuthFactory | undefined; explicit: boolean } {
115
+ if (
116
+ options.apiKey !== undefined &&
117
+ options.apiKey !== null &&
118
+ (typeof options.apiKey !== 'string' || !options.apiKey.trim())
119
+ ) {
120
+ throw new Errors.OpenAIError('The Bedrock bearer credential must not be empty.');
121
+ }
122
+ if (options.apiKey != null && options.tokenProvider) {
123
+ throw new Errors.OpenAIError(
124
+ 'The `apiKey` and `tokenProvider` options are mutually exclusive. Configure only one.',
125
+ );
126
+ }
127
+
128
+ if (options.tokenProvider) {
129
+ const tokenProvider = options.tokenProvider;
130
+ return { factory: () => new BedrockBearerAuth(tokenProvider), explicit: true };
131
+ }
132
+ if (options.apiKey != null) {
133
+ const apiKey = options.apiKey;
134
+ return { factory: () => new BedrockBearerAuth(async () => apiKey), explicit: true };
135
+ }
136
+ if (allowEnvironment && options.apiKey !== null && readEnv('AWS_BEARER_TOKEN_BEDROCK')) {
137
+ return {
138
+ explicit: false,
139
+ factory: () =>
140
+ new BedrockBearerAuth(async () => {
141
+ const token = readEnv('AWS_BEARER_TOKEN_BEDROCK');
142
+ if (!token) {
143
+ throw new Errors.OpenAIError(
144
+ 'Could not find credentials for Bedrock. Set `AWS_BEARER_TOKEN_BEDROCK` or configure AWS credential authentication.',
145
+ );
146
+ }
147
+ return token;
148
+ }),
149
+ };
150
+ }
151
+
152
+ return { factory: undefined, explicit: false };
153
+ }