From 9f583ae3b1b95927cc78d0bdfa5e40137c8d568d Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 3 Oct 2025 16:15:14 +0530 Subject: [PATCH] feat: handle custom tools in scenario via assistant --- enterprise/app/models/captain/scenario.rb | 22 ++++++---------- .../models/captain/custom_tool_spec.rb | 5 ++-- .../models/captain/scenario_spec.rb | 25 +++++++++++-------- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/enterprise/app/models/captain/scenario.rb b/enterprise/app/models/captain/scenario.rb index af49a8470..d04990199 100644 --- a/enterprise/app/models/captain/scenario.rb +++ b/enterprise/app/models/captain/scenario.rb @@ -57,7 +57,7 @@ class Captain::Scenario < ApplicationRecord end def agent_tools - resolved_tools.map { |tool| resolve_tool_instance(tool[:id]) } + resolved_tools.map { |tool| resolve_tool_instance(tool) } end def resolved_instructions @@ -69,19 +69,16 @@ class Captain::Scenario < ApplicationRecord def resolved_tools return [] if tools.blank? - available_tools = self.class.available_agent_tools + available_tools = assistant.available_agent_tools tools.filter_map do |tool_id| - if tool_id.start_with?('custom_') - custom_tool = Captain::CustomTool.find_by(slug: tool_id, account_id: account_id, enabled: true) - custom_tool&.to_tool_metadata - else - available_tools.find { |tool| tool[:id] == tool_id } - end + available_tools.find { |tool| tool[:id] == tool_id } end end - def resolve_tool_instance(tool_id) - if tool_id.start_with?('custom_') + def resolve_tool_instance(tool_metadata) + tool_id = tool_metadata[:id] + + if tool_metadata[:custom] custom_tool = Captain::CustomTool.find_by(slug: tool_id, account_id: account_id, enabled: true) custom_tool&.tool(assistant) else @@ -110,10 +107,7 @@ class Captain::Scenario < ApplicationRecord tool_ids = extract_tool_ids_from_text(instruction) return if tool_ids.empty? - available_tool_ids = self.class.available_tool_ids - custom_tool_ids = Captain::CustomTool.where(account_id: account_id, enabled: true).pluck(:slug) - all_available_tool_ids = available_tool_ids + custom_tool_ids - + all_available_tool_ids = assistant.available_tool_ids invalid_tools = tool_ids - all_available_tool_ids return unless invalid_tools.any? diff --git a/spec/enterprise/models/captain/custom_tool_spec.rb b/spec/enterprise/models/captain/custom_tool_spec.rb index 89150fa1e..0d9e03448 100644 --- a/spec/enterprise/models/captain/custom_tool_spec.rb +++ b/spec/enterprise/models/captain/custom_tool_spec.rb @@ -268,7 +268,7 @@ RSpec.describe Captain::CustomTool, type: :model do end describe '#to_tool_metadata' do - it 'returns tool metadata hash' do + it 'returns tool metadata hash with custom flag' do tool = create(:captain_custom_tool, account: account, slug: 'custom_test-tool', title: 'Test Tool', @@ -278,7 +278,8 @@ RSpec.describe Captain::CustomTool, type: :model do expect(metadata).to eq({ id: 'custom_test-tool', title: 'Test Tool', - description: 'A test tool' + description: 'A test tool', + custom: true }) end end diff --git a/spec/enterprise/models/captain/scenario_spec.rb b/spec/enterprise/models/captain/scenario_spec.rb index dca0a6fbc..45009a3b0 100644 --- a/spec/enterprise/models/captain/scenario_spec.rb +++ b/spec/enterprise/models/captain/scenario_spec.rb @@ -48,9 +48,9 @@ RSpec.describe Captain::Scenario, type: :model do before do # Mock available tools - allow(described_class).to receive(:available_tool_ids).and_return(%w[ - add_contact_note add_private_note update_priority - ]) + allow(described_class).to receive(:built_in_tool_ids).and_return(%w[ + add_contact_note add_private_note update_priority + ]) end describe 'validate_instruction_tools' do @@ -194,11 +194,11 @@ RSpec.describe Captain::Scenario, type: :model do let(:assistant) { create(:captain_assistant, account: account) } before do - allow(described_class).to receive(:available_tool_ids).and_return(%w[add_contact_note]) - allow(described_class).to receive(:available_agent_tools).and_return([ - { id: 'add_contact_note', title: 'Add Contact Note', - description: 'Add a note' } - ]) + allow(described_class).to receive(:built_in_tool_ids).and_return(%w[add_contact_note]) + allow(described_class).to receive(:built_in_agent_tools).and_return([ + { id: 'add_contact_note', title: 'Add Contact Note', + description: 'Add a note' } + ]) end describe '#resolved_tools' do @@ -248,7 +248,8 @@ RSpec.describe Captain::Scenario, type: :model do create(:captain_custom_tool, account: account, slug: 'custom_fetch-order') scenario = create(:captain_scenario, assistant: assistant, account: account) - tool_instance = scenario.send(:resolve_tool_instance, 'custom_fetch-order') + tool_metadata = { id: 'custom_fetch-order', custom: true } + tool_instance = scenario.send(:resolve_tool_instance, tool_metadata) expect(tool_instance).to be_a(Captain::Tools::HttpTool) end @@ -256,7 +257,8 @@ RSpec.describe Captain::Scenario, type: :model do create(:captain_custom_tool, account: account, slug: 'custom_fetch-order', enabled: false) scenario = create(:captain_scenario, assistant: assistant, account: account) - tool_instance = scenario.send(:resolve_tool_instance, 'custom_fetch-order') + tool_metadata = { id: 'custom_fetch-order', custom: true } + tool_instance = scenario.send(:resolve_tool_instance, tool_metadata) expect(tool_instance).to be_nil end @@ -268,7 +270,8 @@ RSpec.describe Captain::Scenario, type: :model do end ) - tool_instance = scenario.send(:resolve_tool_instance, 'add_contact_note') + tool_metadata = { id: 'add_contact_note' } + tool_instance = scenario.send(:resolve_tool_instance, tool_metadata) expect(tool_instance).not_to be_nil expect(tool_instance).not_to be_a(Captain::Tools::HttpTool) end