require 'agents' class Captain::Tools::BasePublicTool < Agents::Tool def initialize(assistant, user: nil, conversation: nil) @assistant = assistant @user = user @conversation = conversation super() end def active? # Public tools are always active true end def permissions # Override in subclasses to specify required permissions # Returns empty array for public tools (no permissions required) [] end def execute(*args, **params) # Adapter for flexible argument handling (RubyLLM vs Agents) actual_params = resolve_params(args, params) # Agents::Tool#execute expects a single hash argument for run super(actual_params) end protected def resolve_params(args, params) # RubyLLM: [params_hash], {} # Agents: [context], {params_hash} if args.first.is_a?(Hash) && params.empty? args.first else params end.with_indifferent_access end private def account_scoped(model_class) model_class.where(account_id: @assistant.account_id) end def find_conversation(state) conversation_id = state&.dig(:conversation, :id) return nil unless conversation_id account_scoped(::Conversation).find_by(id: conversation_id) end def find_contact(state) contact_id = state&.dig(:contact, :id) return nil unless contact_id account_scoped(::Contact).find_by(id: contact_id) end def log_tool_usage(action, details = {}) Rails.logger.info do "#{self.class.name}: #{action} for assistant #{@assistant&.id} - #{details.inspect}" end end end