chatwoot-develop/enterprise/app/services/captain/tools/update_contact_tool.rb

89 lines
2.8 KiB
Ruby

class Captain::Tools::UpdateContactTool < BaseTool
def name
'update_contact'
end
def description
'Updates the contact information (Name and CPF) for the current conversation customer. Use this when the user provides their details.'
end
def tool_parameters_schema
{
type: 'object',
properties: {
nome: {
type: 'string',
description: 'Nome completo do cliente para cadastro.'
},
cpf: {
type: 'string',
description: 'CPF do cliente (apenas números ou formatado).'
}
},
required: []
}
end
def execute(*args, **params)
actual_params = resolve_params(args, params)
File.open(Rails.root.join('log/tool_debug.log'), 'a') do |f|
f.puts "[#{Time.zone.now}] STARTING UpdateContactTool with params: #{actual_params}"
end
name = actual_params[:nome] || actual_params[:name]
cpf = actual_params[:cpf]
return 'Erro: Nenhum dado fornecido (nome ou cpf).' if name.blank? && cpf.blank?
ensure_conversation_context!
unless @conversation&.contact
msg = "Erro Crítico: Contexto de conversa ou contato não disponível. Params: #{actual_params}"
File.open(Rails.root.join('log/tool_debug.log'), 'a') { |f| f.puts "[#{Time.zone.now}] FAILURE: #{msg}" }
return msg
end
contact = @conversation.contact
contact.name = name if name.present?
contact.custom_attributes ||= {}
contact.custom_attributes['cpf'] = cpf if cpf.present?
if contact.save
update_sticky_state(name: contact.name, cpf: contact.custom_attributes['cpf'])
msg = "Dados atualizados com sucesso. Nome: #{contact.name}, CPF: #{contact.custom_attributes['cpf']}"
File.open(Rails.root.join('log/tool_debug.log'), 'a') { |f| f.puts "[#{Time.zone.now}] SUCCESS: #{msg}" }
else
msg = "Erro ao salvar dados: #{contact.errors.full_messages.join(', ')}"
File.open(Rails.root.join('log/tool_debug.log'), 'a') { |f| f.puts "[#{Time.zone.now}] FAILURE: #{msg}" }
end
msg
end
private
# Helper to ensure we have a conversation object
def ensure_conversation_context!
return if @conversation.present?
end
def update_sticky_state(name:, cpf:)
return unless @conversation.respond_to?(:active_scenario_state)
return if name.blank? && cpf.blank?
state = @conversation.active_scenario_state || {}
collected = (state['collected'] || {}).merge(
'name' => name.presence,
'cpf' => cpf.presence
).compact
@conversation.update!(
active_scenario_state: state.merge(
'collected' => collected,
'updated_at' => Time.current.iso8601
)
)
rescue StandardError => e
Rails.logger.warn "[UpdateContactTool] Failed to update sticky state: #{e.message}"
end
end