feat: Add support for search_conversations in copilot (#11520)
Earlier, we were manually checking if a user was an agent and filtering their conversations based on inboxes. This logic should have been part of the conversation permissions service. This PR moves the check to the right place and updates the logic accordingly. Other updates: - Add support for search_conversations service for copilot. - Use PermissionFilterService in contacts/conversations, conversations, copilot search_conversations. --------- Co-authored-by: Sojan <sojan@pepalo.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
class Captain::Tools::BaseService
|
||||
attr_accessor :assistant
|
||||
|
||||
def initialize(assistant)
|
||||
def initialize(assistant, user: nil)
|
||||
@assistant = assistant
|
||||
@user = user
|
||||
end
|
||||
|
||||
def name
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
class Captain::Tools::Copilot::SearchConversationsService < Captain::Tools::BaseService
|
||||
def name
|
||||
'search_conversations'
|
||||
end
|
||||
|
||||
def description
|
||||
'Search conversations based on parameters'
|
||||
end
|
||||
|
||||
def parameters
|
||||
{
|
||||
type: 'object',
|
||||
properties: properties,
|
||||
required: []
|
||||
}
|
||||
end
|
||||
|
||||
def execute(arguments)
|
||||
status = arguments['status']
|
||||
contact_id = arguments['contact_id']
|
||||
priority = arguments['priority']
|
||||
|
||||
conversations = get_conversations(status, contact_id, priority)
|
||||
|
||||
return 'No conversations found' unless conversations.exists?
|
||||
|
||||
total_count = conversations.count
|
||||
conversations = conversations.limit(100)
|
||||
|
||||
<<~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")}
|
||||
RESPONSE
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_conversations(status, contact_id, priority)
|
||||
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
|
||||
end
|
||||
|
||||
def permissible_conversations
|
||||
Conversations::PermissionFilterService.new(
|
||||
@assistant.account.conversations,
|
||||
@user,
|
||||
@assistant.account
|
||||
).perform
|
||||
end
|
||||
|
||||
def properties
|
||||
{
|
||||
contact_id: {
|
||||
type: 'number',
|
||||
description: 'Filter conversations by contact ID'
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
enum: %w[open resolved pending snoozed],
|
||||
description: 'Filter conversations by status'
|
||||
},
|
||||
priority: {
|
||||
type: 'string',
|
||||
enum: %w[low medium high urgent],
|
||||
description: 'Filter conversations by priority'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -1,36 +1,37 @@
|
||||
module Enterprise::Conversations::PermissionFilterService
|
||||
def perform
|
||||
account_user = AccountUser.find_by(account_id: account.id, user_id: user.id)
|
||||
permissions = account_user&.permissions || []
|
||||
user_role = account_user&.role
|
||||
return filter_by_permissions(permissions) if user_has_custom_role?
|
||||
|
||||
# Skip filtering for administrators
|
||||
return conversations if user_role == 'administrator'
|
||||
# Skip filtering for regular agents (without custom roles/permissions)
|
||||
return conversations if user_role == 'agent' && account_user&.custom_role_id.nil?
|
||||
|
||||
filter_by_permissions(permissions)
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_has_custom_role?
|
||||
user_role == 'agent' && account_user&.custom_role_id.present?
|
||||
end
|
||||
|
||||
def permissions
|
||||
account_user&.permissions || []
|
||||
end
|
||||
|
||||
def filter_by_permissions(permissions)
|
||||
# Permission-based filtering with hierarchy
|
||||
# conversation_manage > conversation_unassigned_manage > conversation_participating_manage
|
||||
if permissions.include?('conversation_manage')
|
||||
conversations
|
||||
accessible_conversations
|
||||
elsif permissions.include?('conversation_unassigned_manage')
|
||||
filter_unassigned_and_mine
|
||||
elsif permissions.include?('conversation_participating_manage')
|
||||
conversations.assigned_to(user)
|
||||
accessible_conversations.assigned_to(user)
|
||||
else
|
||||
Conversation.none
|
||||
end
|
||||
end
|
||||
|
||||
def filter_unassigned_and_mine
|
||||
mine = conversations.assigned_to(user)
|
||||
unassigned = conversations.unassigned
|
||||
mine = accessible_conversations.assigned_to(user)
|
||||
unassigned = accessible_conversations.unassigned
|
||||
|
||||
Conversation.from("(#{mine.to_sql} UNION #{unassigned.to_sql}) as conversations")
|
||||
.where(account_id: account.id)
|
||||
|
||||
Reference in New Issue
Block a user