t(a,u,void 0,o));else{const a=Object.keys(e);r=new Array(a.length);for(let u=0,p=a.length;ue?ii(e)?os(e):Os(e.parent):null,dn=xe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Os(e.parent),$root:e=>Os(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ho(e),$forceUpdate:e=>e.f||(e.f=()=>{Ys(e.update)}),$nextTick:e=>e.n||(e.n=Qs.bind(e.proxy)),$watch:e=>pl.bind(e)}),ps=(e,t)=>e!==re&&!e.__isScriptSetup&&Z(e,t),Pl={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:o,accessCache:i,type:a,appContext:u}=e;if(t[0]!=="$"){const g=i[t];if(g!==void 0)switch(g){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return o[t]}else{if(ps(s,t))return i[t]=1,s[t];if(r!==re&&Z(r,t))return i[t]=2,r[t];if(Z(o,t))return i[t]=3,o[t];if(n!==re&&Z(n,t))return i[t]=4,n[t];Ts&&(i[t]=0)}}const p=dn[t];let f,h;if(p)return t==="$attrs"&&Ee(e.attrs,"get",""),p(e);if((f=a.__cssModules)&&(f=f[t]))return f;if(n!==re&&Z(n,t))return i[t]=4,n[t];if(h=u.config.globalProperties,Z(h,t))return h[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:o}=e;return ps(r,t)?(r[t]=n,!0):s!==re&&Z(s,t)?(s[t]=n,!0):Z(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,props:o,type:i}},a){let u;return!!(n[a]||e!==re&&a[0]!=="$"&&Z(e,a)||ps(t,a)||Z(o,a)||Z(s,a)||Z(dn,a)||Z(r.config.globalProperties,a)||(u=i.__cssModules)&&u[a])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Z(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function mr(e){return K(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Ts=!0;function Il(e){const t=Ho(e),n=e.proxy,s=e.ctx;Ts=!1,t.beforeCreate&&vr(t.beforeCreate,e,"bc");const{data:r,computed:o,methods:i,watch:a,provide:u,inject:p,created:f,beforeMount:h,mounted:g,beforeUpdate:v,updated:S,activated:b,deactivated:$,beforeDestroy:R,beforeUnmount:N,destroyed:M,unmounted:D,render:q,renderTracked:oe,renderTriggered:L,errorCaptured:Ie,serverPrefetch:je,expose:Le,inheritAttrs:ze,components:at,directives:Ue,filters:Pt}=t;if(p&&Nl(p,s,null),i)for(const z in i){const H=i[z];W(H)&&(s[z]=H.bind(n))}if(r){const z=r.call(n,n);ee(z)&&(e.data=Xn(z))}if(Ts=!0,o)for(const z in o){const H=o[z],Fe=W(H)?H.bind(n,n):W(H.get)?H.get.bind(n,n):it,Ne=!W(H)&&W(H.set)?H.set.bind(n):it,He=De({get:Fe,set:Ne});Object.defineProperty(s,z,{enumerable:!0,configurable:!0,get:()=>He.value,set:we=>He.value=we})}if(a)for(const z in a)Fo(a[z],s,n,z);if(u){const z=W(u)?u.call(n):u;Reflect.ownKeys(z).forEach(H=>{In(H,z[H])})}f&&vr(f,e,"c");function ae(z,H){K(H)?H.forEach(Fe=>z(Fe.bind(n))):H&&z(H.bind(n))}if(ae(bl,h),ae(er,g),ae(_l,v),ae(xl,S),ae(ml,b),ae(vl,$),ae(Sl,Ie),ae(Al,oe),ae(Cl,L),ae(wl,N),ae(Uo,D),ae(El,je),K(Le))if(Le.length){const z=e.exposed||(e.exposed={});Le.forEach(H=>{Object.defineProperty(z,H,{get:()=>n[H],set:Fe=>n[H]=Fe,enumerable:!0})})}else e.exposed||(e.exposed={});q&&e.render===it&&(e.render=q),ze!=null&&(e.inheritAttrs=ze),at&&(e.components=at),Ue&&(e.directives=Ue),je&&jo(e)}function Nl(e,t,n=it){K(e)&&(e=Ps(e));for(const s in e){const r=e[s];let o;ee(r)?"default"in r?o=mt(r.from||s,r.default,!0):o=mt(r.from||s):o=mt(r),Ae(o)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>o.value,set:i=>o.value=i}):t[s]=o}}function vr(e,t,n){We(K(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Fo(e,t,n,s){let r=s.includes(".")?Do(n,s):()=>n[s];if(fe(e)){const o=t[e];W(o)&&Nn(r,o)}else if(W(e))Nn(r,e.bind(n));else if(ee(e))if(K(e))e.forEach(o=>Fo(o,t,n,s));else{const o=W(e.handler)?e.handler.bind(n):t[e.handler];W(o)&&Nn(r,o,e)}}function Ho(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,a=o.get(t);let u;return a?u=a:!r.length&&!n&&!s?u=t:(u={},r.length&&r.forEach(p=>Fn(u,p,i,!0)),Fn(u,t,i)),ee(t)&&o.set(t,u),u}function Fn(e,t,n,s=!1){const{mixins:r,extends:o}=t;o&&Fn(e,o,n,!0),r&&r.forEach(i=>Fn(e,i,n,!0));for(const i in t)if(!(s&&i==="expose")){const a=kl[i]||n&&n[i];e[i]=a?a(e[i],t[i]):t[i]}return e}const kl={data:yr,props:br,emits:br,methods:rn,computed:rn,beforeCreate:Se,created:Se,beforeMount:Se,mounted:Se,beforeUpdate:Se,updated:Se,beforeDestroy:Se,beforeUnmount:Se,destroyed:Se,unmounted:Se,activated:Se,deactivated:Se,errorCaptured:Se,serverPrefetch:Se,components:rn,directives:rn,watch:Ml,provide:yr,inject:Dl};function yr(e,t){return t?e?function(){return xe(W(e)?e.call(this,this):e,W(t)?t.call(this,this):t)}:t:e}function Dl(e,t){return rn(Ps(e),Ps(t))}function Ps(e){if(K(e)){const t={};for(let n=0;nt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Te(t)}Modifiers`]||e[`${Lt(t)}Modifiers`];function Ul(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||re;let r=n;const o=t.startsWith("update:"),i=o&&Ll(s,t.slice(7));i&&(i.trim&&(r=n.map(f=>fe(f)?f.trim():f)),i.number&&(r=n.map(Jn)));let a,u=s[a=ls(t)]||s[a=ls(Te(t))];!u&&o&&(u=s[a=ls(Lt(t))]),u&&We(u,e,6,r);const p=s[a+"Once"];if(p){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,We(p,e,6,r)}}const Fl=new WeakMap;function $o(e,t,n=!1){const s=n?Fl:t.emitsCache,r=s.get(e);if(r!==void 0)return r;const o=e.emits;let i={},a=!1;if(!W(e)){const u=p=>{const f=$o(p,t,!0);f&&(a=!0,xe(i,f))};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}return!o&&!a?(ee(e)&&s.set(e,null),null):(K(o)?o.forEach(u=>i[u]=null):xe(i,o),ee(e)&&s.set(e,i),i)}function ss(e,t){return!e||!Gn(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),Z(e,t[0].toLowerCase()+t.slice(1))||Z(e,Lt(t))||Z(e,t))}function _r(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[o],slots:i,attrs:a,emit:u,render:p,renderCache:f,props:h,data:g,setupState:v,ctx:S,inheritAttrs:b}=e,$=jn(e);let R,N;try{if(n.shapeFlag&4){const D=r||s,q=D;R=st(p.call(q,D,f,h,v,g,S)),N=a}else{const D=t;R=st(D.length>1?D(h,{attrs:a,slots:i,emit:u}):D(h,null)),N=t.props?a:Hl(a)}}catch(D){jt.length=0,Zn(D,e,1),R=_e(_t)}let M=R;if(N&&b!==!1){const D=Object.keys(N),{shapeFlag:q}=M;D.length&&q&7&&(o&&D.some(Wn)&&(N=Bl(N,o)),M=zt(M,N,!1,!0))}if(n.dirs&&(M=zt(M,null,!1,!0),M.dirs=M.dirs?M.dirs.concat(n.dirs):n.dirs),n.transition){const D=ts(M.type)&&Mo(M)||M;Xs(D,n.transition)}return R=M,jn($),R}const Hl=e=>{let t;for(const n in e)(n==="class"||n==="style"||Gn(n))&&((t||(t={}))[n]=e[n]);return t},Bl=(e,t)=>{const n={};for(const s in e)(!Wn(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function $l(e,t,n){const{props:s,children:r,component:o}=e,{props:i,children:a,patchFlag:u}=t,p=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&u>=0){if(u&1024)return!0;if(u&16)return s?xr(s,i,p):!!i;if(u&8){const f=t.dynamicProps;for(let h=0;hObject.create(Go),qo=e=>Object.getPrototypeOf(e)===Go;function Gl(e,t,n,s=!1){const r={},o=Wo();e.propsDefaults=Object.create(null),zo(e,t,r,o);for(const i in e.propsOptions[0])i in r||(r[i]=void 0);n?e.props=s?r:Ao(r):e.type.props?e.props=r:e.props=o,e.attrs=o}function Wl(e,t,n,s){const{props:r,attrs:o,vnode:{patchFlag:i}}=e,a=X(r),[u]=e.propsOptions;let p=!1;if((s||i>0)&&!(i&16)){if(i&8){const f=e.vnode.dynamicProps;for(let h=0;h{u=!0;const[g,v]=Jo(h,t,!0);xe(i,g),v&&a.push(...v)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!o&&!u)return ee(e)&&s.set(e,Bt),Bt;if(K(o))for(let f=0;fe==="_"||e==="_ctx"||e==="$stable",nr=e=>K(e)?e.map(st):[st(e)],zl=(e,t,n)=>{if(t._n)return t;const s=es((...r)=>nr(t(...r)),n);return s._c=!1,s},Qo=(e,t,n)=>{const s=e._ctx;for(const r in e){if(tr(r))continue;const o=e[r];if(W(o))t[r]=zl(r,o,s);else if(o!=null){const i=nr(o);t[r]=()=>i}}},Yo=(e,t)=>{const n=nr(t);e.slots.default=()=>n},Xo=(e,t,n)=>{for(const s in t)(n||!tr(s))&&(e[s]=t[s])},Jl=(e,t,n)=>{const s=e.slots=Wo();if(e.vnode.shapeFlag&32){const r=t._;r?(Xo(s,t,n),n&&io(s,"_",r,!0)):Qo(t,s)}else t&&Yo(e,t)},Ql=(e,t,n)=>{const{vnode:s,slots:r}=e;let o=!0,i=re;if(s.shapeFlag&32){const a=t._;a?n&&a===1?o=!1:Xo(r,t,n):(o=!t.$stable,Qo(t,r)),i=t}else t&&(Yo(e,t),i={default:1});if(o)for(const a in r)!tr(a)&&i[a]==null&&delete r[a]},Pe=ta;function Yl(e){return Xl(e)}function Xl(e,t){const n=Qn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:o,createElement:i,createText:a,createComment:u,setText:p,setElementText:f,parentNode:h,nextSibling:g,setScopeId:v=it,insertStaticContent:S}=e,b=(l,d,c,y=null,w=null,_=null,T=void 0,O=null,A=!!d.dynamicChildren)=>{if(l===d)return;l&&!nn(l,d)&&(y=x(l),we(l,w,_,!0),l=null),d.patchFlag===-2&&(A=!1,d.dynamicChildren=null);const{type:E,ref:B,shapeFlag:k}=d;switch(E){case rs:$(l,d,c,y);break;case _t:R(l,d,c,y);break;case gs:l==null&&N(d,c,y,T);break;case he:at(l,d,c,y,w,_,T,O,A);break;default:k&1?q(l,d,c,y,w,_,T,O,A):k&6?Ue(l,d,c,y,w,_,T,O,A):(k&64||k&128)&&E.process(l,d,c,y,w,_,T,O,A,V)}B!=null&&w?cn(B,l&&l.ref,_,d||l,!d):B==null&&l&&l.ref!=null&&cn(l.ref,null,_,l,!0)},$=(l,d,c,y)=>{if(l==null)s(d.el=a(d.children),c,y);else{const w=d.el=l.el;d.children!==l.children&&p(w,d.children)}},R=(l,d,c,y)=>{l==null?s(d.el=u(d.children||""),c,y):d.el=l.el},N=(l,d,c,y)=>{[l.el,l.anchor]=S(l.children,d,c,y,l.el,l.anchor)},M=({el:l,anchor:d},c,y)=>{let w;for(;l&&l!==d;)w=g(l),s(l,c,y),l=w;s(d,c,y)},D=({el:l,anchor:d})=>{let c;for(;l&&l!==d;)c=g(l),r(l),l=c;r(d)},q=(l,d,c,y,w,_,T,O,A)=>{if(d.type==="svg"?T="svg":d.type==="math"&&(T="mathml"),l==null)oe(d,c,y,w,_,T,O,A);else{const E=l.el&&l.el._isVueCE?l.el:null;try{E&&E._beginPatch(),je(l,d,w,_,T,O,A)}finally{E&&E._endPatch()}}},oe=(l,d,c,y,w,_,T,O)=>{let A,E;const{props:B,shapeFlag:k,transition:U,dirs:G}=l;if(A=l.el=i(l.type,_,B&&B.is,B),k&8?f(A,l.children):k&16&&Ie(l.children,A,null,y,w,hs(l,_),T,O),G&&It(l,null,y,"created"),L(A,l,l.scopeId,T,y),B){for(const se in B)se!=="value"&&!ln(se)&&o(A,se,null,B[se],_,y);"value"in B&&o(A,"value",null,B.value,_),(E=B.onVnodeBeforeMount)&&Xe(E,y,l)}G&&It(l,null,y,"beforeMount");const J=Zl(w,U);J&&U.beforeEnter(A),s(A,d,c),((E=B&&B.onVnodeMounted)||J||G)&&Pe(()=>{try{E&&Xe(E,y,l),J&&U.enter(A),G&&It(l,null,y,"mounted")}finally{}},w)},L=(l,d,c,y,w)=>{if(c&&v(l,c),y)for(let _=0;_{for(let E=A;E{const O=d.el=l.el;let{patchFlag:A,dynamicChildren:E,dirs:B}=d;A|=l.patchFlag&16;const k=l.props||re,U=d.props||re;let G;if(c&&Nt(c,!1),(G=U.onVnodeBeforeUpdate)&&Xe(G,c,d,l),B&&It(d,l,c,"beforeUpdate"),c&&Nt(c,!0),E&&(!l.dynamicChildren||l.dynamicChildren.length!==E.length)&&(A=0,T=!1,E=null),(k.innerHTML&&U.innerHTML==null||k.textContent&&U.textContent==null)&&f(O,""),E?Le(l.dynamicChildren,E,O,c,y,hs(d,w),_):T||H(l,d,O,null,c,y,hs(d,w),_,!1),A>0){if(A&16)ze(O,k,U,c,w);else if(A&2&&k.class!==U.class&&o(O,"class",null,U.class,w),A&4&&o(O,"style",k.style,U.style,w),A&8){const J=d.dynamicProps;for(let se=0;se{G&&Xe(G,c,d,l),B&&It(d,l,c,"updated")},y)},Le=(l,d,c,y,w,_,T)=>{for(let O=0;O{if(d!==c){if(d!==re)for(const _ in d)!ln(_)&&!(_ in c)&&o(l,_,d[_],null,w,y);for(const _ in c){if(ln(_))continue;const T=c[_],O=d[_];T!==O&&_!=="value"&&o(l,_,O,T,w,y)}"value"in c&&o(l,"value",d.value,c.value,w)}},at=(l,d,c,y,w,_,T,O,A)=>{const E=d.el=l?l.el:a(""),B=d.anchor=l?l.anchor:a("");let{patchFlag:k,dynamicChildren:U,slotScopeIds:G}=d;G&&(O=O?O.concat(G):G),l==null?(s(E,c,y),s(B,c,y),Ie(d.children||[],c,B,w,_,T,O,A)):k>0&&k&64&&U&&l.dynamicChildren&&l.dynamicChildren.length===U.length?(Le(l.dynamicChildren,U,c,w,_,T,O),(d.key!=null||w&&d===w.subTree)&&Zo(l,d,!0)):H(l,d,c,B,w,_,T,O,A)},Ue=(l,d,c,y,w,_,T,O,A)=>{d.slotScopeIds=O,l==null?d.shapeFlag&512?w.ctx.activate(d,c,y,T,A):Pt(d,c,y,w,_,T,A):wt(l,d,A)},Pt=(l,d,c,y,w,_,T)=>{const O=l.component=aa(l,y,w);if(Zs(l)&&(O.ctx.renderer=V),ca(O,!1,T),O.asyncDep){if(w&&w.registerDep(O,ae,T),!l.el){const A=O.subTree=_e(_t);R(null,A,d,c),l.placeholder=A.el}}else ae(O,l,d,c,w,_,T)},wt=(l,d,c)=>{const y=d.component=l.component;if($l(l,d,c))if(y.asyncDep&&!y.asyncResolved){z(y,d,c);return}else y.next=d,y.update();else d.el=l.el,y.vnode=d},ae=(l,d,c,y,w,_,T)=>{const O=()=>{if(l.isMounted){let{next:k,bu:U,u:G,parent:J,vnode:se}=l;{const Qe=ei(l);if(Qe){k&&(k.el=se.el,z(l,k,T)),Qe.asyncDep.then(()=>{Pe(()=>{l.isUnmounted||E()},w)});return}}let te=k,de;Nt(l,!1),k?(k.el=se.el,z(l,k,T)):k=se,U&&Pn(U),(de=k.props&&k.props.onVnodeBeforeUpdate)&&Xe(de,J,k,se),Nt(l,!0);const ye=_r(l),Je=l.subTree;l.subTree=ye,b(Je,ye,h(Je.el),x(Je),l,w,_),k.el=ye.el,te===null&&Kl(l,ye.el),G&&Pe(G,w),(de=k.props&&k.props.onVnodeUpdated)&&Pe(()=>Xe(de,J,k,se),w)}else{let k;const{el:U,props:G}=d,{bm:J,m:se,parent:te,root:de,type:ye}=l,Je=fn(d);Nt(l,!1),J&&Pn(J),!Je&&(k=G&&G.onVnodeBeforeMount)&&Xe(k,te,d),Nt(l,!0);{de.ce&&de.ce._hasShadowRoot()&&de.ce._injectChildStyle(ye,l.parent?l.parent.type:void 0);const Qe=l.subTree=_r(l);b(null,Qe,c,y,l,w,_),d.el=Qe.el}if(se&&Pe(se,w),!Je&&(k=G&&G.onVnodeMounted)){const Qe=d;Pe(()=>Xe(k,te,Qe),w)}(d.shapeFlag&256||te&&fn(te.vnode)&&te.vnode.shapeFlag&256)&&l.a&&Pe(l.a,w),l.isMounted=!0,d=c=y=null}};l.scope.on();const A=l.effect=new co(O);l.scope.off();const E=l.update=A.run.bind(A),B=l.job=A.runIfDirty.bind(A);B.i=l,B.id=l.uid,A.scheduler=()=>Ys(B),Nt(l,!0),E()},z=(l,d,c)=>{d.component=l;const y=l.vnode.props;l.vnode=d,l.next=null,Wl(l,d.props,y,c),Ql(l,d.children,c),vt(),dr(l),yt()},H=(l,d,c,y,w,_,T,O,A=!1)=>{const E=l&&l.children,B=l?l.shapeFlag:0,k=d.children,{patchFlag:U,shapeFlag:G}=d;if(U>0){if(U&128){Ne(E,k,c,y,w,_,T,O,A);return}else if(U&256){Fe(E,k,c,y,w,_,T,O,A);return}}G&8?(B&16&&ve(E,w,_),k!==E&&f(c,k)):B&16?G&16?Ne(E,k,c,y,w,_,T,O,A):ve(E,w,_,!0):(B&8&&f(c,""),G&16&&Ie(k,c,y,w,_,T,O,A))},Fe=(l,d,c,y,w,_,T,O,A)=>{l=l||Bt,d=d||Bt;const E=l.length,B=d.length,k=Math.min(E,B);let U;for(U=0;UB?ve(l,w,_,!0,!1,k):Ie(d,c,y,w,_,T,O,A,k)},Ne=(l,d,c,y,w,_,T,O,A)=>{let E=0;const B=d.length;let k=l.length-1,U=B-1;for(;E<=k&&E<=U;){const G=l[E],J=d[E]=A?pt(d[E]):st(d[E]);if(nn(G,J))b(G,J,c,null,w,_,T,O,A);else break;E++}for(;E<=k&&E<=U;){const G=l[k],J=d[U]=A?pt(d[U]):st(d[U]);if(nn(G,J))b(G,J,c,null,w,_,T,O,A);else break;k--,U--}if(E>k){if(E<=U){const G=U+1,J=GU)for(;E<=k;)we(l[E],w,_,!0),E++;else{const G=E,J=E,se=new Map;for(E=J;E<=U;E++){const ke=d[E]=A?pt(d[E]):st(d[E]);ke.key!=null&&se.set(ke.key,E)}let te,de=0;const ye=U-J+1;let Je=!1,Qe=0;const en=new Array(ye);for(E=0;E=ye){we(ke,w,_,!0);continue}let Ye;if(ke.key!=null)Ye=se.get(ke.key);else for(te=J;te<=U;te++)if(en[te-J]===0&&nn(ke,d[te])){Ye=te;break}Ye===void 0?we(ke,w,_,!0):(en[Ye-J]=E+1,Ye>=Qe?Qe=Ye:Je=!0,b(ke,d[Ye],c,null,w,_,T,O,A),de++)}const or=Je?ea(en):Bt;for(te=or.length-1,E=ye-1;E>=0;E--){const ke=J+E,Ye=d[ke],ir=d[ke+1],lr=ke+1{const{el:_,type:T,transition:O,children:A,shapeFlag:E}=l;if(E&6){He(l.component.subTree,d,c,y);return}if(E&128){l.suspense.move(d,c,y);return}if(E&64){T.move(l,d,c,V);return}if(T===he){s(_,d,c);for(let k=0;kO.enter(_),w));else{const{leave:k,delayLeave:U,afterLeave:G}=O,J=()=>{l.ctx.isUnmounted?r(_):s(_,d,c)},se=()=>{const te=_._isLeaving||!!_[ds];_._isLeaving&&_[ds](!0),O.persisted&&!te?J():k(_,()=>{J(),G&&G()})};U?U(_,J,se):se()}else s(_,d,c)},we=(l,d,c,y=!1,w=!1)=>{const{type:_,props:T,ref:O,children:A,dynamicChildren:E,shapeFlag:B,patchFlag:k,dirs:U,cacheIndex:G,memo:J}=l;if(k===-2&&(w=!1),O!=null&&(vt(),cn(O,null,c,l,!0),yt()),G!=null&&(d.renderCache[G]=void 0),B&256){d.ctx.deactivate(l);return}const se=B&1&&U,te=!fn(l);let de;if(te&&(de=T&&T.onVnodeBeforeUnmount)&&Xe(de,d,l),B&6)ut(l.component,c,y);else{if(B&128){l.suspense.unmount(c,y);return}se&&It(l,null,d,"beforeUnmount"),B&64?l.type.remove(l,d,c,V,y):E&&!E.hasOnce&&(_!==he||k>0&&k&64)?ve(E,d,c,!1,!0):(_===he&&k&384||!w&&B&16)&&ve(A,d,c),y&&Et(l)}const ye=J!=null&&G==null;(te&&(de=T&&T.onVnodeUnmounted)||se||ye)&&Pe(()=>{de&&Xe(de,d,l),se&&It(l,null,d,"unmounted"),ye&&(l.el=null)},c)},Et=l=>{const{type:d,el:c,anchor:y,transition:w}=l;if(d===he){Ct(c,y);return}if(d===gs){D(l);return}const _=()=>{r(c),w&&!w.persisted&&w.afterLeave&&w.afterLeave()};if(l.shapeFlag&1&&w&&!w.persisted){const{leave:T,delayLeave:O}=w,A=()=>T(c,_);O?O(l.el,_,A):A()}else _()},Ct=(l,d)=>{let c;for(;l!==d;)c=g(l),r(l),l=c;r(d)},ut=(l,d,c)=>{const{bum:y,scope:w,job:_,subTree:T,um:O,m:A,a:E}=l;Er(A),Er(E),y&&Pn(y),w.stop(),_&&(_.flags|=8,we(T,l,d,c)),O&&Pe(O,d),Pe(()=>{l.isUnmounted=!0},d)},ve=(l,d,c,y=!1,w=!1,_=0)=>{for(let T=_;T{if(l.shapeFlag&6)return x(l.component.subTree);if(l.shapeFlag&128)return l.suspense.next();const d=g(l.anchor||l.el),c=d&&d[hl];return c?g(c):d};let I=!1;const P=(l,d,c)=>{let y;l==null?d._vnode&&(we(d._vnode,null,null,!0),y=d._vnode.component):b(d._vnode||null,l,d,null,null,null,c),d._vnode=l,I||(I=!0,dr(y),Po(),I=!1)},V={p:b,um:we,m:He,r:Et,mt:Pt,mc:Ie,pc:H,pbc:Le,n:x,o:e};return{render:P,hydrate:void 0,createApp:jl(P)}}function hs({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Nt({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Zl(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Zo(e,t,n=!1){const s=e.children,r=t.children;if(K(s)&&K(r))for(let o=0;o>1,e[n[a]]0&&(t[s]=n[o-1]),n[o]=s)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}function ei(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:ei(t)}function Er(e){if(e)for(let t=0;te.__isSuspense;function ta(e,t){t&&t.pendingBranch?K(e)?t.effects.push(...e):t.effects.push(e):cl(e)}const he=Symbol.for("v-fgt"),rs=Symbol.for("v-txt"),_t=Symbol.for("v-cmt"),gs=Symbol.for("v-stc"),jt=[];let Ve=null;function j(e=!1){jt.push(Ve=e?null:[])}function si(){jt.pop(),Ve=jt[jt.length-1]||null}let vn=1;function Hn(e,t=!1){vn+=e,e<0&&Ve&&t&&(Ve.hasOnce=!0)}function ri(e){return e.dynamicChildren=vn>0?Ve||Bt:null,si(),vn>0&&Ve&&Ve.push(e),e}function F(e,t,n,s,r,o){return ri(m(e,t,n,s,r,o,!0))}function na(e,t,n,s,r){return ri(_e(e,t,n,s,r,!0))}function Bn(e){return e?e.__v_isVNode===!0:!1}function nn(e,t){return e.type===t.type&&e.key===t.key}const oi=({key:e})=>e??null,kn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?fe(e)||Ae(e)||W(e)?{i:Me,r:e,k:t,f:!!n}:e:null);function m(e,t=null,n=null,s=0,r=null,o=e===he?0:1,i=!1,a=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&oi(t),ref:t&&kn(t),scopeId:No,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:Me};return a?($n(u,n),o&128&&e.normalize(u)):n&&(u.shapeFlag|=fe(n)?8:16),vn>0&&!i&&Ve&&(u.patchFlag>0||o&6)&&u.patchFlag!==32&&Ve.push(u),u}const _e=sa;function sa(e,t=null,n=null,s=0,r=null,o=!1){if((!e||e===Ol)&&(e=_t),Bn(e)){const a=zt(e,t,!0);return n&&$n(a,n),vn>0&&!o&&Ve&&(a.shapeFlag&6?Ve[Ve.indexOf(e)]=a:Ve.push(a)),a.patchFlag=-2,a}if(ga(e)&&(e=e.__vccOpts),t){t=ra(t);let{class:a,style:u}=t;a&&!fe(a)&&(t.class=tt(a)),ee(u)&&(Js(u)&&!K(u)&&(u=xe({},u)),t.style=Hs(u))}const i=fe(e)?1:ni(e)?128:ts(e)?64:ee(e)?4:W(e)?2:0;return m(e,t,n,s,r,i,o,!0)}function ra(e){return e?Js(e)||qo(e)?xe({},e):e:null}function zt(e,t,n=!1,s=!1){const{props:r,ref:o,patchFlag:i,children:a,transition:u}=e,p=t?oa(r||{},t):r,f={__v_isVNode:!0,__v_skip:!0,type:e.type,props:p,key:p&&oi(p),ref:t&&t.ref?n&&o?K(o)?o.concat(kn(t)):[o,kn(t)]:kn(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==he?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:u,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&zt(e.ssContent),ssFallback:e.ssFallback&&zt(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return u&&s&&Xs(f,u.clone(f)),f}function Be(e=" ",t=0){return _e(rs,null,e,t)}function ue(e="",t=!1){return t?(j(),na(_t,null,e)):_e(_t,null,e)}function st(e){return e==null||typeof e=="boolean"?_e(_t):K(e)?_e(he,null,e.slice()):Bn(e)?pt(e):_e(rs,null,String(e))}function pt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:zt(e)}function $n(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(K(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),$n(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!qo(t)?t._ctx=Me:r===3&&Me&&(Me.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(W(t)){if(s&65){$n(e,{default:t});return}t={default:t,_ctx:Me},n=32}else t=String(t),s&64?(n=16,t=[Be(t)]):n=8;e.children=t,e.shapeFlag|=n}function oa(...e){const t={};for(let n=0;nCe||Me;let Kn,yn;{const e=Qn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),o=>{r.length>1?r.forEach(i=>i(o)):r[0](o)}};Kn=t("__VUE_INSTANCE_SETTERS__",n=>Ce=n),yn=t("__VUE_SSR_SETTERS__",n=>bn=n)}const Cn=e=>{const t=Ce;return Kn(e),e.scope.on(),()=>{e.scope.off(),Kn(t)}},Cr=()=>{Ce&&Ce.scope.off(),Kn(null)};function ii(e){return e.vnode.shapeFlag&4}let bn=!1;function ca(e,t=!1,n=!1){t&&yn(t);const{props:s,children:r}=e.vnode,o=ii(e);Gl(e,s,o,t),Jl(e,r,n||t);const i=o?fa(e,t):void 0;return t&&yn(!1),i}function fa(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Pl);const{setup:s}=n;if(s){vt();const r=e.setupContext=s.length>1?pa(e):null,o=Cn(e),i=En(s,e,0,[e.props,r]),a=so(i);if(yt(),o(),(a||e.sp)&&!fn(e)&&jo(e),a){if(i.then(Cr,Cr),t)return i.then(u=>{yn(!0);try{Ar(e,u,t)}finally{yn(!1)}}).catch(u=>{Zn(u,e,0)});e.asyncDep=i}else Ar(e,i)}else li(e)}function Ar(e,t,n){W(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ee(t)&&(e.setupState=Ro(t)),li(e)}function li(e,t,n){const s=e.type;e.render||(e.render=s.render||it);{const r=Cn(e);vt();try{Il(e)}finally{yt(),r()}}}const da={get(e,t){return Ee(e,"get",""),e[t]}};function pa(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,da),slots:e.slots,emit:e.emit,expose:t}}function os(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ro(el(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in dn)return dn[n](e)},has(t,n){return n in t||n in dn}})):e.proxy}function ha(e,t=!0){return W(e)?e.displayName||e.name:e.name||t&&e.__name}function ga(e){return W(e)&&"__vccOpts"in e}const De=(e,t)=>ol(e,t,bn);function ai(e,t,n){try{Hn(-1);const s=arguments.length;return s===2?ee(t)&&!K(t)?Bn(t)?_e(e,null,[t]):_e(e,t):_e(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Bn(n)&&(n=[n]),_e(e,t,n))}finally{Hn(1)}}const ma="3.5.41";/**
+* @vue/runtime-dom v3.5.41
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/let Ns;const Sr=typeof window<"u"&&window.trustedTypes;if(Sr)try{Ns=Sr.createPolicy("vue",{createHTML:e=>e})}catch{}const ui=Ns?e=>Ns.createHTML(e):e=>e,va="http://www.w3.org/2000/svg",ya="http://www.w3.org/1998/Math/MathML",dt=typeof document<"u"?document:null,Rr=dt&&dt.createElement("template"),ba={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?dt.createElementNS(va,e):t==="mathml"?dt.createElementNS(ya,e):n?dt.createElement(e,{is:n}):dt.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>dt.createTextNode(e),createComment:e=>dt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>dt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,o){const i=n?n.previousSibling:t.lastChild;if(r&&(r===o||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===o||!(r=r.nextSibling)););else{Rr.innerHTML=ui(s==="svg"?``:s==="mathml"?``:e);const a=Rr.content;if(s==="svg"||s==="mathml"){const u=a.firstChild;for(;u.firstChild;)a.appendChild(u.firstChild);a.removeChild(u)}t.insertBefore(a,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},_a=Symbol("_vtc");function xa(e,t,n){const s=e[_a];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Or=Symbol("_vod"),wa=Symbol("_vsh"),Ea=Symbol(""),Ca=/(?:^|;)\s*display\s*:/;function Aa(e,t,n){const s=e.style,r=fe(n);let o=!1;if(n&&!r){if(t)if(fe(t))for(const i of t.split(";")){const a=i.slice(0,i.indexOf(":")).trim();n[a]==null&&on(s,a,"")}else for(const i in t)n[i]==null&&on(s,i,"");for(const i in n){i==="display"&&(o=!0);const a=n[i];a!=null?Ra(e,i,!fe(t)&&t?t[i]:void 0,a)||on(s,i,a):on(s,i,"")}}else if(r){if(t!==n){const i=s[Ea];i&&(n+=";"+i),s.cssText=n,o=Ca.test(n)}}else t&&e.removeAttribute("style");Or in e&&(e[Or]=o?s.display:"",e[wa]&&(s.display="none"))}const Tr=/\s*!important$/;function on(e,t,n){if(K(n))n.forEach(s=>on(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=Sa(e,t);Tr.test(n)?e.setProperty(Lt(s),n.replace(Tr,""),"important"):e[s]=n}}const Pr=["Webkit","Moz","ms"],ms={};function Sa(e,t){const n=ms[t];if(n)return n;let s=Te(t);if(s!=="filter"&&s in e)return ms[t]=s;s=zn(s);for(let r=0;rvs||(ka.then(()=>vs=0),vs=Date.now());function Ma(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;const r=n.value;if(K(r)){const o=s.stopImmediatePropagation;s.stopImmediatePropagation=()=>{o.call(s),s._stopped=!0};const i=r.slice(),a=[s];for(let u=0;ue.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Va=(e,t,n,s,r,o)=>{const i=r==="svg";t==="class"?xa(e,s,i):t==="style"?Aa(e,n,s):Gn(t)?Wn(t)||Ta(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):ja(e,t,s,i))?(kr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Nr(e,t,s,i,o,t!=="value")):e._isVueCE&&(La(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!fe(s)))?kr(e,Te(t),s,o,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Nr(e,t,s,i))};function ja(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Mr(t)&&W(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Mr(t)&&fe(n)?!1:t in e}function La(e,t){const n=e._def.props;if(!n)return!1;const s=Te(t);return Array.isArray(n)?n.some(r=>Te(r)===s):Object.keys(n).some(r=>Te(r)===s)}const Jt=e=>{const t=e.props["onUpdate:modelValue"]||!1;return K(t)?n=>Pn(t,n):t};function Ua(e){e.target.composing=!0}function Vr(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ot=Symbol("_assign"),On=Symbol("_initialValue");function ys(e,t,n){return t&&(e=e.trim()),n&&(e=Jn(e)),e}const me={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e.parentNode&&(e.type==="text"?e[On]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[On]=e.defaultValue.replace(/\r\n?/g,`
+`))),e[ot]=Jt(r);const o=s||r.props&&r.props.type==="number";Tt(e,t?"change":"input",i=>{i.target.composing||e[ot](ys(e.value,n,o))}),(n||o)&&Tt(e,"change",()=>{e.value=ys(e.value,n,o)}),t||(Tt(e,"compositionstart",Ua),Tt(e,"compositionend",Vr),Tt(e,"change",Vr))},mounted(e,{value:t,modifiers:{trim:n,number:s}}){const r=t??"",o=e[On];delete e[On],o!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==o?e[ot](ys(e.value,n,s)):e.value=r},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:o}},i){if(e[ot]=Jt(i),e.composing)return;const a=(o||e.type==="number")&&!/^0\d/.test(e.value)?Jn(e.value):e.value,u=t??"";if(a===u)return;const p=e.getRootNode();(p instanceof Document||p instanceof ShadowRoot)&&p.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===u)||(e.value=u)}},Dn={deep:!0,created(e,t,n){e[ot]=Jt(n),Tt(e,"change",()=>{const s=e._modelValue,r=_n(e),o=e.checked,i=e[ot];if(K(s)){const a=Bs(s,r),u=a!==-1;if(o&&!u)i(s.concat(r));else if(!o&&u){const p=[...s];p.splice(a,1),i(p)}}else if(Xt(s)){const a=new Set(s);o?a.add(r):a.delete(r),i(a)}else i(ci(e,o))})},mounted:jr,beforeUpdate(e,t,n){e[ot]=Jt(n),jr(e,t,n)}};function jr(e,{value:t,oldValue:n},s){e._modelValue=t;let r;if(K(t))r=Bs(t,s.props.value)>-1;else if(Xt(t))r=t.has(s.props.value);else{if(t===n)return;r=Zt(t,ci(e,!0))}e.checked!==r&&(e.checked=r)}const ks={deep:!0,created(e,{value:t,modifiers:{number:n}},s){e._modelValue=t,Tt(e,"change",()=>{const r=Array.prototype.filter.call(e.options,o=>o.selected).map(o=>n?Jn(_n(o)):_n(o));e[ot](e.multiple?Xt(e._modelValue)?new Set(r):r:r[0]),e._assigning=!0,Qs(()=>{e._assigning=!1})}),e[ot]=Jt(s)},mounted(e,{value:t}){Lr(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[ot]=Jt(n)},updated(e,{value:t}){e._assigning||Lr(e,t)}};function Lr(e,t){const n=e.multiple,s=K(t);if(!(n&&!s&&!Xt(t))){for(let r=0,o=e.options.length;rString(p)===String(a)):i.selected=Bs(t,a)>-1}else i.selected=t.has(a);else if(Zt(_n(i),t)){e.selectedIndex!==r&&(e.selectedIndex=r);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function _n(e){return"_value"in e?e._value:e.value}function ci(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const Fa=["ctrl","shift","alt","meta"],Ha={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Fa.some(n=>e[`${n}Key`]&&!t.includes(n))},Rt=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((r,...o)=>{for(let i=0;i{const t=$a().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Wa(s);if(!r)return;const o=t._component;!W(o)&&!o.render&&!o.template&&(o.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const i=n(r,!1,Ga(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),i},t});function Ga(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Wa(e){return fe(e)?document.querySelector(e):e}const qa=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},za={},Ja={class:"min-h-screen"},Qa={class:"bg-white border-b border-gray-200"},Ya={class:"max-w-6xl mx-auto px-6 py-4 flex items-center justify-between"},Xa={class:"max-w-6xl mx-auto px-6 py-8"};function Za(e,t){const n=Un("router-link"),s=Un("router-view");return j(),F("div",Ja,[m("header",Qa,[m("div",Ya,[_e(n,{to:"/",class:"text-lg font-semibold text-gray-800"},{default:es(()=>[...t[0]||(t[0]=[Be(" uMind ",-1),m("span",{class:"text-brand"},"Orquestador",-1)])]),_:1}),t[1]||(t[1]=m("a",{href:"/app/dashboard",class:"text-sm text-gray-500 hover:text-gray-700"}," ← Volver al panel ",-1))])]),m("main",Xa,[_e(s)])])}const eu=qa(za,[["render",Za]]);/*!
+ * vue-router v4.6.4
+ * (c) 2025 Eduardo San Martin Morote
+ * @license MIT
+ */const Ht=typeof document<"u";function fi(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function tu(e){return e.__esModule||e[Symbol.toStringTag]==="Module"||e.default&&fi(e.default)}const Y=Object.assign;function bs(e,t){const n={};for(const s in t){const r=t[s];n[s]=qe(r)?r.map(e):e(r)}return n}const pn=()=>{},qe=Array.isArray;function Fr(e,t){const n={};for(const s in e)n[s]=s in t?t[s]:e[s];return n}const di=/#/g,nu=/&/g,su=/\//g,ru=/=/g,ou=/\?/g,pi=/\+/g,iu=/%5B/g,lu=/%5D/g,hi=/%5E/g,au=/%60/g,gi=/%7B/g,uu=/%7C/g,mi=/%7D/g,cu=/%20/g;function sr(e){return e==null?"":encodeURI(""+e).replace(uu,"|").replace(iu,"[").replace(lu,"]")}function fu(e){return sr(e).replace(gi,"{").replace(mi,"}").replace(hi,"^")}function Ds(e){return sr(e).replace(pi,"%2B").replace(cu,"+").replace(di,"%23").replace(nu,"%26").replace(au,"`").replace(gi,"{").replace(mi,"}").replace(hi,"^")}function du(e){return Ds(e).replace(ru,"%3D")}function pu(e){return sr(e).replace(di,"%23").replace(ou,"%3F")}function hu(e){return pu(e).replace(su,"%2F")}function xn(e){if(e==null)return null;try{return decodeURIComponent(""+e)}catch{}return""+e}const gu=/\/$/,mu=e=>e.replace(gu,"");function _s(e,t,n="/"){let s,r={},o="",i="";const a=t.indexOf("#");let u=t.indexOf("?");return u=a>=0&&u>a?-1:u,u>=0&&(s=t.slice(0,u),o=t.slice(u,a>0?a:t.length),r=e(o.slice(1))),a>=0&&(s=s||t.slice(0,a),i=t.slice(a,t.length)),s=_u(s??t,n),{fullPath:s+o+i,path:s,query:r,hash:xn(i)}}function vu(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function Hr(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function yu(e,t,n){const s=t.matched.length-1,r=n.matched.length-1;return s>-1&&s===r&&Qt(t.matched[s],n.matched[r])&&vi(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Qt(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function vi(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(!bu(e[n],t[n]))return!1;return!0}function bu(e,t){return qe(e)?Br(e,t):qe(t)?Br(t,e):(e==null?void 0:e.valueOf())===(t==null?void 0:t.valueOf())}function Br(e,t){return qe(t)?e.length===t.length&&e.every((n,s)=>n===t[s]):e.length===1&&e[0]===t}function _u(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),s=e.split("/"),r=s[s.length-1];(r===".."||r===".")&&s.push("");let o=n.length-1,i,a;for(i=0;i1&&o--;else break;return n.slice(0,o).join("/")+"/"+s.slice(i).join("/")}const At={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};let Ms=(function(e){return e.pop="pop",e.push="push",e})({}),xs=(function(e){return e.back="back",e.forward="forward",e.unknown="",e})({});function xu(e){if(!e)if(Ht){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),mu(e)}const wu=/^[^#]+#/;function Eu(e,t){return e.replace(wu,"#")+t}function Cu(e,t){const n=document.documentElement.getBoundingClientRect(),s=e.getBoundingClientRect();return{behavior:t.behavior,left:s.left-n.left-(t.left||0),top:s.top-n.top-(t.top||0)}}const is=()=>({left:window.scrollX,top:window.scrollY});function Au(e){let t;if("el"in e){const n=e.el,s=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?s?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=Cu(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function $r(e,t){return(history.state?history.state.position-t:-1)+e}const Vs=new Map;function Su(e,t){Vs.set(e,t)}function Ru(e){const t=Vs.get(e);return Vs.delete(e),t}function Ou(e){return typeof e=="string"||e&&typeof e=="object"}function yi(e){return typeof e=="string"||typeof e=="symbol"}let ce=(function(e){return e[e.MATCHER_NOT_FOUND=1]="MATCHER_NOT_FOUND",e[e.NAVIGATION_GUARD_REDIRECT=2]="NAVIGATION_GUARD_REDIRECT",e[e.NAVIGATION_ABORTED=4]="NAVIGATION_ABORTED",e[e.NAVIGATION_CANCELLED=8]="NAVIGATION_CANCELLED",e[e.NAVIGATION_DUPLICATED=16]="NAVIGATION_DUPLICATED",e})({});const bi=Symbol("");ce.MATCHER_NOT_FOUND+"",ce.NAVIGATION_GUARD_REDIRECT+"",ce.NAVIGATION_ABORTED+"",ce.NAVIGATION_CANCELLED+"",ce.NAVIGATION_DUPLICATED+"";function Yt(e,t){return Y(new Error,{type:e,[bi]:!0},t)}function ft(e,t){return e instanceof Error&&bi in e&&(t==null||!!(e.type&t))}const Tu=["params","query","hash"];function Pu(e){if(typeof e=="string")return e;if(e.path!=null)return e.path;const t={};for(const n of Tu)n in e&&(t[n]=e[n]);return JSON.stringify(t,null,2)}function Iu(e){const t={};if(e===""||e==="?")return t;const n=(e[0]==="?"?e.slice(1):e).split("&");for(let s=0;sr&&Ds(r)):[s&&Ds(s)]).forEach(r=>{r!==void 0&&(t+=(t.length?"&":"")+n,r!=null&&(t+="="+r))})}return t}function Nu(e){const t={};for(const n in e){const s=e[n];s!==void 0&&(t[n]=qe(s)?s.map(r=>r==null?null:""+r):s==null?s:""+s)}return t}const ku=Symbol(""),Gr=Symbol(""),rr=Symbol(""),_i=Symbol(""),js=Symbol("");function sn(){let e=[];function t(s){return e.push(s),()=>{const r=e.indexOf(s);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Ot(e,t,n,s,r,o=i=>i()){const i=s&&(s.enterCallbacks[r]=s.enterCallbacks[r]||[]);return()=>new Promise((a,u)=>{const p=g=>{g===!1?u(Yt(ce.NAVIGATION_ABORTED,{from:n,to:t})):g instanceof Error?u(g):Ou(g)?u(Yt(ce.NAVIGATION_GUARD_REDIRECT,{from:t,to:g})):(i&&s.enterCallbacks[r]===i&&typeof g=="function"&&i.push(g),a())},f=o(()=>e.call(s&&s.instances[r],t,n,p));let h=Promise.resolve(f);e.length<3&&(h=h.then(p)),h.catch(g=>u(g))})}function ws(e,t,n,s,r=o=>o()){const o=[];for(const i of e)for(const a in i.components){let u=i.components[a];if(!(t!=="beforeRouteEnter"&&!i.instances[a]))if(fi(u)){const p=(u.__vccOpts||u)[t];p&&o.push(Ot(p,n,s,i,a,r))}else{let p=u();o.push(()=>p.then(f=>{if(!f)throw new Error(`Couldn't resolve component "${a}" at "${i.path}"`);const h=tu(f)?f.default:f;i.mods[a]=f,i.components[a]=h;const g=(h.__vccOpts||h)[t];return g&&Ot(g,n,s,i,a,r)()}))}}return o}function Du(e,t){const n=[],s=[],r=[],o=Math.max(t.matched.length,e.matched.length);for(let i=0;iQt(p,a))?s.push(a):n.push(a));const u=e.matched[i];u&&(t.matched.find(p=>Qt(p,u))||r.push(u))}return[n,s,r]}/*!
+ * vue-router v4.6.4
+ * (c) 2025 Eduardo San Martin Morote
+ * @license MIT
+ */let Mu=()=>location.protocol+"//"+location.host;function xi(e,t){const{pathname:n,search:s,hash:r}=t,o=e.indexOf("#");if(o>-1){let i=r.includes(e.slice(o))?e.slice(o).length:1,a=r.slice(i);return a[0]!=="/"&&(a="/"+a),Hr(a,"")}return Hr(n,e)+s+r}function Vu(e,t,n,s){let r=[],o=[],i=null;const a=({state:g})=>{const v=xi(e,location),S=n.value,b=t.value;let $=0;if(g){if(n.value=v,t.value=g,i&&i===S){i=null;return}$=b?g.position-b.position:0}else s(v);r.forEach(R=>{R(n.value,S,{delta:$,type:Ms.pop,direction:$?$>0?xs.forward:xs.back:xs.unknown})})};function u(){i=n.value}function p(g){r.push(g);const v=()=>{const S=r.indexOf(g);S>-1&&r.splice(S,1)};return o.push(v),v}function f(){if(document.visibilityState==="hidden"){const{history:g}=window;if(!g.state)return;g.replaceState(Y({},g.state,{scroll:is()}),"")}}function h(){for(const g of o)g();o=[],window.removeEventListener("popstate",a),window.removeEventListener("pagehide",f),document.removeEventListener("visibilitychange",f)}return window.addEventListener("popstate",a),window.addEventListener("pagehide",f),document.addEventListener("visibilitychange",f),{pauseListeners:u,listen:p,destroy:h}}function Wr(e,t,n,s=!1,r=!1){return{back:e,current:t,forward:n,replaced:s,position:window.history.length,scroll:r?is():null}}function ju(e){const{history:t,location:n}=window,s={value:xi(e,n)},r={value:t.state};r.value||o(s.value,{back:null,current:s.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function o(u,p,f){const h=e.indexOf("#"),g=h>-1?(n.host&&document.querySelector("base")?e:e.slice(h))+u:Mu()+e+u;try{t[f?"replaceState":"pushState"](p,"",g),r.value=p}catch(v){console.error(v),n[f?"replace":"assign"](g)}}function i(u,p){o(u,Y({},t.state,Wr(r.value.back,u,r.value.forward,!0),p,{position:r.value.position}),!0),s.value=u}function a(u,p){const f=Y({},r.value,t.state,{forward:u,scroll:is()});o(f.current,f,!0),o(u,Y({},Wr(s.value,u,null),{position:f.position+1},p),!1),s.value=u}return{location:s,state:r,push:a,replace:i}}function Lu(e){e=xu(e);const t=ju(e),n=Vu(e,t.state,t.location,t.replace);function s(o,i=!0){i||n.pauseListeners(),history.go(o)}const r=Y({location:"",base:e,go:s,createHref:Eu.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}let Dt=(function(e){return e[e.Static=0]="Static",e[e.Param=1]="Param",e[e.Group=2]="Group",e})({});var ge=(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})(ge||{});const Uu={type:Dt.Static,value:""},Fu=/[a-zA-Z0-9_]/;function Hu(e){if(!e)return[[]];if(e==="/")return[[Uu]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(v){throw new Error(`ERR (${n})/"${p}": ${v}`)}let n=ge.Static,s=n;const r=[];let o;function i(){o&&r.push(o),o=[]}let a=0,u,p="",f="";function h(){p&&(n===ge.Static?o.push({type:Dt.Static,value:p}):n===ge.Param||n===ge.ParamRegExp||n===ge.ParamRegExpEnd?(o.length>1&&(u==="*"||u==="+")&&t(`A repeatable param (${p}) must be alone in its segment. eg: '/:ids+.`),o.push({type:Dt.Param,value:p,regexp:f,repeatable:u==="*"||u==="+",optional:u==="*"||u==="?"})):t("Invalid state to consume buffer"),p="")}function g(){p+=u}for(;at.length?t.length===1&&t[0]===Re.Static+Re.Segment?1:-1:0}function wi(e,t){let n=0;const s=e.score,r=t.score;for(;n0&&t[t.length-1]<0}const Wu={strict:!1,end:!0,sensitive:!1};function qu(e,t,n){const s=Ku(Hu(e.path),n),r=Y(s,{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function zu(e,t){const n=[],s=new Map;t=Fr(Wu,t);function r(h){return s.get(h)}function o(h,g,v){const S=!v,b=Qr(h);b.aliasOf=v&&v.record;const $=Fr(t,h),R=[b];if("alias"in h){const D=typeof h.alias=="string"?[h.alias]:h.alias;for(const q of D)R.push(Qr(Y({},b,{components:v?v.record.components:b.components,path:q,aliasOf:v?v.record:b})))}let N,M;for(const D of R){const{path:q}=D;if(g&&q[0]!=="/"){const oe=g.record.path,L=oe[oe.length-1]==="/"?"":"/";D.path=g.record.path+(q&&L+q)}if(N=qu(D,g,$),v?v.alias.push(N):(M=M||N,M!==N&&M.alias.push(N),S&&h.name&&!Yr(N)&&i(h.name)),Ei(N)&&u(N),b.children){const oe=b.children;for(let L=0;L{i(M)}:pn}function i(h){if(yi(h)){const g=s.get(h);g&&(s.delete(h),n.splice(n.indexOf(g),1),g.children.forEach(i),g.alias.forEach(i))}else{const g=n.indexOf(h);g>-1&&(n.splice(g,1),h.record.name&&s.delete(h.record.name),h.children.forEach(i),h.alias.forEach(i))}}function a(){return n}function u(h){const g=Yu(h,n);n.splice(g,0,h),h.record.name&&!Yr(h)&&s.set(h.record.name,h)}function p(h,g){let v,S={},b,$;if("name"in h&&h.name){if(v=s.get(h.name),!v)throw Yt(ce.MATCHER_NOT_FOUND,{location:h});$=v.record.name,S=Y(Jr(g.params,v.keys.filter(M=>!M.optional).concat(v.parent?v.parent.keys.filter(M=>M.optional):[]).map(M=>M.name)),h.params&&Jr(h.params,v.keys.map(M=>M.name))),b=v.stringify(S)}else if(h.path!=null)b=h.path,v=n.find(M=>M.re.test(b)),v&&(S=v.parse(b),$=v.record.name);else{if(v=g.name?s.get(g.name):n.find(M=>M.re.test(g.path)),!v)throw Yt(ce.MATCHER_NOT_FOUND,{location:h,currentLocation:g});$=v.record.name,S=Y({},g.params,h.params),b=v.stringify(S)}const R=[];let N=v;for(;N;)R.unshift(N.record),N=N.parent;return{name:$,path:b,params:S,matched:R,meta:Qu(R)}}e.forEach(h=>o(h));function f(){n.length=0,s.clear()}return{addRoute:o,resolve:p,removeRoute:i,clearRoutes:f,getRoutes:a,getRecordMatcher:r}}function Jr(e,t){const n={};for(const s of t)s in e&&(n[s]=e[s]);return n}function Qr(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:Ju(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 Ju(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 Yr(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function Qu(e){return e.reduce((t,n)=>Y(t,n.meta),{})}function Yu(e,t){let n=0,s=t.length;for(;n!==s;){const o=n+s>>1;wi(e,t[o])<0?s=o:n=o+1}const r=Xu(e);return r&&(s=t.lastIndexOf(r,s-1)),s}function Xu(e){let t=e;for(;t=t.parent;)if(Ei(t)&&wi(e,t)===0)return t}function Ei({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function Xr(e){const t=mt(rr),n=mt(_i),s=De(()=>{const u=Kt(e.to);return t.resolve(u)}),r=De(()=>{const{matched:u}=s.value,{length:p}=u,f=u[p-1],h=n.matched;if(!f||!h.length)return-1;const g=h.findIndex(Qt.bind(null,f));if(g>-1)return g;const v=Zr(u[p-2]);return p>1&&Zr(f)===v&&h[h.length-1].path!==v?h.findIndex(Qt.bind(null,u[p-2])):g}),o=De(()=>r.value>-1&&sc(n.params,s.value.params)),i=De(()=>r.value>-1&&r.value===n.matched.length-1&&vi(n.params,s.value.params));function a(u={}){if(nc(u)){const p=t[Kt(e.replace)?"replace":"push"](Kt(e.to)).catch(pn);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>p),p}return Promise.resolve()}return{route:s,href:De(()=>s.value.href),isActive:o,isExactActive:i,navigate:a}}function Zu(e){return e.length===1?e[0]:e}const ec=Vo({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:Xr,setup(e,{slots:t}){const n=Xn(Xr(e)),{options:s}=mt(rr),r=De(()=>({[eo(e.activeClass,s.linkActiveClass,"router-link-active")]:n.isActive,[eo(e.exactActiveClass,s.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const o=t.default&&Zu(t.default(n));return e.custom?o:ai("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},o)}}}),tc=ec;function nc(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 sc(e,t){for(const n in t){const s=t[n],r=e[n];if(typeof s=="string"){if(s!==r)return!1}else if(!qe(r)||r.length!==s.length||s.some((o,i)=>o.valueOf()!==r[i].valueOf()))return!1}return!0}function Zr(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const eo=(e,t,n)=>e??t??n,rc=Vo({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const s=mt(js),r=De(()=>e.route||s.value),o=mt(Gr,0),i=De(()=>{let p=Kt(o);const{matched:f}=r.value;let h;for(;(h=f[p])&&!h.components;)p++;return p}),a=De(()=>r.value.matched[i.value]);In(Gr,De(()=>i.value+1)),In(ku,a),In(js,r);const u=ne();return Nn(()=>[u.value,a.value,e.name],([p,f,h],[g,v,S])=>{f&&(f.instances[h]=p,v&&v!==f&&p&&p===g&&(f.leaveGuards.size||(f.leaveGuards=v.leaveGuards),f.updateGuards.size||(f.updateGuards=v.updateGuards))),p&&f&&(!v||!Qt(f,v)||!g)&&(f.enterCallbacks[h]||[]).forEach(b=>b(p))},{flush:"post"}),()=>{const p=r.value,f=e.name,h=a.value,g=h&&h.components[f];if(!g)return to(n.default,{Component:g,route:p});const v=h.props[f],S=v?v===!0?p.params:typeof v=="function"?v(p):v:null,$=ai(g,Y({},S,t,{onVnodeUnmounted:R=>{R.component.isUnmounted&&(h.instances[f]=null)},ref:u}));return to(n.default,{Component:$,route:p})||$}}});function to(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const oc=rc;function ic(e){const t=zu(e.routes,e),n=e.parseQuery||Iu,s=e.stringifyQuery||Kr,r=e.history,o=sn(),i=sn(),a=sn(),u=tl(At);let p=At;Ht&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const f=bs.bind(null,x=>""+x),h=bs.bind(null,hu),g=bs.bind(null,xn);function v(x,I){let P,V;return yi(x)?(P=t.getRecordMatcher(x),V=I):V=x,t.addRoute(V,P)}function S(x){const I=t.getRecordMatcher(x);I&&t.removeRoute(I)}function b(){return t.getRoutes().map(x=>x.record)}function $(x){return!!t.getRecordMatcher(x)}function R(x,I){if(I=Y({},I||u.value),typeof x=="string"){const c=_s(n,x,I.path),y=t.resolve({path:c.path},I),w=r.createHref(c.fullPath);return Y(c,y,{params:g(y.params),hash:xn(c.hash),redirectedFrom:void 0,href:w})}let P;if(x.path!=null)P=Y({},x,{path:_s(n,x.path,I.path).path});else{const c=Y({},x.params);for(const y in c)c[y]==null&&delete c[y];P=Y({},x,{params:h(c)}),I.params=h(I.params)}const V=t.resolve(P,I),C=x.hash||"";V.params=f(g(V.params));const l=vu(s,Y({},x,{hash:fu(C),path:V.path})),d=r.createHref(l);return Y({fullPath:l,hash:C,query:s===Kr?Nu(x.query):x.query||{}},V,{redirectedFrom:void 0,href:d})}function N(x){return typeof x=="string"?_s(n,x,u.value.path):Y({},x)}function M(x,I){if(p!==x)return Yt(ce.NAVIGATION_CANCELLED,{from:I,to:x})}function D(x){return L(x)}function q(x){return D(Y(N(x),{replace:!0}))}function oe(x,I){const P=x.matched[x.matched.length-1];if(P&&P.redirect){const{redirect:V}=P;let C=typeof V=="function"?V(x,I):V;return typeof C=="string"&&(C=C.includes("?")||C.includes("#")?C=N(C):{path:C},C.params={}),Y({query:x.query,hash:x.hash,params:C.path!=null?{}:x.params},C)}}function L(x,I){const P=p=R(x),V=u.value,C=x.state,l=x.force,d=x.replace===!0,c=oe(P,V);if(c)return L(Y(N(c),{state:typeof c=="object"?Y({},C,c.state):C,force:l,replace:d}),I||P);const y=P;y.redirectedFrom=I;let w;return!l&&yu(s,V,P)&&(w=Yt(ce.NAVIGATION_DUPLICATED,{to:y,from:V}),He(V,V,!0,!1)),(w?Promise.resolve(w):Le(y,V)).catch(_=>ft(_)?ft(_,ce.NAVIGATION_GUARD_REDIRECT)?_:Ne(_):H(_,y,V)).then(_=>{if(_){if(ft(_,ce.NAVIGATION_GUARD_REDIRECT))return L(Y({replace:d},N(_.to),{state:typeof _.to=="object"?Y({},C,_.to.state):C,force:l}),I||y)}else _=at(y,V,!0,d,C);return ze(y,V,_),_})}function Ie(x,I){const P=M(x,I);return P?Promise.reject(P):Promise.resolve()}function je(x){const I=Ct.values().next().value;return I&&typeof I.runWithContext=="function"?I.runWithContext(x):x()}function Le(x,I){let P;const[V,C,l]=Du(x,I);P=ws(V.reverse(),"beforeRouteLeave",x,I);for(const c of V)c.leaveGuards.forEach(y=>{P.push(Ot(y,x,I))});const d=Ie.bind(null,x,I);return P.push(d),ve(P).then(()=>{P=[];for(const c of o.list())P.push(Ot(c,x,I));return P.push(d),ve(P)}).then(()=>{P=ws(C,"beforeRouteUpdate",x,I);for(const c of C)c.updateGuards.forEach(y=>{P.push(Ot(y,x,I))});return P.push(d),ve(P)}).then(()=>{P=[];for(const c of l)if(c.beforeEnter)if(qe(c.beforeEnter))for(const y of c.beforeEnter)P.push(Ot(y,x,I));else P.push(Ot(c.beforeEnter,x,I));return P.push(d),ve(P)}).then(()=>(x.matched.forEach(c=>c.enterCallbacks={}),P=ws(l,"beforeRouteEnter",x,I,je),P.push(d),ve(P))).then(()=>{P=[];for(const c of i.list())P.push(Ot(c,x,I));return P.push(d),ve(P)}).catch(c=>ft(c,ce.NAVIGATION_CANCELLED)?c:Promise.reject(c))}function ze(x,I,P){a.list().forEach(V=>je(()=>V(x,I,P)))}function at(x,I,P,V,C){const l=M(x,I);if(l)return l;const d=I===At,c=Ht?history.state:{};P&&(V||d?r.replace(x.fullPath,Y({scroll:d&&c&&c.scroll},C)):r.push(x.fullPath,C)),u.value=x,He(x,I,P,d),Ne()}let Ue;function Pt(){Ue||(Ue=r.listen((x,I,P)=>{if(!ut.listening)return;const V=R(x),C=oe(V,ut.currentRoute.value);if(C){L(Y(C,{replace:!0,force:!0}),V).catch(pn);return}p=V;const l=u.value;Ht&&Su($r(l.fullPath,P.delta),is()),Le(V,l).catch(d=>ft(d,ce.NAVIGATION_ABORTED|ce.NAVIGATION_CANCELLED)?d:ft(d,ce.NAVIGATION_GUARD_REDIRECT)?(L(Y(N(d.to),{force:!0}),V).then(c=>{ft(c,ce.NAVIGATION_ABORTED|ce.NAVIGATION_DUPLICATED)&&!P.delta&&P.type===Ms.pop&&r.go(-1,!1)}).catch(pn),Promise.reject()):(P.delta&&r.go(-P.delta,!1),H(d,V,l))).then(d=>{d=d||at(V,l,!1),d&&(P.delta&&!ft(d,ce.NAVIGATION_CANCELLED)?r.go(-P.delta,!1):P.type===Ms.pop&&ft(d,ce.NAVIGATION_ABORTED|ce.NAVIGATION_DUPLICATED)&&r.go(-1,!1)),ze(V,l,d)}).catch(pn)}))}let wt=sn(),ae=sn(),z;function H(x,I,P){Ne(x);const V=ae.list();return V.length?V.forEach(C=>C(x,I,P)):console.error(x),Promise.reject(x)}function Fe(){return z&&u.value!==At?Promise.resolve():new Promise((x,I)=>{wt.add([x,I])})}function Ne(x){return z||(z=!x,Pt(),wt.list().forEach(([I,P])=>x?P(x):I()),wt.reset()),x}function He(x,I,P,V){const{scrollBehavior:C}=e;if(!Ht||!C)return Promise.resolve();const l=!P&&Ru($r(x.fullPath,0))||(V||!P)&&history.state&&history.state.scroll||null;return Qs().then(()=>C(x,I,l)).then(d=>d&&Au(d)).catch(d=>H(d,x,I))}const we=x=>r.go(x);let Et;const Ct=new Set,ut={currentRoute:u,listening:!0,addRoute:v,removeRoute:S,clearRoutes:t.clearRoutes,hasRoute:$,getRoutes:b,resolve:R,options:e,push:D,replace:q,go:we,back:()=>we(-1),forward:()=>we(1),beforeEach:o.add,beforeResolve:i.add,afterEach:a.add,onError:ae.add,isReady:Fe,install(x){x.component("RouterLink",tc),x.component("RouterView",oc),x.config.globalProperties.$router=ut,Object.defineProperty(x.config.globalProperties,"$route",{enumerable:!0,get:()=>Kt(u)}),Ht&&!Et&&u.value===At&&(Et=!0,D(r.location).catch(V=>{}));const I={};for(const V in At)Object.defineProperty(I,V,{get:()=>u.value[V],enumerable:!0});x.provide(rr,ut),x.provide(_i,Ao(I)),x.provide(js,u);const P=x.unmount;Ct.add(x),x.unmount=function(){Ct.delete(x),Ct.size<1&&(p=At,Ue&&Ue(),Ue=null,u.value=At,Et=!1,z=!1),P()}}};function ve(x){return x.reduce((I,P)=>I.then(()=>je(P)),Promise.resolve())}return ut}async function Tn(e,t={}){const n=await fetch(e,{...t,headers:{"Content-Type":"application/json",...t.headers}}),s=n.headers.get("content-type")||"";if(n.redirected||!s.includes("application/json"))throw window.location.href="/login",new Error("Sesión expirada");const r=await n.json();if(!n.ok)throw new Error((r==null?void 0:r.error)||(r==null?void 0:r.message)||"Error de servidor");return r}const pe={get:e=>Tn(e),post:(e,t)=>Tn(e,{method:"POST",body:JSON.stringify(t)}),put:(e,t)=>Tn(e,{method:"PUT",body:JSON.stringify(t)}),del:e=>Tn(e,{method:"DELETE"})},lc={key:0,class:"text-sm text-red-600 mb-4"},ac={key:1,class:"text-sm text-gray-500"},uc={key:2,class:"bg-white rounded-xl border border-gray-200 divide-y divide-gray-100"},cc={key:0,class:"p-6 text-sm text-gray-500"},fc={class:"text-xs text-gray-500 mt-0.5"},dc={class:"flex gap-3 text-sm"},pc=["onClick"],hc=["onClick"],gc={class:"bg-white rounded-xl p-6 w-full max-w-lg"},mc={class:"font-semibold text-gray-800 mb-4"},vc=["value"],yc={class:"flex items-center gap-2 text-sm text-gray-600"},bc={class:"flex justify-end gap-2 pt-2"},_c={__name:"TenantsList",setup(e){const t=ne([]),n=ne([]),s=ne(!0),r=ne(""),o=ne(!1),i=ne(null),a=ne(u());function u(){return{nombre:"",dominios_permitidos:"",ai_config_id:null,tono:"",mensaje_bienvenida:"",activo:!0}}async function p(){s.value=!0,r.value="";try{const[S,b]=await Promise.all([pe.get("/app/umind/tenants"),pe.get("/app/api/ai-config/select")]);t.value=S.items||[],n.value=b.registros||[]}catch(S){r.value=S.message}finally{s.value=!1}}function f(){i.value=null,a.value=u(),o.value=!0}function h(S){i.value=S,a.value={nombre:S.nombre,dominios_permitidos:S.dominios_permitidos,ai_config_id:S.ai_config_id,tono:S.tono,mensaje_bienvenida:S.mensaje_bienvenida,activo:S.activo},o.value=!0}async function g(){const S={...a.value,dominios_permitidos:a.value.dominios_permitidos.split(",").map(b=>b.trim()).filter(Boolean)};try{i.value?await pe.put(`/app/umind/tenants/${i.value.ID}`,S):await pe.post("/app/umind/tenants",S),o.value=!1,await p()}catch(b){r.value=b.message}}async function v(S){if(confirm(`¿Eliminar el tenant "${S.nombre}"? Esto no se puede deshacer.`))try{await pe.del(`/app/umind/tenants/${S.ID}`),await p()}catch(b){r.value=b.message}}return er(p),(S,b)=>{const $=Un("router-link");return j(),F("div",null,[m("div",{class:"flex items-center justify-between mb-6"},[b[8]||(b[8]=m("h1",{class:"text-xl font-semibold text-gray-800"},"Tenants",-1)),m("button",{class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg",onClick:f}," + Nuevo tenant ")]),r.value?(j(),F("p",lc,Q(r.value),1)):ue("",!0),s.value?(j(),F("p",ac,"Cargando...")):(j(),F("div",uc,[t.value.length===0?(j(),F("div",cc," Todavía no hay tenants. Creá el primero. ")):ue("",!0),(j(!0),F(he,null,et(t.value,R=>(j(),F("div",{key:R.ID,class:"p-4 flex items-center justify-between hover:bg-gray-50"},[m("div",null,[_e($,{to:`/tenants/${R.ID}`,class:"font-medium text-gray-800 hover:text-brand"},{default:es(()=>[Be(Q(R.nombre),1)]),_:2},1032,["to"]),m("div",fc,[Be(Q(R.dominios_permitidos||"sin dominios configurados")+" ",1),m("span",{class:tt(["ml-2 px-1.5 py-0.5 rounded",R.activo?"bg-green-100 text-green-700":"bg-gray-100 text-gray-500"])},Q(R.activo?"activo":"inactivo"),3)])]),m("div",dc,[m("button",{class:"text-gray-500 hover:text-gray-800",onClick:N=>h(R)},"Editar",8,pc),m("button",{class:"text-red-500 hover:text-red-700",onClick:N=>v(R)},"Eliminar",8,hc)])]))),128))])),o.value?(j(),F("div",{key:3,class:"fixed inset-0 bg-black/30 flex items-center justify-center p-4 z-50",onClick:b[7]||(b[7]=Rt(R=>o.value=!1,["self"]))},[m("div",gc,[m("h2",mc,Q(i.value?"Editar tenant":"Nuevo tenant"),1),m("form",{class:"space-y-3",onSubmit:Rt(g,["prevent"])},[m("div",null,[b[9]||(b[9]=m("label",{class:"text-xs text-gray-500"},"Nombre",-1)),ie(m("input",{"onUpdate:modelValue":b[0]||(b[0]=R=>a.value.nombre=R),required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,a.value.nombre]])]),m("div",null,[b[10]||(b[10]=m("label",{class:"text-xs text-gray-500"},"Dominios permitidos (separados por coma)",-1)),ie(m("input",{"onUpdate:modelValue":b[1]||(b[1]=R=>a.value.dominios_permitidos=R),placeholder:"ejemplo.com, www.ejemplo.com",required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,a.value.dominios_permitidos]])]),m("div",null,[b[12]||(b[12]=m("label",{class:"text-xs text-gray-500"},"Config de IA",-1)),ie(m("select",{"onUpdate:modelValue":b[2]||(b[2]=R=>a.value.ai_config_id=R),class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},[b[11]||(b[11]=m("option",{value:null},"— sin asignar —",-1)),(j(!0),F(he,null,et(n.value,R=>(j(),F("option",{key:R.ID,value:R.ID},Q(R.nombre)+" ("+Q(R.provider)+") ",9,vc))),128))],512),[[ks,a.value.ai_config_id]])]),m("div",null,[b[13]||(b[13]=m("label",{class:"text-xs text-gray-500"},"Tono / personalidad",-1)),ie(m("textarea",{"onUpdate:modelValue":b[3]||(b[3]=R=>a.value.tono=R),rows:"2",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,a.value.tono]])]),m("div",null,[b[14]||(b[14]=m("label",{class:"text-xs text-gray-500"},"Mensaje de bienvenida",-1)),ie(m("input",{"onUpdate:modelValue":b[4]||(b[4]=R=>a.value.mensaje_bienvenida=R),class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,a.value.mensaje_bienvenida]])]),m("label",yc,[ie(m("input",{"onUpdate:modelValue":b[5]||(b[5]=R=>a.value.activo=R),type:"checkbox"},null,512),[[Dn,a.value.activo]]),b[15]||(b[15]=Be(" Activo ",-1))]),m("div",bc,[m("button",{type:"button",class:"px-4 py-2 text-sm text-gray-500",onClick:b[6]||(b[6]=R=>o.value=!1)}," Cancelar "),b[16]||(b[16]=m("button",{type:"submit",class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg"}," Guardar ",-1))])],32)])])):ue("",!0)])}}},xc={key:0,class:"mt-2 mb-6"},wc={class:"text-xl font-semibold text-gray-800"},Ec={class:"text-xs text-gray-500 mt-1"},Cc={class:"bg-gray-100 px-1.5 py-0.5 rounded"},Ac={key:1,class:"text-sm text-red-600 mb-4"},Sc={class:"border-b border-gray-200 mb-6 flex gap-6 text-sm overflow-x-auto"},Rc=["onClick"],Oc={key:2},Tc=["disabled"],Pc={class:"bg-white rounded-xl border border-gray-200 divide-y divide-gray-100"},Ic={key:0,class:"p-6 text-sm text-gray-500"},Nc={class:"text-sm text-gray-800"},kc={class:"text-xs text-gray-500 mt-0.5"},Dc={key:0},Mc={key:1,class:"text-red-600"},Vc=["onClick"],jc={key:3},Lc={class:"bg-white rounded-xl border border-gray-200 divide-y divide-gray-100"},Uc={key:0,class:"p-6 text-sm text-gray-500"},Fc={class:"text-sm text-gray-800 font-mono"},Hc={class:"text-xs text-gray-500 mt-0.5"},Bc={class:"text-xs text-gray-400 mt-0.5"},$c={key:0,class:"ml-1 text-green-600"},Kc={key:1,class:"ml-1 text-gray-400"},Gc={class:"flex gap-3 text-sm shrink-0"},Wc=["onClick"],qc=["onClick"],zc={class:"bg-white rounded-xl p-6 w-full max-w-xl max-h-[85vh] overflow-y-auto"},Jc={class:"font-semibold text-gray-800 mb-4"},Qc={class:"border border-gray-200 rounded-lg p-3 space-y-2"},Yc=["onUpdate:modelValue"],Xc=["onUpdate:modelValue"],Zc=["onUpdate:modelValue"],ef={class:"text-xs text-gray-500 flex items-center gap-1"},tf=["onUpdate:modelValue"],nf=["onClick"],sf={key:0,class:"text-xs text-gray-400"},rf={class:"border border-gray-200 rounded-lg p-3 space-y-2"},of={class:"flex items-center gap-2 text-xs text-gray-500"},lf={class:"flex items-center gap-2 text-sm text-gray-600"},af={class:"flex justify-end gap-2 pt-2"},uf={key:4},cf={class:"bg-white rounded-xl border border-gray-200 divide-y divide-gray-100"},ff={key:0,class:"p-6 text-sm text-gray-500"},df={class:"flex items-center justify-between"},pf={class:"font-medium text-gray-800 capitalize"},hf={class:"flex gap-3 text-sm"},gf=["onClick"],mf=["onClick"],vf={class:"text-xs text-gray-500 mt-1 break-all"},yf={class:"bg-gray-100 px-1 rounded"},bf={key:0,class:"text-xs text-gray-400 mt-1"},_f={key:1,class:"text-xs text-red-600 mt-1"},xf={class:"bg-white rounded-xl p-6 w-full max-w-md"},wf={key:0},Ef={class:"flex justify-end gap-2 pt-2"},Cf={key:5,class:"bg-white rounded-xl border border-gray-200 p-4 flex flex-col h-[28rem]"},Af={class:"flex-1 overflow-y-auto space-y-2 mb-3"},Sf={key:0,class:"text-sm text-gray-500"},Rf={key:1,class:"text-xs text-gray-400"},Of=["disabled"],Tf={key:6,class:"grid grid-cols-3 gap-4"},Pf={class:"col-span-1 bg-white rounded-xl border border-gray-200 divide-y divide-gray-100 max-h-[28rem] overflow-y-auto"},If={key:0,class:"p-4 text-sm text-gray-500"},Nf=["onClick"],kf={class:"text-gray-800 truncate"},Df={class:"text-xs text-gray-400 mt-0.5"},Mf={class:"col-span-2 bg-white rounded-xl border border-gray-200 p-4 max-h-[28rem] overflow-y-auto space-y-2"},Vf={key:0,class:"text-sm text-gray-500"},jf={__name:"TenantDetail",props:{id:{type:String,required:!0}},setup(e){const t=e,n=De(()=>Number(t.id)),s=ne(null),r=ne(""),o=ne("conocimiento"),i=ne([]),a=ne(""),u=ne(30),p=ne(!1);async function f(){const C=await pe.get("/app/umind/tenants");s.value=(C.items||[]).find(l=>String(l.ID)===t.id)||null}async function h(){const C=await pe.get(`/app/umind/documentos?tenant_id=${t.id}`);i.value=C.items||[]}async function g(){if(a.value.trim()){p.value=!0,r.value="";try{await pe.post("/app/umind/documentos",{tenant_id:n.value,url:a.value.trim(),max_paginas:Number(u.value)||30}),a.value="",await h()}catch(C){r.value=C.message}finally{p.value=!1}}}async function v(C){confirm("¿Eliminar esta fuente y sus fragmentos indexados?")&&(await pe.del(`/app/umind/documentos/${C}`),await h())}const S=De(()=>C=>({listo:"bg-green-100 text-green-700",procesando:"bg-amber-100 text-amber-700",pendiente:"bg-gray-100 text-gray-500",error:"bg-red-100 text-red-700"})[C]||"bg-gray-100 text-gray-500"),b=ne([]),$=ne([]),R=ne(null);async function N(){const C=await pe.get(`/app/umind/sesiones?tenant_id=${t.id}`);b.value=C.items||[]}async function M(C){R.value=C;const l=await pe.get(`/app/umind/historial?tenant_id=${t.id}&session_id=${C}`);$.value=l.items||[]}const D=ne([]),q=ne(!1),oe=ne(null),L=ne(Ie());function Ie(){return{nombre:"",descripcion:"",url:"",auth_header_nombre:"",auth_header_valor:"",tocarAuth:!1,parametros:[],activa:!0}}async function je(){const C=await pe.get(`/app/umind/tools?tenant_id=${t.id}`);D.value=C.items||[]}function Le(){oe.value=null,L.value=Ie(),q.value=!0}function ze(C){oe.value=C;let l=[];try{l=JSON.parse(C.parametros_json||"[]")||[]}catch{l=[]}L.value={nombre:C.nombre,descripcion:C.descripcion,url:C.url,auth_header_nombre:C.auth_header_nombre,auth_header_valor:"",tocarAuth:!1,parametros:l,activa:C.activa},q.value=!0}function at(){L.value.parametros.push({nombre:"",tipo:"string",descripcion:"",requerido:!1})}function Ue(C){L.value.parametros.splice(C,1)}async function Pt(){const C={tenant_id:n.value,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&&(C.auth_header_valor=L.value.auth_header_valor);try{oe.value?await pe.put(`/app/umind/tools/${oe.value.ID}`,C):await pe.post("/app/umind/tools",C),q.value=!1,await je()}catch(l){r.value=l.message}}async function wt(C){confirm(`¿Eliminar la tool "${C.nombre}"?`)&&(await pe.del(`/app/umind/tools/${C.ID}`),await je())}const ae=ne([]),z=ne(!1),H=ne(Fe());function Fe(){return{tipo:"telegram",bot_token:"",phone_number_id:"",access_token:"",app_secret:"",verify_token:""}}async function Ne(){const C=await pe.get(`/app/umind/canales?tenant_id=${t.id}`);ae.value=C.items||[]}function He(){H.value=Fe(),z.value=!0}async function we(){const C=H.value.tipo==="telegram"?{bot_token:H.value.bot_token}:{phone_number_id:H.value.phone_number_id,access_token:H.value.access_token,app_secret:H.value.app_secret,verify_token:H.value.verify_token};try{await pe.post("/app/umind/canales",{tenant_id:n.value,tipo:H.value.tipo,credenciales:C,activo:!0}),z.value=!1,await Ne()}catch(l){r.value=l.message}}async function Et(C){await pe.put(`/app/umind/canales/${C.ID}`,{activo:!C.activo,credenciales:{}}),await Ne()}async function Ct(C){confirm(`¿Eliminar el canal ${C.tipo}?`)&&(await pe.del(`/app/umind/canales/${C.ID}`),await Ne())}const ut=`staff-preview-${Math.random().toString(36).slice(2)}`,ve=ne([]),x=ne(""),I=ne(!1);async function P(){const C=x.value.trim();if(!(!C||I.value)){x.value="",ve.value.push({role:"user",content:C}),I.value=!0;try{const l=await pe.post("/app/umind/chat",{tenant_id:n.value,session_id:ut,mensaje:C});ve.value.push({role:"assistant",content:l.respuesta})}catch(l){ve.value.push({role:"assistant",content:`⚠️ ${l.message}`})}finally{I.value=!1}}}const V=[["conocimiento","Base de conocimiento"],["herramientas","Herramientas"],["canales","Canales"],["chat","Chat de prueba"],["conversaciones","Conversaciones"]];return er(async()=>{try{await Promise.all([f(),h(),N(),je(),Ne()])}catch(C){r.value=C.message}}),(C,l)=>{const d=Un("router-link");return j(),F("div",null,[_e(d,{to:"/",class:"text-sm text-gray-500 hover:text-gray-700"},{default:es(()=>[...l[20]||(l[20]=[Be("← Tenants",-1)])]),_:1}),s.value?(j(),F("div",xc,[m("h1",wc,Q(s.value.nombre),1),m("p",Ec,[l[21]||(l[21]=Be(" site_key: ",-1)),m("code",Cc,Q(s.value.site_key),1)])])):ue("",!0),r.value?(j(),F("p",Ac,Q(r.value),1)):ue("",!0),m("div",Sc,[(j(),F(he,null,et(V,([c,y])=>m("button",{key:c,class:tt(["pb-2 border-b-2 whitespace-nowrap",o.value===c?"border-brand text-brand font-medium":"border-transparent text-gray-500"]),onClick:w=>o.value=c},Q(y),11,Rc)),64))]),o.value==="conocimiento"?(j(),F("div",Oc,[m("form",{class:"flex gap-2 mb-4",onSubmit:Rt(g,["prevent"])},[ie(m("input",{"onUpdate:modelValue":l[0]||(l[0]=c=>a.value=c),type:"url",placeholder:"https://ejemplo.com",required:"",class:"flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,a.value]]),ie(m("input",{"onUpdate:modelValue":l[1]||(l[1]=c=>u.value=c),type:"number",min:"1",max:"200",class:"w-24 border border-gray-300 rounded-lg px-3 py-2 text-sm",title:"Máximo de páginas a crawlear"},null,512),[[me,u.value]]),m("button",{type:"submit",disabled:p.value,class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg disabled:opacity-50"},Q(p.value?"Agregando...":"Crawlear sitio"),9,Tc)],32),m("div",Pc,[i.value.length===0?(j(),F("div",Ic,"Sin fuentes todavía.")):ue("",!0),(j(!0),F(he,null,et(i.value,c=>(j(),F("div",{key:c.ID,class:"p-4 flex items-center justify-between"},[m("div",null,[m("div",Nc,Q(c.origen),1),m("div",kc,[m("span",{class:tt(["px-1.5 py-0.5 rounded",S.value(c.estado)])},Q(c.estado),3),c.total_chunks?(j(),F("span",Dc," · "+Q(c.total_chunks)+" fragmentos",1)):ue("",!0),c.error?(j(),F("span",Mc," · "+Q(c.error),1)):ue("",!0)])]),m("button",{class:"text-red-500 hover:text-red-700 text-sm",onClick:y=>v(c.ID)},"Eliminar",8,Vc)]))),128))])])):o.value==="herramientas"?(j(),F("div",jc,[m("div",{class:"flex justify-between items-center mb-4"},[l[22]||(l[22]=m("p",{class:"text-xs text-gray-500"},"Máximo 10 tools activas por tenant.",-1)),m("button",{class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg",onClick:Le}," + Nueva tool ")]),m("div",Lc,[D.value.length===0?(j(),F("div",Uc,"Sin tools custom todavía.")):ue("",!0),(j(!0),F(he,null,et(D.value,c=>(j(),F("div",{key:c.ID,class:"p-4 flex items-center justify-between"},[m("div",null,[m("div",Fc,Q(c.nombre),1),m("div",Hc,Q(c.descripcion),1),m("div",Bc,[Be(Q(c.url)+" ",1),c.auth_configurado?(j(),F("span",$c,"· auth configurada")):ue("",!0),c.activa?ue("",!0):(j(),F("span",Kc,"· inactiva"))])]),m("div",Gc,[m("button",{class:"text-gray-500 hover:text-gray-800",onClick:y=>ze(c)},"Editar",8,Wc),m("button",{class:"text-red-500 hover:text-red-700",onClick:y=>wt(c)},"Eliminar",8,qc)])]))),128))]),q.value?(j(),F("div",{key:0,class:"fixed inset-0 bg-black/30 flex items-center justify-center p-4 z-50",onClick:l[10]||(l[10]=Rt(c=>q.value=!1,["self"]))},[m("div",zc,[m("h2",Jc,Q(oe.value?"Editar tool":"Nueva tool"),1),m("form",{class:"space-y-3",onSubmit:Rt(Pt,["prevent"])},[m("div",null,[l[23]||(l[23]=m("label",{class:"text-xs text-gray-500"},"Nombre (identificador, ej: consultar_stock)",-1)),ie(m("input",{"onUpdate:modelValue":l[2]||(l[2]=c=>L.value.nombre=c),required:"",pattern:"[a-z][a-z0-9_]{2,63}",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono"},null,512),[[me,L.value.nombre]])]),m("div",null,[l[24]||(l[24]=m("label",{class:"text-xs text-gray-500"},"Descripción (esto lo lee el modelo para decidir cuándo usarla)",-1)),ie(m("textarea",{"onUpdate:modelValue":l[3]||(l[3]=c=>L.value.descripcion=c),rows:"2",required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,L.value.descripcion]])]),m("div",null,[l[25]||(l[25]=m("label",{class:"text-xs text-gray-500"},"URL del webhook (https)",-1)),ie(m("input",{"onUpdate:modelValue":l[4]||(l[4]=c=>L.value.url=c),type:"url",required:"",placeholder:"https://...",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,L.value.url]])]),m("div",Qc,[m("div",{class:"flex items-center justify-between"},[l[26]||(l[26]=m("label",{class:"text-xs text-gray-500"},"Parámetros que completa el modelo",-1)),m("button",{type:"button",class:"text-xs text-brand",onClick:at},"+ agregar")]),(j(!0),F(he,null,et(L.value.parametros,(c,y)=>(j(),F("div",{key:y,class:"flex gap-2 items-center"},[ie(m("input",{"onUpdate:modelValue":w=>c.nombre=w,placeholder:"nombre",class:"flex-1 border border-gray-300 rounded px-2 py-1 text-xs font-mono"},null,8,Yc),[[me,c.nombre]]),ie(m("select",{"onUpdate:modelValue":w=>c.tipo=w,class:"border border-gray-300 rounded px-2 py-1 text-xs"},[...l[27]||(l[27]=[m("option",{value:"string"},"string",-1),m("option",{value:"number"},"number",-1),m("option",{value:"boolean"},"boolean",-1)])],8,Xc),[[ks,c.tipo]]),ie(m("input",{"onUpdate:modelValue":w=>c.descripcion=w,placeholder:"descripción",class:"flex-1 border border-gray-300 rounded px-2 py-1 text-xs"},null,8,Zc),[[me,c.descripcion]]),m("label",ef,[ie(m("input",{"onUpdate:modelValue":w=>c.requerido=w,type:"checkbox"},null,8,tf),[[Dn,c.requerido]]),l[28]||(l[28]=Be(" req. ",-1))]),m("button",{type:"button",class:"text-red-400 text-xs",onClick:w=>Ue(y)},"✕",8,nf)]))),128)),L.value.parametros.length===0?(j(),F("p",sf,"Sin parámetros.")):ue("",!0)]),m("div",rf,[l[29]||(l[29]=m("label",{class:"text-xs text-gray-500"},"Autenticación saliente (opcional)",-1)),ie(m("input",{"onUpdate:modelValue":l[5]||(l[5]=c=>L.value.auth_header_nombre=c),placeholder:"Nombre del header, ej: Authorization",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,L.value.auth_header_nombre]]),m("label",of,[ie(m("input",{"onUpdate:modelValue":l[6]||(l[6]=c=>L.value.tocarAuth=c),type:"checkbox"},null,512),[[Dn,L.value.tocarAuth]]),Be(" "+Q(oe.value?"Cambiar el valor del secreto":"Configurar valor"),1)]),L.value.tocarAuth?ie((j(),F("input",{key:0,"onUpdate:modelValue":l[7]||(l[7]=c=>L.value.auth_header_valor=c),type:"password",placeholder:"Valor del header (ej: Bearer xxxx)",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512)),[[me,L.value.auth_header_valor]]):ue("",!0)]),m("label",lf,[ie(m("input",{"onUpdate:modelValue":l[8]||(l[8]=c=>L.value.activa=c),type:"checkbox"},null,512),[[Dn,L.value.activa]]),l[30]||(l[30]=Be(" Activa ",-1))]),m("div",af,[m("button",{type:"button",class:"px-4 py-2 text-sm text-gray-500",onClick:l[9]||(l[9]=c=>q.value=!1)},"Cancelar"),l[31]||(l[31]=m("button",{type:"submit",class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg"},"Guardar",-1))])],32)])])):ue("",!0)])):o.value==="canales"?(j(),F("div",uf,[m("div",{class:"flex justify-end mb-4"},[m("button",{class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg",onClick:He}," + Nuevo canal ")]),m("div",cf,[ae.value.length===0?(j(),F("div",ff,"Sin canales configurados.")):ue("",!0),(j(!0),F(he,null,et(ae.value,c=>(j(),F("div",{key:c.ID,class:"p-4"},[m("div",df,[m("div",null,[m("span",pf,Q(c.tipo),1),m("span",{class:tt(["ml-2 px-1.5 py-0.5 rounded text-xs",c.activo?"bg-green-100 text-green-700":"bg-gray-100 text-gray-500"])},Q(c.activo?"activo":"inactivo"),3)]),m("div",hf,[m("button",{class:"text-gray-500 hover:text-gray-800",onClick:y=>Et(c)},Q(c.activo?"Desactivar":"Activar"),9,gf),m("button",{class:"text-red-500 hover:text-red-700",onClick:y=>Ct(c)},"Eliminar",8,mf)])]),m("p",vf,[l[32]||(l[32]=Be(" Webhook: ",-1)),m("code",yf,Q(c.webhook_url),1)]),c.tipo==="whatsapp"?(j(),F("p",bf,' Registrá esta URL como "Callback URL" en Meta for Developers → WhatsApp → Configuration, con el mismo verify_token que pusiste acá. ')):ue("",!0),c.ultimo_error?(j(),F("p",_f,Q(c.ultimo_error),1)):ue("",!0)]))),128))]),z.value?(j(),F("div",{key:0,class:"fixed inset-0 bg-black/30 flex items-center justify-center p-4 z-50",onClick:l[18]||(l[18]=Rt(c=>z.value=!1,["self"]))},[m("div",xf,[l[41]||(l[41]=m("h2",{class:"font-semibold text-gray-800 mb-4"},"Nuevo canal",-1)),m("form",{class:"space-y-3",onSubmit:Rt(we,["prevent"])},[m("div",null,[l[34]||(l[34]=m("label",{class:"text-xs text-gray-500"},"Tipo",-1)),ie(m("select",{"onUpdate:modelValue":l[11]||(l[11]=c=>H.value.tipo=c),class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},[...l[33]||(l[33]=[m("option",{value:"telegram"},"Telegram",-1),m("option",{value:"whatsapp"},"WhatsApp Business",-1)])],512),[[ks,H.value.tipo]])]),H.value.tipo==="telegram"?(j(),F("div",wf,[l[35]||(l[35]=m("label",{class:"text-xs text-gray-500"},"Bot token (de @BotFather)",-1)),ie(m("input",{"onUpdate:modelValue":l[12]||(l[12]=c=>H.value.bot_token=c),type:"password",required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,H.value.bot_token]])])):(j(),F(he,{key:1},[m("div",null,[l[36]||(l[36]=m("label",{class:"text-xs text-gray-500"},"Phone Number ID",-1)),ie(m("input",{"onUpdate:modelValue":l[13]||(l[13]=c=>H.value.phone_number_id=c),required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,H.value.phone_number_id]])]),m("div",null,[l[37]||(l[37]=m("label",{class:"text-xs text-gray-500"},"Access Token",-1)),ie(m("input",{"onUpdate:modelValue":l[14]||(l[14]=c=>H.value.access_token=c),type:"password",required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,H.value.access_token]])]),m("div",null,[l[38]||(l[38]=m("label",{class:"text-xs text-gray-500"},"App Secret",-1)),ie(m("input",{"onUpdate:modelValue":l[15]||(l[15]=c=>H.value.app_secret=c),type:"password",required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,H.value.app_secret]])]),m("div",null,[l[39]||(l[39]=m("label",{class:"text-xs text-gray-500"},"Verify Token (lo inventás vos, lo vas a usar en Meta)",-1)),ie(m("input",{"onUpdate:modelValue":l[16]||(l[16]=c=>H.value.verify_token=c),required:"",class:"w-full border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,H.value.verify_token]])])],64)),m("div",Ef,[m("button",{type:"button",class:"px-4 py-2 text-sm text-gray-500",onClick:l[17]||(l[17]=c=>z.value=!1)},"Cancelar"),l[40]||(l[40]=m("button",{type:"submit",class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg"},"Guardar",-1))])],32)])])):ue("",!0)])):o.value==="chat"?(j(),F("div",Cf,[m("div",Af,[ve.value.length===0?(j(),F("p",Sf," Probá el agente tal cual lo va a ver un visitante — usa la misma config de IA y las mismas tools/base de conocimiento del tenant. ")):ue("",!0),(j(!0),F(he,null,et(ve.value,(c,y)=>(j(),F("div",{key:y,class:tt(["max-w-[80%] px-3 py-2 rounded-lg text-sm whitespace-pre-wrap",c.role==="user"?"bg-brand text-white ml-auto":"bg-gray-100 text-gray-800"])},Q(c.content),3))),128)),I.value?(j(),F("p",Rf,"Pensando...")):ue("",!0)]),m("form",{class:"flex gap-2",onSubmit:Rt(P,["prevent"])},[ie(m("input",{"onUpdate:modelValue":l[19]||(l[19]=c=>x.value=c),placeholder:"Escribí un mensaje de prueba...",class:"flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm"},null,512),[[me,x.value]]),m("button",{type:"submit",disabled:I.value,class:"bg-brand hover:bg-brand-dark text-white text-sm font-medium px-4 py-2 rounded-lg disabled:opacity-50"}," Enviar ",8,Of)],32)])):(j(),F("div",Tf,[m("div",Pf,[b.value.length===0?(j(),F("div",If,"Sin conversaciones.")):ue("",!0),(j(!0),F(he,null,et(b.value,c=>(j(),F("button",{key:c.session_id,class:tt(["w-full text-left p-3 hover:bg-gray-50 text-sm",R.value===c.session_id?"bg-gray-50":""]),onClick:y=>M(c.session_id)},[m("div",kf,Q(c.content),1),m("div",Df,Q(c.session_id),1)],10,Nf))),128))]),m("div",Mf,[R.value?ue("",!0):(j(),F("p",Vf,"Elegí una conversación de la izquierda.")),(j(!0),F(he,null,et($.value,c=>(j(),F("div",{key:c.ID,class:tt(["max-w-[80%] px-3 py-2 rounded-lg text-sm",c.role==="user"?"bg-brand text-white ml-auto":"bg-gray-100 text-gray-800"])},Q(c.content),3))),128))])]))])}}},Lf=ic({history:Lu("/orchestrator/"),routes:[{path:"/",name:"tenants",component:_c},{path:"/tenants/:id",name:"tenant-detail",component:jf,props:!0}]});Ka(eu).use(Lf).mount("#app");
diff --git a/public/orchestrator/assets/index-CamCOnxy.css b/public/orchestrator/assets/index-CamCOnxy.css
new file mode 100644
index 0000000..1e7051c
--- /dev/null
+++ b/public/orchestrator/assets/index-CamCOnxy.css
@@ -0,0 +1 @@
+*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.inset-0{top:0;right:0;bottom:0;left:0}.z-50{z-index:50}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.flex{display:flex}.grid{display:grid}.h-\[28rem\]{height:28rem}.max-h-\[28rem\]{max-height:28rem}.max-h-\[85vh\]{max-height:85vh}.min-h-screen{min-height:100vh}.w-24{width:6rem}.w-full{width:100%}.max-w-6xl{max-width:72rem}.max-w-\[80\%\]{max-width:80%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-brand{--tw-border-opacity: 1;border-color:rgb(142 176 47 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-black\/30{background-color:#0000004d}.bg-brand{--tw-bg-opacity: 1;background-color:rgb(142 176 47 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-brand{--tw-text-opacity: 1;color:rgb(142 176 47 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:bg-brand-dark:hover{--tw-bg-opacity: 1;background-color:rgb(113 144 38 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:text-brand:hover{--tw-text-opacity: 1;color:rgb(142 176 47 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.hover\:text-red-700:hover{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.disabled\:opacity-50:disabled{opacity:.5}
diff --git a/public/orchestrator/index.html b/public/orchestrator/index.html
new file mode 100644
index 0000000..eb39958
--- /dev/null
+++ b/public/orchestrator/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ uMind — Orquestador
+
+
+
+
+
+
+
diff --git a/rest/controllers/api/umind_canal_webhook_controller.go b/rest/controllers/api/umind_canal_webhook_controller.go
new file mode 100644
index 0000000..19f3a41
--- /dev/null
+++ b/rest/controllers/api/umind_canal_webhook_controller.go
@@ -0,0 +1,140 @@
+package controllers
+
+import (
+ "log"
+ "strings"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/sujit-baniya/fiber-boilerplate/pkg/models"
+ "github.com/sujit-baniya/fiber-boilerplate/pkg/services"
+)
+
+// ─── Telegram ────────────────────────────────────────────────────────────────
+
+type umindTgChat struct {
+ ID int64 `json:"id"`
+}
+
+type umindTgMessage struct {
+ Chat umindTgChat `json:"chat"`
+ Text string `json:"text"`
+}
+
+type umindTgUpdate struct {
+ Message *umindTgMessage `json:"message"`
+}
+
+// UmindTelegramWebhook recibe updates del bot de Telegram de un tenant.
+// Ruta: POST /webhooks/umind-telegram/:webhook_secret
+// El webhook_secret es un identificador nuestro (no el bot token real) —
+// ver el comentario en models.UmindCanal.
+func UmindTelegramWebhook(c *fiber.Ctx) error {
+ secret := c.Params("webhook_secret")
+ canal, err := models.GetUmindCanalByWebhookSecret("telegram", secret)
+ if err != nil {
+ return c.SendStatus(fiber.StatusOK) // siempre 200 a Telegram, aunque no matchee
+ }
+
+ var update umindTgUpdate
+ if err := c.BodyParser(&update); err != nil || update.Message == nil {
+ return c.SendStatus(fiber.StatusOK)
+ }
+ texto := strings.TrimSpace(update.Message.Text)
+ if texto == "" {
+ return c.SendStatus(fiber.StatusOK)
+ }
+
+ if err := services.ProcesarMensajeTelegramUmind(canal, update.Message.Chat.ID, texto); err != nil {
+ log.Printf("[UMIND_TELEGRAM] canal %d: %v", canal.ID, err)
+ }
+ return c.SendStatus(fiber.StatusOK)
+}
+
+// ─── WhatsApp ────────────────────────────────────────────────────────────────
+
+type umindWaMessage struct {
+ From string `json:"from"`
+ Type string `json:"type"`
+ Text struct {
+ Body string `json:"body"`
+ } `json:"text"`
+}
+
+type umindWaValue struct {
+ Metadata struct {
+ PhoneNumberID string `json:"phone_number_id"`
+ } `json:"metadata"`
+ Messages []umindWaMessage `json:"messages"`
+}
+
+type umindWaChange struct {
+ Value umindWaValue `json:"value"`
+}
+
+type umindWaEntry struct {
+ Changes []umindWaChange `json:"changes"`
+}
+
+type umindWaPayload struct {
+ Entry []umindWaEntry `json:"entry"`
+}
+
+// UmindWhatsAppVerify atiende el handshake de verificación que Meta hace al
+// configurar el webhook (hub.mode/hub.verify_token/hub.challenge).
+// Ruta: GET /webhooks/umind-whatsapp/:webhook_secret
+func UmindWhatsAppVerify(c *fiber.Ctx) error {
+ secret := c.Params("webhook_secret")
+ canal, err := models.GetUmindCanalByWebhookSecret("whatsapp", secret)
+ if err != nil {
+ return c.SendStatus(fiber.StatusForbidden)
+ }
+ credenciales, err := services.DescifrarCredencialesCanal(canal.CredencialesEnc)
+ if err != nil {
+ return c.SendStatus(fiber.StatusForbidden)
+ }
+
+ if c.Query("hub.mode") != "subscribe" || c.Query("hub.verify_token") != credenciales["verify_token"] || credenciales["verify_token"] == "" {
+ return c.SendStatus(fiber.StatusForbidden)
+ }
+ return c.SendString(c.Query("hub.challenge"))
+}
+
+// UmindWhatsAppWebhook recibe mensajes entrantes de WhatsApp Business Cloud
+// API. La única autenticación real acá es la firma HMAC del body — el
+// webhook_secret en la URL identifica el canal, pero no alcanza solo.
+// Ruta: POST /webhooks/umind-whatsapp/:webhook_secret
+func UmindWhatsAppWebhook(c *fiber.Ctx) error {
+ secret := c.Params("webhook_secret")
+ canal, err := models.GetUmindCanalByWebhookSecret("whatsapp", secret)
+ if err != nil {
+ return c.SendStatus(fiber.StatusOK)
+ }
+ credenciales, err := services.DescifrarCredencialesCanal(canal.CredencialesEnc)
+ if err != nil {
+ log.Printf("[UMIND_WHATSAPP] canal %d: credenciales corruptas: %v", canal.ID, err)
+ return c.SendStatus(fiber.StatusOK)
+ }
+
+ if !services.ValidarFirmaWhatsApp(credenciales["app_secret"], c.Body(), c.Get("X-Hub-Signature-256")) {
+ log.Printf("[UMIND_WHATSAPP] canal %d: firma inválida", canal.ID)
+ return c.SendStatus(fiber.StatusUnauthorized)
+ }
+
+ var payload umindWaPayload
+ if err := c.BodyParser(&payload); err != nil {
+ return c.SendStatus(fiber.StatusOK)
+ }
+ for _, entry := range payload.Entry {
+ for _, change := range entry.Changes {
+ for _, msg := range change.Value.Messages {
+ if msg.Type != "text" || strings.TrimSpace(msg.Text.Body) == "" {
+ continue
+ }
+ if err := services.ProcesarMensajeWhatsAppUmind(canal, msg.From, strings.TrimSpace(msg.Text.Body)); err != nil {
+ log.Printf("[UMIND_WHATSAPP] canal %d: %v", canal.ID, err)
+ }
+ }
+ }
+ }
+ return c.SendStatus(fiber.StatusOK)
+}
diff --git a/rest/controllers/umind_admin_controller.go b/rest/controllers/umind_admin_controller.go
index 7c15105..560ea80 100644
--- a/rest/controllers/umind_admin_controller.go
+++ b/rest/controllers/umind_admin_controller.go
@@ -1,11 +1,14 @@
package controllers
import (
+ "fmt"
"math"
+ "regexp"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
+ "github.com/sujit-baniya/fiber-boilerplate/app"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
@@ -213,3 +216,272 @@ func GetUmindHistorialHandler(c *fiber.Ctx) error {
}
return c.JSON(fiber.Map{"items": items})
}
+
+// ─── Tools custom (webhooks) ───────────────────────────────────────────────
+
+var umindNombreToolRegex = regexp.MustCompile(`^[a-z][a-z0-9_]{2,63}$`)
+
+func GetUmindHerramientasHandler(c *fiber.Ctx) error {
+ tenantID, err := strconv.ParseUint(c.Query("tenant_id"), 10, 64)
+ if err != nil || tenantID == 0 {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant_id requerido"})
+ }
+ items, err := models.GetUmindHerramientasByTenant(uint(tenantID))
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ // No se devuelve el secreto cifrado ni el descifrado — solo si hay uno configurado.
+ out := make([]fiber.Map, len(items))
+ for i, h := range items {
+ out[i] = fiber.Map{
+ "ID": h.ID, "tenant_id": h.TenantID, "nombre": h.Nombre, "descripcion": h.Descripcion,
+ "parametros_json": h.ParametrosJSON, "url": h.URL, "auth_header_nombre": h.AuthHeaderNombre,
+ "auth_configurado": h.AuthHeaderValorEnc != "", "activa": h.Activa,
+ }
+ }
+ return c.JSON(fiber.Map{"items": out})
+}
+
+type umindHerramientaReq struct {
+ TenantID uint `json:"tenant_id"`
+ Nombre string `json:"nombre"`
+ Descripcion string `json:"descripcion"`
+ Parametros []models.UmindHerramientaParametro `json:"parametros"`
+ URL string `json:"url"`
+ AuthHeaderNombre string `json:"auth_header_nombre"`
+ AuthHeaderValor *string `json:"auth_header_valor"` // nil = no tocar (en updates)
+ Activa bool `json:"activa"`
+}
+
+func CreateUmindHerramientaHandler(c *fiber.Ctx) error {
+ var req umindHerramientaReq
+ if err := c.BodyParser(&req); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
+ }
+ if req.TenantID == 0 {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant_id requerido"})
+ }
+ if !umindNombreToolRegex.MatchString(req.Nombre) {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "el nombre debe ser minúsculas/números/guion_bajo, empezar con letra (3-64 caracteres)"})
+ }
+ if !strings.HasPrefix(strings.ToLower(strings.TrimSpace(req.URL)), "https://") {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "la URL debe ser https"})
+ }
+
+ parametrosJSON, err := models.ParametrosToJSON(req.Parametros)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "parametros inválidos"})
+ }
+ var authEnc string
+ if req.AuthHeaderValor != nil && *req.AuthHeaderValor != "" {
+ authEnc, err = services.CifrarSecretoUmind(*req.AuthHeaderValor)
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ }
+
+ h := &models.UmindHerramienta{
+ TenantID: req.TenantID, Nombre: req.Nombre, Descripcion: strings.TrimSpace(req.Descripcion),
+ ParametrosJSON: parametrosJSON, URL: strings.TrimSpace(req.URL),
+ AuthHeaderNombre: strings.TrimSpace(req.AuthHeaderNombre), AuthHeaderValorEnc: authEnc, Activa: true,
+ }
+ if err := models.CreateUmindHerramienta(h); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.Status(fiber.StatusCreated).JSON(fiber.Map{"ok": true, "id": h.ID})
+}
+
+func UpdateUmindHerramientaHandler(c *fiber.Ctx) error {
+ id, err := strconv.ParseUint(c.Params("id"), 10, 64)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
+ }
+ var req umindHerramientaReq
+ if err := c.BodyParser(&req); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
+ }
+ if !umindNombreToolRegex.MatchString(req.Nombre) {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "el nombre debe ser minúsculas/números/guion_bajo, empezar con letra (3-64 caracteres)"})
+ }
+ if !strings.HasPrefix(strings.ToLower(strings.TrimSpace(req.URL)), "https://") {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "la URL debe ser https"})
+ }
+ parametrosJSON, err := models.ParametrosToJSON(req.Parametros)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "parametros inválidos"})
+ }
+
+ updates := map[string]interface{}{
+ "nombre": req.Nombre, "descripcion": strings.TrimSpace(req.Descripcion),
+ "parametros_json": parametrosJSON, "url": strings.TrimSpace(req.URL),
+ "auth_header_nombre": strings.TrimSpace(req.AuthHeaderNombre), "activa": req.Activa,
+ }
+ if req.AuthHeaderValor != nil {
+ if *req.AuthHeaderValor == "" {
+ updates["auth_header_valor_enc"] = ""
+ } else {
+ enc, err := services.CifrarSecretoUmind(*req.AuthHeaderValor)
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ updates["auth_header_valor_enc"] = enc
+ }
+ }
+ if err := models.UpdateUmindHerramienta(uint(id), updates); err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.JSON(fiber.Map{"ok": true})
+}
+
+func DeleteUmindHerramientaHandler(c *fiber.Ctx) error {
+ id, err := strconv.ParseUint(c.Params("id"), 10, 64)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
+ }
+ if err := models.DeleteUmindHerramienta(uint(id)); err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.JSON(fiber.Map{"ok": true})
+}
+
+// ─── Canales (Telegram / WhatsApp) ─────────────────────────────────────────
+
+func GetUmindCanalesHandler(c *fiber.Ctx) error {
+ tenantID, err := strconv.ParseUint(c.Query("tenant_id"), 10, 64)
+ if err != nil || tenantID == 0 {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant_id requerido"})
+ }
+ items, err := models.GetUmindCanalesByTenant(uint(tenantID))
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ out := make([]fiber.Map, len(items))
+ for i, canal := range items {
+ webhookURL := ""
+ if canal.Tipo == "telegram" {
+ webhookURL = fmt.Sprintf("%s/webhooks/umind-telegram/%s", app.Http.Server.Url, canal.WebhookSecret)
+ } else if canal.Tipo == "whatsapp" {
+ webhookURL = fmt.Sprintf("%s/webhooks/umind-whatsapp/%s", app.Http.Server.Url, canal.WebhookSecret)
+ }
+ out[i] = fiber.Map{
+ "ID": canal.ID, "tenant_id": canal.TenantID, "tipo": canal.Tipo, "activo": canal.Activo,
+ "webhook_url": webhookURL, "ultimo_error": canal.UltimoError,
+ }
+ }
+ return c.JSON(fiber.Map{"items": out})
+}
+
+type umindCanalReq struct {
+ TenantID uint `json:"tenant_id"`
+ Tipo string `json:"tipo"`
+ Credenciales map[string]string `json:"credenciales"`
+ Activo bool `json:"activo"`
+}
+
+func CreateUmindCanalHandler(c *fiber.Ctx) error {
+ var req umindCanalReq
+ if err := c.BodyParser(&req); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
+ }
+ if req.TenantID == 0 {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant_id requerido"})
+ }
+ switch req.Tipo {
+ case "telegram":
+ if strings.TrimSpace(req.Credenciales["bot_token"]) == "" {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "bot_token requerido"})
+ }
+ case "whatsapp":
+ for _, k := range []string{"phone_number_id", "access_token", "app_secret", "verify_token"} {
+ if strings.TrimSpace(req.Credenciales[k]) == "" {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": k + " requerido"})
+ }
+ }
+ default:
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tipo debe ser telegram o whatsapp"})
+ }
+
+ credencialesEnc, err := services.CifrarCredencialesCanal(req.Credenciales)
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ canal := &models.UmindCanal{TenantID: req.TenantID, Tipo: req.Tipo, Activo: true, CredencialesEnc: credencialesEnc}
+ if err := models.CreateUmindCanal(canal); err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+
+ if req.Tipo == "telegram" {
+ webhookURL := fmt.Sprintf("%s/webhooks/umind-telegram/%s", app.Http.Server.Url, canal.WebhookSecret)
+ if err := services.RegistrarWebhookTelegram(req.Credenciales["bot_token"], webhookURL); err != nil {
+ models.UpdateUmindCanal(canal.ID, map[string]interface{}{"ultimo_error": err.Error()})
+ }
+ }
+ return c.Status(fiber.StatusCreated).JSON(fiber.Map{"ok": true, "id": canal.ID, "webhook_secret": canal.WebhookSecret})
+}
+
+func UpdateUmindCanalHandler(c *fiber.Ctx) error {
+ id, err := strconv.ParseUint(c.Params("id"), 10, 64)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
+ }
+ var req umindCanalReq
+ if err := c.BodyParser(&req); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
+ }
+ updates := map[string]interface{}{"activo": req.Activo}
+ if len(req.Credenciales) > 0 {
+ enc, err := services.CifrarCredencialesCanal(req.Credenciales)
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ updates["credenciales_enc"] = enc
+ updates["ultimo_error"] = ""
+ }
+ if err := models.UpdateUmindCanal(uint(id), updates); err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.JSON(fiber.Map{"ok": true})
+}
+
+func DeleteUmindCanalHandler(c *fiber.Ctx) error {
+ id, err := strconv.ParseUint(c.Params("id"), 10, 64)
+ if err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"})
+ }
+ if err := models.DeleteUmindCanal(uint(id)); err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.JSON(fiber.Map{"ok": true})
+}
+
+// ─── Chat de prueba ─────────────────────────────────────────────────────────
+
+// UmindChatPruebaHandler deja que el staff pruebe el agente de un tenant
+// directo desde el panel, sin pasar por site_key/dominio (ya está gateado
+// por la sesión con la que se llega acá).
+func UmindChatPruebaHandler(c *fiber.Ctx) error {
+ var req struct {
+ TenantID uint `json:"tenant_id"`
+ SessionID string `json:"session_id"`
+ Mensaje string `json:"mensaje"`
+ }
+ if err := c.BodyParser(&req); err != nil {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"})
+ }
+ if strings.TrimSpace(req.Mensaje) == "" {
+ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "mensaje requerido"})
+ }
+ tenant, err := models.GetUmindTenantByID(req.TenantID)
+ if err != nil {
+ return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "tenant no encontrado"})
+ }
+ sessionID := strings.TrimSpace(req.SessionID)
+ if sessionID == "" {
+ sessionID = "staff-preview:" + strconv.FormatUint(uint64(extraerUserID(c)), 10)
+ }
+ respuesta, err := services.ProcessWidgetMessage(tenant, sessionID, strings.TrimSpace(req.Mensaje))
+ if err != nil {
+ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
+ }
+ return c.JSON(fiber.Map{"session_id": sessionID, "respuesta": respuesta})
+}
diff --git a/rest/routes/publicas.go b/rest/routes/publicas.go
index b1b0f79..7a86608 100755
--- a/rest/routes/publicas.go
+++ b/rest/routes/publicas.go
@@ -1,6 +1,8 @@
package routes
import (
+ "time"
+
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/rest/controllers"
apiControllers "github.com/sujit-baniya/fiber-boilerplate/rest/controllers/api"
@@ -101,9 +103,20 @@ func RutasPublicas(web fiber.Router) {
// Público por diseño (lo llama el navegador del visitante de un sitio de
// terceros) — la protección es site_key + validación de dominio, no
// sesión. Excluido de AuthApi() por vivir fuera del grupo /api.
+ // middlewares.Limit por IP: cada mensaje dispara una llamada al LLM del
+ // tenant, sin límite era gasto libre para cualquiera con la site_key.
+ umindMsgLimit := middlewares.Limit(20, 1*time.Minute)
web.Get("/widget/umind.js", apiControllers.UmindWidgetScript)
widget := web.Group("/widget/:site_key")
widget.Options("*", middlewares.UmindWidgetCORS)
widget.Get("/init", middlewares.AuthUmindWidget, apiControllers.UmindWidgetInit)
- widget.Post("/mensaje", middlewares.AuthUmindWidget, apiControllers.UmindWidgetMensaje)
+ widget.Post("/mensaje", umindMsgLimit, middlewares.AuthUmindWidget, apiControllers.UmindWidgetMensaje)
+
+ // ─── uMind: canales adicionales (Telegram, WhatsApp) ──────────────────────
+ // Igual que el widget: público por diseño, la autenticación real es
+ // específica de cada proveedor (firma de WhatsApp; Telegram no firma, el
+ // webhook_secret en la URL es lo único que lo protege).
+ web.Post("/webhooks/umind-telegram/:webhook_secret", umindMsgLimit, apiControllers.UmindTelegramWebhook)
+ web.Get("/webhooks/umind-whatsapp/:webhook_secret", apiControllers.UmindWhatsAppVerify)
+ web.Post("/webhooks/umind-whatsapp/:webhook_secret", umindMsgLimit, apiControllers.UmindWhatsAppWebhook)
}
diff --git a/rest/routes/user.go b/rest/routes/user.go
index a7148aa..f3e2930 100755
--- a/rest/routes/user.go
+++ b/rest/routes/user.go
@@ -365,6 +365,25 @@ func UserRoutes(app fiber.Router) {
protected.Delete("/umind/documentos/:id", middlewares.SoloAdmin, controllers.DeleteUmindDocumentoHandler)
protected.Get("/umind/sesiones", controllers.GetUmindSesionesHandler)
protected.Get("/umind/historial", controllers.GetUmindHistorialHandler)
+ protected.Get("/umind/tools", controllers.GetUmindHerramientasHandler)
+ protected.Post("/umind/tools", middlewares.SoloAdmin, controllers.CreateUmindHerramientaHandler)
+ protected.Put("/umind/tools/:id", middlewares.SoloAdmin, controllers.UpdateUmindHerramientaHandler)
+ protected.Delete("/umind/tools/:id", middlewares.SoloAdmin, controllers.DeleteUmindHerramientaHandler)
+ protected.Get("/umind/canales", controllers.GetUmindCanalesHandler)
+ protected.Post("/umind/canales", middlewares.SoloAdmin, controllers.CreateUmindCanalHandler)
+ protected.Put("/umind/canales/:id", middlewares.SoloAdmin, controllers.UpdateUmindCanalHandler)
+ protected.Delete("/umind/canales/:id", middlewares.SoloAdmin, controllers.DeleteUmindCanalHandler)
+ protected.Post("/umind/chat", controllers.UmindChatPruebaHandler)
+
+ // ─── uMind Orquestador (SPA Vue) ────────────────────────────────────────────
+ // Estáticos reales (JS/CSS del build) ya los sirve el Static("/") general
+ // registrado en config.LoadStatic — esto es solo el fallback para las rutas
+ // del lado del cliente (vue-router en modo history), protegido con sesión.
+ orchestratorFallback := func(c *fiber.Ctx) error {
+ return c.SendFile("./public/orchestrator/index.html")
+ }
+ app.Get("/orchestrator", middlewares.AuthWeb(), orchestratorFallback)
+ app.Get("/orchestrator/*", middlewares.AuthWeb(), orchestratorFallback)
// ─── OSS API (Alibaba Cloud + S3/MinIO) ────────────────────────────────────
protected.Get("/oss-api", middlewares.MenuMiddleware, controllers.OssApiIndex)