openai 0.78.0 → 0.80.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +99 -0
- data/README.md +241 -8
- data/SECURITY.md +6 -22
- data/azure.md +110 -0
- data/bedrock.md +197 -0
- data/examples/mtls_custom_http_client.rb +61 -0
- data/lib/openai/auth/workload_identity.rb +13 -2
- data/lib/openai/auth/workload_identity_auth.rb +2 -1
- data/lib/openai/client.rb +29 -6
- data/lib/openai/errors.rb +11 -1
- data/lib/openai/helpers/streaming/chat_completion_stream.rb +3 -3
- data/lib/openai/helpers/streaming/response_stream.rb +5 -6
- data/lib/openai/helpers/structured_output/base_model.rb +20 -19
- data/lib/openai/helpers/structured_output/json_schema_converter.rb +12 -5
- data/lib/openai/http_client.rb +99 -7
- data/lib/openai/internal/conversation_cursor_page.rb +5 -6
- data/lib/openai/internal/cursor_page.rb +3 -3
- data/lib/openai/internal/logging.rb +419 -0
- data/lib/openai/internal/next_cursor_page.rb +5 -6
- data/lib/openai/internal/page.rb +2 -2
- data/lib/openai/internal/provider.rb +7 -1
- data/lib/openai/internal/read_io_adapter.rb +42 -18
- data/lib/openai/internal/stream.rb +2 -2
- data/lib/openai/internal/transport/base_client.rb +137 -37
- data/lib/openai/internal/type/array_of.rb +6 -4
- data/lib/openai/internal/type/base_model.rb +39 -1
- data/lib/openai/internal/type/base_page.rb +19 -2
- data/lib/openai/internal/type/base_stream.rb +39 -7
- data/lib/openai/internal/type/hash_of.rb +3 -3
- data/lib/openai/internal/util.rb +52 -27
- data/lib/openai/models/admin/organization/audit_log_list_params.rb +3 -1
- data/lib/openai/models/admin/organization/audit_log_list_response.rb +33 -11
- data/lib/openai/models/admin/organization/groups/role_list_response.rb +5 -1
- data/lib/openai/models/admin/organization/groups/role_retrieve_response.rb +5 -1
- data/lib/openai/models/admin/organization/projects/groups/role_list_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/groups/role_retrieve_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/service_account_create_response.rb +3 -1
- data/lib/openai/models/admin/organization/projects/users/role_list_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/users/role_retrieve_response.rb +6 -1
- data/lib/openai/models/admin/organization/users/role_list_response.rb +5 -1
- data/lib/openai/models/admin/organization/users/role_retrieve_response.rb +5 -1
- data/lib/openai/models/all_models.rb +5 -0
- data/lib/openai/models/audio/transcription_create_params.rb +7 -1
- data/lib/openai/models/audio/translation_create_params.rb +7 -1
- data/lib/openai/models/beta/beta_mcp_tool_call_error.rb +84 -0
- data/lib/openai/models/beta/beta_response.rb +27 -0
- data/lib/openai/models/beta/beta_response_input_item.rb +3 -3
- data/lib/openai/models/beta/beta_response_item.rb +3 -3
- data/lib/openai/models/beta/beta_response_output_item.rb +3 -3
- data/lib/openai/models/beta/beta_response_output_item_added_event.rb +5 -2
- data/lib/openai/models/beta/beta_response_output_text_annotation_added_event.rb +201 -4
- data/lib/openai/models/beta/beta_response_reasoning_item.rb +5 -0
- data/lib/openai/models/beta/beta_response_stream_event.rb +1 -1
- data/lib/openai/models/beta/beta_responses_client_event.rb +46 -3
- data/lib/openai/models/beta/beta_responses_server_event.rb +1143 -63
- data/lib/openai/models/beta/beta_web_search_tool.rb +11 -1
- data/lib/openai/models/beta/response_compact_params.rb +18 -0
- data/lib/openai/models/beta/response_create_params.rb +27 -0
- data/lib/openai/models/chat_model.rb +1 -0
- data/lib/openai/models/completion_usage.rb +26 -2
- data/lib/openai/models/containers/file_create_params.rb +4 -0
- data/lib/openai/models/content_provenance_check_create_params.rb +4 -0
- data/lib/openai/models/conversations/conversation_item.rb +3 -3
- data/lib/openai/models/file_create_params.rb +4 -0
- data/lib/openai/models/image_create_variation_params.rb +4 -0
- data/lib/openai/models/image_edit_params.rb +8 -0
- data/lib/openai/models/model.rb +9 -1
- data/lib/openai/models/responses/mcp_tool_call_error.rb +82 -0
- data/lib/openai/models/responses/response.rb +9 -0
- data/lib/openai/models/responses/response_compact_params.rb +18 -0
- data/lib/openai/models/responses/response_create_params.rb +9 -0
- data/lib/openai/models/responses/response_input_item.rb +3 -3
- data/lib/openai/models/responses/response_item.rb +3 -3
- data/lib/openai/models/responses/response_output_item.rb +3 -3
- data/lib/openai/models/responses/response_output_item_added_event.rb +5 -2
- data/lib/openai/models/responses/response_output_text_annotation_added_event.rb +201 -4
- data/lib/openai/models/responses/response_reasoning_item.rb +5 -0
- data/lib/openai/models/responses/response_stream_event.rb +1 -1
- data/lib/openai/models/responses/responses_client_event.rb +22 -1
- data/lib/openai/models/responses/responses_server_event.rb +1107 -56
- data/lib/openai/models/responses/web_search_tool.rb +11 -1
- data/lib/openai/models/responses_model.rb +5 -0
- data/lib/openai/models/skill_create_params.rb +4 -0
- data/lib/openai/models/skills/version_create_params.rb +4 -0
- data/lib/openai/models/uploads/part_create_params.rb +4 -0
- data/lib/openai/models/vector_store_search_response.rb +3 -1
- data/lib/openai/models/video_create_character_params.rb +4 -0
- data/lib/openai/models/video_create_params.rb +4 -0
- data/lib/openai/models/video_edit_params.rb +4 -0
- data/lib/openai/models/video_extend_params.rb +4 -0
- data/lib/openai/models.rb +9 -1
- data/lib/openai/net_http_client.rb +20 -6
- data/lib/openai/providers/azure.rb +216 -0
- data/lib/openai/providers/bedrock.rb +130 -17
- data/lib/openai/resources/admin/organization/projects/groups/roles.rb +1 -1
- data/lib/openai/resources/admin/organization/projects/groups.rb +1 -1
- data/lib/openai/resources/admin/organization/projects/users/roles.rb +1 -1
- data/lib/openai/resources/admin/organization/projects.rb +4 -2
- data/lib/openai/resources/audio/transcriptions.rb +8 -0
- data/lib/openai/resources/audio/translations.rb +4 -0
- data/lib/openai/resources/beta/responses.rb +1 -1
- data/lib/openai/resources/beta/threads/runs/steps.rb +2 -2
- data/lib/openai/resources/containers/files.rb +4 -0
- data/lib/openai/resources/content_provenance_checks.rb +4 -0
- data/lib/openai/resources/conversations/items.rb +1 -1
- data/lib/openai/resources/evals/runs/output_items.rb +1 -1
- data/lib/openai/resources/files.rb +5 -1
- data/lib/openai/resources/images.rb +12 -0
- data/lib/openai/resources/responses.rb +3 -2
- data/lib/openai/resources/skills/versions.rb +4 -0
- data/lib/openai/resources/skills.rb +4 -0
- data/lib/openai/resources/uploads/parts.rb +4 -0
- data/lib/openai/resources/vector_stores/file_batches.rb +1 -1
- data/lib/openai/resources/videos.rb +38 -0
- data/lib/openai/resources/webhooks.rb +18 -6
- data/lib/openai/version.rb +1 -1
- data/lib/openai.rb +111 -105
- data/rbi/openai/auth.rbi +4 -4
- data/rbi/openai/client.rbi +13 -3
- data/rbi/openai/errors.rbi +7 -0
- data/rbi/openai/helpers/streaming/events.rbi +12 -0
- data/rbi/openai/http_client.rbi +62 -2
- data/rbi/openai/internal/logging.rbi +192 -0
- data/rbi/openai/internal/provider.rbi +3 -0
- data/rbi/openai/internal/read_io_adapter.rbi +6 -1
- data/rbi/openai/internal/transport/base_client.rbi +61 -7
- data/rbi/openai/internal/type/base_model.rbi +24 -1
- data/rbi/openai/internal/type/base_page.rbi +13 -2
- data/rbi/openai/internal/type/base_stream.rbi +15 -4
- data/rbi/openai/internal/util.rbi +26 -2
- data/rbi/openai/models/admin/organization/audit_log_list_params.rbi +5 -0
- data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +5 -0
- data/rbi/openai/models/all_models.rbi +25 -0
- data/rbi/openai/models/audio/transcription_create_params.rbi +14 -2
- data/rbi/openai/models/audio/translation_create_params.rbi +14 -2
- data/rbi/openai/models/beta/beta_mcp_tool_call_error.rbi +122 -0
- data/rbi/openai/models/beta/beta_response.rbi +47 -0
- data/rbi/openai/models/beta/beta_response_input_item.rbi +27 -3
- data/rbi/openai/models/beta/beta_response_item.rbi +27 -3
- data/rbi/openai/models/beta/beta_response_output_item.rbi +27 -3
- data/rbi/openai/models/beta/beta_response_output_item_added_event.rbi +8 -2
- data/rbi/openai/models/beta/beta_response_output_text_annotation_added_event.rbi +297 -5
- data/rbi/openai/models/beta/beta_response_reasoning_item.rbi +10 -0
- data/rbi/openai/models/beta/beta_response_stream_event.rbi +1 -1
- data/rbi/openai/models/beta/beta_responses_client_event.rbi +69 -1
- data/rbi/openai/models/beta/beta_responses_server_event.rbi +3945 -54
- data/rbi/openai/models/beta/beta_web_search_tool.rbi +15 -0
- data/rbi/openai/models/beta/response_compact_params.rbi +30 -0
- data/rbi/openai/models/beta/response_create_params.rbi +47 -0
- data/rbi/openai/models/chat_model.rbi +2 -0
- data/rbi/openai/models/completion_usage.rbi +39 -6
- data/rbi/openai/models/containers/file_create_params.rbi +8 -0
- data/rbi/openai/models/content_provenance_check_create_params.rbi +8 -0
- data/rbi/openai/models/conversations/conversation_item.rbi +12 -3
- data/rbi/openai/models/file_create_params.rbi +8 -0
- data/rbi/openai/models/image_create_variation_params.rbi +8 -0
- data/rbi/openai/models/image_edit_params.rbi +16 -0
- data/rbi/openai/models/model.rbi +14 -1
- data/rbi/openai/models/responses/mcp_tool_call_error.rbi +120 -0
- data/rbi/openai/models/responses/response.rbi +17 -0
- data/rbi/openai/models/responses/response_compact_params.rbi +30 -0
- data/rbi/openai/models/responses/response_create_params.rbi +17 -0
- data/rbi/openai/models/responses/response_input_item.rbi +27 -3
- data/rbi/openai/models/responses/response_item.rbi +27 -3
- data/rbi/openai/models/responses/response_output_item.rbi +27 -3
- data/rbi/openai/models/responses/response_output_item_added_event.rbi +8 -2
- data/rbi/openai/models/responses/response_output_text_annotation_added_event.rbi +297 -5
- data/rbi/openai/models/responses/response_reasoning_item.rbi +10 -0
- data/rbi/openai/models/responses/response_stream_event.rbi +1 -1
- data/rbi/openai/models/responses/responses_client_event.rbi +36 -0
- data/rbi/openai/models/responses/responses_server_event.rbi +3385 -53
- data/rbi/openai/models/responses/web_search_tool.rbi +15 -0
- data/rbi/openai/models/responses_model.rbi +25 -0
- data/rbi/openai/models/skill_create_params.rbi +8 -0
- data/rbi/openai/models/skills/version_create_params.rbi +8 -0
- data/rbi/openai/models/uploads/part_create_params.rbi +8 -0
- data/rbi/openai/models/video_create_character_params.rbi +8 -0
- data/rbi/openai/models/video_create_params.rbi +8 -0
- data/rbi/openai/models/video_edit_params.rbi +8 -0
- data/rbi/openai/models/video_extend_params.rbi +8 -0
- data/rbi/openai/net_http_client.rbi +2 -2
- data/rbi/openai/providers.rbi +11 -0
- data/rbi/openai/resources/audio/transcriptions.rbi +14 -2
- data/rbi/openai/resources/audio/translations.rbi +7 -1
- data/rbi/openai/resources/beta/responses.rbi +8 -0
- data/rbi/openai/resources/containers/files.rbi +4 -0
- data/rbi/openai/resources/content_provenance_checks.rbi +4 -0
- data/rbi/openai/resources/files.rbi +5 -1
- data/rbi/openai/resources/images.rbi +20 -0
- data/rbi/openai/resources/responses.rbi +8 -0
- data/rbi/openai/resources/skills/versions.rbi +4 -0
- data/rbi/openai/resources/skills.rbi +4 -0
- data/rbi/openai/resources/uploads/parts.rbi +4 -0
- data/rbi/openai/resources/videos.rbi +16 -0
- data/sig/openai/client.rbs +6 -2
- data/sig/openai/errors.rbs +5 -0
- data/sig/openai/http_client.rbs +37 -2
- data/sig/openai/internal/logging.rbs +88 -0
- data/sig/openai/internal/provider.rbs +3 -1
- data/sig/openai/internal/read_io_adapter.rbs +3 -1
- data/sig/openai/internal/transport/base_client.rbs +33 -5
- data/sig/openai/internal/type/base_model.rbs +13 -0
- data/sig/openai/internal/type/base_page.rbs +8 -1
- data/sig/openai/internal/type/base_stream.rbs +8 -2
- data/sig/openai/internal/util.rbs +12 -0
- data/sig/openai/models/admin/organization/audit_log_list_params.rbs +2 -0
- data/sig/openai/models/admin/organization/audit_log_list_response.rbs +2 -0
- data/sig/openai/models/all_models.rbs +10 -0
- data/sig/openai/models/beta/beta_mcp_tool_call_error.rbs +75 -0
- data/sig/openai/models/beta/beta_response.rbs +14 -1
- data/sig/openai/models/beta/beta_response_input_item.rbs +4 -4
- data/sig/openai/models/beta/beta_response_item.rbs +4 -4
- data/sig/openai/models/beta/beta_response_output_item.rbs +4 -4
- data/sig/openai/models/beta/beta_response_output_text_annotation_added_event.rbs +149 -4
- data/sig/openai/models/beta/beta_responses_client_event.rbs +21 -1
- data/sig/openai/models/beta/beta_responses_server_event.rbs +2005 -53
- data/sig/openai/models/beta/beta_web_search_tool.rbs +7 -0
- data/sig/openai/models/beta/response_compact_params.rbs +12 -0
- data/sig/openai/models/beta/response_create_params.rbs +14 -1
- data/sig/openai/models/chat_model.rbs +2 -0
- data/sig/openai/models/completion_usage.rbs +27 -6
- data/sig/openai/models/conversations/conversation_item.rbs +4 -4
- data/sig/openai/models/model.rbs +12 -2
- data/sig/openai/models/responses/mcp_tool_call_error.rbs +73 -0
- data/sig/openai/models/responses/response.rbs +2 -1
- data/sig/openai/models/responses/response_compact_params.rbs +12 -0
- data/sig/openai/models/responses/response_create_params.rbs +2 -1
- data/sig/openai/models/responses/response_input_item.rbs +4 -4
- data/sig/openai/models/responses/response_item.rbs +4 -4
- data/sig/openai/models/responses/response_output_item.rbs +4 -4
- data/sig/openai/models/responses/response_output_text_annotation_added_event.rbs +149 -4
- data/sig/openai/models/responses/responses_client_event.rbs +9 -1
- data/sig/openai/models/responses/responses_server_event.rbs +1834 -53
- data/sig/openai/models/responses/web_search_tool.rbs +7 -0
- data/sig/openai/models/responses_model.rbs +10 -0
- data/sig/openai/net_http_client.rbs +2 -2
- data/sig/openai/providers.rbs +7 -0
- metadata +30 -1
|
@@ -10,6 +10,14 @@ module OpenAI
|
|
|
10
10
|
# @return [Symbol, OpenAI::Models::Responses::WebSearchTool::Type]
|
|
11
11
|
required :type, enum: -> { OpenAI::Responses::WebSearchTool::Type }
|
|
12
12
|
|
|
13
|
+
# @!attribute external_web_access
|
|
14
|
+
# Allow live internet access for web search. Defaults to true when omitted. When
|
|
15
|
+
# false, the web search tool runs in offline/cache-only mode and will not fetch
|
|
16
|
+
# new external content.
|
|
17
|
+
#
|
|
18
|
+
# @return [Boolean, nil]
|
|
19
|
+
optional :external_web_access, OpenAI::Internal::Type::Boolean
|
|
20
|
+
|
|
13
21
|
# @!attribute filters
|
|
14
22
|
# Filters for the search.
|
|
15
23
|
#
|
|
@@ -29,7 +37,7 @@ module OpenAI
|
|
|
29
37
|
# @return [OpenAI::Models::Responses::WebSearchTool::UserLocation, nil]
|
|
30
38
|
optional :user_location, -> { OpenAI::Responses::WebSearchTool::UserLocation }, nil?: true
|
|
31
39
|
|
|
32
|
-
# @!method initialize(type:, filters: nil, search_context_size: nil, user_location: nil)
|
|
40
|
+
# @!method initialize(type:, external_web_access: nil, filters: nil, search_context_size: nil, user_location: nil)
|
|
33
41
|
# Some parameter documentations has been truncated, see
|
|
34
42
|
# {OpenAI::Models::Responses::WebSearchTool} for more details.
|
|
35
43
|
#
|
|
@@ -38,6 +46,8 @@ module OpenAI
|
|
|
38
46
|
#
|
|
39
47
|
# @param type [Symbol, OpenAI::Models::Responses::WebSearchTool::Type] The type of the web search tool. One of `web_search` or `web_search_2025_08_26`.
|
|
40
48
|
#
|
|
49
|
+
# @param external_web_access [Boolean] Allow live internet access for web search. Defaults to true when omitted. When f
|
|
50
|
+
#
|
|
41
51
|
# @param filters [OpenAI::Models::Responses::WebSearchTool::Filters, nil] Filters for the search.
|
|
42
52
|
#
|
|
43
53
|
# @param search_context_size [Symbol, OpenAI::Models::Responses::WebSearchTool::SearchContextSize] High level guidance for the amount of context window space to use for the search
|
|
@@ -24,10 +24,15 @@ module OpenAI
|
|
|
24
24
|
O4_MINI_DEEP_RESEARCH_2025_06_26 = :"o4-mini-deep-research-2025-06-26"
|
|
25
25
|
COMPUTER_USE_PREVIEW = :"computer-use-preview"
|
|
26
26
|
COMPUTER_USE_PREVIEW_2025_03_11 = :"computer-use-preview-2025-03-11"
|
|
27
|
+
GPT_5_5_PRO = :"gpt-5.5-pro"
|
|
28
|
+
GPT_5_5_PRO_2026_04_23 = :"gpt-5.5-pro-2026-04-23"
|
|
27
29
|
GPT_5_CODEX = :"gpt-5-codex"
|
|
28
30
|
GPT_5_PRO = :"gpt-5-pro"
|
|
29
31
|
GPT_5_PRO_2025_10_06 = :"gpt-5-pro-2025-10-06"
|
|
30
32
|
GPT_5_1_CODEX_MAX = :"gpt-5.1-codex-max"
|
|
33
|
+
GPT_DAYBREAK_BLUE_LATEST = :"gpt-daybreak-blue-latest"
|
|
34
|
+
GPT_DAYBREAK_RED_LATEST = :"gpt-daybreak-red-latest"
|
|
35
|
+
GPT_5_6_CYBER = :"gpt-5.6-cyber"
|
|
31
36
|
|
|
32
37
|
# @!method self.values
|
|
33
38
|
# @return [Array<Symbol>]
|
|
@@ -10,6 +10,10 @@ module OpenAI
|
|
|
10
10
|
# @!attribute files
|
|
11
11
|
# Skill files to upload (directory upload) or a single zip file.
|
|
12
12
|
#
|
|
13
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
14
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
15
|
+
# content type.
|
|
16
|
+
#
|
|
13
17
|
# @return [Array<Pathname, StringIO, IO, String, OpenAI::FilePart>, Pathname, StringIO, IO, String, OpenAI::FilePart, nil]
|
|
14
18
|
optional :files, union: -> { OpenAI::SkillCreateParams::Files }
|
|
15
19
|
|
|
@@ -22,6 +22,10 @@ module OpenAI
|
|
|
22
22
|
# @!attribute files
|
|
23
23
|
# Skill files to upload (directory upload) or a single zip file.
|
|
24
24
|
#
|
|
25
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
26
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
27
|
+
# content type.
|
|
28
|
+
#
|
|
25
29
|
# @return [Array<Pathname, StringIO, IO, String, OpenAI::FilePart>, Pathname, StringIO, IO, String, OpenAI::FilePart, nil]
|
|
26
30
|
optional :files, union: -> { OpenAI::Skills::VersionCreateParams::Files }
|
|
27
31
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute data
|
|
17
17
|
# The chunk of bytes for this Part.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart]
|
|
20
24
|
required :data, OpenAI::Internal::Type::FileInput
|
|
21
25
|
|
|
@@ -13,7 +13,9 @@ module OpenAI
|
|
|
13
13
|
#
|
|
14
14
|
# @return [Hash{Symbol=>String, Float, Boolean}, nil]
|
|
15
15
|
required :attributes,
|
|
16
|
-
-> {
|
|
16
|
+
-> {
|
|
17
|
+
OpenAI::Internal::Type::HashOf[union: OpenAI::Models::VectorStoreSearchResponse::Attribute]
|
|
18
|
+
},
|
|
17
19
|
nil?: true
|
|
18
20
|
|
|
19
21
|
# @!attribute content
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute video
|
|
17
17
|
# Video file used to create a character.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart]
|
|
20
24
|
required :video, OpenAI::Internal::Type::FileInput
|
|
21
25
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute input_reference
|
|
17
17
|
# Optional reference asset upload or reference object that guides generation.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::ImageInputReferenceParam, nil]
|
|
20
24
|
optional :input_reference, union: -> { OpenAI::VideoCreateParams::InputReference }
|
|
21
25
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute video
|
|
17
17
|
# Reference to the completed video to edit.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::VideoEditParams::Video::VideoReferenceInputParam]
|
|
20
24
|
required :video, union: -> { OpenAI::VideoEditParams::Video }
|
|
21
25
|
|
|
@@ -23,6 +23,10 @@ module OpenAI
|
|
|
23
23
|
# @!attribute video
|
|
24
24
|
# Reference to the completed video to extend.
|
|
25
25
|
#
|
|
26
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
27
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
28
|
+
# content type.
|
|
29
|
+
#
|
|
26
30
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::VideoExtendParams::Video::VideoReferenceInputParam]
|
|
27
31
|
required :video, union: -> { OpenAI::VideoExtendParams::Video }
|
|
28
32
|
|
data/lib/openai/models.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module OpenAI
|
|
4
|
-
|
|
4
|
+
# ActiveSupport 6 implements Class#subclasses using ==, which invokes BaseModel's
|
|
5
|
+
# structural equality before all model aliases are loaded.
|
|
6
|
+
base_model = OpenAI::Internal::Type::BaseModel
|
|
7
|
+
subclasses =
|
|
8
|
+
ObjectSpace.each_object(base_model.singleton_class).select do |candidate|
|
|
9
|
+
!candidate.singleton_class? && candidate.superclass.equal?(base_model)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
[base_model, *subclasses].each do |cls|
|
|
5
13
|
cls.define_sorbet_constant!(:OrHash) { T.type_alias { T.any(cls, OpenAI::Internal::AnyHash) } }
|
|
6
14
|
end
|
|
7
15
|
|
|
@@ -5,6 +5,10 @@ require_relative "internal/read_io_adapter"
|
|
|
5
5
|
module OpenAI
|
|
6
6
|
# The SDK's pooled Net::HTTP implementation.
|
|
7
7
|
#
|
|
8
|
+
# Network operations from a non-blocking fiber cooperate with its active Ruby
|
|
9
|
+
# Fiber scheduler, allowing concurrent requests and streams without occupying
|
|
10
|
+
# one thread per request.
|
|
11
|
+
#
|
|
8
12
|
# Pass a block to configure each SDK-created connection before it is pooled
|
|
9
13
|
# and started.
|
|
10
14
|
class NetHTTPClient < HTTPClient
|
|
@@ -66,15 +70,15 @@ module OpenAI
|
|
|
66
70
|
# @api private
|
|
67
71
|
#
|
|
68
72
|
# @param conn [Net::HTTP]
|
|
69
|
-
# @param deadline [Float]
|
|
73
|
+
# @param deadline [Float, nil]
|
|
70
74
|
private def calibrate_socket_timeout(conn, deadline)
|
|
71
|
-
timeout = remaining_timeout(
|
|
75
|
+
timeout = deadline&.then { remaining_timeout(_1) }
|
|
72
76
|
conn.open_timeout = conn.read_timeout = conn.write_timeout = conn.continue_timeout = timeout
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
# @api private
|
|
76
80
|
#
|
|
77
|
-
# @param deadline [Float]
|
|
81
|
+
# @param deadline [Float, nil]
|
|
78
82
|
# @return [Float]
|
|
79
83
|
# @raise [Timeout::Error]
|
|
80
84
|
private def remaining_timeout(deadline)
|
|
@@ -130,7 +134,6 @@ module OpenAI
|
|
|
130
134
|
# @yieldparam [Net::HTTP]
|
|
131
135
|
private def with_pool(url, deadline:, &blk)
|
|
132
136
|
origin = OpenAI::Internal::Util.uri_origin(url)
|
|
133
|
-
timeout = remaining_timeout(deadline)
|
|
134
137
|
pool =
|
|
135
138
|
@mutex.synchronize do
|
|
136
139
|
@pools[origin] ||= ConnectionPool.new(size: @size) do
|
|
@@ -138,7 +141,18 @@ module OpenAI
|
|
|
138
141
|
end
|
|
139
142
|
end
|
|
140
143
|
|
|
141
|
-
pool.with(timeout:
|
|
144
|
+
return pool.with(timeout: remaining_timeout(deadline), &blk) if deadline
|
|
145
|
+
|
|
146
|
+
checked_out = false
|
|
147
|
+
begin
|
|
148
|
+
pool.with do |connection|
|
|
149
|
+
checked_out = true
|
|
150
|
+
blk.call(connection)
|
|
151
|
+
end
|
|
152
|
+
rescue ConnectionPool::TimeoutError
|
|
153
|
+
retry unless checked_out
|
|
154
|
+
raise
|
|
155
|
+
end
|
|
142
156
|
end
|
|
143
157
|
|
|
144
158
|
# @api private
|
|
@@ -200,7 +214,7 @@ module OpenAI
|
|
|
200
214
|
# @return [OpenAI::HTTPClient::Response]
|
|
201
215
|
def execute(request)
|
|
202
216
|
url = request.url
|
|
203
|
-
deadline = OpenAI::Internal::Util.monotonic_secs +
|
|
217
|
+
deadline = request.timeout&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
204
218
|
|
|
205
219
|
req = nil
|
|
206
220
|
finished = false
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenAI
|
|
4
|
+
module Providers
|
|
5
|
+
# @api private
|
|
6
|
+
module Azure
|
|
7
|
+
API_KEY_AUTH_MARKER = :openai_azure_api_key
|
|
8
|
+
BEARER_AUTH_MARKER = :openai_azure_bearer
|
|
9
|
+
AUTH_HEADERS = %w[api-key authorization].freeze
|
|
10
|
+
MISSING_ENDPOINT_MESSAGE =
|
|
11
|
+
"Azure OpenAI requires an endpoint. Pass `endpoint` to `azure(...)`, or set " \
|
|
12
|
+
"`AZURE_OPENAI_ENDPOINT`."
|
|
13
|
+
MISSING_CREDENTIALS_MESSAGE =
|
|
14
|
+
"Could not find credentials for Azure OpenAI. Pass `api_key` or `token_provider` " \
|
|
15
|
+
"to `azure(...)`, or set `AZURE_OPENAI_API_KEY`."
|
|
16
|
+
|
|
17
|
+
class Definition
|
|
18
|
+
attr_reader :name
|
|
19
|
+
|
|
20
|
+
def initialize(base_url:, credential_provider:, authentication:)
|
|
21
|
+
@name = "azure"
|
|
22
|
+
@base_url = base_url.freeze
|
|
23
|
+
@credential_provider = credential_provider
|
|
24
|
+
@authentication = authentication
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def configure
|
|
28
|
+
auth = Auth.new(
|
|
29
|
+
base_url: @base_url,
|
|
30
|
+
credential_provider: @credential_provider,
|
|
31
|
+
authentication: @authentication
|
|
32
|
+
)
|
|
33
|
+
OpenAI::Internal::Provider::Runtime.new(
|
|
34
|
+
name: name,
|
|
35
|
+
base_url: @base_url,
|
|
36
|
+
prepare_request: auth.method(:prepare_request),
|
|
37
|
+
authentication_headers: AUTH_HEADERS
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Auth
|
|
43
|
+
def initialize(base_url:, credential_provider:, authentication:)
|
|
44
|
+
@base_url = URI(base_url)
|
|
45
|
+
@credential_provider = credential_provider
|
|
46
|
+
@authentication = authentication
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def prepare_request(request)
|
|
50
|
+
Azure.validate_origin!(request.fetch(:url), @base_url)
|
|
51
|
+
marker = @authentication == :api_key ? API_KEY_AUTH_MARKER : BEARER_AUTH_MARKER
|
|
52
|
+
headers = Azure.provider_headers(request, marker: marker)
|
|
53
|
+
credential = resolve_credential
|
|
54
|
+
auth_header =
|
|
55
|
+
if @authentication == :api_key
|
|
56
|
+
{"api-key" => credential}
|
|
57
|
+
else
|
|
58
|
+
{"authorization" => "Bearer #{credential}"}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
request.merge(headers: headers.merge(auth_header), provider_auth: marker)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private def resolve_credential
|
|
65
|
+
credential = @credential_provider.call
|
|
66
|
+
unless credential.is_a?(String) && !credential.strip.empty?
|
|
67
|
+
name = @authentication == :api_key ? "API key" : "token provider"
|
|
68
|
+
raise OpenAI::Errors::Error,
|
|
69
|
+
"The Azure OpenAI #{name} must return a non-empty string."
|
|
70
|
+
end
|
|
71
|
+
credential
|
|
72
|
+
rescue OpenAI::Errors::Error
|
|
73
|
+
raise
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
message =
|
|
76
|
+
if @authentication == :api_key
|
|
77
|
+
"Failed to resolve an API key for Azure OpenAI."
|
|
78
|
+
else
|
|
79
|
+
"Failed to resolve a bearer token for Azure OpenAI."
|
|
80
|
+
end
|
|
81
|
+
raise OpenAI::Errors::Error.new(message), cause: e
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class << self
|
|
86
|
+
def normalize_endpoint(endpoint)
|
|
87
|
+
uri = URI(endpoint)
|
|
88
|
+
unless uri.is_a?(URI::HTTP) && uri.host
|
|
89
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must be an absolute HTTP or HTTPS URL."
|
|
90
|
+
end
|
|
91
|
+
unless uri.query.nil?
|
|
92
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include a query string."
|
|
93
|
+
end
|
|
94
|
+
unless uri.fragment.nil?
|
|
95
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include a fragment."
|
|
96
|
+
end
|
|
97
|
+
unless uri.userinfo.nil?
|
|
98
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include user information."
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
path = uri.path.sub(%r{/+\z}, "")
|
|
102
|
+
uri.path =
|
|
103
|
+
case path
|
|
104
|
+
when %r{/openai/v1\z}
|
|
105
|
+
path
|
|
106
|
+
when %r{/openai\z}
|
|
107
|
+
"#{path}/v1"
|
|
108
|
+
else
|
|
109
|
+
"#{path}/openai/v1"
|
|
110
|
+
end
|
|
111
|
+
uri.to_s
|
|
112
|
+
rescue URI::InvalidURIError => e
|
|
113
|
+
message = "The Azure OpenAI `endpoint` must be an absolute HTTP or HTTPS URL."
|
|
114
|
+
raise ArgumentError.new(message), cause: e
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def normalize_optional_string(value)
|
|
118
|
+
return nil unless value.is_a?(String)
|
|
119
|
+
normalized = value.strip
|
|
120
|
+
normalized unless normalized.empty?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def provider_headers(request, marker:)
|
|
124
|
+
headers = request.fetch(:headers).dup
|
|
125
|
+
if request[:provider_auth] == marker
|
|
126
|
+
AUTH_HEADERS.each { headers.delete(_1) }
|
|
127
|
+
elsif AUTH_HEADERS.any? { headers.key?(_1) }
|
|
128
|
+
raise OpenAI::Errors::Error,
|
|
129
|
+
"Azure OpenAI provider authentication cannot be combined with a custom " \
|
|
130
|
+
"`Authorization` or `api-key` header."
|
|
131
|
+
end
|
|
132
|
+
headers
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def validate_origin!(url, base_url)
|
|
136
|
+
return if OpenAI::Internal::Util.uri_origin(url) == OpenAI::Internal::Util.uri_origin(base_url)
|
|
137
|
+
raise OpenAI::Errors::Error,
|
|
138
|
+
"Refusing to authenticate a request for an origin other than the configured " \
|
|
139
|
+
"Azure OpenAI endpoint."
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
class << self
|
|
145
|
+
# Configure the standard OpenAI client for the Azure OpenAI v1 API.
|
|
146
|
+
#
|
|
147
|
+
# @param endpoint [String, nil] Azure OpenAI resource endpoint. Defaults to
|
|
148
|
+
# `AZURE_OPENAI_ENDPOINT`. `/openai/v1` is appended when absent.
|
|
149
|
+
#
|
|
150
|
+
# @param api_key [String, nil] Azure OpenAI API key. Defaults to
|
|
151
|
+
# `AZURE_OPENAI_API_KEY` when no token provider is configured. Passing
|
|
152
|
+
# `nil` explicitly skips the environment fallback.
|
|
153
|
+
#
|
|
154
|
+
# @param token_provider [#call, nil] Callable returning a Microsoft Entra
|
|
155
|
+
# bearer token before each request attempt.
|
|
156
|
+
#
|
|
157
|
+
# @return [OpenAI::Provider]
|
|
158
|
+
def azure(
|
|
159
|
+
endpoint: OpenAI::Internal::OMIT,
|
|
160
|
+
api_key: OpenAI::Internal::OMIT,
|
|
161
|
+
token_provider: nil
|
|
162
|
+
)
|
|
163
|
+
configured_endpoint =
|
|
164
|
+
if endpoint.equal?(OpenAI::Internal::OMIT)
|
|
165
|
+
Azure.normalize_optional_string(ENV["AZURE_OPENAI_ENDPOINT"])
|
|
166
|
+
else
|
|
167
|
+
normalized = Azure.normalize_optional_string(endpoint)
|
|
168
|
+
if !endpoint.nil? && normalized.nil?
|
|
169
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not be empty."
|
|
170
|
+
end
|
|
171
|
+
normalized
|
|
172
|
+
end
|
|
173
|
+
raise ArgumentError, Azure::MISSING_ENDPOINT_MESSAGE if configured_endpoint.nil?
|
|
174
|
+
base_url = Azure.normalize_endpoint(configured_endpoint)
|
|
175
|
+
|
|
176
|
+
explicit_api_key = !api_key.equal?(OpenAI::Internal::OMIT) && !api_key.nil?
|
|
177
|
+
normalized_api_key = Azure.normalize_optional_string(api_key)
|
|
178
|
+
if explicit_api_key && normalized_api_key.nil?
|
|
179
|
+
raise ArgumentError, "The Azure OpenAI API key must not be empty."
|
|
180
|
+
end
|
|
181
|
+
unless token_provider.nil? || token_provider.respond_to?(:call)
|
|
182
|
+
raise ArgumentError, "The Azure OpenAI `token_provider` must respond to `call`."
|
|
183
|
+
end
|
|
184
|
+
if explicit_api_key && !token_provider.nil?
|
|
185
|
+
raise ArgumentError,
|
|
186
|
+
"The Azure OpenAI `api_key` and `token_provider` options are mutually exclusive."
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
environment_api_key =
|
|
190
|
+
if api_key.equal?(OpenAI::Internal::OMIT) && token_provider.nil?
|
|
191
|
+
Azure.normalize_optional_string(ENV["AZURE_OPENAI_API_KEY"])
|
|
192
|
+
end
|
|
193
|
+
resolved_api_key = normalized_api_key || environment_api_key
|
|
194
|
+
if resolved_api_key.nil? && token_provider.nil?
|
|
195
|
+
raise ArgumentError, Azure::MISSING_CREDENTIALS_MESSAGE
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
if token_provider
|
|
199
|
+
credential_provider = token_provider
|
|
200
|
+
authentication = :bearer
|
|
201
|
+
else
|
|
202
|
+
resolved_api_key.freeze
|
|
203
|
+
credential_provider = -> { resolved_api_key }
|
|
204
|
+
authentication = :api_key
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
definition = Azure::Definition.new(
|
|
208
|
+
base_url: base_url,
|
|
209
|
+
credential_provider: credential_provider,
|
|
210
|
+
authentication: authentication
|
|
211
|
+
)
|
|
212
|
+
OpenAI::Internal::Provider.create(definition)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|