feat: Add force legacy auto-resolve flag (#13804)

# Pull Request Template

## Description

Add account setting and store_accessor for
`captain_force_legacy_auto_resolve`.
Enterprise job now skips LLM evaluation when this flag is true and falls
back to legacy time-based resolution. Add spec to cover the fallback.


## Type of change

We recently rolled out Captain deciding if a conversation is resolved or
not. While it is an improvement for majority of customers, some still
prefer the old way of auto-resolving based on inactivity. This PR adds a
check.

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

legacy_auto_resolve = true

<img width="1282" height="848" alt="CleanShot 2026-03-13 at 19 55 55@2x"
src="https://github.com/user-attachments/assets/dfdcc5d5-6d21-462b-87a6-a5e1b1290a8b"
/>


legacy_auto_resolve = false
<img width="1268" height="864" alt="CleanShot 2026-03-13 at 20 00 50@2x"
src="https://github.com/user-attachments/assets/f4719ec6-922a-4c3b-bc45-7b29eaced565"
/>



## 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
- [x] Any dependent changes have been merged and published in downstream
modules
This commit is contained in:
Aakash Bakhle
2026-03-14 03:34:58 +05:30
committed by GitHub
parent 412b72db7c
commit a90ffe6264
9 changed files with 121 additions and 10 deletions

View File

@@ -41,7 +41,7 @@ class Account < ApplicationRecord
'audio_transcriptions': { 'type': %w[boolean null] },
'auto_resolve_label': { 'type': %w[string null] },
'keep_pending_on_bot_failure': { 'type': %w[boolean null] },
'captain_disable_auto_resolve': { 'type': %w[boolean null] },
'captain_auto_resolve_mode': { 'type': %w[string null], 'enum': ['evaluated', 'legacy', 'disabled', nil] },
'conversation_required_attributes': {
'type': %w[array null],
'items': { 'type': 'string' }
@@ -91,7 +91,8 @@ class Account < ApplicationRecord
store_accessor :settings, :audio_transcriptions, :auto_resolve_label
store_accessor :settings, :captain_models, :captain_features
store_accessor :settings, :keep_pending_on_bot_failure
store_accessor :settings, :captain_disable_auto_resolve
store_accessor :settings, :captain_auto_resolve_mode
include AccountCaptainAutoResolve
has_many :account_users, dependent: :destroy_async
has_many :agent_bot_inboxes, dependent: :destroy_async

View File

@@ -0,0 +1,21 @@
module AccountCaptainAutoResolve
extend ActiveSupport::Concern
VALID_CAPTAIN_AUTO_RESOLVE_MODES = %w[evaluated legacy disabled].freeze
included do
VALID_CAPTAIN_AUTO_RESOLVE_MODES.each do |mode|
define_method("captain_auto_resolve_#{mode}?") do
captain_auto_resolve_mode == mode
end
end
end
def captain_auto_resolve_mode
mode = settings&.[]('captain_auto_resolve_mode')
return mode if VALID_CAPTAIN_AUTO_RESOLVE_MODES.include?(mode)
return 'disabled' if settings&.[]('captain_disable_auto_resolve') == true
feature_enabled?('captain_tasks') ? 'evaluated' : 'legacy'
end
end