fix(captain/hermes-builder): callback resolve session via last_session
Bug: Hermes nao propaga chat_id no metadata do callback. Callback controller nao conseguia resolver qual session armazenar a resposta. WARN "no session_key resolvable — ignorando" descartava todas as respostas do Construtor. Fix: HermesBuilder::Storage.remember_last_session() grava ultima session por account quando admin chama /start ou /create. Callback le essa key via last_session_for(account_id). MVP-safe pra 1 admin por conta. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f362949579
commit
5f6aed05c9
@ -30,35 +30,14 @@ class Webhooks::Captain::HermesBuilderCallbackController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Estratégia: usar o session_id do metadata (Hermes propaga o chat_id).
|
# Hermes nao propaga chat_id no metadata da resposta de callback, entao
|
||||||
# Fallback: account_id da query string + último user que mandou msg
|
# usamos a ultima sessao ativa do account (gravada por
|
||||||
# (raro, mas evita perder resposta).
|
# HermesBuilder::Storage.remember_last_session no /start e /create).
|
||||||
|
# MVP-safe pra 1 admin por vez por conta.
|
||||||
def resolve_session_key
|
def resolve_session_key
|
||||||
chat_id = params[:metadata]&.[](:chat_id) || params.dig(:metadata, 'chat_id')
|
|
||||||
if chat_id.is_a?(String) && chat_id.include?('builder-')
|
|
||||||
# Formato: webhook:construtor-admin:session:builder-<account>-<user>
|
|
||||||
session_id = chat_id.split(':').last
|
|
||||||
return "hermes_builder:#{session_id}" if session_id.start_with?('builder-')
|
|
||||||
end
|
|
||||||
|
|
||||||
account_id = params[:account_id]
|
account_id = params[:account_id]
|
||||||
return nil if account_id.blank?
|
return nil if account_id.blank?
|
||||||
|
|
||||||
# Fallback: pega últimas 5 sessões do account, retorna a mais recente
|
HermesBuilder::Storage.last_session_for(account_id)
|
||||||
# com mensagens. Aceitável pra MVP com 1 admin testando por vez.
|
|
||||||
recent_session_key_for(account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def recent_session_key_for(account_id)
|
|
||||||
return nil unless Rails.cache.respond_to?(:redis)
|
|
||||||
|
|
||||||
pattern = "hermes_builder:builder-#{account_id}-*"
|
|
||||||
keys = Rails.cache.redis.with { |c| c.keys(pattern) }
|
|
||||||
return nil if keys.blank?
|
|
||||||
|
|
||||||
keys.first.sub(/^.*?(hermes_builder:.*)$/, '\1')
|
|
||||||
rescue StandardError => e
|
|
||||||
Rails.logger.warn("[HermesBuilder::Callback] recent_session_key fallback failed: #{e.class} - #{e.message}")
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -21,6 +21,7 @@ class Api::V1::Accounts::Captain::HermesBuilderController < Api::V1::Accounts::B
|
|||||||
return render json: { error: 'Texto vazio' }, status: :bad_request if text.blank?
|
return render json: { error: 'Texto vazio' }, status: :bad_request if text.blank?
|
||||||
|
|
||||||
HermesBuilder::Storage.append(session_key, role: 'user', content: text)
|
HermesBuilder::Storage.append(session_key, role: 'user', content: text)
|
||||||
|
HermesBuilder::Storage.remember_last_session(Current.account.id, session_key)
|
||||||
HermesBuilder::Dispatcher.send_to_construtor(session_id: session_id, message: text)
|
HermesBuilder::Dispatcher.send_to_construtor(session_id: session_id, message: text)
|
||||||
|
|
||||||
render json: { ok: true, session_id: session_id }, status: :accepted
|
render json: { ok: true, session_id: session_id }, status: :accepted
|
||||||
@ -34,6 +35,7 @@ class Api::V1::Accounts::Captain::HermesBuilderController < Api::V1::Accounts::B
|
|||||||
# quando admin clica "Iniciar" — sem ter que digitar primeira msg.
|
# quando admin clica "Iniciar" — sem ter que digitar primeira msg.
|
||||||
def start
|
def start
|
||||||
HermesBuilder::Storage.clear(session_key)
|
HermesBuilder::Storage.clear(session_key)
|
||||||
|
HermesBuilder::Storage.remember_last_session(Current.account.id, session_key)
|
||||||
HermesBuilder::Dispatcher.send_to_construtor(
|
HermesBuilder::Dispatcher.send_to_construtor(
|
||||||
session_id: session_id,
|
session_id: session_id,
|
||||||
message: '__START__ Inicie o fluxo de criação de novo agente Hermes. Comece pela primeira pergunta do Bloco 1 (nome do agente).'
|
message: '__START__ Inicie o fluxo de criação de novo agente Hermes. Comece pela primeira pergunta do Bloco 1 (nome do agente).'
|
||||||
|
|||||||
@ -29,4 +29,15 @@ module HermesBuilder::Storage
|
|||||||
def clear(session_key)
|
def clear(session_key)
|
||||||
Rails.cache.delete(session_key)
|
Rails.cache.delete(session_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Última sessão ativa por account — usada pelo callback do Hermes pra
|
||||||
|
# roteamento (Hermes nao propaga chat_id no metadata da resposta).
|
||||||
|
# Aceitavel pra MVP com 1 admin por vez por conta.
|
||||||
|
def remember_last_session(account_id, session_key)
|
||||||
|
Rails.cache.write("hermes_builder:last_session:account:#{account_id}", session_key, expires_in: TTL)
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_session_for(account_id)
|
||||||
|
Rails.cache.read("hermes_builder:last_session:account:#{account_id}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user