diff --git a/orchestrator/src/views/AgenteDetail.vue b/orchestrator/src/views/AgenteDetail.vue
index 38a4729..9c60a49 100644
--- a/orchestrator/src/views/AgenteDetail.vue
+++ b/orchestrator/src/views/AgenteDetail.vue
@@ -12,6 +12,7 @@ import TabConversaciones from './agente/TabConversaciones.vue'
import TabHerramientas from './agente/TabHerramientas.vue'
import TabCanales from './agente/TabCanales.vue'
import EstadoAgente from './agente/EstadoAgente.vue'
+import PrimerosPasos from './agente/PrimerosPasos.vue'
const props = defineProps({
tenantId: { type: String, required: true },
@@ -254,6 +255,12 @@ const AVANZADO = [
['auditoria', 'Problemas'],
]
+// La guía se muestra hasta que sabe algo Y atiende en algún lado. Probar es
+// deseable pero no bloquea: nadie queda preso de la guía por no haber chateado.
+const configurando = computed(
+ () => !documentos.value.some((d) => d.estado === 'listo') || !canales.value.some((c) => c.activo),
+)
+
const mostrarAvanzado = ref(false)
// Si se entra directo a una pestaña avanzada (por la URL o desde el estado de
@@ -313,10 +320,18 @@ watch(
-
+
+
const problemas = computed(() => props.eventos.filter((e) => e.nivel === 'error').length)
+// Solo conversaciones de clientes: la bandeja separa las pruebas propias, y si
+// este número las incluyera diría una cosa distinta que la lista de al lado.
+const reales = computed(() =>
+ props.sesiones.filter((s) => !String(s.session_id).startsWith('staff-preview')),
+)
+
// Cada señal dice qué pasa y, cuando algo anda mal, a dónde ir a arreglarlo.
const señales = computed(() => [
{
@@ -63,9 +69,9 @@ const señales = computed(() => [
icono: 'grafico',
// Que nadie haya escrito todavía no es un problema: es un dato.
bien: true,
- neutro: props.sesiones.length === 0,
- texto: props.sesiones.length
- ? `${props.sesiones.length} ${props.sesiones.length === 1 ? 'conversación' : 'conversaciones'}`
+ neutro: reales.value.length === 0,
+ texto: reales.value.length
+ ? `${reales.value.length} ${reales.value.length === 1 ? 'conversación' : 'conversaciones'}`
: 'Nadie escribió todavía',
destino: 'conversaciones',
},
diff --git a/orchestrator/src/views/agente/PrimerosPasos.vue b/orchestrator/src/views/agente/PrimerosPasos.vue
new file mode 100644
index 0000000..ef52656
--- /dev/null
+++ b/orchestrator/src/views/agente/PrimerosPasos.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
Pongamos a andar tu asistente
+ {{ hechos }} de {{ pasos.length }}
+
+
+ Tres pasos y empieza a responderle a tus clientes. Diez minutos, sin nada técnico.
+
uMind contesta por vos en WhatsApp y en tu sitio, con la información de tu negocio. Entiende las notas de voz y lee las fotos y archivos que te mandan tus clientes.
',4))])):(_(),C("div",cd,[ne(ss,{estado:"normal",tam:64,class:"mx-auto mb-4 text-brand"}),a("h1",dd,I(Re(ze).esPortal?"Elegí tu espacio de la izquierda":"Elegí un espacio de la izquierda"),1),a("p",fd,I(Re(ze).esPortal?"Adentro vas a poder crear y configurar tus agentes.":"o creá uno nuevo para empezar a configurar su agente."),1)]))}},md={class:"flex flex-col items-center justify-center text-center py-12 px-6"},hd={key:0,class:"text-3xl mb-3 opacity-70"},vd={class:"text-sm font-medium text-texto"},gd={key:2,class:"text-xs text-tenue mt-1.5 max-w-sm leading-relaxed"},bd={key:3,class:"mt-4"},Nt={__name:"UiEmptyState",props:{estado:{type:String,default:"durmiendo"},titulo:String,detalle:String,icono:{type:String,default:""}},setup(e){return(t,n)=>(_(),C("div",md,[e.icono?(_(),C("div",hd,I(e.icono),1)):(_(),Ce(ss,{key:1,estado:e.estado,tam:64,class:"mb-3 text-brand"},null,8,["estado"])),a("p",vd,I(e.titulo),1),e.detalle?(_(),C("p",gd,I(e.detalle),1)):K("",!0),t.$slots.default?(_(),C("div",bd,[Yl(t.$slots,"default")])):K("",!0)]))}},xd={key:0,class:"mb-6"},yd={class:"flex items-start justify-between gap-4"},_d={class:"text-xl font-semibold text-texto"},wd={class:"text-xs text-tenue mt-1"},kd={key:1,class:"text-sm text-red-600 dark:text-red-400 mb-4"},Cd={class:"flex items-center justify-between mb-4"},Ad={class:"flex items-center gap-2"},$d={key:0,class:"badge-alerta"},Ed={key:1,class:"badge-neutro"},Sd=["disabled"],Id={key:2,class:"text-xs text-tenue -mt-2 mb-4"},Rd={key:3,class:"text-xs text-tenue -mt-2 mb-4"},Pd={key:4,class:"grid gap-3 sm:grid-cols-2"},Td=["disabled"],Od={key:6,class:"grid gap-3 sm:grid-cols-2"},Dd={class:"flex items-start gap-3"},Md={class:"min-w-0 flex-1"},Nd={class:"flex items-center gap-2"},Vd={class:"font-medium text-texto truncate"},jd={class:"text-xs text-tenue mt-0.5 truncate"},Ud={class:"flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"},Ld=["onClick"],Fd=["onClick"],qd=["onClick"],Hd={class:"flex items-center gap-4 mt-3.5 pt-3 border-t border-borde text-xs text-tenue"},Bd={class:"tabular-nums"},Gd={class:"text-texto font-medium"},Kd={class:"tabular-nums"},Wd={class:"text-texto font-medium"},zd={class:"tabular-nums"},Jd={class:"text-texto font-medium"},Qd={class:"bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl p-6 w-full max-w-lg max-h-[calc(100vh-2rem)] overflow-y-auto"},Yd={class:"font-semibold text-gray-800 dark:text-gray-100 mb-4"},Zd={key:0},Xd={class:"grid gap-1.5"},ef=["value"],tf={class:"min-w-0"},nf={class:"block text-sm text-texto"},sf={class:"block text-xs text-tenue"},of={key:0,class:"block text-xs text-tenue mt-0.5"},rf=["value"],lf={class:"flex items-center gap-2"},af={class:"flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300"},uf={class:"flex justify-end gap-2 pt-2"},cf={type:"submit",class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg"},df={__name:"TenantAgentes",props:{id:{type:String,required:!0}},setup(e){const t=e,n=me(()=>Number(t.id)),s=go(),o=H(null),r=H([]),i=H([]),l=H(""),u=H(!1),f=H(null),d=H(A()),p=H(null),h=H({}),b=H(!0);function R(Z){const L=h.value[Z.ID]||{};return Z.activo?L.documentos>0?{tipo:"ok",texto:"listo"}:{tipo:"alerta",texto:"sin conocimiento"}:{tipo:"neutro",texto:"inactivo"}}function k(Z){const L=h.value[Z.ID]||{};return{documentos:L.documentos||0,canales:L.canales||0,conversaciones:L.conversaciones_7d||0}}function P(Z){return String(Z||"?").trim().split(/\s+/).slice(0,2).map(L=>L[0]).join("").toUpperCase()}const N=me(()=>{if(!p.value)return{sinPlan:!0};const Z=p.value.max_agentes||0;return{sinPlan:!1,nombre:p.value.nombre,ilimitado:Z<=0,max:Z,usados:r.value.length,lleno:Z>0&&r.value.length>=Z}});function A(){return{nombre:"",ai_config_id:null,tono:"",mensaje_bienvenida:"",color:"#8eb02f",activo:!0,plantilla_rubro:""}}const w=H([]);async function y(){l.value="",b.value=!0;try{const[Z,L,Ee,W]=await Promise.all([se.get(te("/umind/tenants")),se.get(te(`/umind/agentes?tenant_id=${t.id}`)),se.get(te("/umind/ai-configs")),se.get(te("/umind/plantillas-rubro"))]);o.value=(Z.items||[]).find(Ke=>String(Ke.ID)===t.id)||null,r.value=L.items||[],p.value=L.plan||null,h.value=L.resumen||{},i.value=Ee.items||[],w.value=W.items||[]}catch(Z){l.value=Z.message}finally{b.value=!1}}async function x(Z){const L=prompt(`Nombre de la copia de "${Z.nombre}":`,`${Z.nombre} (copia)`);if(L!==null){l.value="";try{const Ee=await se.post(te(`/umind/agentes/${Z.ID}/duplicar`),{tenant_id:Number(n.value),nombre:L.trim()});await y(),Ee.aviso&&alert(Ee.aviso)}catch(Ee){l.value=Ee.message}}}function O(){f.value=null,d.value=A(),u.value=!0}function V(Z){f.value=Z,d.value={nombre:Z.nombre,ai_config_id:Z.ai_config_id,tono:Z.tono,mensaje_bienvenida:Z.mensaje_bienvenida,color:Z.color||"#8eb02f",activo:Z.activo},u.value=!0}async function j(){try{if(f.value)await se.put(te(`/umind/agentes/${f.value.ID}`),{tenant_id:n.value,...d.value}),u.value=!1,await y();else{const Z=await se.post(te("/umind/agentes"),{tenant_id:n.value,...d.value});u.value=!1,s.push(`/tenants/${n.value}/agentes/${Z.id}`)}}catch(Z){l.value=Z.message}}async function _e(Z){confirm(`¿Eliminar el agente "${Z.nombre}"? Esto no se puede deshacer.`)&&(await se.del(te(`/umind/agentes/${Z.ID}`)),await y())}return It(()=>t.id,y,{immediate:!0}),(Z,L)=>{const Ee=mn("router-link");return _(),C("div",null,[o.value?(_(),C("div",xd,[a("div",yd,[a("div",null,[a("h1",_d,I(o.value.nombre),1),a("p",wd,I(o.value.dominios_permitidos||"sin dominios configurados"),1)]),ne(Ee,{to:`/tenants/${n.value??e.id}/ia`,class:"btn-ghost"},{default:nt(()=>[...L[10]||(L[10]=[ie("Tu IA",-1)])]),_:1},8,["to"]),ne(Ee,{to:`/tenants/${n.value??e.id}/uso`,class:"btn-ghost inline-flex items-center gap-1.5"},{default:nt(()=>[ne(Me,{nombre:"grafico"}),L[11]||(L[11]=ie(" Consumo",-1))]),_:1},8,["to"])])])):K("",!0),l.value?(_(),C("p",kd,I(l.value),1)):K("",!0),a("div",Cd,[a("div",Ad,[L[12]||(L[12]=a("h2",{class:"text-sm font-medium text-tenue"},"Agentes",-1)),N.value.sinPlan?(_(),C("span",$d,"sin plan · sin límite")):N.value.ilimitado?(_(),C("span",Ed,I(N.value.nombre)+" · ilimitado",1)):(_(),C("span",{key:2,class:xe(N.value.lleno?"badge-alerta":"badge-neutro")},I(N.value.nombre)+" · "+I(N.value.usados)+" de "+I(N.value.max),3))]),a("button",{class:"btn-primary",disabled:N.value.lleno,onClick:O},"+ Nuevo agente",8,Sd)]),N.value.sinPlan&&!Re(ze).esPortal?(_(),C("p",Id," Este espacio no tiene plan asignado, así que no se le aplica ningún límite de agentes. Asignale uno desde el lápiz del espacio, en la barra izquierda. ")):N.value.lleno?(_(),C("p",Rd," Alcanzaste el máximo de agentes de tu plan. ")):K("",!0),b.value?(_(),C("div",Pd,[(_(),C(re,null,we(2,W=>a("div",{key:W,class:"card p-4 animate-pulse"},[...L[13]||(L[13]=[$i('
',2)])])),64))])):r.value.length===0?(_(),Ce(Nt,{key:5,class:"card",estado:"durmiendo",titulo:"Todavía no hay agentes",detalle:"Creá el primero y cargale su base de conocimiento para que empiece a responder."},{default:nt(()=>[a("button",{class:"btn-primary",disabled:N.value.lleno,onClick:O},"+ Crear el primer agente",8,Td)]),_:1})):(_(),C("div",Od,[(_(!0),C(re,null,we(r.value,W=>(_(),Ce(Ee,{key:W.ID,to:`/tenants/${n.value}/agentes/${W.ID}`,class:"card p-4 relative group hover:shadow-lg hover:-translate-y-0.5 transition-all overflow-hidden"},{default:nt(()=>[a("span",{class:"absolute inset-x-0 top-0 h-1",style:Jt({background:W.color||"#8eb02f"})},null,4),a("div",Dd,[a("span",{class:"w-10 h-10 rounded-xl flex items-center justify-center text-white text-sm font-semibold shrink-0",style:Jt({background:W.color||"#8eb02f",opacity:W.activo?1:.4})},I(P(W.nombre)),5),a("div",Md,[a("div",Nd,[a("span",Vd,I(W.nombre),1),a("span",{class:xe(`badge-${R(W).tipo}`)},I(R(W).texto),3)]),a("p",jd,I(W.tono||"sin tono definido"),1)]),a("div",Ud,[a("button",{class:"p-1 text-tenue hover:text-texto",title:"Editar",onClick:Pe(Ke=>V(W),["prevent","stop"])},[ne(Me,{nombre:"lapiz",tam:14})],8,Ld),a("button",{class:"p-1 text-tenue hover:text-texto",title:"Duplicar: copia el conocimiento y las herramientas a un agente nuevo",onClick:Pe(Ke=>x(W),["prevent","stop"])},[ne(Me,{nombre:"copiar",tam:14})],8,Fd),a("button",{class:"p-1 text-tenue hover:text-red-600",title:"Eliminar",onClick:Pe(Ke=>_e(W),["prevent","stop"])},[ne(Me,{nombre:"cerrar",tam:14})],8,qd)])]),a("div",Hd,[a("span",Bd,[a("b",Gd,I(k(W).conversaciones),1),L[14]||(L[14]=ie(" conversaciones · 7d",-1))]),a("span",Kd,[a("b",Wd,I(k(W).documentos),1),L[15]||(L[15]=ie(" fuentes",-1))]),a("span",zd,[a("b",Jd,I(k(W).canales),1),L[16]||(L[16]=ie(" canales",-1))])])]),_:2},1032,["to"]))),128))])),u.value?(_(),C("div",{key:7,class:"fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50",onClick:L[9]||(L[9]=Pe(W=>u.value=!1,["self"]))},[a("div",Qd,[a("h2",Yd,I(f.value?"Editar agente":"Nuevo agente"),1),a("form",{class:"space-y-3",onSubmit:Pe(j,["prevent"])},[a("div",null,[L[17]||(L[17]=a("label",{class:"label"},"Nombre",-1)),X(a("input",{"onUpdate:modelValue":L[0]||(L[0]=W=>d.value.nombre=W),required:"",placeholder:"ej: Ventas, Soporte",class:"input"},null,512),[[ue,d.value.nombre]])]),!f.value&&w.value.length?(_(),C("div",Zd,[L[18]||(L[18]=a("label",{class:"label"},"Arrancar con",-1)),a("div",Xd,[(_(!0),C(re,null,we([{clave:"",nombre:"Agente en blanco",descripcion:"Sin conocimiento cargado. Lo escribís vos desde cero."},...w.value],W=>(_(),C("label",{key:W.clave,class:xe(["flex gap-2.5 p-2.5 rounded-lg border cursor-pointer transition-colors",d.value.plantilla_rubro===W.clave?"border-brand bg-brand/5":"border-borde hover:border-brand/40"])},[X(a("input",{"onUpdate:modelValue":L[1]||(L[1]=Ke=>d.value.plantilla_rubro=Ke),type:"radio",value:W.clave,class:"mt-1 text-brand focus:ring-brand"},null,8,ef),[[iu,d.value.plantilla_rubro]]),a("span",tf,[a("span",nf,I(W.nombre),1),a("span",sf,I(W.descripcion),1),W.notas?(_(),C("span",of,I(W.notas)+" notas listas para editar · "+I(W.resumen),1)):K("",!0)])],2))),128))]),L[19]||(L[19]=a("p",{class:"text-xs text-tenue mt-1.5"}," Las notas vienen con ejemplos entre corchetes — abrilas y reemplazalas por tus datos reales. ",-1))])):K("",!0),a("div",null,[L[21]||(L[21]=a("label",{class:"label"},"Config de IA",-1)),X(a("select",{"onUpdate:modelValue":L[2]||(L[2]=W=>d.value.ai_config_id=W),class:"input"},[L[20]||(L[20]=a("option",{value:null},"— sin asignar —",-1)),(_(!0),C(re,null,we(i.value,W=>(_(),C("option",{key:W.ID,value:W.ID},I(W.nombre)+" ("+I(W.provider)+")",9,rf))),128))],512),[[un,d.value.ai_config_id]])]),a("div",null,[L[22]||(L[22]=a("label",{class:"label"},"Tono / personalidad",-1)),X(a("textarea",{"onUpdate:modelValue":L[3]||(L[3]=W=>d.value.tono=W),rows:"2",class:"input"},null,512),[[ue,d.value.tono]])]),a("div",null,[L[23]||(L[23]=a("label",{class:"label"},"Mensaje de bienvenida",-1)),X(a("input",{"onUpdate:modelValue":L[4]||(L[4]=W=>d.value.mensaje_bienvenida=W),class:"input"},null,512),[[ue,d.value.mensaje_bienvenida]])]),a("div",null,[L[24]||(L[24]=a("label",{class:"label"},"Color del widget",-1)),a("div",lf,[X(a("input",{"onUpdate:modelValue":L[5]||(L[5]=W=>d.value.color=W),type:"color",class:"w-10 h-9 border border-gray-300 dark:border-gray-700 rounded cursor-pointer bg-white dark:bg-gray-800"},null,512),[[ue,d.value.color]]),X(a("input",{"onUpdate:modelValue":L[6]||(L[6]=W=>d.value.color=W),type:"text",pattern:"#[0-9a-fA-F]{6}",class:"flex-1 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-100 rounded-lg px-3 py-2 text-sm font-mono"},null,512),[[ue,d.value.color]])])]),a("label",af,[X(a("input",{"onUpdate:modelValue":L[7]||(L[7]=W=>d.value.activo=W),type:"checkbox"},null,512),[[Pt,d.value.activo]]),L[25]||(L[25]=ie(" Activo ",-1))]),a("div",uf,[a("button",{type:"button",class:"px-4 py-2 text-sm text-gray-500 dark:text-gray-400",onClick:L[8]||(L[8]=W=>u.value=!1)},"Cancelar"),a("button",cf,I(f.value?"Guardar":"Crear"),1)])],32)])])):K("",!0)])}}},ff={class:"card divide-y divide-borde max-h-[32rem] overflow-y-auto"},pf={class:"cursor-pointer flex items-center gap-2 text-sm"},mf={class:"text-tenue text-xs shrink-0"},hf={class:"text-texto truncate"},vf={class:"text-tenue text-xs ml-auto shrink-0"},gf={key:0,class:"mt-2 bg-elevado border border-borde rounded-lg p-2 text-xs text-gray-600 dark:text-gray-400 overflow-x-auto whitespace-pre-wrap"},bf={__name:"TabAuditoria",props:{eventos:{type:Array,default:()=>[]}},setup(e){const t=me(()=>s=>({error:"badge-error",warn:"badge-alerta"})[s]||"badge-neutro");function n(s){try{return new Date(s).toLocaleString()}catch{return s}}return(s,o)=>(_(),C("div",null,[o[0]||(o[0]=a("p",{class:"label mb-4"}," Errores y eventos técnicos de este agente — fallos al llamar a la IA, a una herramienta, al correo o a los canales. Últimos 100. ",-1)),a("div",ff,[e.eventos.length===0?(_(),Ce(Nt,{key:0,estado:"contenta",titulo:"Ningún problema registrado",detalle:"Acá aparecen los errores: una herramienta que no responde, una fuente que no se pudo leer. Que esté vacío es buena señal."})):K("",!0),(_(!0),C(re,null,we(e.eventos,r=>(_(),C("details",{key:r.ID,class:"p-3"},[a("summary",pf,[a("span",{class:xe(["px-1.5 py-0.5 rounded text-xs shrink-0",t.value(r.nivel)])},I(r.nivel),3),a("span",mf,I(r.origen),1),a("span",hf,I(r.mensaje),1),a("span",vf,I(n(r.CreatedAt)),1)]),r.detalle?(_(),C("pre",gf,I(r.detalle),1)):K("",!0)]))),128))])]))}},xf={class:"flex gap-2 mb-4"},yf={class:"card divide-y divide-borde"},_f={class:"font-medium text-texto capitalize"},wf={class:"ml-2 text-sm text-tenue"},kf=["onClick"],Cf={__name:"TabConexiones",props:{agenteId:{type:Number,required:!0},conexiones:{type:Array,default:()=>[]}},emits:["recargar"],setup(e,{emit:t}){const n=e,s=t;function o(i){window.location.href=te(`/umind/conexiones/conectar?agente_id=${n.agenteId}&proveedor=${i}`)}async function r(i){confirm(`¿Desconectar la cuenta ${i.email||i.proveedor}?`)&&(await se.del(te(`/umind/conexiones/${i.ID}`)),s("recargar"))}return(i,l)=>(_(),C("div",null,[l[2]||(l[2]=a("p",{class:"label mb-4"}," Conectá una cuenta de correo para que este agente pueda enviar y leer correo en su nombre. Se soporta una cuenta activa a la vez. ",-1)),a("div",xf,[a("button",{class:"border border-borde hover:border-brand text-sm font-medium px-4 py-2 rounded-lg text-gray-700 dark:text-gray-200 transition-colors",onClick:l[0]||(l[0]=u=>o("google"))}," Conectar Google "),a("button",{class:"border border-borde hover:border-brand text-sm font-medium px-4 py-2 rounded-lg text-gray-700 dark:text-gray-200 transition-colors",onClick:l[1]||(l[1]=u=>o("microsoft"))}," Conectar Outlook ")]),a("div",yf,[e.conexiones.length===0?(_(),Ce(Nt,{key:0,titulo:"Sin cuentas conectadas",detalle:"Conectando una cuenta de correo, el agente puede leer y responder mensajes con tu dirección."})):K("",!0),(_(!0),C(re,null,we(e.conexiones,u=>(_(),C("div",{key:u.ID,class:"p-4 flex items-center justify-between"},[a("div",null,[a("span",_f,I(u.proveedor),1),a("span",wf,I(u.email),1),a("span",{class:xe(["ml-2 px-1.5 py-0.5 rounded text-xs",u.activo?"badge-ok":"badge-neutro"])},I(u.activo?"activa":"inactiva"),3)]),a("button",{class:"text-red-500 hover:text-red-700 text-sm",onClick:f=>r(u)},"Desconectar",8,kf)]))),128))])]))}},Af={class:"card p-4 flex flex-col h-[28rem]"},$f={class:"flex-1 overflow-y-auto space-y-2 mb-3"},Ef={key:0,class:"text-sm text-tenue"},Sf={key:1,class:"flex items-center gap-2"},If=["disabled"],br={__name:"TabChat",props:{agenteId:{type:Number,required:!0}},setup(e){const t=e,n=`staff-preview-${Math.random().toString(36).slice(2)}`,s=H([]),o=H(""),r=H(!1);async function i(){const l=o.value.trim();if(!(!l||r.value)){o.value="",s.value.push({role:"user",content:l}),r.value=!0;try{const u=await se.post(te("/umind/chat"),{agente_id:t.agenteId,session_id:n,mensaje:l});s.value.push({role:"assistant",content:u.respuesta})}catch(u){s.value.push({role:"assistant",content:`⚠ ${u.message}`})}finally{r.value=!1}}}return(l,u)=>(_(),C("div",Af,[a("div",$f,[s.value.length===0?(_(),C("p",Ef," Probá este agente tal cual lo va a ver un visitante — usa la misma config de IA, las mismas herramientas y la misma base de conocimiento. ")):K("",!0),(_(!0),C(re,null,we(s.value,(f,d)=>(_(),C("div",{key:d,class:xe(["max-w-[80%] px-3 py-2 rounded-lg text-sm whitespace-pre-wrap",f.role==="user"?"bg-brand text-white ml-auto":"bg-elevado text-texto"])},I(f.content),3))),128)),r.value?(_(),C("div",Sf,[ne(ss,{estado:"pensando",tam:30,class:"text-brand"}),u[1]||(u[1]=a("span",{class:"text-xs text-tenue"},"Pensando…",-1))])):K("",!0)]),a("form",{class:"flex gap-2",onSubmit:Pe(i,["prevent"])},[X(a("input",{"onUpdate:modelValue":u[0]||(u[0]=f=>o.value=f),placeholder:"Escribí un mensaje de prueba...",class:"flex-1 input"},null,512),[[ue,o.value]]),a("button",{type:"submit",disabled:r.value,class:"btn-primary disabled:opacity-50 transition-colors"}," Enviar ",8,If)],32)]))}},Rf={class:"grid grid-cols-3 gap-4"},Pf={class:"col-span-1 card divide-y divide-borde max-h-[28rem] overflow-y-auto"},Tf=["onClick"],Of={class:"text-texto truncate"},Df={class:"text-xs text-tenue mt-0.5"},Mf={class:"col-span-2 card p-4 max-h-[28rem] overflow-y-auto space-y-2"},Nf={key:0,class:"text-sm text-tenue"},Vf={__name:"TabConversaciones",props:{agenteId:{type:Number,required:!0},sesiones:{type:Array,default:()=>[]}},setup(e){const t=e,n=H([]),s=H(null);async function o(r){s.value=r;const i=await se.get(te(`/umind/historial?agente_id=${t.agenteId}&session_id=${r}`));n.value=i.items||[]}return(r,i)=>(_(),C("div",Rf,[a("div",Pf,[e.sesiones.length===0?(_(),Ce(Nt,{key:0,titulo:"Nadie escribió todavía",detalle:"Acá vas a ver todo lo que le preguntan y qué contestó."})):K("",!0),(_(!0),C(re,null,we(e.sesiones,l=>(_(),C("button",{key:l.session_id,class:xe(["w-full text-left p-3 hover:bg-elevado text-sm",s.value===l.session_id?"bg-gray-50 dark:bg-gray-800":""]),onClick:u=>o(l.session_id)},[a("div",Of,I(l.content),1),a("div",Df,I(l.session_id),1)],10,Tf))),128))]),a("div",Mf,[s.value?K("",!0):(_(),C("p",Nf,"Elegí una conversación de la izquierda.")),(_(!0),C(re,null,we(n.value,l=>(_(),C("div",{key:l.ID,class:xe(["max-w-[80%] px-3 py-2 rounded-lg text-sm",l.role==="user"?"bg-brand text-white ml-auto":"bg-elevado text-texto"])},I(l.content),3))),128))])]))}},jf={class:"card divide-y divide-borde"},Uf={class:"text-sm text-texto font-mono"},Lf={class:"label mt-0.5"},Ff={class:"text-xs text-tenue mt-0.5"},qf={key:0,class:"ml-1 text-green-600 dark:text-green-400"},Hf={key:1,class:"ml-1 text-gray-400"},Bf={class:"flex gap-3 text-sm shrink-0"},Gf=["onClick"],Kf=["onClick"],Wf={class:"card p-6 w-full max-w-xl max-h-[85vh] overflow-y-auto"},zf={class:"font-semibold text-texto mb-4"},Jf={class:"border border-borde rounded-lg p-3 space-y-2"},Qf=["onUpdate:modelValue"],Yf=["onUpdate:modelValue"],Zf=["onUpdate:modelValue"],Xf={class:"label flex items-center gap-1"},ep=["onUpdate:modelValue"],tp=["onClick"],np={key:0,class:"text-xs text-gray-400"},sp={class:"border border-borde rounded-lg p-3 space-y-2"},op={class:"flex items-center gap-2 label"},rp={class:"flex items-center gap-2 text-sm text-texto"},ip={class:"flex justify-end gap-2 pt-2"},lp={__name:"TabHerramientas",props:{agenteId:{type:Number,required:!0},tools:{type:Array,default:()=>[]}},emits:["recargar","error"],setup(e,{emit:t}){const n=e,s=t,o=H(!1),r=H(null),i=H(l());function l(){return{nombre:"",descripcion:"",url:"",auth_header_nombre:"",auth_header_valor:"",tocarAuth:!1,parametros:[],activa:!0}}function u(){r.value=null,i.value=l(),o.value=!0}function f(R){r.value=R;let k=[];try{k=JSON.parse(R.parametros_json||"[]")||[]}catch{k=[]}i.value={nombre:R.nombre,descripcion:R.descripcion,url:R.url,auth_header_nombre:R.auth_header_nombre,auth_header_valor:"",tocarAuth:!1,parametros:k,activa:R.activa},o.value=!0}function d(){i.value.parametros.push({nombre:"",tipo:"string",descripcion:"",requerido:!1})}function p(R){i.value.parametros.splice(R,1)}async function h(){const R={agente_id:n.agenteId,nombre:i.value.nombre.trim(),descripcion:i.value.descripcion,url:i.value.url.trim(),auth_header_nombre:i.value.auth_header_nombre,parametros:i.value.parametros,activa:i.value.activa};i.value.tocarAuth&&(R.auth_header_valor=i.value.auth_header_valor);try{r.value?await se.put(te(`/umind/tools/${r.value.ID}`),R):await se.post(te("/umind/tools"),R),o.value=!1,s("recargar")}catch(k){s("error",k.message)}}async function b(R){confirm(`¿Eliminar la herramienta "${R.nombre}"?`)&&(await se.del(te(`/umind/tools/${R.ID}`)),s("recargar"))}return(R,k)=>(_(),C("div",null,[a("div",{class:"flex justify-between items-center mb-4"},[k[9]||(k[9]=a("p",{class:"label"},"Máximo 10 herramientas activas por agente.",-1)),a("button",{class:"btn-primary",onClick:u}," + Nueva herramienta ")]),a("div",jf,[e.tools.length===0?(_(),Ce(Nt,{key:0,titulo:"Sin herramientas conectadas",detalle:"Las herramientas le dejan consultar tus sistemas mientras conversa: stock, estado de un pedido, disponibilidad de turnos. Sin ninguna, responde solo con lo que tiene cargado."})):K("",!0),(_(!0),C(re,null,we(e.tools,P=>(_(),C("div",{key:P.ID,class:"p-4 flex items-center justify-between"},[a("div",null,[a("div",Uf,I(P.nombre),1),a("div",Lf,I(P.descripcion),1),a("div",Ff,[ie(I(P.url)+" ",1),P.auth_configurado?(_(),C("span",qf,"· auth configurada")):K("",!0),P.activa?K("",!0):(_(),C("span",Hf,"· inactiva"))])]),a("div",Bf,[a("button",{class:"text-tenue hover:text-gray-800 dark:hover:text-gray-100",onClick:N=>f(P)},"Editar",8,Gf),a("button",{class:"text-red-500 hover:text-red-700",onClick:N=>b(P)},"Eliminar",8,Kf)])]))),128))]),o.value?(_(),C("div",{key:0,class:"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50",onClick:k[8]||(k[8]=Pe(P=>o.value=!1,["self"]))},[a("div",Wf,[a("h2",zf,I(r.value?"Editar herramienta":"Nueva herramienta"),1),a("form",{class:"space-y-3",onSubmit:Pe(h,["prevent"])},[a("div",null,[k[10]||(k[10]=a("label",{class:"label"},"Nombre (identificador, ej: consultar_stock)",-1)),X(a("input",{"onUpdate:modelValue":k[0]||(k[0]=P=>i.value.nombre=P),required:"",pattern:"[a-z][a-z0-9_]{2,63}",class:"input font-mono"},null,512),[[ue,i.value.nombre]])]),a("div",null,[k[11]||(k[11]=a("label",{class:"label"},"Descripción (esto lo lee el modelo para decidir cuándo usarla)",-1)),X(a("textarea",{"onUpdate:modelValue":k[1]||(k[1]=P=>i.value.descripcion=P),rows:"2",required:"",class:"input"},null,512),[[ue,i.value.descripcion]])]),a("div",null,[k[12]||(k[12]=a("label",{class:"label"},"URL del webhook (https)",-1)),X(a("input",{"onUpdate:modelValue":k[2]||(k[2]=P=>i.value.url=P),type:"url",required:"",placeholder:"https://...",class:"input"},null,512),[[ue,i.value.url]])]),a("div",Jf,[a("div",{class:"flex items-center justify-between"},[k[13]||(k[13]=a("label",{class:"label"},"Parámetros que completa el modelo",-1)),a("button",{type:"button",class:"text-xs text-brand",onClick:d},"+ agregar")]),(_(!0),C(re,null,we(i.value.parametros,(P,N)=>(_(),C("div",{key:N,class:"flex gap-2 items-center"},[X(a("input",{"onUpdate:modelValue":A=>P.nombre=A,placeholder:"nombre",class:"flex-1 border border-borde bg-white dark:bg-gray-800 text-texto rounded px-2 py-1 text-xs font-mono"},null,8,Qf),[[ue,P.nombre]]),X(a("select",{"onUpdate:modelValue":A=>P.tipo=A,class:"border border-borde bg-white dark:bg-gray-800 text-texto rounded px-2 py-1 text-xs"},[...k[14]||(k[14]=[a("option",{value:"string"},"string",-1),a("option",{value:"number"},"number",-1),a("option",{value:"boolean"},"boolean",-1)])],8,Yf),[[un,P.tipo]]),X(a("input",{"onUpdate:modelValue":A=>P.descripcion=A,placeholder:"descripción",class:"flex-1 border border-borde bg-white dark:bg-gray-800 text-texto rounded px-2 py-1 text-xs"},null,8,Zf),[[ue,P.descripcion]]),a("label",Xf,[X(a("input",{"onUpdate:modelValue":A=>P.requerido=A,type:"checkbox"},null,8,ep),[[Pt,P.requerido]]),k[15]||(k[15]=ie(" req. ",-1))]),a("button",{type:"button",class:"text-red-400 text-xs",onClick:A=>p(N)},[ne(Me,{nombre:"cerrar",tam:13})],8,tp)]))),128)),i.value.parametros.length===0?(_(),C("p",np,"Sin parámetros.")):K("",!0)]),a("div",sp,[k[16]||(k[16]=a("label",{class:"label"},"Autenticación saliente (opcional)",-1)),X(a("input",{"onUpdate:modelValue":k[3]||(k[3]=P=>i.value.auth_header_nombre=P),placeholder:"Nombre del header, ej: Authorization",class:"input"},null,512),[[ue,i.value.auth_header_nombre]]),a("label",op,[X(a("input",{"onUpdate:modelValue":k[4]||(k[4]=P=>i.value.tocarAuth=P),type:"checkbox"},null,512),[[Pt,i.value.tocarAuth]]),ie(" "+I(r.value?"Cambiar el valor del secreto":"Configurar valor"),1)]),i.value.tocarAuth?X((_(),C("input",{key:0,"onUpdate:modelValue":k[5]||(k[5]=P=>i.value.auth_header_valor=P),type:"password",placeholder:"Valor del header (ej: Bearer xxxx)",class:"input"},null,512)),[[ue,i.value.auth_header_valor]]):K("",!0)]),a("label",rp,[X(a("input",{"onUpdate:modelValue":k[6]||(k[6]=P=>i.value.activa=P),type:"checkbox"},null,512),[[Pt,i.value.activa]]),k[17]||(k[17]=ie(" Activa ",-1))]),a("div",ip,[a("button",{type:"button",class:"btn-ghost",onClick:k[7]||(k[7]=P=>o.value=!1)},"Cancelar"),k[18]||(k[18]=a("button",{type:"submit",class:"btn-primary"},"Guardar",-1))])],32)])])):K("",!0)]))}},ap={class:"card p-4 mb-4"},up={class:"flex items-center justify-between mb-2"},cp={class:"bg-elevado border border-borde rounded-lg p-2.5 text-xs text-texto overflow-x-auto"},dp={class:"card divide-y divide-borde"},fp={class:"flex items-center justify-between"},pp={class:"font-medium text-texto capitalize"},mp={class:"flex gap-3 text-sm"},hp=["onClick"],vp=["onClick"],gp={class:"flex gap-4 mt-2 text-xs"},bp={class:"flex items-center gap-1.5 text-texto cursor-pointer"},xp=["checked","onChange"],yp={class:"flex items-center gap-1.5 text-texto cursor-pointer"},_p=["checked","onChange"],wp={class:"flex items-center gap-1.5 text-texto cursor-pointer"},kp=["checked","onChange"],Cp={class:"label mt-1 break-all"},Ap={class:"bg-elevado px-1 rounded"},$p={key:0,class:"text-xs text-tenue mt-1"},Ep={key:1,class:"text-xs text-red-600 dark:text-red-400 mt-1"},Sp={class:"card p-6 w-full max-w-md"},Ip={key:0},Rp={class:"flex flex-col gap-2 pt-1"},Pp={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},Tp={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},Op={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},Dp={class:"flex justify-end gap-2 pt-2"},Mp={__name:"TabCanales",props:{agenteId:{type:Number,required:!0},siteKey:{type:String,default:""},canales:{type:Array,default:()=>[]}},emits:["recargar","error"],setup(e,{emit:t}){const n=e,s=t,o=H(!1),r=H(f()),i=H(!1),l=me(()=>{const A=n.siteKey||"TU_SITE_KEY";return`
-
+
+