diff --git a/app/models/concerns/reauthorizable.rb b/app/models/concerns/reauthorizable.rb index 7a09f6436..0845c181b 100644 --- a/app/models/concerns/reauthorizable.rb +++ b/app/models/concerns/reauthorizable.rb @@ -49,6 +49,8 @@ module Reauthorizable AdministratorNotifications::IntegrationsNotificationMailer.with(account: account).slack_disconnect.deliver_later elsif dialogflow? AdministratorNotifications::IntegrationsNotificationMailer.with(account: account).dialogflow_disconnect.deliver_later + elsif openai? + AdministratorNotifications::IntegrationsNotificationMailer.with(account: account).openai_disconnect.deliver_later end end diff --git a/app/models/integrations/hook.rb b/app/models/integrations/hook.rb index 97d3f91ae..913e06112 100644 --- a/app/models/integrations/hook.rb +++ b/app/models/integrations/hook.rb @@ -60,6 +60,10 @@ class Integrations::Hook < ApplicationRecord app_id == 'notion' end + def openai? + app_id == 'openai' + end + def disable update(status: 'disabled') end diff --git a/app/views/api/v1/models/_hook.json.jbuilder b/app/views/api/v1/models/_hook.json.jbuilder index 5df214ac8..4c4bf447e 100644 --- a/app/views/api/v1/models/_hook.json.jbuilder +++ b/app/views/api/v1/models/_hook.json.jbuilder @@ -4,6 +4,7 @@ json.status resource.enabled? json.inbox resource.inbox&.slice(:id, :name) json.account_id resource.account_id json.hook_type resource.hook_type +json.reauthorization_required resource.reauthorization_required? json.settings resource.settings if Current.account_user&.administrator? json.reference_id resource.reference_id if Current.account_user&.administrator? diff --git a/lib/integrations/llm_base_service.rb b/lib/integrations/llm_base_service.rb index ca9459fc8..bc34ffb17 100644 --- a/lib/integrations/llm_base_service.rb +++ b/lib/integrations/llm_base_service.rb @@ -96,6 +96,9 @@ class Integrations::LlmBaseService end end + RATE_LIMIT_ERRORS = [RubyLLM::RateLimitError].freeze + AUTH_ERRORS = [RubyLLM::UnauthorizedError, RubyLLM::PaymentRequiredError, RubyLLM::ForbiddenError].freeze + def execute_ruby_llm_request(parsed_body) messages = parsed_body['messages'] model = parsed_body['model'] @@ -104,11 +107,26 @@ class Integrations::LlmBaseService chat = context.chat(model: model) setup_chat_with_messages(chat, messages) end + rescue *RATE_LIMIT_ERRORS => e + handle_rate_limit_error(e, messages) + rescue *AUTH_ERRORS => e + handle_auth_error(e, messages) rescue StandardError => e ChatwootExceptionTracker.new(e, account: hook.account).capture_exception build_error_response_from_exception(e, messages) end + def handle_rate_limit_error(error, messages) + Rails.logger.warn "[LLM] Rate limit error for hook #{hook.id}: #{error.message}" + build_error_response_from_exception(error, messages, error_type: 'rate_limit') + end + + def handle_auth_error(error, messages) + Rails.logger.warn "[LLM] Auth error for hook #{hook.id}: #{error.class} - #{error.message}" + hook.authorization_error! + build_error_response_from_exception(error, messages, error_type: 'auth') + end + def setup_chat_with_messages(chat, messages) apply_system_instructions(chat, messages) response = send_conversation_messages(chat, messages) @@ -163,7 +181,9 @@ class Integrations::LlmBaseService } end - def build_error_response_from_exception(error, messages) - { error: error.message, request_messages: messages } + def build_error_response_from_exception(error, messages, error_type: nil) + response = { error: error.message, request_messages: messages } + response[:error_type] = error_type if error_type + response end end