Captain auto-resolve policy is now owned by each assistant. Existing assistants first read an assistant-level setting, fall back to the current account setting during rollout, and are backfilled asynchronously so behavior is preserved. ## Closes [AI-163](https://linear.app/chatwoot/issue/AI-163) ## How to test 1. Configure different auto-resolve modes on two assistants in the same account through the API. 2. Confirm each assistant follows its own mode when the inactivity job runs. 3. Confirm an assistant without the new setting follows the existing account mode. 4. Run the migration job and confirm the account mode is copied without overwriting an existing assistant mode. 5. Confirm evaluated mode falls back to time-based resolution when the `captain_tasks` capability is unavailable. ## What changed - Added assistant-level `disabled`, `legacy`, and `evaluated` policy storage and validation. - Updated scheduling and resolution runtime reads to use the assistant policy. - Added a compatibility fallback and asynchronous backfill from the account setting. - Preserved the account-level `captain_tasks` capability gate for evaluation. - Kept this foundation independent of the Captain V2 guard; the timer and advanced settings in stacks 2–5 are Captain V2-only. Stack 1 of 5. This is the base for #15303.
26 lines
1.3 KiB
Ruby
26 lines
1.3 KiB
Ruby
class Captain::Tools::ResolveConversationTool < Captain::Tools::BasePublicTool
|
|
description 'Resolve a conversation when the issue has been addressed or the conversation should be closed'
|
|
param :reason, type: 'string', desc: 'Brief reason for resolving the conversation', required: true
|
|
|
|
def perform(tool_context, reason:)
|
|
conversation = find_conversation(tool_context.state)
|
|
return 'Conversation not found' unless conversation
|
|
return "Conversation ##{conversation.display_id} is already resolved" if conversation.resolved?
|
|
return 'Auto-resolve is disabled for this assistant' if @assistant.inactive_conversation_resolution_disabled?
|
|
|
|
log_tool_usage('resolve_conversation', { conversation_id: conversation.id, reason: reason })
|
|
|
|
conversation.with_captain_activity_context(reason: reason, reason_type: :tool) { conversation.resolved! }
|
|
Captain::ConversationEvents.resolved(conversation: conversation, assistant: @assistant,
|
|
source: Captain::ConversationEvents::Sources::TOOL, at: Time.current)
|
|
|
|
"Conversation ##{conversation.display_id} resolved#{" (Reason: #{reason})" if reason}"
|
|
end
|
|
|
|
private
|
|
|
|
def permissions
|
|
%w[conversation_manage conversation_unassigned_manage conversation_participating_manage]
|
|
end
|
|
end
|