diff --git a/enterprise/app/models/concerns/toolable.rb b/enterprise/app/models/concerns/toolable.rb index 58b24bf36..89e1f4f2d 100644 --- a/enterprise/app/models/concerns/toolable.rb +++ b/enterprise/app/models/concerns/toolable.rb @@ -2,7 +2,20 @@ module Concerns::Toolable extend ActiveSupport::Concern def tool(assistant) - Captain::Tools::HttpTool.new(assistant, self) + custom_tool_record = self + + tool_class = Class.new(Captain::Tools::HttpTool) do + description custom_tool_record.description + + custom_tool_record.param_schema.each do |param_def| + param param_def['name'].to_sym, + type: param_def['type'], + desc: param_def['description'], + required: param_def.fetch('required', true) + end + end + + tool_class.new(assistant, self) end def build_request_url(params) diff --git a/enterprise/lib/captain/tools/http_tool.rb b/enterprise/lib/captain/tools/http_tool.rb index ea58d1264..e6a4f6d9e 100644 --- a/enterprise/lib/captain/tools/http_tool.rb +++ b/enterprise/lib/captain/tools/http_tool.rb @@ -7,10 +7,6 @@ class Captain::Tools::HttpTool < Agents::Tool super() end - def description - @custom_tool.description - end - def active? @custom_tool.enabled? end diff --git a/spec/enterprise/models/captain/custom_tool_spec.rb b/spec/enterprise/models/captain/custom_tool_spec.rb index 0d9e03448..23f7cbd2c 100644 --- a/spec/enterprise/models/captain/custom_tool_spec.rb +++ b/spec/enterprise/models/captain/custom_tool_spec.rb @@ -283,5 +283,46 @@ RSpec.describe Captain::CustomTool, type: :model do }) end end + + describe '#tool' do + let(:assistant) { create(:captain_assistant, account: account) } + + it 'returns HttpTool instance' do + tool = create(:captain_custom_tool, account: account) + + tool_instance = tool.tool(assistant) + expect(tool_instance).to be_a(Captain::Tools::HttpTool) + end + + it 'sets description on the tool class' do + tool = create(:captain_custom_tool, account: account, description: 'Fetches order data') + + tool_instance = tool.tool(assistant) + expect(tool_instance.description).to eq('Fetches order data') + end + + it 'sets parameters on the tool class' do + tool = create(:captain_custom_tool, :with_params, account: account) + + tool_instance = tool.tool(assistant) + params = tool_instance.parameters + + expect(params.keys).to contain_exactly(:order_id, :include_details) + expect(params[:order_id].name).to eq(:order_id) + expect(params[:order_id].type).to eq('string') + expect(params[:order_id].description).to eq('The order ID') + expect(params[:order_id].required).to be true + + expect(params[:include_details].name).to eq(:include_details) + expect(params[:include_details].required).to be false + end + + it 'works with empty param_schema' do + tool = create(:captain_custom_tool, account: account, param_schema: []) + + tool_instance = tool.tool(assistant) + expect(tool_instance.parameters).to be_empty + end + end end end diff --git a/spec/factories/captain/custom_tool.rb b/spec/factories/captain/custom_tool.rb index 81921b1c5..2bfcbf360 100644 --- a/spec/factories/captain/custom_tool.rb +++ b/spec/factories/captain/custom_tool.rb @@ -6,6 +6,7 @@ FactoryBot.define do http_method { 'GET' } auth_type { 'none' } auth_config { {} } + param_schema { [] } enabled { true } association :account @@ -34,6 +35,15 @@ FactoryBot.define do response_template { 'Order status: {{ response.status }}' } end + trait :with_params do + param_schema do + [ + { 'name' => 'order_id', 'type' => 'string', 'description' => 'The order ID', 'required' => true }, + { 'name' => 'include_details', 'type' => 'boolean', 'description' => 'Include order details', 'required' => false } + ] + end + end + trait :disabled do enabled { false } end