openai 0.77.1 → 0.79.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/README.md +341 -10
  4. data/SECURITY.md +6 -22
  5. data/azure.md +110 -0
  6. data/bedrock.md +132 -0
  7. data/examples/mtls_custom_http_client.rb +61 -0
  8. data/lib/openai/auth/workload_identity.rb +13 -2
  9. data/lib/openai/auth/workload_identity_auth.rb +2 -1
  10. data/lib/openai/client.rb +34 -14
  11. data/lib/openai/errors.rb +11 -1
  12. data/lib/openai/helpers/streaming/chat_completion_stream.rb +3 -3
  13. data/lib/openai/helpers/streaming/response_stream.rb +5 -6
  14. data/lib/openai/helpers/structured_output/base_model.rb +20 -19
  15. data/lib/openai/helpers/structured_output/json_schema_converter.rb +12 -5
  16. data/lib/openai/http_client.rb +189 -0
  17. data/lib/openai/internal/conversation_cursor_page.rb +5 -6
  18. data/lib/openai/internal/cursor_page.rb +3 -3
  19. data/lib/openai/internal/logging.rb +419 -0
  20. data/lib/openai/internal/next_cursor_page.rb +5 -6
  21. data/lib/openai/internal/page.rb +2 -2
  22. data/lib/openai/internal/provider.rb +7 -1
  23. data/lib/openai/internal/read_io_adapter.rb +161 -0
  24. data/lib/openai/internal/stream.rb +2 -2
  25. data/lib/openai/internal/transport/base_client.rb +216 -57
  26. data/lib/openai/internal/type/array_of.rb +6 -4
  27. data/lib/openai/internal/type/base_model.rb +39 -1
  28. data/lib/openai/internal/type/base_page.rb +19 -2
  29. data/lib/openai/internal/type/base_stream.rb +40 -8
  30. data/lib/openai/internal/type/hash_of.rb +3 -3
  31. data/lib/openai/internal/util.rb +59 -112
  32. data/lib/openai/models/admin/organization/audit_log_list_params.rb +3 -1
  33. data/lib/openai/models/admin/organization/audit_log_list_response.rb +33 -11
  34. data/lib/openai/models/admin/organization/groups/role_list_response.rb +5 -1
  35. data/lib/openai/models/admin/organization/groups/role_retrieve_response.rb +5 -1
  36. data/lib/openai/models/admin/organization/projects/groups/role_list_response.rb +6 -1
  37. data/lib/openai/models/admin/organization/projects/groups/role_retrieve_response.rb +6 -1
  38. data/lib/openai/models/admin/organization/projects/service_account_create_response.rb +3 -1
  39. data/lib/openai/models/admin/organization/projects/users/role_list_response.rb +6 -1
  40. data/lib/openai/models/admin/organization/projects/users/role_retrieve_response.rb +6 -1
  41. data/lib/openai/models/admin/organization/users/role_list_response.rb +5 -1
  42. data/lib/openai/models/admin/organization/users/role_retrieve_response.rb +5 -1
  43. data/lib/openai/models/all_models.rb +3 -0
  44. data/lib/openai/models/audio/transcription_create_params.rb +7 -1
  45. data/lib/openai/models/audio/translation_create_params.rb +7 -1
  46. data/lib/openai/models/beta/beta_response.rb +9 -0
  47. data/lib/openai/models/beta/beta_response_stream_event.rb +1 -1
  48. data/lib/openai/models/beta/beta_responses_client_event.rb +28 -3
  49. data/lib/openai/models/beta/beta_responses_server_event.rb +1037 -61
  50. data/lib/openai/models/beta/response_compact_params.rb +9 -0
  51. data/lib/openai/models/beta/response_create_params.rb +9 -0
  52. data/lib/openai/models/containers/file_create_params.rb +4 -0
  53. data/lib/openai/models/content_provenance_check_create_params.rb +4 -0
  54. data/lib/openai/models/file_create_params.rb +4 -0
  55. data/lib/openai/models/image_create_variation_params.rb +4 -0
  56. data/lib/openai/models/image_edit_params.rb +8 -0
  57. data/lib/openai/models/responses/response_compact_params.rb +9 -0
  58. data/lib/openai/models/responses/response_stream_event.rb +1 -1
  59. data/lib/openai/models/responses/responses_client_event.rb +13 -1
  60. data/lib/openai/models/responses/responses_server_event.rb +1027 -54
  61. data/lib/openai/models/responses_model.rb +3 -0
  62. data/lib/openai/models/skill_create_params.rb +4 -0
  63. data/lib/openai/models/skills/version_create_params.rb +4 -0
  64. data/lib/openai/models/uploads/part_create_params.rb +4 -0
  65. data/lib/openai/models/vector_store_search_response.rb +3 -1
  66. data/lib/openai/models/video_create_character_params.rb +4 -0
  67. data/lib/openai/models/video_create_params.rb +4 -0
  68. data/lib/openai/models/video_edit_params.rb +4 -0
  69. data/lib/openai/models/video_extend_params.rb +4 -0
  70. data/lib/openai/models.rb +9 -1
  71. data/lib/openai/net_http_client.rb +295 -0
  72. data/lib/openai/providers/azure.rb +216 -0
  73. data/lib/openai/providers/bedrock.rb +3 -1
  74. data/lib/openai/resources/admin/organization/projects/groups/roles.rb +1 -1
  75. data/lib/openai/resources/admin/organization/projects/groups.rb +1 -1
  76. data/lib/openai/resources/admin/organization/projects/users/roles.rb +1 -1
  77. data/lib/openai/resources/admin/organization/projects.rb +4 -2
  78. data/lib/openai/resources/audio/transcriptions.rb +8 -0
  79. data/lib/openai/resources/audio/translations.rb +4 -0
  80. data/lib/openai/resources/beta/responses.rb +1 -1
  81. data/lib/openai/resources/beta/threads/runs/steps.rb +2 -2
  82. data/lib/openai/resources/containers/files.rb +4 -0
  83. data/lib/openai/resources/content_provenance_checks.rb +4 -0
  84. data/lib/openai/resources/conversations/items.rb +1 -1
  85. data/lib/openai/resources/evals/runs/output_items.rb +1 -1
  86. data/lib/openai/resources/files.rb +4 -0
  87. data/lib/openai/resources/images.rb +12 -0
  88. data/lib/openai/resources/responses.rb +3 -2
  89. data/lib/openai/resources/skills/versions.rb +4 -0
  90. data/lib/openai/resources/skills.rb +4 -0
  91. data/lib/openai/resources/uploads/parts.rb +4 -0
  92. data/lib/openai/resources/vector_stores/file_batches.rb +1 -1
  93. data/lib/openai/resources/videos.rb +38 -0
  94. data/lib/openai/resources/webhooks.rb +18 -6
  95. data/lib/openai/version.rb +1 -1
  96. data/lib/openai.rb +113 -108
  97. data/rbi/openai/auth.rbi +4 -4
  98. data/rbi/openai/client.rbi +15 -3
  99. data/rbi/openai/errors.rbi +7 -0
  100. data/rbi/openai/helpers/streaming/events.rbi +12 -0
  101. data/rbi/openai/http_client.rbi +123 -0
  102. data/rbi/openai/internal/logging.rbi +192 -0
  103. data/rbi/openai/internal/provider.rbi +3 -0
  104. data/rbi/openai/internal/read_io_adapter.rbi +52 -0
  105. data/rbi/openai/internal/transport/base_client.rbi +80 -10
  106. data/rbi/openai/internal/type/base_model.rbi +24 -1
  107. data/rbi/openai/internal/type/base_page.rbi +13 -2
  108. data/rbi/openai/internal/type/base_stream.rbi +16 -5
  109. data/rbi/openai/internal/util.rbi +26 -42
  110. data/rbi/openai/models/admin/organization/audit_log_list_params.rbi +5 -0
  111. data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +5 -0
  112. data/rbi/openai/models/all_models.rbi +15 -0
  113. data/rbi/openai/models/audio/transcription_create_params.rbi +14 -2
  114. data/rbi/openai/models/audio/translation_create_params.rbi +14 -2
  115. data/rbi/openai/models/beta/beta_response.rbi +15 -0
  116. data/rbi/openai/models/beta/beta_response_stream_event.rbi +1 -1
  117. data/rbi/openai/models/beta/beta_responses_client_event.rbi +37 -1
  118. data/rbi/openai/models/beta/beta_responses_server_event.rbi +3791 -54
  119. data/rbi/openai/models/beta/response_compact_params.rbi +15 -0
  120. data/rbi/openai/models/beta/response_create_params.rbi +15 -0
  121. data/rbi/openai/models/containers/file_create_params.rbi +8 -0
  122. data/rbi/openai/models/content_provenance_check_create_params.rbi +8 -0
  123. data/rbi/openai/models/file_create_params.rbi +8 -0
  124. data/rbi/openai/models/image_create_variation_params.rbi +8 -0
  125. data/rbi/openai/models/image_edit_params.rbi +16 -0
  126. data/rbi/openai/models/responses/response_compact_params.rbi +15 -0
  127. data/rbi/openai/models/responses/response_stream_event.rbi +1 -1
  128. data/rbi/openai/models/responses/responses_client_event.rbi +19 -0
  129. data/rbi/openai/models/responses/responses_server_event.rbi +3282 -53
  130. data/rbi/openai/models/responses_model.rbi +15 -0
  131. data/rbi/openai/models/skill_create_params.rbi +8 -0
  132. data/rbi/openai/models/skills/version_create_params.rbi +8 -0
  133. data/rbi/openai/models/uploads/part_create_params.rbi +8 -0
  134. data/rbi/openai/models/video_create_character_params.rbi +8 -0
  135. data/rbi/openai/models/video_create_params.rbi +8 -0
  136. data/rbi/openai/models/video_edit_params.rbi +8 -0
  137. data/rbi/openai/models/video_extend_params.rbi +8 -0
  138. data/rbi/openai/net_http_client.rbi +64 -0
  139. data/rbi/openai/providers.rbi +9 -0
  140. data/rbi/openai/resources/audio/transcriptions.rbi +14 -2
  141. data/rbi/openai/resources/audio/translations.rbi +7 -1
  142. data/rbi/openai/resources/containers/files.rbi +4 -0
  143. data/rbi/openai/resources/content_provenance_checks.rbi +4 -0
  144. data/rbi/openai/resources/files.rbi +4 -0
  145. data/rbi/openai/resources/images.rbi +20 -0
  146. data/rbi/openai/resources/skills/versions.rbi +4 -0
  147. data/rbi/openai/resources/skills.rbi +4 -0
  148. data/rbi/openai/resources/uploads/parts.rbi +4 -0
  149. data/rbi/openai/resources/videos.rbi +16 -0
  150. data/sig/openai/client.rbs +7 -2
  151. data/sig/openai/errors.rbs +5 -0
  152. data/sig/openai/http_client.rbs +76 -0
  153. data/sig/openai/internal/logging.rbs +88 -0
  154. data/sig/openai/internal/provider.rbs +3 -1
  155. data/sig/openai/internal/read_io_adapter.rbs +23 -0
  156. data/sig/openai/internal/transport/base_client.rbs +41 -6
  157. data/sig/openai/internal/type/base_model.rbs +13 -0
  158. data/sig/openai/internal/type/base_page.rbs +8 -1
  159. data/sig/openai/internal/type/base_stream.rbs +9 -3
  160. data/sig/openai/internal/util.rbs +12 -16
  161. data/sig/openai/models/admin/organization/audit_log_list_params.rbs +2 -0
  162. data/sig/openai/models/admin/organization/audit_log_list_response.rbs +2 -0
  163. data/sig/openai/models/all_models.rbs +6 -0
  164. data/sig/openai/models/beta/beta_response.rbs +6 -0
  165. data/sig/openai/models/beta/beta_responses_client_event.rbs +13 -0
  166. data/sig/openai/models/beta/beta_responses_server_event.rbs +1946 -54
  167. data/sig/openai/models/beta/response_compact_params.rbs +6 -0
  168. data/sig/openai/models/beta/response_create_params.rbs +6 -0
  169. data/sig/openai/models/responses/response_compact_params.rbs +6 -0
  170. data/sig/openai/models/responses/responses_client_event.rbs +7 -0
  171. data/sig/openai/models/responses/responses_server_event.rbs +1786 -53
  172. data/sig/openai/models/responses_model.rbs +6 -0
  173. data/sig/openai/net_http_client.rbs +34 -0
  174. data/sig/openai/providers.rbs +6 -0
  175. metadata +33 -4
  176. data/lib/openai/internal/transport/pooled_net_requester.rb +0 -210
  177. data/rbi/openai/internal/transport/pooled_net_requester.rbi +0 -82
  178. data/sig/openai/internal/transport/pooled_net_requester.rbs +0 -48
@@ -23,6 +23,9 @@ module OpenAI
23
23
  | :"gpt-5-pro"
24
24
  | :"gpt-5-pro-2025-10-06"
25
25
  | :"gpt-5.1-codex-max"
26
+ | :"gpt-daybreak-blue-latest"
27
+ | :"gpt-daybreak-red-latest"
28
+ | :"gpt-5.6-cyber"
26
29
 
27
30
  module ResponsesOnlyModel
28
31
  extend OpenAI::Internal::Type::Enum
@@ -41,6 +44,9 @@ module OpenAI
41
44
  GPT_5_PRO: :"gpt-5-pro"
42
45
  GPT_5_PRO_2025_10_06: :"gpt-5-pro-2025-10-06"
43
46
  GPT_5_1_CODEX_MAX: :"gpt-5.1-codex-max"
47
+ GPT_DAYBREAK_BLUE_LATEST: :"gpt-daybreak-blue-latest"
48
+ GPT_DAYBREAK_RED_LATEST: :"gpt-daybreak-red-latest"
49
+ GPT_5_6_CYBER: :"gpt-5.6-cyber"
44
50
 
45
51
  def self?.values: -> ::Array[OpenAI::Models::ResponsesModel::responses_only_model]
46
52
  end
@@ -0,0 +1,34 @@
1
+ module OpenAI
2
+ class NetHTTPClient < OpenAI::HTTPClient
3
+ KEEP_ALIVE_TIMEOUT: 30
4
+
5
+ DEFAULT_MAX_CONNECTIONS: Integer
6
+
7
+ private def connect: (url: URI::Generic) -> top
8
+
9
+ private def calibrate_socket_timeout: (top conn, Float? deadline) -> void
10
+
11
+ private def build_request: (
12
+ OpenAI::HTTPClient::Request request
13
+ ) {
14
+ (String arg0) -> void
15
+ } -> [top, (^-> void)]
16
+
17
+ private def with_pool: (
18
+ URI::Generic url,
19
+ deadline: Float?
20
+ ) {
21
+ (top arg0) -> void
22
+ } -> void
23
+
24
+ private def configured_connection: (URI::Generic url) -> top
25
+
26
+ def close: -> void
27
+
28
+ def execute: (
29
+ OpenAI::HTTPClient::Request request
30
+ ) -> OpenAI::HTTPClient::Response
31
+
32
+ def initialize: (?size: Integer) ?{ (Net::HTTP) -> void } -> void
33
+ end
34
+ end
@@ -1,5 +1,11 @@
1
1
  module OpenAI
2
2
  module Providers
3
+ def self.azure: (
4
+ ?endpoint: String?,
5
+ ?api_key: String?,
6
+ ?token_provider: (^-> String)?
7
+ ) -> OpenAI::Provider
8
+
3
9
  def self.bedrock: (
4
10
  ?region: String?,
5
11
  ?base_url: String?,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.77.1
4
+ version: 0.79.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenAI
@@ -39,6 +39,20 @@ dependencies:
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: connection_pool
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.2.3
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.3
54
+ - !ruby/object:Gem::Dependency
55
+ name: logger
42
56
  requirement: !ruby/object:Gem::Requirement
43
57
  requirements:
44
58
  - - ">="
@@ -57,12 +71,17 @@ extensions: []
57
71
  extra_rdoc_files:
58
72
  - README.md
59
73
  - VERSIONING.md
74
+ - azure.md
75
+ - bedrock.md
60
76
  files:
61
77
  - ".ignore"
62
78
  - CHANGELOG.md
63
79
  - README.md
64
80
  - SECURITY.md
65
81
  - VERSIONING.md
82
+ - azure.md
83
+ - bedrock.md
84
+ - examples/mtls_custom_http_client.rb
66
85
  - lib/openai.rb
67
86
  - lib/openai/auth/subject_token_provider.rb
68
87
  - lib/openai/auth/subject_token_providers/azure_managed_identity_token_provider.rb
@@ -87,15 +106,17 @@ files:
87
106
  - lib/openai/helpers/structured_output/json_schema_converter.rb
88
107
  - lib/openai/helpers/structured_output/parsed_json.rb
89
108
  - lib/openai/helpers/structured_output/union_of.rb
109
+ - lib/openai/http_client.rb
90
110
  - lib/openai/internal.rb
91
111
  - lib/openai/internal/conversation_cursor_page.rb
92
112
  - lib/openai/internal/cursor_page.rb
113
+ - lib/openai/internal/logging.rb
93
114
  - lib/openai/internal/next_cursor_page.rb
94
115
  - lib/openai/internal/page.rb
95
116
  - lib/openai/internal/provider.rb
117
+ - lib/openai/internal/read_io_adapter.rb
96
118
  - lib/openai/internal/stream.rb
97
119
  - lib/openai/internal/transport/base_client.rb
98
- - lib/openai/internal/transport/pooled_net_requester.rb
99
120
  - lib/openai/internal/type/array_of.rb
100
121
  - lib/openai/internal/type/base_model.rb
101
122
  - lib/openai/internal/type/base_page.rb
@@ -1196,7 +1217,9 @@ files:
1196
1217
  - lib/openai/models/webhooks/response_incomplete_webhook_event.rb
1197
1218
  - lib/openai/models/webhooks/unwrap_webhook_event.rb
1198
1219
  - lib/openai/models/webhooks/webhook_unwrap_params.rb
1220
+ - lib/openai/net_http_client.rb
1199
1221
  - lib/openai/provider.rb
1222
+ - lib/openai/providers/azure.rb
1200
1223
  - lib/openai/providers/bedrock.rb
1201
1224
  - lib/openai/request_options.rb
1202
1225
  - lib/openai/resources/admin.rb
@@ -1310,15 +1333,17 @@ files:
1310
1333
  - rbi/openai/helpers/structured_output/enum_of.rbi
1311
1334
  - rbi/openai/helpers/structured_output/json_schema_converter.rbi
1312
1335
  - rbi/openai/helpers/structured_output/union_of.rbi
1336
+ - rbi/openai/http_client.rbi
1313
1337
  - rbi/openai/internal.rbi
1314
1338
  - rbi/openai/internal/conversation_cursor_page.rbi
1315
1339
  - rbi/openai/internal/cursor_page.rbi
1340
+ - rbi/openai/internal/logging.rbi
1316
1341
  - rbi/openai/internal/next_cursor_page.rbi
1317
1342
  - rbi/openai/internal/page.rbi
1318
1343
  - rbi/openai/internal/provider.rbi
1344
+ - rbi/openai/internal/read_io_adapter.rbi
1319
1345
  - rbi/openai/internal/stream.rbi
1320
1346
  - rbi/openai/internal/transport/base_client.rbi
1321
- - rbi/openai/internal/transport/pooled_net_requester.rbi
1322
1347
  - rbi/openai/internal/type/array_of.rbi
1323
1348
  - rbi/openai/internal/type/base_model.rbi
1324
1349
  - rbi/openai/internal/type/base_page.rbi
@@ -2418,6 +2443,7 @@ files:
2418
2443
  - rbi/openai/models/webhooks/response_incomplete_webhook_event.rbi
2419
2444
  - rbi/openai/models/webhooks/unwrap_webhook_event.rbi
2420
2445
  - rbi/openai/models/webhooks/webhook_unwrap_params.rbi
2446
+ - rbi/openai/net_http_client.rbi
2421
2447
  - rbi/openai/provider.rbi
2422
2448
  - rbi/openai/providers.rbi
2423
2449
  - rbi/openai/request_options.rbi
@@ -2521,15 +2547,17 @@ files:
2521
2547
  - sig/openai/client.rbs
2522
2548
  - sig/openai/errors.rbs
2523
2549
  - sig/openai/file_part.rbs
2550
+ - sig/openai/http_client.rbs
2524
2551
  - sig/openai/internal.rbs
2525
2552
  - sig/openai/internal/conversation_cursor_page.rbs
2526
2553
  - sig/openai/internal/cursor_page.rbs
2554
+ - sig/openai/internal/logging.rbs
2527
2555
  - sig/openai/internal/next_cursor_page.rbs
2528
2556
  - sig/openai/internal/page.rbs
2529
2557
  - sig/openai/internal/provider.rbs
2558
+ - sig/openai/internal/read_io_adapter.rbs
2530
2559
  - sig/openai/internal/stream.rbs
2531
2560
  - sig/openai/internal/transport/base_client.rbs
2532
- - sig/openai/internal/transport/pooled_net_requester.rbs
2533
2561
  - sig/openai/internal/type/array_of.rbs
2534
2562
  - sig/openai/internal/type/base_model.rbs
2535
2563
  - sig/openai/internal/type/base_page.rbs
@@ -3629,6 +3657,7 @@ files:
3629
3657
  - sig/openai/models/webhooks/response_incomplete_webhook_event.rbs
3630
3658
  - sig/openai/models/webhooks/unwrap_webhook_event.rbs
3631
3659
  - sig/openai/models/webhooks/webhook_unwrap_params.rbs
3660
+ - sig/openai/net_http_client.rbs
3632
3661
  - sig/openai/provider.rbs
3633
3662
  - sig/openai/providers.rbs
3634
3663
  - sig/openai/request_options.rbs
@@ -1,210 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenAI
4
- module Internal
5
- module Transport
6
- # @api private
7
- class PooledNetRequester
8
- extend OpenAI::Internal::Util::SorbetRuntimeSupport
9
-
10
- # from the golang stdlib
11
- # https://github.com/golang/go/blob/c8eced8580028328fde7c03cbfcb720ce15b2358/src/net/http/transport.go#L49
12
- KEEP_ALIVE_TIMEOUT = 30
13
-
14
- DEFAULT_MAX_CONNECTIONS = [Etc.nprocessors, 99].max
15
-
16
- class << self
17
- # @api private
18
- #
19
- # @param cert_store [OpenSSL::X509::Store]
20
- # @param url [URI::Generic]
21
- #
22
- # @return [Net::HTTP]
23
- def connect(cert_store:, url:)
24
- port =
25
- case [url.port, url.scheme]
26
- in [Integer, _]
27
- url.port
28
- in [nil, "http" | "ws"]
29
- Net::HTTP.http_default_port
30
- in [nil, "https" | "wss"]
31
- Net::HTTP.https_default_port
32
- end
33
-
34
- Net::HTTP.new(url.host, port).tap do
35
- _1.use_ssl = %w[https wss].include?(url.scheme)
36
- _1.max_retries = 0
37
-
38
- (_1.cert_store = cert_store) if _1.use_ssl?
39
- end
40
- end
41
-
42
- # @api private
43
- #
44
- # @param conn [Net::HTTP]
45
- # @param deadline [Float]
46
- def calibrate_socket_timeout(conn, deadline)
47
- timeout = deadline - OpenAI::Internal::Util.monotonic_secs
48
- conn.open_timeout = conn.read_timeout = conn.write_timeout = conn.continue_timeout = timeout
49
- end
50
-
51
- # @api private
52
- #
53
- # @param request [Hash{Symbol=>Object}] .
54
- #
55
- # @option request [Symbol] :method
56
- #
57
- # @option request [URI::Generic] :url
58
- #
59
- # @option request [Hash{String=>String}] :headers
60
- #
61
- # @param blk [Proc]
62
- #
63
- # @yieldparam [String]
64
- # @return [Array(Net::HTTPGenericRequest, Proc)]
65
- def build_request(request, &blk)
66
- method, url, headers, body = request.fetch_values(:method, :url, :headers, :body)
67
- req = Net::HTTPGenericRequest.new(
68
- method.to_s.upcase,
69
- !body.nil?,
70
- method != :head,
71
- URI(url.to_s) # ensure we construct a URI class of the right scheme
72
- )
73
-
74
- headers.each { req[_1] = _2 }
75
-
76
- case body
77
- in nil
78
- req["content-length"] ||= 0 unless req["transfer-encoding"]
79
- in String
80
- req["content-length"] ||= body.bytesize.to_s unless req["transfer-encoding"]
81
- req.body_stream = OpenAI::Internal::Util::ReadIOAdapter.new(body, &blk)
82
- in StringIO
83
- req["content-length"] ||= body.size.to_s unless req["transfer-encoding"]
84
- req.body_stream = OpenAI::Internal::Util::ReadIOAdapter.new(body, &blk)
85
- in Pathname | IO | Enumerator
86
- req["transfer-encoding"] ||= "chunked" unless req["content-length"]
87
- req.body_stream = OpenAI::Internal::Util::ReadIOAdapter.new(body, &blk)
88
- end
89
-
90
- [req, req.body_stream&.method(:close)]
91
- end
92
- end
93
-
94
- # @api private
95
- #
96
- # @param url [URI::Generic]
97
- # @param deadline [Float]
98
- # @param blk [Proc]
99
- #
100
- # @raise [Timeout::Error]
101
- # @yieldparam [Net::HTTP]
102
- private def with_pool(url, deadline:, &blk)
103
- origin = OpenAI::Internal::Util.uri_origin(url)
104
- timeout = deadline - OpenAI::Internal::Util.monotonic_secs
105
- pool =
106
- @mutex.synchronize do
107
- @pools[origin] ||= ConnectionPool.new(size: @size) do
108
- self.class.connect(cert_store: @cert_store, url: url)
109
- end
110
- end
111
-
112
- pool.with(timeout: timeout, &blk)
113
- end
114
-
115
- # @api private
116
- #
117
- # @param request [Hash{Symbol=>Object}] .
118
- #
119
- # @option request [Symbol] :method
120
- #
121
- # @option request [URI::Generic] :url
122
- #
123
- # @option request [Hash{String=>String}] :headers
124
- #
125
- # @option request [Object] :body
126
- #
127
- # @option request [Float] :deadline
128
- #
129
- # @return [Array(Integer, Net::HTTPResponse, Enumerable<String>)]
130
- def execute(request)
131
- url, deadline = request.fetch_values(:url, :deadline)
132
-
133
- req = nil
134
- finished = false
135
-
136
- # rubocop:disable Metrics/BlockLength
137
- enum = Enumerator.new do |y|
138
- next if finished
139
-
140
- with_pool(url, deadline: deadline) do |conn|
141
- eof = false
142
- closing = nil
143
- ::Thread.handle_interrupt(Object => :never) do
144
- ::Thread.handle_interrupt(Object => :immediate) do
145
- req, closing = self.class.build_request(request) do
146
- self.class.calibrate_socket_timeout(conn, deadline)
147
- end
148
-
149
- self.class.calibrate_socket_timeout(conn, deadline)
150
- unless conn.started?
151
- conn.keep_alive_timeout = self.class::KEEP_ALIVE_TIMEOUT
152
- conn.start
153
- end
154
-
155
- self.class.calibrate_socket_timeout(conn, deadline)
156
- ::Kernel.catch(:jump) do
157
- conn.request(req) do |rsp|
158
- y << [req, rsp]
159
- ::Kernel.throw(:jump) if finished
160
-
161
- rsp.read_body do |bytes|
162
- y << bytes.force_encoding(Encoding::BINARY)
163
- ::Kernel.throw(:jump) if finished
164
-
165
- self.class.calibrate_socket_timeout(conn, deadline)
166
- end
167
- eof = true
168
- end
169
- end
170
- end
171
- ensure
172
- begin
173
- conn.finish if !eof && conn&.started?
174
- ensure
175
- closing&.call
176
- end
177
- end
178
- end
179
- rescue Timeout::Error
180
- raise OpenAI::Errors::APITimeoutError.new(url: url, request: req)
181
- rescue StandardError
182
- raise OpenAI::Errors::APIConnectionError.new(url: url, request: req)
183
- end
184
- # rubocop:enable Metrics/BlockLength
185
-
186
- _, response = enum.next
187
- body = OpenAI::Internal::Util.fused_enum(enum, external: true) do
188
- finished = true
189
- loop { enum.next }
190
- end
191
- [Integer(response.code), response, body]
192
- end
193
-
194
- # @api private
195
- #
196
- # @param size [Integer]
197
- def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
198
- @mutex = Mutex.new
199
- @size = size
200
- @cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths)
201
- @pools = {}
202
- end
203
-
204
- define_sorbet_constant!(:Request) do
205
- T.type_alias { {method: Symbol, url: URI::Generic, headers: T::Hash[String, String], body: T.anything, deadline: Float} }
206
- end
207
- end
208
- end
209
- end
210
- end
@@ -1,82 +0,0 @@
1
- # typed: strong
2
-
3
- module OpenAI
4
- module Internal
5
- module Transport
6
- # @api private
7
- class PooledNetRequester
8
- extend OpenAI::Internal::Util::SorbetRuntimeSupport
9
-
10
- Request =
11
- T.type_alias do
12
- {
13
- method: Symbol,
14
- url: URI::Generic,
15
- headers: T::Hash[String, String],
16
- body: T.anything,
17
- deadline: Float
18
- }
19
- end
20
-
21
- # from the golang stdlib
22
- # https://github.com/golang/go/blob/c8eced8580028328fde7c03cbfcb720ce15b2358/src/net/http/transport.go#L49
23
- KEEP_ALIVE_TIMEOUT = 30
24
-
25
- DEFAULT_MAX_CONNECTIONS = T.let(T.unsafe(nil), Integer)
26
-
27
- class << self
28
- # @api private
29
- sig do
30
- params(cert_store: OpenSSL::X509::Store, url: URI::Generic).returns(
31
- Net::HTTP
32
- )
33
- end
34
- def connect(cert_store:, url:)
35
- end
36
-
37
- # @api private
38
- sig { params(conn: Net::HTTP, deadline: Float).void }
39
- def calibrate_socket_timeout(conn, deadline)
40
- end
41
-
42
- # @api private
43
- sig do
44
- params(
45
- request: OpenAI::Internal::Transport::PooledNetRequester::Request,
46
- blk: T.proc.params(arg0: String).void
47
- ).returns([Net::HTTPGenericRequest, T.proc.void])
48
- end
49
- def build_request(request, &blk)
50
- end
51
- end
52
-
53
- # @api private
54
- sig do
55
- params(
56
- url: URI::Generic,
57
- deadline: Float,
58
- blk: T.proc.params(arg0: Net::HTTP).void
59
- ).void
60
- end
61
- private def with_pool(url, deadline:, &blk)
62
- end
63
-
64
- # @api private
65
- sig do
66
- params(
67
- request: OpenAI::Internal::Transport::PooledNetRequester::Request
68
- ).returns([Integer, Net::HTTPResponse, T::Enumerable[String]])
69
- end
70
- def execute(request)
71
- end
72
-
73
- # @api private
74
- sig { params(size: Integer).returns(T.attached_class) }
75
- def self.new(
76
- size: OpenAI::Internal::Transport::PooledNetRequester::DEFAULT_MAX_CONNECTIONS
77
- )
78
- end
79
- end
80
- end
81
- end
82
- end
@@ -1,48 +0,0 @@
1
- module OpenAI
2
- module Internal
3
- module Transport
4
- class PooledNetRequester
5
- extend OpenAI::Internal::Util::SorbetRuntimeSupport
6
-
7
- type request =
8
- {
9
- method: Symbol,
10
- url: URI::Generic,
11
- headers: ::Hash[String, String],
12
- body: top,
13
- deadline: Float
14
- }
15
-
16
- KEEP_ALIVE_TIMEOUT: 30
17
-
18
- DEFAULT_MAX_CONNECTIONS: Integer
19
-
20
- def self.connect: (
21
- cert_store: OpenSSL::X509::Store,
22
- url: URI::Generic
23
- ) -> top
24
-
25
- def self.calibrate_socket_timeout: (top conn, Float deadline) -> void
26
-
27
- def self.build_request: (
28
- OpenAI::Internal::Transport::PooledNetRequester::request request
29
- ) {
30
- (String arg0) -> void
31
- } -> [top, (^-> void)]
32
-
33
- private def with_pool: (
34
- URI::Generic url,
35
- deadline: Float
36
- ) {
37
- (top arg0) -> void
38
- } -> void
39
-
40
- def execute: (
41
- OpenAI::Internal::Transport::PooledNetRequester::request request
42
- ) -> [Integer, top, Enumerable[String]]
43
-
44
- def initialize: (?size: Integer) -> void
45
- end
46
- end
47
- end
48
- end