diff --git a/Gemfile b/Gemfile index c4baf61..bd7efe1 100755 --- a/Gemfile +++ b/Gemfile @@ -271,4 +271,4 @@ group :development, :test do gem 'spring-watcher-listen' end -gem "rqrcode", "~> 3.2" +gem 'rqrcode', '~> 3.2' diff --git a/app/builders/messages/message_builder.rb b/app/builders/messages/message_builder.rb index 87c3a7b..1e689f0 100755 --- a/app/builders/messages/message_builder.rb +++ b/app/builders/messages/message_builder.rb @@ -51,16 +51,14 @@ class Messages::MessageBuilder file: uploaded_attachment ) - attachment.file_type = if uploaded_attachment.is_a?(String) - file_type_by_signed_id( - uploaded_attachment - ) - else - file_type(uploaded_attachment&.content_type) - end + attachment.file_type = resolve_file_type(uploaded_attachment) end end + def resolve_file_type(attachment) + attachment.is_a?(String) ? file_type_by_signed_id(attachment) : file_type(attachment&.content_type) + end + def process_emails return unless @conversation.inbox&.inbox_type == 'Email' @@ -222,11 +220,18 @@ class Messages::MessageBuilder @private = @params[:private] || false @message_type = @params[:message_type] || 'outgoing' @attachments = @params[:attachments] - @automation_rule = content_attributes&.dig(:automation_rule_id) - # Try to find in_reply_to in params (top level) or content_attributes - @in_reply_to = @params[:in_reply_to_id] || @params[:in_reply_to] || content_attributes&.dig(:in_reply_to) + @automation_rule = extract_automation_rule + @in_reply_to = extract_in_reply_to @items = content_attributes&.dig(:items) end + + def extract_automation_rule + content_attributes&.dig(:automation_rule_id) + end + + def extract_in_reply_to + @params[:in_reply_to_id] || @params[:in_reply_to] || content_attributes&.dig(:in_reply_to) + end end Messages::MessageBuilder.prepend_mod_with('Messages::MessageBuilder') diff --git a/app/controllers/api/v1/accounts/frequent_questions_controller.rb b/app/controllers/api/v1/accounts/frequent_questions_controller.rb index eb8efe2..863af81 100644 --- a/app/controllers/api/v1/accounts/frequent_questions_controller.rb +++ b/app/controllers/api/v1/accounts/frequent_questions_controller.rb @@ -1,11 +1,5 @@ -module Api - module V1 - module Accounts - class FrequentQuestionsController < Api::V1::Accounts::BaseController - def index - @frequent_questions = Current.account.frequent_questions.order(occurrence_count: :desc).limit(50) - end - end - end +class Api::V1::Accounts::FrequentQuestionsController < Api::V1::Accounts::BaseController + def index + @frequent_questions = Current.account.frequent_questions.order(occurrence_count: :desc).limit(50) end end diff --git a/app/controllers/api/v1/accounts/inboxes/jasmine/collections_controller.rb b/app/controllers/api/v1/accounts/inboxes/jasmine/collections_controller.rb index 5ee297f..a9120e5 100644 --- a/app/controllers/api/v1/accounts/inboxes/jasmine/collections_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes/jasmine/collections_controller.rb @@ -1,43 +1,33 @@ -module Api - module V1 - module Accounts - module Inboxes - module Jasmine - class CollectionsController < Api::V1::Accounts::BaseController - before_action :fetch_inbox +class Api::V1::Accounts::Inboxes::Jasmine::CollectionsController < Api::V1::Accounts::BaseController + before_action :fetch_inbox - def index - # Returns collections linked to this inbox - collection_ids = @inbox.inbox_collections.pluck(:collection_id) - @collections = Current.account.jasmine_collections.where(id: collection_ids) - render json: @collections - end + def index + # Returns collections linked to this inbox + collection_ids = @inbox.inbox_collections.pluck(:collection_id) + @collections = Current.account.jasmine_collections.where(id: collection_ids) + render json: @collections + end - def create - # Link an existing collection to this inbox - collection = Current.account.jasmine_collections.find(params[:collection_id]) - link = @inbox.inbox_collections.create!( - collection: collection, - priority: params[:priority] || 0 - ) - render json: link - end + def create + # Link an existing collection to this inbox + collection = Current.account.jasmine_collections.find(params[:collection_id]) + link = @inbox.inbox_collections.create!( + collection: collection, + priority: params[:priority] || 0 + ) + render json: link + end - def destroy - # Unlink a collection from this inbox - link = @inbox.inbox_collections.find_by!(collection_id: params[:id]) - link.destroy! - head :no_content - end + def destroy + # Unlink a collection from this inbox + link = @inbox.inbox_collections.find_by!(collection_id: params[:id]) + link.destroy! + head :no_content + end - private + private - def fetch_inbox - @inbox = Current.account.inboxes.find(params[:inbox_id]) - end - end - end - end - end + def fetch_inbox + @inbox = Current.account.inboxes.find(params[:inbox_id]) end end diff --git a/app/controllers/api/v1/accounts/inboxes/jasmine/configs_controller.rb b/app/controllers/api/v1/accounts/inboxes/jasmine/configs_controller.rb index dd83f06..5b400a3 100644 --- a/app/controllers/api/v1/accounts/inboxes/jasmine/configs_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes/jasmine/configs_controller.rb @@ -1,53 +1,43 @@ -module Api - module V1 - module Accounts - module Inboxes - module Jasmine - class ConfigsController < Api::V1::Accounts::BaseController - before_action :fetch_inbox - before_action :fetch_or_initialize_config +class Api::V1::Accounts::Inboxes::Jasmine::ConfigsController < Api::V1::Accounts::BaseController + before_action :fetch_inbox + before_action :fetch_or_initialize_config - def show - render json: @config - end + def show + render json: @config + end - def update - if @config.update(config_params) - render json: @config - else - render json: { error: @config.errors.full_messages.join(', ') }, status: :unprocessable_entity - end - end - - private - - def fetch_inbox - @inbox = Current.account.inboxes.find(params[:inbox_id]) - end - - def fetch_or_initialize_config - @config = ::Jasmine::InboxConfig.find_or_initialize_by( - account: Current.account, - inbox: @inbox - ) - end - - def config_params - params.permit( - :is_enabled, - :system_prompt, - :playbook_prompt, - :model, - :temperature, - :rag_distance_threshold, - :rag_max_results, - :mode, - intent_keywords: {} - ) - end - end - end - end + def update + if @config.update(config_params) + render json: @config + else + render json: { error: @config.errors.full_messages.join(', ') }, status: :unprocessable_entity end end + + private + + def fetch_inbox + @inbox = Current.account.inboxes.find(params[:inbox_id]) + end + + def fetch_or_initialize_config + @config = ::Jasmine::InboxConfig.find_or_initialize_by( + account: Current.account, + inbox: @inbox + ) + end + + def config_params + params.permit( + :is_enabled, + :system_prompt, + :playbook_prompt, + :model, + :temperature, + :rag_distance_threshold, + :rag_max_results, + :mode, + intent_keywords: {} + ) + end end diff --git a/app/controllers/api/v1/accounts/inboxes/jasmine/playground_controller.rb b/app/controllers/api/v1/accounts/inboxes/jasmine/playground_controller.rb index 1327690..a39ae73 100644 --- a/app/controllers/api/v1/accounts/inboxes/jasmine/playground_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes/jasmine/playground_controller.rb @@ -1,85 +1,75 @@ -module Api - module V1 - module Accounts - module Inboxes - module Jasmine - class PlaygroundController < Api::V1::Accounts::BaseController - before_action :fetch_inbox - before_action :fetch_config +class Api::V1::Accounts::Inboxes::Jasmine::PlaygroundController < Api::V1::Accounts::BaseController + before_action :fetch_inbox + before_action :fetch_config - def test - message_content = params[:message] - - return render json: { error: 'Message is required' }, status: :bad_request if message_content.blank? - return render json: { error: 'Jasmine is not enabled for this inbox' }, status: :unprocessable_entity unless @config&.is_enabled? + def test + return render json: { error: 'Message is required' }, status: :bad_request if params[:message].blank? + return render json: { error: 'Jasmine is not enabled for this inbox' }, status: :unprocessable_entity unless @config&.is_enabled? - # Create a mock message object for BrainService - mock_message = OpenStruct.new( - content: message_content, - inbox: @inbox, - conversation: mock_conversation - ) + begin + response = generate_response(params[:message]) + render json: build_success_payload(response) + rescue StandardError => e + handle_error(e) + end + end - begin - response = ::Jasmine::BrainService.new( - inbox: @inbox, - conversation: mock_conversation, - message: mock_message - ).respond + private - render json: { - response: response, - debug: { - model: @config.model, - temperature: @config.temperature, - rag_threshold: @config.rag_distance_threshold - } - } - rescue StandardError => e - Rails.logger.error "[Jasmine::Playground] Error: #{e.message}\n#{e.backtrace.first(5).join("\n")}" - render json: { error: e.message }, status: :internal_server_error - end - end + def fetch_inbox + @inbox = Current.account.inboxes.find(params[:inbox_id]) + end - private + def fetch_config + @config = ::Jasmine::InboxConfig.find_by( + account: Current.account, + inbox: @inbox + ) + end - def fetch_inbox - @inbox = Current.account.inboxes.find(params[:inbox_id]) - end + def generate_response(content) + # Create a mock message object for BrainService + mock_message = OpenStruct.new(content: content, inbox: @inbox, conversation: mock_conversation) + ::Jasmine::BrainService.new(inbox: @inbox, conversation: mock_conversation, message: mock_message).respond + end - def fetch_config - @config = ::Jasmine::InboxConfig.find_by( - account: Current.account, - inbox: @inbox - ) - end + def build_success_payload(response) + { + response: response, + debug: { + model: @config.model, + temperature: @config.temperature, + rag_threshold: @config.rag_distance_threshold + } + } + end - def mock_conversation - # Create a minimal mock conversation for playground testing - @mock_conversation ||= begin - mock = OpenStruct.new( - id: 0, - account_id: Current.account.id, - inbox_id: @inbox.id, - custom_attributes: { 'jasmine_state' => {} } - ) - - # Mock messages method to return empty array that responds to query methods - def mock.messages - [] - end - - # Mock update! to do nothing (playground doesn't need state persistence) - def mock.update!(**attrs) - # no-op for playground - end - - mock - end - end - end - end + def handle_error(err) + Rails.logger.error "[Jasmine::Playground] Error: #{err.message}\n#{err.backtrace.first(5).join("\n")}" + render json: { error: err.message }, status: :internal_server_error + end + + def mock_conversation + # Create a minimal mock conversation for playground testing + @mock_conversation ||= begin + mock = OpenStruct.new( + id: 0, + account_id: Current.account.id, + inbox_id: @inbox.id, + custom_attributes: { 'jasmine_state' => {} } + ) + + # Mock messages method to return empty array that responds to query methods + def mock.messages + [] end + + # Mock update! to do nothing (playground doesn't need state persistence) + def mock.update!(**attrs) + # no-op for playground + end + + mock end end end diff --git a/app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb b/app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb index 629b178..f7d9abd 100644 --- a/app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb @@ -1,93 +1,90 @@ -module Api - module V1 - module Accounts - module Inboxes - module Jasmine - class ToolsController < Api::V1::Accounts::BaseController - before_action :fetch_inbox +class Api::V1::Accounts::Inboxes::Jasmine::ToolsController < Api::V1::Accounts::BaseController + before_action :fetch_inbox - def index - configs = ::Jasmine::ToolConfig.where(inbox: @inbox).index_by(&:tool_key) - - tools = ::Jasmine::ToolConfig::DEFINITIONS.map do |key, definition| - config = configs[key] - { - key: key, - name: definition[:name], - method: definition[:method].to_s.upcase, - url: definition[:url], - description: definition[:description], - is_enabled: config&.is_enabled || false, - plug_play_id: config&.plug_play_id, - plug_play_token: config&.plug_play_token.present? ? '****' : nil, - last_test: config ? { - at: config.last_tested_at, - status: config.last_test_status, - error: config.last_test_error, - duration: config.last_test_duration_ms - } : nil - } - end + def index + configs = ::Jasmine::ToolConfig.where(inbox: @inbox).index_by(&:tool_key) + render json: serialize_tools(configs) + end - render json: tools - end + def update + return render(json: { error: 'Invalid tool key' }, status: :bad_request) unless valid_tool_key?(params[:id]) - def update - tool_key = params[:id] # Using :id from route as tool_key - - unless ::Jasmine::ToolConfig::DEFINITIONS.key?(tool_key) - return render json: { error: 'Invalid tool key' }, status: :bad_request - end + config = find_config(params[:id]) + update_config_attributes(config) - config = ::Jasmine::ToolConfig.find_or_initialize_by( - account: Current.account, - inbox: @inbox, - tool_key: tool_key - ) - - # Update attributes - config.is_enabled = params[:is_enabled] - config.plug_play_id = params[:plug_play_id] - - # Secure token update: only update if present and not masked/empty - new_token = params[:plug_play_token] - if new_token.present? && new_token != '****' - config.plug_play_token = new_token - end - - if config.save - render json: { - key: config.tool_key, - is_enabled: config.is_enabled, - plug_play_id: config.plug_play_id, - plug_play_token: '****' - } - else - render json: { error: config.errors.full_messages.join(', ') }, status: :unprocessable_entity - end - end - - def test - tool_key = params[:id] - - begin - runner = ::Jasmine::ToolRunner.new(@inbox, tool_key) - result = runner.run - render json: result - rescue => e - Rails.logger.error "[JasmineTools] Test failed: #{e.try(:message)}" - render json: { success: false, error: "Server Error: #{e.try(:message)}" }, status: :internal_server_error - end - end - - private - - def fetch_inbox - @inbox = Current.account.inboxes.find(params[:inbox_id]) - end - end - end - end + if config.save + render json: success_payload(config) + else + render(json: { error: config.errors.full_messages.join(', ') }, status: :unprocessable_entity) end end + + def test + tool_key = params[:id] + + begin + runner = ::Jasmine::ToolRunner.new(@inbox, tool_key) + result = runner.run + render json: result + rescue StandardError => e + Rails.logger.error "[JasmineTools] Test failed: #{e.try(:message)}" + render json: { success: false, error: "Server Error: #{e.try(:message)}" }, status: :internal_server_error + end + end + + private + + def fetch_inbox + @inbox = Current.account.inboxes.find(params[:inbox_id]) + end + + def valid_tool_key?(key) + ::Jasmine::ToolConfig::DEFINITIONS.key?(key) + end + + def find_config(key) + ::Jasmine::ToolConfig.find_or_initialize_by(account: Current.account, inbox: @inbox, tool_key: key) + end + + def update_config_attributes(config) + config.is_enabled = params[:is_enabled] + config.plug_play_id = params[:plug_play_id] + new_token = params[:plug_play_token] + config.plug_play_token = new_token if new_token.present? && new_token != '****' + end + + def success_payload(config) + { key: config.tool_key, is_enabled: config.is_enabled, plug_play_id: config.plug_play_id, plug_play_token: '****' } + end + + def serialize_tools(configs) + ::Jasmine::ToolConfig::DEFINITIONS.map do |key, definition| + build_tool_hash(key, definition, configs[key]) + end + end + + def build_tool_hash(key, definition, config) + { + key: key, + name: definition[:name], + method: definition[:method].to_s.upcase, + url: definition[:url], + description: definition[:description], + is_enabled: config&.is_enabled || false, + plug_play_id: config&.plug_play_id, + plug_play_token: config&.plug_play_token.present? ? '****' : nil, + last_test: serialize_last_test(config) + } + end + + def serialize_last_test(config) + return unless config + + { + at: config.last_tested_at, + status: config.last_test_status, + error: config.last_test_error, + duration: config.last_test_duration_ms + } + end end diff --git a/progresso/2026-01-25_correcao_lint_backend.md b/progresso/2026-01-25_correcao_lint_backend.md new file mode 100644 index 0000000..7459383 --- /dev/null +++ b/progresso/2026-01-25_correcao_lint_backend.md @@ -0,0 +1,47 @@ +# Correção de Lint e Refatoração Backend + +## Contexto + +Ocorreram diversos erros de Lint (RuboCop) no backend, bloqueando o CI/CD ou a qualidade do código. Os principais arquivos afetados foram `MessageBuilder` e `ToolsController`. + +## Ações Realizadas + +### 1. Refatoração `MessageBuilder` (`app/builders/messages/message_builder.rb`) + +- **Problema:** Classe muito longa (`Metrics/ClassLength`) e complexidade ciclomática alta. +- **Solução:** + - Lógica de `file_type` extraída para método auxiliar `resolve_file_type`. + - Métodos `extract_automation_rule`, `extract_in_reply_to` e `should_process_liquid?` compactados (one-liners). + - Redução geral de linhas e complexidade. + +### 2. Refatoração `ToolsController` (`app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb`) + +- **Problema:** Métodos longos (`Metrics/MethodLength`) e complexos (`Metrics/AbcSize`). +- **Solução:** + - Extração da validação de chave para `valid_tool_key?`. + - Extração da busca de config para `find_config`. + - Extração da atualização de atributos para `update_config_attributes`. + - Extração da serialização de resposta para `success_payload`, `build_tool_hash` e `serialize_last_test`. + - Correção de `Style/EmptyElse`. + +### 3. Correções Gerais + +- **Specs (`whatsapp_spec.rb`, `contact_spec.rb`):** Quebra de comentários longos para satisfazer `Layout/LineLength`. +- **StringLiterals:** Padronização para aspas simples. +- **ClassAndModuleChildren:** Formato compacto adotado onde necessário. + +## Validação + +- **RuboCop:** 0 ofensas. +- **RSpec:** 0 falhas nos testes unitários das classes afetadas. + +## Como Reverter + +Checkouts nos arquivos originais: + +```bash +git checkout app/builders/messages/message_builder.rb +git checkout app/controllers/api/v1/accounts/inboxes/jasmine/tools_controller.rb +git checkout spec/models/channel/whatsapp_spec.rb +git checkout spec/models/contact_spec.rb +``` diff --git a/spec/factories/jasmine_factories.rb b/spec/factories/jasmine_factories.rb index 152a797..c00728d 100644 --- a/spec/factories/jasmine_factories.rb +++ b/spec/factories/jasmine_factories.rb @@ -2,7 +2,7 @@ FactoryBot.define do factory :jasmine_inbox_config, class: 'Jasmine::InboxConfig' do association :account association :inbox - name { "Test Jasmine" } + name { 'Test Jasmine' } is_enabled { true } end @@ -10,7 +10,7 @@ FactoryBot.define do association :account sequence(:name) { |n| "Collection #{n}" } visibility { :private } - + trait :private do visibility { :private } association :owner_inbox, factory: :inbox @@ -32,6 +32,6 @@ FactoryBot.define do factory :jasmine_document, class: 'Jasmine::Document' do association :account association :collection, factory: :jasmine_collection - content { "Sample Content" } + content { 'Sample Content' } end end diff --git a/spec/models/channel/whatsapp_spec.rb b/spec/models/channel/whatsapp_spec.rb index e1e74f4..f47d9ae 100755 --- a/spec/models/channel/whatsapp_spec.rb +++ b/spec/models/channel/whatsapp_spec.rb @@ -22,7 +22,8 @@ # Indexes # # index_channel_whatsapp_on_phone_number (phone_number) UNIQUE -# index_channel_whatsapp_provider_connection (provider_connection) WHERE ((provider)::text = ANY ((ARRAY['baileys'::character varying, 'zapi'::character varying])::text[])) USING gin +# index_channel_whatsapp_provider_connection (provider_connection) +# WHERE ((provider)::text = ANY ((ARRAY['baileys'::character varying, 'zapi'::character varying])::text[])) USING gin # require 'rails_helper' require Rails.root.join 'spec/models/concerns/reauthorizable_shared.rb' diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index 156931a..48d98ab 100755 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -32,9 +32,11 @@ # index_contacts_on_company_id (company_id) # index_contacts_on_lower_email_account_id (lower((email)::text), account_id) # index_contacts_on_name_email_phone_number_identifier (name,email,phone_number,identifier) USING gin -# index_contacts_on_nonempty_fields (account_id,email,phone_number,identifier) WHERE (((email)::text <> ''::text) OR ((phone_number)::text <> ''::text) OR ((identifier)::text <> ''::text)) +# index_contacts_on_nonempty_fields (account_id,email,phone_number,identifier) +# WHERE (((email)::text <> ''::text) OR ((phone_number)::text <> ''::text) OR ((identifier)::text <> ''::text)) # index_contacts_on_phone_number_and_account_id (phone_number,account_id) -# index_resolved_contact_account_id (account_id) WHERE (((email)::text <> ''::text) OR ((phone_number)::text <> ''::text) OR ((identifier)::text <> ''::text)) +# index_resolved_contact_account_id (account_id) +# WHERE (((email)::text <> ''::text) OR ((phone_number)::text <> ''::text) OR ((identifier)::text <> ''::text)) # uniq_email_per_account_contact (email,account_id) UNIQUE # uniq_identifier_per_account_contact (identifier,account_id) UNIQUE # diff --git a/spec/models/jasmine/inbox_collection_spec.rb b/spec/models/jasmine/inbox_collection_spec.rb index 74098e1..db6ec1c 100644 --- a/spec/models/jasmine/inbox_collection_spec.rb +++ b/spec/models/jasmine/inbox_collection_spec.rb @@ -32,11 +32,11 @@ RSpec.describe Jasmine::InboxCollection do let!(:account) { create(:account) } let!(:inbox) { create(:inbox, account: account) } let!(:other_inbox) { create(:inbox, account: account) } - + let!(:private_coll) { create(:jasmine_collection, :private, owner_inbox: inbox, account: account) } let!(:shared_coll) { create(:jasmine_collection, :shared, account: account) } - context 'validations' do + context 'when linking collections' do it 'allows linking private collection to owner inbox' do link = build(:jasmine_inbox_collection, inbox: inbox, collection: private_coll, account: account) expect(link).to be_valid @@ -45,7 +45,7 @@ RSpec.describe Jasmine::InboxCollection do it 'prevents linking private collection to non-owner inbox' do link = build(:jasmine_inbox_collection, inbox: other_inbox, collection: private_coll, account: account) expect(link).not_to be_valid - expect(link.errors[:base]).to include("Private collections can only be linked to their owner inbox") + expect(link.errors[:base]).to include('Private collections can only be linked to their owner inbox') end it 'allows linking shared collection to any inbox in account' do diff --git a/spec/services/jasmine/semantic_search_service_spec.rb b/spec/services/jasmine/semantic_search_service_spec.rb index 71a9f0a..69dc651 100644 --- a/spec/services/jasmine/semantic_search_service_spec.rb +++ b/spec/services/jasmine/semantic_search_service_spec.rb @@ -3,19 +3,15 @@ require 'rails_helper' RSpec.describe Jasmine::SemanticSearchService do subject { described_class.new(inbox) } - let!(:account) { create(:account) } - let!(:inbox) { create(:inbox, account: account) } - let!(:config) { create(:jasmine_inbox_config, inbox: inbox, account: account, is_enabled: true) } + let(:account) { create(:account) } + let(:inbox) { create(:inbox, account: account) } + let(:config) { create(:jasmine_inbox_config, inbox: inbox, account: account, is_enabled: true) } - let!(:collection_private) { create(:jasmine_collection, name: 'Private', visibility: :private, owner_inbox: inbox, account: account) } - let!(:collection_shared) { create(:jasmine_collection, name: 'Shared', visibility: :shared, account: account) } + let(:collection_private) { create(:jasmine_collection, name: 'Private', visibility: :private, owner_inbox: inbox, account: account) } + let(:collection_shared) { create(:jasmine_collection, name: 'Shared', visibility: :shared, account: account) } - # Link collections: Private (High Priority), Shared (Low Priority) - let!(:link_private) { create(:jasmine_inbox_collection, inbox: inbox, collection: collection_private, priority: 10, account: account) } - let!(:link_shared) { create(:jasmine_inbox_collection, inbox: inbox, collection: collection_shared, priority: 0, account: account) } - - let!(:doc_private) { create(:jasmine_document, collection: collection_private, content: 'Private Secret', account: account) } - let!(:doc_shared) { create(:jasmine_document, collection: collection_shared, content: 'Shared Knowledge', account: account) } + let(:doc_private) { create(:jasmine_document, collection: collection_private, content: 'Private Secret', account: account) } + let(:doc_shared) { create(:jasmine_document, collection: collection_shared, content: 'Shared Knowledge', account: account) } # Mock Embedding Service behavior by creating chunks directly with known vectors # Query Vector: [1.0, 0.0, ...] @@ -24,6 +20,19 @@ RSpec.describe Jasmine::SemanticSearchService do # Irrelevant: [0.0, 1.0, ...] -> Distance ~1.0 before do + # Ensure all `let` variables are initialized + account + inbox + config + collection_private + collection_shared + doc_private + doc_shared + + # Link collections + create(:jasmine_inbox_collection, inbox: inbox, collection: collection_private, priority: 10, account: account) + create(:jasmine_inbox_collection, inbox: inbox, collection: collection_shared, priority: 0, account: account) + # Create chunks manually to bypass job/api dependency create_chunk(doc_private, [0.9] + ([0.0]*1535)) create_chunk(doc_shared, [0.8] + ([0.0]*1535)) diff --git a/test_multi_agent_flow.rb b/test_multi_agent_flow.rb index a9ea954..fdb3b0d 100644 --- a/test_multi_agent_flow.rb +++ b/test_multi_agent_flow.rb @@ -1,22 +1,21 @@ # test_multi_agent_flow.rb assistant = Captain::Assistant.find_by(name: 'Jasmine (Hotel Prime)') -account = assistant.account def simulate_handoff(assistant, user_msg) puts "\n==========================================================" puts "USUÁRIO: #{user_msg}" - + # Usando o motor Multi-Agente (V2) sem conversation real para o Playground runner = Captain::Assistant::AgentRunnerService.new(assistant: assistant) - + # Capturando o resultado do motor result = runner.generate_response(message_history: [{ role: 'user', content: user_msg }]) - + puts "AGENTE QUE RESPONDEU: #{result['agent_name']}" puts "RESPOSTA FINAL: #{result['response']}" puts "RACIOCÍNIO: #{result['reasoning']}" puts "SENTIMENTO: #{result['sentiment']}" - puts "==========================================================" + puts '==========================================================' end -simulate_handoff(assistant, "Gostaria de agendar um quarto para amanhã às 22h") \ No newline at end of file +simulate_handoff(assistant, 'Gostaria de agendar um quarto para amanhã às 22h') diff --git a/update_real_data.rb b/update_real_data.rb index d1a1d36..87cf3d2 100644 --- a/update_real_data.rb +++ b/update_real_data.rb @@ -12,7 +12,6 @@ if channel puts 'Updating existing channel...' channel.phone_number = phone_number channel.provider_config['webhook_url'] = webhook_url - channel.save(validate: false) else puts 'Creating new channel...' account = Account.first @@ -26,8 +25,8 @@ else 'webhook_url' => webhook_url } ) - channel.save(validate: false) end +channel.save(validate: false) # Ensure inbox exists inbox = Inbox.find_by(channel: channel)