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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -0
- data/README.md +23 -1
- data/lib/openai/client.rb +3 -386
- data/lib/openai/helpers/admin/organization/projects/api_keys.rb +42 -0
- data/lib/openai/helpers/agents/session_stream_resource.rb +60 -0
- data/lib/openai/helpers/beta/agents/artifacts.rb +18 -0
- data/lib/openai/helpers/beta/agents/files.rb +41 -0
- data/lib/openai/helpers/client_runtime.rb +391 -0
- data/lib/openai/helpers/files.rb +47 -0
- data/lib/openai/helpers/live/websocket.rb +8 -57
- data/lib/openai/helpers/models/chat/parsed.rb +32 -0
- data/lib/openai/helpers/models/responses/parsed.rb +30 -0
- data/lib/openai/helpers/models/responses/response.rb +32 -0
- data/lib/openai/helpers/models/webhooks/webhook_endpoint_with_secret.rb +20 -0
- data/lib/openai/helpers/realtime/client_extension.rb +1 -2
- data/lib/openai/helpers/realtime/connection_manager.rb +1 -1
- data/lib/openai/helpers/realtime/translation.rb +7 -50
- data/lib/openai/helpers/responses_websocket/client_extension.rb +1 -2
- data/lib/openai/helpers/streaming/chat_completion_resource.rb +36 -0
- data/lib/openai/helpers/streaming/response_stream.rb +1 -16
- data/lib/openai/helpers/streaming/response_stream_resource.rb +78 -0
- data/lib/openai/helpers/vector_stores/file_batches.rb +188 -0
- data/lib/openai/helpers/vector_stores/files.rb +198 -0
- data/lib/openai/helpers/websocket/client_request.rb +31 -6
- data/lib/openai/helpers/websocket/connection.rb +58 -0
- data/lib/openai/helpers/websocket/connection_manager.rb +4 -2
- data/lib/openai/helpers/websocket/protocol.rb +2 -1
- data/lib/openai/helpers/websocket/resource.rb +54 -0
- data/lib/openai/helpers/websocket/typed_connection.rb +95 -0
- data/lib/openai/helpers/websocket.rb +4 -0
- data/lib/openai/models/admin/organization/audit_log_list_response.rb +5 -3
- data/lib/openai/models/admin/organization/external_storage_configuration.rb +5 -3
- data/lib/openai/models/admin/organization/external_storage_create_params.rb +33 -3
- data/lib/openai/models/admin/organization/oci_external_storage_provider.rb +37 -0
- data/lib/openai/models/admin/organization/project_residency.rb +3 -0
- data/lib/openai/models/admin/organization/projects/api_key_update_params.rb +64 -0
- data/lib/openai/models/admin/organization/projects/api_key_update_scopes_params.rb +34 -0
- data/lib/openai/models/admin/organization/usage_decisions_params.rb +177 -0
- data/lib/openai/models/admin/organization/usage_decisions_response.rb +351 -0
- data/lib/openai/models/audio/speech_create_params.rb +6 -3
- data/lib/openai/models/audio/translation_create_response.rb +0 -1
- data/lib/openai/models/audio/voice.rb +17 -2
- data/lib/openai/models/audio/voice_create_params.rb +100 -3
- data/lib/openai/models/beta/agent_create_params.rb +4 -2
- data/lib/openai/models/beta/agent_list_params.rb +4 -4
- data/lib/openai/models/beta/agent_session.rb +37 -1
- data/lib/openai/models/beta/agent_update_params.rb +4 -2
- data/lib/openai/models/beta/agents/environment_list_params.rb +7 -7
- data/lib/openai/models/beta/agents/session_create_params.rb +39 -3
- data/lib/openai/models/beta/agents/session_list_params.rb +7 -10
- data/lib/openai/models/beta/agents/session_update_params.rb +33 -1
- data/lib/openai/models/beta/agents/sessions/artifact_list_params.rb +11 -11
- data/lib/openai/models/beta/agents/vault_list_params.rb +23 -13
- data/lib/openai/models/beta/agents/vault_status_filter.rb +1 -3
- data/lib/openai/models/beta/agents/vault_update_params.rb +47 -0
- data/lib/openai/models/beta/agents/vaults/credential_list_params.rb +23 -13
- data/lib/openai/models/beta/beta_response.rb +23 -2
- data/lib/openai/models/beta/beta_response_error.rb +19 -1
- data/lib/openai/models/beta/beta_response_input_item.rb +107 -1
- data/lib/openai/models/beta/beta_response_item.rb +107 -1
- data/lib/openai/models/beta/beta_response_output_item.rb +107 -1
- data/lib/openai/models/beta/beta_responses_client_event.rb +23 -2
- data/lib/openai/models/beta/response_compact_params.rb +21 -0
- data/lib/openai/models/beta/response_create_params.rb +23 -2
- data/lib/openai/models/beta/session_turn_error.rb +3 -0
- data/lib/openai/models/chat/chat_completion_audio_param.rb +3 -3
- data/lib/openai/models/chat/chat_completion_message.rb +0 -8
- data/lib/openai/models/chat/chat_completion_message_function_tool_call.rb +0 -8
- data/lib/openai/models/chat/completion_create_params.rb +5 -12
- data/lib/openai/models/chat_model.rb +21 -0
- data/lib/openai/models/conversations/conversation_item.rb +107 -1
- data/lib/openai/models/decision.rb +17 -2
- data/lib/openai/models/decision_create_params.rb +29 -12
- data/lib/openai/models/decision_input_image.rb +4 -3
- data/lib/openai/models/decision_input_message.rb +4 -4
- data/lib/openai/models/decision_input_part.rb +3 -2
- data/lib/openai/models/image_edit_completed_event.rb +1 -2
- data/lib/openai/models/image_edit_partial_image_event.rb +1 -2
- data/lib/openai/models/image_gen_completed_event.rb +1 -2
- data/lib/openai/models/image_gen_partial_image_event.rb +1 -2
- data/lib/openai/models/images_response.rb +1 -2
- data/lib/openai/models/live/built_in_voice.rb +1 -0
- data/lib/openai/models/live/client_event.rb +14 -2
- data/lib/openai/models/live/decision_create_event.rb +26 -0
- data/lib/openai/models/live/decision_event.rb +117 -0
- data/lib/openai/models/live/decision_item_create_event.rb +194 -0
- data/lib/openai/models/live/decision_item_created_event.rb +202 -0
- data/lib/openai/models/live/decision_item_delete_event.rb +38 -0
- data/lib/openai/models/live/decision_item_deleted_event.rb +46 -0
- data/lib/openai/models/live/decision_trigger.rb +244 -0
- data/lib/openai/models/live/decisions_delegation_config.rb +201 -0
- data/lib/openai/models/live/decisions_delegation_update_config.rb +208 -0
- data/lib/openai/models/live/delegation_created_event.rb +10 -10
- data/lib/openai/models/live/fork_client_event.rb +14 -2
- data/lib/openai/models/live/fork_server_event.rb +17 -2
- data/lib/openai/models/live/media_session_config.rb +47 -11
- data/lib/openai/models/live/output_audio_fixture_play_event.rb +48 -0
- data/lib/openai/models/live/output_audio_fixture_played_event.rb +42 -0
- data/lib/openai/models/live/output_audio_fixture_playing_event.rb +41 -0
- data/lib/openai/models/live/server_event.rb +17 -2
- data/lib/openai/models/live/session_accept_params.rb +47 -11
- data/lib/openai/models/live/session_config.rb +47 -11
- data/lib/openai/models/live/session_resource.rb +47 -11
- data/lib/openai/models/live/session_update_config.rb +38 -6
- data/lib/openai/models/live/session_update_event.rb +8 -8
- data/lib/openai/models/live/sideband_client_event.rb +57 -0
- data/lib/openai/models/live/sideband_server_event.rb +78 -0
- data/lib/openai/models/realtime/realtime_audio_config_output.rb +6 -3
- data/lib/openai/models/realtime/realtime_response_create_audio_output.rb +6 -3
- data/lib/openai/models/realtime/realtime_response_status.rb +10 -1
- data/lib/openai/models/response_format_json_schema.rb +1 -1
- data/lib/openai/models/responses/function_tool.rb +8 -6
- data/lib/openai/models/responses/response.rb +2 -23
- data/lib/openai/models/responses/response_compact_params.rb +21 -0
- data/lib/openai/models/responses/response_create_params.rb +3 -6
- data/lib/openai/models/responses/response_error.rb +19 -1
- data/lib/openai/models/responses/response_format_text_config.rb +0 -4
- data/lib/openai/models/responses/response_function_tool_call.rb +0 -8
- data/lib/openai/models/responses/response_input_item.rb +107 -1
- data/lib/openai/models/responses/response_item.rb +107 -1
- data/lib/openai/models/responses/response_output_item.rb +107 -1
- data/lib/openai/models/responses/response_output_text.rb +0 -8
- data/lib/openai/models/responses/responses_client_event.rb +2 -2
- data/lib/openai/models/safety/safety_alert.rb +12 -1
- data/lib/openai/models/video_create_error.rb +19 -1
- data/lib/openai/models/webhooks/unwrap_webhook_event.rb +4 -4
- data/lib/openai/models/webhooks/webhook_endpoint_with_secret.rb +0 -9
- data/lib/openai/resources/admin/organization/external_storage.rb +1 -1
- data/lib/openai/resources/admin/organization/projects/api_keys.rb +61 -0
- data/lib/openai/resources/admin/organization/usage.rb +67 -0
- data/lib/openai/resources/audio/speech.rb +2 -1
- data/lib/openai/resources/audio/voices.rb +10 -10
- data/lib/openai/resources/beta/agents/environments/files.rb +3 -31
- data/lib/openai/resources/beta/agents/environments.rb +3 -3
- data/lib/openai/resources/beta/agents/sessions/artifacts.rb +5 -11
- data/lib/openai/resources/beta/agents/sessions.rb +20 -56
- data/lib/openai/resources/beta/agents/vaults/credentials.rb +10 -6
- data/lib/openai/resources/beta/agents/vaults.rb +45 -6
- data/lib/openai/resources/beta/agents.rb +6 -4
- data/lib/openai/resources/beta/responses.rb +2 -2
- data/lib/openai/resources/chat/completions.rb +11 -37
- data/lib/openai/resources/decisions.rb +9 -15
- data/lib/openai/resources/files.rb +0 -39
- data/lib/openai/resources/live/forks.rb +19 -0
- data/lib/openai/resources/live/sideband.rb +19 -0
- data/lib/openai/resources/live.rb +19 -0
- data/lib/openai/resources/realtime/translations.rb +19 -0
- data/lib/openai/resources/realtime.rb +19 -0
- data/lib/openai/resources/responses.rb +44 -95
- data/lib/openai/resources/vector_stores/file_batches.rb +0 -178
- data/lib/openai/resources/vector_stores/files.rb +0 -188
- data/lib/openai/resources/webhooks.rb +13 -29
- data/lib/openai/version.rb +1 -1
- data/lib/openai.rb +31 -0
- data/rbi/openai/client.rbi +0 -103
- data/rbi/openai/helpers/admin/organization/projects/api_keys.rbi +25 -0
- data/rbi/openai/helpers/beta/agents/artifacts.rbi +25 -0
- data/rbi/openai/helpers/beta/agents/files.rbi +48 -0
- data/rbi/openai/helpers/client_runtime.rbi +108 -0
- data/rbi/openai/helpers/files.rbi +25 -0
- data/rbi/openai/helpers/models/chat/parsed.rbi +21 -0
- data/rbi/openai/helpers/models/responses/parsed.rbi +19 -0
- data/rbi/openai/helpers/models/responses/response.rbi +15 -0
- data/rbi/openai/helpers/streaming/response_stream.rbi +301 -0
- data/rbi/openai/helpers/vector_stores/file_batches.rbi +102 -0
- data/rbi/openai/helpers/vector_stores/files.rbi +122 -0
- data/rbi/openai/helpers/websocket.rbi +82 -0
- data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +6 -3
- data/rbi/openai/models/admin/organization/external_storage_configuration.rbi +4 -2
- data/rbi/openai/models/admin/organization/external_storage_create_params.rbi +63 -4
- data/rbi/openai/models/admin/organization/oci_external_storage_provider.rbi +71 -0
- data/rbi/openai/models/admin/organization/project_residency.rbi +12 -0
- data/rbi/openai/models/admin/organization/projects/api_key_update_params.rbi +110 -0
- data/rbi/openai/models/admin/organization/projects/api_key_update_scopes_params.rbi +72 -0
- data/rbi/openai/models/admin/organization/usage_decisions_params.rbi +229 -0
- data/rbi/openai/models/admin/organization/usage_decisions_response.rbi +479 -0
- data/rbi/openai/models/audio/speech_create_params.rbi +6 -3
- data/rbi/openai/models/audio/voice.rbi +21 -2
- data/rbi/openai/models/audio/voice_create_params.rbi +149 -4
- data/rbi/openai/models/beta/agent_create_params.rbi +4 -2
- data/rbi/openai/models/beta/agent_list_params.rbi +8 -5
- data/rbi/openai/models/beta/agent_session.rbi +64 -1
- data/rbi/openai/models/beta/agent_update_params.rbi +4 -2
- data/rbi/openai/models/beta/agents/environment_list_params.rbi +7 -7
- data/rbi/openai/models/beta/agents/session_create_params.rbi +62 -2
- data/rbi/openai/models/beta/agents/session_list_params.rbi +11 -11
- data/rbi/openai/models/beta/agents/session_update_params.rbi +56 -0
- data/rbi/openai/models/beta/agents/sessions/artifact_list_params.rbi +19 -13
- data/rbi/openai/models/beta/agents/vault_list_params.rbi +30 -13
- data/rbi/openai/models/beta/agents/vault_status_filter.rbi +1 -3
- data/rbi/openai/models/beta/agents/vault_update_params.rbi +87 -0
- data/rbi/openai/models/beta/agents/vaults/credential_list_params.rbi +30 -13
- data/rbi/openai/models/beta/beta_response.rbi +2 -2
- data/rbi/openai/models/beta/beta_response_error.rbi +24 -3
- data/rbi/openai/models/beta/beta_response_input_item.rbi +191 -0
- data/rbi/openai/models/beta/beta_response_item.rbi +189 -0
- data/rbi/openai/models/beta/beta_response_output_item.rbi +191 -0
- data/rbi/openai/models/beta/beta_responses_client_event.rbi +2 -2
- data/rbi/openai/models/beta/response_create_params.rbi +2 -2
- data/rbi/openai/models/beta/session_turn_error.rbi +3 -0
- data/rbi/openai/models/chat/chat_completion_audio_param.rbi +3 -3
- data/rbi/openai/models/chat/chat_completion_message.rbi +0 -4
- data/rbi/openai/models/chat/chat_completion_message_function_tool_call.rbi +0 -4
- data/rbi/openai/models/chat/completion_create_params.rbi +63 -78
- data/rbi/openai/models/conversations/conversation_item.rbi +191 -0
- data/rbi/openai/models/decision.rbi +14 -1
- data/rbi/openai/models/decision_create_params.rbi +23 -12
- data/rbi/openai/models/decision_input_image.rbi +4 -3
- data/rbi/openai/models/decision_input_message.rbi +4 -4
- data/rbi/openai/models/decision_input_part.rbi +2 -1
- data/rbi/openai/models/image_edit_completed_event.rbi +1 -0
- data/rbi/openai/models/image_edit_partial_image_event.rbi +1 -0
- data/rbi/openai/models/image_gen_completed_event.rbi +1 -0
- data/rbi/openai/models/image_gen_partial_image_event.rbi +1 -0
- data/rbi/openai/models/images_response.rbi +1 -0
- data/rbi/openai/models/live/built_in_voice.rbi +1 -0
- data/rbi/openai/models/live/client_event.rbi +4 -0
- data/rbi/openai/models/live/decision_create_event.rbi +55 -0
- data/rbi/openai/models/live/decision_event.rbi +185 -0
- data/rbi/openai/models/live/decision_item_create_event.rbi +338 -0
- data/rbi/openai/models/live/decision_item_created_event.rbi +354 -0
- data/rbi/openai/models/live/decision_item_delete_event.rbi +66 -0
- data/rbi/openai/models/live/decision_item_deleted_event.rbi +77 -0
- data/rbi/openai/models/live/decision_trigger.rbi +465 -0
- data/rbi/openai/models/live/decisions_delegation_config.rbi +393 -0
- data/rbi/openai/models/live/decisions_delegation_update_config.rbi +412 -0
- data/rbi/openai/models/live/delegation_created_event.rbi +8 -10
- data/rbi/openai/models/live/fork_client_event.rbi +4 -0
- data/rbi/openai/models/live/fork_server_event.rbi +5 -0
- data/rbi/openai/models/live/media_session_config.rbi +95 -14
- data/rbi/openai/models/live/output_audio_fixture_play_event.rbi +76 -0
- data/rbi/openai/models/live/output_audio_fixture_played_event.rbi +73 -0
- data/rbi/openai/models/live/output_audio_fixture_playing_event.rbi +72 -0
- data/rbi/openai/models/live/server_event.rbi +5 -0
- data/rbi/openai/models/live/session_accept_params.rbi +88 -12
- data/rbi/openai/models/live/session_config.rbi +100 -14
- data/rbi/openai/models/live/session_resource.rbi +81 -10
- data/rbi/openai/models/live/session_update_config.rbi +86 -9
- data/rbi/openai/models/live/session_update_event.rbi +8 -8
- data/rbi/openai/models/live/sideband_client_event.rbi +40 -0
- data/rbi/openai/models/live/sideband_server_event.rbi +47 -0
- data/rbi/openai/models/realtime/realtime_audio_config_output.rbi +6 -3
- data/rbi/openai/models/realtime/realtime_response_create_audio_output.rbi +6 -3
- data/rbi/openai/models/realtime/realtime_response_status.rbi +13 -1
- data/rbi/openai/models/realtime/realtime_translation_input_audio_buffer_append_event.rbi +1 -1
- data/rbi/openai/models/realtime/realtime_translation_output_audio_delta_event.rbi +3 -3
- data/rbi/openai/models/realtime/realtime_translation_session_close_event.rbi +1 -1
- data/rbi/openai/models/realtime/realtime_translation_session_update_event.rbi +5 -1
- data/rbi/openai/models/responses/response.rbi +2 -7
- data/rbi/openai/models/responses/response_create_params.rbi +5 -9
- data/rbi/openai/models/responses/response_error.rbi +24 -3
- data/rbi/openai/models/responses/response_function_tool_call.rbi +0 -4
- data/rbi/openai/models/responses/response_function_web_search.rbi +21 -17
- data/rbi/openai/models/responses/response_input_item.rbi +191 -0
- data/rbi/openai/models/responses/response_item.rbi +189 -0
- data/rbi/openai/models/responses/response_output_item.rbi +191 -0
- data/rbi/openai/models/responses/response_output_text.rbi +0 -4
- data/rbi/openai/models/responses/responses_client_event.rbi +2 -2
- data/rbi/openai/models/safety/safety_alert.rbi +13 -1
- data/rbi/openai/models/video_create_error.rbi +24 -3
- data/rbi/openai/models/webhooks/unwrap_webhook_event.rbi +1 -1
- data/rbi/openai/resources/admin/organization/external_storage.rbi +2 -1
- data/rbi/openai/resources/admin/organization/projects/api_keys.rbi +48 -0
- data/rbi/openai/resources/admin/organization/usage.rbi +56 -0
- data/rbi/openai/resources/audio/speech.rbi +2 -1
- data/rbi/openai/resources/audio/voices.rbi +13 -10
- data/rbi/openai/resources/beta/agents/environments/files.rbi +3 -33
- data/rbi/openai/resources/beta/agents/environments.rbi +3 -3
- data/rbi/openai/resources/beta/agents/sessions/artifacts.rbi +5 -13
- data/rbi/openai/resources/beta/agents/sessions.rbi +15 -4
- data/rbi/openai/resources/beta/agents/vaults/credentials.rbi +9 -5
- data/rbi/openai/resources/beta/agents/vaults.rbi +34 -5
- data/rbi/openai/resources/beta/agents.rbi +6 -4
- data/rbi/openai/resources/beta/responses.rbi +2 -2
- data/rbi/openai/resources/chat/completions.rbi +26 -29
- data/rbi/openai/resources/decisions.rbi +9 -15
- data/rbi/openai/resources/files.rbi +0 -18
- data/rbi/openai/resources/live/forks.rbi +17 -0
- data/rbi/openai/resources/live/sideband.rbi +17 -0
- data/rbi/openai/resources/live.rbi +17 -0
- data/rbi/openai/resources/realtime/translations.rbi +17 -0
- data/rbi/openai/resources/realtime.rbi +17 -0
- data/rbi/openai/resources/responses.rbi +41 -333
- data/rbi/openai/resources/vector_stores/file_batches.rbi +0 -93
- data/rbi/openai/resources/vector_stores/files.rbi +0 -113
- data/rbi/openai/resources/webhooks.rbi +1 -1
- data/sig/openai/client.rbs +0 -50
- data/sig/openai/helpers/admin/organization/projects/api_keys.rbs +18 -0
- data/sig/openai/helpers/beta/agents/artifacts.rbs +17 -0
- data/sig/openai/helpers/beta/agents/files.rbs +30 -0
- data/sig/openai/helpers/client_runtime.rbs +53 -0
- data/sig/openai/helpers/files.rbs +12 -0
- data/sig/openai/helpers/models/responses/response.rbs +9 -0
- data/sig/openai/helpers/streaming/response_stream.rbs +37 -0
- data/sig/openai/helpers/vector_stores/file_batches.rbs +38 -0
- data/sig/openai/helpers/vector_stores/files.rbs +43 -0
- data/sig/openai/helpers/websocket.rbs +40 -0
- data/sig/openai/models/admin/organization/audit_log_list_response.rbs +1 -0
- data/sig/openai/models/admin/organization/external_storage_configuration.rbs +1 -0
- data/sig/openai/models/admin/organization/external_storage_create_params.rbs +33 -0
- data/sig/openai/models/admin/organization/oci_external_storage_provider.rbs +34 -0
- data/sig/openai/models/admin/organization/project_residency.rbs +6 -0
- data/sig/openai/models/admin/organization/projects/api_key_update_params.rbs +77 -0
- data/sig/openai/models/admin/organization/projects/api_key_update_scopes_params.rbs +38 -0
- data/sig/openai/models/admin/organization/usage_decisions_params.rbs +170 -0
- data/sig/openai/models/admin/organization/usage_decisions_response.rbs +319 -0
- data/sig/openai/models/audio/speech_create_params.rbs +4 -2
- data/sig/openai/models/audio/voice.rbs +21 -3
- data/sig/openai/models/audio/voice_create_params.rbs +90 -1
- data/sig/openai/models/beta/agent_create_params.rbs +4 -2
- data/sig/openai/models/beta/agent_list_params.rbs +9 -6
- data/sig/openai/models/beta/agent_session.rbs +36 -2
- data/sig/openai/models/beta/agent_update_params.rbs +4 -2
- data/sig/openai/models/beta/agents/environment_list_params.rbs +9 -9
- data/sig/openai/models/beta/agents/session_create_params.rbs +29 -2
- data/sig/openai/models/beta/agents/session_list_params.rbs +12 -12
- data/sig/openai/models/beta/agents/session_update_params.rbs +23 -0
- data/sig/openai/models/beta/agents/sessions/artifact_list_params.rbs +21 -15
- data/sig/openai/models/beta/agents/vault_list_params.rbs +32 -14
- data/sig/openai/models/beta/agents/vault_update_params.rbs +54 -0
- data/sig/openai/models/beta/agents/vaults/credential_list_params.rbs +32 -14
- data/sig/openai/models/beta/beta_response.rbs +2 -2
- data/sig/openai/models/beta/beta_response_error.rbs +19 -3
- data/sig/openai/models/beta/beta_response_input_item.rbs +110 -0
- data/sig/openai/models/beta/beta_response_item.rbs +110 -0
- data/sig/openai/models/beta/beta_response_output_item.rbs +110 -0
- data/sig/openai/models/beta/beta_responses_client_event.rbs +2 -2
- data/sig/openai/models/beta/response_create_params.rbs +2 -2
- data/sig/openai/models/beta/session_turn_error.rbs +4 -0
- data/sig/openai/models/chat/chat_completion_audio_param.rbs +2 -2
- data/sig/openai/models/chat/completion_create_params.rbs +2 -2
- data/sig/openai/models/conversations/conversation_item.rbs +110 -0
- data/sig/openai/models/decision.rbs +13 -0
- data/sig/openai/models/decision_create_params.rbs +19 -8
- data/sig/openai/models/decision_input_image.rbs +2 -2
- data/sig/openai/models/decision_input_message.rbs +2 -2
- data/sig/openai/models/live/built_in_voice.rbs +2 -0
- data/sig/openai/models/live/client_event.rbs +4 -0
- data/sig/openai/models/live/decision_create_event.rbs +18 -0
- data/sig/openai/models/live/decision_event.rbs +102 -0
- data/sig/openai/models/live/decision_item_create_event.rbs +183 -0
- data/sig/openai/models/live/decision_item_created_event.rbs +195 -0
- data/sig/openai/models/live/decision_item_delete_event.rbs +33 -0
- data/sig/openai/models/live/decision_item_deleted_event.rbs +49 -0
- data/sig/openai/models/live/decision_trigger.rbs +234 -0
- data/sig/openai/models/live/decisions_delegation_config.rbs +195 -0
- data/sig/openai/models/live/decisions_delegation_update_config.rbs +202 -0
- data/sig/openai/models/live/delegation_created_event.rbs +6 -7
- data/sig/openai/models/live/fork_client_event.rbs +4 -0
- data/sig/openai/models/live/fork_server_event.rbs +5 -0
- data/sig/openai/models/live/media_session_config.rbs +58 -11
- data/sig/openai/models/live/output_audio_fixture_play_event.rbs +42 -0
- data/sig/openai/models/live/output_audio_fixture_played_event.rbs +44 -0
- data/sig/openai/models/live/output_audio_fixture_playing_event.rbs +44 -0
- data/sig/openai/models/live/server_event.rbs +5 -0
- data/sig/openai/models/live/session_accept_params.rbs +57 -10
- data/sig/openai/models/live/session_config.rbs +58 -11
- data/sig/openai/models/live/session_resource.rbs +57 -10
- data/sig/openai/models/live/session_update_config.rbs +54 -3
- data/sig/openai/models/live/session_update_event.rbs +6 -6
- data/sig/openai/models/live/sideband_client_event.rbs +26 -0
- data/sig/openai/models/live/sideband_server_event.rbs +33 -0
- data/sig/openai/models/realtime/realtime_audio_config_output.rbs +6 -3
- data/sig/openai/models/realtime/realtime_response_create_audio_output.rbs +6 -3
- data/sig/openai/models/realtime/realtime_response_status.rbs +15 -3
- data/sig/openai/models/responses/response.rbs +2 -4
- data/sig/openai/models/responses/response_create_params.rbs +2 -2
- data/sig/openai/models/responses/response_error.rbs +19 -3
- data/sig/openai/models/responses/response_input_item.rbs +110 -0
- data/sig/openai/models/responses/response_item.rbs +110 -0
- data/sig/openai/models/responses/response_output_item.rbs +110 -0
- data/sig/openai/models/responses/responses_client_event.rbs +2 -2
- data/sig/openai/models/safety/safety_alert.rbs +12 -2
- data/sig/openai/models/video_create_error.rbs +19 -3
- data/sig/openai/models/webhooks/unwrap_webhook_event.rbs +1 -1
- data/sig/openai/resources/admin/organization/projects/api_keys.rbs +8 -0
- data/sig/openai/resources/admin/organization/usage.rbs +15 -0
- data/sig/openai/resources/beta/agents/environments/files.rbs +0 -17
- data/sig/openai/resources/beta/agents/sessions/artifacts.rbs +2 -6
- data/sig/openai/resources/beta/agents/sessions.rbs +4 -1
- data/sig/openai/resources/beta/agents/vaults/credentials.rbs +2 -1
- data/sig/openai/resources/beta/agents/vaults.rbs +9 -1
- data/sig/openai/resources/beta/agents.rbs +1 -1
- data/sig/openai/resources/files.rbs +0 -7
- data/sig/openai/resources/live/forks.rbs +8 -0
- data/sig/openai/resources/live/sideband.rbs +8 -0
- data/sig/openai/resources/live.rbs +7 -0
- data/sig/openai/resources/realtime/translations.rbs +7 -0
- data/sig/openai/resources/realtime.rbs +7 -0
- data/sig/openai/resources/responses.rbs +7 -31
- data/sig/openai/resources/vector_stores/file_batches.rbs +0 -31
- data/sig/openai/resources/vector_stores/files.rbs +0 -36
- data/sig/openai/resources/webhooks.rbs +1 -1
- metadata +89 -1
|
@@ -70,3 +70,21 @@ module OpenAI
|
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
module OpenAI
|
|
75
|
+
module Resources
|
|
76
|
+
class Beta
|
|
77
|
+
class Agents
|
|
78
|
+
class Sessions
|
|
79
|
+
class Artifacts
|
|
80
|
+
# Access artifacts from exactly this completed turn (beta).
|
|
81
|
+
# @return [OpenAI::Helpers::Beta::Agents::ResultArtifacts]
|
|
82
|
+
def for_result(result)
|
|
83
|
+
OpenAI::Helpers::Beta::Agents::ResultArtifacts.new(artifacts: self, client: @client, result: result)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -234,3 +234,44 @@ module OpenAI
|
|
|
234
234
|
end
|
|
235
235
|
end
|
|
236
236
|
end
|
|
237
|
+
|
|
238
|
+
module OpenAI
|
|
239
|
+
module Resources
|
|
240
|
+
class Beta
|
|
241
|
+
class Agents
|
|
242
|
+
class Environments
|
|
243
|
+
class Files
|
|
244
|
+
# Upload selected local files for a new hosted environment (beta).
|
|
245
|
+
# @return [OpenAI::Helpers::Beta::Agents::PreparedFiles]
|
|
246
|
+
def prepare(files, request_options: {})
|
|
247
|
+
OpenAI::Helpers::Beta::Agents::FilePreparation
|
|
248
|
+
.new(client: @client, environment_files: self)
|
|
249
|
+
.prepare(files, request_options: request_options)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Upload an explicitly selected directory snapshot (beta).
|
|
253
|
+
# @return [OpenAI::Helpers::Beta::Agents::PreparedFiles]
|
|
254
|
+
def prepare_directory(directory, destination:, include:, request_options: {})
|
|
255
|
+
OpenAI::Helpers::Beta::Agents::FilePreparation
|
|
256
|
+
.new(client: @client, environment_files: self)
|
|
257
|
+
.prepare_directory(
|
|
258
|
+
directory,
|
|
259
|
+
destination: destination,
|
|
260
|
+
include: include,
|
|
261
|
+
request_options: request_options
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Upload and stage a local file in an existing environment (beta).
|
|
266
|
+
# @return [OpenAI::Helpers::Beta::Agents::PreparedFiles]
|
|
267
|
+
def upload(environment_id, file:, path:, request_options: {})
|
|
268
|
+
OpenAI::Helpers::Beta::Agents::FilePreparation
|
|
269
|
+
.new(client: @client, environment_files: self)
|
|
270
|
+
.upload(environment_id, file: file, path: path, request_options: request_options)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenAI
|
|
4
|
+
class Client < OpenAI::Internal::Transport::BaseClient
|
|
5
|
+
# @api private
|
|
6
|
+
private def x509_identity?(identity)
|
|
7
|
+
OpenAI::Auth::X509Transport.exact_instance?(identity, OpenAI::Auth::X509WorkloadIdentity)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @api private
|
|
11
|
+
private def x509_transport?(transport)
|
|
12
|
+
OpenAI::Auth::X509Transport.exact_instance?(transport, OpenAI::Auth::X509Transport)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Creates and returns a new client for interacting with the API.
|
|
16
|
+
#
|
|
17
|
+
# @param api_key [String, nil] Defaults to `ENV["OPENAI_API_KEY"]`.
|
|
18
|
+
# Mutually exclusive with `workload_identity`.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
# @api private
|
|
22
|
+
private def build_request(request, options)
|
|
23
|
+
if @provider_runtime
|
|
24
|
+
built = super
|
|
25
|
+
body = built[:body]
|
|
26
|
+
# Capture only the final model; provider hooks run after body encoding.
|
|
27
|
+
model = body.reverse_each.find { |key, _| key == :model || key == "model" }&.last if body.is_a?(Hash)
|
|
28
|
+
model = model.to_s if model.is_a?(Symbol)
|
|
29
|
+
return built.merge(provider_request_model: model)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
unless @workload_identity_auth && x509_transport?(@requester)
|
|
33
|
+
return super
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
selected = {}.merge(request.fetch(:security, {bearer_auth: true, admin_api_key_auth: true})).freeze
|
|
37
|
+
if selected.any? { |scheme, enabled| enabled && scheme != :bearer_auth && scheme != :admin_api_key_auth }
|
|
38
|
+
raise ArgumentError, "Unsupported authentication security scheme for X.509 workload identity"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
security = {
|
|
42
|
+
bearer_auth: selected[:bearer_auth] == true,
|
|
43
|
+
admin_api_key_auth: selected[:admin_api_key_auth] == true
|
|
44
|
+
}.freeze
|
|
45
|
+
expected = auth_headers(security: security)["authorization"]
|
|
46
|
+
built = super(request.merge(security: security), options)
|
|
47
|
+
canonical_headers = @requester.validate_api_request!(
|
|
48
|
+
url: built.fetch(:url),
|
|
49
|
+
headers: built.fetch(:headers)
|
|
50
|
+
)
|
|
51
|
+
unless expected == canonical_headers["authorization"]
|
|
52
|
+
raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
auth_max_retries = options.fetch(:max_retries, @max_retries)
|
|
56
|
+
built.merge(headers: canonical_headers, x509_auth_max_retries: auth_max_retries)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @api private
|
|
60
|
+
private def prepare_request(request, redirect_count:, retry_count:)
|
|
61
|
+
if workload_identity_request?(request)
|
|
62
|
+
request = prepare_workload_identity_request(request, retry_count: retry_count)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
preparer = @provider_runtime&.prepare_request
|
|
66
|
+
return super(request, redirect_count: redirect_count, retry_count: retry_count) unless preparer
|
|
67
|
+
preparer.call(request)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @api private
|
|
71
|
+
private def validate_prepared_request(request, original_request:)
|
|
72
|
+
prepared_request = super
|
|
73
|
+
return prepared_request unless @workload_identity_auth && x509_transport?(@requester)
|
|
74
|
+
|
|
75
|
+
canonical_headers = @requester.validate_api_request!(
|
|
76
|
+
url: prepared_request.fetch(:url),
|
|
77
|
+
headers: prepared_request.fetch(:headers)
|
|
78
|
+
)
|
|
79
|
+
expected = if (context = original_request[:x509_request_context])
|
|
80
|
+
"Bearer #{context.fetch(:token)}"
|
|
81
|
+
else
|
|
82
|
+
original_request.fetch(:headers)["authorization"]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
unless canonical_headers["authorization"] == expected
|
|
86
|
+
raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
prepared_request.merge(headers: canonical_headers)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @api private
|
|
93
|
+
private def validate_retry_delay!(request, delay:)
|
|
94
|
+
deadline = request[:x509_request_context]&.fetch(:deadline) || request[:workload_identity_deadline]
|
|
95
|
+
if deadline && delay >= deadline - OpenAI::Internal::Util.monotonic_secs
|
|
96
|
+
raise WORKLOAD_IDENTITY_DEADLINE_ERROR, "request timed out during workload identity authentication"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
super
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @api private
|
|
103
|
+
private def send_request(request, redirect_count:, retry_count:, send_retry_header:)
|
|
104
|
+
if @workload_identity_auth && x509_transport?(@requester)
|
|
105
|
+
canonical_headers = @requester.validate_api_request!(
|
|
106
|
+
url: request.fetch(:url),
|
|
107
|
+
headers: request.fetch(:headers)
|
|
108
|
+
)
|
|
109
|
+
request = request.merge(headers: canonical_headers)
|
|
110
|
+
authorization = canonical_headers["authorization"]
|
|
111
|
+
expected = "Bearer #{WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}"
|
|
112
|
+
admin_authorization = @admin_api_key && "Bearer #{@admin_api_key}"
|
|
113
|
+
unless authorization.nil? || authorization == expected || authorization == admin_authorization
|
|
114
|
+
raise OpenAI::Errors::Error, "X.509 requests cannot override the selected authorization credential"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return super unless workload_identity_request?(request)
|
|
119
|
+
|
|
120
|
+
x509_request = x509_transport?(@requester)
|
|
121
|
+
previous_context = request[:x509_request_context]
|
|
122
|
+
deadline = if x509_request
|
|
123
|
+
previous_context&.fetch(:deadline) ||
|
|
124
|
+
request[:workload_identity_deadline] ||
|
|
125
|
+
request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
126
|
+
else
|
|
127
|
+
request[:workload_identity_deadline] ||
|
|
128
|
+
request[:timeout]&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
request = request.merge(workload_identity_deadline: deadline)
|
|
132
|
+
if x509_request
|
|
133
|
+
replay_state = previous_context&.fetch(:replay_state) || []
|
|
134
|
+
issuer_retries = previous_context&.fetch(:issuer_retries, 0) || 0
|
|
135
|
+
auth_max_retries = previous_context&.fetch(:auth_max_retries) || request.fetch(:x509_auth_max_retries)
|
|
136
|
+
api_max_retries = previous_context&.fetch(:api_max_retries) || request.fetch(:max_retries)
|
|
137
|
+
log_context = previous_context&.fetch(:log_context) || yield
|
|
138
|
+
context = {
|
|
139
|
+
deadline: deadline,
|
|
140
|
+
replay_state: replay_state,
|
|
141
|
+
issuer_retries: issuer_retries,
|
|
142
|
+
auth_max_retries: auth_max_retries,
|
|
143
|
+
api_max_retries: api_max_retries,
|
|
144
|
+
log_context: log_context,
|
|
145
|
+
token: nil
|
|
146
|
+
}
|
|
147
|
+
request = request.merge(x509_request_context: context, max_retries: 0)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
begin
|
|
151
|
+
super(
|
|
152
|
+
request,
|
|
153
|
+
redirect_count: redirect_count,
|
|
154
|
+
retry_count: retry_count,
|
|
155
|
+
send_retry_header: send_retry_header
|
|
156
|
+
)
|
|
157
|
+
rescue OpenAI::Errors::AuthenticationError
|
|
158
|
+
if x509_request
|
|
159
|
+
rejected_token = request.fetch(:x509_request_context).fetch(:token)
|
|
160
|
+
raise if rejected_token.nil?
|
|
161
|
+
|
|
162
|
+
@workload_identity_auth.invalidate_token(rejected_token)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
replay_allowed = request_replayable?(request)
|
|
166
|
+
replay_allowed &&= x509_request ? replay_state.empty? : retry_count.zero?
|
|
167
|
+
raise unless replay_allowed
|
|
168
|
+
|
|
169
|
+
if x509_request
|
|
170
|
+
replay_state << true
|
|
171
|
+
replay_state.freeze
|
|
172
|
+
issuer_retries = context.fetch(:issuer_retries)
|
|
173
|
+
auth_max_retries = context.fetch(:auth_max_retries)
|
|
174
|
+
api_max_retries = context.fetch(:api_max_retries)
|
|
175
|
+
log_context = context.fetch(:log_context)
|
|
176
|
+
context = {
|
|
177
|
+
deadline: deadline,
|
|
178
|
+
replay_state: replay_state,
|
|
179
|
+
issuer_retries: issuer_retries,
|
|
180
|
+
auth_max_retries: auth_max_retries,
|
|
181
|
+
api_max_retries: api_max_retries,
|
|
182
|
+
log_context: log_context,
|
|
183
|
+
token: nil
|
|
184
|
+
}
|
|
185
|
+
request = request.merge(x509_request_context: context)
|
|
186
|
+
else
|
|
187
|
+
@workload_identity_auth.invalidate_token
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
begin
|
|
191
|
+
super(
|
|
192
|
+
request,
|
|
193
|
+
redirect_count: redirect_count,
|
|
194
|
+
retry_count: retry_count + 1,
|
|
195
|
+
send_retry_header: send_retry_header
|
|
196
|
+
)
|
|
197
|
+
rescue OpenAI::Errors::AuthenticationError
|
|
198
|
+
if x509_request && (rejected_token = request.fetch(:x509_request_context).fetch(:token))
|
|
199
|
+
@workload_identity_auth.invalidate_token(rejected_token)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
raise
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
rescue Timeout::Error => error
|
|
207
|
+
unless x509_request
|
|
208
|
+
raise unless error.is_a?(WORKLOAD_IDENTITY_DEADLINE_ERROR)
|
|
209
|
+
|
|
210
|
+
url = request.fetch(:url).dup
|
|
211
|
+
url.query = nil
|
|
212
|
+
url.fragment = nil
|
|
213
|
+
cause = Timeout::Error.new(error.message)
|
|
214
|
+
raise OpenAI::Errors::APITimeoutError.new(url: url, message: error.message), cause: cause
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
url = request.fetch(:url).dup
|
|
218
|
+
url.query = nil
|
|
219
|
+
url.fragment = nil
|
|
220
|
+
message = "request timed out during workload identity authentication"
|
|
221
|
+
raise OpenAI::Errors::APITimeoutError.new(url: url, message: message), cause: nil
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
private def workload_identity_request?(request)
|
|
225
|
+
return false unless @workload_identity_auth
|
|
226
|
+
|
|
227
|
+
expected = "Bearer #{WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}"
|
|
228
|
+
request[:headers]["authorization"] == expected
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
private def prepare_workload_identity_request(request, retry_count:)
|
|
232
|
+
deadline = request[:workload_identity_deadline]
|
|
233
|
+
previous_issuer_retries = request[:x509_request_context]&.fetch(:issuer_retries, 0) || 0
|
|
234
|
+
attempts = 0
|
|
235
|
+
begin
|
|
236
|
+
token = @workload_identity_auth.get_token(deadline: deadline)
|
|
237
|
+
rescue OpenAI::Errors::APIError => error
|
|
238
|
+
status = error.status
|
|
239
|
+
connection_failure = error.is_a?(OpenAI::Errors::APIConnectionError)
|
|
240
|
+
retryable_connection_failure = connection_failure &&
|
|
241
|
+
false.equal?(error.request_may_have_been_sent?)
|
|
242
|
+
retryable_status = retryable_connection_failure ||
|
|
243
|
+
[408, 409, 429].include?(status) ||
|
|
244
|
+
(status.is_a?(Integer) && (500..599).cover?(status))
|
|
245
|
+
consumed_retries = attempts + previous_issuer_retries + retry_count
|
|
246
|
+
unless x509_transport?(@requester) &&
|
|
247
|
+
retryable_status &&
|
|
248
|
+
consumed_retries < request.fetch(:x509_request_context).fetch(:auth_max_retries) &&
|
|
249
|
+
(retryable_connection_failure || self.class.should_retry?(status, headers: error.headers || {}))
|
|
250
|
+
raise
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
delay = retry_delay(error.headers || {}, retry_count: attempts)
|
|
254
|
+
if deadline && delay >= deadline - OpenAI::Internal::Util.monotonic_secs
|
|
255
|
+
raise Timeout::Error, "request timed out during workload identity authentication"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
context = request.fetch(:x509_request_context)
|
|
259
|
+
response = if connection_failure
|
|
260
|
+
nil
|
|
261
|
+
else
|
|
262
|
+
OpenAI::ResponseMetadata.new(status: status, headers: error.headers || {})
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
context.fetch(:log_context).retry_scheduled(
|
|
266
|
+
connection_failure ? error : status,
|
|
267
|
+
delay: delay,
|
|
268
|
+
response: response,
|
|
269
|
+
retry_count: consumed_retries,
|
|
270
|
+
max_retries: context.fetch(:auth_max_retries)
|
|
271
|
+
)
|
|
272
|
+
sleep(delay)
|
|
273
|
+
attempts += 1
|
|
274
|
+
retry
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
if (context = request[:x509_request_context])
|
|
278
|
+
context[:issuer_retries] = previous_issuer_retries + attempts
|
|
279
|
+
context[:token] = token.dup.freeze
|
|
280
|
+
context.freeze
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
updated_headers = request[:headers].merge("authorization" => "Bearer #{token}")
|
|
284
|
+
updated_request = request
|
|
285
|
+
.except(:workload_identity_deadline, :x509_request_context, :x509_auth_max_retries)
|
|
286
|
+
.merge(headers: updated_headers)
|
|
287
|
+
if context
|
|
288
|
+
updated_request = updated_request.merge(
|
|
289
|
+
max_retries: [context.fetch(:api_max_retries) - context.fetch(:issuer_retries), 0].max
|
|
290
|
+
)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
request_with_remaining_timeout(
|
|
294
|
+
updated_request,
|
|
295
|
+
deadline
|
|
296
|
+
)
|
|
297
|
+
rescue Timeout::Error => e
|
|
298
|
+
raise if x509_transport?(@requester)
|
|
299
|
+
|
|
300
|
+
url = request.fetch(:url).dup
|
|
301
|
+
url.query = nil
|
|
302
|
+
url.fragment = nil
|
|
303
|
+
raise OpenAI::Errors::APITimeoutError.new(url: url, message: e.message)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# @api private
|
|
307
|
+
private def request_with_remaining_timeout(request, deadline)
|
|
308
|
+
return request if deadline.nil?
|
|
309
|
+
|
|
310
|
+
remaining = deadline - OpenAI::Internal::Util.monotonic_secs
|
|
311
|
+
unless remaining.positive?
|
|
312
|
+
raise Timeout::Error, "request timed out during workload identity authentication"
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
request.merge(timeout: remaining)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Returns a new client of the same class with the supplied constructor options overridden.
|
|
319
|
+
# Other settings and the HTTP transport are inherited. The original client
|
|
320
|
+
# is unchanged. Header overrides are merged; nil removes an individual
|
|
321
|
+
# header, and default_headers: nil clears all custom default headers.
|
|
322
|
+
# Subclasses with incompatible constructors or a private .new must override
|
|
323
|
+
# this method if they need to support copying.
|
|
324
|
+
#
|
|
325
|
+
# @example Select a regional endpoint for a call
|
|
326
|
+
# client.with_options(base_url: "https://eu.api.openai.com/v1").responses.create(...)
|
|
327
|
+
# @param overrides [Hash{Symbol=>Object}] Options accepted by {#initialize}.
|
|
328
|
+
# @return [self]
|
|
329
|
+
def with_options(**overrides)
|
|
330
|
+
if overrides.key?(:workload_identity) && !overrides.key?(:http_client)
|
|
331
|
+
selected_identity = overrides.fetch(:workload_identity)
|
|
332
|
+
if x509_identity?(selected_identity) && (configured_transport = selected_identity.transport)
|
|
333
|
+
overrides = overrides.merge(http_client: configured_transport)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
previous_transport = @copy_options.fetch(:http_client)
|
|
338
|
+
transport = overrides.fetch(:http_client, previous_transport)
|
|
339
|
+
if overrides[:data_residency] && x509_transport?(transport)
|
|
340
|
+
residency = overrides.fetch(:data_residency)
|
|
341
|
+
options = OpenAI::Internal::ClientOptions.copy(@copy_options, overrides.except(:data_residency))
|
|
342
|
+
options.delete(:base_url) unless overrides.key?(:base_url)
|
|
343
|
+
return copy_with_workload_identity_auth(options.merge(data_residency: residency))
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
options = OpenAI::Internal::ClientOptions.copy(@copy_options, overrides)
|
|
347
|
+
adopted_identity = x509_identity?(options.fetch(:workload_identity)) &&
|
|
348
|
+
!x509_identity?(@copy_options.fetch(:workload_identity))
|
|
349
|
+
previous_origin = previous_transport.api_origin if x509_transport?(previous_transport)
|
|
350
|
+
selected_origin = transport.api_origin if x509_transport?(transport)
|
|
351
|
+
if adopted_identity && selected_origin
|
|
352
|
+
inherited_origin = OpenAI::Internal::Util.uri_origin(URI(options.fetch(:base_url).to_s))
|
|
353
|
+
adopted_identity = !inherited_origin.casecmp?(selected_origin)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
if (adopted_identity || previous_origin != selected_origin) &&
|
|
357
|
+
!overrides.key?(:base_url) &&
|
|
358
|
+
!overrides[:data_residency]
|
|
359
|
+
options.delete(:base_url)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
copy_with_workload_identity_auth(options)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# @api private
|
|
366
|
+
private def copy_with_workload_identity_auth(options)
|
|
367
|
+
copied = self.class.new(**options)
|
|
368
|
+
identity = @copy_options.fetch(:workload_identity)
|
|
369
|
+
if x509_identity?(identity) &&
|
|
370
|
+
identity.equal?(options.fetch(:workload_identity)) &&
|
|
371
|
+
copied.requester.equal?(@requester)
|
|
372
|
+
copied.adopt_workload_identity_auth!(@workload_identity_auth)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
copied
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# @api private
|
|
379
|
+
def adopt_workload_identity_auth!(authenticator)
|
|
380
|
+
identity = @copy_options.fetch(:workload_identity)
|
|
381
|
+
unless x509_identity?(identity) &&
|
|
382
|
+
x509_transport?(@requester) &&
|
|
383
|
+
OpenAI::Auth::X509Transport.exact_instance?(authenticator, OpenAI::Auth::WorkloadIdentityAuth) &&
|
|
384
|
+
authenticator.bound_to?(identity, transport: @requester)
|
|
385
|
+
raise ArgumentError, "X.509 authenticator must match its workload identity and attested transport"
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
@workload_identity_auth = authenticator
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../resources/files"
|
|
4
|
+
require_relative "resource_polling"
|
|
5
|
+
|
|
6
|
+
module OpenAI
|
|
7
|
+
module Resources
|
|
8
|
+
class Files
|
|
9
|
+
# Wait for an uploaded file to finish processing.
|
|
10
|
+
#
|
|
11
|
+
# The returned file may have an `error` status; callers should inspect the
|
|
12
|
+
# status before using it. Polling intervals and the overall timeout are in
|
|
13
|
+
# seconds. Finite timeouts include authentication and request replay time and
|
|
14
|
+
# disable transport retries so the deadline remains strict. Set `timeout` to
|
|
15
|
+
# `nil` to wait indefinitely and retain configured transport retries.
|
|
16
|
+
#
|
|
17
|
+
# @overload wait_for_processing(file_id, poll_interval: nil, timeout: 1800.0, request_options: {})
|
|
18
|
+
#
|
|
19
|
+
# @param file_id [String] The ID of the file to wait for.
|
|
20
|
+
#
|
|
21
|
+
# @param poll_interval [Integer, Float, nil] How often to retrieve the file. When omitted, the SDK honors the server's
|
|
22
|
+
# polling hint and otherwise waits 5 seconds.
|
|
23
|
+
#
|
|
24
|
+
# @param timeout [Integer, Float, nil] Maximum total time to poll. Defaults to 30 minutes. Set to `nil` to wait
|
|
25
|
+
# indefinitely.
|
|
26
|
+
#
|
|
27
|
+
# @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
|
|
28
|
+
#
|
|
29
|
+
# @raise [ArgumentError, OpenAI::Errors::PollingError]
|
|
30
|
+
# @return [OpenAI::Models::FileObject]
|
|
31
|
+
def wait_for_processing(
|
|
32
|
+
file_id,
|
|
33
|
+
poll_interval: nil,
|
|
34
|
+
timeout: OpenAI::Internal::Poller::DEFAULT_TIMEOUT,
|
|
35
|
+
request_options: {}
|
|
36
|
+
)
|
|
37
|
+
OpenAI::Helpers::ResourcePolling.wait_for_file(
|
|
38
|
+
self,
|
|
39
|
+
file_id,
|
|
40
|
+
poll_interval: poll_interval,
|
|
41
|
+
timeout: timeout,
|
|
42
|
+
request_options: request_options
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -63,6 +63,7 @@ module OpenAI
|
|
|
63
63
|
# send session.start and observe session.started before further commands.
|
|
64
64
|
class Connection < OpenAI::WebSocket::Connection
|
|
65
65
|
include OpenAI::WebSocket::Protocol
|
|
66
|
+
include OpenAI::WebSocket::GuardedConnection
|
|
66
67
|
|
|
67
68
|
# @api private
|
|
68
69
|
def initialize(socket:, url:)
|
|
@@ -77,58 +78,6 @@ module OpenAI
|
|
|
77
78
|
send_raw(encode_client_event(event))
|
|
78
79
|
end
|
|
79
80
|
|
|
80
|
-
def closed? = @poisoned || @closed || super
|
|
81
|
-
|
|
82
|
-
def close(code: 1000, reason: "")
|
|
83
|
-
@poisoned || @closed ? abort : super
|
|
84
|
-
@closed = true
|
|
85
|
-
nil
|
|
86
|
-
rescue StandardError
|
|
87
|
-
@poisoned = true
|
|
88
|
-
raise OpenAI::Errors::LiveConnectionError.new(url: @url), cause: nil
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# @api private
|
|
92
|
-
def abort
|
|
93
|
-
super
|
|
94
|
-
@closed = true
|
|
95
|
-
nil
|
|
96
|
-
rescue StandardError
|
|
97
|
-
@poisoned = true
|
|
98
|
-
raise OpenAI::Errors::LiveConnectionError.new(url: @url), cause: nil
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
private def write_text(text)
|
|
102
|
-
complete = false
|
|
103
|
-
super
|
|
104
|
-
complete = true
|
|
105
|
-
nil
|
|
106
|
-
rescue StandardError
|
|
107
|
-
raise OpenAI::Errors::LiveConnectionError.new(url: @url), cause: nil
|
|
108
|
-
ensure
|
|
109
|
-
# Also retire a possibly buffered write when cancellation bypasses
|
|
110
|
-
# StandardError, before another sender or normal cleanup can flush it.
|
|
111
|
-
@poisoned = true unless complete
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
private def read_raw_message
|
|
115
|
-
raise connection_error("Cannot read from a failed Live WebSocket.") if @poisoned
|
|
116
|
-
return nil if @closed
|
|
117
|
-
text = super
|
|
118
|
-
@closed = text.nil?
|
|
119
|
-
text
|
|
120
|
-
rescue StandardError
|
|
121
|
-
@poisoned = true
|
|
122
|
-
raise OpenAI::Errors::LiveConnectionError.new(url: @url), cause: nil
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
private def socket_closed?
|
|
126
|
-
super
|
|
127
|
-
rescue StandardError
|
|
128
|
-
@poisoned = true
|
|
129
|
-
raise OpenAI::Errors::LiveConnectionError.new(url: @url), cause: nil
|
|
130
|
-
end
|
|
131
|
-
|
|
132
81
|
private def encode_client_event(event)
|
|
133
82
|
validate_event_tree!(event)
|
|
134
83
|
payload = OpenAI::Internal::Type::Converter.dump(client_event_type, event)
|
|
@@ -244,6 +193,9 @@ module OpenAI
|
|
|
244
193
|
end
|
|
245
194
|
end
|
|
246
195
|
|
|
196
|
+
private def transport_error = OpenAI::Errors::LiveConnectionError.new(url: @url)
|
|
197
|
+
private def failed_read_message = "Cannot read from a failed Live WebSocket."
|
|
198
|
+
|
|
247
199
|
private def connection_error(message)
|
|
248
200
|
OpenAI::Errors::LiveConnectionError.new(url: @url, message: message)
|
|
249
201
|
end
|
|
@@ -305,8 +257,7 @@ module OpenAI
|
|
|
305
257
|
websocket_base_url = websocket_base_url&.to_s&.dup&.freeze
|
|
306
258
|
build = lambda do |deadline|
|
|
307
259
|
build_shared_websocket_connection_request(
|
|
308
|
-
path: path,
|
|
309
|
-
query: query,
|
|
260
|
+
request: live.__websocket_request(query: query).merge(path: path),
|
|
310
261
|
websocket_base_url: websocket_base_url,
|
|
311
262
|
options: options,
|
|
312
263
|
deadline: deadline,
|
|
@@ -344,7 +295,7 @@ module OpenAI
|
|
|
344
295
|
# not in the URL. This opens only the transport, never starts a session.
|
|
345
296
|
def connect(websocket_base_url: nil, request_options: nil, transport: nil, transport_options: {}, &block)
|
|
346
297
|
open_live_websocket(
|
|
347
|
-
path:
|
|
298
|
+
path: __websocket_request.fetch(:path),
|
|
348
299
|
connection_class: OpenAI::Live::Connection,
|
|
349
300
|
websocket_base_url: websocket_base_url,
|
|
350
301
|
request_options: request_options,
|
|
@@ -429,7 +380,7 @@ class OpenAI::Resources::Live::Sideband
|
|
|
429
380
|
end
|
|
430
381
|
|
|
431
382
|
open_live_websocket(
|
|
432
|
-
path:
|
|
383
|
+
path: __websocket_request(session_id).fetch(:path),
|
|
433
384
|
query: graceful_close.nil? ? {} : {"graceful_close" => graceful_close.to_s},
|
|
434
385
|
connection_class: OpenAI::Live::SidebandConnection,
|
|
435
386
|
websocket_base_url: websocket_base_url,
|
|
@@ -448,7 +399,7 @@ class OpenAI::Resources::Live::Forks
|
|
|
448
399
|
# session: {} to inherit the recording, then wait for session.started.
|
|
449
400
|
def connect(session_id, websocket_base_url: nil, request_options: nil, transport: nil, transport_options: {}, &block)
|
|
450
401
|
open_live_websocket(
|
|
451
|
-
path:
|
|
402
|
+
path: __websocket_request(session_id).fetch(:path),
|
|
452
403
|
connection_class: OpenAI::Live::ForkConnection,
|
|
453
404
|
websocket_base_url: websocket_base_url,
|
|
454
405
|
request_options: request_options,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../models/chat/chat_completion_message"
|
|
4
|
+
require_relative "../../../models/chat/chat_completion_message_function_tool_call"
|
|
5
|
+
|
|
6
|
+
module OpenAI
|
|
7
|
+
module Models
|
|
8
|
+
module Chat
|
|
9
|
+
class ChatCompletionMessage
|
|
10
|
+
response_only do
|
|
11
|
+
# @!attribute parsed
|
|
12
|
+
# The parsed contents of the message, if JSON schema is specified.
|
|
13
|
+
#
|
|
14
|
+
# @return [Object, nil]
|
|
15
|
+
optional :parsed, OpenAI::StructuredOutput::ParsedJson
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class ChatCompletionMessageFunctionToolCall
|
|
20
|
+
class Function
|
|
21
|
+
response_only do
|
|
22
|
+
# @!attribute parsed
|
|
23
|
+
# The parsed contents of the arguments.
|
|
24
|
+
#
|
|
25
|
+
# @return [Object, nil]
|
|
26
|
+
required :parsed, OpenAI::StructuredOutput::ParsedJson
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../models/responses/response_output_text"
|
|
4
|
+
require_relative "../../../models/responses/response_function_tool_call"
|
|
5
|
+
|
|
6
|
+
module OpenAI
|
|
7
|
+
module Models
|
|
8
|
+
module Responses
|
|
9
|
+
class ResponseOutputText
|
|
10
|
+
response_only do
|
|
11
|
+
# @!attribute parsed
|
|
12
|
+
# The parsed contents of the output, if JSON schema is specified.
|
|
13
|
+
#
|
|
14
|
+
# @return [Object, nil]
|
|
15
|
+
optional :parsed, OpenAI::StructuredOutput::ParsedJson
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class ResponseFunctionToolCall
|
|
20
|
+
response_only do
|
|
21
|
+
# @!attribute parsed
|
|
22
|
+
# The parsed contents of the arguments.
|
|
23
|
+
#
|
|
24
|
+
# @return [Object, nil]
|
|
25
|
+
required :parsed, OpenAI::StructuredOutput::ParsedJson
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|