fix(umind): la respuesta genérica no quedaba en la conversación, y eso perpetuaba el error

Cuando el agente caía en "dame un poco más de detalle", esa respuesta no se
guardaba. En Conversaciones quedaban las preguntas del visitante una tras otra
sin ninguna respuesta, así que el dueño no tenía forma de enterarse de que su
agente estaba fallando — justo la pantalla donde debería verlo.

Lo grave es lo otro: ese historial se le reenvía al modelo en cada turno. Un
modelo que ve cuatro preguntas seguidas y ninguna respuesta lee una
conversación rota, se confunde y vuelve a fallar. El primer error se
perpetuaba solo, y por eso una vez que empezaba ya no salía más.

Ahora se guarda siempre lo que el visitante recibió, sea la respuesta buena o
la genérica.

Las sesiones que ya quedaron con el historial roto se normalizan solas: la
ventana es de 6 mensajes, así que después de un par de intercambios buenos los
huecos salen de contexto.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-21 19:41:13 -05:00
co-authored by Claude Opus 5
parent cdfbff605e
commit a8cc5c6289
2 changed files with 50 additions and 1 deletions
+8 -1
View File
@@ -374,10 +374,17 @@ func ProcessWidgetMessage(agente *models.UmindAgente, sessionID, userText string
// Antes de dar el mensaje genérico, usar lo que el modelo ya escribió.
if strings.TrimSpace(ultimoTextoParcial) != "" {
finalResponse = ultimoTextoParcial
_ = models.SaveUmindMensaje(agente.ID, sessionID, "assistant", finalResponse)
} else {
finalResponse = "Un momento, por favor — dame un poco más de detalle sobre lo que necesitas."
}
// Se guarda igual, aunque sea el mensaje genérico. Sin esto quedaba una
// conversación con varios mensajes del visitante y ninguna respuesta:
// no se veía en Conversaciones —el dueño no se enteraba de que su
// agente estaba fallando— y, peor, ese historial roto se le reenviaba
// al modelo en el turno siguiente. Un modelo que ve cuatro preguntas
// seguidas sin una sola respuesta se confunde y vuelve a fallar, así
// que el primer error se perpetuaba solo.
_ = models.SaveUmindMensaje(agente.ID, sessionID, "assistant", finalResponse)
}
return finalResponse, nil
}
+42
View File
@@ -0,0 +1,42 @@
package services
import (
"os"
"strings"
"testing"
)
// Todo lo que ve el visitante tiene que quedar guardado, incluido el mensaje
// genérico de cuando algo falla. Sin eso pasaban dos cosas, y la segunda es la
// grave:
//
// 1. En Conversaciones se veían las preguntas sin ninguna respuesta, así que
// el dueño no se enteraba de que su agente estaba fallando.
// 2. Ese historial roto se le reenviaba al modelo en el turno siguiente. Un
// modelo que ve cuatro preguntas seguidas sin una sola respuesta se
// confunde y vuelve a fallar: el primer error se perpetuaba solo.
func TestLaRespuestaAlVisitanteSiempreQuedaGuardada(t *testing.T) {
b, err := os.ReadFile("umind_agent_service.go")
if err != nil {
t.Fatal(err)
}
fuente := string(b)
// El bloque del fallback tiene que guardar.
i := strings.Index(fuente, `if finalResponse == "" {`)
if i < 0 {
t.Fatal("no encontré el bloque de fallback")
}
bloque := fuente[i:]
if j := strings.Index(bloque, "\n\treturn finalResponse"); j > 0 {
bloque = bloque[:j]
}
if !strings.Contains(bloque, "SaveUmindMensaje") {
t.Error("el mensaje genérico no se guarda: la conversación queda con preguntas sin respuesta y el historial roto se reenvía al modelo")
}
// Y el mensaje del visitante también, desde antes del bucle.
if !strings.Contains(fuente, `SaveUmindMensaje(agente.ID, sessionID, "user", userText)`) {
t.Error("no se guarda el mensaje del visitante")
}
}