openai 0.103.0 → 0.104.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 (395) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +23 -1
  4. data/lib/openai/client.rb +3 -386
  5. data/lib/openai/helpers/admin/organization/projects/api_keys.rb +42 -0
  6. data/lib/openai/helpers/agents/session_stream_resource.rb +60 -0
  7. data/lib/openai/helpers/beta/agents/artifacts.rb +18 -0
  8. data/lib/openai/helpers/beta/agents/files.rb +41 -0
  9. data/lib/openai/helpers/client_runtime.rb +391 -0
  10. data/lib/openai/helpers/files.rb +47 -0
  11. data/lib/openai/helpers/live/websocket.rb +8 -57
  12. data/lib/openai/helpers/models/chat/parsed.rb +32 -0
  13. data/lib/openai/helpers/models/responses/parsed.rb +30 -0
  14. data/lib/openai/helpers/models/responses/response.rb +32 -0
  15. data/lib/openai/helpers/models/webhooks/webhook_endpoint_with_secret.rb +20 -0
  16. data/lib/openai/helpers/realtime/client_extension.rb +1 -2
  17. data/lib/openai/helpers/realtime/connection_manager.rb +1 -1
  18. data/lib/openai/helpers/realtime/translation.rb +7 -50
  19. data/lib/openai/helpers/responses_websocket/client_extension.rb +1 -2
  20. data/lib/openai/helpers/streaming/chat_completion_resource.rb +36 -0
  21. data/lib/openai/helpers/streaming/response_stream.rb +1 -16
  22. data/lib/openai/helpers/streaming/response_stream_resource.rb +78 -0
  23. data/lib/openai/helpers/vector_stores/file_batches.rb +188 -0
  24. data/lib/openai/helpers/vector_stores/files.rb +198 -0
  25. data/lib/openai/helpers/websocket/client_request.rb +31 -6
  26. data/lib/openai/helpers/websocket/connection.rb +58 -0
  27. data/lib/openai/helpers/websocket/connection_manager.rb +4 -2
  28. data/lib/openai/helpers/websocket/protocol.rb +2 -1
  29. data/lib/openai/helpers/websocket/resource.rb +54 -0
  30. data/lib/openai/helpers/websocket/typed_connection.rb +95 -0
  31. data/lib/openai/helpers/websocket.rb +4 -0
  32. data/lib/openai/models/admin/organization/audit_log_list_response.rb +5 -3
  33. data/lib/openai/models/admin/organization/external_storage_configuration.rb +5 -3
  34. data/lib/openai/models/admin/organization/external_storage_create_params.rb +33 -3
  35. data/lib/openai/models/admin/organization/oci_external_storage_provider.rb +37 -0
  36. data/lib/openai/models/admin/organization/project_residency.rb +3 -0
  37. data/lib/openai/models/admin/organization/projects/api_key_update_params.rb +64 -0
  38. data/lib/openai/models/admin/organization/projects/api_key_update_scopes_params.rb +34 -0
  39. data/lib/openai/models/admin/organization/usage_decisions_params.rb +177 -0
  40. data/lib/openai/models/admin/organization/usage_decisions_response.rb +351 -0
  41. data/lib/openai/models/audio/speech_create_params.rb +6 -3
  42. data/lib/openai/models/audio/translation_create_response.rb +0 -1
  43. data/lib/openai/models/audio/voice.rb +17 -2
  44. data/lib/openai/models/audio/voice_create_params.rb +100 -3
  45. data/lib/openai/models/beta/agent_create_params.rb +4 -2
  46. data/lib/openai/models/beta/agent_list_params.rb +4 -4
  47. data/lib/openai/models/beta/agent_session.rb +37 -1
  48. data/lib/openai/models/beta/agent_update_params.rb +4 -2
  49. data/lib/openai/models/beta/agents/environment_list_params.rb +7 -7
  50. data/lib/openai/models/beta/agents/session_create_params.rb +39 -3
  51. data/lib/openai/models/beta/agents/session_list_params.rb +7 -10
  52. data/lib/openai/models/beta/agents/session_update_params.rb +33 -1
  53. data/lib/openai/models/beta/agents/sessions/artifact_list_params.rb +11 -11
  54. data/lib/openai/models/beta/agents/vault_list_params.rb +23 -13
  55. data/lib/openai/models/beta/agents/vault_status_filter.rb +1 -3
  56. data/lib/openai/models/beta/agents/vault_update_params.rb +47 -0
  57. data/lib/openai/models/beta/agents/vaults/credential_list_params.rb +23 -13
  58. data/lib/openai/models/beta/beta_response.rb +23 -2
  59. data/lib/openai/models/beta/beta_response_error.rb +19 -1
  60. data/lib/openai/models/beta/beta_response_input_item.rb +107 -1
  61. data/lib/openai/models/beta/beta_response_item.rb +107 -1
  62. data/lib/openai/models/beta/beta_response_output_item.rb +107 -1
  63. data/lib/openai/models/beta/beta_responses_client_event.rb +23 -2
  64. data/lib/openai/models/beta/response_compact_params.rb +21 -0
  65. data/lib/openai/models/beta/response_create_params.rb +23 -2
  66. data/lib/openai/models/beta/session_turn_error.rb +3 -0
  67. data/lib/openai/models/chat/chat_completion_audio_param.rb +3 -3
  68. data/lib/openai/models/chat/chat_completion_message.rb +0 -8
  69. data/lib/openai/models/chat/chat_completion_message_function_tool_call.rb +0 -8
  70. data/lib/openai/models/chat/completion_create_params.rb +5 -12
  71. data/lib/openai/models/chat_model.rb +21 -0
  72. data/lib/openai/models/conversations/conversation_item.rb +107 -1
  73. data/lib/openai/models/decision.rb +17 -2
  74. data/lib/openai/models/decision_create_params.rb +29 -12
  75. data/lib/openai/models/decision_input_image.rb +4 -3
  76. data/lib/openai/models/decision_input_message.rb +4 -4
  77. data/lib/openai/models/decision_input_part.rb +3 -2
  78. data/lib/openai/models/image_edit_completed_event.rb +1 -2
  79. data/lib/openai/models/image_edit_partial_image_event.rb +1 -2
  80. data/lib/openai/models/image_gen_completed_event.rb +1 -2
  81. data/lib/openai/models/image_gen_partial_image_event.rb +1 -2
  82. data/lib/openai/models/images_response.rb +1 -2
  83. data/lib/openai/models/live/built_in_voice.rb +1 -0
  84. data/lib/openai/models/live/client_event.rb +14 -2
  85. data/lib/openai/models/live/decision_create_event.rb +26 -0
  86. data/lib/openai/models/live/decision_event.rb +117 -0
  87. data/lib/openai/models/live/decision_item_create_event.rb +194 -0
  88. data/lib/openai/models/live/decision_item_created_event.rb +202 -0
  89. data/lib/openai/models/live/decision_item_delete_event.rb +38 -0
  90. data/lib/openai/models/live/decision_item_deleted_event.rb +46 -0
  91. data/lib/openai/models/live/decision_trigger.rb +244 -0
  92. data/lib/openai/models/live/decisions_delegation_config.rb +201 -0
  93. data/lib/openai/models/live/decisions_delegation_update_config.rb +208 -0
  94. data/lib/openai/models/live/delegation_created_event.rb +10 -10
  95. data/lib/openai/models/live/fork_client_event.rb +14 -2
  96. data/lib/openai/models/live/fork_server_event.rb +17 -2
  97. data/lib/openai/models/live/media_session_config.rb +47 -11
  98. data/lib/openai/models/live/output_audio_fixture_play_event.rb +48 -0
  99. data/lib/openai/models/live/output_audio_fixture_played_event.rb +42 -0
  100. data/lib/openai/models/live/output_audio_fixture_playing_event.rb +41 -0
  101. data/lib/openai/models/live/server_event.rb +17 -2
  102. data/lib/openai/models/live/session_accept_params.rb +47 -11
  103. data/lib/openai/models/live/session_config.rb +47 -11
  104. data/lib/openai/models/live/session_resource.rb +47 -11
  105. data/lib/openai/models/live/session_update_config.rb +38 -6
  106. data/lib/openai/models/live/session_update_event.rb +8 -8
  107. data/lib/openai/models/live/sideband_client_event.rb +57 -0
  108. data/lib/openai/models/live/sideband_server_event.rb +78 -0
  109. data/lib/openai/models/realtime/realtime_audio_config_output.rb +6 -3
  110. data/lib/openai/models/realtime/realtime_response_create_audio_output.rb +6 -3
  111. data/lib/openai/models/realtime/realtime_response_status.rb +10 -1
  112. data/lib/openai/models/response_format_json_schema.rb +1 -1
  113. data/lib/openai/models/responses/function_tool.rb +8 -6
  114. data/lib/openai/models/responses/response.rb +2 -23
  115. data/lib/openai/models/responses/response_compact_params.rb +21 -0
  116. data/lib/openai/models/responses/response_create_params.rb +3 -6
  117. data/lib/openai/models/responses/response_error.rb +19 -1
  118. data/lib/openai/models/responses/response_format_text_config.rb +0 -4
  119. data/lib/openai/models/responses/response_function_tool_call.rb +0 -8
  120. data/lib/openai/models/responses/response_input_item.rb +107 -1
  121. data/lib/openai/models/responses/response_item.rb +107 -1
  122. data/lib/openai/models/responses/response_output_item.rb +107 -1
  123. data/lib/openai/models/responses/response_output_text.rb +0 -8
  124. data/lib/openai/models/responses/responses_client_event.rb +2 -2
  125. data/lib/openai/models/safety/safety_alert.rb +12 -1
  126. data/lib/openai/models/video_create_error.rb +19 -1
  127. data/lib/openai/models/webhooks/unwrap_webhook_event.rb +4 -4
  128. data/lib/openai/models/webhooks/webhook_endpoint_with_secret.rb +0 -9
  129. data/lib/openai/resources/admin/organization/external_storage.rb +1 -1
  130. data/lib/openai/resources/admin/organization/projects/api_keys.rb +61 -0
  131. data/lib/openai/resources/admin/organization/usage.rb +67 -0
  132. data/lib/openai/resources/audio/speech.rb +2 -1
  133. data/lib/openai/resources/audio/voices.rb +10 -10
  134. data/lib/openai/resources/beta/agents/environments/files.rb +3 -31
  135. data/lib/openai/resources/beta/agents/environments.rb +3 -3
  136. data/lib/openai/resources/beta/agents/sessions/artifacts.rb +5 -11
  137. data/lib/openai/resources/beta/agents/sessions.rb +20 -56
  138. data/lib/openai/resources/beta/agents/vaults/credentials.rb +10 -6
  139. data/lib/openai/resources/beta/agents/vaults.rb +45 -6
  140. data/lib/openai/resources/beta/agents.rb +6 -4
  141. data/lib/openai/resources/beta/responses.rb +2 -2
  142. data/lib/openai/resources/chat/completions.rb +11 -37
  143. data/lib/openai/resources/decisions.rb +9 -15
  144. data/lib/openai/resources/files.rb +0 -39
  145. data/lib/openai/resources/live/forks.rb +19 -0
  146. data/lib/openai/resources/live/sideband.rb +19 -0
  147. data/lib/openai/resources/live.rb +19 -0
  148. data/lib/openai/resources/realtime/translations.rb +19 -0
  149. data/lib/openai/resources/realtime.rb +19 -0
  150. data/lib/openai/resources/responses.rb +44 -95
  151. data/lib/openai/resources/vector_stores/file_batches.rb +0 -178
  152. data/lib/openai/resources/vector_stores/files.rb +0 -188
  153. data/lib/openai/resources/webhooks.rb +13 -29
  154. data/lib/openai/version.rb +1 -1
  155. data/lib/openai.rb +31 -0
  156. data/rbi/openai/client.rbi +0 -103
  157. data/rbi/openai/helpers/admin/organization/projects/api_keys.rbi +25 -0
  158. data/rbi/openai/helpers/beta/agents/artifacts.rbi +25 -0
  159. data/rbi/openai/helpers/beta/agents/files.rbi +48 -0
  160. data/rbi/openai/helpers/client_runtime.rbi +108 -0
  161. data/rbi/openai/helpers/files.rbi +25 -0
  162. data/rbi/openai/helpers/models/chat/parsed.rbi +21 -0
  163. data/rbi/openai/helpers/models/responses/parsed.rbi +19 -0
  164. data/rbi/openai/helpers/models/responses/response.rbi +15 -0
  165. data/rbi/openai/helpers/streaming/response_stream.rbi +301 -0
  166. data/rbi/openai/helpers/vector_stores/file_batches.rbi +102 -0
  167. data/rbi/openai/helpers/vector_stores/files.rbi +122 -0
  168. data/rbi/openai/helpers/websocket.rbi +82 -0
  169. data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +6 -3
  170. data/rbi/openai/models/admin/organization/external_storage_configuration.rbi +4 -2
  171. data/rbi/openai/models/admin/organization/external_storage_create_params.rbi +63 -4
  172. data/rbi/openai/models/admin/organization/oci_external_storage_provider.rbi +71 -0
  173. data/rbi/openai/models/admin/organization/project_residency.rbi +12 -0
  174. data/rbi/openai/models/admin/organization/projects/api_key_update_params.rbi +110 -0
  175. data/rbi/openai/models/admin/organization/projects/api_key_update_scopes_params.rbi +72 -0
  176. data/rbi/openai/models/admin/organization/usage_decisions_params.rbi +229 -0
  177. data/rbi/openai/models/admin/organization/usage_decisions_response.rbi +479 -0
  178. data/rbi/openai/models/audio/speech_create_params.rbi +6 -3
  179. data/rbi/openai/models/audio/voice.rbi +21 -2
  180. data/rbi/openai/models/audio/voice_create_params.rbi +149 -4
  181. data/rbi/openai/models/beta/agent_create_params.rbi +4 -2
  182. data/rbi/openai/models/beta/agent_list_params.rbi +8 -5
  183. data/rbi/openai/models/beta/agent_session.rbi +64 -1
  184. data/rbi/openai/models/beta/agent_update_params.rbi +4 -2
  185. data/rbi/openai/models/beta/agents/environment_list_params.rbi +7 -7
  186. data/rbi/openai/models/beta/agents/session_create_params.rbi +62 -2
  187. data/rbi/openai/models/beta/agents/session_list_params.rbi +11 -11
  188. data/rbi/openai/models/beta/agents/session_update_params.rbi +56 -0
  189. data/rbi/openai/models/beta/agents/sessions/artifact_list_params.rbi +19 -13
  190. data/rbi/openai/models/beta/agents/vault_list_params.rbi +30 -13
  191. data/rbi/openai/models/beta/agents/vault_status_filter.rbi +1 -3
  192. data/rbi/openai/models/beta/agents/vault_update_params.rbi +87 -0
  193. data/rbi/openai/models/beta/agents/vaults/credential_list_params.rbi +30 -13
  194. data/rbi/openai/models/beta/beta_response.rbi +2 -2
  195. data/rbi/openai/models/beta/beta_response_error.rbi +24 -3
  196. data/rbi/openai/models/beta/beta_response_input_item.rbi +191 -0
  197. data/rbi/openai/models/beta/beta_response_item.rbi +189 -0
  198. data/rbi/openai/models/beta/beta_response_output_item.rbi +191 -0
  199. data/rbi/openai/models/beta/beta_responses_client_event.rbi +2 -2
  200. data/rbi/openai/models/beta/response_create_params.rbi +2 -2
  201. data/rbi/openai/models/beta/session_turn_error.rbi +3 -0
  202. data/rbi/openai/models/chat/chat_completion_audio_param.rbi +3 -3
  203. data/rbi/openai/models/chat/chat_completion_message.rbi +0 -4
  204. data/rbi/openai/models/chat/chat_completion_message_function_tool_call.rbi +0 -4
  205. data/rbi/openai/models/chat/completion_create_params.rbi +63 -78
  206. data/rbi/openai/models/conversations/conversation_item.rbi +191 -0
  207. data/rbi/openai/models/decision.rbi +14 -1
  208. data/rbi/openai/models/decision_create_params.rbi +23 -12
  209. data/rbi/openai/models/decision_input_image.rbi +4 -3
  210. data/rbi/openai/models/decision_input_message.rbi +4 -4
  211. data/rbi/openai/models/decision_input_part.rbi +2 -1
  212. data/rbi/openai/models/image_edit_completed_event.rbi +1 -0
  213. data/rbi/openai/models/image_edit_partial_image_event.rbi +1 -0
  214. data/rbi/openai/models/image_gen_completed_event.rbi +1 -0
  215. data/rbi/openai/models/image_gen_partial_image_event.rbi +1 -0
  216. data/rbi/openai/models/images_response.rbi +1 -0
  217. data/rbi/openai/models/live/built_in_voice.rbi +1 -0
  218. data/rbi/openai/models/live/client_event.rbi +4 -0
  219. data/rbi/openai/models/live/decision_create_event.rbi +55 -0
  220. data/rbi/openai/models/live/decision_event.rbi +185 -0
  221. data/rbi/openai/models/live/decision_item_create_event.rbi +338 -0
  222. data/rbi/openai/models/live/decision_item_created_event.rbi +354 -0
  223. data/rbi/openai/models/live/decision_item_delete_event.rbi +66 -0
  224. data/rbi/openai/models/live/decision_item_deleted_event.rbi +77 -0
  225. data/rbi/openai/models/live/decision_trigger.rbi +465 -0
  226. data/rbi/openai/models/live/decisions_delegation_config.rbi +393 -0
  227. data/rbi/openai/models/live/decisions_delegation_update_config.rbi +412 -0
  228. data/rbi/openai/models/live/delegation_created_event.rbi +8 -10
  229. data/rbi/openai/models/live/fork_client_event.rbi +4 -0
  230. data/rbi/openai/models/live/fork_server_event.rbi +5 -0
  231. data/rbi/openai/models/live/media_session_config.rbi +95 -14
  232. data/rbi/openai/models/live/output_audio_fixture_play_event.rbi +76 -0
  233. data/rbi/openai/models/live/output_audio_fixture_played_event.rbi +73 -0
  234. data/rbi/openai/models/live/output_audio_fixture_playing_event.rbi +72 -0
  235. data/rbi/openai/models/live/server_event.rbi +5 -0
  236. data/rbi/openai/models/live/session_accept_params.rbi +88 -12
  237. data/rbi/openai/models/live/session_config.rbi +100 -14
  238. data/rbi/openai/models/live/session_resource.rbi +81 -10
  239. data/rbi/openai/models/live/session_update_config.rbi +86 -9
  240. data/rbi/openai/models/live/session_update_event.rbi +8 -8
  241. data/rbi/openai/models/live/sideband_client_event.rbi +40 -0
  242. data/rbi/openai/models/live/sideband_server_event.rbi +47 -0
  243. data/rbi/openai/models/realtime/realtime_audio_config_output.rbi +6 -3
  244. data/rbi/openai/models/realtime/realtime_response_create_audio_output.rbi +6 -3
  245. data/rbi/openai/models/realtime/realtime_response_status.rbi +13 -1
  246. data/rbi/openai/models/realtime/realtime_translation_input_audio_buffer_append_event.rbi +1 -1
  247. data/rbi/openai/models/realtime/realtime_translation_output_audio_delta_event.rbi +3 -3
  248. data/rbi/openai/models/realtime/realtime_translation_session_close_event.rbi +1 -1
  249. data/rbi/openai/models/realtime/realtime_translation_session_update_event.rbi +5 -1
  250. data/rbi/openai/models/responses/response.rbi +2 -7
  251. data/rbi/openai/models/responses/response_create_params.rbi +5 -9
  252. data/rbi/openai/models/responses/response_error.rbi +24 -3
  253. data/rbi/openai/models/responses/response_function_tool_call.rbi +0 -4
  254. data/rbi/openai/models/responses/response_function_web_search.rbi +21 -17
  255. data/rbi/openai/models/responses/response_input_item.rbi +191 -0
  256. data/rbi/openai/models/responses/response_item.rbi +189 -0
  257. data/rbi/openai/models/responses/response_output_item.rbi +191 -0
  258. data/rbi/openai/models/responses/response_output_text.rbi +0 -4
  259. data/rbi/openai/models/responses/responses_client_event.rbi +2 -2
  260. data/rbi/openai/models/safety/safety_alert.rbi +13 -1
  261. data/rbi/openai/models/video_create_error.rbi +24 -3
  262. data/rbi/openai/models/webhooks/unwrap_webhook_event.rbi +1 -1
  263. data/rbi/openai/resources/admin/organization/external_storage.rbi +2 -1
  264. data/rbi/openai/resources/admin/organization/projects/api_keys.rbi +48 -0
  265. data/rbi/openai/resources/admin/organization/usage.rbi +56 -0
  266. data/rbi/openai/resources/audio/speech.rbi +2 -1
  267. data/rbi/openai/resources/audio/voices.rbi +13 -10
  268. data/rbi/openai/resources/beta/agents/environments/files.rbi +3 -33
  269. data/rbi/openai/resources/beta/agents/environments.rbi +3 -3
  270. data/rbi/openai/resources/beta/agents/sessions/artifacts.rbi +5 -13
  271. data/rbi/openai/resources/beta/agents/sessions.rbi +15 -4
  272. data/rbi/openai/resources/beta/agents/vaults/credentials.rbi +9 -5
  273. data/rbi/openai/resources/beta/agents/vaults.rbi +34 -5
  274. data/rbi/openai/resources/beta/agents.rbi +6 -4
  275. data/rbi/openai/resources/beta/responses.rbi +2 -2
  276. data/rbi/openai/resources/chat/completions.rbi +26 -29
  277. data/rbi/openai/resources/decisions.rbi +9 -15
  278. data/rbi/openai/resources/files.rbi +0 -18
  279. data/rbi/openai/resources/live/forks.rbi +17 -0
  280. data/rbi/openai/resources/live/sideband.rbi +17 -0
  281. data/rbi/openai/resources/live.rbi +17 -0
  282. data/rbi/openai/resources/realtime/translations.rbi +17 -0
  283. data/rbi/openai/resources/realtime.rbi +17 -0
  284. data/rbi/openai/resources/responses.rbi +41 -333
  285. data/rbi/openai/resources/vector_stores/file_batches.rbi +0 -93
  286. data/rbi/openai/resources/vector_stores/files.rbi +0 -113
  287. data/rbi/openai/resources/webhooks.rbi +1 -1
  288. data/sig/openai/client.rbs +0 -50
  289. data/sig/openai/helpers/admin/organization/projects/api_keys.rbs +18 -0
  290. data/sig/openai/helpers/beta/agents/artifacts.rbs +17 -0
  291. data/sig/openai/helpers/beta/agents/files.rbs +30 -0
  292. data/sig/openai/helpers/client_runtime.rbs +53 -0
  293. data/sig/openai/helpers/files.rbs +12 -0
  294. data/sig/openai/helpers/models/responses/response.rbs +9 -0
  295. data/sig/openai/helpers/streaming/response_stream.rbs +37 -0
  296. data/sig/openai/helpers/vector_stores/file_batches.rbs +38 -0
  297. data/sig/openai/helpers/vector_stores/files.rbs +43 -0
  298. data/sig/openai/helpers/websocket.rbs +40 -0
  299. data/sig/openai/models/admin/organization/audit_log_list_response.rbs +1 -0
  300. data/sig/openai/models/admin/organization/external_storage_configuration.rbs +1 -0
  301. data/sig/openai/models/admin/organization/external_storage_create_params.rbs +33 -0
  302. data/sig/openai/models/admin/organization/oci_external_storage_provider.rbs +34 -0
  303. data/sig/openai/models/admin/organization/project_residency.rbs +6 -0
  304. data/sig/openai/models/admin/organization/projects/api_key_update_params.rbs +77 -0
  305. data/sig/openai/models/admin/organization/projects/api_key_update_scopes_params.rbs +38 -0
  306. data/sig/openai/models/admin/organization/usage_decisions_params.rbs +170 -0
  307. data/sig/openai/models/admin/organization/usage_decisions_response.rbs +319 -0
  308. data/sig/openai/models/audio/speech_create_params.rbs +4 -2
  309. data/sig/openai/models/audio/voice.rbs +21 -3
  310. data/sig/openai/models/audio/voice_create_params.rbs +90 -1
  311. data/sig/openai/models/beta/agent_create_params.rbs +4 -2
  312. data/sig/openai/models/beta/agent_list_params.rbs +9 -6
  313. data/sig/openai/models/beta/agent_session.rbs +36 -2
  314. data/sig/openai/models/beta/agent_update_params.rbs +4 -2
  315. data/sig/openai/models/beta/agents/environment_list_params.rbs +9 -9
  316. data/sig/openai/models/beta/agents/session_create_params.rbs +29 -2
  317. data/sig/openai/models/beta/agents/session_list_params.rbs +12 -12
  318. data/sig/openai/models/beta/agents/session_update_params.rbs +23 -0
  319. data/sig/openai/models/beta/agents/sessions/artifact_list_params.rbs +21 -15
  320. data/sig/openai/models/beta/agents/vault_list_params.rbs +32 -14
  321. data/sig/openai/models/beta/agents/vault_update_params.rbs +54 -0
  322. data/sig/openai/models/beta/agents/vaults/credential_list_params.rbs +32 -14
  323. data/sig/openai/models/beta/beta_response.rbs +2 -2
  324. data/sig/openai/models/beta/beta_response_error.rbs +19 -3
  325. data/sig/openai/models/beta/beta_response_input_item.rbs +110 -0
  326. data/sig/openai/models/beta/beta_response_item.rbs +110 -0
  327. data/sig/openai/models/beta/beta_response_output_item.rbs +110 -0
  328. data/sig/openai/models/beta/beta_responses_client_event.rbs +2 -2
  329. data/sig/openai/models/beta/response_create_params.rbs +2 -2
  330. data/sig/openai/models/beta/session_turn_error.rbs +4 -0
  331. data/sig/openai/models/chat/chat_completion_audio_param.rbs +2 -2
  332. data/sig/openai/models/chat/completion_create_params.rbs +2 -2
  333. data/sig/openai/models/conversations/conversation_item.rbs +110 -0
  334. data/sig/openai/models/decision.rbs +13 -0
  335. data/sig/openai/models/decision_create_params.rbs +19 -8
  336. data/sig/openai/models/decision_input_image.rbs +2 -2
  337. data/sig/openai/models/decision_input_message.rbs +2 -2
  338. data/sig/openai/models/live/built_in_voice.rbs +2 -0
  339. data/sig/openai/models/live/client_event.rbs +4 -0
  340. data/sig/openai/models/live/decision_create_event.rbs +18 -0
  341. data/sig/openai/models/live/decision_event.rbs +102 -0
  342. data/sig/openai/models/live/decision_item_create_event.rbs +183 -0
  343. data/sig/openai/models/live/decision_item_created_event.rbs +195 -0
  344. data/sig/openai/models/live/decision_item_delete_event.rbs +33 -0
  345. data/sig/openai/models/live/decision_item_deleted_event.rbs +49 -0
  346. data/sig/openai/models/live/decision_trigger.rbs +234 -0
  347. data/sig/openai/models/live/decisions_delegation_config.rbs +195 -0
  348. data/sig/openai/models/live/decisions_delegation_update_config.rbs +202 -0
  349. data/sig/openai/models/live/delegation_created_event.rbs +6 -7
  350. data/sig/openai/models/live/fork_client_event.rbs +4 -0
  351. data/sig/openai/models/live/fork_server_event.rbs +5 -0
  352. data/sig/openai/models/live/media_session_config.rbs +58 -11
  353. data/sig/openai/models/live/output_audio_fixture_play_event.rbs +42 -0
  354. data/sig/openai/models/live/output_audio_fixture_played_event.rbs +44 -0
  355. data/sig/openai/models/live/output_audio_fixture_playing_event.rbs +44 -0
  356. data/sig/openai/models/live/server_event.rbs +5 -0
  357. data/sig/openai/models/live/session_accept_params.rbs +57 -10
  358. data/sig/openai/models/live/session_config.rbs +58 -11
  359. data/sig/openai/models/live/session_resource.rbs +57 -10
  360. data/sig/openai/models/live/session_update_config.rbs +54 -3
  361. data/sig/openai/models/live/session_update_event.rbs +6 -6
  362. data/sig/openai/models/live/sideband_client_event.rbs +26 -0
  363. data/sig/openai/models/live/sideband_server_event.rbs +33 -0
  364. data/sig/openai/models/realtime/realtime_audio_config_output.rbs +6 -3
  365. data/sig/openai/models/realtime/realtime_response_create_audio_output.rbs +6 -3
  366. data/sig/openai/models/realtime/realtime_response_status.rbs +15 -3
  367. data/sig/openai/models/responses/response.rbs +2 -4
  368. data/sig/openai/models/responses/response_create_params.rbs +2 -2
  369. data/sig/openai/models/responses/response_error.rbs +19 -3
  370. data/sig/openai/models/responses/response_input_item.rbs +110 -0
  371. data/sig/openai/models/responses/response_item.rbs +110 -0
  372. data/sig/openai/models/responses/response_output_item.rbs +110 -0
  373. data/sig/openai/models/responses/responses_client_event.rbs +2 -2
  374. data/sig/openai/models/safety/safety_alert.rbs +12 -2
  375. data/sig/openai/models/video_create_error.rbs +19 -3
  376. data/sig/openai/models/webhooks/unwrap_webhook_event.rbs +1 -1
  377. data/sig/openai/resources/admin/organization/projects/api_keys.rbs +8 -0
  378. data/sig/openai/resources/admin/organization/usage.rbs +15 -0
  379. data/sig/openai/resources/beta/agents/environments/files.rbs +0 -17
  380. data/sig/openai/resources/beta/agents/sessions/artifacts.rbs +2 -6
  381. data/sig/openai/resources/beta/agents/sessions.rbs +4 -1
  382. data/sig/openai/resources/beta/agents/vaults/credentials.rbs +2 -1
  383. data/sig/openai/resources/beta/agents/vaults.rbs +9 -1
  384. data/sig/openai/resources/beta/agents.rbs +1 -1
  385. data/sig/openai/resources/files.rbs +0 -7
  386. data/sig/openai/resources/live/forks.rbs +8 -0
  387. data/sig/openai/resources/live/sideband.rbs +8 -0
  388. data/sig/openai/resources/live.rbs +7 -0
  389. data/sig/openai/resources/realtime/translations.rbs +7 -0
  390. data/sig/openai/resources/realtime.rbs +7 -0
  391. data/sig/openai/resources/responses.rbs +7 -31
  392. data/sig/openai/resources/vector_stores/file_batches.rbs +0 -31
  393. data/sig/openai/resources/vector_stores/files.rbs +0 -36
  394. data/sig/openai/resources/webhooks.rbs +1 -1
  395. metadata +89 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b50a0bb1c17d033d4179a483168878412ecc245f68bd4192692600581db9bc0
4
- data.tar.gz: 13eff5cdbaa168cb9837a9a04fc5b39a8cf8d19374d65a4f67be7028bb369d0f
3
+ metadata.gz: e16df42bfa691e5400644594e19849234985cf11213fd204361a9c7d8599205b
4
+ data.tar.gz: c6d3594da881c17292a1c4466604aa0af3cf2f92f369cbe640c9b2f2384f0d36
5
5
  SHA512:
6
- metadata.gz: 63338541f098246944ee6a1e761d0c47ad8434eb722302059205ce4c75a92cb8ab92916d7d3d2156f6882a55ebeb79d051fd51ec25c9db8c6f515bf556d1151d
7
- data.tar.gz: a8b900d61a286c864507f0a3ab0195a9df0886b825d10cb4beaa7d9125e918176a1f08f3dba71bcfd7d700df87f4a54c2ad62a0ff26232276dbb6e41d1a4d740
6
+ metadata.gz: 5127ae2d7c23c25e87b7ac3d10088b4cf8fd07a5f68a4dcf135956d1b72036e50af83f551991101f79b0c10d99ac2532a11e1e269ee8a9fed03fe2c2a6670c54
7
+ data.tar.gz: e09a526ec3a8eb15fef050fc5c15b6c4425022fd399ed982a8231170a18e390f140bef6ea29d04e15d9e241065bd05c8053060b81476e30cab849d0f61a38ca1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,86 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.104.0](https://github.com/openai/openai-ruby/compare/v0.103.0...v0.104.0) (2026-10-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * **api:** add beta session spending limits ([#834](https://github.com/openai/openai-ruby/issues/834)) ([c185bc4](https://github.com/openai/openai-ruby/commit/c185bc44d83e46ea1f787caeda070ffcbb1c672d))
9
+ * **api:** add billing_not_active session error code ([#829](https://github.com/openai/openai-ruby/issues/829)) ([519de99](https://github.com/openai/openai-ruby/commit/519de999e68e9ac45a6fccf59cd316e3ea98da36))
10
+ * **api:** add OCI external-storage provider support ([#835](https://github.com/openai/openai-ruby/issues/835)) ([cb28e54](https://github.com/openai/openai-ruby/commit/cb28e540cd386a87bc268605ee068e617d584e3a))
11
+ * **api:** add organization Decisions usage reporting ([#838](https://github.com/openai/openai-ruby/issues/838)) ([ab2c712](https://github.com/openai/openai-ruby/commit/ab2c7126ab00843bf0d54e664ec63ba4f4658db4))
12
+ * **api:** add prompt-based voice creation ([#891](https://github.com/openai/openai-ruby/issues/891)) ([43450af](https://github.com/openai/openai-ruby/commit/43450afac60fbff8945f40258f99e8014d0a4b74))
13
+ * **api:** add regional processing residency options ([#866](https://github.com/openai/openai-ruby/issues/866)) ([e27adc6](https://github.com/openai/openai-ruby/commit/e27adc6f619da8a764d347fc59d017b7909a6d54))
14
+ * **api:** add response error diagnostics and model notices ([#872](https://github.com/openai/openai-ruby/issues/872)) ([f0c4dfd](https://github.com/openai/openai-ruby/commit/f0c4dfd8119b7b614439646d8584379b847f7660))
15
+ * **api:** add scope-only project API key updates ([#867](https://github.com/openai/openai-ruby/issues/867)) ([53e6572](https://github.com/openai/openai-ruby/commit/53e6572113e963d63eecb143a9d9b4317834b245))
16
+ * **api:** add shida to named Live voices ([#830](https://github.com/openai/openai-ruby/issues/830)) ([4918656](https://github.com/openai/openai-ruby/commit/491865696bacbd2577e7d12baa67b57ae94efb4c))
17
+ * **api:** add vault updates and metadata filters ([#824](https://github.com/openai/openai-ruby/issues/824)) ([9967b42](https://github.com/openai/openai-ruby/commit/9967b42dcf457aae54e642d4ebb16ea171480d73))
18
+ * **api:** align beta pagination limits and non-null parameters ([#833](https://github.com/openai/openai-ruby/issues/833)) ([e29a104](https://github.com/openai/openai-ruby/commit/e29a1049c193b9e65fcefe2d73a03a33e815aa3b))
19
+ * **api:** expose image tool error and moderation details ([#857](https://github.com/openai/openai-ruby/issues/857)) ([ecc5ba0](https://github.com/openai/openai-ruby/commit/ecc5ba014fd20601892b520532f1d662ca901995))
20
+ * **api:** support audio fixture playback in Live sessions ([#869](https://github.com/openai/openai-ruby/issues/869)) ([77ab2e6](https://github.com/openai/openai-ruby/commit/77ab2e66b31599bdfde48942df541bf00af2ec9f))
21
+ * **api:** support Decisions in Live sessions ([#884](https://github.com/openai/openai-ruby/issues/884)) ([808d7de](https://github.com/openai/openai-ruby/commit/808d7dec6fc4a475e3dd9f1b3785bc0bc73a022e))
22
+ * **api:** support image URLs and detailed safety alert explanations ([#836](https://github.com/openai/openai-ruby/issues/836)) ([9e5cc5c](https://github.com/openai/openai-ruby/commit/9e5cc5c9312213c53f5b07fa031fa31092a5239b))
23
+ * **api:** support scopes in project API key updates ([#889](https://github.com/openai/openai-ruby/issues/889)) ([c471323](https://github.com/openai/openai-ruby/commit/c471323246e6f063851109a4b45ba816471a2956))
24
+ * **api:** support updating project API key expiry ([#844](https://github.com/openai/openai-ruby/issues/844)) ([5490f04](https://github.com/openai/openai-ruby/commit/5490f04d01949633e750d5a0288ba73178a39f60))
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * **api:** clarify project API key scope updates ([#886](https://github.com/openai/openai-ruby/issues/886)) ([0947f00](https://github.com/openai/openai-ruby/commit/0947f007cb34ce64b4eeac6d67113351bebf2584))
30
+ * **api:** expose Realtime response error messages ([#868](https://github.com/openai/openai-ruby/issues/868)) ([0bf770c](https://github.com/openai/openai-ruby/commit/0bf770c78789967c8c936316b189635fe0d7e18b))
31
+
32
+
33
+ ### Chores
34
+
35
+ * **api:** clarify agent tool limits and environment pagination ([#843](https://github.com/openai/openai-ruby/issues/843)) ([c51092e](https://github.com/openai/openai-ruby/commit/c51092efae4da025e344e6d557d4a8bb9263e6a5))
36
+ * **api:** clarify decision creation documentation ([#831](https://github.com/openai/openai-ruby/issues/831)) ([983a531](https://github.com/openai/openai-ruby/commit/983a5314d9dba5f3539b9e81220b185ee123b0d5))
37
+ * **api:** clarify Decisions question and answer descriptions ([#828](https://github.com/openai/openai-ruby/issues/828)) ([bc4a105](https://github.com/openai/openai-ruby/commit/bc4a1050da3d94bc2570ded2ae76dee78470f934))
38
+ * **api:** clarify Decisions request and response fields ([#862](https://github.com/openai/openai-ruby/issues/862)) ([cb94c48](https://github.com/openai/openai-ruby/commit/cb94c48f6d80ad1057e7e58e54909ba158a11c9f))
39
+ * **api:** clarify the Live startup history token limit ([#881](https://github.com/openai/openai-ruby/issues/881)) ([a2688e1](https://github.com/openai/openai-ruby/commit/a2688e1a4e1a5b805923a96c2293462ba31e07b2))
40
+ * **api:** document 128-character safety identifiers ([#827](https://github.com/openai/openai-ruby/issues/827)) ([951d306](https://github.com/openai/openai-ruby/commit/951d306a7d4365041e530bdb9ab9846673068265))
41
+ * **api:** document decision choice constraints ([#832](https://github.com/openai/openai-ruby/issues/832)) ([c15703a](https://github.com/openai/openai-ruby/commit/c15703ae2c7838c17e870b2f8922b51a9a0c74ed))
42
+ * **api:** document Files API rate-limit responses ([#826](https://github.com/openai/openai-ruby/issues/826)) ([9208b6f](https://github.com/openai/openai-ruby/commit/9208b6ff9e5bbe216377ce4622865ae5e94e1d22))
43
+ * **api:** maintain structured output compatibility ([#885](https://github.com/openai/openai-ruby/issues/885)) ([cc7ff70](https://github.com/openai/openai-ruby/commit/cc7ff7072bd332744fe575256a9be2d6938d9148))
44
+ * **api:** preserve agent resource helper loading ([#858](https://github.com/openai/openai-ruby/issues/858)) ([fa4626b](https://github.com/openai/openai-ruby/commit/fa4626bbd15ba42ed3ad1981aebf3df1c0c31a86))
45
+ * **api:** preserve Ruby SDK compatibility ([#837](https://github.com/openai/openai-ruby/issues/837)) ([1c0c5a6](https://github.com/openai/openai-ruby/commit/1c0c5a6e82c8456a81971e887087d6aa1bdd31d5))
46
+ * **api:** preserve structured-output input types ([#882](https://github.com/openai/openai-ruby/issues/882)) ([04a3164](https://github.com/openai/openai-ruby/commit/04a3164b5fc3daa1401e93228cc8d41949be49af))
47
+ * **api:** preserve structured-output schema inputs ([#880](https://github.com/openai/openai-ruby/issues/880)) ([3fcdc5d](https://github.com/openai/openai-ruby/commit/3fcdc5d9cfd44c34ed3821c43c915b1730dd4421))
48
+ * **api:** preserve structured-output tool inputs ([#877](https://github.com/openai/openai-ruby/issues/877)) ([39e09c2](https://github.com/openai/openai-ruby/commit/39e09c2dda914a53d1ebeaa0bd6050857a7bc136))
49
+ * **api:** preserve webhook diagnostic redaction ([#879](https://github.com/openai/openai-ruby/issues/879)) ([b9ec465](https://github.com/openai/openai-ruby/commit/b9ec4658e4e76577e9f9c59f14d6c1cd59f58409))
50
+ * **ci:** prepare the next release branch ([#863](https://github.com/openai/openai-ruby/issues/863)) ([5f6a60b](https://github.com/openai/openai-ruby/commit/5f6a60b0f904a6ddc7584cfa3206d600aaf5582e))
51
+ * **deps-dev:** bump sorbet-runtime from 0.6.13508 to 0.6.13528 in the development-dependencies group ([#845](https://github.com/openai/openai-ruby/issues/845)) ([6e01d68](https://github.com/openai/openai-ruby/commit/6e01d68d2c8fb10bcfa2a2a9a6771b9c656cb6fd))
52
+ * **deps:** bump actions/create-github-app-token from 3.2.0 to 3.3.0 ([#847](https://github.com/openai/openai-ruby/issues/847)) ([ceac848](https://github.com/openai/openai-ruby/commit/ceac8485637b04e7f7f3b1ddb05309c3d4850dfb))
53
+ * **deps:** bump ruby/setup-ruby from 1.327.0 to 1.329.0 ([#846](https://github.com/openai/openai-ruby/issues/846)) ([51cd56e](https://github.com/openai/openai-ruby/commit/51cd56e5a39f8d02ad90ef2305595d79ed9469e5))
54
+ * **deps:** bump the codeql group with 2 updates ([#888](https://github.com/openai/openai-ruby/issues/888)) ([df298b6](https://github.com/openai/openai-ruby/commit/df298b634b5c88dfea2f3bd5e1e243ece8cf7295))
55
+
56
+
57
+ ### Documentation
58
+
59
+ * document hosted checker rollout on main ([#873](https://github.com/openai/openai-ruby/issues/873)) ([9196a24](https://github.com/openai/openai-ruby/commit/9196a24282555fb7312844eb7d792ed589f2ea64))
60
+
61
+
62
+ ### Styles
63
+
64
+ * align webhook source with generated baseline ([#861](https://github.com/openai/openai-ruby/issues/861)) ([4d2b7d2](https://github.com/openai/openai-ruby/commit/4d2b7d2aa5a5b166e55a4625a4d08760fc9c60a8))
65
+
66
+
67
+ ### Refactors
68
+
69
+ * isolate agent file helpers from generated resources ([#853](https://github.com/openai/openai-ruby/issues/853)) ([bc078ba](https://github.com/openai/openai-ruby/commit/bc078baeb9b2274e182b8421b2bf46206bbd23eb))
70
+ * isolate agent session stream helper from generated resource ([#854](https://github.com/openai/openai-ruby/issues/854)) ([bdc2d86](https://github.com/openai/openai-ruby/commit/bdc2d866c0ac5049c0d9eb4722a0980c4010b3be))
71
+ * isolate chat completion stream helper from generated resource ([#855](https://github.com/openai/openai-ruby/issues/855)) ([9efcd4e](https://github.com/openai/openai-ruby/commit/9efcd4efde9370281ae4273aad737542f09655aa))
72
+ * isolate client request and copying methods ([#860](https://github.com/openai/openai-ruby/issues/860)) ([37195b2](https://github.com/openai/openai-ruby/commit/37195b2963fe68058440f781ac7b1822bb35fd5e))
73
+ * isolate file polling in SDK extensions ([#840](https://github.com/openai/openai-ruby/issues/840)) ([d8c5f75](https://github.com/openai/openai-ruby/commit/d8c5f75ac43e87c84833fb15daabd77299121080))
74
+ * isolate parsed chat fields from generated models ([#851](https://github.com/openai/openai-ruby/issues/851)) ([7b13907](https://github.com/openai/openai-ruby/commit/7b13907e3a1913b7f53940db70e2525487484ebe))
75
+ * isolate parsed response fields from generated models ([#852](https://github.com/openai/openai-ruby/issues/852)) ([7e54b76](https://github.com/openai/openai-ruby/commit/7e54b768b908961680183ec3dcbef7f498e3415c))
76
+ * isolate response output text helper from generated model ([#850](https://github.com/openai/openai-ruby/issues/850)) ([a75091c](https://github.com/openai/openai-ruby/commit/a75091c9d877ed310aa401f2a1aee69745791aef))
77
+ * isolate response stream helpers from generated resource ([#856](https://github.com/openai/openai-ruby/issues/856)) ([b8ca246](https://github.com/openai/openai-ruby/commit/b8ca246f47ca5c3c1ce528eef068118b2d9d6b60))
78
+ * isolate vector store file batch helpers ([#842](https://github.com/openai/openai-ruby/issues/842)) ([3a15812](https://github.com/openai/openai-ruby/commit/3a158124ce0f4f5c5e0b7f88249adcebe2f4c4bf))
79
+ * isolate vector store file helpers ([#841](https://github.com/openai/openai-ruby/issues/841)) ([0344821](https://github.com/openai/openai-ruby/commit/03448210f4726ed995b317ca6af8e3da75c0fbbf))
80
+ * reuse response output text helper in streams ([#839](https://github.com/openai/openai-ruby/issues/839)) ([9c847e9](https://github.com/openai/openai-ruby/commit/9c847e93a4ec40eb2f6d06386b5c3a9c3f69251f))
81
+ * share Live and Translation WebSocket failure handling ([#871](https://github.com/openai/openai-ruby/issues/871)) ([a60ebe9](https://github.com/openai/openai-ruby/commit/a60ebe95ea89df2f6bc44f671877b48b24bce2e2))
82
+ * use generated Ruby WebSocket bindings ([#887](https://github.com/openai/openai-ruby/issues/887)) ([6baf841](https://github.com/openai/openai-ruby/commit/6baf84161558cd87fcf21885db62887fbf8620e9))
83
+
3
84
  ## [0.103.0](https://github.com/openai/openai-ruby/compare/v0.102.0...v0.103.0) (2026-10-09)
4
85
 
5
86
 
data/README.md CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
15
15
  <!-- x-release-please-start-version -->
16
16
 
17
17
  ```ruby
18
- gem "openai", "~> 0.103.0"
18
+ gem "openai", "~> 0.104.0"
19
19
  ```
20
20
 
21
21
  <!-- x-release-please-end -->
@@ -1212,6 +1212,28 @@ All parameter and response objects inherit from `OpenAI::Internal::Type::BaseMod
1212
1212
 
1213
1213
  4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.
1214
1214
 
1215
+ ### Updating project API-key scopes
1216
+
1217
+ Use `update_scopes` to replace a project's API-key restrictions without changing
1218
+ its expiration. Configure an admin API key with permission to write project API
1219
+ keys:
1220
+
1221
+ ```ruby
1222
+ client = OpenAI::Client.new(admin_api_key: ENV.fetch("OPENAI_ADMIN_KEY"))
1223
+ key = client.admin.organization.projects.api_keys.update_scopes(
1224
+ "key_example",
1225
+ project_id: "proj_example",
1226
+ scopes: ["api.all.read"]
1227
+ )
1228
+ ```
1229
+
1230
+ An empty `scopes: []` removes key restrictions (All permissions), subject to the
1231
+ owner's effective access; it does **not** mean no access. This does not change
1232
+ roles or grant administrative permissions. Expired keys cannot be updated, and
1233
+ scope changes follow the same authentication-cache propagation as dashboard edits.
1234
+ The response contains the redacted key, never its secret. Use the existing
1235
+ `update(..., expires_in_seconds: ...)` method to change expiration.
1236
+
1215
1237
  ### Making custom or undocumented requests
1216
1238
 
1217
1239
  #### Undocumented properties
data/lib/openai/client.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "helpers/data_residency"
4
+ require_relative "helpers/client_runtime"
4
5
 
5
6
  module OpenAI
6
7
  class Client < OpenAI::Internal::Transport::BaseClient
@@ -40,6 +41,7 @@ module OpenAI
40
41
  # @api private
41
42
  attr_reader :workload_identity_auth
42
43
 
44
+ # Generated resource accessors.
43
45
  # @return [OpenAI::Resources::Decisions]
44
46
  attr_reader :decisions
45
47
 
@@ -180,392 +182,6 @@ module OpenAI
180
182
  {"authorization" => "Bearer #{@admin_api_key}"}
181
183
  end
182
184
 
183
- # @api private
184
- private def x509_identity?(identity)
185
- OpenAI::Auth::X509Transport.exact_instance?(identity, OpenAI::Auth::X509WorkloadIdentity)
186
- end
187
-
188
- # @api private
189
- private def x509_transport?(transport)
190
- OpenAI::Auth::X509Transport.exact_instance?(transport, OpenAI::Auth::X509Transport)
191
- end
192
-
193
- # Creates and returns a new client for interacting with the API.
194
- #
195
- # @param api_key [String, nil] Defaults to `ENV["OPENAI_API_KEY"]`.
196
- # Mutually exclusive with `workload_identity`.
197
- #
198
-
199
- # @api private
200
- private def build_request(request, options)
201
- if @provider_runtime
202
- built = super
203
- body = built[:body]
204
- # Capture only the final model; provider hooks run after body encoding.
205
- model = body.reverse_each.find { |key, _| key == :model || key == "model" }&.last if body.is_a?(Hash)
206
- model = model.to_s if model.is_a?(Symbol)
207
- return built.merge(provider_request_model: model)
208
- end
209
-
210
- unless @workload_identity_auth && x509_transport?(@requester)
211
- return super
212
- end
213
-
214
- selected = {}.merge(request.fetch(:security, {bearer_auth: true, admin_api_key_auth: true})).freeze
215
- if selected.any? { |scheme, enabled| enabled && scheme != :bearer_auth && scheme != :admin_api_key_auth }
216
- raise ArgumentError, "Unsupported authentication security scheme for X.509 workload identity"
217
- end
218
-
219
- security = {
220
- bearer_auth: selected[:bearer_auth] == true,
221
- admin_api_key_auth: selected[:admin_api_key_auth] == true
222
- }.freeze
223
- expected = auth_headers(security: security)["authorization"]
224
- built = super(request.merge(security: security), options)
225
- canonical_headers = @requester.validate_api_request!(
226
- url: built.fetch(:url),
227
- headers: built.fetch(:headers)
228
- )
229
- unless expected == canonical_headers["authorization"]
230
- raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
231
- end
232
-
233
- auth_max_retries = options.fetch(:max_retries, @max_retries)
234
- built.merge(headers: canonical_headers, x509_auth_max_retries: auth_max_retries)
235
- end
236
-
237
- # @api private
238
- private def prepare_request(request, redirect_count:, retry_count:)
239
- if workload_identity_request?(request)
240
- request = prepare_workload_identity_request(request, retry_count: retry_count)
241
- end
242
-
243
- preparer = @provider_runtime&.prepare_request
244
- return super(request, redirect_count: redirect_count, retry_count: retry_count) unless preparer
245
- preparer.call(request)
246
- end
247
-
248
- # @api private
249
- private def validate_prepared_request(request, original_request:)
250
- prepared_request = super
251
- return prepared_request unless @workload_identity_auth && x509_transport?(@requester)
252
-
253
- canonical_headers = @requester.validate_api_request!(
254
- url: prepared_request.fetch(:url),
255
- headers: prepared_request.fetch(:headers)
256
- )
257
- expected = if (context = original_request[:x509_request_context])
258
- "Bearer #{context.fetch(:token)}"
259
- else
260
- original_request.fetch(:headers)["authorization"]
261
- end
262
-
263
- unless canonical_headers["authorization"] == expected
264
- raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
265
- end
266
-
267
- prepared_request.merge(headers: canonical_headers)
268
- end
269
-
270
- # @api private
271
- private def validate_retry_delay!(request, delay:)
272
- deadline = request[:x509_request_context]&.fetch(:deadline) || request[:workload_identity_deadline]
273
- if deadline && delay >= deadline - OpenAI::Internal::Util.monotonic_secs
274
- raise WORKLOAD_IDENTITY_DEADLINE_ERROR, "request timed out during workload identity authentication"
275
- end
276
-
277
- super
278
- end
279
-
280
- # @api private
281
- private def send_request(request, redirect_count:, retry_count:, send_retry_header:)
282
- if @workload_identity_auth && x509_transport?(@requester)
283
- canonical_headers = @requester.validate_api_request!(
284
- url: request.fetch(:url),
285
- headers: request.fetch(:headers)
286
- )
287
- request = request.merge(headers: canonical_headers)
288
- authorization = canonical_headers["authorization"]
289
- expected = "Bearer #{WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}"
290
- admin_authorization = @admin_api_key && "Bearer #{@admin_api_key}"
291
- unless authorization.nil? || authorization == expected || authorization == admin_authorization
292
- raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
293
- end
294
- end
295
-
296
- return super unless workload_identity_request?(request)
297
-
298
- x509_request = x509_transport?(@requester)
299
- previous_context = request[:x509_request_context]
300
- deadline = if x509_request
301
- previous_context&.fetch(:deadline) ||
302
- request[:workload_identity_deadline] ||
303
- request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
304
- else
305
- request[:workload_identity_deadline] ||
306
- request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
307
- end
308
-
309
- request = request.merge(workload_identity_deadline: deadline)
310
- if x509_request
311
- replay_state = previous_context&.fetch(:replay_state) || []
312
- issuer_retries = previous_context&.fetch(:issuer_retries, 0) || 0
313
- auth_max_retries = previous_context&.fetch(:auth_max_retries) || request.fetch(:x509_auth_max_retries)
314
- api_max_retries = previous_context&.fetch(:api_max_retries) || request.fetch(:max_retries)
315
- log_context = previous_context&.fetch(:log_context) || yield
316
- context = {
317
- deadline: deadline,
318
- replay_state: replay_state,
319
- issuer_retries: issuer_retries,
320
- auth_max_retries: auth_max_retries,
321
- api_max_retries: api_max_retries,
322
- log_context: log_context,
323
- token: nil
324
- }
325
- request = request.merge(x509_request_context: context, max_retries: 0)
326
- end
327
-
328
- begin
329
- super(
330
- request,
331
- redirect_count: redirect_count,
332
- retry_count: retry_count,
333
- send_retry_header: send_retry_header
334
- )
335
- rescue OpenAI::Errors::AuthenticationError
336
- if x509_request
337
- rejected_token = request.fetch(:x509_request_context).fetch(:token)
338
- raise if rejected_token.nil?
339
-
340
- @workload_identity_auth.invalidate_token(rejected_token)
341
- end
342
-
343
- replay_allowed = request_replayable?(request)
344
- replay_allowed &&= x509_request ? replay_state.empty? : retry_count.zero?
345
- raise unless replay_allowed
346
-
347
- if x509_request
348
- replay_state << true
349
- replay_state.freeze
350
- issuer_retries = context.fetch(:issuer_retries)
351
- auth_max_retries = context.fetch(:auth_max_retries)
352
- api_max_retries = context.fetch(:api_max_retries)
353
- log_context = context.fetch(:log_context)
354
- context = {
355
- deadline: deadline,
356
- replay_state: replay_state,
357
- issuer_retries: issuer_retries,
358
- auth_max_retries: auth_max_retries,
359
- api_max_retries: api_max_retries,
360
- log_context: log_context,
361
- token: nil
362
- }
363
- request = request.merge(x509_request_context: context)
364
- else
365
- @workload_identity_auth.invalidate_token
366
- end
367
-
368
- begin
369
- super(
370
- request,
371
- redirect_count: redirect_count,
372
- retry_count: retry_count + 1,
373
- send_retry_header: send_retry_header
374
- )
375
- rescue OpenAI::Errors::AuthenticationError
376
- if x509_request && (rejected_token = request.fetch(:x509_request_context).fetch(:token))
377
- @workload_identity_auth.invalidate_token(rejected_token)
378
- end
379
-
380
- raise
381
- end
382
- end
383
-
384
- rescue Timeout::Error => error
385
- unless x509_request
386
- raise unless error.is_a?(WORKLOAD_IDENTITY_DEADLINE_ERROR)
387
-
388
- url = request.fetch(:url).dup
389
- url.query = nil
390
- url.fragment = nil
391
- cause = Timeout::Error.new(error.message)
392
- raise OpenAI::Errors::APITimeoutError.new(url: url, message: error.message), cause: cause
393
- end
394
-
395
- url = request.fetch(:url).dup
396
- url.query = nil
397
- url.fragment = nil
398
- message = "request timed out during workload identity authentication"
399
- raise OpenAI::Errors::APITimeoutError.new(url: url, message: message), cause: nil
400
- end
401
-
402
- private def workload_identity_request?(request)
403
- return false unless @workload_identity_auth
404
-
405
- expected = "Bearer #{WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}"
406
- request[:headers]["authorization"] == expected
407
- end
408
-
409
- private def prepare_workload_identity_request(request, retry_count:)
410
- deadline = request[:workload_identity_deadline]
411
- previous_issuer_retries = request[:x509_request_context]&.fetch(:issuer_retries, 0) || 0
412
- attempts = 0
413
- begin
414
- token = @workload_identity_auth.get_token(deadline: deadline)
415
- rescue OpenAI::Errors::APIError => error
416
- status = error.status
417
- connection_failure = error.is_a?(OpenAI::Errors::APIConnectionError)
418
- retryable_connection_failure = connection_failure &&
419
- false.equal?(error.request_may_have_been_sent?)
420
- retryable_status = retryable_connection_failure ||
421
- [408, 409, 429].include?(status) ||
422
- (status.is_a?(Integer) && (500..599).cover?(status))
423
- consumed_retries = attempts + previous_issuer_retries + retry_count
424
- unless x509_transport?(@requester) &&
425
- retryable_status &&
426
- consumed_retries < request.fetch(:x509_request_context).fetch(:auth_max_retries) &&
427
- (retryable_connection_failure || self.class.should_retry?(status, headers: error.headers || {}))
428
- raise
429
- end
430
-
431
- delay = retry_delay(error.headers || {}, retry_count: attempts)
432
- if deadline && delay >= deadline - OpenAI::Internal::Util.monotonic_secs
433
- raise Timeout::Error, "request timed out during workload identity authentication"
434
- end
435
-
436
- context = request.fetch(:x509_request_context)
437
- response = if connection_failure
438
- nil
439
- else
440
- OpenAI::ResponseMetadata.new(status: status, headers: error.headers || {})
441
- end
442
-
443
- context.fetch(:log_context).retry_scheduled(
444
- connection_failure ? error : status,
445
- delay: delay,
446
- response: response,
447
- retry_count: consumed_retries,
448
- max_retries: context.fetch(:auth_max_retries)
449
- )
450
- sleep(delay)
451
- attempts += 1
452
- retry
453
- end
454
-
455
- if (context = request[:x509_request_context])
456
- context[:issuer_retries] = previous_issuer_retries + attempts
457
- context[:token] = token.dup.freeze
458
- context.freeze
459
- end
460
-
461
- updated_headers = request[:headers].merge("authorization" => "Bearer #{token}")
462
- updated_request = request
463
- .except(:workload_identity_deadline, :x509_request_context, :x509_auth_max_retries)
464
- .merge(headers: updated_headers)
465
- if context
466
- updated_request = updated_request.merge(
467
- max_retries: [context.fetch(:api_max_retries) - context.fetch(:issuer_retries), 0].max
468
- )
469
- end
470
-
471
- request_with_remaining_timeout(
472
- updated_request,
473
- deadline
474
- )
475
- rescue Timeout::Error => e
476
- raise if x509_transport?(@requester)
477
-
478
- url = request.fetch(:url).dup
479
- url.query = nil
480
- url.fragment = nil
481
- raise OpenAI::Errors::APITimeoutError.new(url: url, message: e.message)
482
- end
483
-
484
- # @api private
485
- private def request_with_remaining_timeout(request, deadline)
486
- return request if deadline.nil?
487
-
488
- remaining = deadline - OpenAI::Internal::Util.monotonic_secs
489
- unless remaining.positive?
490
- raise Timeout::Error, "request timed out during workload identity authentication"
491
- end
492
-
493
- request.merge(timeout: remaining)
494
- end
495
-
496
- # Returns a new client of the same class with the supplied constructor options overridden.
497
- # Other settings and the HTTP transport are inherited. The original client
498
- # is unchanged. Header overrides are merged; nil removes an individual
499
- # header, and default_headers: nil clears all custom default headers.
500
- # Subclasses with incompatible constructors or a private .new must override
501
- # this method if they need to support copying.
502
- #
503
- # @example Select a regional endpoint for a call
504
- # client.with_options(base_url: "https://eu.api.openai.com/v1").responses.create(...)
505
- # @param overrides [Hash{Symbol=>Object}] Options accepted by {#initialize}.
506
- # @return [self]
507
- def with_options(**overrides)
508
- if overrides.key?(:workload_identity) && !overrides.key?(:http_client)
509
- selected_identity = overrides.fetch(:workload_identity)
510
- if x509_identity?(selected_identity) && (configured_transport = selected_identity.transport)
511
- overrides = overrides.merge(http_client: configured_transport)
512
- end
513
- end
514
-
515
- previous_transport = @copy_options.fetch(:http_client)
516
- transport = overrides.fetch(:http_client, previous_transport)
517
- if overrides[:data_residency] && x509_transport?(transport)
518
- residency = overrides.fetch(:data_residency)
519
- options = OpenAI::Internal::ClientOptions.copy(@copy_options, overrides.except(:data_residency))
520
- options.delete(:base_url) unless overrides.key?(:base_url)
521
- return copy_with_workload_identity_auth(options.merge(data_residency: residency))
522
- end
523
-
524
- options = OpenAI::Internal::ClientOptions.copy(@copy_options, overrides)
525
- adopted_identity = x509_identity?(options.fetch(:workload_identity)) &&
526
- !x509_identity?(@copy_options.fetch(:workload_identity))
527
- previous_origin = previous_transport.api_origin if x509_transport?(previous_transport)
528
- selected_origin = transport.api_origin if x509_transport?(transport)
529
- if adopted_identity && selected_origin
530
- inherited_origin = OpenAI::Internal::Util.uri_origin(URI(options.fetch(:base_url).to_s))
531
- adopted_identity = !inherited_origin.casecmp?(selected_origin)
532
- end
533
-
534
- if (adopted_identity || previous_origin != selected_origin) &&
535
- !overrides.key?(:base_url) &&
536
- !overrides[:data_residency]
537
- options.delete(:base_url)
538
- end
539
-
540
- copy_with_workload_identity_auth(options)
541
- end
542
-
543
- # @api private
544
- private def copy_with_workload_identity_auth(options)
545
- copied = self.class.new(**options)
546
- identity = @copy_options.fetch(:workload_identity)
547
- if x509_identity?(identity) &&
548
- identity.equal?(options.fetch(:workload_identity)) &&
549
- copied.requester.equal?(@requester)
550
- copied.adopt_workload_identity_auth!(@workload_identity_auth)
551
- end
552
-
553
- copied
554
- end
555
-
556
- # @api private
557
- def adopt_workload_identity_auth!(authenticator)
558
- identity = @copy_options.fetch(:workload_identity)
559
- unless x509_identity?(identity) &&
560
- x509_transport?(@requester) &&
561
- OpenAI::Auth::X509Transport.exact_instance?(authenticator, OpenAI::Auth::WorkloadIdentityAuth) &&
562
- authenticator.bound_to?(identity, transport: @requester)
563
- raise ArgumentError, "X.509 authenticator must match its workload identity and attested transport"
564
- end
565
-
566
- @workload_identity_auth = authenticator
567
- end
568
-
569
185
  # Creates and returns a new client for interacting with the API.
570
186
  #
571
187
  # @param api_key [String, nil] Defaults to `ENV["OPENAI_API_KEY"]`.
@@ -815,6 +431,7 @@ module OpenAI
815
431
  on_retry: self.on_retry()
816
432
  )
817
433
 
434
+ # Initialize generated resources.
818
435
  @decisions = OpenAI::Resources::Decisions.new(client: self)
819
436
  @completions = OpenAI::Resources::Completions.new(client: self)
820
437
  @chat = OpenAI::Resources::Chat.new(client: self)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../../resources/admin/organization/projects/api_keys"
4
+
5
+ module OpenAI
6
+ module Resources
7
+ class Admin
8
+ class Organization
9
+ class Projects
10
+ class APIKeys
11
+ # Replace an API key's scope restrictions without changing its expiration.
12
+ # Requires permission to write project API keys; expired keys cannot be updated.
13
+ # An empty array removes key restrictions (All permissions), subject to the
14
+ # owner's effective access. This does not change roles or grant admin permissions.
15
+ # Changes follow the same authentication-cache propagation as dashboard edits.
16
+ # To update the expiration in the same request, pass
17
+ # `request_options: {extra_body: {expires_in_seconds: seconds}}`.
18
+ #
19
+ # @param api_key_id [String]
20
+ # @param project_id [String]
21
+ # @param scopes [Array<String>] Use ["api.all.read"] for read-only access.
22
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}]
23
+ # @return [OpenAI::Models::Admin::Organization::Projects::ProjectAPIKey]
24
+ def update_scopes(api_key_id, project_id:, scopes:, request_options: {})
25
+ parsed, options = OpenAI::Admin::Organization::Projects::APIKeyUpdateScopesParams.dump_request(
26
+ {scopes: scopes, request_options: request_options}
27
+ )
28
+ @client.request(
29
+ method: :post,
30
+ path: ["organization/projects/%1$s/api_keys/%2$s", project_id, api_key_id],
31
+ body: parsed,
32
+ model: OpenAI::Admin::Organization::Projects::ProjectAPIKey,
33
+ security: {admin_api_key_auth: true},
34
+ options: options
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAI
4
+ module Resources
5
+ class Beta
6
+ class Agents
7
+ class Sessions
8
+ # Submit input to an idle session and stream one turn through idle or failure.
9
+ # The caller must be the session's only input writer during iteration.
10
+ # Handlers run sequentially; failures submit a generic error without exception text.
11
+ # Input and each tool result use distinct retry-safe idempotency keys.
12
+ # A block closes the connection on every exit path without cancelling the turn.
13
+ #
14
+ # @param session_id [String]
15
+ # @param input [String, Array<OpenAI::Models::Beta::AgentSessionInputMessageParam>]
16
+ # @param tool_handlers [Hash{String=>Proc}]
17
+ # @param on_tool_error [Proc, nil]
18
+ # Beta: use with tool_handlers to log or monitor argument parsing, handler
19
+ # execution, and output conversion failures locally. Receives ToolError;
20
+ # API/transport errors still propagate normally. Ordinary observer errors
21
+ # are ignored, and the submitted tool failure stays generic.
22
+ # @param idempotency_key [String, nil] Applies only to the input submission.
23
+ # @param output_type [Class<OpenAI::BaseModel>, nil] Beta: parse output without changing session configuration.
24
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
25
+ # @yieldparam stream [OpenAI::Helpers::Agents::SessionStream]
26
+ # @return [OpenAI::Helpers::Agents::SessionStream]
27
+ def stream(
28
+ session_id,
29
+ input:,
30
+ tool_handlers: {},
31
+ on_tool_error: nil,
32
+ idempotency_key: nil,
33
+ output_type: nil,
34
+ request_options: {}
35
+ )
36
+ stream = OpenAI::Helpers::Agents::SessionStream.new(
37
+ sessions: self,
38
+ session_id: session_id,
39
+ input: input,
40
+ tool_handlers: tool_handlers,
41
+ on_tool_error: on_tool_error,
42
+ idempotency_key: idempotency_key,
43
+ output_type: output_type,
44
+ request_options: request_options
45
+ )
46
+ return stream unless block_given?
47
+
48
+ begin
49
+ yield stream
50
+ ensure
51
+ stream.close
52
+ end
53
+
54
+ stream
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end