fix(umind): prohíbe inventar URLs y contactos, y hace clickeables los enlaces

El agente estaba dando https://escuelametropolitana.com/login.php, una
ruta que no existe: el prompt decía "no inventes datos" pero no decía
nada de URLs, teléfonos ni correos, que es justo lo que un modelo
confabula con más confianza porque "sabe" que un login suele estar en
/login.php. Un enlace inventado deja a la persona sin poder completar el
trámite, peor que no responder.

- Regla explícita: URLs, teléfonos, WhatsApp y correos solo si aparecen
  LITERALMENTE en los resultados de buscar_conocimiento, copiados carácter
  por carácter, sin completar rutas ni cambiar el dominio.
- Widget: los enlaces se vuelven clickeables. El contenido sale de páginas
  crawleadas, así que NO se inserta como HTML: se parte por URL y cada
  trozo va con createTextNode o un <a> con rel=noopener noreferrer
  nofollow. Verificado que un <img onerror> o un <script> en la respuesta
  quedan escapados como texto inerte.
- WhatsApp: preview_url=true, así el primer enlace se ve como tarjeta
  clickeable en vez de texto pelado.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-13 12:46:46 -05:00
co-authored by Claude Sonnet 5
parent 4995c5fca5
commit 7146539f86
3 changed files with 34 additions and 3 deletions
+4 -1
View File
@@ -169,7 +169,10 @@ func enviarMensajeWhatsApp(phoneNumberID, accessToken, to, texto string) error {
"messaging_product": "whatsapp",
"to": to,
"type": "text",
"text": map[string]string{"body": texto},
// preview_url hace que WhatsApp renderice el primer enlace del mensaje
// como tarjeta clickeable con título e imagen, en vez de dejarlo como
// texto pelado. Sin esto los enlaces que manda el agente se ven crudos.
"text": map[string]interface{}{"body": texto, "preview_url": true},
}
body, err := json.Marshal(payload)
if err != nil {