iachat/spec/enterprise/models/concerns/agentable_concierge_spec.rb
Rodribm10 7b009cf47f feat(lifecycle): inject concierge context into Captain orchestrator prompt
Adds concierge.* and reservation.* Liquid variables to agent_instructions
so Sofia's orchestrator_prompt receives unit persona/knowledge/variables
and reservation data resolved from conversation.custom_attributes.current_unit_id.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:25:16 -03:00

64 lines
2.2 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Concerns::Agentable, type: :model do
let(:account) { create(:account) }
let(:inbox) { create(:inbox, account: account) }
let(:brand) { create(:captain_brand, account: account) }
let(:unit) do
Captain::Unit.create!(
account: account,
brand: brand,
name: 'Prime Águas Lindas',
concierge_config: {
'persona_name' => 'Sofia',
'knowledge' => 'Hotel com café às 7h',
'variables' => { 'wifi_password' => 'abc123' }
}
)
end
let(:contact) { create(:contact, account: account, name: 'João Silva') }
let(:conversation) do
create(:conversation,
account: account, inbox: inbox, contact: contact,
custom_attributes: { 'current_unit_id' => unit.id })
end
let(:assistant) do
create(:captain_assistant,
account: account,
orchestrator_prompt: '{{ concierge.persona_name }} in {{ concierge.unit_name }} knows: {{ concierge.knowledge }}')
end
def mock_context_for(conv)
state = { conversation: { id: conv.id } }.with_indifferent_access
ctx = instance_double(Agents::RunContext)
allow(ctx).to receive(:context).and_return({ state: state })
ctx
end
describe '#agent_instructions concierge injection' do
it 'resolves concierge context from current_unit_id' do
ctx = mock_context_for(conversation)
rendered = assistant.agent_instructions(ctx)
expect(rendered).to include('Sofia in Prime Águas Lindas')
expect(rendered).to include('Hotel com café às 7h')
end
it 'falls back to empty strings when current_unit_id missing' do
conversation.update!(custom_attributes: {})
ctx = mock_context_for(conversation)
rendered = assistant.agent_instructions(ctx)
expect(rendered).to be_a(String)
end
it 'falls back gracefully when conversation id is nil' do
state = { conversation: {} }.with_indifferent_access
ctx = instance_double(Agents::RunContext)
allow(ctx).to receive(:context).and_return({ state: state })
rendered = assistant.agent_instructions(ctx)
expect(rendered).to be_a(String)
end
end
end