feat: add tools
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
###### Captain Agent Tools Configuration #######
|
||||
# id: Tool identifier used to resolve the class (Captain::Tools::{PascalCase(id)}Tool)
|
||||
# title: Human-readable tool name for frontend display
|
||||
# description: Brief description of what the tool does
|
||||
# icon: Icon name for frontend display (frontend icon system)
|
||||
#######################################################
|
||||
|
||||
- id: add_contact_note
|
||||
title: "Add Contact Note"
|
||||
description: "Add a note to a contact profile"
|
||||
icon: "note-add"
|
||||
|
||||
- id: add_private_note
|
||||
title: "Add Private Note"
|
||||
description: "Add a private note to a conversation (internal only)"
|
||||
icon: "eye-off"
|
||||
|
||||
- id: update_priority
|
||||
title: "Update Priority"
|
||||
description: "Update conversation priority level"
|
||||
icon: "exclamation-triangle"
|
||||
@@ -0,0 +1,39 @@
|
||||
class Captain::Tools::AddContactNoteTool < Captain::Tools::BaseAgentTool
|
||||
description 'Add a note to a contact profile'
|
||||
param :contact_id, type: 'string', desc: 'The ID of the contact (optional if conversation_id is provided)'
|
||||
param :conversation_id, type: 'string', desc: 'The display ID of the conversation to find the contact (optional if contact_id is provided)'
|
||||
param :note, type: 'string', desc: 'The note content to add to the contact'
|
||||
|
||||
def perform(_tool_context, note:, contact_id: nil, conversation_id: nil)
|
||||
log_tool_usage('add_contact_note', { contact_id: contact_id, conversation_id: conversation_id, note_length: note.length })
|
||||
|
||||
return 'Missing required parameters: need either contact_id or conversation_id, and note' if note.blank?
|
||||
return 'Must provide either contact_id or conversation_id' if contact_id.blank? && conversation_id.blank?
|
||||
|
||||
contact = nil
|
||||
|
||||
if contact_id.present?
|
||||
contact = account_scoped(::Contact).find_by(id: contact_id)
|
||||
return 'Contact not found' if contact.nil?
|
||||
elsif conversation_id.present?
|
||||
conversation = account_scoped(::Conversation).find_by(display_id: conversation_id)
|
||||
return 'Conversation not found' if conversation.nil?
|
||||
|
||||
contact = conversation.contact
|
||||
end
|
||||
|
||||
# Create contact note
|
||||
contact.notes.create!(
|
||||
account: @assistant.account,
|
||||
contact: contact,
|
||||
content: note,
|
||||
user: @user
|
||||
)
|
||||
|
||||
"Note added successfully to contact #{contact.name} (ID: #{contact.id})"
|
||||
end
|
||||
|
||||
def active?
|
||||
user_has_permission('contact_manage')
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
class Captain::Tools::AddPrivateNoteTool < Captain::Tools::BaseAgentTool
|
||||
description 'Add a private note to a conversation'
|
||||
param :conversation_id, type: 'string', desc: 'The display ID of the conversation'
|
||||
param :note, type: 'string', desc: 'The private note content'
|
||||
|
||||
def perform(_tool_context, conversation_id:, note:)
|
||||
log_tool_usage('add_private_note', { conversation_id: conversation_id, note_length: note.length })
|
||||
|
||||
return 'Missing required parameters' if conversation_id.blank? || note.blank?
|
||||
|
||||
conversation = account_scoped(::Conversation).find_by(display_id: conversation_id)
|
||||
return 'Conversation not found' if conversation.nil?
|
||||
|
||||
# Create private note message
|
||||
conversation.messages.create!(
|
||||
account: @assistant.account,
|
||||
inbox: conversation.inbox,
|
||||
sender: @user,
|
||||
content: note,
|
||||
message_type: 'activity',
|
||||
private: true
|
||||
)
|
||||
|
||||
"Private note added successfully to conversation #{conversation_id}"
|
||||
end
|
||||
|
||||
def active?
|
||||
user_has_permission('conversation_manage') ||
|
||||
user_has_permission('conversation_unassigned_manage') ||
|
||||
user_has_permission('conversation_participating_manage')
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,44 @@
|
||||
require 'agents'
|
||||
|
||||
class Captain::Tools::BaseAgentTool < Agents::Tool
|
||||
def initialize(assistant, user: nil)
|
||||
@assistant = assistant
|
||||
@user = user
|
||||
super()
|
||||
end
|
||||
|
||||
def active?
|
||||
user_has_permission(required_permission)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def required_permission
|
||||
# Override in subclasses to specify the required permission
|
||||
'agent'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_has_permission(permission)
|
||||
return false if @user.blank?
|
||||
|
||||
account_user = AccountUser.find_by(account_id: @assistant.account_id, user_id: @user.id)
|
||||
return false if account_user.blank?
|
||||
|
||||
return account_user.custom_role.permissions.include?(permission) if account_user.custom_role.present?
|
||||
|
||||
# Default permission for agents without custom roles
|
||||
account_user.administrator? || account_user.agent?
|
||||
end
|
||||
|
||||
def account_scoped(model_class)
|
||||
model_class.where(account_id: @assistant.account_id)
|
||||
end
|
||||
|
||||
def log_tool_usage(action, details = {})
|
||||
Rails.logger.info do
|
||||
"#{self.class.name}: #{action} by user #{@user&.id} for assistant #{@assistant&.id} - #{details.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
class Captain::Tools::UpdatePriorityTool < Captain::Tools::BaseAgentTool
|
||||
description 'Update the priority of a conversation'
|
||||
param :conversation_id, type: 'string', desc: 'The display ID of the conversation'
|
||||
param :priority, type: 'string', desc: 'The priority level: nil, low, medium, high, urgent'
|
||||
|
||||
def perform(_tool_context, conversation_id:, priority:)
|
||||
log_tool_usage('update_priority', { conversation_id: conversation_id, priority: priority })
|
||||
|
||||
return 'Missing required parameters' if conversation_id.blank?
|
||||
|
||||
conversation = account_scoped(::Conversation).find_by(display_id: conversation_id)
|
||||
return 'Conversation not found' if conversation.nil?
|
||||
|
||||
# Validate priority value
|
||||
valid_priorities = [nil, 'low', 'medium', 'high', 'urgent']
|
||||
priority = nil if priority == 'nil' || priority.blank?
|
||||
|
||||
return "Invalid priority. Valid options: #{valid_priorities.join(', ')}" unless valid_priorities.include?(priority)
|
||||
|
||||
# Update the priority
|
||||
conversation.update!(priority: priority)
|
||||
|
||||
priority_text = priority || 'none'
|
||||
"Priority updated to '#{priority_text}' for conversation #{conversation_id}"
|
||||
end
|
||||
|
||||
def active?
|
||||
user_has_permission('conversation_manage') ||
|
||||
user_has_permission('conversation_unassigned_manage') ||
|
||||
user_has_permission('conversation_participating_manage')
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user