fix(captain): captain_unit_id em captain_assistants — fim do lookup quebrado

Captain::Assistant agora aponta direto pra Captain::Unit. Antes a relação
ia via CaptainInbox, mas isso quebrou quando re-apontamos as inboxes pros
Hermes — assistants captain_interno (Juliana, Bianca, Lara, Nina,
Valentina) ficaram SEM CaptainInbox associada e o lookup
unit_for(assistant) retornava nil.

Resultado: get_assistant_pricing(3) (Lara) caía no fallback de scenario
text. Construtor reportava "veio cenário/prompt, não tabela estruturada".

Migration adiciona captain_unit_id (FK opcional). Backfill explícito:
- 1 Juliana → unit 3 (Qnn01)
- 2 Bianca → unit 2 (PrimeAL)
- 3 Lara → unit 2 (PrimeAL — mesmo brand)
- 4 Nina → unit 5 (Express)
- 6 Valentina → unit 4 (Dolce Amore)
- 9 Lara.H → unit 2 (via parent_assistant_id=3)

Tools get_assistant_pricing_tool e save_agent_spec_tool atualizados pra
usar assistant.captain_unit primeiro (nova relação direta), com fallback
pro CaptainInbox se nulo (pra retrocompatibilidade).

Validado live: tool retorna grid markdown com Stilo/Alexa/Hidromassagem
em Seg-Qua + Qui-Dom corretamente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rodribm10 2026-05-02 12:45:53 -03:00
parent 22eab86302
commit 5ef59ecc12
5 changed files with 23 additions and 1 deletions

View File

@ -0,0 +1,9 @@
class AddCaptainUnitIdToCaptainAssistants < ActiveRecord::Migration[7.1]
def change
add_reference :captain_assistants,
:captain_unit,
foreign_key: { to_table: :captain_units, on_delete: :nullify },
null: true,
index: true
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2026_05_02_120100) do
ActiveRecord::Schema[7.1].define(version: 2026_05_02_160000) do
# These extensions should be enabled to support this database
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
@ -342,7 +342,9 @@ ActiveRecord::Schema[7.1].define(version: 2026_05_02_120100) do
t.string "hermes_subscription_secret"
t.integer "hermes_port"
t.bigint "parent_assistant_id"
t.bigint "captain_unit_id"
t.index ["account_id"], name: "index_captain_assistants_on_account_id"
t.index ["captain_unit_id"], name: "index_captain_assistants_on_captain_unit_id"
t.index ["engine"], name: "index_captain_assistants_on_engine"
t.index ["hermes_port"], name: "idx_captain_assistants_hermes_port_unique", unique: true, where: "(hermes_port IS NOT NULL)"
t.index ["parent_assistant_id"], name: "index_captain_assistants_on_parent_assistant_id"
@ -2166,6 +2168,7 @@ ActiveRecord::Schema[7.1].define(version: 2026_05_02_120100) do
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "captain_assets", "accounts"
add_foreign_key "captain_assets", "captain_suites"
add_foreign_key "captain_assistants", "captain_units", on_delete: :nullify
add_foreign_key "captain_brands", "accounts"
add_foreign_key "captain_configurations", "accounts"
add_foreign_key "captain_contact_memories", "accounts", on_delete: :cascade

View File

@ -21,15 +21,21 @@
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint not null
# captain_unit_id :bigint
# parent_assistant_id :bigint
#
# Indexes
#
# idx_captain_assistants_hermes_port_unique (hermes_port) UNIQUE WHERE (hermes_port IS NOT NULL)
# index_captain_assistants_on_account_id (account_id)
# index_captain_assistants_on_captain_unit_id (captain_unit_id)
# index_captain_assistants_on_engine (engine)
# index_captain_assistants_on_parent_assistant_id (parent_assistant_id)
#
# Foreign Keys
#
# fk_rails_... (captain_unit_id => captain_units.id) ON DELETE => nullify
#
class Captain::Assistant < ApplicationRecord
include Avatarable
include Concerns::CaptainToolsHelpers
@ -38,6 +44,7 @@ class Captain::Assistant < ApplicationRecord
self.table_name = 'captain_assistants'
belongs_to :account
belongs_to :captain_unit, class_name: 'Captain::Unit', optional: true
has_many :documents, class_name: 'Captain::Document', dependent: :destroy_async
has_many :responses, class_name: 'Captain::AssistantResponse', dependent: :destroy_async
has_many :captain_inboxes,

View File

@ -68,6 +68,8 @@ class Captain::Mcp::Tools::GetAssistantPricingTool < Captain::Mcp::Tools::BaseTo
end
def unit_for(assistant)
return assistant.captain_unit if assistant.captain_unit_id.present?
ci = CaptainInbox.find_by(captain_assistant_id: assistant.id)
return nil if ci.blank?

View File

@ -132,6 +132,7 @@ class Captain::Mcp::Tools::SaveAgentSpecTool < Captain::Mcp::Tools::BaseTool
def parent_unit_for(parent)
return nil if parent.nil?
return parent.captain_unit if parent.captain_unit_id.present?
ci = parent.captain_inboxes.first
return nil if ci.nil?