Commit Graph
5 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Sonnet 5 997e3cc790 feat: log de auditoría técnica por agente
Nueva tabla umind_eventos_log + tab "Auditoría" en el panel: errores y
eventos que hasta ahora solo se podían ver pidiendo los logs del servidor
(fallos al llamar al AI, respuestas sin texto usable, tools/webhooks que
fallan, tokens de correo que no se pueden refrescar, firmas de WhatsApp
inválidas, errores procesando mensajes de Telegram/WhatsApp) quedan
registrados por agente, visibles directo en el panel con el JSON crudo
expandible para diagnosticar sin acceso al servidor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 09:58:59 -05:00
Lizandro GuarnizoandClaude Sonnet 5 f3f2f421d6 feat: uMind pasa a multi-agente por tenant
Un tenant (negocio/sitio, dueño de los dominios permitidos) puede tener
varios UmindAgente independientes (ej. "Ventas", "Soporte"), cada uno con
su propia config de IA, tono, base de conocimiento, tools, canales y
conexión de correo. El site_key también pasa a ser por agente, así cada
uno tiene su propio <script> de widget embebible y su propio color.

Backend:
- Nuevo modelo UmindAgente (pkg/models/umind_agente.go), con SiteKey,
  AiConfigID, Tono, MensajeBienvenida y Color — campos que antes vivían en
  UmindTenant y se sacan de ahí (las columnas viejas quedan huérfanas sin
  usar, no se hace DROP COLUMN).
- UmindDocumento, UmindChunk, UmindHerramienta, UmindCanal, UmindConexion y
  UmindMensaje pasan de TenantID a AgenteID. El campo se agrega sin
  "not null" para no romper el ALTER TABLE en Postgres sobre tablas que ya
  tienen filas (ej. emetropolitana).
- migrations.MigrarUmindAgentes(): idempotente, crea un agente "Principal"
  por cada tenant existente heredando lo que ya tenía configurado, y mueve
  sus datos de tenant_id a agente_id. Corre en cada arranque normal, mismo
  criterio que los Seed* — nada se rompe para los tenants ya en producción.
- Motor del agente, widget, canales (Telegram/WhatsApp) y OAuth de correo
  ahora operan sobre UmindAgente; el tenant solo se consulta para el
  chequeo de dominio permitido y el nombre del negocio que ve el visitante.

Frontend: nueva jerarquía de navegación tenant → lista de agentes
(TenantAgentes.vue) → detalle de un agente (AgenteDetail.vue, antes
TenantDetail.vue) con las mismas 6 tabs de siempre, ahora por agente. El
modal de tenant en el sidebar se achica a nombre/dominios/activo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 09:30:06 -05:00
Lizandro GuarnizoandClaude Sonnet 5 8c1e754ab3 feat: rediseña el widget embebible (ícono AI, color configurable, animaciones)
El bubble era un emoji 💬 sobre un color fijo hardcodeado en el JS. Ahora:
- Ícono nuevo (spark/sparkle, el motivo visual estándar de "asistente IA"
  hoy) en vez del emoji, con anillo de pulso al cargar para llamar la
  atención sin ser invasivo.
- Color configurable por tenant (UmindTenant.Color, validado como hex en el
  server) — se aplica en tiempo real vía /widget/:site_key/init, así que
  cambiarlo desde el panel no requiere recopiar el <script>.
- Panel con animación de entrada, botón de cerrar explícito, subtítulo
  "Asistente con IA · uMind" y badge de marca — antes solo tenía el nombre
  del tenant y ningún indicio de qué lo potencia.
- El widget ahora se inicializa al cargar el script (no al primer click), así
  el color/nombre reales ya están listos antes de que el visitante abra el chat.

Selector de color agregado al form de tenant en el orquestador (input
type=color + hex).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 20:03:51 -05:00
Lizandro GuarnizoandClaude Sonnet 5 da0bffe661 feat: orquestador uMind (SPA Vue) + tools custom + canales Telegram/WhatsApp
SPA nueva en /orchestrator (Vue 3 + Vite, servida por el mismo binario Go
bajo /orchestrator para que la cookie de sesión funcione sin tocar CORS),
reemplaza al panel Alpine.js como punto de entrada del menú.

Backend, todo aditivo sobre el motor de uMind ya existente:
- UmindHerramienta: tools custom por tenant que llaman un webhook HTTP,
  integradas al loop de function-calling existente. Cliente HTTP con
  guardas SSRF (bloqueo de IPs privadas/loopback/link-local resuelto en el
  momento de conectar, no antes, para cerrar la ventana de DNS rebinding)
  que no existían en el proyecto.
- UmindCanal: Telegram y WhatsApp Business Cloud API como canales
  adicionales del mismo agente que ya atiende el widget web, ambos
  reusando ProcessWidgetMessage. WhatsApp valida X-Hub-Signature-256.
  Credenciales cifradas en reposo con el mismo AES-GCM+APP_KEY que ya usa
  el proyecto para la contraseña SMTP (primer uso para secretos de uMind).
- Se conecta middlewares.Limit() (rate limiter que existía pero no se
  usaba en ningún lado) al widget público y a los webhooks nuevos.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 22:16:20 -05:00
Lizandro GD 5ee5880dc2 Agrega uMind: chat con IA embebible por tenant (F1 — widget web + RAG)
Multi-tenant dentro de soft_usite, reutilizando la infraestructura ya
existente (AiConfig, motor de function-calling del agente de Telegram)
en vez de un servicio nuevo aparte:

- UmindTenant: sitio/cliente con dominios permitidos, config de IA para
  el chat y personalidad/tono.
- Ingesta: crawler simple (mismo dominio, N páginas) + chunking +
  embeddings (config global con módulo "umind_embeddings", pensada
  para OpenAI ya que Claude no ofrece embeddings) guardados como JSON,
  con búsqueda por similitud coseno en memoria (sin pgvector todavía).
- Agente acotado: única herramienta buscar_conocimiento, sin acceso a
  nada interno — si no encuentra la respuesta, lo dice en vez de
  inventar.
- Widget público (/widget/umind.js + /widget/:site_key/*), autenticado
  por site_key + validación de dominio (Origin/Referer), no por
  secreto, ya que la key viaja en el HTML público del sitio instalado.
- Panel /app/umind: tenants, estado de ingesta, historial de
  conversaciones por sesión.
2026-08-07 16:18:16 +00:00