diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 773126755..f6c40feb9 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -92,7 +92,10 @@ class Api::V1::AccountsController < Api::BaseController end def settings_params - params.permit(:auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting, :audio_transcriptions, :auto_resolve_label) + permitted = params.permit(:auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting, :audio_transcriptions, :auto_resolve_label) + permitted[:captain_models] = params[:captain_models].to_unsafe_h if params[:captain_models].present? + permitted[:captain_features] = params[:captain_features].to_unsafe_h if params[:captain_features].present? + permitted end def check_signup_enabled diff --git a/app/models/account.rb b/app/models/account.rb index 06767939d..ad14d6fd9 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -53,9 +53,11 @@ class Account < ApplicationRecord validates_with JsonSchemaValidator, schema: SETTINGS_PARAMS_SCHEMA, attribute_resolver: ->(record) { record.settings } + validate :validate_captain_models store_accessor :settings, :auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting store_accessor :settings, :audio_transcriptions, :auto_resolve_label + store_accessor :settings, :captain_models, :captain_features has_many :account_users, dependent: :destroy_async has_many :agent_bot_inboxes, dependent: :destroy_async @@ -159,8 +161,46 @@ class Account < ApplicationRecord ISO_639.find(account_locale)&.english_name&.downcase || 'english' end + def captain_preferences + { + models: captain_models_with_defaults, + features: captain_features_with_defaults + }.with_indifferent_access + end + private + def captain_models_with_defaults + stored_models = captain_models || {} + Llm::ConfigService.feature_keys.each_with_object({}) do |feature_key, result| + stored_value = stored_models[feature_key] + result[feature_key] = if stored_value.present? && Llm::ConfigService.valid_model_for_feature?(feature_key, stored_value) + stored_value + else + Llm::ConfigService.default_model_for_feature(feature_key) + end + end + end + + def captain_features_with_defaults + stored_features = captain_features || {} + Llm::ConfigService.feature_keys.index_with do |feature_key| + stored_features[feature_key] == true + end + end + + def validate_captain_models + return if captain_models.blank? + + captain_models.each do |feature_key, model_name| + next if model_name.blank? + next if Llm::ConfigService.valid_model_for_feature?(feature_key, model_name) + + allowed_models = Llm::ConfigService.models_for_feature(feature_key) + errors.add(:captain_models, "'#{model_name}' is not a valid model for #{feature_key}. Allowed: #{allowed_models.join(', ')}") + end + end + def notify_creation Rails.configuration.dispatcher.dispatch(ACCOUNT_CREATED, Time.zone.now, account: self) end diff --git a/app/views/api/v1/models/_account.json.jbuilder b/app/views/api/v1/models/_account.json.jbuilder index efeff7db5..0221f956a 100644 --- a/app/views/api/v1/models/_account.json.jbuilder +++ b/app/views/api/v1/models/_account.json.jbuilder @@ -25,3 +25,4 @@ json.name @account.name json.support_email @account.support_email json.status @account.status json.cache_keys @account.cache_keys +json.captain_preferences @account.captain_preferences