diff --git a/orchestrator/src/views/Uso.vue b/orchestrator/src/views/Uso.vue index 7712ea5..72a9d65 100644 --- a/orchestrator/src/views/Uso.vue +++ b/orchestrator/src/views/Uso.vue @@ -21,6 +21,7 @@ const ETIQUETAS = { ia: { nombre: 'Inteligencia artificial', icono: 'cerebro', color: '#8eb02f' }, ocr: { nombre: 'Lectura de imágenes', icono: 'imagen', color: '#2f7fb0' }, whisper: { nombre: 'Transcripción de audio', icono: 'microfono', color: '#b0752f' }, + documento: { nombre: 'Documentos generados', icono: 'archivo', color: '#7b5fb0' }, } const etiqueta = (t) => ETIQUETAS[t] || { nombre: t, icono: 'grafico', color: '#94a3b8' } diff --git a/pkg/models/umind_accion.go b/pkg/models/umind_accion.go index 43f1a76..79afd78 100644 --- a/pkg/models/umind_accion.go +++ b/pkg/models/umind_accion.go @@ -114,3 +114,9 @@ func VencerAccionesViejas() int64 { Update("estado", "vencida") return res.RowsAffected } + +// VincularArchivoAAccion engancha el documento producido a la acción. +func VincularArchivoAAccion(accionID, archivoID uint) { + app.Http.Database.DB.Model(&UmindAccionPendiente{}).Where("id = ?", accionID). + Update("archivo_id", archivoID) +} diff --git a/pkg/models/umind_archivo.go b/pkg/models/umind_archivo.go index 4c4b325..8ff6019 100644 --- a/pkg/models/umind_archivo.go +++ b/pkg/models/umind_archivo.go @@ -1,6 +1,7 @@ package models import ( + "fmt" "time" "github.com/sujit-baniya/fiber-boilerplate/app" @@ -67,3 +68,19 @@ func VincularArchivoADocumento(archivoID, documentoID uint) error { // AhoraUnix da el prefijo de tiempo para los nombres de archivo en disco. func AhoraUnix() int64 { return time.Now().Unix() } + +// HayEspacioUmind dice si entra un archivo más en el espacio del plan. +func HayEspacioUmind(tenantID uint, bytes int64) error { + tenant, err := GetUmindTenantByID(tenantID) + if err != nil || tenant.PlanID == nil { + return nil // sin plan asignado no se limita + } + plan, err := GetUmindPlanByID(*tenant.PlanID) + if err != nil || plan.MaxAlmacenamientoMB <= 0 { + return nil + } + if EspacioUsadoUmind(tenantID)+bytes > int64(plan.MaxAlmacenamientoMB)<<20 { + return fmt.Errorf("el espacio de archivos del plan está lleno (%d MB)", plan.MaxAlmacenamientoMB) + } + return nil +} diff --git a/pkg/services/umind_agent_service.go b/pkg/services/umind_agent_service.go index 7283ee0..388181a 100644 --- a/pkg/services/umind_agent_service.go +++ b/pkg/services/umind_agent_service.go @@ -155,8 +155,23 @@ func umindEmailTools() []agentTool { // esperando a una persona. El trabajo real vive en ejecutarHerramienta, que es // lo que corre después una aprobación. func executeUmindTool(agenteID uint, sessionID string, sesionInterna bool, name string, args map[string]interface{}) string { - if RequiereAprobacion(sesionInterna, name) { - return EncolarAccion(agenteID, sessionID, name, args) + switch CategoriaTool(agenteID, name) { + case "desconocida": + // Un nombre que no existe se rechaza acá y no se encola. Si no, el + // modelo alucinando un nombre le llena la bandeja al dueño de + // solicitudes para ejecutar herramientas que nunca existieron. + return fmt.Sprintf(`{"error": "herramienta desconocida: %s"}`, name) + case "interna": + // Programar avisos y vigilancias gasta el plan del dueño. No se + // encolan para que las apruebe: desde un canal público directamente + // no se piden. + if !sesionInterna { + return `{"error": "eso solo puede pedirlo el dueño desde su canal privado"}` + } + case "accion": + if !sesionInterna { + return EncolarAccion(agenteID, sessionID, name, args) + } } return ejecutarHerramienta(agenteID, sessionID, sesionInterna, name, args) } diff --git a/pkg/services/umind_aprobacion_service.go b/pkg/services/umind_aprobacion_service.go index 1816942..3feff8a 100644 --- a/pkg/services/umind_aprobacion_service.go +++ b/pkg/services/umind_aprobacion_service.go @@ -104,6 +104,11 @@ func EjecutarAccionAprobada(accion *models.UmindAccionPendiente, quien string) e if err := models.CerrarAccion(accion.ID, estado, quien, "", resultado); err != nil { return err } + // Si la acción produjo un documento, se engancha a la acción para que el + // que aprobó pueda abrirlo desde la misma fila donde apretó el botón. + if id := archivoDelResultado(resultado); id != nil { + models.VincularArchivoAAccion(accion.ID, *id) + } if estado == "fallida" { models.RegistrarEventoUmind(accion.AgenteID, "error", "aprobacion", "Una acción aprobada falló al ejecutarse: "+accion.Resumen, resultado) @@ -148,3 +153,39 @@ func avisarAccionPendiente(agente *models.UmindAgente, accion *models.UmindAccio } } } + +// CategoriaTool clasifica la llamada ANTES de decidir qué hacer con ella: +// +// lectura — no sale nada del negocio, se ejecuta siempre +// interna — gasta el plan del dueño, solo desde su canal privado +// accion — sale hacia afuera, espera aprobación si el pedido es público +// desconocida — el nombre no existe: se rechaza, nunca se encola +// +// La clasificación existe porque sin ella todo lo que no fuera lectura se +// encolaba, incluidos los nombres que el modelo inventa. +func CategoriaTool(agenteID uint, name string) string { + switch name { + case "buscar_conocimiento", "leer_bandeja": + return "lectura" + case "programar_aviso", "listar_avisos", "cancelar_aviso", + "crear_vigilancia", "listar_vigilancias", "cancelar_vigilancia": + return "interna" + case "enviar_correo", "generar_documento": + return "accion" + } + if _, err := models.GetUmindHerramientaByNombre(agenteID, name); err == nil { + return "accion" + } + return "desconocida" +} + +// archivoDelResultado saca el archivo_id que devuelve generar_documento. +func archivoDelResultado(resultado string) *uint { + var r struct { + ArchivoID uint `json:"archivo_id"` + } + if err := json.Unmarshal([]byte(resultado), &r); err != nil || r.ArchivoID == 0 { + return nil + } + return &r.ArchivoID +} diff --git a/pkg/services/umind_aprobacion_test.go b/pkg/services/umind_aprobacion_test.go index 04c698b..2459abc 100644 --- a/pkg/services/umind_aprobacion_test.go +++ b/pkg/services/umind_aprobacion_test.go @@ -82,3 +82,59 @@ func TestAccionAprobadaUsaElPayloadGuardado(t *testing.T) { t.Error("falta el reclamo: sin él, dos aprobaciones simultáneas ejecutan dos veces") } } + +// La clasificación es lo que decide entre ejecutar, encolar y rechazar. Sin +// ella, todo lo que no fuera lectura se encolaba —incluidos los nombres que el +// modelo inventa—, y la bandeja del dueño se llenaba de solicitudes para +// ejecutar herramientas que nunca existieron. +func TestCategoriaTool(t *testing.T) { + casos := map[string]string{ + "buscar_conocimiento": "lectura", + "leer_bandeja": "lectura", + "programar_aviso": "interna", + "cancelar_aviso": "interna", + "listar_avisos": "interna", + "crear_vigilancia": "interna", + "listar_vigilancias": "interna", + "enviar_correo": "accion", + "generar_documento": "accion", + } + for tool, quiero := range casos { + // agenteID 0: las tools con nombre fijo no consultan la base. + if got := CategoriaTool(0, tool); got != quiero { + t.Errorf("CategoriaTool(%q) = %q, quiero %q", tool, got, quiero) + } + } +} + +// El camino completo desde un canal público, que es donde escribe cualquiera. +func TestPuertaDeToolsDesdeCanalPublico(t *testing.T) { + b, err := os.ReadFile("umind_agent_service.go") + if err != nil { + t.Fatal(err) + } + s := string(b) + i := strings.Index(s, "func executeUmindTool") + cuerpo := s[i:] + cuerpo = cuerpo[:strings.Index(cuerpo, "\nfunc ejecutarHerramienta")] + + // La clasificación tiene que decidir ANTES de encolar. + cat := strings.Index(cuerpo, "CategoriaTool") + enc := strings.Index(cuerpo, "EncolarAccion") + if cat < 0 || enc < 0 || cat > enc { + t.Fatal("la clasificación tiene que ir antes de encolar") + } + // Un nombre inexistente se rechaza, no se encola. + desc := cuerpo[strings.Index(cuerpo, `case "desconocida":`):strings.Index(cuerpo, `case "interna":`)] + if strings.Contains(desc, "EncolarAccion") { + t.Error("una herramienta desconocida no puede encolarse") + } + // Las internas se rechazan desde un canal público, no se encolan. + inter := cuerpo[strings.Index(cuerpo, `case "interna":`):strings.Index(cuerpo, `case "accion":`)] + if strings.Contains(inter, "EncolarAccion") { + t.Error("las tools internas no pueden encolarse desde un canal público") + } + if !strings.Contains(inter, "!sesionInterna") { + t.Error("falta el rechazo de tools internas en canal público") + } +} diff --git a/pkg/services/umind_documento_tools.go b/pkg/services/umind_documento_tools.go index 4d621ce..64fa94a 100644 --- a/pkg/services/umind_documento_tools.go +++ b/pkg/services/umind_documento_tools.go @@ -116,6 +116,11 @@ func renderPDFDesdePlantilla(contenidoHTML string, datos map[string]interface{}) // guardarPDFEnRepositorio deja el documento en los archivos del espacio, para // que quede a la vista y descargable como cualquier otro. func guardarPDFEnRepositorio(tenantID uint, nombreBase string, pdf []byte) (*models.UmindArchivo, error) { + // Un PDF generado ocupa lo mismo que uno subido: si no contara para la + // cuota, el tope del plan se esquivaría pidiéndole documentos al agente. + if err := models.HayEspacioUmind(tenantID, int64(len(pdf))); err != nil { + return nil, err + } dir := filepath.Join("uploads", "umind", strconv.FormatUint(uint64(tenantID), 10)) if err := os.MkdirAll(dir, 0o755); err != nil { return nil, err diff --git a/public/orchestrator/assets/index-BTIDeKXh.js b/public/orchestrator/assets/index-NgTBLrrq.js similarity index 91% rename from public/orchestrator/assets/index-BTIDeKXh.js rename to public/orchestrator/assets/index-NgTBLrrq.js index 89bf09e..c0c3019 100644 --- a/public/orchestrator/assets/index-BTIDeKXh.js +++ b/public/orchestrator/assets/index-NgTBLrrq.js @@ -24,6 +24,6 @@ * (c) 2025 Eduardo San Martin Morote * @license MIT */let Ju=()=>location.protocol+"//"+location.host;function Br(e,t){const{pathname:n,search:s,hash:o}=t,a=e.indexOf("#");if(a>-1){let l=o.includes(e.slice(a))?e.slice(a).length:1,i=o.slice(l);return i[0]!=="/"&&(i="/"+i),sa(i,"")}return sa(n,e)+s+o}function Yu(e,t,n,s){let o=[],a=[],l=null;const i=({state:f})=>{const _=Br(e,location),k=n.value,A=t.value;let I=0;if(f){if(n.value=_,t.value=f,l&&l===k){l=null;return}I=A?f.position-A.position:0}else s(_);o.forEach(y=>{y(n.value,k,{delta:I,type:Qs.pop,direction:I?I>0?Ms.forward:Ms.back:Ms.unknown})})};function u(){l=n.value}function d(f){o.push(f);const _=()=>{const k=o.indexOf(f);k>-1&&o.splice(k,1)};return a.push(_),_}function c(){if(document.visibilityState==="hidden"){const{history:f}=window;if(!f.state)return;f.replaceState(he({},f.state,{scroll:ys()}),"")}}function p(){for(const f of a)f();a=[],window.removeEventListener("popstate",i),window.removeEventListener("pagehide",c),document.removeEventListener("visibilitychange",c)}return window.addEventListener("popstate",i),window.addEventListener("pagehide",c),document.addEventListener("visibilitychange",c),{pauseListeners:u,listen:d,destroy:p}}function ia(e,t,n,s=!1,o=!1){return{back:e,current:t,forward:n,replaced:s,position:window.history.length,scroll:o?ys():null}}function Zu(e){const{history:t,location:n}=window,s={value:Br(e,n)},o={value:t.state};o.value||a(s.value,{back:null,current:s.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function a(u,d,c){const p=e.indexOf("#"),f=p>-1?(n.host&&document.querySelector("base")?e:e.slice(p))+u:Ju()+e+u;try{t[c?"replaceState":"pushState"](d,"",f),o.value=d}catch(_){console.error(_),n[c?"replace":"assign"](f)}}function l(u,d){a(u,he({},t.state,ia(o.value.back,u,o.value.forward,!0),d,{position:o.value.position}),!0),s.value=u}function i(u,d){const c=he({},o.value,t.state,{forward:u,scroll:ys()});a(c.current,c,!0),a(u,he({},ia(s.value,u,null),{position:c.position+1},d),!1),s.value=u}return{location:s,state:o,push:i,replace:l}}function Xu(e){e=Nu(e);const t=Zu(e),n=Yu(e,t.state,t.location,t.replace);function s(a,l=!0){l||n.pauseListeners(),history.go(a)}const o=he({location:"",base:e,go:s,createHref:Vu.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}let Qt=(function(e){return e[e.Static=0]="Static",e[e.Param=1]="Param",e[e.Group=2]="Group",e})({});var Ie=(function(e){return e[e.Static=0]="Static",e[e.Param=1]="Param",e[e.ParamRegExp=2]="ParamRegExp",e[e.ParamRegExpEnd=3]="ParamRegExpEnd",e[e.EscapeNext=4]="EscapeNext",e})(Ie||{});const ec={type:Qt.Static,value:""},tc=/[a-zA-Z0-9_]/;function nc(e){if(!e)return[[]];if(e==="/")return[[ec]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(_){throw new Error(`ERR (${n})/"${d}": ${_}`)}let n=Ie.Static,s=n;const o=[];let a;function l(){a&&o.push(a),a=[]}let i=0,u,d="",c="";function p(){d&&(n===Ie.Static?a.push({type:Qt.Static,value:d}):n===Ie.Param||n===Ie.ParamRegExp||n===Ie.ParamRegExpEnd?(a.length>1&&(u==="*"||u==="+")&&t(`A repeatable param (${d}) must be alone in its segment. eg: '/:ids+.`),a.push({type:Qt.Param,value:d,regexp:c,repeatable:u==="*"||u==="+",optional:u==="*"||u==="?"})):t("Invalid state to consume buffer"),d="")}function f(){d+=u}for(;it.length?t.length===1&&t[0]===He.Static+He.Segment?1:-1:0}function Wr(e,t){let n=0;const s=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const lc={strict:!1,end:!0,sensitive:!1};function ic(e,t,n){const s=ac(nc(e.path),n),o=he(s,{record:e,parent:t,children:[],alias:[]});return t&&!o.record.aliasOf==!t.record.aliasOf&&t.children.push(o),o}function uc(e,t){const n=[],s=new Map;t=na(lc,t);function o(p){return s.get(p)}function a(p,f,_){const k=!_,A=fa(p);A.aliasOf=_&&_.record;const I=na(t,p),y=[A];if("alias"in p){const x=typeof p.alias=="string"?[p.alias]:p.alias;for(const $ of x)y.push(fa(he({},A,{components:_?_.record.components:A.components,path:$,aliasOf:_?_.record:A})))}let w,g;for(const x of y){const{path:$}=x;if(f&&$[0]!=="/"){const U=f.record.path,F=U[U.length-1]==="/"?"":"/";x.path=f.record.path+($&&F+$)}if(w=ic(x,f,I),_?_.alias.push(w):(g=g||w,g!==w&&g.alias.push(w),k&&p.name&&!pa(w)&&l(p.name)),Gr(w)&&u(w),A.children){const U=A.children;for(let F=0;F{l(g)}:In}function l(p){if(Fr(p)){const f=s.get(p);f&&(s.delete(p),n.splice(n.indexOf(f),1),f.children.forEach(l),f.alias.forEach(l))}else{const f=n.indexOf(p);f>-1&&(n.splice(f,1),p.record.name&&s.delete(p.record.name),p.children.forEach(l),p.alias.forEach(l))}}function i(){return n}function u(p){const f=fc(p,n);n.splice(f,0,p),p.record.name&&!pa(p)&&s.set(p.record.name,p)}function d(p,f){let _,k={},A,I;if("name"in p&&p.name){if(_=s.get(p.name),!_)throw pn(Ce.MATCHER_NOT_FOUND,{location:p});I=_.record.name,k=he(da(f.params,_.keys.filter(g=>!g.optional).concat(_.parent?_.parent.keys.filter(g=>g.optional):[]).map(g=>g.name)),p.params&&da(p.params,_.keys.map(g=>g.name))),A=_.stringify(k)}else if(p.path!=null)A=p.path,_=n.find(g=>g.re.test(A)),_&&(k=_.parse(A),I=_.record.name);else{if(_=f.name?s.get(f.name):n.find(g=>g.re.test(f.path)),!_)throw pn(Ce.MATCHER_NOT_FOUND,{location:p,currentLocation:f});I=_.record.name,k=he({},f.params,p.params),A=_.stringify(k)}const y=[];let w=_;for(;w;)y.unshift(w.record),w=w.parent;return{name:I,path:A,params:k,matched:y,meta:dc(y)}}e.forEach(p=>a(p));function c(){n.length=0,s.clear()}return{addRoute:a,resolve:d,removeRoute:l,clearRoutes:c,getRoutes:i,getRecordMatcher:o}}function da(e,t){const n={};for(const s of t)s in e&&(n[s]=e[s]);return n}function fa(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:cc(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function cc(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const s in e.components)t[s]=typeof n=="object"?n[s]:n;return t}function pa(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function dc(e){return e.reduce((t,n)=>he(t,n.meta),{})}function fc(e,t){let n=0,s=t.length;for(;n!==s;){const a=n+s>>1;Wr(e,t[a])<0?s=a:n=a+1}const o=pc(e);return o&&(s=t.lastIndexOf(o,s-1)),s}function pc(e){let t=e;for(;t=t.parent;)if(Gr(t)&&Wr(e,t)===0)return t}function Gr({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function ma(e){const t=lt(_s),n=lt(xo),s=le(()=>{const u=Re(e.to);return t.resolve(u)}),o=le(()=>{const{matched:u}=s.value,{length:d}=u,c=u[d-1],p=n.matched;if(!c||!p.length)return-1;const f=p.findIndex(fn.bind(null,c));if(f>-1)return f;const _=va(u[d-2]);return d>1&&va(c)===_&&p[p.length-1].path!==_?p.findIndex(fn.bind(null,u[d-2])):f}),a=le(()=>o.value>-1&&bc(n.params,s.value.params)),l=le(()=>o.value>-1&&o.value===n.matched.length-1&&qr(n.params,s.value.params));function i(u={}){if(gc(u)){const d=t[Re(e.replace)?"replace":"push"](Re(e.to)).catch(In);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>d),d}return Promise.resolve()}return{route:s,href:le(()=>s.value.href),isActive:a,isExactActive:l,navigate:i}}function mc(e){return e.length===1?e[0]:e}const vc=tr({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:ma,setup(e,{slots:t}){const n=fs(ma(e)),{options:s}=lt(_s),o=le(()=>({[ha(e.activeClass,s.linkActiveClass,"router-link-active")]:n.isActive,[ha(e.exactActiveClass,s.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const a=t.default&&mc(t.default(n));return e.custom?a:Dr("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},a)}}}),hc=vc;function gc(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function bc(e,t){for(const n in t){const s=t[n],o=e[n];if(typeof s=="string"){if(s!==o)return!1}else if(!ft(o)||o.length!==s.length||s.some((a,l)=>a.valueOf()!==o[l].valueOf()))return!1}return!0}function va(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const ha=(e,t,n)=>e??t??n,xc=tr({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const s=lt(Ys),o=le(()=>e.route||s.value),a=lt(la,0),l=le(()=>{let d=Re(a);const{matched:c}=o.value;let p;for(;(p=c[d])&&!p.components;)d++;return d}),i=le(()=>o.value.matched[l.value]);Kn(la,le(()=>l.value+1)),Kn(Ku,i),Kn(Ys,o);const u=j();return Ge(()=>[u.value,i.value,e.name],([d,c,p],[f,_,k])=>{c&&(c.instances[p]=d,_&&_!==c&&d&&d===f&&(c.leaveGuards.size||(c.leaveGuards=_.leaveGuards),c.updateGuards.size||(c.updateGuards=_.updateGuards))),d&&c&&(!_||!fn(c,_)||!f)&&(c.enterCallbacks[p]||[]).forEach(A=>A(d))},{flush:"post"}),()=>{const d=o.value,c=e.name,p=i.value,f=p&&p.components[c];if(!f)return ga(n.default,{Component:f,route:d});const _=p.props[c],k=_?_===!0?d.params:typeof _=="function"?_(d):_:null,I=Dr(f,he({},k,t,{onVnodeUnmounted:y=>{y.component.isUnmounted&&(p.instances[c]=null)},ref:u}));return ga(n.default,{Component:I,route:d})||I}}});function ga(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const yc=xc;function _c(e){const t=uc(e.routes,e),n=e.parseQuery||Gu,s=e.stringifyQuery||ra,o=e.history,a=xn(),l=xn(),i=xn(),u=Sl(Ut);let d=Ut;tn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const c=Ts.bind(null,O=>""+O),p=Ts.bind(null,Iu),f=Ts.bind(null,jn);function _(O,G){let W,ee;return Fr(O)?(W=t.getRecordMatcher(O),ee=G):ee=O,t.addRoute(ee,W)}function k(O){const G=t.getRecordMatcher(O);G&&t.removeRoute(G)}function A(){return t.getRoutes().map(O=>O.record)}function I(O){return!!t.getRecordMatcher(O)}function y(O,G){if(G=he({},G||u.value),typeof O=="string"){const C=Os(n,O,G.path),T=t.resolve({path:C.path},G),M=o.createHref(C.fullPath);return he(C,T,{params:f(T.params),hash:jn(C.hash),redirectedFrom:void 0,href:M})}let W;if(O.path!=null)W=he({},O,{path:Os(n,O.path,G.path).path});else{const C=he({},O.params);for(const T in C)C[T]==null&&delete C[T];W=he({},O,{params:p(C)}),G.params=p(G.params)}const ee=t.resolve(W,G),ue=O.hash||"";ee.params=c(f(ee.params));const m=Du(s,he({},O,{hash:Au(ue),path:ee.path})),h=o.createHref(m);return he({fullPath:m,hash:ue,query:s===ra?zu(O.query):O.query||{}},ee,{redirectedFrom:void 0,href:h})}function w(O){return typeof O=="string"?Os(n,O,u.value.path):he({},O)}function g(O,G){if(d!==O)return pn(Ce.NAVIGATION_CANCELLED,{from:G,to:O})}function x(O){return F(O)}function $(O){return x(he(w(O),{replace:!0}))}function U(O,G){const W=O.matched[O.matched.length-1];if(W&&W.redirect){const{redirect:ee}=W;let ue=typeof ee=="function"?ee(O,G):ee;return typeof ue=="string"&&(ue=ue.includes("?")||ue.includes("#")?ue=w(ue):{path:ue},ue.params={}),he({query:O.query,hash:O.hash,params:ue.path!=null?{}:O.params},ue)}}function F(O,G){const W=d=y(O),ee=u.value,ue=O.state,m=O.force,h=O.replace===!0,C=U(W,ee);if(C)return F(he(w(C),{state:typeof C=="object"?he({},ue,C.state):ue,force:m,replace:h}),G||W);const T=W;T.redirectedFrom=G;let M;return!m&&Tu(s,ee,W)&&(M=pn(Ce.NAVIGATION_DUPLICATED,{to:T,from:ee}),nt(ee,ee,!0,!1)),(M?Promise.resolve(M):te(T,ee)).catch(D=>At(D)?At(D,Ce.NAVIGATION_GUARD_REDIRECT)?D:Ke(D):pe(D,T,ee)).then(D=>{if(D){if(At(D,Ce.NAVIGATION_GUARD_REDIRECT))return F(he({replace:h},w(D.to),{state:typeof D.to=="object"?he({},ue,D.to.state):ue,force:m}),G||T)}else D=Pe(T,ee,!0,h,ue);return B(T,ee,D),D})}function H(O,G){const W=g(O,G);return W?Promise.reject(W):Promise.resolve()}function me(O){const G=Ze.values().next().value;return G&&typeof G.runWithContext=="function"?G.runWithContext(O):O()}function te(O,G){let W;const[ee,ue,m]=Qu(O,G);W=Ns(ee.reverse(),"beforeRouteLeave",O,G);for(const C of ee)C.leaveGuards.forEach(T=>{W.push(qt(T,O,G))});const h=H.bind(null,O,G);return W.push(h),Qe(W).then(()=>{W=[];for(const C of a.list())W.push(qt(C,O,G));return W.push(h),Qe(W)}).then(()=>{W=Ns(ue,"beforeRouteUpdate",O,G);for(const C of ue)C.updateGuards.forEach(T=>{W.push(qt(T,O,G))});return W.push(h),Qe(W)}).then(()=>{W=[];for(const C of m)if(C.beforeEnter)if(ft(C.beforeEnter))for(const T of C.beforeEnter)W.push(qt(T,O,G));else W.push(qt(C.beforeEnter,O,G));return W.push(h),Qe(W)}).then(()=>(O.matched.forEach(C=>C.enterCallbacks={}),W=Ns(m,"beforeRouteEnter",O,G,me),W.push(h),Qe(W))).then(()=>{W=[];for(const C of l.list())W.push(qt(C,O,G));return W.push(h),Qe(W)}).catch(C=>At(C,Ce.NAVIGATION_CANCELLED)?C:Promise.reject(C))}function B(O,G,W){i.list().forEach(ee=>me(()=>ee(O,G,W)))}function Pe(O,G,W,ee,ue){const m=g(O,G);if(m)return m;const h=G===Ut,C=tn?history.state:{};W&&(ee||h?o.replace(O.fullPath,he({scroll:h&&C&&C.scroll},ue)):o.push(O.fullPath,ue)),u.value=O,nt(O,G,W,h),Ke()}let J;function ze(){J||(J=o.listen((O,G,W)=>{if(!pt.listening)return;const ee=y(O),ue=U(ee,pt.currentRoute.value);if(ue){F(he(ue,{replace:!0,force:!0}),ee).catch(In);return}d=ee;const m=u.value;tn&&qu(aa(m.fullPath,W.delta),ys()),te(ee,m).catch(h=>At(h,Ce.NAVIGATION_ABORTED|Ce.NAVIGATION_CANCELLED)?h:At(h,Ce.NAVIGATION_GUARD_REDIRECT)?(F(he(w(h.to),{force:!0}),ee).then(C=>{At(C,Ce.NAVIGATION_ABORTED|Ce.NAVIGATION_DUPLICATED)&&!W.delta&&W.type===Qs.pop&&o.go(-1,!1)}).catch(In),Promise.reject()):(W.delta&&o.go(-W.delta,!1),pe(h,ee,m))).then(h=>{h=h||Pe(ee,m,!1),h&&(W.delta&&!At(h,Ce.NAVIGATION_CANCELLED)?o.go(-W.delta,!1):W.type===Qs.pop&&At(h,Ce.NAVIGATION_ABORTED|Ce.NAVIGATION_DUPLICATED)&&o.go(-1,!1)),B(ee,m,h)}).catch(In)}))}let Vt=xn(),Se=xn(),ve;function pe(O,G,W){Ke(O);const ee=Se.list();return ee.length?ee.forEach(ue=>ue(O,G,W)):console.error(O),Promise.reject(O)}function at(){return ve&&u.value!==Ut?Promise.resolve():new Promise((O,G)=>{Vt.add([O,G])})}function Ke(O){return ve||(ve=!O,ze(),Vt.list().forEach(([G,W])=>O?W(O):G()),Vt.reset()),O}function nt(O,G,W,ee){const{scrollBehavior:ue}=e;if(!tn||!ue)return Promise.resolve();const m=!W&&Fu(aa(O.fullPath,0))||(ee||!W)&&history.state&&history.state.scroll||null;return uo().then(()=>ue(O,G,m)).then(h=>h&&Lu(h)).catch(h=>pe(h,O,G))}const De=O=>o.go(O);let $t;const Ze=new Set,pt={currentRoute:u,listening:!0,addRoute:_,removeRoute:k,clearRoutes:t.clearRoutes,hasRoute:I,getRoutes:A,resolve:y,options:e,push:x,replace:$,go:De,back:()=>De(-1),forward:()=>De(1),beforeEach:a.add,beforeResolve:l.add,afterEach:i.add,onError:Se.add,isReady:at,install(O){O.component("RouterLink",hc),O.component("RouterView",yc),O.config.globalProperties.$router=pt,Object.defineProperty(O.config.globalProperties,"$route",{enumerable:!0,get:()=>Re(u)}),tn&&!$t&&u.value===Ut&&($t=!0,x(o.location).catch(ee=>{}));const G={};for(const ee in Ut)Object.defineProperty(G,ee,{get:()=>u.value[ee],enumerable:!0});O.provide(_s,pt),O.provide(xo,Ba(G)),O.provide(Ys,u);const W=O.unmount;Ze.add(O),O.unmount=function(){Ze.delete(O),Ze.size<1&&(d=Ut,J&&J(),J=null,u.value=Ut,$t=!1,ve=!1),W()}}};function Qe(O){return O.reduce((G,W)=>G.then(()=>me(W)),Promise.resolve())}return pt}function yo(){return lt(_s)}function zr(e){return lt(xo)}const Gn=window.location.pathname.startsWith("/portal/"),Ye={esPortal:Gn,baseRuta:Gn?"/portal/studio/":"/studio/",apiBase:Gn?"/portal":"/app",urlLogin:Gn?"/portal/login":"/login"};function K(e){return Ye.apiBase+e}async function yn(e,t={}){const n=t.body instanceof FormData,s=await fetch(e,{...t,headers:n?t.headers:{"Content-Type":"application/json",...t.headers}}),o=s.headers.get("content-type")||"";if(s.redirected||!o.includes("application/json"))throw window.location.href=Ye.urlLogin,new Error("Sesión expirada");const a=await s.json();if(!s.ok){const l=typeof(a==null?void 0:a.error)=="string"?a.error:a==null?void 0:a.message;throw new Error(l||"Error de servidor")}return a}const Q={get:e=>yn(e),postForm:(e,t)=>yn(e,{method:"POST",body:t,headers:{}}),post:(e,t)=>yn(e,{method:"POST",body:JSON.stringify(t)}),put:(e,t)=>yn(e,{method:"PUT",body:JSON.stringify(t)}),del:e=>yn(e,{method:"DELETE"})},kn=j(!1),wc={class:"h-14 px-4 flex items-center gap-2 border-b border-borde"},kc={key:0,class:"px-3 pt-3"},$c={key:1,class:"px-3 pt-2 text-xs text-red-600 dark:text-red-400"},Cc={class:"flex-1 overflow-y-auto px-2 py-3 space-y-0.5"},Ac={key:0,class:"px-2 text-xs text-tenue"},Sc={key:1,class:"px-2 text-xs text-tenue"},Ec={class:"truncate"},Ic={class:"flex items-center gap-1 mt-0.5"},Rc={class:"text-[11px] text-tenue"},Pc={key:0,class:"flex opacity-0 group-hover:opacity-100 transition-opacity pr-1.5 gap-0.5"},Dc=["onClick"],Tc=["onClick"],Oc={class:"card w-full max-w-lg p-6 animate-escalar shadow-2xl"},Mc={class:"font-semibold text-texto mb-4"},Nc={key:0,class:"grid grid-cols-2 gap-3"},jc=["value"],Vc={class:"text-[11px] text-tenue mt-1"},Uc=["value"],Lc={class:"text-[11px] text-tenue mt-1"},qc={class:"flex items-center gap-2 text-sm text-texto"},Fc={class:"flex justify-end gap-2 pt-2"},Hc={__name:"Sidebar",setup(e,{expose:t}){const n=zr(),s=yo(),o=j([]),a=j([]),l=j([]),i=j(!0),u=j(""),d=j(!1),c=j(null),p=j(_()),f=le(()=>n.params.tenantId||n.params.id);Ge(()=>n.fullPath,()=>{kn.value=!1});function _(){return{nombre:"",dominios_permitidos:"",activo:!0,cliente_id:null,plan_id:null}}async function k(){i.value=!0,u.value="";try{const $=await Q.get(K("/umind/tenants"));o.value=$.items||[]}catch($){u.value=$.message}finally{i.value=!1}}function A($){return Array.isArray($)?$:($==null?void 0:$.items)||($==null?void 0:$.registros)||[]}async function I(){if(Ye.esPortal)return;const[$,U]=await Promise.allSettled([Q.get("/app/api/clientes/select"),Q.get("/app/umind-planes/list")]);a.value=$.status==="fulfilled"?A($.value):[],l.value=U.status==="fulfilled"?A(U.value):[];const F=[];$.status==="rejected"&&F.push("clientes"),U.status==="rejected"&&F.push("planes"),F.length&&(u.value=`No se pudo cargar la lista de ${F.join(" ni ")}.`)}function y(){c.value=null,p.value=_(),d.value=!0}function w($){c.value=$,p.value={nombre:$.nombre,dominios_permitidos:$.dominios_permitidos,activo:$.activo,cliente_id:$.cliente_id??null,plan_id:$.plan_id??null},d.value=!0}async function g(){const $={...p.value,dominios_permitidos:p.value.dominios_permitidos.split(",").map(U=>U.trim()).filter(Boolean)};try{if(c.value)await Q.put(K(`/umind/tenants/${c.value.ID}`),$),d.value=!1,await k();else{const U=await Q.post(K("/umind/tenants"),$);d.value=!1,await k(),s.push(`/tenants/${U.id}`)}}catch(U){u.value=U.message}}async function x($){confirm(`¿Eliminar el espacio "${$.nombre}"? Esto borra también sus agentes. No se puede deshacer.`)&&(await Q.del(K(`/umind/tenants/${$.ID}`)),f.value===String($.ID)&&s.push("/"),await k())}return t({recargar:k}),hs(()=>{k(),I()}),($,U)=>{const F=Wt("router-link");return v(),b(Z,null,[Re(kn)?(v(),b("div",{key:0,class:"fixed inset-0 bg-black/50 z-30 md:hidden",onClick:U[0]||(U[0]=H=>kn.value=!1)})):V("",!0),r("aside",{class:ie(["w-64 shrink-0 flex flex-col border-r border-borde bg-superficie fixed inset-y-0 left-0 z-40 transition-transform duration-200 md:static md:h-screen md:sticky md:top-0 md:translate-x-0",Re(kn)?"translate-x-0":"-translate-x-full"])},[r("div",wc,[ne(F,{to:"/",class:"flex items-center gap-2 text-base font-semibold text-texto"},{default:dt(()=>[...U[8]||(U[8]=[r("svg",{viewBox:"0 0 96 96",class:"w-6 h-6 shrink-0","aria-hidden":"true"},[r("rect",{width:"96",height:"96",rx:"22",fill:"#8eb02f"}),r("path",{d:"M32,42 V58 A14,14 0 0 0 60,58 V42",fill:"none",stroke:"#fff","stroke-width":"10","stroke-linecap":"round","stroke-linejoin":"round"}),r("path",{d:"M60,58 V64",fill:"none",stroke:"#fff","stroke-width":"10","stroke-linecap":"round"}),r("circle",{cx:"60",cy:"28",r:"7",fill:"#fff"})],-1),r("span",null,[Y("uMind "),r("span",{class:"text-brand"},"Studio")],-1)])]),_:1})]),Re(Ye).esPortal?V("",!0):(v(),b("div",kc,[r("button",{class:"btn-primary w-full",onClick:y}," + Nuevo espacio ")])),u.value?(v(),b("p",$c,S(u.value),1)):V("",!0),r("nav",Cc,[i.value?(v(),b("p",Ac,"Cargando...")):o.value.length===0?(v(),b("p",Sc,S(Re(Ye).esPortal?"Todavía no tenés ningún espacio asignado. Escribinos y lo activamos.":"Sin espacios todavía."),1)):V("",!0),(v(!0),b(Z,null,ce(o.value,H=>(v(),b("div",{key:H.ID,class:ie(["group flex items-center rounded-lg transition-colors",f.value===String(H.ID)?"bg-brand/10":"hover:bg-elevado"])},[ne(F,{to:`/tenants/${H.ID}`,class:ie(["flex-1 min-w-0 px-2.5 py-2 text-sm",f.value===String(H.ID)?"text-brand font-medium":"text-texto"])},{default:dt(()=>[r("div",Ec,S(H.nombre),1),r("div",Ic,[r("span",{class:ie(["w-1.5 h-1.5 rounded-full",H.activo?"bg-green-500":"bg-tenue/40"])},null,2),r("span",Rc,S(H.activo?"activo":"inactivo"),1)])]),_:2},1032,["to","class"]),Re(Ye).esPortal?V("",!0):(v(),b("div",Pc,[r("button",{class:"p-1 text-tenue hover:text-texto",title:"Editar",onClick:me=>w(H)},[ne(Ne,{nombre:"lapiz",tam:14})],8,Dc),r("button",{class:"p-1 text-tenue hover:text-red-600",title:"Eliminar",onClick:me=>x(H)},[ne(Ne,{nombre:"cerrar",tam:14})],8,Tc)]))],2))),128))])],2),d.value?(v(),b("div",{key:1,class:"fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50",onClick:U[7]||(U[7]=Ae(H=>d.value=!1,["self"]))},[r("div",Oc,[r("h2",Mc,S(c.value?"Editar espacio":"Nuevo espacio"),1),U[17]||(U[17]=r("p",{class:"text-xs text-tenue mb-3"}," Un espacio es el negocio o sitio dueño de los dominios permitidos. La config de IA, tono y demás se configuran por agente, dentro del tenant. ",-1)),r("form",{class:"space-y-3",onSubmit:Ae(g,["prevent"])},[r("div",null,[U[9]||(U[9]=r("label",{class:"label"},"Nombre",-1)),z(r("input",{"onUpdate:modelValue":U[1]||(U[1]=H=>p.value.nombre=H),required:"",class:"input"},null,512),[[re,p.value.nombre]])]),r("div",null,[U[10]||(U[10]=r("label",{class:"label"},"Dominios permitidos (separados por coma)",-1)),z(r("input",{"onUpdate:modelValue":U[2]||(U[2]=H=>p.value.dominios_permitidos=H),placeholder:"ejemplo.com, www.ejemplo.com",required:"",class:"input"},null,512),[[re,p.value.dominios_permitidos]])]),Re(Ye).esPortal?V("",!0):(v(),b("div",Nc,[r("div",null,[U[12]||(U[12]=r("label",{class:"label"},"Cliente",-1)),z(r("select",{"onUpdate:modelValue":U[3]||(U[3]=H=>p.value.cliente_id=H),class:"input"},[U[11]||(U[11]=r("option",{value:null},"— sin asignar —",-1)),(v(!0),b(Z,null,ce(a.value,H=>(v(),b("option",{key:H.ID,value:H.ID},S(H.nombre),9,jc))),128))],512),[[Nt,p.value.cliente_id]]),r("p",Vc,S(a.value.length?"Define quién ve este espacio desde el portal.":"No hay clientes activos — creá uno en Clientes."),1)]),r("div",null,[U[14]||(U[14]=r("label",{class:"label"},"Plan",-1)),z(r("select",{"onUpdate:modelValue":U[4]||(U[4]=H=>p.value.plan_id=H),class:"input"},[U[13]||(U[13]=r("option",{value:null},"— sin plan —",-1)),(v(!0),b(Z,null,ce(l.value,H=>(v(),b("option",{key:H.ID,value:H.ID},S(H.nombre)+" ("+S(H.max_agentes===0?"∞":H.max_agentes)+" agentes) ",9,Uc))),128))],512),[[Nt,p.value.plan_id]]),r("p",Lc,S(l.value.length?"Límite de agentes y precios de consumo.":"No hay planes — creá uno en uMind Planes."),1)])])),r("label",qc,[z(r("input",{"onUpdate:modelValue":U[5]||(U[5]=H=>p.value.activo=H),type:"checkbox"},null,512),[[st,p.value.activo]]),U[15]||(U[15]=Y(" Activo ",-1))]),r("div",Fc,[r("button",{type:"button",class:"btn-ghost",onClick:U[6]||(U[6]=H=>d.value=!1)}," Cancelar "),U[16]||(U[16]=r("button",{type:"submit",class:"btn-primary"}," Guardar ",-1))])],32)])])):V("",!0)],64)}}},Kr="umind-tema";function Bc(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"oscuro":"claro"}const ln=j(localStorage.getItem(Kr)||Bc());function Qr(){document.documentElement.classList.toggle("dark",ln.value==="oscuro")}function ba(){ln.value=ln.value==="oscuro"?"claro":"oscuro",localStorage.setItem(Kr,ln.value),Qr()}Qr();const xa="umind_despertar_visto",ya=1250,Wc={__name:"DespertarUmind",setup(e){const t=j(null),n=j(!1);let s=null,o=null;function a(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}return hs(()=>{a()||sessionStorage.getItem(xa)||(sessionStorage.setItem(xa,"1"),n.value=!0,o=setTimeout(()=>n.value=!1,ya),requestAnimationFrame(()=>{const l=t.value;if(!l)return;const i=l.getContext("2d"),u=Math.min(window.devicePixelRatio||1,2),d=window.innerWidth,c=window.innerHeight;l.width=Math.round(d*u),l.height=Math.round(c*u),i.setTransform(u,0,0,u,0,0);const p=d<640?22:46,f=Array.from({length:p},()=>({x:Math.random()*d,y:Math.random()*c,r:1+Math.random()*1.6,demora:Math.random()*.45})),_=performance.now(),k=A=>{const I=Math.min(1,(A-_)/ya);i.clearRect(0,0,d,c);const y=I<.75?1:1-(I-.75)/.25;for(let w=0;w170||(i.strokeStyle=`rgba(142, 176, 47, ${.16*(1-me/170)*x*y})`,i.lineWidth=1,i.beginPath(),i.moveTo(g.x,g.y),i.lineTo(U.x,U.y),i.stroke())}i.beginPath(),i.arc(g.x,g.y,g.r*x,0,Math.PI*2),i.fillStyle=`rgba(142, 176, 47, ${.5*x*y})`,i.fill()}}I<1&&(s=requestAnimationFrame(k))};s=requestAnimationFrame(k)}))}),or(()=>{s&&cancelAnimationFrame(s),o&&clearTimeout(o)}),(l,i)=>n.value?(v(),b("canvas",{key:0,ref_key:"lienzo",ref:t,class:"fixed inset-0 w-full h-full pointer-events-none z-50","aria-hidden":"true"},null,512)):V("",!0)}},Gc={class:"min-h-screen flex"},zc={class:"flex-1 min-w-0 flex flex-col"},Kc={class:"h-14 shrink-0 flex items-center gap-1 px-4 sm:px-6 border-b border-borde"},Qc=["title"],Jc={class:"flex-1 max-w-5xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-6 sm:py-8 animate-aparecer"},Yc={__name:"App",setup(e){return(t,n)=>{const s=Wt("router-view");return v(),b("div",Gc,[ne(Wc),ne(Hc),r("main",zc,[r("header",Kc,[r("button",{class:"btn-ghost !px-2 !py-1.5 md:hidden","aria-label":"Abrir menú",onClick:n[0]||(n[0]=o=>kn.value=!0)},[...n[2]||(n[2]=[r("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor","stroke-width":"2",viewBox:"0 0 24 24"},[r("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M4 6h16M4 12h16M4 18h16"})],-1)])]),n[3]||(n[3]=r("span",{class:"flex-1"},null,-1)),r("button",{class:"btn-ghost !px-2.5 !py-1.5",title:Re(ln)==="oscuro"?"Cambiar a claro":"Cambiar a oscuro",onClick:n[1]||(n[1]=(...o)=>Re(ba)&&Re(ba)(...o))},[ne(Ne,{nombre:Re(ln)==="oscuro"?"sol":"luna",tam:17},null,8,["nombre"])],8,Qc)]),r("div",Jc,[ne(s)])])])}}},Zc=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n},Xc=["width","height","aria-label"],ed=["fill"],td=["stroke"],nd=["cy"],sd=["cy"],od=["cy"],ad=["cy"],rd={key:1,d:"M41,66 h12 M67,66 h12",class:"umi-linea","stroke-width":"5","stroke-linecap":"round",fill:"none"},ld={key:4,d:"M50,78 q10,8 20,0",class:"umi-linea","stroke-width":"4",fill:"none","stroke-linecap":"round"},id={__name:"UiMascota",props:{estado:{type:String,default:"normal"},tam:{type:[Number,String],default:72}},setup(e){return(t,n)=>(v(),b("svg",{width:e.tam,height:e.tam,viewBox:"0 0 120 120",class:"shrink-0",role:"img","aria-label":`Umi, la mascota de uMind (${e.estado})`},[r("circle",{cx:"60",cy:"26",r:"6",fill:e.estado==="alerta"?"#dc2626":"currentColor",class:ie(e.estado==="pensando"?"umi-late":"")},null,10,ed),r("line",{x1:"60",y1:"32",x2:"60",y2:"44",stroke:e.estado==="alerta"?"#dc2626":"currentColor","stroke-width":"4","stroke-linecap":"round"},null,8,td),n[7]||(n[7]=r("path",{d:"M30,46 V76 A30,30 0 0 0 90,76 V46 Z",fill:"currentColor"},null,-1)),e.estado==="normal"||e.estado==="contenta"||e.estado==="alerta"?(v(),b(Z,{key:0},[r("circle",{cx:"47",cy:e.estado==="contenta"?64:66,r:"6",class:"umi-ojo"},null,8,nd),r("circle",{cx:"73",cy:e.estado==="contenta"?64:66,r:"6",class:"umi-ojo"},null,8,sd),r("circle",{cx:"48",cy:e.estado==="contenta"?65:67,r:"3",class:"umi-pupila"},null,8,od),r("circle",{cx:"74",cy:e.estado==="contenta"?65:67,r:"3",class:"umi-pupila"},null,8,ad)],64)):e.estado==="durmiendo"?(v(),b("path",rd)):e.estado==="pensando"?(v(),b(Z,{key:2},[n[0]||(n[0]=r("circle",{cx:"45",cy:"66",r:"4.5",class:"umi-ojo umi-p1"},null,-1)),n[1]||(n[1]=r("circle",{cx:"60",cy:"66",r:"4.5",class:"umi-ojo umi-p2"},null,-1)),n[2]||(n[2]=r("circle",{cx:"75",cy:"66",r:"4.5",class:"umi-ojo umi-p3"},null,-1))],64)):e.estado==="buscando"?(v(),b(Z,{key:3},[n[3]||(n[3]=r("circle",{cx:"47",cy:"66",r:"6",class:"umi-ojo"},null,-1)),n[4]||(n[4]=r("circle",{cx:"73",cy:"66",r:"6",class:"umi-ojo"},null,-1)),n[5]||(n[5]=r("circle",{cx:"50",cy:"66",r:"3",class:"umi-pupila"},null,-1)),n[6]||(n[6]=r("circle",{cx:"76",cy:"66",r:"3",class:"umi-pupila"},null,-1))],64)):V("",!0),e.estado==="contenta"?(v(),b("path",ld)):V("",!0)],8,Xc))}},Vn=Zc(id,[["__scopeId","data-v-551897a0"]]),ud={key:0,class:"flex flex-col items-center justify-center py-24 text-sm text-tenue"},cd={key:1,class:"max-w-md mx-auto text-center py-20"},dd={key:2,class:"flex flex-col items-center justify-center text-center py-24"},fd={class:"text-lg font-medium text-texto"},pd={class:"text-sm text-tenue mt-1"},md={__name:"Home",setup(e){const t=yo(),n=j(Ye.esPortal),s=j(!1);async function o(){if(Ye.esPortal)try{const l=(await Q.get(K("/umind/tenants"))).items||[];if(l.length===0){s.value=!0;return}if(l.length!==1)return;const i=l[0].ID,d=(await Q.get(K(`/umind/agentes?tenant_id=${i}`))).items||[];if(d.length===1){t.replace(`/tenants/${i}/agentes/${d[0].ID}`);return}t.replace(`/tenants/${i}`)}catch{}finally{n.value=!1}}return hs(o),(a,l)=>n.value?(v(),b("div",ud," Abriendo tu asistente… ")):s.value?(v(),b("div",cd,[ne(Vn,{estado:"durmiendo",tam:80,class:"mx-auto mb-4 text-brand"}),l[0]||(l[0]=go('

Todavía no tenés un asistente activo

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.

Quiero activarlo

Volver al portal

',4))])):(v(),b("div",dd,[ne(Vn,{estado:"normal",tam:64,class:"mx-auto mb-4 text-brand"}),r("h1",fd,S(Re(Ye).esPortal?"Elegí tu espacio de la izquierda":"Elegí un espacio de la izquierda"),1),r("p",pd,S(Re(Ye).esPortal?"Adentro vas a poder crear y configurar tus agentes.":"o creá uno nuevo para empezar a configurar su agente."),1)]))}},vd={class:"flex flex-col items-center justify-center text-center py-12 px-6"},hd={key:0,class:"text-3xl mb-3 opacity-70"},gd={class:"text-sm font-medium text-texto"},bd={key:2,class:"text-xs text-tenue mt-1.5 max-w-sm leading-relaxed"},xd={key:3,class:"mt-4"},qe={__name:"UiEmptyState",props:{estado:{type:String,default:"durmiendo"},titulo:String,detalle:String,icono:{type:String,default:""}},setup(e){return(t,n)=>(v(),b("div",vd,[e.icono?(v(),b("div",hd,S(e.icono),1)):(v(),de(Vn,{key:1,estado:e.estado,tam:64,class:"mb-3 text-brand"},null,8,["estado"])),r("p",gd,S(e.titulo),1),e.detalle?(v(),b("p",bd,S(e.detalle),1)):V("",!0),t.$slots.default?(v(),b("div",xd,[Xl(t.$slots,"default")])):V("",!0)]))}},yd={class:"flex gap-1 flex-wrap mb-6 border-b border-borde pb-2"},_d={key:0,class:"px-1.5 py-0.5 rounded-full bg-amber-500 text-white text-[10px] font-semibold leading-none"},vn={__name:"NavEspacio",props:{tenantId:{type:[String,Number],required:!0}},setup(e){const t=e,n=j(0);async function s(){try{const a=await Q.get(K(`/umind/acciones?tenant_id=${t.tenantId}`));n.value=a.pendientes||0}catch{n.value=0}}Ge(()=>t.tenantId,s,{immediate:!0});const o=[["tenant-agentes","","Agentes"],["pendientes","/pendientes","Pendientes"],["archivos","/archivos","Archivos"],["plantillas","/plantillas","Plantillas"],["uso","/uso","Consumo"],["ai-propia","/ia","Tu IA"]];return(a,l)=>{const i=Wt("router-link");return v(),b("nav",yd,[(v(),b(Z,null,ce(o,([u,d,c])=>ne(i,{key:u,to:`/tenants/${e.tenantId}${d}`,class:ie(["px-3 py-1.5 rounded-lg text-sm transition-colors inline-flex items-center gap-1.5",a.$route.name===u?"bg-brand/10 text-brand font-medium":"text-tenue hover:text-texto hover:bg-elevado"])},{default:dt(()=>[Y(S(c)+" ",1),u==="pendientes"&&n.value>0?(v(),b("span",_d,S(n.value),1)):V("",!0)]),_:2},1032,["to","class"])),64))])}}},wd={key:0,class:"mb-4"},kd={class:"flex items-start justify-between gap-4"},$d={class:"text-xl font-semibold text-texto"},Cd={class:"text-xs text-tenue mt-1"},Ad={key:1,class:"text-sm text-red-600 dark:text-red-400 mb-4"},Sd={class:"flex items-center justify-between mb-4"},Ed={class:"flex items-center gap-2"},Id={key:0,class:"badge-alerta"},Rd={key:1,class:"badge-neutro"},Pd=["disabled"],Dd={key:2,class:"text-xs text-tenue -mt-2 mb-4"},Td={key:3,class:"text-xs text-tenue -mt-2 mb-4"},Od={key:4,class:"grid gap-3 sm:grid-cols-2"},Md=["disabled"],Nd={key:6,class:"grid gap-3 sm:grid-cols-2"},jd={class:"flex items-start gap-3"},Vd={class:"min-w-0 flex-1"},Ud={class:"flex items-center gap-2"},Ld={class:"font-medium text-texto truncate"},qd={class:"text-xs text-tenue mt-0.5 truncate"},Fd={class:"flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"},Hd=["onClick"],Bd=["onClick"],Wd=["onClick"],Gd={class:"flex items-center gap-4 mt-3.5 pt-3 border-t border-borde text-xs text-tenue"},zd={class:"tabular-nums"},Kd={class:"text-texto font-medium"},Qd={class:"tabular-nums"},Jd={class:"text-texto font-medium"},Yd={class:"tabular-nums"},Zd={class:"text-texto font-medium"},Xd={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"},ef={class:"font-semibold text-gray-800 dark:text-gray-100 mb-4"},tf={key:0},nf={class:"grid gap-1.5"},sf=["value"],of={class:"min-w-0"},af={class:"block text-sm text-texto"},rf={class:"block text-xs text-tenue"},lf={key:0,class:"block text-xs text-tenue mt-0.5"},uf=["value"],cf={class:"flex items-center gap-2"},df={class:"flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300"},ff={class:"flex justify-end gap-2 pt-2"},pf={type:"submit",class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg"},mf={__name:"TenantAgentes",props:{id:{type:String,required:!0}},setup(e){const t=e,n=le(()=>Number(t.id)),s=yo(),o=j(null),a=j([]),l=j([]),i=j(""),u=j(!1),d=j(null),c=j(w()),p=j(null),f=j({}),_=j(!0);function k(te){const B=f.value[te.ID]||{};return te.activo?B.documentos>0?{tipo:"ok",texto:"listo"}:{tipo:"alerta",texto:"sin conocimiento"}:{tipo:"neutro",texto:"inactivo"}}function A(te){const B=f.value[te.ID]||{};return{documentos:B.documentos||0,canales:B.canales||0,conversaciones:B.conversaciones_7d||0}}function I(te){return String(te||"?").trim().split(/\s+/).slice(0,2).map(B=>B[0]).join("").toUpperCase()}const y=le(()=>{if(!p.value)return{sinPlan:!0};const te=p.value.max_agentes||0;return{sinPlan:!1,nombre:p.value.nombre,ilimitado:te<=0,max:te,usados:a.value.length,lleno:te>0&&a.value.length>=te}});function w(){return{nombre:"",ai_config_id:null,tono:"",mensaje_bienvenida:"",color:"#8eb02f",activo:!0,plantilla_rubro:""}}const g=j([]);async function x(){i.value="",_.value=!0;try{const[te,B,Pe,J]=await Promise.all([Q.get(K("/umind/tenants")),Q.get(K(`/umind/agentes?tenant_id=${t.id}`)),Q.get(K("/umind/ai-configs")),Q.get(K("/umind/plantillas-rubro"))]);o.value=(te.items||[]).find(ze=>String(ze.ID)===t.id)||null,a.value=B.items||[],p.value=B.plan||null,f.value=B.resumen||{},l.value=Pe.items||[],g.value=J.items||[]}catch(te){i.value=te.message}finally{_.value=!1}}async function $(te){const B=prompt(`Nombre de la copia de "${te.nombre}":`,`${te.nombre} (copia)`);if(B!==null){i.value="";try{const Pe=await Q.post(K(`/umind/agentes/${te.ID}/duplicar`),{tenant_id:Number(n.value),nombre:B.trim()});await x(),Pe.aviso&&alert(Pe.aviso)}catch(Pe){i.value=Pe.message}}}function U(){d.value=null,c.value=w(),u.value=!0}function F(te){d.value=te,c.value={nombre:te.nombre,ai_config_id:te.ai_config_id,tono:te.tono,mensaje_bienvenida:te.mensaje_bienvenida,color:te.color||"#8eb02f",activo:te.activo},u.value=!0}async function H(){try{if(d.value)await Q.put(K(`/umind/agentes/${d.value.ID}`),{tenant_id:n.value,...c.value}),u.value=!1,await x();else{const te=await Q.post(K("/umind/agentes"),{tenant_id:n.value,...c.value});u.value=!1,s.push(`/tenants/${n.value}/agentes/${te.id}`)}}catch(te){i.value=te.message}}async function me(te){confirm(`¿Eliminar el agente "${te.nombre}"? Esto no se puede deshacer.`)&&(await Q.del(K(`/umind/agentes/${te.ID}`)),await x())}return Ge(()=>t.id,x,{immediate:!0}),(te,B)=>{const Pe=Wt("router-link");return v(),b("div",null,[o.value?(v(),b("div",wd,[r("div",kd,[r("div",null,[r("h1",$d,S(o.value.nombre),1),r("p",Cd,S(o.value.dominios_permitidos||"sin dominios configurados"),1)])])])):V("",!0),ne(vn,{"tenant-id":n.value??e.id},null,8,["tenant-id"]),i.value?(v(),b("p",Ad,S(i.value),1)):V("",!0),r("div",Sd,[r("div",Ed,[B[10]||(B[10]=r("h2",{class:"text-sm font-medium text-tenue"},"Agentes",-1)),y.value.sinPlan?(v(),b("span",Id,"sin plan · sin límite")):y.value.ilimitado?(v(),b("span",Rd,S(y.value.nombre)+" · ilimitado",1)):(v(),b("span",{key:2,class:ie(y.value.lleno?"badge-alerta":"badge-neutro")},S(y.value.nombre)+" · "+S(y.value.usados)+" de "+S(y.value.max),3))]),r("button",{class:"btn-primary",disabled:y.value.lleno,onClick:U},"+ Nuevo agente",8,Pd)]),y.value.sinPlan&&!Re(Ye).esPortal?(v(),b("p",Dd," 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. ")):y.value.lleno?(v(),b("p",Td," Alcanzaste el máximo de agentes de tu plan. ")):V("",!0),_.value?(v(),b("div",Od,[(v(),b(Z,null,ce(2,J=>r("div",{key:J,class:"card p-4 animate-pulse"},[...B[11]||(B[11]=[go('
',2)])])),64))])):a.value.length===0?(v(),de(qe,{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:dt(()=>[r("button",{class:"btn-primary",disabled:y.value.lleno,onClick:U},"+ Crear el primer agente",8,Md)]),_:1})):(v(),b("div",Nd,[(v(!0),b(Z,null,ce(a.value,J=>(v(),de(Pe,{key:J.ID,to:`/tenants/${n.value}/agentes/${J.ID}`,class:"card p-4 relative group hover:shadow-lg hover:-translate-y-0.5 transition-all overflow-hidden"},{default:dt(()=>[r("span",{class:"absolute inset-x-0 top-0 h-1",style:Ft({background:J.color||"#8eb02f"})},null,4),r("div",jd,[r("span",{class:"w-10 h-10 rounded-xl flex items-center justify-center text-white text-sm font-semibold shrink-0",style:Ft({background:J.color||"#8eb02f",opacity:J.activo?1:.4})},S(I(J.nombre)),5),r("div",Vd,[r("div",Ud,[r("span",Ld,S(J.nombre),1),r("span",{class:ie(`badge-${k(J).tipo}`)},S(k(J).texto),3)]),r("p",qd,S(J.tono||"sin tono definido"),1)]),r("div",Fd,[r("button",{class:"p-1 text-tenue hover:text-texto",title:"Editar",onClick:Ae(ze=>F(J),["prevent","stop"])},[ne(Ne,{nombre:"lapiz",tam:14})],8,Hd),r("button",{class:"p-1 text-tenue hover:text-texto",title:"Duplicar: copia el conocimiento y las herramientas a un agente nuevo",onClick:Ae(ze=>$(J),["prevent","stop"])},[ne(Ne,{nombre:"copiar",tam:14})],8,Bd),r("button",{class:"p-1 text-tenue hover:text-red-600",title:"Eliminar",onClick:Ae(ze=>me(J),["prevent","stop"])},[ne(Ne,{nombre:"cerrar",tam:14})],8,Wd)])]),r("div",Gd,[r("span",zd,[r("b",Kd,S(A(J).conversaciones),1),B[12]||(B[12]=Y(" conversaciones · 7d",-1))]),r("span",Qd,[r("b",Jd,S(A(J).documentos),1),B[13]||(B[13]=Y(" fuentes",-1))]),r("span",Yd,[r("b",Zd,S(A(J).canales),1),B[14]||(B[14]=Y(" canales",-1))])])]),_:2},1032,["to"]))),128))])),u.value?(v(),b("div",{key:7,class:"fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50",onClick:B[9]||(B[9]=Ae(J=>u.value=!1,["self"]))},[r("div",Xd,[r("h2",ef,S(d.value?"Editar agente":"Nuevo agente"),1),r("form",{class:"space-y-3",onSubmit:Ae(H,["prevent"])},[r("div",null,[B[15]||(B[15]=r("label",{class:"label"},"Nombre",-1)),z(r("input",{"onUpdate:modelValue":B[0]||(B[0]=J=>c.value.nombre=J),required:"",placeholder:"ej: Ventas, Soporte",class:"input"},null,512),[[re,c.value.nombre]])]),!d.value&&g.value.length?(v(),b("div",tf,[B[16]||(B[16]=r("label",{class:"label"},"Arrancar con",-1)),r("div",nf,[(v(!0),b(Z,null,ce([{clave:"",nombre:"Agente en blanco",descripcion:"Sin conocimiento cargado. Lo escribís vos desde cero."},...g.value],J=>(v(),b("label",{key:J.clave,class:ie(["flex gap-2.5 p-2.5 rounded-lg border cursor-pointer transition-colors",c.value.plantilla_rubro===J.clave?"border-brand bg-brand/5":"border-borde hover:border-brand/40"])},[z(r("input",{"onUpdate:modelValue":B[1]||(B[1]=ze=>c.value.plantilla_rubro=ze),type:"radio",value:J.clave,class:"mt-1 text-brand focus:ring-brand"},null,8,sf),[[zs,c.value.plantilla_rubro]]),r("span",of,[r("span",af,S(J.nombre),1),r("span",rf,S(J.descripcion),1),J.notas?(v(),b("span",lf,S(J.notas)+" notas listas para editar · "+S(J.resumen),1)):V("",!0)])],2))),128))]),B[17]||(B[17]=r("p",{class:"text-xs text-tenue mt-1.5"}," Las notas vienen con ejemplos entre corchetes — abrilas y reemplazalas por tus datos reales. ",-1))])):V("",!0),r("div",null,[B[19]||(B[19]=r("label",{class:"label"},"Config de IA",-1)),z(r("select",{"onUpdate:modelValue":B[2]||(B[2]=J=>c.value.ai_config_id=J),class:"input"},[B[18]||(B[18]=r("option",{value:null},"— sin asignar —",-1)),(v(!0),b(Z,null,ce(l.value,J=>(v(),b("option",{key:J.ID,value:J.ID},S(J.nombre)+" ("+S(J.provider)+")",9,uf))),128))],512),[[Nt,c.value.ai_config_id]])]),r("div",null,[B[20]||(B[20]=r("label",{class:"label"},"Tono / personalidad",-1)),z(r("textarea",{"onUpdate:modelValue":B[3]||(B[3]=J=>c.value.tono=J),rows:"2",class:"input"},null,512),[[re,c.value.tono]])]),r("div",null,[B[21]||(B[21]=r("label",{class:"label"},"Mensaje de bienvenida",-1)),z(r("input",{"onUpdate:modelValue":B[4]||(B[4]=J=>c.value.mensaje_bienvenida=J),class:"input"},null,512),[[re,c.value.mensaje_bienvenida]])]),r("div",null,[B[22]||(B[22]=r("label",{class:"label"},"Color del widget",-1)),r("div",cf,[z(r("input",{"onUpdate:modelValue":B[5]||(B[5]=J=>c.value.color=J),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),[[re,c.value.color]]),z(r("input",{"onUpdate:modelValue":B[6]||(B[6]=J=>c.value.color=J),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),[[re,c.value.color]])])]),r("label",df,[z(r("input",{"onUpdate:modelValue":B[7]||(B[7]=J=>c.value.activo=J),type:"checkbox"},null,512),[[st,c.value.activo]]),B[23]||(B[23]=Y(" Activo ",-1))]),r("div",ff,[r("button",{type:"button",class:"px-4 py-2 text-sm text-gray-500 dark:text-gray-400",onClick:B[8]||(B[8]=J=>u.value=!1)},"Cancelar"),r("button",pf,S(d.value?"Guardar":"Crear"),1)])],32)])])):V("",!0)])}}},vf={class:"card divide-y divide-borde max-h-[32rem] overflow-y-auto"},hf={class:"cursor-pointer flex items-center gap-2 text-sm"},gf={class:"text-tenue text-xs shrink-0"},bf={class:"text-texto truncate"},xf={class:"text-tenue text-xs ml-auto shrink-0"},yf={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"},_f={__name:"TabAuditoria",props:{eventos:{type:Array,default:()=>[]}},setup(e){const t=le(()=>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)=>(v(),b("div",null,[o[0]||(o[0]=r("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)),r("div",vf,[e.eventos.length===0?(v(),de(qe,{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."})):V("",!0),(v(!0),b(Z,null,ce(e.eventos,a=>(v(),b("details",{key:a.ID,class:"p-3"},[r("summary",hf,[r("span",{class:ie(["px-1.5 py-0.5 rounded text-xs shrink-0",t.value(a.nivel)])},S(a.nivel),3),r("span",gf,S(a.origen),1),r("span",bf,S(a.mensaje),1),r("span",xf,S(n(a.CreatedAt)),1)]),a.detalle?(v(),b("pre",yf,S(a.detalle),1)):V("",!0)]))),128))])]))}},wf={class:"space-y-6"},kf={key:0,class:"text-sm text-red-600 dark:text-red-400"},$f={key:1,class:"label"},Cf={class:"card divide-y divide-borde"},Af={class:"min-w-0"},Sf={class:"font-medium text-texto"},Ef={class:"text-xs text-tenue mt-0.5"},If={key:0,class:"text-xs text-tenue mt-1"},Rf=["onClick"],Pf={class:"card divide-y divide-borde"},Df={class:"min-w-0"},Tf={class:"flex items-center gap-2 flex-wrap"},Of={class:"font-medium text-texto"},Mf={key:0,class:"px-1.5 py-0.5 rounded text-xs badge-neutro"},Nf={key:1,class:"px-1.5 py-0.5 rounded text-xs bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300"},jf={class:"text-xs text-tenue mt-0.5"},Vf={key:0,class:"text-xs text-red-600 dark:text-red-400 mt-1"},Uf=["onClick"],Lf={__name:"TabAcciones",props:{agenteId:{type:Number,required:!0}},setup(e){const t=e,n=j([]),s=j([]),o=j(!0),a=j("");async function l(){o.value=!0,a.value="";try{const f=await Q.get(K(`/umind/avisos?agente_id=${t.agenteId}`));n.value=(f.items||[]).filter(_=>_.estado==="pendiente")}catch(f){a.value=f.message}try{const f=await Q.get(K(`/umind/vigilancias?agente_id=${t.agenteId}`));s.value=f.items||[]}catch{s.value=[]}o.value=!1}Ge(()=>t.agenteId,l,{immediate:!0});async function i(f){confirm(`¿Cancelar el recordatorio "${f.titulo}"?`)&&(await Q.del(K(`/umind/avisos/${f.ID}`)),await l())}async function u(f){confirm(`¿Apagar la vigilancia "${f.nombre}"?`)&&(await Q.del(K(`/umind/vigilancias/${f.ID}`)),await l())}const d={diario:"todos los días",semanal:"cada semana",mensual:"cada mes",anual:"cada año"};function c(f){return new Date(f).toLocaleString("es",{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})}function p(f){return!f||f.startsWith("panel:")?"te llega por correo":f.startsWith("tg:")?"te llega por Telegram":f.startsWith("mail:")?`te llega a ${f.slice(5)}`:"te llega por correo"}return(f,_)=>(v(),b("div",wf,[a.value?(v(),b("p",kf,S(a.value),1)):V("",!0),o.value?(v(),b("p",$f,"Cargando…")):(v(),b(Z,{key:2},[r("section",null,[_[0]||(_[0]=r("h3",{class:"text-sm font-medium text-texto mb-1"},"Recordatorios",-1)),_[1]||(_[1]=r("p",{class:"label mb-3"},[Y(" Pediselos hablando: "),r("em",null,"«avisame el 15 de marzo que vence la póliza de Acme, y todos los años»"),Y(". ")],-1)),r("div",Cf,[n.value.length===0?(v(),de(qe,{key:0,titulo:"Sin recordatorios",detalle:"Escribile desde tu canal privado y programá el primero. Te avisa por donde se lo pediste."})):V("",!0),(v(!0),b(Z,null,ce(n.value,k=>(v(),b("div",{key:k.ID,class:"p-4 flex items-center justify-between gap-4"},[r("div",Af,[r("span",Sf,S(k.titulo),1),r("p",Ef,[Y(S(c(k.proximo_at))+" ",1),k.repetir?(v(),b(Z,{key:0},[Y(" · se repite "+S(d[k.repetir]||k.repetir),1)],64)):V("",!0),Y(" · "+S(p(k.destino)),1)]),k.detalle?(v(),b("p",If,S(k.detalle),1)):V("",!0)]),r("button",{class:"text-sm text-red-500 hover:text-red-700 shrink-0",onClick:A=>i(k)},"Cancelar",8,Rf)]))),128))])]),r("section",null,[_[2]||(_[2]=r("h3",{class:"text-sm font-medium text-texto mb-1"},"Vigilancias",-1)),_[3]||(_[3]=r("p",{class:"label mb-3"}," Consultan una de tus herramientas cada tanto y te avisan cuando pasa algo. Solo avisan al entrar en la condición, no cada vez que la revisan. ",-1)),r("div",Pf,[s.value.length===0?(v(),de(qe,{key:0,titulo:"Sin vigilancias",detalle:"Si tenés una herramienta conectada, pedile algo como «avisame cuando esta API devuelva stock en cero»."})):V("",!0),(v(!0),b(Z,null,ce(s.value,k=>(v(),b("div",{key:k.ID,class:"p-4 flex items-center justify-between gap-4"},[r("div",Df,[r("div",Tf,[r("span",Of,S(k.nombre),1),k.activa?k.en_condicion?(v(),b("span",Nf,"se está cumpliendo")):V("",!0):(v(),b("span",Mf,"apagada"))]),r("p",jf,S(k.condicion)+" · revisa cada "+S(k.intervalo_min)+" min · usa "+S(k.herramienta),1),k.ultimo_error?(v(),b("p",Vf,S(k.ultimo_error),1)):V("",!0)]),r("button",{class:"text-sm text-red-500 hover:text-red-700 shrink-0",onClick:A=>u(k)},"Apagar",8,Uf)]))),128))])])],64))]))}},qf={class:"flex flex-wrap gap-2 mb-4"},Ff={class:"grid sm:grid-cols-2 gap-3"},Hf={key:0,class:"grid sm:grid-cols-3 gap-3"},Bf={key:1,class:"text-sm text-red-600 dark:text-red-400"},Wf={class:"flex items-center justify-between"},Gf=["disabled"],zf={class:"card divide-y divide-borde"},Kf={class:"flex items-center justify-between gap-3"},Qf={class:"min-w-0"},Jf={class:"font-medium text-texto"},Yf={class:"ml-2 text-xs text-tenue"},Zf={class:"flex items-center gap-3 shrink-0 text-sm"},Xf=["disabled","onClick"],ep=["onClick"],tp={__name:"TabConexiones",props:{agenteId:{type:Number,required:!0},conexiones:{type:Array,default:()=>[]}},emits:["recargar"],setup(e,{emit:t}){const n=e,s=t,o=j(!1),a=j(!1),l=j(""),i=j(!1),u=j({email:"",password:"",host:"",puerto:993,encriptado:"ssl"}),d=j(null),c=j({});function p(I){return{google:"Google",microsoft:"Outlook",imap:"Casilla propia"}[I]||I}function f(I){window.location.href=K(`/umind/conexiones/conectar?agente_id=${n.agenteId}&proveedor=${I}`)}async function _(){a.value=!0,l.value="";try{await Q.post(K("/umind/conexiones/imap"),{agente_id:n.agenteId,email:u.value.email,password:u.value.password,host:i.value?u.value.host:"",puerto:i.value?Number(u.value.puerto):0,encriptado:u.value.encriptado}),o.value=!1,u.value={email:"",password:"",host:"",puerto:993,encriptado:"ssl"},i.value=!1,s("recargar")}catch(I){l.value=I.message,!i.value&&/conexión|conectar|resolver/i.test(I.message)&&(i.value=!0)}finally{a.value=!1}}async function k(I){d.value=I.ID,c.value={...c.value,[I.ID]:null};try{const y=await Q.post(K(`/umind/conexiones/${I.ID}/probar`),{});c.value={...c.value,[I.ID]:{ok:!0,texto:y.message}}}catch(y){c.value={...c.value,[I.ID]:{ok:!1,texto:y.message}}}finally{d.value=null}}async function A(I){confirm(`¿Desconectar la cuenta ${I.email||I.proveedor}?`)&&(await Q.del(K(`/umind/conexiones/${I.ID}`)),s("recargar"))}return(I,y)=>(v(),b("div",null,[y[15]||(y[15]=r("p",{class:"label mb-4"},[Y(" Las casillas que el agente puede consultar cuando se lo pedís — por ejemplo: "),r("em",null,"«revisame los correos de hoy y haceme un resumen»"),Y(". Solo lectura: nunca marca nada como leído ni manda nada. Podés conectar varias. ")],-1)),r("div",qf,[r("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:y[0]||(y[0]=w=>f("google"))}," Conectar Google "),r("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:y[1]||(y[1]=w=>f("microsoft"))}," Conectar Outlook "),r("button",{class:"btn-primary",onClick:y[2]||(y[2]=w=>o.value=!o.value)}," + Casilla propia ")]),o.value?(v(),b("form",{key:0,class:"card p-4 mb-4 space-y-3",onSubmit:Ae(_,["prevent"])},[r("div",Ff,[r("div",null,[y[8]||(y[8]=r("label",{class:"label"},"Correo",-1)),z(r("input",{"onUpdate:modelValue":y[3]||(y[3]=w=>u.value.email=w),type:"email",required:"",placeholder:"ventas@tunegocio.com",class:"input"},null,512),[[re,u.value.email]])]),r("div",null,[y[9]||(y[9]=r("label",{class:"label"},"Contraseña",-1)),z(r("input",{"onUpdate:modelValue":y[4]||(y[4]=w=>u.value.password=w),type:"password",autocomplete:"new-password",required:"",class:"input"},null,512),[[re,u.value.password]])])]),i.value?(v(),b("div",Hf,[r("div",null,[y[10]||(y[10]=r("label",{class:"label"},"Servidor IMAP",-1)),z(r("input",{"onUpdate:modelValue":y[5]||(y[5]=w=>u.value.host=w),placeholder:"mail.tunegocio.com",class:"input font-mono"},null,512),[[re,u.value.host]])]),r("div",null,[y[11]||(y[11]=r("label",{class:"label"},"Puerto",-1)),z(r("input",{"onUpdate:modelValue":y[6]||(y[6]=w=>u.value.puerto=w),type:"number",class:"input"},null,512),[[re,u.value.puerto]])]),r("div",null,[y[13]||(y[13]=r("label",{class:"label"},"Encriptación",-1)),z(r("select",{"onUpdate:modelValue":y[7]||(y[7]=w=>u.value.encriptado=w),class:"input"},[...y[12]||(y[12]=[r("option",{value:"ssl"},"SSL (993)",-1),r("option",{value:"starttls"},"STARTTLS (143)",-1)])],512),[[Nt,u.value.encriptado]])])])):V("",!0),l.value?(v(),b("p",Bf,S(l.value),1)):V("",!0),r("div",Wf,[y[14]||(y[14]=r("p",{class:"text-xs text-tenue"}," Se prueba la conexión antes de guardar. Gmail y Outlook van por sus botones de arriba. ",-1)),r("button",{type:"submit",class:"btn-primary",disabled:a.value},S(a.value?"Probando…":"Conectar"),9,Gf)])],32)):V("",!0),r("div",zf,[e.conexiones.length===0?(v(),de(qe,{key:0,titulo:"Sin cuentas conectadas",detalle:"Conectá una casilla y vas a poder pedirle al agente que te revise el correo y te lo resuma, sin abrir el webmail."})):V("",!0),(v(!0),b(Z,null,ce(e.conexiones,w=>(v(),b("div",{key:w.ID,class:"p-4"},[r("div",Kf,[r("div",Qf,[r("span",Jf,S(w.email),1),r("span",Yf,S(p(w.proveedor)),1),r("span",{class:ie(["ml-2 px-1.5 py-0.5 rounded text-xs",w.activo?"badge-ok":"badge-neutro"])},S(w.activo?"activa":"inactiva"),3),c.value[w.ID]?(v(),b("p",{key:0,class:ie(["text-xs mt-1",c.value[w.ID].ok?"text-brand":"text-red-600 dark:text-red-400"])},S(c.value[w.ID].texto),3)):V("",!0)]),r("div",Zf,[w.proveedor==="imap"?(v(),b("button",{key:0,class:"text-brand hover:underline disabled:opacity-40",disabled:d.value===w.ID,onClick:g=>k(w)},S(d.value===w.ID?"Probando…":"Probar"),9,Xf)):V("",!0),r("button",{class:"text-red-500 hover:text-red-700",onClick:g=>A(w)},"Desconectar",8,ep)])])]))),128))])]))}},np={class:"card p-4 flex flex-col h-[28rem]"},sp={class:"flex-1 overflow-y-auto space-y-2 mb-3"},op={key:0,class:"text-sm text-tenue"},ap={key:1,class:"flex items-center gap-2"},rp=["disabled"],_a={__name:"TabChat",props:{agenteId:{type:Number,required:!0}},setup(e){const t=e,n=`staff-preview-${Math.random().toString(36).slice(2)}`,s=j([]),o=j(""),a=j(!1);async function l(){const i=o.value.trim();if(!(!i||a.value)){o.value="",s.value.push({role:"user",content:i}),a.value=!0;try{const u=await Q.post(K("/umind/chat"),{agente_id:t.agenteId,session_id:n,mensaje:i});s.value.push({role:"assistant",content:u.respuesta})}catch(u){s.value.push({role:"assistant",content:`⚠ ${u.message}`})}finally{a.value=!1}}}return(i,u)=>(v(),b("div",np,[r("div",sp,[s.value.length===0?(v(),b("p",op," 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. ")):V("",!0),(v(!0),b(Z,null,ce(s.value,(d,c)=>(v(),b("div",{key:c,class:ie(["max-w-[80%] px-3 py-2 rounded-lg text-sm whitespace-pre-wrap",d.role==="user"?"bg-brand text-white ml-auto":"bg-elevado text-texto"])},S(d.content),3))),128)),a.value?(v(),b("div",ap,[ne(Vn,{estado:"pensando",tam:30,class:"text-brand"}),u[1]||(u[1]=r("span",{class:"text-xs text-tenue"},"Pensando…",-1))])):V("",!0)]),r("form",{class:"flex gap-2",onSubmit:Ae(l,["prevent"])},[z(r("input",{"onUpdate:modelValue":u[0]||(u[0]=d=>o.value=d),placeholder:"Escribí un mensaje de prueba...",class:"flex-1 input"},null,512),[[re,o.value]]),r("button",{type:"submit",disabled:a.value,class:"btn-primary disabled:opacity-50 transition-colors"}," Enviar ",8,rp)],32)]))}},lp={class:"grid lg:grid-cols-[minmax(16rem,22rem)_1fr] gap-4 items-start"},ip={class:"card divide-y divide-borde max-h-[30rem] overflow-y-auto"},up=["onClick"],cp={class:"text-sm text-texto line-clamp-2"},dp={class:"flex items-center gap-2 mt-1.5 text-xs text-tenue"},fp={class:"tabular-nums"},pp={class:"ml-auto tabular-nums"},mp={key:2,class:"flex items-center gap-2 p-3 text-xs text-tenue cursor-pointer select-none"},vp={class:"card p-4 max-h-[30rem] overflow-y-auto"},hp={key:1,class:"text-sm text-tenue"},gp={key:2,class:"space-y-2"},bp={__name:"TabConversaciones",props:{agenteId:{type:Number,required:!0},sesiones:{type:Array,default:()=>[]}},setup(e){const t=e,n=j([]),s=j(null),o=j(!1);function a(f){const _=String(f||"");return _.startsWith("wa:")?{nombre:"WhatsApp",icono:"mensaje",clase:"badge-ok"}:_.startsWith("tg:")?{nombre:"Telegram",icono:"mensaje",clase:"badge-neutro"}:_.startsWith("staff-preview")?{nombre:"Prueba",icono:"escribir",clase:"badge-alerta"}:{nombre:"Tu web",icono:"sitio",clase:"badge-neutro"}}const l=j(!1),i=le(()=>t.sesiones.filter(f=>!String(f.session_id).startsWith("staff-preview"))),u=le(()=>t.sesiones.filter(f=>String(f.session_id).startsWith("staff-preview"))),d=le(()=>l.value?t.sesiones:i.value);function c(f){if(!f)return"";const _=new Date(f),A=Math.floor((new Date().setHours(0,0,0,0)-new Date(_).setHours(0,0,0,0))/864e5),I=new Date(f).toLocaleTimeString("es",{hour:"2-digit",minute:"2-digit"});return A<=0?`hoy ${I}`:A===1?`ayer ${I}`:A<7?`hace ${A} días`:new Date(f).toLocaleDateString("es",{day:"numeric",month:"short"})}async function p(f){s.value=f,o.value=!0;try{const _=await Q.get(K(`/umind/historial?agente_id=${t.agenteId}&session_id=${f}`));n.value=_.items||[]}finally{o.value=!1}}return(f,_)=>(v(),b("div",lp,[r("div",ip,[d.value.length===0&&u.value.length===0?(v(),de(qe,{key:0,titulo:"Nadie escribió todavía",detalle:"Cuando alguien le hable a tu asistente —por WhatsApp, Telegram o tu web— la conversación aparece acá, con lo que preguntó y lo que se le respondió."})):d.value.length===0?(v(),de(qe,{key:1,estado:"durmiendo",titulo:"Ningún cliente escribió todavía",detalle:`Hay ${u.value.length} ${u.value.length===1?"conversación de prueba tuya":"conversaciones de prueba tuyas"} — activá el filtro de abajo para verlas.`},null,8,["detalle"])):V("",!0),(v(!0),b(Z,null,ce(d.value,k=>(v(),b("button",{key:k.session_id,class:ie(["w-full text-left p-3 hover:bg-elevado transition-colors",s.value===k.session_id?"bg-gray-50 dark:bg-gray-800":""]),onClick:A=>p(k.session_id)},[r("div",cp,S(k.primer_mensaje||"(sin mensaje)"),1),r("div",dp,[r("span",{class:ie(["px-1.5 py-0.5 rounded",a(k.session_id).clase])},S(a(k.session_id).nombre),3),r("span",fp,S(k.mensajes)+" msj",1),r("span",pp,S(c(k.ultimo)),1)])],10,up))),128)),u.value.length?(v(),b("label",mp,[z(r("input",{"onUpdate:modelValue":_[0]||(_[0]=k=>l.value=k),type:"checkbox",class:"rounded border-borde text-brand focus:ring-brand"},null,512),[[st,l.value]]),Y(" "+S(u.value.length===1?"Mostrar mi prueba":`Mostrar mis ${u.value.length} pruebas`),1)])):V("",!0)]),r("div",vp,[s.value?o.value?(v(),b("p",hp,"Cargando…")):(v(),b("div",gp,[(v(!0),b(Z,null,ce(n.value,k=>(v(),b("div",{key:k.ID,class:ie(k.role==="user"?"text-right":"")},[r("div",{class:ie(["inline-block max-w-[80%] px-3 py-2 rounded-lg text-sm text-left whitespace-pre-wrap",k.role==="user"?"bg-brand text-white":"bg-elevado text-texto"])},S(k.content),3),r("div",{class:ie(["text-[10px] text-tenue mt-0.5 tabular-nums",k.role==="user"?"pr-1":"pl-1"])},S(c(k.CreatedAt)),3)],2))),128))])):(v(),de(qe,{key:0,estado:"normal",titulo:"Elegí una conversación",detalle:"Vas a ver el intercambio completo: lo que escribió la persona y lo que contestó tu asistente. Si una respuesta no te gusta, corregí su información en «Lo que sabe»."}))])]))}},xp={class:"card divide-y divide-borde"},yp={class:"text-sm text-texto font-mono"},_p={class:"label mt-0.5"},wp={class:"text-xs text-tenue mt-0.5"},kp={key:0,class:"ml-1 text-green-600 dark:text-green-400"},$p={key:1,class:"ml-1 text-gray-400"},Cp={class:"flex gap-3 text-sm shrink-0"},Ap=["onClick"],Sp=["onClick"],Ep={class:"card p-6 w-full max-w-xl max-h-[85vh] overflow-y-auto"},Ip={class:"font-semibold text-texto mb-4"},Rp={class:"border border-borde rounded-lg p-3 space-y-2"},Pp=["onUpdate:modelValue"],Dp=["onUpdate:modelValue"],Tp=["onUpdate:modelValue"],Op={class:"label flex items-center gap-1"},Mp=["onUpdate:modelValue"],Np=["onClick"],jp={key:0,class:"text-xs text-gray-400"},Vp={class:"border border-borde rounded-lg p-3 space-y-2"},Up={class:"flex items-center gap-2 label"},Lp={class:"flex items-center gap-2 text-sm text-texto"},qp={class:"flex justify-end gap-2 pt-2"},Fp={__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=j(!1),a=j(null),l=j(i());function i(){return{nombre:"",descripcion:"",url:"",auth_header_nombre:"",auth_header_valor:"",tocarAuth:!1,parametros:[],activa:!0}}function u(){a.value=null,l.value=i(),o.value=!0}function d(k){a.value=k;let A=[];try{A=JSON.parse(k.parametros_json||"[]")||[]}catch{A=[]}l.value={nombre:k.nombre,descripcion:k.descripcion,url:k.url,auth_header_nombre:k.auth_header_nombre,auth_header_valor:"",tocarAuth:!1,parametros:A,activa:k.activa},o.value=!0}function c(){l.value.parametros.push({nombre:"",tipo:"string",descripcion:"",requerido:!1})}function p(k){l.value.parametros.splice(k,1)}async function f(){const k={agente_id:n.agenteId,nombre:l.value.nombre.trim(),descripcion:l.value.descripcion,url:l.value.url.trim(),auth_header_nombre:l.value.auth_header_nombre,parametros:l.value.parametros,activa:l.value.activa};l.value.tocarAuth&&(k.auth_header_valor=l.value.auth_header_valor);try{a.value?await Q.put(K(`/umind/tools/${a.value.ID}`),k):await Q.post(K("/umind/tools"),k),o.value=!1,s("recargar")}catch(A){s("error",A.message)}}async function _(k){confirm(`¿Eliminar la herramienta "${k.nombre}"?`)&&(await Q.del(K(`/umind/tools/${k.ID}`)),s("recargar"))}return(k,A)=>(v(),b("div",null,[r("div",{class:"flex justify-between items-center mb-4"},[A[9]||(A[9]=r("p",{class:"label"},"Máximo 10 herramientas activas por agente.",-1)),r("button",{class:"btn-primary",onClick:u}," + Nueva herramienta ")]),r("div",xp,[e.tools.length===0?(v(),de(qe,{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."})):V("",!0),(v(!0),b(Z,null,ce(e.tools,I=>(v(),b("div",{key:I.ID,class:"p-4 flex items-center justify-between"},[r("div",null,[r("div",yp,S(I.nombre),1),r("div",_p,S(I.descripcion),1),r("div",wp,[Y(S(I.url)+" ",1),I.auth_configurado?(v(),b("span",kp,"· auth configurada")):V("",!0),I.activa?V("",!0):(v(),b("span",$p,"· inactiva"))])]),r("div",Cp,[r("button",{class:"text-tenue hover:text-gray-800 dark:hover:text-gray-100",onClick:y=>d(I)},"Editar",8,Ap),r("button",{class:"text-red-500 hover:text-red-700",onClick:y=>_(I)},"Eliminar",8,Sp)])]))),128))]),o.value?(v(),b("div",{key:0,class:"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50",onClick:A[8]||(A[8]=Ae(I=>o.value=!1,["self"]))},[r("div",Ep,[r("h2",Ip,S(a.value?"Editar herramienta":"Nueva herramienta"),1),r("form",{class:"space-y-3",onSubmit:Ae(f,["prevent"])},[r("div",null,[A[10]||(A[10]=r("label",{class:"label"},"Nombre (identificador, ej: consultar_stock)",-1)),z(r("input",{"onUpdate:modelValue":A[0]||(A[0]=I=>l.value.nombre=I),required:"",pattern:"[a-z][a-z0-9_]{2,63}",class:"input font-mono"},null,512),[[re,l.value.nombre]])]),r("div",null,[A[11]||(A[11]=r("label",{class:"label"},"Descripción (esto lo lee el modelo para decidir cuándo usarla)",-1)),z(r("textarea",{"onUpdate:modelValue":A[1]||(A[1]=I=>l.value.descripcion=I),rows:"2",required:"",class:"input"},null,512),[[re,l.value.descripcion]])]),r("div",null,[A[12]||(A[12]=r("label",{class:"label"},"URL del webhook (https)",-1)),z(r("input",{"onUpdate:modelValue":A[2]||(A[2]=I=>l.value.url=I),type:"url",required:"",placeholder:"https://...",class:"input"},null,512),[[re,l.value.url]])]),r("div",Rp,[r("div",{class:"flex items-center justify-between"},[A[13]||(A[13]=r("label",{class:"label"},"Parámetros que completa el modelo",-1)),r("button",{type:"button",class:"text-xs text-brand",onClick:c},"+ agregar")]),(v(!0),b(Z,null,ce(l.value.parametros,(I,y)=>(v(),b("div",{key:y,class:"flex gap-2 items-center"},[z(r("input",{"onUpdate:modelValue":w=>I.nombre=w,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,Pp),[[re,I.nombre]]),z(r("select",{"onUpdate:modelValue":w=>I.tipo=w,class:"border border-borde bg-white dark:bg-gray-800 text-texto rounded px-2 py-1 text-xs"},[...A[14]||(A[14]=[r("option",{value:"string"},"string",-1),r("option",{value:"number"},"number",-1),r("option",{value:"boolean"},"boolean",-1)])],8,Dp),[[Nt,I.tipo]]),z(r("input",{"onUpdate:modelValue":w=>I.descripcion=w,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,Tp),[[re,I.descripcion]]),r("label",Op,[z(r("input",{"onUpdate:modelValue":w=>I.requerido=w,type:"checkbox"},null,8,Mp),[[st,I.requerido]]),A[15]||(A[15]=Y(" req. ",-1))]),r("button",{type:"button",class:"text-red-400 text-xs",onClick:w=>p(y)},[ne(Ne,{nombre:"cerrar",tam:13})],8,Np)]))),128)),l.value.parametros.length===0?(v(),b("p",jp,"Sin parámetros.")):V("",!0)]),r("div",Vp,[A[16]||(A[16]=r("label",{class:"label"},"Autenticación saliente (opcional)",-1)),z(r("input",{"onUpdate:modelValue":A[3]||(A[3]=I=>l.value.auth_header_nombre=I),placeholder:"Nombre del header, ej: Authorization",class:"input"},null,512),[[re,l.value.auth_header_nombre]]),r("label",Up,[z(r("input",{"onUpdate:modelValue":A[4]||(A[4]=I=>l.value.tocarAuth=I),type:"checkbox"},null,512),[[st,l.value.tocarAuth]]),Y(" "+S(a.value?"Cambiar el valor del secreto":"Configurar valor"),1)]),l.value.tocarAuth?z((v(),b("input",{key:0,"onUpdate:modelValue":A[5]||(A[5]=I=>l.value.auth_header_valor=I),type:"password",placeholder:"Valor del header (ej: Bearer xxxx)",class:"input"},null,512)),[[re,l.value.auth_header_valor]]):V("",!0)]),r("label",Lp,[z(r("input",{"onUpdate:modelValue":A[6]||(A[6]=I=>l.value.activa=I),type:"checkbox"},null,512),[[st,l.value.activa]]),A[17]||(A[17]=Y(" Activa ",-1))]),r("div",qp,[r("button",{type:"button",class:"btn-ghost",onClick:A[7]||(A[7]=I=>o.value=!1)},"Cancelar"),A[18]||(A[18]=r("button",{type:"submit",class:"btn-primary"},"Guardar",-1))])],32)])])):V("",!0)]))}},Hp={class:"card p-4 mb-4"},Bp={class:"flex items-center justify-between mb-2"},Wp={class:"bg-elevado border border-borde rounded-lg p-2.5 text-xs text-texto overflow-x-auto"},Gp={class:"card divide-y divide-borde"},zp={class:"flex items-center justify-between"},Kp={class:"font-medium text-texto capitalize"},Qp={key:0,class:"ml-2 px-1.5 py-0.5 rounded text-xs badge-neutro"},Jp={class:"flex gap-3 text-sm"},Yp=["onClick"],Zp=["onClick"],Xp={class:"flex gap-4 mt-2 text-xs"},em={class:"flex items-center gap-1.5 text-texto cursor-pointer"},tm=["checked","onChange"],nm={class:"flex items-center gap-1.5 text-texto cursor-pointer"},sm=["checked","onChange"],om={class:"flex items-center gap-1.5 text-texto cursor-pointer"},am=["checked","onChange"],rm={key:0,class:"label mt-1"},lm={key:1,class:"label mt-1 break-all"},im={class:"bg-elevado px-1 rounded"},um={key:2,class:"text-xs text-tenue mt-1"},cm={key:3,class:"text-xs text-red-600 dark:text-red-400 mt-1"},dm={class:"card p-6 w-full max-w-md"},fm={key:0},pm={class:"grid sm:grid-cols-2 gap-3"},mm={class:"flex flex-col gap-1.5 mt-1"},vm={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},hm={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},gm={class:"text-xs text-tenue"},bm={class:"grid sm:grid-cols-2 gap-3 mt-2"},xm={class:"rounded-lg border border-borde p-3 mt-1"},ym={class:"flex items-start gap-2 text-sm text-texto cursor-pointer"},_m={class:"flex flex-col gap-2 pt-1"},wm={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},km={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},$m={class:"flex items-center gap-2 text-sm text-texto cursor-pointer"},Cm={class:"flex justify-end gap-2 pt-2"},Am={__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=j(!1),a=j(d()),l=j(!1),i=le(()=>{const w=n.siteKey||"TU_SITE_KEY";return` +