feat(soporte): botón de borrador que redacta con la base de conocimiento

En cada ticket, " Borrador" propone una respuesta usando los fragmentos más
parecidos de la base de conocimiento del agente de uMind que se elija en la
configuración de soporte, más el hilo de la conversación.

El borrador cae en el cuadro de respuesta y no se manda: lo revisa una persona
y aprieta enviar. Contestarle a un cliente con lo que dijo un modelo, sin que
nadie lo lea, es la forma más rápida de perderlo.

Sin agente configurado el borrador se arma igual, solo con la conversación —
peor, pero mejor que un error. El prompt le prohíbe inventar precios, plazos o
pasos que no estén en la documentación, y le pide decir qué falta preguntar
cuando no alcanza para resolver.

El cuadro de respuesta pasa a textarea: un borrador de varios renglones no
entraba en un input de una línea.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-17 19:45:38 -05:00
co-authored by Claude Opus 5
parent bfcc320b7c
commit 1b599606f7
7 changed files with 225 additions and 54 deletions
+3
View File
@@ -45,6 +45,9 @@ type SoporteWebhookConfig struct {
// clasifica cada correo nuevo antes de abrir ticket.
ClasificarConIA bool `json:"clasificar_con_ia" gorm:"column:clasificar_con_ia;default:false"`
ContextoNegocio string `json:"contexto_negocio" gorm:"column:contexto_negocio;type:text"`
// Agente de uMind cuya base de conocimiento se usa para redactar borradores
// de respuesta. Sin agente el borrador se arma solo con la conversación.
AgenteBorradorID *uint `json:"agente_borrador_id" gorm:"column:agente_borrador_id;index"`
// Solo para la vista: dice si ya hay contraseña guardada sin exponerla, para
// que el formulario sepa que puede mandar el campo vacío sin borrarla.
+9
View File
@@ -47,6 +47,15 @@ func GetUmindAgentesByTenant(tenantID uint) ([]UmindAgente, error) {
return items, err
}
// GetTodosLosUmindAgentes lista todos los agentes de todos los tenants. Es solo
// para pantallas de staff que necesitan elegir uno (ej. de qué base de
// conocimiento salen los borradores de soporte).
func GetTodosLosUmindAgentes() ([]UmindAgente, error) {
var items []UmindAgente
err := app.Http.Database.DB.Order("nombre ASC").Find(&items).Error
return items, err
}
func GetUmindAgenteByID(id uint) (*UmindAgente, error) {
var a UmindAgente
if err := app.Http.Database.DB.First(&a, id).Error; err != nil {