diff --git a/README.md b/README.md index 316ac3f6..fa326448 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ When the library is unable to connect to the API, or if the API returns a non-su ```ruby begin job = openai.fine_tuning.jobs.create(model: "gpt-4o", training_file: "file-abc123") -rescue OpenAI::Error => e +rescue OpenAI::Errors::APIError => e puts(e.status) # 400 end ``` @@ -103,7 +103,7 @@ Error codes are as followed: | HTTP 409 | `ConflictError` | | HTTP 422 | `UnprocessableEntityError` | | HTTP 429 | `RateLimitError` | -| HTTP >=500 | `InternalServerError` | +| HTTP >= 500 | `InternalServerError` | | Other HTTP error | `APIStatusError` | | Timeout | `APITimeoutError` | | Network error | `APIConnectionError` | diff --git a/lib/openai/errors.rb b/lib/openai/errors.rb index ad1e9852..bc67421d 100644 --- a/lib/openai/errors.rb +++ b/lib/openai/errors.rb @@ -1,219 +1,256 @@ # frozen_string_literal: true module OpenAI - class Error < StandardError - # @!parse - # # @return [StandardError, nil] - # attr_accessor :cause - end + module Errors + class Error < StandardError + # @!parse + # # @return [StandardError, nil] + # attr_accessor :cause + end - class ConversionError < OpenAI::Error - end + class ConversionError < OpenAI::Errors::Error + end + + class APIError < OpenAI::Errors::Error + # @return [URI::Generic] + attr_accessor :url + + # @return [Integer, nil] + attr_accessor :status + + # @return [Object, nil] + attr_accessor :body + + # @return [String, nil] + attr_accessor :code - class APIError < OpenAI::Error - # @return [URI::Generic] - attr_accessor :url - - # @return [Integer, nil] - attr_accessor :status - - # @return [Object, nil] - attr_accessor :body - - # @return [String, nil] - attr_accessor :code - - # @return [String, nil] - attr_accessor :param - - # @return [String, nil] - attr_accessor :type - - # @api private - # - # @param url [URI::Generic] - # @param status [Integer, nil] - # @param body [Object, nil] - # @param request [nil] - # @param response [nil] - # @param message [String, nil] - def initialize(url:, status: nil, body: nil, request: nil, response: nil, message: nil) - @url = url - @status = status - @body = body - @request = request - @response = response - super(message) + # @return [String, nil] + attr_accessor :param + + # @return [String, nil] + attr_accessor :type + + # @api private + # + # @param url [URI::Generic] + # @param status [Integer, nil] + # @param body [Object, nil] + # @param request [nil] + # @param response [nil] + # @param message [String, nil] + def initialize(url:, status: nil, body: nil, request: nil, response: nil, message: nil) + @url = url + @status = status + @body = body + @request = request + @response = response + super(message) + end end - end - class APIConnectionError < OpenAI::APIError - # @!parse - # # @return [nil] - # attr_accessor :status - - # @!parse - # # @return [nil] - # attr_accessor :body - - # @!parse - # # @return [nil] - # attr_accessor :code - - # @!parse - # # @return [nil] - # attr_accessor :param - - # @!parse - # # @return [nil] - # attr_accessor :type - - # @api private - # - # @param url [URI::Generic] - # @param status [nil] - # @param body [nil] - # @param request [nil] - # @param response [nil] - # @param message [String, nil] - def initialize( - url:, - status: nil, - body: nil, - request: nil, - response: nil, - message: "Connection error." - ) - super + class APIConnectionError < OpenAI::Errors::APIError + # @!parse + # # @return [nil] + # attr_accessor :status + + # @!parse + # # @return [nil] + # attr_accessor :body + + # @!parse + # # @return [nil] + # attr_accessor :code + + # @!parse + # # @return [nil] + # attr_accessor :param + + # @!parse + # # @return [nil] + # attr_accessor :type + + # @api private + # + # @param url [URI::Generic] + # @param status [nil] + # @param body [nil] + # @param request [nil] + # @param response [nil] + # @param message [String, nil] + def initialize( + url:, + status: nil, + body: nil, + request: nil, + response: nil, + message: "Connection error." + ) + super + end end - end - class APITimeoutError < OpenAI::APIConnectionError - # @api private - # - # @param url [URI::Generic] - # @param status [nil] - # @param body [nil] - # @param request [nil] - # @param response [nil] - # @param message [String, nil] - def initialize( - url:, - status: nil, - body: nil, - request: nil, - response: nil, - message: "Request timed out." - ) - super + class APITimeoutError < OpenAI::Errors::APIConnectionError + # @api private + # + # @param url [URI::Generic] + # @param status [nil] + # @param body [nil] + # @param request [nil] + # @param response [nil] + # @param message [String, nil] + def initialize( + url:, + status: nil, + body: nil, + request: nil, + response: nil, + message: "Request timed out." + ) + super + end end - end - class APIStatusError < OpenAI::APIError - # @api private - # - # @param url [URI::Generic] - # @param status [Integer] - # @param body [Object, nil] - # @param request [nil] - # @param response [nil] - # @param message [String, nil] - # - # @return [OpenAI::APIStatusError] - def self.for(url:, status:, body:, request:, response:, message: nil) - kwargs = {url: url, status: status, body: body, request: request, response: response, message: message} - - case status - in 400 - OpenAI::BadRequestError.new(**kwargs) - in 401 - OpenAI::AuthenticationError.new(**kwargs) - in 403 - OpenAI::PermissionDeniedError.new(**kwargs) - in 404 - OpenAI::NotFoundError.new(**kwargs) - in 409 - OpenAI::ConflictError.new(**kwargs) - in 422 - OpenAI::UnprocessableEntityError.new(**kwargs) - in 429 - OpenAI::RateLimitError.new(**kwargs) - in (500..) - OpenAI::InternalServerError.new(**kwargs) - else - OpenAI::APIStatusError.new(**kwargs) + class APIStatusError < OpenAI::Errors::APIError + # @api private + # + # @param url [URI::Generic] + # @param status [Integer] + # @param body [Object, nil] + # @param request [nil] + # @param response [nil] + # @param message [String, nil] + # + # @return [OpenAI::Errors::APIStatusError] + def self.for(url:, status:, body:, request:, response:, message: nil) + kwargs = { + url: url, + status: status, + body: body, + request: request, + response: response, + message: message + } + + case status + in 400 + OpenAI::Errors::BadRequestError.new(**kwargs) + in 401 + OpenAI::Errors::AuthenticationError.new(**kwargs) + in 403 + OpenAI::Errors::PermissionDeniedError.new(**kwargs) + in 404 + OpenAI::Errors::NotFoundError.new(**kwargs) + in 409 + OpenAI::Errors::ConflictError.new(**kwargs) + in 422 + OpenAI::Errors::UnprocessableEntityError.new(**kwargs) + in 429 + OpenAI::Errors::RateLimitError.new(**kwargs) + in (500..) + OpenAI::Errors::InternalServerError.new(**kwargs) + else + OpenAI::Errors::APIStatusError.new(**kwargs) + end + end + + # @!parse + # # @return [Integer] + # attr_accessor :status + + # @!parse + # # @return [String, nil] + # attr_accessor :code + + # @!parse + # # @return [String, nil] + # attr_accessor :param + + # @!parse + # # @return [String, nil] + # attr_accessor :type + + # @api private + # + # @param url [URI::Generic] + # @param status [Integer] + # @param body [Object, nil] + # @param request [nil] + # @param response [nil] + # @param message [String, nil] + def initialize(url:, status:, body:, request:, response:, message: nil) + message ||= OpenAI::Util.dig(body, :message) { {url: url.to_s, status: status, body: body} } + @code = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :code)) + @param = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :param)) + @type = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :type)) + super( + url: url, + status: status, + body: body, + request: request, + response: response, + message: message&.to_s + ) end end - # @!parse - # # @return [Integer] - # attr_accessor :status - - # @!parse - # # @return [String, nil] - # attr_accessor :code - - # @!parse - # # @return [String, nil] - # attr_accessor :param - - # @!parse - # # @return [String, nil] - # attr_accessor :type - - # @api private - # - # @param url [URI::Generic] - # @param status [Integer] - # @param body [Object, nil] - # @param request [nil] - # @param response [nil] - # @param message [String, nil] - def initialize(url:, status:, body:, request:, response:, message: nil) - message ||= OpenAI::Util.dig(body, :message) { {url: url.to_s, status: status, body: body} } - @code = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :code)) - @param = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :param)) - @type = OpenAI::Type::Converter.coerce(String, OpenAI::Util.dig(body, :type)) - super( - url: url, - status: status, - body: body, - request: request, - response: response, - message: message&.to_s - ) + class BadRequestError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 400 end - end - class BadRequestError < OpenAI::APIStatusError - HTTP_STATUS = 400 - end + class AuthenticationError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 401 + end - class AuthenticationError < OpenAI::APIStatusError - HTTP_STATUS = 401 - end + class PermissionDeniedError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 403 + end - class PermissionDeniedError < OpenAI::APIStatusError - HTTP_STATUS = 403 - end + class NotFoundError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 404 + end - class NotFoundError < OpenAI::APIStatusError - HTTP_STATUS = 404 - end + class ConflictError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 409 + end - class ConflictError < OpenAI::APIStatusError - HTTP_STATUS = 409 - end + class UnprocessableEntityError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 422 + end - class UnprocessableEntityError < OpenAI::APIStatusError - HTTP_STATUS = 422 - end + class RateLimitError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 429 + end - class RateLimitError < OpenAI::APIStatusError - HTTP_STATUS = 429 + class InternalServerError < OpenAI::Errors::APIStatusError + HTTP_STATUS = (500..) + end end - class InternalServerError < OpenAI::APIStatusError - HTTP_STATUS = (500..) - end + Error = OpenAI::Errors::Error + + ConversionError = OpenAI::Errors::ConversionError + + APIError = OpenAI::Errors::APIError + + APIStatusError = OpenAI::Errors::APIStatusError + + APIConnectionError = OpenAI::Errors::APIConnectionError + + APITimeoutError = OpenAI::Errors::APITimeoutError + + BadRequestError = OpenAI::Errors::BadRequestError + + AuthenticationError = OpenAI::Errors::AuthenticationError + + PermissionDeniedError = OpenAI::Errors::PermissionDeniedError + + NotFoundError = OpenAI::Errors::NotFoundError + + ConflictError = OpenAI::Errors::ConflictError + + UnprocessableEntityError = OpenAI::Errors::UnprocessableEntityError + + RateLimitError = OpenAI::Errors::RateLimitError + + InternalServerError = OpenAI::Errors::InternalServerError end diff --git a/lib/openai/stream.rb b/lib/openai/stream.rb index d3be1bd5..9c6f4244 100644 --- a/lib/openai/stream.rb +++ b/lib/openai/stream.rb @@ -46,7 +46,7 @@ class Stream else "An error occurred during streaming" end - OpenAI::APIError.for( + OpenAI::Errors::APIError.for( url: @url, status: @status, body: body, diff --git a/lib/openai/transport/base_client.rb b/lib/openai/transport/base_client.rb index fb9321c1..3679bf42 100644 --- a/lib/openai/transport/base_client.rb +++ b/lib/openai/transport/base_client.rb @@ -92,7 +92,7 @@ def follow_redirect(request, status:, response_headers:) URI.join(url, response_headers["location"]) rescue ArgumentError message = "Server responded with status #{status} but no valid location header." - raise OpenAI::APIConnectionError.new(url: url, message: message) + raise OpenAI::Errors::APIConnectionError.new(url: url, message: message) end request = {**request, url: location} @@ -100,7 +100,7 @@ def follow_redirect(request, status:, response_headers:) case [url.scheme, location.scheme] in ["https", "http"] message = "Tried to redirect to a insecure URL" - raise OpenAI::APIConnectionError.new(url: url, message: message) + raise OpenAI::Errors::APIConnectionError.new(url: url, message: message) else nil end @@ -129,13 +129,13 @@ def follow_redirect(request, status:, response_headers:) # @api private # - # @param status [Integer, OpenAI::APIConnectionError] + # @param status [Integer, OpenAI::Errors::APIConnectionError] # @param stream [Enumerable, nil] def reap_connection!(status, stream:) case status in (..199) | (300..499) stream&.each { next } - in OpenAI::APIConnectionError | (500..) + in OpenAI::Errors::APIConnectionError | (500..) OpenAI::Util.close_fused!(stream) else end @@ -326,7 +326,7 @@ def initialize( # # @param send_retry_header [Boolean] # - # @raise [OpenAI::APIError] + # @raise [OpenAI::Errors::APIError] # @return [Array(Integer, Net::HTTPResponse, Enumerable)] private def send_request(request, redirect_count:, retry_count:, send_retry_header:) url, headers, max_retries, timeout = request.fetch_values(:url, :headers, :max_retries, :timeout) @@ -349,7 +349,7 @@ def initialize( self.class.reap_connection!(status, stream: stream) message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects." - raise OpenAI::APIConnectionError.new(url: url, message: message) + raise OpenAI::Errors::APIConnectionError.new(url: url, message: message) in 300..399 self.class.reap_connection!(status, stream: stream) @@ -369,14 +369,14 @@ def initialize( self.class.reap_connection!(status, stream: stream) end - raise OpenAI::APIStatusError.for( + raise OpenAI::Errors::APIStatusError.for( url: url, status: status, body: decoded, request: nil, response: response ) - in (400..) | OpenAI::APIConnectionError + in (400..) | OpenAI::Errors::APIConnectionError self.class.reap_connection!(status, stream: stream) delay = retry_delay(response, retry_count: retry_count) @@ -416,7 +416,7 @@ def initialize( # # @option req [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil] :options # - # @raise [OpenAI::APIError] + # @raise [OpenAI::Errors::APIError] # @return [Object] def request(req) self.class.validate!(req) diff --git a/lib/openai/transport/pooled_net_requester.rb b/lib/openai/transport/pooled_net_requester.rb index 57c8bf5e..b3259684 100644 --- a/lib/openai/transport/pooled_net_requester.rb +++ b/lib/openai/transport/pooled_net_requester.rb @@ -153,7 +153,7 @@ def execute(request) end end rescue Timeout::Error - raise OpenAI::APITimeoutError + raise OpenAI::Errors::APITimeoutError end conn, _, response = enum.next diff --git a/lib/openai/type/base_page.rb b/lib/openai/type/base_page.rb index 5f9ee0fa..a98b0624 100644 --- a/lib/openai/type/base_page.rb +++ b/lib/openai/type/base_page.rb @@ -29,7 +29,7 @@ module BasePage # @return [Boolean] def next_page? = (raise NotImplementedError) - # @raise [OpenAI::APIError] + # @raise [OpenAI::Errors::APIError] # @return [OpenAI::Type::BasePage] def next_page = (raise NotImplementedError) diff --git a/rbi/lib/openai/errors.rbi b/rbi/lib/openai/errors.rbi index e010e283..d04fc102 100644 --- a/rbi/lib/openai/errors.rbi +++ b/rbi/lib/openai/errors.rbi @@ -1,171 +1,201 @@ # typed: strong module OpenAI - class Error < StandardError - sig { returns(T.nilable(StandardError)) } - attr_accessor :cause - end - - class ConversionError < OpenAI::Error - end - - class APIError < OpenAI::Error - sig { returns(URI::Generic) } - attr_accessor :url - - sig { returns(T.nilable(Integer)) } - attr_accessor :status - - sig { returns(T.nilable(T.anything)) } - attr_accessor :body + module Errors + class Error < StandardError + sig { returns(T.nilable(StandardError)) } + attr_accessor :cause + end - sig { returns(T.nilable(String)) } - attr_accessor :code + class ConversionError < OpenAI::Errors::Error + end - sig { returns(T.nilable(String)) } - attr_accessor :param + class APIError < OpenAI::Errors::Error + sig { returns(URI::Generic) } + attr_accessor :url + + sig { returns(T.nilable(Integer)) } + attr_accessor :status + + sig { returns(T.nilable(T.anything)) } + attr_accessor :body + + sig { returns(T.nilable(String)) } + attr_accessor :code + + sig { returns(T.nilable(String)) } + attr_accessor :param + + sig { returns(T.nilable(String)) } + attr_accessor :type + + # @api private + sig do + params( + url: URI::Generic, + status: T.nilable(Integer), + body: T.nilable(Object), + request: NilClass, + response: NilClass, + message: T.nilable(String) + ) + .returns(T.attached_class) + end + def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: nil) + end + end - sig { returns(T.nilable(String)) } - attr_accessor :type + class APIConnectionError < OpenAI::Errors::APIError + sig { void } + attr_accessor :status + + sig { void } + attr_accessor :body + + sig { void } + attr_accessor :code + + sig { void } + attr_accessor :param + + sig { void } + attr_accessor :type + + # @api private + sig do + params( + url: URI::Generic, + status: NilClass, + body: NilClass, + request: NilClass, + response: NilClass, + message: T.nilable(String) + ) + .returns(T.attached_class) + end + def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: "Connection error.") + end + end - # @api private - sig do - params( - url: URI::Generic, - status: T.nilable(Integer), - body: T.nilable(Object), - request: NilClass, - response: NilClass, - message: T.nilable(String) - ) - .returns(T.attached_class) + class APITimeoutError < OpenAI::Errors::APIConnectionError + # @api private + sig do + params( + url: URI::Generic, + status: NilClass, + body: NilClass, + request: NilClass, + response: NilClass, + message: T.nilable(String) + ) + .returns(T.attached_class) + end + def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: "Request timed out.") + end end - def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: nil) + + class APIStatusError < OpenAI::Errors::APIError + # @api private + sig do + params( + url: URI::Generic, + status: Integer, + body: T.nilable(Object), + request: NilClass, + response: NilClass, + message: T.nilable(String) + ) + .returns(T.attached_class) + end + def self.for(url:, status:, body:, request:, response:, message: nil) + end + + sig { returns(Integer) } + attr_accessor :status + + sig { returns(T.nilable(String)) } + attr_accessor :code + + sig { returns(T.nilable(String)) } + attr_accessor :param + + sig { returns(T.nilable(String)) } + attr_accessor :type + + # @api private + sig do + params( + url: URI::Generic, + status: Integer, + body: T.nilable(Object), + request: NilClass, + response: NilClass, + message: T.nilable(String) + ) + .returns(T.attached_class) + end + def self.new(url:, status:, body:, request:, response:, message: nil) + end end - end - class APIConnectionError < OpenAI::APIError - sig { void } - attr_accessor :status - - sig { void } - attr_accessor :body - - sig { void } - attr_accessor :code - - sig { void } - attr_accessor :param - - sig { void } - attr_accessor :type - - # @api private - sig do - params( - url: URI::Generic, - status: NilClass, - body: NilClass, - request: NilClass, - response: NilClass, - message: T.nilable(String) - ) - .returns(T.attached_class) + class BadRequestError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 400 end - def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: "Connection error.") + + class AuthenticationError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 401 end - end - class APITimeoutError < OpenAI::APIConnectionError - # @api private - sig do - params( - url: URI::Generic, - status: NilClass, - body: NilClass, - request: NilClass, - response: NilClass, - message: T.nilable(String) - ) - .returns(T.attached_class) + class PermissionDeniedError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 403 end - def self.new(url:, status: nil, body: nil, request: nil, response: nil, message: "Request timed out.") + + class NotFoundError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 404 end - end - class APIStatusError < OpenAI::APIError - # @api private - sig do - params( - url: URI::Generic, - status: Integer, - body: T.nilable(Object), - request: NilClass, - response: NilClass, - message: T.nilable(String) - ) - .returns(T.attached_class) + class ConflictError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 409 end - def self.for(url:, status:, body:, request:, response:, message: nil) + + class UnprocessableEntityError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 422 end - sig { returns(Integer) } - attr_accessor :status - - sig { returns(T.nilable(String)) } - attr_accessor :code - - sig { returns(T.nilable(String)) } - attr_accessor :param - - sig { returns(T.nilable(String)) } - attr_accessor :type - - # @api private - sig do - params( - url: URI::Generic, - status: Integer, - body: T.nilable(Object), - request: NilClass, - response: NilClass, - message: T.nilable(String) - ) - .returns(T.attached_class) + class RateLimitError < OpenAI::Errors::APIStatusError + HTTP_STATUS = 429 end - def self.new(url:, status:, body:, request:, response:, message: nil) + + class InternalServerError < OpenAI::Errors::APIStatusError + HTTP_STATUS = T.let((500..), T::Range[Integer]) end end - class BadRequestError < OpenAI::APIStatusError - HTTP_STATUS = 400 - end + Error = OpenAI::Errors::Error - class AuthenticationError < OpenAI::APIStatusError - HTTP_STATUS = 401 - end + ConversionError = OpenAI::Errors::ConversionError - class PermissionDeniedError < OpenAI::APIStatusError - HTTP_STATUS = 403 - end + APIError = OpenAI::Errors::APIError - class NotFoundError < OpenAI::APIStatusError - HTTP_STATUS = 404 - end + APIStatusError = OpenAI::Errors::APIStatusError - class ConflictError < OpenAI::APIStatusError - HTTP_STATUS = 409 - end + APIConnectionError = OpenAI::Errors::APIConnectionError - class UnprocessableEntityError < OpenAI::APIStatusError - HTTP_STATUS = 422 - end + APITimeoutError = OpenAI::Errors::APITimeoutError - class RateLimitError < OpenAI::APIStatusError - HTTP_STATUS = 429 - end + BadRequestError = OpenAI::Errors::BadRequestError - class InternalServerError < OpenAI::APIStatusError - HTTP_STATUS = T.let((500..), T::Range[Integer]) - end + AuthenticationError = OpenAI::Errors::AuthenticationError + + PermissionDeniedError = OpenAI::Errors::PermissionDeniedError + + NotFoundError = OpenAI::Errors::NotFoundError + + ConflictError = OpenAI::Errors::ConflictError + + UnprocessableEntityError = OpenAI::Errors::UnprocessableEntityError + + RateLimitError = OpenAI::Errors::RateLimitError + + InternalServerError = OpenAI::Errors::InternalServerError end diff --git a/rbi/lib/openai/transport/base_client.rbi b/rbi/lib/openai/transport/base_client.rbi index 7deae432..c8afd87e 100644 --- a/rbi/lib/openai/transport/base_client.rbi +++ b/rbi/lib/openai/transport/base_client.rbi @@ -82,9 +82,10 @@ module OpenAI # @api private sig do params( - status: T.any(Integer, OpenAI::APIConnectionError), + status: T.any(Integer, OpenAI::Errors::APIConnectionError), stream: T.nilable(T::Enumerable[String]) - ).void + ) + .void end def reap_connection!(status, stream:) end diff --git a/sig/openai/errors.rbs b/sig/openai/errors.rbs index 6d5804f3..8dc6afce 100644 --- a/sig/openai/errors.rbs +++ b/sig/openai/errors.rbs @@ -1,105 +1,135 @@ module OpenAI - class Error < StandardError - attr_accessor cause: StandardError? + module Errors + class Error < StandardError + attr_accessor cause: StandardError? + end + + class ConversionError < OpenAI::Errors::Error + end + + class APIError < OpenAI::Errors::Error + attr_accessor url: URI::Generic + + attr_accessor status: Integer? + + attr_accessor body: top? + + attr_accessor code: String? + + attr_accessor param: String? + + attr_accessor type: String? + + def initialize: ( + url: URI::Generic, + ?status: Integer?, + ?body: Object?, + ?request: nil, + ?response: nil, + ?message: String? + ) -> void + end + + class APIConnectionError < OpenAI::Errors::APIError + def initialize: ( + url: URI::Generic, + ?status: nil, + ?body: nil, + ?request: nil, + ?response: nil, + ?message: String? + ) -> void + end + + class APITimeoutError < OpenAI::Errors::APIConnectionError + def initialize: ( + url: URI::Generic, + ?status: nil, + ?body: nil, + ?request: nil, + ?response: nil, + ?message: String? + ) -> void + end + + class APIStatusError < OpenAI::Errors::APIError + def self.for: ( + url: URI::Generic, + status: Integer, + body: Object?, + request: nil, + response: nil, + ?message: String? + ) -> instance + + def initialize: ( + url: URI::Generic, + status: Integer, + body: Object?, + request: nil, + response: nil, + ?message: String? + ) -> void + end + + class BadRequestError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 400 + end + + class AuthenticationError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 401 + end + + class PermissionDeniedError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 403 + end + + class NotFoundError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 404 + end + + class ConflictError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 409 + end + + class UnprocessableEntityError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 422 + end + + class RateLimitError < OpenAI::Errors::APIStatusError + HTTP_STATUS: 429 + end + + class InternalServerError < OpenAI::Errors::APIStatusError + HTTP_STATUS: Range[Integer] + end end - class ConversionError < OpenAI::Error - end - - class APIError < OpenAI::Error - attr_accessor url: URI::Generic - - attr_accessor status: Integer? + class Error = OpenAI::Errors::Error - attr_accessor body: top? + class ConversionError = OpenAI::Errors::ConversionError - attr_accessor code: String? + class APIError = OpenAI::Errors::APIError - attr_accessor param: String? + class APIStatusError = OpenAI::Errors::APIStatusError - attr_accessor type: String? - - def initialize: ( - url: URI::Generic, - ?status: Integer?, - ?body: Object?, - ?request: nil, - ?response: nil, - ?message: String? - ) -> void - end - - class APIConnectionError < OpenAI::APIError - def initialize: ( - url: URI::Generic, - ?status: nil, - ?body: nil, - ?request: nil, - ?response: nil, - ?message: String? - ) -> void - end - - class APITimeoutError < OpenAI::APIConnectionError - def initialize: ( - url: URI::Generic, - ?status: nil, - ?body: nil, - ?request: nil, - ?response: nil, - ?message: String? - ) -> void - end + class APIConnectionError = OpenAI::Errors::APIConnectionError - class APIStatusError < OpenAI::APIError - def self.for: ( - url: URI::Generic, - status: Integer, - body: Object?, - request: nil, - response: nil, - ?message: String? - ) -> instance - - def initialize: ( - url: URI::Generic, - status: Integer, - body: Object?, - request: nil, - response: nil, - ?message: String? - ) -> void - end + class APITimeoutError = OpenAI::Errors::APITimeoutError - class BadRequestError < OpenAI::APIStatusError - HTTP_STATUS: 400 - end + class BadRequestError = OpenAI::Errors::BadRequestError - class AuthenticationError < OpenAI::APIStatusError - HTTP_STATUS: 401 - end + class AuthenticationError = OpenAI::Errors::AuthenticationError - class PermissionDeniedError < OpenAI::APIStatusError - HTTP_STATUS: 403 - end + class PermissionDeniedError = OpenAI::Errors::PermissionDeniedError - class NotFoundError < OpenAI::APIStatusError - HTTP_STATUS: 404 - end + class NotFoundError = OpenAI::Errors::NotFoundError - class ConflictError < OpenAI::APIStatusError - HTTP_STATUS: 409 - end + class ConflictError = OpenAI::Errors::ConflictError - class UnprocessableEntityError < OpenAI::APIStatusError - HTTP_STATUS: 422 - end + class UnprocessableEntityError = OpenAI::Errors::UnprocessableEntityError - class RateLimitError < OpenAI::APIStatusError - HTTP_STATUS: 429 - end + class RateLimitError = OpenAI::Errors::RateLimitError - class InternalServerError < OpenAI::APIStatusError - HTTP_STATUS: Range[Integer] - end + class InternalServerError = OpenAI::Errors::InternalServerError end diff --git a/sig/openai/transport/base_client.rbs b/sig/openai/transport/base_client.rbs index 4ae59a76..724f235c 100644 --- a/sig/openai/transport/base_client.rbs +++ b/sig/openai/transport/base_client.rbs @@ -47,7 +47,7 @@ module OpenAI ) -> OpenAI::Transport::BaseClient::request_input def self.reap_connection!: ( - Integer | OpenAI::APIConnectionError status, + Integer | OpenAI::Errors::APIConnectionError status, stream: Enumerable[String]? ) -> void diff --git a/test/openai/base_model_test.rb b/test/openai/base_model_test.rb index 7238cd06..737cb8fa 100644 --- a/test/openai/base_model_test.rb +++ b/test/openai/base_model_test.rb @@ -390,7 +390,7 @@ def test_accessors tap do target.public_send(accessor) flunk - rescue OpenAI::ConversionError => e + rescue OpenAI::Errors::ConversionError => e assert_kind_of(expect, e.cause) end else diff --git a/test/openai/client_test.rb b/test/openai/client_test.rb index cbb0c21d..6b35af97 100644 --- a/test/openai/client_test.rb +++ b/test/openai/client_test.rb @@ -199,7 +199,7 @@ def test_client_redirect_307 requester = MockRequester.new(307, {"location" => "/redirected"}, {}) openai.requester = requester - assert_raises(OpenAI::APIConnectionError) do + assert_raises(OpenAI::Errors::APIConnectionError) do openai.chat.completions.create( messages: [{content: "string", role: :developer}], model: :"o3-mini", @@ -221,7 +221,7 @@ def test_client_redirect_303 requester = MockRequester.new(303, {"location" => "/redirected"}, {}) openai.requester = requester - assert_raises(OpenAI::APIConnectionError) do + assert_raises(OpenAI::Errors::APIConnectionError) do openai.chat.completions.create( messages: [{content: "string", role: :developer}], model: :"o3-mini", @@ -240,7 +240,7 @@ def test_client_redirect_auth_keep_same_origin requester = MockRequester.new(307, {"location" => "/redirected"}, {}) openai.requester = requester - assert_raises(OpenAI::APIConnectionError) do + assert_raises(OpenAI::Errors::APIConnectionError) do openai.chat.completions.create( messages: [{content: "string", role: :developer}], model: :"o3-mini", @@ -259,7 +259,7 @@ def test_client_redirect_auth_strip_cross_origin requester = MockRequester.new(307, {"location" => "https://example.com/redirected"}, {}) openai.requester = requester - assert_raises(OpenAI::APIConnectionError) do + assert_raises(OpenAI::Errors::APIConnectionError) do openai.chat.completions.create( messages: [{content: "string", role: :developer}], model: :"o3-mini",