diff --git a/enterprise/app/services/captain/tools/copilot/search_conversations_service.rb b/enterprise/app/services/captain/tools/copilot/search_conversations_service.rb index 9e824d1f5..d4acb9837 100644 --- a/enterprise/app/services/captain/tools/copilot/search_conversations_service.rb +++ b/enterprise/app/services/captain/tools/copilot/search_conversations_service.rb @@ -4,9 +4,9 @@ class Captain::Tools::Copilot::SearchConversationsService < Captain::Tools::Base end description 'Search conversations based on parameters' - param :status, type: :string, desc: 'Status of the conversation' + param :status, type: :string, desc: 'Status of the conversation (open, resolved, pending, snoozed). Leave empty to search all statuses.' param :contact_id, type: :number, desc: 'Contact id' - param :priority, type: :string, desc: 'Priority of conversation' + param :priority, type: :string, desc: 'Priority of conversation (low, medium, high, urgent). Leave empty to search all priorities.' param :labels, type: :string, desc: 'Labels available' def execute(status: nil, contact_id: nil, priority: nil, labels: nil) @@ -19,7 +19,7 @@ class Captain::Tools::Copilot::SearchConversationsService < Captain::Tools::Base <<~RESPONSE #{total_count > 100 ? "Found #{total_count} conversations (showing first 100)" : "Total number of conversations: #{total_count}"} - #{conversations.map { |conversation| conversation.to_llm_text(include_contact_details: true) }.join("\n---\n")} + #{conversations.map { |conversation| conversation.to_llm_text(include_contact_details: true, include_private_messages: true) }.join("\n---\n")} RESPONSE end @@ -34,12 +34,20 @@ class Captain::Tools::Copilot::SearchConversationsService < Captain::Tools::Base def get_conversations(status, contact_id, priority, labels) conversations = permissible_conversations conversations = conversations.where(contact_id: contact_id) if contact_id.present? - conversations = conversations.where(status: status) if status.present? - conversations = conversations.where(priority: priority) if priority.present? + conversations = conversations.where(status: status) if valid_status?(status) + conversations = conversations.where(priority: priority) if valid_priority?(priority) conversations = conversations.tagged_with(labels, any: true) if labels.present? conversations end + def valid_status?(status) + status.present? && Conversation.statuses.key?(status) + end + + def valid_priority?(priority) + priority.present? && Conversation.priorities.key?(priority) + end + def permissible_conversations Conversations::PermissionFilterService.new( @assistant.account.conversations, diff --git a/spec/enterprise/services/captain/tools/copilot/search_conversations_service_spec.rb b/spec/enterprise/services/captain/tools/copilot/search_conversations_service_spec.rb index a02d05404..0835b6125 100644 --- a/spec/enterprise/services/captain/tools/copilot/search_conversations_service_spec.rb +++ b/spec/enterprise/services/captain/tools/copilot/search_conversations_service_spec.rb @@ -119,5 +119,42 @@ RSpec.describe Captain::Tools::Copilot::SearchConversationsService do result = service.execute(status: 'snoozed') expect(result).to eq('No conversations found') end + + context 'when invalid status is provided' do + it 'ignores invalid status and returns all conversations' do + result = service.execute(status: 'all') + expect(result).to include('Total number of conversations: 2') + expect(result).to include(open_conversation.to_llm_text(include_contact_details: true)) + expect(result).to include(resolved_conversation.to_llm_text(include_contact_details: true)) + end + + it 'ignores random invalid status values' do + result = service.execute(status: 'invalid_status') + expect(result).to include('Total number of conversations: 2') + end + end + + context 'when invalid priority is provided' do + it 'ignores invalid priority and returns all conversations' do + result = service.execute(priority: 'all') + expect(result).to include('Total number of conversations: 2') + expect(result).to include(open_conversation.to_llm_text(include_contact_details: true)) + expect(result).to include(resolved_conversation.to_llm_text(include_contact_details: true)) + end + + it 'ignores random invalid priority values' do + result = service.execute(priority: 'invalid_priority') + expect(result).to include('Total number of conversations: 2') + end + end + + context 'when combining valid and invalid parameters' do + it 'applies valid filters and ignores invalid ones' do + result = service.execute(status: 'all', contact_id: contact.id) + expect(result).to include('Total number of conversations: 1') + expect(result).to include(open_conversation.to_llm_text(include_contact_details: true)) + expect(result).not_to include(resolved_conversation.to_llm_text(include_contact_details: true)) + end + end end end