Files
chatwoot/spec/enterprise/services/llm/base_ai_service_spec.rb
Sony MathewandGitHub cf134deb37 fix: Preserve Captain LLM defaults (#14858)
# Pull Request Template

## Description

Adjusts the Captain LLM feature defaults after feature routing so the
defaults stay intentional and avoid unintended high-cost model upgrades.
Assistant, copilot, and onboarding content generation now default to
`gpt-4.1`; audio transcription keeps `gpt-4o-mini-transcribe` as the
default while exposing `whisper-1` as an available account override
option.

Related: https://linear.app/chatwoot/issue/CW-7425/test-new-models

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- `ruby -ryaml -e 'yaml = YAML.load_file("config/llm.yml"); features =
yaml.fetch("features"); models = yaml.fetch("models"); features.each {
|name, cfg| missing = Array(cfg["models"]) - models.keys; raise
"#{name}: missing #{missing.join(",")}" if missing.any?; raise "#{name}:
default not in models" unless
Array(cfg["models"]).include?(cfg["default"]) }'`
- `node -e
"JSON.parse(require('fs').readFileSync('app/javascript/dashboard/i18n/locale/en/settings.json',
'utf8'))"`
- `pnpm exec prettier --check
app/javascript/dashboard/i18n/locale/en/settings.json`
- `bundle exec rspec spec/lib/llm/feature_router_spec.rb
spec/enterprise/services/llm/base_ai_service_spec.rb
spec/enterprise/models/concerns/agentable_spec.rb
spec/enterprise/services/messages/audio_transcription_service_spec.rb
spec/models/concerns/captain_featurable_spec.rb
spec/models/account_spec.rb
spec/controllers/api/v1/accounts/captain/preferences_controller_spec.rb
spec/controllers/super_admin/accounts_controller_spec.rb`
- `bundle exec rspec
spec/enterprise/services/captain/llm/article_translation_service_spec.rb
spec/enterprise/services/messages/audio_transcription_service_spec.rb
spec/enterprise/services/llm/base_ai_service_spec.rb`
- `RUBOCOP_CACHE_ROOT=/private/tmp/rubocop_cache bundle exec rubocop
enterprise/app/services/captain/llm/article_translation_service.rb
enterprise/app/services/messages/audio_transcription_service.rb
spec/enterprise/services/captain/llm/article_translation_service_spec.rb
spec/enterprise/services/llm/base_ai_service_spec.rb
spec/enterprise/services/messages/audio_transcription_service_spec.rb`
- `git diff --check`

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2026-06-25 21:35:09 +05:30

64 lines
2.3 KiB
Ruby

require 'rails_helper'
RSpec.describe Llm::BaseAiService do
subject(:service) { described_class.new }
let(:account) { create(:account) }
before do
InstallationConfig.where(name: %w[CAPTAIN_OPEN_AI_API_KEY CAPTAIN_OPEN_AI_MODEL]).destroy_all
create(:installation_config, name: 'CAPTAIN_OPEN_AI_API_KEY', value: 'test-key')
end
describe '#initialize' do
it 'uses the installation model when no feature is provided' do
create(:installation_config, name: 'CAPTAIN_OPEN_AI_MODEL', value: 'gpt-4.1-nano')
expect(described_class.new.model).to eq('gpt-4.1-nano')
end
it 'uses the account override when feature context is provided' do
create(:installation_config, name: 'CAPTAIN_OPEN_AI_MODEL', value: 'gpt-4.1-nano')
account.update!(captain_models: { 'assistant' => 'gpt-5.2' })
expect(described_class.new(feature: 'assistant', account: account).model).to eq('gpt-5.2')
end
it 'uses the installation model when feature context has no account override' do
create(:installation_config, name: 'CAPTAIN_OPEN_AI_MODEL', value: 'gpt-4.1-nano')
expect(described_class.new(feature: 'assistant', account: account).model).to eq('gpt-4.1-nano')
end
it 'uses the feature default when feature context has no account override or installation model' do
expect(described_class.new(feature: 'assistant', account: account).model).to eq(Llm::Models.default_model_for('assistant'))
end
end
describe '#sanitize_json_response' do
it 'strips ```json fences' do
input = "```json\n{\"key\": \"value\"}\n```"
expect(service.send(:sanitize_json_response, input)).to eq('{"key": "value"}')
end
it 'strips bare ``` fences' do
input = "```\n{\"key\": \"value\"}\n```"
expect(service.send(:sanitize_json_response, input)).to eq('{"key": "value"}')
end
it 'passes through plain JSON unchanged' do
input = '{"key": "value"}'
expect(service.send(:sanitize_json_response, input)).to eq('{"key": "value"}')
end
it 'returns nil for nil input' do
expect(service.send(:sanitize_json_response, nil)).to be_nil
end
it 'strips surrounding whitespace' do
input = " \n{\"key\": \"value\"}\n "
expect(service.send(:sanitize_json_response, input)).to eq('{"key": "value"}')
end
end
end