agentix-cli 0.103.3 → 0.104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{board-dashboard-IRMCGCU5.js → board-dashboard-5EPKRDEW.js} +404 -215
- package/dist/board-dashboard-5EPKRDEW.js.map +1 -0
- package/dist/{chunk-SOTHC2VI.js → chunk-IO74N5DB.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-4WUNHCTC.js → program-SAEPPSSW.js} +4 -4
- package/package.json +1 -1
- package/dist/board-dashboard-IRMCGCU5.js.map +0 -1
- /package/dist/{chunk-SOTHC2VI.js.map → chunk-IO74N5DB.js.map} +0 -0
- /package/dist/{program-4WUNHCTC.js.map → program-SAEPPSSW.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as A,b as mr,c as fr,d as hr,e as gr,f as _e,g as xr,h as vr,i as Mt,k as br,n as yr,o as wr,p as kr,q as _r,r as Sr,v as Er,w as Tr,x as Cr,y as Ir,z as Mr}from"./chunk-ZBKKOUNJ.js";import{a as Ar}from"./chunk-UVMCAZL7.js";import{a as ur}from"./chunk-QAIYUMHW.js";import{a as At,b as z,c as M,h as ve,i as Ct,j as re,k as K,l as It,m as cr,n as dr,o as pr}from"./chunk-N7HKIMMR.js";import{a as lr}from"./chunk-2NYP4OQU.js";import{a as ce,b as ir}from"./chunk-JWDJMFU6.js";import{$a as sr,A as bt,B as zn,E as qn,F as Fn,Fa as er,G as Un,Ha as Ne,Ma as tr,N as U,O as Wn,Oa as De,P as Gn,Pa as kt,Qa as _t,Ra as St,Sa as Et,Ta as ar,Ua as nr,Va as rr,Wa as Tt,Ya as or,a as In,c as mt,d as da,e as Mn,i as ft,l as Xe,n as Ln,ta as Vn,va as Yn,w as gt,wa as Qn,x as Nn,xa as Zn,y as xt,z as vt}from"./chunk-NWNVHL57.js";import"./chunk-GTJIKXDB.js";import{g as An,h as Cn}from"./chunk-25RQQ55U.js";import{a as Bn,b as N,c as Xn,d as Kn,h as Jn}from"./chunk-DG5I6PPM.js";import{p as Rn,t as $n}from"./chunk-S2GAEH2F.js";import"./chunk-IOPAWHKW.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Pn,e as pa}from"./chunk-ACFQBLPX.js";import{g as ht}from"./chunk-LQE73AZR.js";import{b as jn,c as On}from"./chunk-2D3RYIDU.js";import{m as Dn,n as yt,o as wt,q as Hn}from"./chunk-E5OV6RTG.js";import{a as yn,f as wn,g as la,h as ca,l as kn,m as _n,n as Sn,u as dt,v as pt,w as ut,x as le,y as Tn}from"./chunk-FZ7VHFL5.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-BEFKOHRC.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-MVLNVMWI.js";import{a as En}from"./chunk-OLUAEBHJ.js";import"./chunk-XHUOWYNY.js";import"./chunk-76KJXOEV.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as bn}from"./chunk-Q57GZPDA.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-HE4PDESB.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{G as hn,J as
|
|
1
|
+
import{a as A,b as mr,c as fr,d as hr,e as gr,f as _e,g as xr,h as vr,i as Mt,k as br,n as yr,o as wr,p as kr,q as _r,r as Sr,v as Er,w as Tr,x as Cr,y as Ir,z as Mr}from"./chunk-ZBKKOUNJ.js";import{a as Ar}from"./chunk-UVMCAZL7.js";import{a as ur}from"./chunk-QAIYUMHW.js";import{a as At,b as z,c as M,h as ve,i as Ct,j as re,k as K,l as It,m as cr,n as dr,o as pr}from"./chunk-N7HKIMMR.js";import{a as lr}from"./chunk-2NYP4OQU.js";import{a as ce,b as ir}from"./chunk-JWDJMFU6.js";import{$a as sr,A as bt,B as zn,E as qn,F as Fn,Fa as er,G as Un,Ha as Ne,Ma as tr,N as U,O as Wn,Oa as De,P as Gn,Pa as kt,Qa as _t,Ra as St,Sa as Et,Ta as ar,Ua as nr,Va as rr,Wa as Tt,Ya as or,a as In,c as mt,d as da,e as Mn,i as ft,l as Xe,n as Ln,ta as Vn,va as Yn,w as gt,wa as Qn,x as Nn,xa as Zn,y as xt,z as vt}from"./chunk-NWNVHL57.js";import"./chunk-GTJIKXDB.js";import{g as An,h as Cn}from"./chunk-25RQQ55U.js";import{a as Bn,b as N,c as Xn,d as Kn,h as Jn}from"./chunk-DG5I6PPM.js";import{p as Rn,t as $n}from"./chunk-S2GAEH2F.js";import"./chunk-IOPAWHKW.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Pn,e as pa}from"./chunk-ACFQBLPX.js";import{g as ht}from"./chunk-LQE73AZR.js";import{b as jn,c as On}from"./chunk-2D3RYIDU.js";import{m as Dn,n as yt,o as wt,q as Hn}from"./chunk-E5OV6RTG.js";import{a as yn,f as wn,g as la,h as ca,l as kn,m as _n,n as Sn,u as dt,v as pt,w as ut,x as le,y as Tn}from"./chunk-FZ7VHFL5.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-BEFKOHRC.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-MVLNVMWI.js";import{a as En}from"./chunk-OLUAEBHJ.js";import"./chunk-XHUOWYNY.js";import"./chunk-76KJXOEV.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as bn}from"./chunk-Q57GZPDA.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-HE4PDESB.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{G as hn,J as Fl,K as lt,L as gn,N as xn,P as vn,T as ia,a as cn,b as dn,c as Bl,ea as X,ha as ct,r as ot,s as zl,t as oa,u as sa,x as ql}from"./chunk-IA3BC7M3.js";import{a as it,i as fn}from"./chunk-RJ7DASOU.js";import{a as pn,b as st,c as ra,d as un,h as mn}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function ua(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function Lr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:ua(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Se=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Lt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Se(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Rr(t={}){return M({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
2
|
|
|
3
3
|
<div class="bf-head">
|
|
4
4
|
<div>
|
|
@@ -85,7 +85,7 @@ ${Lt(oe.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:Ul,scripts:`<script>${z({decayOf:ua,rankByDecay:Lr})}const ICON = ${JSON.stringify(oe)};${Wl}</script>`})}var Ul=`
|
|
89
89
|
.bf{max-width:1240px;margin:0 auto;padding:22px 24px 48px}
|
|
90
90
|
.bf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
91
91
|
.bf :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
@@ -361,7 +361,7 @@ button.bf-tag.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,transpare
|
|
|
361
361
|
.bf{padding:16px 14px 36px}
|
|
362
362
|
.bf-head{flex-direction:column;gap:14px;align-items:stretch}
|
|
363
363
|
.bf-sync{justify-content:space-between}
|
|
364
|
-
}`,
|
|
364
|
+
}`,Wl=String.raw`
|
|
365
365
|
(function(){
|
|
366
366
|
const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
367
367
|
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
@@ -776,7 +776,7 @@ if(document.querySelector('form :focus'))return;
|
|
|
776
776
|
if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
|
|
777
777
|
refresh();
|
|
778
778
|
},15000);
|
|
779
|
-
})();`;function ma(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),d=r[r.length-1];d&&l.startedAt-d.to<=e?(d.to=Math.max(d.to,c),d.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let d=1;d<r.length;d++){let u=r[d].from-r[d-1].to;u<c&&(c=u,l=d)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function fa(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function $r(t,e=[],a){let{bands:n,gaps:r}=ma(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(v=>l.startedAt>=v.from&&l.startedAt<=v.to);if(c===-1)continue;let d=n[c],u=d.to-d.from||1,m=(l.startedAt-d.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,d)=>fa(l.runs.filter(u=>u.band===d))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as
|
|
779
|
+
})();`;function ma(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),d=r[r.length-1];d&&l.startedAt-d.to<=e?(d.to=Math.max(d.to,c),d.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let d=1;d<r.length;d++){let u=r[d].from-r[d-1].to;u<c&&(c=u,l=d)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function fa(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function $r(t,e=[],a){let{bands:n,gaps:r}=ma(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(v=>l.startedAt>=v.from&&l.startedAt<=v.to);if(c===-1)continue;let d=n[c],u=d.to-d.from||1,m=(l.startedAt-d.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,d)=>fa(l.runs.filter(u=>u.band===d))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Gl}from"crypto";import{readFileSync as Xl,statSync as Kl}from"fs";import{resolve as Jl,dirname as Vl}from"path";import{fileURLToPath as Yl}from"url";var Pr=new Map;function Rt(t){let e=Pr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Vl(Yl(import.meta.url)),r=Jl(n,"web",t),o=Kl(r),s=o.size<8e6?Gl("sha1").update(Xl(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Pr.set(t,a),a}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},$t=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Ql=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],jr={timeline:"Every run on the mesh, from task traces. The axis breaks over silence — quiet stretches are labelled, not drawn.",map:"The fleet as a transit map: projects are lines, agents are stations, work in flight is a train. Live."};function Or(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return M({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
|
|
780
780
|
|
|
781
781
|
<div class="ac-head">
|
|
782
782
|
<div>
|
|
@@ -799,7 +799,7 @@ refresh();
|
|
|
799
799
|
<div class="ac-bar">
|
|
800
800
|
<span class="ac-lbl">Lanes by</span>
|
|
801
801
|
<div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
|
|
802
|
-
${
|
|
802
|
+
${Ql.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${$t(o,13)}${r}</button>`).join("")}
|
|
803
803
|
</div>
|
|
804
804
|
<div class="ac-key">
|
|
805
805
|
<span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
|
|
@@ -819,7 +819,7 @@ refresh();
|
|
|
819
819
|
<div id="ax-fleet-root" data-hours="24" data-src="${Rt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Zl,scripts:`<script>${z({computeBands:ma,packTracks:fa,buildTimeline:$r})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(jr)};${ec}</script>`})}var Zl=`
|
|
823
823
|
.ac{max-width:1440px;margin:0 auto;padding:22px 24px 48px}
|
|
824
824
|
.ac :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
|
|
825
825
|
.ac-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:14px}
|
|
@@ -905,7 +905,7 @@ refresh();
|
|
|
905
905
|
@media (max-width:640px){.ac{padding:16px 16px 32px}.ac-head{flex-direction:column;gap:10px}
|
|
906
906
|
.ac-tools{flex-wrap:wrap;padding-top:0}.ac-map{height:calc(100vh - 250px);margin:0 -16px;
|
|
907
907
|
border-left:none;border-right:none;border-radius:0}}
|
|
908
|
-
`,
|
|
908
|
+
`,ec=String.raw`
|
|
909
909
|
const $=id=>document.getElementById(id);
|
|
910
910
|
const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
911
911
|
const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
|
|
@@ -1024,7 +1024,7 @@ history.replaceState(null,'',u);
|
|
|
1024
1024
|
if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
|
|
1025
1025
|
$('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
|
|
1026
1026
|
show(view);
|
|
1027
|
-
`;function Nr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
1027
|
+
`;function Nr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:tc,scripts:`<script src="${Rt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var tc=`
|
|
1028
1028
|
/* Preload the fonts the redesign's CSS references. Placed in the shell so
|
|
1029
1029
|
* they start fetching while the React bundle is still parsing. */
|
|
1030
1030
|
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
|
|
@@ -1045,11 +1045,11 @@ body { margin: 0; overflow: hidden; }
|
|
|
1045
1045
|
font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1046
1046
|
text-align: center;
|
|
1047
1047
|
}
|
|
1048
|
-
`;import{createServer as
|
|
1048
|
+
`;import{createServer as Fm}from"http";import{appendFileSync as Um,existsSync as Ml,mkdirSync as Wm}from"fs";import{readFile as Gm}from"fs/promises";import{fileURLToPath as Xm}from"url";import{dirname as Km,resolve as at}from"path";Fl();function He(t,e){if(!t)return"absent";let a=Pn(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ee=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function Pt(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Dr(t.headers["sec-fetch-mode"]),n.site=Dr(t.headers["sec-fetch-site"]),n}function Dr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as ac}from"zlib";var nc=[41,121,255],rc=[255,255,255],Hr=new Map;function Be(t){let e=Hr.get(t);return e||(e=sc(t,oc(t)),Hr.set(t,e)),e}function oc(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,c=i*i+l*l<=r*r?rc:nc;a.set(c,o*e+1+s*3)}return a}function sc(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),ha("IHDR",a),ha("IDAT",ac(e)),ha("IEND",Buffer.alloc(0))])}function ha(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(lc(n)),Buffer.concat([a,n,r])}var ic=Array.from({length:256},(t,e)=>{let a=e;for(let n=0;n<8;n++)a=a&1?3988292384^a>>>1:a>>>1;return a>>>0});function lc(t){let e=4294967295;for(let a of t)e=ic[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}ct();ql();var jt=7,cc=["waiting_owner","needs_attention"],dc={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Ot(t,e){let a=t.toLowerCase().split("@")[0],n=dc[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Br(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function zr(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(v=>v.name==="person"),i=v=>({id:v.id,state:v.state,agentId:v.agent_id,text:v.text,channel:v.channel,chatId:v.chat_id,createdAt:v.created_at,updatedAt:v.updated_at,closedAt:v.closed_at??null,question:v.question??null,attentionReason:v.attention_reason??null,evidence:v.evidence??null,where:{label:Ot(v.channel,v.chat_id),url:a.linkFor?.(v.channel,v.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${oa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...oa).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${sa.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
1049
|
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...sa,n-jt*864e5).map(i):[],d=[];try{d=Mt(t,e,50).filter(v=>v.startedAt>=n-jt*864e5)}catch{}let u=new Map;if(s&&d.length){let v=t.prepare(`SELECT l.ref, r.id, r.state, r.evidence FROM request_links l JOIN requests r ON r.id = l.request_id
|
|
1050
|
-
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${d.map(()=>"?").join(",")})`).all(e,...d.map(S=>S.taskId));for(let S of v)u.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=d.map(v=>({...v,where:v.channel?{label:Ot(v.channel,v.chatId??""),url:a.linkFor?.(v.channel,v.chatId??"")??null}:null,request:u.get(v.taskId)??null})),h=new Set(m.map(v=>v.request?.id).filter(Boolean)),k=[...l.filter(v=>!
|
|
1050
|
+
WHERE l.kind = 'run' AND r.person = ? AND l.ref IN (${d.map(()=>"?").join(",")})`).all(e,...d.map(S=>S.taskId));for(let S of v)u.set(S.ref,{id:S.id,state:S.state,evidence:S.evidence??null})}let m=d.map(v=>({...v,where:v.channel?{label:Ot(v.channel,v.chatId??""),url:a.linkFor?.(v.channel,v.chatId??"")??null}:null,request:u.get(v.taskId)??null})),h=new Set(m.map(v=>v.request?.id).filter(Boolean)),k=[...l.filter(v=>!cc.includes(v.state)),...c].filter(v=>!h.has(v.id));return{open:l,recent:c,runs:m,other:k}}ia();var pc=4e3;function qr(t,e,a){return e.agents?.length?[...e.agents]:t.prepare(`SELECT agent_id, MAX(started_at) AS last FROM task_traces
|
|
1051
1051
|
WHERE person = ? AND started_at >= ? AND (channel IS NULL OR channel != 'a2a')
|
|
1052
|
-
GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-jt*864e5).map(r=>r.agent_id)}function Fr(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(lt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=s.get(l),d=c??i.get(l);if(!d)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null};let u=o(d.person??null),m=d.status==="error"||d.status==="timeout",h=c?"working":m&&u==="you"?"blocked":"free",k=u==="you"&&d.channel!=="a2a",v=k&&d.channel;return{agentId:l,state:h,by:u,at:c?d.started_at:d.finished_at??d.started_at,text:k?d.message_preview??null:null,fullText:k&&c&&String(d.original_message??d.message_preview??"").slice(0,
|
|
1052
|
+
GROUP BY agent_id ORDER BY last DESC LIMIT 12`).all(e.id,a-jt*864e5).map(r=>r.agent_id)}function Fr(t,e,a,n){let r=new Set(n.people.filter(l=>l.role==="owner").map(l=>l.id));r.add(lt);let o=l=>l===e?"you":l&&r.has(l)?"owner":"other",s=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status = 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1"),i=t.prepare("SELECT * FROM task_traces WHERE agent_id = ? AND status != 'in-flight' ORDER BY started_at DESC, rowid DESC LIMIT 1");return a.map(l=>{let c=s.get(l),d=c??i.get(l);if(!d)return{agentId:l,state:"free",by:null,at:null,text:null,fullText:null,where:null};let u=o(d.person??null),m=d.status==="error"||d.status==="timeout",h=c?"working":m&&u==="you"?"blocked":"free",k=u==="you"&&d.channel!=="a2a",v=k&&d.channel;return{agentId:l,state:h,by:u,at:c?d.started_at:d.finished_at??d.started_at,text:k?d.message_preview??null:null,fullText:k&&c&&String(d.original_message??d.message_preview??"").slice(0,pc)||null,where:v?{label:Ot(d.channel,d.chat_id??""),url:n.linkFor?.(d.channel,d.chat_id??"")??null}:null}})}function Ur(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Wr(t,e){return!t||e-t>=3e4||t>e}function Nt(t,e){let a="23456789ABCDEFGHJKMNPQRSTUVWXYZ",n=String(t||"").toUpperCase(),r=Math.max(0,Math.min(Number(e)||0,n.length)),o="",s=0;for(let l=0;l<n.length&&o.length<8;l++)a.indexOf(n.charAt(l))<0||(o+=n.charAt(l),l<r&&s++);let i=o.length>4?o.slice(0,4)+"-"+o.slice(4):o;return{value:i,caret:Math.min(s>4?s+1:s,i.length)}}function Gr(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}function Xr(t,e,a,n){return t?e?{text:"Can't reach the server. "+(n?"Showing what was last loaded. ":"")+"Trying again every "+a+" seconds.",retry:!0}:{text:"Offline. Showing what was last loaded; live state needs a connection.",retry:!1}:null}function Kr(t){return String(t??"").replace(/```[\w-]*|`/g,"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^[ \t]*(?:#{1,6}|>+|[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm,"").replace(/\*\*|~~/g,"").replace(/(^|[\s(])\*(\S(?:[^*\n]*\S)?)\*(?=[\s).,;:!?]|$)/gm,"$1$2").replace(/\s+/g," ").trim()}function Jr(t){let e=t.by==="you"?"you":t.by==="owner"?"the owner":t.by?"someone else":null;return t.state==="working"?t.by==="you"?{label:"Working",tone:"work",what:t.text,by:e,hint:"Busy. A new message waits in line until this ends."}:{label:"Working",tone:"work",what:"Busy with someone else's task",by:e,hint:"A message you send now waits in line until this ends."}:t.state==="blocked"?{label:"Blocked",tone:"stuck",what:t.text?"Stopped on: "+t.text:null,by:e,hint:"It stopped before finishing. It needs a person."}:{label:"Free",tone:"free",what:t.by==="you"&&t.text?"Finished: "+t.text:null,by:t.by==="you"?e:null,hint:"Free. Ready for your next message."}}function Vr(t){let e=t.request?t.request.state:"";return e==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:e==="needs_attention"?{label:"Stuck",tone:"stuck"}:t.status==="in-flight"?{label:"Running",tone:"work"}:t.status==="ok"?{label:"Finished",tone:"done"}:t.status==="error"||t.status==="timeout"?{label:"Stopped",tone:"stuck"}:t.status==="canceled"||t.status==="cancelled"?{label:"Stopped",tone:"off"}:{label:String(t.status||"").replace(/[_-]/g," "),tone:"off"}}function Yr(t){return t==="in_progress"?{label:"In progress",tone:"work"}:t==="waiting_owner"?{label:"Waiting on the owner",tone:"wait"}:t==="waiting_other"?{label:"Waiting on another agent",tone:"wait"}:t==="needs_attention"?{label:"Stuck",tone:"stuck"}:t==="done"?{label:"Finished",tone:"done"}:t==="declined"?{label:"Declined",tone:"off"}:t==="dropped"?{label:"Dropped",tone:"off"}:{label:String(t||"").replace(/_/g," "),tone:"off"}}function Qr(t,e){if(!t.length&&!e)return"Nothing sent yet.";let a=t.slice(0,4).map(function(n){return n.state==="working"?n.agentId+(n.by==="you"?" is working on your task.":" is busy with someone else's task."):n.state==="blocked"?n.agentId+" stopped on your task.":n.agentId+" is free."});return t.length>4&&a.push(t.length-4+" more below."),a.join(" ")||"Nothing running now."}var Zr=`
|
|
1053
1053
|
(function () {
|
|
1054
1054
|
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1055
1055
|
var who = document.getElementById('who');
|
|
@@ -1321,7 +1321,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1321
1321
|
.pulse { display: inline-block; width: 12px; height: 12px; margin-right: 10px; border-radius: 50%; border: 3px solid var(--ax-amber-ink); box-sizing: border-box; animation: breathe 2.4s ease-in-out infinite; }
|
|
1322
1322
|
@keyframes breathe { 50% { opacity: 0.35; } }
|
|
1323
1323
|
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
|
|
1324
|
-
`;var
|
|
1324
|
+
`;var uc="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})()</script>";function ga(t){return`<meta charset="utf-8">
|
|
1325
1325
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1326
1326
|
<meta name="theme-color" content="#2979FF">
|
|
1327
1327
|
<meta name="referrer" content="no-referrer">
|
|
@@ -1331,7 +1331,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1331
1331
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1332
1332
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1333
1333
|
<title>${t}</title>
|
|
1334
|
-
${
|
|
1334
|
+
${uc}
|
|
1335
1335
|
<style>${At}${eo}</style>`}function ro(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var oo=`
|
|
1336
1336
|
var CACHE = 'agentx-member-v1';
|
|
1337
1337
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
@@ -1380,7 +1380,7 @@ ${xa("Connecting\u2026",`
|
|
|
1380
1380
|
<section aria-labelledby="h-sent"><h2 id="h-sent">What you sent <span class="n">(last 7 days)</span></h2><ul id="sent" class="rows"></ul></section>
|
|
1381
1381
|
<p id="updated" class="foot"></p>
|
|
1382
1382
|
</main>
|
|
1383
|
-
<script>${z({workState:
|
|
1383
|
+
<script>${z({workState:mc,ageText:fc,connectionNote:Xr,plainPreview:Kr,agentLine:Jr,sentState:Vr,requestState:Yr,summaryLine:Qr})}${Zr}</script>
|
|
1384
1384
|
</body>
|
|
1385
1385
|
</html>`}function lo(){return`<!doctype html>
|
|
1386
1386
|
<html lang="en">
|
|
@@ -1405,7 +1405,7 @@ ${xa("This machine is not paired yet")}
|
|
|
1405
1405
|
<p class="help">No code? Ask the owner to run <code>agentx people invite <you></code>. A code works once, for 10 minutes.</p>
|
|
1406
1406
|
</div>
|
|
1407
1407
|
</main>
|
|
1408
|
-
<script>${z({formatPairInput:Nt})}${
|
|
1408
|
+
<script>${z({formatPairInput:Nt})}${hc}</script>
|
|
1409
1409
|
</body>
|
|
1410
1410
|
</html>`}function co(){return`<!doctype html>
|
|
1411
1411
|
<html lang="en">
|
|
@@ -1420,9 +1420,9 @@ ${xa("This machine is paired")}
|
|
|
1420
1420
|
<p class="help">If they say no, this page asks for a new code.</p>
|
|
1421
1421
|
</div>
|
|
1422
1422
|
</main>
|
|
1423
|
-
<script>${
|
|
1423
|
+
<script>${gc}</script>
|
|
1424
1424
|
</body>
|
|
1425
|
-
</html>`}function
|
|
1425
|
+
</html>`}function mc(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function fc(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min":Math.floor(r/24)+" d "+r%24+" h"}var hc=`
|
|
1426
1426
|
(function () {
|
|
1427
1427
|
var form = document.getElementById('pair-form');
|
|
1428
1428
|
var machine = document.getElementById('machine');
|
|
@@ -1466,7 +1466,7 @@ ${xa("This machine is paired")}
|
|
|
1466
1466
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1467
1467
|
});
|
|
1468
1468
|
})();
|
|
1469
|
-
`,
|
|
1469
|
+
`,gc=`
|
|
1470
1470
|
(function () {
|
|
1471
1471
|
var msg = document.getElementById('msg');
|
|
1472
1472
|
function check() {
|
|
@@ -1477,10 +1477,10 @@ ${xa("This machine is paired")}
|
|
|
1477
1477
|
}
|
|
1478
1478
|
setInterval(check, 5000);
|
|
1479
1479
|
})();
|
|
1480
|
-
`;var Dt="agentx_member",hc=90*86400,gc=new wt,fo=t=>t.replace(/^\[app\]/,"[member]"),xc=new Ee(t=>console.log(fo(t))),po=new WeakMap;function vc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return xc;let e=po.get(t.log);return e||po.set(t.log,e=new Ee(a=>t.log(fo(a)))),e}var uo=null;function Ke(t,e=X){try{return uo=e().people}catch{return uo??t}}async function ho(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new dt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ht(r.root),limiter:r.pairLimiter??gc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",ro());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",oo);if(a==="/member/icon-192.png")return be(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/member/icon-512.png")return be(e,200,"image/png",Be(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let d=await wr(t,i);return d.status===200&&e.setHeader("Set-Cookie",mo(d.token)),d.status===429&&e.setHeader("Retry-After",String(d.retryAfter)),Te(e,d.status,d.body)}let l=_r(bc(t),i,yr(t));if(!l.ok){if(l.status===401){let d=va(t);return vc(r).record(a.slice(0,120),Pt(t,He(ba(t,Dt),o),d?He(d,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",lo()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?be(e,202,"text/html; charset=utf-8",co()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(d=>d.id===l.personId);if(n==="GET"&&a==="/member"){let d=ba(t,Dt);return d&&!va(t)&&e.setHeader("Set-Cookie",mo(d)),be(e,200,"text/html; charset=utf-8",io())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let d=r.db?.()??null;if(!d)return Te(e,503,{error:"the work list needs the database"});let u=(r.now??Date.now)(),m=zr(d,l.personId,{now:u,linkFor:r.linkFor}),h=[];try{let k=qr(d,c??{id:l.personId},u);h=Fr(d,l.personId,k,{people:r.people(),linkFor:r.linkFor})}catch(k){let v=k instanceof Error?k.message:String(k);/no such table/i.test(v)||r.log?.(`[member] agent cards failed: ${v}`)}return Te(e,200,{...m,agents:h})}return Te(e,404,{error:"not found"})}function mo(t){return`${Dt}=${t}; Path=/; Max-Age=${hc}; HttpOnly; Secure; SameSite=Lax`}function bc(t){return va(t)??ba(t,Dt)}function va(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ba(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function be(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return be(t,e,"application/json",JSON.stringify(a))}Dl();var go='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Bt,readFileSync as So,writeFileSync as Eo,rmSync as Lh,mkdirSync as Ec,copyFileSync as Tc,readdirSync as Ac}from"fs";import{resolve as ze}from"path";Hl();function vo(t){let e=ot.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ot.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function Ht(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=ot.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var xo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function bo(t){return Ht(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function yo(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ht((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:xo(t?.chats),senders:xo(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function wo(t){let e=String(t?.id??"");return Ht(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function ko(t){let e=String(t?.id??"");return Ht(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}ct();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function _o(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Ct([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+wc()+cr,css:_c,scripts:`${e}<script>${dr}
|
|
1480
|
+
`;var Dt="agentx_member",xc=90*86400,vc=new wt,fo=t=>t.replace(/^\[app\]/,"[member]"),bc=new Ee(t=>console.log(fo(t))),po=new WeakMap;function yc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return bc;let e=po.get(t.log);return e||po.set(t.log,e=new Ee(a=>t.log(fo(a)))),e}var uo=null;function Ke(t,e=X){try{return uo=e().people}catch{return uo??t}}async function ho(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new dt(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ht(r.root),limiter:r.pairLimiter??vc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",ro());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",oo);if(a==="/member/icon-192.png")return be(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/member/icon-512.png")return be(e,200,"image/png",Be(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let d=await wr(t,i);return d.status===200&&e.setHeader("Set-Cookie",mo(d.token)),d.status===429&&e.setHeader("Retry-After",String(d.retryAfter)),Te(e,d.status,d.body)}let l=_r(wc(t),i,yr(t));if(!l.ok){if(l.status===401){let d=va(t);return yc(r).record(a.slice(0,120),Pt(t,He(ba(t,Dt),o),d?He(d,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",lo()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?be(e,202,"text/html; charset=utf-8",co()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(d=>d.id===l.personId);if(n==="GET"&&a==="/member"){let d=ba(t,Dt);return d&&!va(t)&&e.setHeader("Set-Cookie",mo(d)),be(e,200,"text/html; charset=utf-8",io())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let d=r.db?.()??null;if(!d)return Te(e,503,{error:"the work list needs the database"});let u=(r.now??Date.now)(),m=zr(d,l.personId,{now:u,linkFor:r.linkFor}),h=[];try{let k=qr(d,c??{id:l.personId},u);h=Fr(d,l.personId,k,{people:r.people(),linkFor:r.linkFor})}catch(k){let v=k instanceof Error?k.message:String(k);/no such table/i.test(v)||r.log?.(`[member] agent cards failed: ${v}`)}return Te(e,200,{...m,agents:h})}return Te(e,404,{error:"not found"})}function mo(t){return`${Dt}=${t}; Path=/; Max-Age=${xc}; HttpOnly; Secure; SameSite=Lax`}function wc(t){return va(t)??ba(t,Dt)}function va(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ba(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function be(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return be(t,e,"application/json",JSON.stringify(a))}Bl();var go='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Bt,readFileSync as So,writeFileSync as Eo,rmSync as Ph,mkdirSync as Ac,copyFileSync as Cc,readdirSync as Ic}from"fs";import{resolve as ze}from"path";zl();function vo(t){let e=ot.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ot.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function Ht(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=ot.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var xo=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function bo(t){return Ht(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function yo(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ht((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:xo(t?.chats),senders:xo(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function wo(t){let e=String(t?.id??"");return Ht(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function ko(t){let e=String(t?.id??"");return Ht(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}ct();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function _o(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+Ct([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+_c()+cr,css:Ec,scripts:`${e}<script>${dr}
|
|
1481
1481
|
${pr}
|
|
1482
|
-
${
|
|
1483
|
-
${
|
|
1482
|
+
${kc}
|
|
1483
|
+
${Tc}</script>`})}var kc=`
|
|
1484
1484
|
(function(){
|
|
1485
1485
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1486
1486
|
async function voiceMissing() {
|
|
@@ -1574,8 +1574,8 @@ ${Sc}</script>`})}var yc=`
|
|
|
1574
1574
|
refresh();
|
|
1575
1575
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1576
1576
|
document.addEventListener('ax-config-saved', refresh);
|
|
1577
|
-
})();`;function
|
|
1578
|
-
`:"";return
|
|
1577
|
+
})();`;function _c(){let t=Kn().business?`<button data-tab="business">Business</button>
|
|
1578
|
+
`:"";return Sc.replace("__BUSINESS_TABS__",t)}var Sc=`
|
|
1579
1579
|
<div id="peer-banner" class="peer-banner">
|
|
1580
1580
|
<span class="label">Managing</span>
|
|
1581
1581
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -2234,7 +2234,7 @@ ${Sc}</script>`})}var yc=`
|
|
|
2234
2234
|
<div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
|
|
2235
2235
|
</section>
|
|
2236
2236
|
</main>
|
|
2237
|
-
`,
|
|
2237
|
+
`,Ec=`
|
|
2238
2238
|
|
|
2239
2239
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2240
2240
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2442,7 +2442,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2442
2442
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2443
2443
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2444
2444
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2445
|
-
`,
|
|
2445
|
+
`,Tc=`
|
|
2446
2446
|
const $ = (id) => document.getElementById(id);
|
|
2447
2447
|
let state = null;
|
|
2448
2448
|
|
|
@@ -5326,11 +5326,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5326
5326
|
})();
|
|
5327
5327
|
|
|
5328
5328
|
refresh();
|
|
5329
|
-
`;function To(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_o({peers:a,localToken:n}))}async function Ao(t,e){let a=ka();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Co(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await zc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Cc(t),r={"GET /api/admin/state":()=>Mc(),"POST /api/admin/agents":()=>Oc(n),"PATCH /api/admin/agents":()=>Nc(n),"DELETE /api/admin/agents":()=>Dc(n),"POST /api/admin/agents/access":()=>Lc(n),"POST /api/admin/channels/telegram":()=>Hc(n),"DELETE /api/admin/channels/telegram":()=>cd(n),"POST /api/admin/channels/telegram/toggle":()=>dd(n),"POST /api/admin/crons":()=>pd(n),"DELETE /api/admin/crons":()=>ud(n),"POST /api/admin/config/raw":()=>md(n),"GET /api/admin/tokens":()=>Rc(),"POST /api/admin/tokens":()=>$c(n),"DELETE /api/admin/tokens":()=>Pc(n),"POST /api/admin/agents/test":()=>jc(n),"POST /api/admin/agents/integrations":()=>Xc(n),"DELETE /api/admin/agents/integrations":()=>Kc(n),"PATCH /api/admin/agents/integrations":()=>Jc(n),"PATCH /api/admin/channels/telegram":()=>Bc(n),"POST /api/admin/channels/slack":()=>ad(n),"POST /api/admin/channels/slack/toggle":()=>nd(n),"POST /api/admin/channels/discord":()=>rd(n),"POST /api/admin/channels/discord/toggle":()=>od(n),"POST /api/admin/channels/gitlab":()=>sd(n),"POST /api/admin/channels/gitlab/toggle":()=>id(n),"POST /api/admin/channels/request-status":()=>Tr(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>Td(n),"DELETE /api/admin/actions":()=>Ad(n),"POST /api/admin/actions/run":()=>Cd(n),"GET /api/admin/channels/whatsapp/chats":()=>Je("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Je("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>ld(n),"POST /api/admin/webhooks":()=>Vc(n),"PATCH /api/admin/webhooks":()=>Yc(n),"DELETE /api/admin/webhooks":()=>td(n),"POST /api/admin/whatsapp-triage":()=>bo(n),"POST /api/admin/whatsapp-triage/rules":()=>yo(n),"PATCH /api/admin/whatsapp-triage/rules":()=>wo(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ko(n),"POST /api/admin/mesh/peers":()=>Qc(n),"DELETE /api/admin/mesh/peers":()=>Zc(n),"POST /api/admin/mesh/toggle":()=>ed(n),"GET /api/admin/files":()=>qc(t),"GET /api/admin/files/read":()=>Fc(t),"PUT /api/admin/files":()=>Uc(n),"POST /api/admin/files/skill":()=>Wc(n),"DELETE /api/admin/files/skill":()=>Gc(n),"POST /api/admin/business/orgchart":()=>fd(n),"DELETE /api/admin/business/orgchart":()=>hd(n),"POST /api/admin/business/project":()=>gd(n),"DELETE /api/admin/business/project":()=>bd(n),"POST /api/admin/business/client":()=>xd(n),"DELETE /api/admin/business/client":()=>vd(n),"POST /api/admin/business/contact":()=>yd(n),"DELETE /api/admin/business/contact":()=>wd(n),"POST /api/admin/boards":()=>kd(n),"DELETE /api/admin/boards":()=>_d(n),"POST /api/admin/boards/columns":()=>Sd(n),"DELETE /api/admin/boards/columns":()=>Ed(n),"POST /api/admin/notifications":()=>Md(n),"POST /api/admin/screen":()=>Ld(n),"POST /api/admin/webhooks/triggers":()=>Rd(n),"POST /api/admin/mesh/health":()=>Id(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ue("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ue("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ue("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ue("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ue("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ue("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ue("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ue("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ya(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ya(e,200,i)}catch(n){ya(e,400,{error:n.message||"admin op failed"})}}function ya(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Cc(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function Ic(t){let e=ze(process.cwd(),t);if(!Bt(e))return[];let a=[];for(let n of Ac(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(So(ze(e,n.name),"utf-8")))}catch{}return a}function ka(){let t=ze(process.cwd(),"agentx.json");return Bt(t)?JSON.parse(So(t,"utf-8")):null}function Mc(){let t=ka();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([p,f])=>({id:p,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let b=x.credentials||{},_={};for(let[T,w]of Object.entries(b))typeof w=="string"&&/^[A-Z][A-Z0-9_]*$/.test(w)?_[T]=process.env[w]?"set":"unset":typeof w=="string"&&(_[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:b,credStatus:_,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([p,f])=>({id:p,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([p,f])=>({id:p,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(p=>({id:p.id,source:p.source,agentId:p.agentId,secretEnv:p.secretEnv||"",description:p.description||"",enabled:p.enabled!==!1,triggers:p.triggers&&typeof p.triggers=="object"?p.triggers:{},defaultWorkflow:p.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(p=>({url:p.url,name:p.name,hasToken:!!p.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},k=t.notifications||{},v={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:Rn(k.local),ntfy:Cr(t.channels?.ntfy)},S=[];try{S=Ic(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(p=>({id:p.id,name:p.name,source:p.source||{type:"gitlab",projects:[]},primaryToolLabel:p.primaryToolLabel||"",timeRangeDays:p.timeRangeDays??30,closedWindowDays:p.closedWindowDays??30,columns:Array.isArray(p.columns)?p.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Er(t),whatsappTriage:vo(t),crons:l,webhooks:c,mesh:d,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:v,screen:or(t.screen),actions:S}}function Lc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Rc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function $c(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Pc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function jc(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Oc(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(t?.tier)?t.tier:"claude-code",r=Mo(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ze(process.cwd(),"agents",e),{summary:l}=A(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),d.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Bt(c))try{Ec(i,{recursive:!0}),Eo(c,`# ${a}
|
|
5329
|
+
`;function To(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_o({peers:a,localToken:n}))}async function Ao(t,e){let a=ka();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Co(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Fc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Mc(t),r={"GET /api/admin/state":()=>Rc(),"POST /api/admin/agents":()=>Dc(n),"PATCH /api/admin/agents":()=>Hc(n),"DELETE /api/admin/agents":()=>Bc(n),"POST /api/admin/agents/access":()=>$c(n),"POST /api/admin/channels/telegram":()=>zc(n),"DELETE /api/admin/channels/telegram":()=>pd(n),"POST /api/admin/channels/telegram/toggle":()=>ud(n),"POST /api/admin/crons":()=>md(n),"DELETE /api/admin/crons":()=>fd(n),"POST /api/admin/config/raw":()=>hd(n),"GET /api/admin/tokens":()=>Pc(),"POST /api/admin/tokens":()=>jc(n),"DELETE /api/admin/tokens":()=>Oc(n),"POST /api/admin/agents/test":()=>Nc(n),"POST /api/admin/agents/integrations":()=>Jc(n),"DELETE /api/admin/agents/integrations":()=>Vc(n),"PATCH /api/admin/agents/integrations":()=>Yc(n),"PATCH /api/admin/channels/telegram":()=>qc(n),"POST /api/admin/channels/slack":()=>rd(n),"POST /api/admin/channels/slack/toggle":()=>od(n),"POST /api/admin/channels/discord":()=>sd(n),"POST /api/admin/channels/discord/toggle":()=>id(n),"POST /api/admin/channels/gitlab":()=>ld(n),"POST /api/admin/channels/gitlab/toggle":()=>cd(n),"POST /api/admin/channels/request-status":()=>Tr(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>Cd(n),"DELETE /api/admin/actions":()=>Id(n),"POST /api/admin/actions/run":()=>Md(n),"GET /api/admin/channels/whatsapp/chats":()=>Je("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Je("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>dd(n),"POST /api/admin/webhooks":()=>Qc(n),"PATCH /api/admin/webhooks":()=>Zc(n),"DELETE /api/admin/webhooks":()=>nd(n),"POST /api/admin/whatsapp-triage":()=>bo(n),"POST /api/admin/whatsapp-triage/rules":()=>yo(n),"PATCH /api/admin/whatsapp-triage/rules":()=>wo(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ko(n),"POST /api/admin/mesh/peers":()=>ed(n),"DELETE /api/admin/mesh/peers":()=>td(n),"POST /api/admin/mesh/toggle":()=>ad(n),"GET /api/admin/files":()=>Uc(t),"GET /api/admin/files/read":()=>Wc(t),"PUT /api/admin/files":()=>Gc(n),"POST /api/admin/files/skill":()=>Xc(n),"DELETE /api/admin/files/skill":()=>Kc(n),"POST /api/admin/business/orgchart":()=>gd(n),"DELETE /api/admin/business/orgchart":()=>xd(n),"POST /api/admin/business/project":()=>vd(n),"DELETE /api/admin/business/project":()=>wd(n),"POST /api/admin/business/client":()=>bd(n),"DELETE /api/admin/business/client":()=>yd(n),"POST /api/admin/business/contact":()=>kd(n),"DELETE /api/admin/business/contact":()=>_d(n),"POST /api/admin/boards":()=>Sd(n),"DELETE /api/admin/boards":()=>Ed(n),"POST /api/admin/boards/columns":()=>Td(n),"DELETE /api/admin/boards/columns":()=>Ad(n),"POST /api/admin/notifications":()=>Rd(n),"POST /api/admin/screen":()=>$d(n),"POST /api/admin/webhooks/triggers":()=>Pd(n),"POST /api/admin/mesh/health":()=>Ld(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ue("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ue("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ue("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ue("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ue("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ue("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ue("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ue("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ya(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ya(e,200,i)}catch(n){ya(e,400,{error:n.message||"admin op failed"})}}function ya(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Mc(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function Lc(t){let e=ze(process.cwd(),t);if(!Bt(e))return[];let a=[];for(let n of Ic(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(So(ze(e,n.name),"utf-8")))}catch{}return a}function ka(){let t=ze(process.cwd(),"agentx.json");return Bt(t)?JSON.parse(So(t,"utf-8")):null}function Rc(){let t=ka();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([p,f])=>({id:p,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let b=x.credentials||{},_={};for(let[T,w]of Object.entries(b))typeof w=="string"&&/^[A-Z][A-Z0-9_]*$/.test(w)?_[T]=process.env[w]?"set":"unset":typeof w=="string"&&(_[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:b,credStatus:_,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([p,f])=>({id:p,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([p,f])=>({id:p,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(p=>({id:p.id,source:p.source,agentId:p.agentId,secretEnv:p.secretEnv||"",description:p.description||"",enabled:p.enabled!==!1,triggers:p.triggers&&typeof p.triggers=="object"?p.triggers:{},defaultWorkflow:p.defaultWorkflow||""})):[],d={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(p=>({url:p.url,name:p.name,hasToken:!!p.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},k=t.notifications||{},v={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:Rn(k.local),ntfy:Cr(t.channels?.ntfy)},S=[];try{S=Lc(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(p=>({id:p.id,name:p.name,source:p.source||{type:"gitlab",projects:[]},primaryToolLabel:p.primaryToolLabel||"",timeRangeDays:p.timeRangeDays??30,closedWindowDays:p.closedWindowDays??30,columns:Array.isArray(p.columns)?p.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:Er(t),whatsappTriage:vo(t),crons:l,webhooks:c,mesh:d,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:v,screen:or(t.screen),actions:S}}function $c(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function Pc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function jc(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Oc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Nc(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let d=X();r=d.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=d.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Dc(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(t?.tier)?t.tier:"claude-code",r=Mo(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ze(process.cwd(),"agents",e),{summary:l}=A(d=>{if(d.agents=d.agents||{},d.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),d.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Bt(c))try{Ac(i,{recursive:!0}),Eo(c,`# ${a}
|
|
5330
5330
|
|
|
5331
5331
|
${s||"You are "+a+"."}
|
|
5332
|
-
`)}catch{}return{summary:l}}function Nc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=Mo(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Dc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Hc(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Bc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Je(t){let{url:e,headers:a}=_a(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ue(t,e){let{url:a,headers:n}=_a(),r=await fetch(a+t,{method:"POST",headers:{...n,"Content-Type":"application/json"},body:JSON.stringify(e||{})}),o=await r.text();if(!r.ok)throw new Error(`daemon ${r.status}: ${o.slice(0,200)}`);try{return JSON.parse(o)}catch{return{raw:o}}}async function zc(t,e){try{let{url:a,headers:n}=_a(),r=await fetch(a+e,{headers:n}),o=await r.text();t.writeHead(r.status,{"Content-Type":r.headers.get("content-type")||"image/svg+xml","Cache-Control":"no-store"}),t.end(o)}catch(a){t.writeHead(502,{"Content-Type":"text/plain; charset=utf-8"}),t.end("daemon unreachable: "+(a?.message||"unknown"))}}function _a(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ve(t){let a=ka()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function wa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function qc(t){let e=wa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Fc(t){let e=wa(t,"agent").trim(),a=wa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return kt(Ve(e),a)}function Uc(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=_t(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Wc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=St(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Gc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Et(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Xc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Kc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Jc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(d=>d.kind===a&&d.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Io=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Vc(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!Io.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(d=>d.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Yc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Io.includes(a.source)&&(o.source=a.source),typeof a.agentId=="string"&&a.agentId.trim()){if(!r.agents?.[a.agentId])throw new Error(`Unknown agent "${a.agentId}".`);o.agentId=a.agentId.trim()}return typeof a.secretEnv=="string"&&(o.secretEnv=a.secretEnv.trim()||void 0),typeof a.description=="string"&&(o.description=a.description.trim()||void 0),typeof a.enabled=="boolean"&&(o.enabled=a.enabled),`updated webhook "${e}"`});return{summary:n}}function Qc(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function Zc(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function ed(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function td(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function ad(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function nd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function rd(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function od(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function sd(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function id(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function ld(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-XVMWASQR.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function cd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function dd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function pd(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function ud(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function md(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ze(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Bt(n))try{Tc(n,r)}catch{}Eo(n,JSON.stringify(a,null,2)+`
|
|
5333
|
-
`,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function Mo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function fd(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function hd(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function gd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function xd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function vd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function bd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function yd(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function wd(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function kd(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...d,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function _d(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Sd(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let d=l.columns.findIndex(u=>u.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ed(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Td(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function Ad(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function Cd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function Id(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Md(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=$n(a.notifications.local,t.local),n.push("local="+JSON.stringify(a.notifications.local))),"ntfy"in t&&t.ntfy&&typeof t.ntfy=="object"&&(a.channels=a.channels||{},a.channels.ntfy=Ir(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function Ld(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=sr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Rd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ct();import{resolve as jd}from"path";function Lo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5332
|
+
`)}catch{}return{summary:l}}function Hc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=Mo(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Bc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function zc(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function qc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Je(t){let{url:e,headers:a}=_a(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ue(t,e){let{url:a,headers:n}=_a(),r=await fetch(a+t,{method:"POST",headers:{...n,"Content-Type":"application/json"},body:JSON.stringify(e||{})}),o=await r.text();if(!r.ok)throw new Error(`daemon ${r.status}: ${o.slice(0,200)}`);try{return JSON.parse(o)}catch{return{raw:o}}}async function Fc(t,e){try{let{url:a,headers:n}=_a(),r=await fetch(a+e,{headers:n}),o=await r.text();t.writeHead(r.status,{"Content-Type":r.headers.get("content-type")||"image/svg+xml","Cache-Control":"no-store"}),t.end(o)}catch(a){t.writeHead(502,{"Content-Type":"text/plain; charset=utf-8"}),t.end("daemon unreachable: "+(a?.message||"unknown"))}}function _a(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ve(t){let a=ka()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function wa(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Uc(t){let e=wa(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Wc(t){let e=wa(t,"agent").trim(),a=wa(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return kt(Ve(e),a)}function Gc(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=_t(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Xc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=St(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Kc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=Et(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Jc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Vc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Yc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(d=>d.kind===a&&d.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var Io=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Qc(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!Io.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(d=>d.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Zc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&Io.includes(a.source)&&(o.source=a.source),typeof a.agentId=="string"&&a.agentId.trim()){if(!r.agents?.[a.agentId])throw new Error(`Unknown agent "${a.agentId}".`);o.agentId=a.agentId.trim()}return typeof a.secretEnv=="string"&&(o.secretEnv=a.secretEnv.trim()||void 0),typeof a.description=="string"&&(o.description=a.description.trim()||void 0),typeof a.enabled=="boolean"&&(o.enabled=a.enabled),`updated webhook "${e}"`});return{summary:n}}function ed(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function td(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function ad(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function nd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function rd(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function od(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function sd(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function id(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function ld(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function cd(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function dd(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-XVMWASQR.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function pd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function ud(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function md(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function fd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function hd(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ze(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Bt(n))try{Cc(n,r)}catch{}Eo(n,JSON.stringify(a,null,2)+`
|
|
5333
|
+
`,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function Mo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function gd(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function xd(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function vd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function bd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function yd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function wd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function kd(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function _d(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function Sd(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),d={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(d.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...d,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(d),`board "${e}" added`});return{summary:i}}async function Ed(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function Td(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let d=l.columns.findIndex(u=>u.id===a);return d>=0?(l.columns[d]={...l.columns[d],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function Ad(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function Cd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function Id(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function Md(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function Ld(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function Rd(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=$n(a.notifications.local,t.local),n.push("local="+JSON.stringify(a.notifications.local))),"ntfy"in t&&t.ntfy&&typeof t.ntfy=="object"&&(a.channels=a.channels||{},a.channels.ntfy=Ir(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function $d(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=sr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Pd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}ct();import{resolve as Nd}from"path";function Lo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5334
5334
|
|
|
5335
5335
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5336
5336
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5385,7 +5385,7 @@ ${s||"You are "+a+"."}
|
|
|
5385
5385
|
<h2>Recent classifications</h2>
|
|
5386
5386
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5387
5387
|
<div id="recent"></div>
|
|
5388
|
-
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css
|
|
5388
|
+
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:jd,scripts:`${e}<script>${Od}</script>`})}var jd=`
|
|
5389
5389
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5390
5390
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5391
5391
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5489,7 +5489,7 @@ details {
|
|
|
5489
5489
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5490
5490
|
}
|
|
5491
5491
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5492
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5492
|
+
details[open] summary { margin-bottom: 8px; }`,Od=`
|
|
5493
5493
|
const $ = (id) => document.getElementById(id);
|
|
5494
5494
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5495
5495
|
|
|
@@ -5709,7 +5709,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5709
5709
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5710
5710
|
|
|
5711
5711
|
refresh();
|
|
5712
|
-
`;function $o(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lo({peers:a,localToken:n}))}async function Po(t,e,a){try{let n=t.method==="GET"?void 0:await
|
|
5712
|
+
`;function $o(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lo({peers:a,localToken:n}))}async function Po(t,e,a){try{let n=t.method==="GET"?void 0:await Gd(t),r=Dd(),o={"GET /api/admin/graph/state":()=>Hd(r),"POST /api/admin/graph/classifications/approve":()=>Bd(r,n),"POST /api/admin/graph/classifications/reject":()=>zd(r,n),"POST /api/admin/graph/nodes":()=>qd(r,n),"PATCH /api/admin/graph/nodes":()=>Fd(r,n),"DELETE /api/admin/graph/nodes":()=>Ud(r,n),"PUT /api/admin/graph/schema":()=>Wd(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Sa(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Sa(e,200,l)}catch(n){Sa(e,400,{error:n?.message||"graph op failed"})}}function Dd(){let t=X(),e=Nd(process.cwd(),t.graph.baseDir);return new bn({baseDir:e})}function Hd(t){let e=X(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function Bd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=jo(t,a);return Array.isArray(e?.path)&&e.path.length>0&&(n.path=e.path.map(r=>String(r))),e?.proposedAxes&&typeof e.proposedAxes=="object"&&(n.proposedAxes=Ea(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function zd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=jo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function jo(t,e){let n=t.readRecentClassifications(500).find(r=>r.msgHash===e);if(!n)throw new Error(`No classification found for ${e}`);return n}function qd(t,e){let a=Ro(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?Ro(String(e.parentId)):null,o=Ea({[a]:e?.axes||{}})[a]||{};if(!a)throw new Error("id is required");if(!n)throw new Error("level is required");let s={id:a,level:n,parentId:r,axes:o,createdAt:new Date().toISOString(),createdBy:"admin-ui"};return t.addNode(s),{node:s}}function Fd(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Ea({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ud(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Wd(t,e){if(!e?.schema||typeof e.schema!="object")throw new Error("schema object is required");return t.saveSchema(e.schema),{summary:"Schema saved"}}function Ea(t){let e={};for(let[a,n]of Object.entries(t||{})){if(!n||typeof n!="object")continue;let r={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(r[o]=s);e[a]=r}return e}function Ro(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Sa(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Gd(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var Oo=`
|
|
5713
5713
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5714
5714
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5715
5715
|
<p class="apv__lead">What you asked agents for that is not finished, oldest first. Reply, hand it to an agent, close it as done, or drop it. Nothing leaves this list by getting old.</p>
|
|
@@ -5927,7 +5927,7 @@ ${Oo}
|
|
|
5927
5927
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5928
5928
|
</form>
|
|
5929
5929
|
</details>
|
|
5930
|
-
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5930
|
+
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Xd+No,scripts:`${e}<script>${Kd}</script><script>${Do}</script>`})}var Xd=`
|
|
5931
5931
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5932
5932
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5933
5933
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5976,7 +5976,7 @@ ${Oo}
|
|
|
5976
5976
|
@media (max-width: 560px) {
|
|
5977
5977
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5978
5978
|
}
|
|
5979
|
-
`,
|
|
5979
|
+
`,Kd=`
|
|
5980
5980
|
(function(){
|
|
5981
5981
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
5982
5982
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -6144,7 +6144,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
6144
6144
|
load();
|
|
6145
6145
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
6146
6146
|
})();
|
|
6147
|
-
`;import{existsSync as
|
|
6147
|
+
`;import{existsSync as Jd,readFileSync as Vd}from"fs";var Ae="/api/admin/approvals/requests";function Bo(t){let e=En(t);if(!Jd(e))return[];try{let a=JSON.parse(Vd(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var zo=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function qo(t,e,a,n){try{return await Yd(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Yd(t,e,a,n){if(t==="GET"&&e===Ae){let o=xt(n);return{status:200,body:{items:o?o.listOpen().map(s=>zn(s,o)):[],agents:Bo(n.configPath),settings:gt(n.configPath)}}}let r=e===`${Ae}/reply`?"reply":e===`${Ae}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=xt(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let d=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",u=Bo(n.configPath).find(h=>h.id===d);if(r==="handoff"&&!u)return{status:400,body:{error:`"${d}" is not an agent on this node`}};if(!gt(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,d,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let m=u?.name??d;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${m} will go on with ${o}`:`${m} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Ae}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=xt(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Ae}/settings`){let o={},s=l=>{let c=a[l];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${l} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=zo(a.from),o.channels=zo(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await Nn(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:gt(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var Qd=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function zt(t,e=64*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8");if(!r.trim())return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function Fo(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Ho({peers:e,localToken:a}))}async function Uo(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Ae)){let i=await qo(o,a,o==="POST"?await zt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=vt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await zt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Qd.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let d=_e(s.configPath),u=await bt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:d.laterHours,by:"operator (dashboard)"});return u.ok?(te(e,200,{ok:!0,message:u.message}),!0):(te(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await zt(t),l=qn(s,typeof i.key=="string"?i.key:"",!!_e(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await zt(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let m=xr(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let d=await vr(l,{configPath:s.configPath,reload:s.reload});return d.success?(te(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(te(e,400,{error:d.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}ia();function Wo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates and guests. Open a person to see the machines they paired and what they asked for."})+`
|
|
6148
6148
|
<div class="pp">
|
|
6149
6149
|
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
6150
6150
|
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
@@ -6157,7 +6157,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6157
6157
|
</ol>
|
|
6158
6158
|
</section>
|
|
6159
6159
|
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
6160
|
-
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:
|
|
6160
|
+
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Zd,scripts:`${e}<script>${ep}</script>`})}var Zd=`
|
|
6161
6161
|
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
6162
6162
|
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
6163
6163
|
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -6198,7 +6198,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6198
6198
|
.pp-text { overflow-wrap: anywhere; }
|
|
6199
6199
|
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
6200
6200
|
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
6201
|
-
`,
|
|
6201
|
+
`,ep=`
|
|
6202
6202
|
(function () {
|
|
6203
6203
|
var list = document.getElementById('pp-list');
|
|
6204
6204
|
var msg = document.getElementById('pp-msg');
|
|
@@ -6336,7 +6336,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6336
6336
|
load();
|
|
6337
6337
|
setInterval(load, 30000);
|
|
6338
6338
|
})();
|
|
6339
|
-
`;var Ta="/api/admin/people";function
|
|
6339
|
+
`;var Ta="/api/admin/people";function tp(t,e){let a=kr(t,e);return a?{...e,answer:a}:e}function ap(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function me(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function np(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&ap(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:lt,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var rp=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Go(t,e,a,n){if(a!=="/people"&&a!==Ta&&!a.startsWith(`${Ta}/`))return!1;let r=(t.method||"GET").toUpperCase();if(a==="/people")return r!=="GET"?(me(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Wo({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return me(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(d=>tp(n.root,d)),s=()=>np(n.people(),o());if(r==="GET"&&a===Ta){let c=s();return me(e,200,{people:c,paired:c.reduce((d,u)=>d+u.machines.active+u.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return me(e,404,{error:`no person "${i[1]}"`}),!0;let d=n.db(),u=[],m=[];try{d&&(u=br(d,c.id))}catch{}try{d&&(m=Mt(d,c.id,20))}catch{}return me(e,200,{person:c,devices:o(c.id).sort(rp),requests:u,runs:m,database:!!d}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,c,d]=l,u=n.members.byToken(d);if(!u||u.personId!==c)return me(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return me(e,409,{error:"this machine's access has already ended"}),!0;let m=Sr({tokens:n.tokens??new F,members:n.members,now:n.now},d,"removed by the owner (dashboard)");return me(e,200,{ok:!0,device:m}),!0}return me(e,404,{error:"not found"}),!0}import{resolve as cp}from"path";import{existsSync as dp}from"fs";import pp from"better-sqlite3";var Xo=new WeakSet;function op(t,e,a={}){if(Xo.has(t))return;Xo.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let c=i[l].bind(i);i[l]=(...d)=>{let u=r();try{return c(...d)}finally{let m=r()-u;m>=n&&e({sql:s,ms:m})}}}return i}}function sp(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ye(t,e){op(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${sp(a)}`))}function Ko(t={}){let e=`<div class="ax-obs">
|
|
6340
6340
|
<header class="ax-obs__head">
|
|
6341
6341
|
<h1>Health</h1>
|
|
6342
6342
|
<p class="ax-obs__sub">Platform-health view: what each agent ran, what failed, and how the router decided. <span class="ax-obs__sub-link">Spend lives on the <a href="/admin/cost">Cost</a> page.</span></p>
|
|
@@ -6458,7 +6458,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6458
6458
|
</div>
|
|
6459
6459
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6460
6460
|
</section>
|
|
6461
|
-
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6461
|
+
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ip,scripts:`<script>${lp}</script>`})}var ip=`
|
|
6462
6462
|
.ax-obs { padding: 16px 24px; }
|
|
6463
6463
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6464
6464
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6575,7 +6575,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6575
6575
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6576
6576
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6577
6577
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6578
|
-
`,
|
|
6578
|
+
`,lp=`
|
|
6579
6579
|
(function(){
|
|
6580
6580
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6581
6581
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -6959,7 +6959,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6959
6959
|
|
|
6960
6960
|
load(current);
|
|
6961
6961
|
})();
|
|
6962
|
-
`;var Yo={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function Qo(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Aa(t){let e=Yo[Qo(t.model)],a=t.input_tokens/1e6*e.input+t.output_tokens/1e6*e.output+t.cache_read_tokens/1e6*e.cacheRead+t.cache_create_tokens/1e6*e.cacheCreate,n=(t.tier2_input_tokens??0)/1e6*e.input*.5+(t.tier2_output_tokens??0)/1e6*e.output*.5+(t.tier2_cache_read_tokens??0)/1e6*e.cacheRead*.5+(t.tier2_cache_create_tokens??0)/1e6*e.cacheCreate*.5;return a+n}function
|
|
6962
|
+
`;var Yo={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function Qo(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Aa(t){let e=Yo[Qo(t.model)],a=t.input_tokens/1e6*e.input+t.output_tokens/1e6*e.output+t.cache_read_tokens/1e6*e.cacheRead+t.cache_create_tokens/1e6*e.cacheCreate,n=(t.tier2_input_tokens??0)/1e6*e.input*.5+(t.tier2_output_tokens??0)/1e6*e.output*.5+(t.tier2_cache_read_tokens??0)/1e6*e.cacheRead*.5+(t.tier2_cache_create_tokens??0)/1e6*e.cacheCreate*.5;return a+n}function up(){let t=cp(process.cwd(),".agentx/db.sqlite");if(!dp(t))return null;try{let e=new pp(t,{readonly:!0,fileMustExist:!0});return ye(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Zo(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ko({peers:a}))}function mp(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function es(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=up();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=mp(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6963
6963
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6964
6964
|
FROM route_traces
|
|
6965
6965
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
@@ -6974,8 +6974,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6974
6974
|
FROM task_history
|
|
6975
6975
|
WHERE ${i.join(" AND ")}
|
|
6976
6976
|
ORDER BY started_at DESC LIMIT @limit
|
|
6977
|
-
`,u=r.db.prepare(c).all(l).map(m=>({...m,plain:ts(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,
|
|
6978
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6977
|
+
`,u=r.db.prepare(c).all(l).map(m=>({...m,plain:ts(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,fp(r.db)),!0;if(n==="activity")return fe(e,200,hp(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Jo(i.searchParams.get("range"));return fe(e,200,Vo(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Jo(i.searchParams.get("range")),c=Vo(r.db,l),d=gp(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(d),!0}return fe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function ts(t){let e=String(t||"");return e?/timed out|SIGTERM|exit 143|maxExecutionMinutes/i.test(e)?"Agent ran past its time limit":/ECONNREFUSED|fetch failed|getaddrinfo|ENOTFOUND/i.test(e)?"Couldn't reach a service over the network":/401|403|Unauthorized|Forbidden|invalid token|missing scope/i.test(e)?"Authentication or permission denied":/rate limit|429|too many requests/i.test(e)?"Hit a rate limit (too many calls)":/quota|insufficient_quota/i.test(e)?"Provider account out of quota or credits":/tier-?2|tier two|200K|200,000/i.test(e)?"Hit Anthropic tier-2 billing threshold":/JSON|parse|unexpected token/i.test(e)?"Got a response in the wrong shape":/permission denied|EACCES|EPERM/i.test(e)?"File permission denied":/ENOENT|no such file/i.test(e)?"Expected file is missing":/abort|cancel/i.test(e)?"Task was cancelled before it finished":e.split(`
|
|
6978
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function fp(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,d=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=w=>d.length?d[Math.min(d.length-1,Math.floor(d.length*w))].duration_ms:0,m=u(.5),h=u(.95),v=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((w,I)=>w+Aa(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((w,I)=>w+Aa(I),0),g=t.prepare(`
|
|
6979
6979
|
SELECT agent_id,
|
|
6980
6980
|
COUNT(*) AS tasks,
|
|
6981
6981
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -6998,7 +6998,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6998
6998
|
FROM task_history
|
|
6999
6999
|
WHERE status='error' AND started_at >= ?
|
|
7000
7000
|
ORDER BY started_at DESC LIMIT 5
|
|
7001
|
-
`).all(o).map(w=>({...w,plain:ts(w.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:v,spendDelta:v-S,idleAgentCount:b.length},perAgent:g,perChannel:p,idleAgents:b,recentErrors:T}}function
|
|
7001
|
+
`).all(o).map(w=>({...w,plain:ts(w.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:v,spendDelta:v-S,idleAgentCount:b.length},perAgent:g,perChannel:p,idleAgents:b,recentErrors:T}}function hp(t,e){let a=new Date(Date.now()-864e5).toISOString(),n=new Date(Date.now()-7*864e5).toISOString(),r=e.agent?"AND agent_id = @agent":"",o=e.agent?{agent:e.agent}:{},s=t.prepare(`
|
|
7002
7002
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
7003
7003
|
COUNT(*) AS tasks,
|
|
7004
7004
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -7033,10 +7033,10 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7033
7033
|
FROM usage_daily
|
|
7034
7034
|
${a}
|
|
7035
7035
|
ORDER BY day
|
|
7036
|
-
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,d=0,u=0,m=0,h=0,k=0,v=0,S=0,g={},p={};for(let E of n){let $=Aa(E),L=Qo(E.model),j=Yo[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),Oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(d+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,v+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(m+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=Oe,Z.cost+=$,Z.tier2+=W;let B=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});B.tasks+=E.tasks||0,B.cost+=$,B.tier2+=W,B.input+=q,B.output+=G,B.cacheRead+=ie,B.cacheCreate+=Oe,E.model&&(B.model=E.model);let O=p[E.agent_id]||(p[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=Oe,E.model&&(O.model=E.model)}let f=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,b=0,_=0,T=0,w=0,I=0;for(let E of f)x+=E.tasks,b+=E.input,_+=E.output,T+=E.cacheRead,w+=E.cacheCreate,I+=E.cost;let C=Object.entries(p).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:d,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:b+_+T+w,cacheHitRange:T+b>0?T/(T+b):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(d-S)/S:0,tasksDeltaWoW:v>0?(k-v)/v:0},days:f,perAgent:C}}function
|
|
7036
|
+
`).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,d=0,u=0,m=0,h=0,k=0,v=0,S=0,g={},p={};for(let E of n){let $=Aa(E),L=Qo(E.model),j=Yo[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),Oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(d+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,v+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(m+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=Oe,Z.cost+=$,Z.tier2+=W;let B=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});B.tasks+=E.tasks||0,B.cost+=$,B.tier2+=W,B.input+=q,B.output+=G,B.cacheRead+=ie,B.cacheCreate+=Oe,E.model&&(B.model=E.model);let O=p[E.agent_id]||(p[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=Oe,E.model&&(O.model=E.model)}let f=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,b=0,_=0,T=0,w=0,I=0;for(let E of f)x+=E.tasks,b+=E.input,_+=E.output,T+=E.cacheRead,w+=E.cacheCreate,I+=E.cost;let C=Object.entries(p).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:d,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:b+_+T+w,cacheHitRange:T+b>0?T/(T+b):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(d-S)/S:0,tasksDeltaWoW:v>0?(k-v)/v:0},days:f,perAgent:C}}function gp(t){let e="date,tasks,input,output,cache_read,cache_create,cost_usd,top_agent",a=t.map(n=>{let r=Object.entries(n.agents).sort(([,o],[,s])=>s.cost-o.cost)[0];return[n.date,n.tasks,n.input,n.output,n.cacheRead,n.cacheCreate,n.cost.toFixed(6),r?r[0]:""].join(",")});return e+`
|
|
7037
7037
|
`+a.join(`
|
|
7038
7038
|
`)+`
|
|
7039
|
-
`}import{resolve as
|
|
7039
|
+
`}import{resolve as xp}from"path";import{existsSync as vp}from"fs";import bp from"better-sqlite3";function yp(){let t=xp(process.cwd(),".agentx/intent/ledger.sqlite");if(!vp(t))return null;try{let e=new bp(t,{readonly:!0,fileMustExist:!0});return ye(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-as>6e4&&(as=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var as=0;function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wp(t){if(!t)return;let e=String(t).trim().match(/^(\d+)\s*(s|m|h|d|w)?$/i);if(!e)return;let a=parseInt(e[1],10),n=(e[2]||"h").toLowerCase(),r=n==="s"?1e3:n==="m"?6e4:n==="h"?36e5:n==="d"?864e5:n==="w"?7*864e5:0;return Date.now()-a*r}async function ns(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=yp();if(!r)return Ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=wp(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),d=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,v=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),p=r.db.prepare(`
|
|
7040
7040
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
7041
7041
|
LEFT JOIN intent_resolutions r
|
|
7042
7042
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
@@ -7868,7 +7868,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7868
7868
|
</header>
|
|
7869
7869
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
7870
7870
|
</section>
|
|
7871
|
-
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
7871
|
+
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:kp,scripts:`<script>${_p}</script>`})}var kp=`
|
|
7872
7872
|
.ax-pj__root {
|
|
7873
7873
|
display: grid;
|
|
7874
7874
|
grid-template-columns: 360px 1fr;
|
|
@@ -8055,7 +8055,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8055
8055
|
}
|
|
8056
8056
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
8057
8057
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
8058
|
-
`,
|
|
8058
|
+
`,_p=`
|
|
8059
8059
|
(function(){
|
|
8060
8060
|
const $ = (sel) => document.querySelector(sel);
|
|
8061
8061
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8705,9 +8705,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8705
8705
|
load();
|
|
8706
8706
|
});
|
|
8707
8707
|
})();
|
|
8708
|
-
`;import{resolve as Ra,join as Np}from"path";import{existsSync as $a,readdirSync as Dp,readFileSync as Hp}from"fs";import Bp from"better-sqlite3";var ls=String.raw`[\w.-]+(?:/[\w.-]+)+`,kp=new RegExp(`^(?:chat:)?(${ls}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),_p=new RegExp(`^\\[(?:GitLab|GitHub) (${ls}) `);function is(t){if(!t)return null;let e=t.match(kp);return e?e[1]:null}function Ca(t){if(!t)return null;let e=t.trimStart().match(_p);return e?e[1]:null}function qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():is(typeof n?.chatId=="string"?n.chatId:null)??is(e)??Ca(a)}function Sp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ft(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ep=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Tp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ap=t=>/^issue/i.test(t)?"issue":"mr";function Cp(t){let e=t.subject.match(Ep)??t.inputPreview.trimStart().match(Tp);return e?{kind:Ap(e[1]),n:Number(e[2])}:null}function Ip(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function cs(t){if(!Sp(t.projectId))return[];let e=Cp(t);return e?[e]:Ip(t.inputPreview)}var Mp=6e4,Lp=5*6e4,Rp=40,ds=6,ps=new Map;function us(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of cs(n)){let s=Ft(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Rp)return[...e.values()]}}return[...e.values()]}async function ms(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ft(s.project,s.ref),l=ps.get(i);l&&n-l.at<(s.github?Lp:Mp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ds)await Promise.all(o.slice(s,s+ds).map(async i=>{let l=Ft(i.project,i.ref),c=null;try{c=i.github?await Pp(i,e,a):await $p(i,e,a)}catch{}ps.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function fs(t,e,a){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3);try{let o=await a(t,{headers:e,signal:n.signal});return o.ok?await o.json():null}finally{clearTimeout(r)}}async function $p(t,e,a){let n=e.gitlab;if(!n?.host||!n.token)return null;let r=`${n.host.replace(/\/+$/,"")}/api/v4/projects/${encodeURIComponent(t.project)}`,o=t.ref.kind==="mr"?`merge_requests/${t.ref.n}`:`issues/${t.ref.n}`,s=await fs(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function Pp(t,e,a){let n=t.ref.kind==="mr"?`pulls/${t.ref.n}`:`issues/${t.ref.n}`,r={Accept:"application/vnd.github+json","User-Agent":"agentx-dashboard"};e.githubToken&&(r.Authorization=`Bearer ${e.githubToken}`);let o=await fs(`https://api.github.com/repos/${t.project}/${n}`,r,a);return o?{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(o.title??""),state:o.merged_at?"merged":o.state==="open"?"opened":String(o.state??"opened"),draft:!!o.draft,url:String(o.html_url??""),pipeline:null,mergedAt:o.merged_at?Date.parse(o.merged_at):null}:null}mn();var Ia=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function hs(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=st(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Ia(o.from,80);if(s){a.callback={from:s,status:Ia(o.status,20)??"done"};let i=Ia(o.peer,80);i&&(a.callback.peer=i)}}return a}mn();ia();var gs={kind:"agentx",id:"agentx",name:"AgentX"},Ma={kind:"person",id:"unknown",name:"Unknown"},jp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),xs=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Op(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function vs(t){let e=s=>({kind:"person",id:`person:${s}`,name:gn(t.people,s)}),a=(s,i)=>i||jp.has(s)?gs:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??vn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(un(s)==="human")return xs(s?.senderUsername)?a(c,!1):Ma;let d=!!Ie(n.senderAgentId)||ra(l?l.sender:s?.sender);return c==="desktop"&&!d?Ma:a(c,d)}let r=Op(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=xn(t.people,t.channel,r);return o?e(o.id):ra(r.name)?gs:pn.has(t.channel)&&!xs(r.username)?Ma:a(t.channel,!1)}function Pa(){let t=Ra(process.cwd(),".agentx/intent/ledger.sqlite");if(!$a(t))return null;try{let e=new Bp(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-bs>6e4&&(bs=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var bs=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function zp(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function ks(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function qp(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function _s(t,e,a){return Mn(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function Fp(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!La(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!La(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Wp(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!La(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",u=ys(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:ys(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var Up={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Wp(t,e){let a=Up[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ys(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function La(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Ss(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
|
|
8708
|
+
`;import{resolve as Ra,join as Hp}from"path";import{existsSync as $a,readdirSync as Bp,readFileSync as zp}from"fs";import qp from"better-sqlite3";var ls=String.raw`[\w.-]+(?:/[\w.-]+)+`,Sp=new RegExp(`^(?:chat:)?(${ls}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),Ep=new RegExp(`^\\[(?:GitLab|GitHub) (${ls}) `);function is(t){if(!t)return null;let e=t.match(Sp);return e?e[1]:null}function Ca(t){if(!t)return null;let e=t.trimStart().match(Ep);return e?e[1]:null}function qt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():is(typeof n?.chatId=="string"?n.chatId:null)??is(e)??Ca(a)}function Tp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Ft(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var Ap=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Cp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Ip=t=>/^issue/i.test(t)?"issue":"mr";function Mp(t){let e=t.subject.match(Ap)??t.inputPreview.trimStart().match(Cp);return e?{kind:Ip(e[1]),n:Number(e[2])}:null}function Lp(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function cs(t){if(!Tp(t.projectId))return[];let e=Mp(t);return e?[e]:Lp(t.inputPreview)}var Rp=6e4,$p=5*6e4,Pp=40,ds=6,ps=new Map;function us(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of cs(n)){let s=Ft(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Pp)return[...e.values()]}}return[...e.values()]}async function ms(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Ft(s.project,s.ref),l=ps.get(i);l&&n-l.at<(s.github?$p:Rp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ds)await Promise.all(o.slice(s,s+ds).map(async i=>{let l=Ft(i.project,i.ref),c=null;try{c=i.github?await Op(i,e,a):await jp(i,e,a)}catch{}ps.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function fs(t,e,a){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3);try{let o=await a(t,{headers:e,signal:n.signal});return o.ok?await o.json():null}finally{clearTimeout(r)}}async function jp(t,e,a){let n=e.gitlab;if(!n?.host||!n.token)return null;let r=`${n.host.replace(/\/+$/,"")}/api/v4/projects/${encodeURIComponent(t.project)}`,o=t.ref.kind==="mr"?`merge_requests/${t.ref.n}`:`issues/${t.ref.n}`,s=await fs(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function Op(t,e,a){let n=t.ref.kind==="mr"?`pulls/${t.ref.n}`:`issues/${t.ref.n}`,r={Accept:"application/vnd.github+json","User-Agent":"agentx-dashboard"};e.githubToken&&(r.Authorization=`Bearer ${e.githubToken}`);let o=await fs(`https://api.github.com/repos/${t.project}/${n}`,r,a);return o?{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(o.title??""),state:o.merged_at?"merged":o.state==="open"?"opened":String(o.state??"opened"),draft:!!o.draft,url:String(o.html_url??""),pipeline:null,mergedAt:o.merged_at?Date.parse(o.merged_at):null}:null}mn();var Ia=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function hs(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=st(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Ia(o.from,80);if(s){a.callback={from:s,status:Ia(o.status,20)??"done"};let i=Ia(o.peer,80);i&&(a.callback.peer=i)}}return a}mn();ia();var gs={kind:"agentx",id:"agentx",name:"AgentX"},Ma={kind:"person",id:"unknown",name:"Unknown"},Np=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),xs=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Dp(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function vs(t){let e=s=>({kind:"person",id:`person:${s}`,name:gn(t.people,s)}),a=(s,i)=>i||Np.has(s)?gs:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??vn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(un(s)==="human")return xs(s?.senderUsername)?a(c,!1):Ma;let d=!!Ie(n.senderAgentId)||ra(l?l.sender:s?.sender);return c==="desktop"&&!d?Ma:a(c,d)}let r=Dp(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=xn(t.people,t.channel,r);return o?e(o.id):ra(r.name)?gs:pn.has(t.channel)&&!xs(r.username)?Ma:a(t.channel,!1)}function Pa(){let t=Ra(process.cwd(),".agentx/intent/ledger.sqlite");if(!$a(t))return null;try{let e=new qp(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-bs>6e4&&(bs=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var bs=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Fp(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function ks(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function Up(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function _s(t,e,a){return Mn(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function Wp(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!La(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!La(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Xp(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!La(i||l||"")){let d=typeof n.channel=="string"?n.channel:"",u=ys(d);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:ys(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var Gp={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Xp(t,e){let a=Gp[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ys(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function La(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function Ss(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
|
|
8709
8709
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8710
|
-
${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function
|
|
8710
|
+
${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function Kp(t){if(!t)return"(no subject)";let e;return(e=t.match(/^merge_request:(\d+)(?::note:(\d+))?/))?e[2]?`MR #${e[1]} \xB7 note ${e[2]}`:`MR #${e[1]}`:(e=t.match(/^issue:(\d+)(?::note:(\d+))?/))?e[2]?`Issue #${e[1]} \xB7 note ${e[2]}`:`Issue #${e[1]}`:(e=t.match(/^chat:(.+?):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,40)}`:(e=t.match(/^mesh:agent:(.+)$/))?`\u2192 ${e[1]}`:(e=t.match(/^workflow:([^:]+):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,30)}`:t.length>60?t.slice(0,57)+"\u2026":t}function Es(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8711
8711
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8712
8712
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8713
8713
|
`).all(r),s=new Map,i=new Map;if(o.length>0){let w=o.map(L=>L.id),I=w.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(w.map((L,j)=>[`id${j}`,L])),E=t.prepare(`
|
|
@@ -8716,7 +8716,7 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
|
|
|
8716
8716
|
`).all(C);for(let L of E)s.has(L.event_id)||s.set(L.event_id,[]),s.get(L.event_id).push(L);let $=t.prepare(`
|
|
8717
8717
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8718
8718
|
FROM intent_resolutions WHERE decision_event_id IN (${I})
|
|
8719
|
-
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,d=new Map,u=new Map,m=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],v=da(e?.business??{}),S=e?.people??[];for(let w of o){let I=null;try{I=JSON.parse(w.raw_json)}catch{}let C=_s(w.source,I,k),E=Ss(w.source,I),$=hs(I),L=w.project??qt(I,w.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=mt(L,h),W=L);let q=
|
|
8719
|
+
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,d=new Map,u=new Map,m=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],v=da(e?.business??{}),S=e?.people??[];for(let w of o){let I=null;try{I=JSON.parse(w.raw_json)}catch{}let C=_s(w.source,I,k),E=Ss(w.source,I),$=hs(I),L=w.project??qt(I,w.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=mt(L,h),W=L);let q=Fp(w.source,w.intent||"",I),G=Me[q]||{label:q,color:"#6b7280"};d.has(q)||d.set(q,{id:q,label:G.label,color:G.color});let ie=vs({source:w.source,channel:q,raw:I,people:S,channelLabel:O=>Me[O]?.label??O}),Oe="__system",Z,B=Wp(w.source,w.intent||"",I);if(B){Oe=B.id,Z=B.kind;let O=C?.displayName||B.name;(!u.has(B.id)||C?.displayName)&&u.set(B.id,{id:B.id,name:O,avatar:J(O),kind:B.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let O of s.get(w.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let Nl=`${w.id}|${O.decided_by}`,rt=i.get(Nl),sn=O.decided_at,ln=rt?.resolved_at??null,aa=ln===null,Dl=rt?.duration_ms??(aa?n-sn:0),Hl=aa?"active":rt?.status==="error"||rt?.status==="fail"?"error":"completed",ee,Ge;if(j)ee=j,Ge=W;else{let na=v.get(O.agent_id);na?(ee=na,Ge=`${na}/_${w.source}`):(ee="unmapped",Ge=`unmapped/_${w.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:ks(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ge),m.push({id:`${w.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ge,channelId:q,initiatorId:Oe,initiatorKind:Z,subject:Kp(w.subject),intent:w.intent||"",startedAt:sn,resolvedAt:ln,duration:Dl,active:aa,outcome:Hl,tokens:0,inputPreview:E,system:Up(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(w=>({...w,projects:[...c.get(w.id)||[]].sort()})).sort((w,I)=>w.id.localeCompare(I.id)),p=[],f=new Set;if(e){let w=e.business??{},I=C=>{let E=w.orgChart?.[C]?.role,$=E?w.roles?.[E]?.title:void 0;return typeof $=="string"&&$.trim()?$.trim():void 0};for(let[C,E]of Object.entries(e.agents||{})){let $={id:C,name:E.name||C,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:I(C)};p.push($),f.add(C)}}for(let w of m)f.has(w.agentId)||(p.push({id:w.agentId,name:w.agentId,tier:"worker",model:"",role:""}),f.add(w.agentId));p.sort((w,I)=>w.id.localeCompare(I.id));let x=[],b=new Set;for(let[w,I]of Object.entries(Me))x.push({id:w,label:I.label,color:I.color}),b.add(w);for(let w of d.values())b.has(w.id)||x.push(w);let _=[...u.values()];_.find(w=>w.id==="__system")||_.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:p,channels:x,initiators:_,dispatches:m,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function ja(t){let e=Pa();if(!e)return null;try{return Es(e.db,As(),t)}finally{e.close()}}function Ts(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:d}of t){l.gitlab??=d.forges?.gitlab,l.github??=d.forges?.github,d.now>s&&(s=d.now),d.windowH>i&&(i=d.windowH);for(let u of d.clients){let m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}for(let u of d.agents)a.has(u.id)||a.set(u.id,u);for(let u of d.channels)n.has(u.id)||n.set(u.id,u);for(let u of d.initiators)r.has(u.id)||r.set(u.id,u);for(let u of d.dispatches){let m=Jp(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:ks(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,d)=>c.id.localeCompare(d.id)),agents:[...a.values()].sort((c,d)=>c.id.localeCompare(d.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,d)=>d.startedAt-c.startedAt)}}function Jp(t){if(t.clientId!=="unmapped")return t;let e=Ca(t.inputPreview);if(!e)return t;let a=ge?.business?.projects??[];return{...t,projectId:e,clientId:mt(e,a)}}async function Ut(t){let e=ge?.channels?.gitlab,a=await ms(us(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ge=null;function As(){return ge&&{...ge,people:Ke(ge.people)}}function Cs(t){ge=t}async function Is(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Pa();if(!n)return he(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=Ms(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await Ut(Es(n.db,As(),o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Vp=5e3;async function Oa(t,e,a,n=ja){if(a!=="/api/admin/activity-graph/stream"&&!a.startsWith("/api/admin/activity-graph/stream?"))return!1;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: connected
|
|
8720
8720
|
|
|
8721
8721
|
`);let r=new URL(t.url||"/","http://_"),o=Ms(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,i=()=>{s=!0};t.on("close",i),t.on("error",i),e.on("close",i),e.on("error",i);let l=setInterval(()=>{if(!s)try{e.write(`: hb
|
|
8722
8722
|
|
|
@@ -8729,7 +8729,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
8729
8729
|
`)}catch(d){e.write(`event: error
|
|
8730
8730
|
data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
8731
8731
|
|
|
8732
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8732
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<Vp;)await new Promise(d=>setTimeout(d,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Ms(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Yp(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Ra(process.cwd(),".agentx/task-history",t,n);if(!$a(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Ra(process.cwd(),".agentx/task-history",t,o);return $a(s)?ws(s,e,a):null}return ws(r,e,a)}function ws(t,e,a){let n=null,r=1/0;for(let o of Bp(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(zp(Hp(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let d=Date.parse(i);if(!Number.isFinite(d))continue;l=d}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function Ls(t,e,a){let n=a.match(/^\/api\/admin\/activity-graph\/dispatch\/([^/?]+)(?:\?.*)?$/);if(!n)return!1;let r=decodeURIComponent(n[1]),o=r.indexOf("|");if(o<0)return he(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Pa();if(!l)return he(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return he(e,404,{error:"event not found"}),!0;let d=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!d)return he(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Ss(c.source,m),k=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,v=null,S=null;if(d.agent_id){let _=Yp(d.agent_id,d.decided_at);if(_){typeof _.responseText=="string"&&(v=_.responseText);let T=_.transcript;Array.isArray(T)&&(S=T.length)}}let g=ge?.business?.projects??[],p=ge?.business?.contactMap??[],f=da(ge?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},b=_s(c.source,m,p);if(b)x={client:b.client,project:b.project||`${b.client}/_chat`,via:`contactMap (channel=${b.channel??"*"}${b.username?` username=${b.username}`:""}${b.chatId?` chatId=${b.chatId}`:""})`};else if(c.project||qt(m,c.subject,h)){let _=c.project||qt(m,c.subject,h);x={client:mt(_,g),project:_,via:c.project?`project namespace prefix (${_})`:`forge path in chat id / message (${_})`}}else if(d.agent_id){let _=f.get(d.agent_id);_&&(x={client:_,project:`${_}/_${c.source}`,via:`orgChart fallback (agent ${d.agent_id} reports up to a PM whose project belongs to ${_})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:d.decided_by,agentId:d.agent_id,outcome:d.outcome,reason:d.reason,startedAt:d.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:v,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as tu,readFileSync as au}from"fs";import{resolve as $s}from"path";ct();function Rs(t){let e=t.agentId,a=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",n=`<script>window.AGENT_ID = ${JSON.stringify(e)};</script>`,r=Qp.replace(/__AGENT_ID__/g,N(e));return M({title:`AgentX \xB7 ${N(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${N(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Zp,headExtras:'<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">',scripts:`${n}${a}<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script><script>${eu}</script>`})}var Qp=`
|
|
8733
8733
|
<!-- Breadcrumb -->
|
|
8734
8734
|
<div class="ax-crumb">
|
|
8735
8735
|
<a href="/admin">Settings</a>
|
|
@@ -9318,7 +9318,7 @@ data: ${JSON.stringify({error:d?.message??String(d)})}
|
|
|
9318
9318
|
</div>
|
|
9319
9319
|
</div>
|
|
9320
9320
|
</div>
|
|
9321
|
-
`,
|
|
9321
|
+
`,Zp=`
|
|
9322
9322
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
9323
9323
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
9324
9324
|
* primitives live in components.css.ts. */
|
|
@@ -9437,7 +9437,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9437
9437
|
|
|
9438
9438
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9439
9439
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9440
|
-
`,
|
|
9440
|
+
`,eu=`
|
|
9441
9441
|
const $ = (id) => document.getElementById(id);
|
|
9442
9442
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9443
9443
|
|
|
@@ -10293,15 +10293,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
10293
10293
|
/* ===== Boot ===== */
|
|
10294
10294
|
initOptsToggles();
|
|
10295
10295
|
loadAgent();
|
|
10296
|
-
`;function Ps(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rs({agentId:a,peers:n,localToken:r}))}async function js(t,e,a){try{let n=t.method==="GET"?void 0:await
|
|
10297
|
-
`);return Ds(a,r,s,`install-${n}:${Date.now()}`)}async function
|
|
10298
|
-
`);return Ds(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ns(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Ds(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),d;try{d=JSON.parse(c)}catch{d={content:c}}if(!l.ok)throw new Error(d?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:d?.taskId,content:d?.content,duration:d?.duration,error:d?.error}}function
|
|
10296
|
+
`;function Ps(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rs({agentId:a,peers:n,localToken:r}))}async function js(t,e,a){try{let n=t.method==="GET"?void 0:await Su(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){Wt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Ye(i),"PATCH ":()=>nu(i,n),"PATCH capability":()=>su(i,n),"POST mcp":()=>ru(i,n),"DELETE mcp":()=>ou(i,n),"GET identity":()=>iu(i),"GET identity/file":()=>lu(i,String(o.path||"")),"PUT identity/file":()=>cu(i,n),"GET skills":()=>du(i),"POST skills":()=>pu(i,n),"DELETE skills":()=>uu(i,n),"GET skills/tree":()=>mu(i,String(o.slug||"")),"GET skills/file":()=>fu(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>hu(i,n),"GET skills/deps":()=>gu(i,String(o.slug||"")),"POST skills/install":()=>xu(i,n,t),"POST skills/deps":()=>vu(i,n,t),"GET channels":()=>bu(i),"GET activity":()=>yu(i,t),"GET handovers":()=>wu(i),"POST handovers":()=>ku(i,n),"DELETE handovers":()=>_u(n)}[c];if(!u){Wt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();Wt(e,200,m)}catch(n){Wt(e,400,{error:n?.message||"agent op failed"})}}function Os(){let t=$s(process.cwd(),"agentx.json");return tu(t)?JSON.parse(au(t,"utf-8")):null}function V(t){let e=Os();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function Ye(t){let{def:e,cfg:a}=V(t),n=e.workspace?De(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function nu(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function ru(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=A(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:Ye(t)}}function ou(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:Ye(t)}}function su(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function iu(t){let{def:e}=V(t);return De(e.workspace)}function lu(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return kt(a.workspace,e)}function cu(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return _t(n.workspace,a,String(e?.content??""))}function du(t){let{def:e}=V(t),a=De(e.workspace);return{skills:a.skills,workspace:a.workspace}}function pu(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return St(n.workspace,a,{title:e?.title,content:e?.content})}function uu(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return Et(n.workspace,a)}function mu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=ar(a.workspace,e),r=Tt(a.workspace,e);return{slug:e,tree:n,deps:r}}function fu(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return nr(n.workspace,e,a)}function hu(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return rr(r.workspace,a,n,String(e?.content??""))}function gu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Tt(a.workspace,e)}async function xu(t,e,a){let n=String(e?.package||"").trim();if(!n||!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)?$/.test(n))throw new Error("package must be in 'owner/repo' or 'owner/repo/skill' form");let r=Ns(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
|
|
10297
|
+
`);return Ds(a,r,s,`install-${n}:${Date.now()}`)}async function vu(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Ns(e?.worker),{def:o}=V(t),s=Tt(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=$s(o.workspace,".claude","skills",n),l=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${i}`,`Detected manifest: ${s.file}`,`Run: ${s.command}`,"Stream the install output. On success, summarise the packages installed.","On failure, report the exit code and the last 20 lines of output."].join(`
|
|
10298
|
+
`);return Ds(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Ns(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Ds(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),d;try{d=JSON.parse(c)}catch{d={content:c}}if(!l.ok)throw new Error(d?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:d?.taskId,content:d?.content,duration:d?.duration,error:d?.error}}function bu(t){let e=Os(),a=[],n=e?.channels?.telegram?.accounts||{};for(let[o,s]of Object.entries(n))s?.agentBinding===t&&a.push({channel:"telegram",account:o,detail:s?.botUsername||o});e?.channels?.slack?.agentBinding===t&&a.push({channel:"slack",detail:"bound"}),e?.channels?.discord?.agentBinding===t&&a.push({channel:"discord",detail:"bound"});let r=e?.channels?.gitlab?.agentMappings||[];for(let o of r)o?.agentId===t&&a.push({channel:"gitlab",detail:(o?.gitlabUsernames||[]).join(", ")||"mapped"});return{bindings:a}}async function yu(t,e){try{let n=(X().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function Na(){return new yn}function wu(t){let e=Na(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function ku(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=Na().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function _u(t){let e=String(t?.channel||"").trim(),a=String(t?.chatId||"").trim();if(!e||!a)throw new Error("channel and chatId required");let n=t?.accountId?String(t.accountId):void 0;return{summary:Na().remove(e,a,n)?"Released":"No active handover for that chat"}}function Wt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Su(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var Le={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Hs=[{term:"Agent",definition:'An AI worker with its own role, instructions, and channels it responds on. Think of each agent as a job title \u2014 "support", "devops", "sales".'},{term:"Trigger word",alias:"mention",definition:"A word that activates an agent. When the trigger appears in a message (e.g. @support), AgentX routes the message to that agent."},{term:"Channel",definition:"Where messages come from \u2014 Telegram, WhatsApp, Discord, GitLab comments, a scheduled cron, or an HTTP webhook."},{term:"AI engine",alias:"tier",definition:"Which backend answers: Claude Code, Codex CLI, Anthropic Agent SDK, or AgentX's provider-agnostic orchestrator."},{term:"Agent folder",alias:"workspace",definition:"The directory on disk where the agent lives. It holds the agent's personality (CLAUDE.md), its knowledge (wiki), and the tools it can use."},{term:"Team network",alias:"mesh",definition:'When you run AgentX on more than one machine, the machines find each other and share work. Each machine is a "node"; together they are your team network.'},{term:"Status check-in",alias:"heartbeat",definition:"A lightweight ping between machines so each one knows the others are alive and responsive."},{term:"Board",definition:"A Kanban view of tasks (issues, tickets) pulled from GitLab. Drag cards between columns to move work forward \u2014 the labels update upstream automatically."},{term:"Task",definition:"A single conversation or job an agent handles, from trigger message to final reply. Every task is logged and replayable."},{term:"Schedule",alias:"cron",definition:'A recurring job \u2014 e.g. "every Monday at 9am" \u2014 that nudges an agent without a human trigger.'},{term:"Status label",alias:"scopedLabel",definition:"A GitLab label that moves an issue between Kanban columns (e.g. Status::Doing). Labels are mutually exclusive by prefix."}];function Da(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
10299
10299
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
10300
10300
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
10301
10301
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
10302
10302
|
<main id="grid" class="ax-live__body"></main>
|
|
10303
10303
|
</div>
|
|
10304
|
-
`;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:
|
|
10304
|
+
`;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:Eu,scripts:e+`<script>${Tu}</script>`,headExtras:`<script>
|
|
10305
10305
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
10306
10306
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
10307
10307
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -10312,7 +10312,7 @@ loadAgent();
|
|
|
10312
10312
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
10313
10313
|
right.insertBefore(extras, right.firstChild);
|
|
10314
10314
|
});
|
|
10315
|
-
</script>`})}var
|
|
10315
|
+
</script>`})}var Eu=`
|
|
10316
10316
|
/* --- Page frame --- */
|
|
10317
10317
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
10318
10318
|
|
|
@@ -10519,7 +10519,7 @@ loadAgent();
|
|
|
10519
10519
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10520
10520
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10521
10521
|
}
|
|
10522
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10522
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,Tu=`
|
|
10523
10523
|
'use strict';
|
|
10524
10524
|
|
|
10525
10525
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -12324,12 +12324,12 @@ window.MXD=(function(){
|
|
|
12324
12324
|
}
|
|
12325
12325
|
load();setInterval(load,5000);
|
|
12326
12326
|
})();
|
|
12327
|
-
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var
|
|
12327
|
+
</script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var Au=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],Cu=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Iu=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Js(t){let e=ve({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+Ct([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
|
|
12328
12328
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
12329
|
-
${
|
|
12329
|
+
${Cu.map((i,l)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${i.id}" aria-controls="mx-view-${i.id}" aria-selected="${l===0}" data-view="${i.id}">${i.label}</button>`).join("")}
|
|
12330
12330
|
</div>
|
|
12331
12331
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
12332
|
-
${
|
|
12332
|
+
${Iu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
12333
12333
|
</div>
|
|
12334
12334
|
</div>
|
|
12335
12335
|
<p id="mx-analytics-updated" class="mx-updated" aria-live="polite">Reading node histories...</p>`,n=`<div class="mx-view" id="mx-view-activity" role="tabpanel" aria-labelledby="mx-tab-activity">
|
|
@@ -12382,7 +12382,7 @@ window.MXD=(function(){
|
|
|
12382
12382
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
12383
12383
|
${ne(ae.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
|
|
12384
12384
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
12385
|
-
${
|
|
12385
|
+
${Au.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12386
12386
|
</div>
|
|
12387
12387
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
12388
12388
|
</section>
|
|
@@ -12423,7 +12423,7 @@ window.MXD=(function(){
|
|
|
12423
12423
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
12424
12424
|
</header>
|
|
12425
12425
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
12426
|
-
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Bs+Ws,scripts:zs+
|
|
12426
|
+
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Bs+Ws,scripts:zs+Mu+qs+Fs+Gs+Us+Ks})}var Mu=`<script>
|
|
12427
12427
|
(function(){
|
|
12428
12428
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
12429
12429
|
var range=document.getElementById('mx-range');
|
|
@@ -12454,7 +12454,7 @@ window.MXD=(function(){
|
|
|
12454
12454
|
</script>`;function Vs(t){let e=ve({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
|
|
12455
12455
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12456
12456
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12457
|
-
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:
|
|
12457
|
+
<p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent <id></code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:Lu,scripts:`<script>${Ru}</script>`})}var Lu=`
|
|
12458
12458
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12459
12459
|
.gm-empty { color: var(--ax-text-2); }
|
|
12460
12460
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12472,7 +12472,7 @@ window.MXD=(function(){
|
|
|
12472
12472
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12473
12473
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12474
12474
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12475
|
-
`,
|
|
12475
|
+
`,Ru=`
|
|
12476
12476
|
(function () {
|
|
12477
12477
|
var list = document.getElementById('gm-list');
|
|
12478
12478
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12519,7 +12519,7 @@ window.MXD=(function(){
|
|
|
12519
12519
|
load();
|
|
12520
12520
|
setInterval(load, 30000);
|
|
12521
12521
|
})();
|
|
12522
|
-
`;async function Ys(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return
|
|
12522
|
+
`;async function Ys(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return $u(s,e.days)}function $u(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,d=0,u=0,m=0,h=0,k=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let p of g.days){let f=n.get(p.day)||{day:p.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=p[x]?.[0]||0,f[x][1]+=p[x]?.[1]||0;n.set(p.day,f)}for(let p of g.origins){let f=r.get(p.channel)||{channel:p.channel,runs:0,errors:0,hours:0};f.runs+=p.runs,f.errors+=p.errors,f.hours+=p.hours,r.set(p.channel,f)}for(let p of g.causes){let f=o.get(p.cause)||{cause:p.cause,count:0,agents:[],example:""};f.count+=p.count;for(let x of p.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=p.example),o.set(p.cause,f)}for(let p of g.rotations.byReason)s.set(p.reason,(s.get(p.reason)||0)+p.count);c+=g.rotations.total,d+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let p of g.jobs)i.push({...p,node:S.name,nodeUrl:S.url});for(let p of g.threads)l.push({...p,node:S.name,nodeUrl:S.url})}let v=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:v.length?Math.min(...v):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:d,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:k}}}async function Qs(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(i=>i.url.replace(/\/+$/,"")===r);if(!o){t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"node not in dashboard allowlist",target:r}));return}let s={Accept:"application/json"};o.token&&(s.Authorization=`Bearer ${o.token}`);try{let i=await fetch(r+n,{headers:s}),l=await i.text();t.writeHead(i.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(l)}catch(i){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:i?.message||"upstream fetch failed"}))}}async function Zs(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return Pu(s,e.day)}function Pu(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function ei(t={}){let e=`
|
|
12523
12523
|
<select id="boardPicker" title="Switch board"></select>
|
|
12524
12524
|
<div class="search">
|
|
12525
12525
|
<span class="icon">\u2315</span>
|
|
@@ -12620,7 +12620,7 @@ window.MXD=(function(){
|
|
|
12620
12620
|
</footer>
|
|
12621
12621
|
</div>
|
|
12622
12622
|
</div>
|
|
12623
|
-
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css
|
|
12623
|
+
<script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:ju,scripts:`<script>${Ou}</script>`,headExtras:`<script>
|
|
12624
12624
|
// The boards page has its own connection dot + wants body height:100%
|
|
12625
12625
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
12626
12626
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -12636,7 +12636,7 @@ window.MXD=(function(){
|
|
|
12636
12636
|
right.insertBefore(dot, right.firstChild);
|
|
12637
12637
|
}
|
|
12638
12638
|
});
|
|
12639
|
-
</script>`})}var
|
|
12639
|
+
</script>`})}var ju=`
|
|
12640
12640
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
12641
12641
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
12642
12642
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -12889,7 +12889,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
12889
12889
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
12890
12890
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
12891
12891
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
12892
|
-
`,
|
|
12892
|
+
`,Ou=`
|
|
12893
12893
|
'use strict';
|
|
12894
12894
|
const state = {
|
|
12895
12895
|
boards: [], current: null, items: {},
|
|
@@ -13944,7 +13944,7 @@ function appendEvents(events) {
|
|
|
13944
13944
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
13945
13945
|
`;function ti(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
13946
13946
|
<p class="lead">What the terms on the dashboard mean. Schema keys (shown in the pill on the right of each term) are what you'd write in <code>agentx.json</code> \u2014 the dashboard just relabels them for readability.</p>
|
|
13947
|
-
${Hs.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
13947
|
+
${Hs.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Nu})}var Nu=`
|
|
13948
13948
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
13949
13949
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13950
13950
|
.lead {
|
|
@@ -14051,7 +14051,7 @@ article.term p {
|
|
|
14051
14051
|
</aside>
|
|
14052
14052
|
</div>
|
|
14053
14053
|
|
|
14054
|
-
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
14054
|
+
<div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Du,scripts:`<script>${z({workflowHealth:In})}${Hu}</script>`})}var Du=`
|
|
14055
14055
|
.ax-wf__root {
|
|
14056
14056
|
display: grid;
|
|
14057
14057
|
grid-template-columns: 340px 1fr;
|
|
@@ -14435,7 +14435,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14435
14435
|
font-size: 12px; z-index: 50;
|
|
14436
14436
|
}
|
|
14437
14437
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14438
|
-
`,
|
|
14438
|
+
`,Hu=`
|
|
14439
14439
|
(() => {
|
|
14440
14440
|
const $ = (sel) => document.querySelector(sel)
|
|
14441
14441
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -15268,7 +15268,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15268
15268
|
<p class="hint">AgentX is layered: <strong>System</strong> (agents, channels, mesh) \u2192 <strong>Processes</strong> (workflows that turn intent into work) \u2192 <strong>Procedures</strong> (this page: reusable steps a process composes). Higher tiers depend on lower; never the reverse.</p>
|
|
15269
15269
|
<p class="hint">Adding a new procedure is a code change (a new <code>action.builtin</code> module under <code>src/actions/builtin/</code> or a new template YAML in <code>src/workflows/templates/</code>) \u2014 not a UI flow. This page is the read-only catalog.</p>
|
|
15270
15270
|
</section>
|
|
15271
|
-
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15271
|
+
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Bu,scripts:`<script>${zu}</script>`})}var Bu=`
|
|
15272
15272
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
15273
15273
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
15274
15274
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -15294,7 +15294,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15294
15294
|
.ax-proc__req { display: inline-block; padding: 1px 6px; font-size: 10px; font-family: var(--ax-mono); border: 1px solid color-mix(in oklch, var(--ax-warn, #f59e0b) 40%, var(--ax-border)); border-radius: 3px; color: var(--ax-warn, #f59e0b); }
|
|
15295
15295
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
15296
15296
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
15297
|
-
`,
|
|
15297
|
+
`,zu=`
|
|
15298
15298
|
(function(){
|
|
15299
15299
|
function $(sel){ return document.querySelector(sel) }
|
|
15300
15300
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -15437,7 +15437,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15437
15437
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15438
15438
|
</div>
|
|
15439
15439
|
</footer>
|
|
15440
|
-
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15440
|
+
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:qu,scripts:`<script>${Fu}</script>`})}var qu=`
|
|
15441
15441
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15442
15442
|
the sticky topbar. Breathe. */
|
|
15443
15443
|
.ax-task-page {
|
|
@@ -15579,7 +15579,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15579
15579
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
15580
15580
|
}
|
|
15581
15581
|
|
|
15582
|
-
`,
|
|
15582
|
+
`,Fu=`
|
|
15583
15583
|
(function () {
|
|
15584
15584
|
var root = document.querySelector('.ax-task-page');
|
|
15585
15585
|
if (!root) return;
|
|
@@ -15993,7 +15993,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15993
15993
|
<div class="ax-history__list" id="hist-list">
|
|
15994
15994
|
<div class="ax-history__empty">loading\u2026</div>
|
|
15995
15995
|
</div>
|
|
15996
|
-
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15996
|
+
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Uu,scripts:`<script>${Wu}</script>`})}var Uu=`
|
|
15997
15997
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
15998
15998
|
flush against the sticky topbar. */
|
|
15999
15999
|
.ax-history {
|
|
@@ -16045,7 +16045,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16045
16045
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
16046
16046
|
}
|
|
16047
16047
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
16048
|
-
`,
|
|
16048
|
+
`,Wu=`
|
|
16049
16049
|
(function () {
|
|
16050
16050
|
var root = document.querySelector('.ax-history');
|
|
16051
16051
|
if (!root) return;
|
|
@@ -16145,11 +16145,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
16145
16145
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
16146
16146
|
});
|
|
16147
16147
|
})();
|
|
16148
|
-
`;function ii(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return qe(t,e,l=>si(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:
|
|
16148
|
+
`;function ii(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return qe(t,e,l=>si(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Xu(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return R(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?qe(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return R(e,200,{ok:!0,emission:c})}):R(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?qe(t,e,l=>{try{let c=a.layouts.save(s,l);return R(e,200,{layout:c})}catch(c){return R(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?qe(t,e,l=>{let c=la.safeParse(l);if(!c.success)return R(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let d=ca(c.data).map(u=>({path:"",message:u}));return R(e,200,{ok:d.length===0,issues:d,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?R(e,200,{workflow:l}):R(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return qe(t,e,d=>si(e,a,d,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),R(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return R(e,404,{error:"unknown workflows endpoint",path:n})}var Gu=["mesh"];function si(t,e,a,n){let r=la.safeParse(a);if(!r.success)return R(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=ca(o);if(s.length>0)return R(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return R(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return R(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,c=e.store.get(n.id);if(c)for(let d of Gu)!(d in l)&&d in c&&(o[d]=c[d])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),d=l?.yamlPath,u=!!d||/yaml round-trip failed/.test(c);return R(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:u?"yaml-authored":"save-failed",...d?{path:d}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function Xu(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,d=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!d)return R(e,200,{runs:u});let m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return qe(t,e,c=>{let d=c?.status;return d!=="paused"&&d!=="running"&&d!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,d)?R(e,200,{ok:!0,runId:l,status:d}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return Ku(t,e,a,l);let c=a.runs.get(l);return c?R(e,200,{run:c}):R(e,404,{error:"run not found"})}return R(e,404,{error:"unknown runs endpoint"})}function Ku(t,e,a,n){let r=a.runs.get(n);if(!r)return R(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
|
|
16149
16149
|
|
|
16150
16150
|
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(d);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
|
|
16151
16151
|
|
|
16152
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function qe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){R(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{R(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{R(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>R(e,400,{error:"body read failed",message:r.message})),!0}function R(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as
|
|
16152
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,d=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function qe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){R(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{R(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{R(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>R(e,400,{error:"body read failed",message:r.message})),!0}function R(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Am}from"fs";import{createRequire as Cm}from"module";var Ju=2048,li=/^[A-Za-z0-9_-]{8,256}$/;async function ci(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return Y(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):Vu()});if(n==="GET"&&a==="/api/app/alerts")return Y(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return Y(e,404,{error:"not found"});if(!s||l)return Y(e,503,{error:l});let c;try{c=await yt(t)}catch(h){return Y(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),k=h.map(g=>ce[g].field).join(", "),v=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${v}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return Y(e,400,{error:`${k} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return Y(e,200,{ok:!0,...S})}let d=Yu(c.endpoint,o.allowedHosts);if(!d){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(d,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!li.test(u)||typeof m!="string"||!li.test(m)?Y(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?Y(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:d,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function Vu(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Yu(t,e){if(typeof t!="string"||t.length>Ju)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}fn();var pi=50,Qu=280;async function ui(t,e,a,n,r,o){if(a!=="/api/app/announcements")return!1;if(n==="GET"){let s=o.prefs(),i=[],l=null;try{i=Zu(await o.recent(pi))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return di(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return di(e,404,{error:"not found"})}function mi(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=it();return r?new ir(r):null}}}function Zu(t){let e=[];for(let a of Array.isArray(t)?t:[]){let n=a;!n||n.kind!=="announce"||typeof n.id!="string"||typeof n.at!="string"||e.push({id:n.id.slice(0,64),text:Ha(typeof n.summary=="string"?n.summary:"",Qu),by:typeof n.agentId=="string"?Ha(n.agentId,100):null,node:Ha(typeof n.node=="string"?n.node:"",100),at:n.at.slice(0,40)})}return e.sort((a,n)=>(Date.parse(n.at)||0)-(Date.parse(a.at)||0)),e.slice(0,pi)}function Ha(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function di(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var em="operator",tm=50,fi=4,hi=500;function am(t){let e={channel:"app",chatId:t.chatId,sender:em,...t.spoken?{via:"voice"}:{}};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function gi(t,e,a,n){let{path:r,body:o}=am(e),s="",i=!1,l=[],c=new Map,d=(u,m,h)=>{let k=u!=="done",v=i?{text:ut(m,k),artifacts:[]}:pt(m,le.perMessage,k),{cleanText:S,ui:g}=u==="done"?ft(v.text):{cleanText:v.text,ui:void 0},p=i?void 0:Ba(g);return{status:u,text:S,tools:l,files:v.artifacts,...p?{ui:p}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return d("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of rm(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<tm){let k={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(k),h.id&&c.set(String(h.id),k)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return d("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return d("error",s,nm(h.error))}}return a.aborted?d("stopped",s):d("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?d("stopped",s):d("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function nm(t){let e=String(t||"The agent could not answer.");return wn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function Ba(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}});let r=(t.quickReplies??[]).slice(0,fi).map(s=>s.slice(0,hi));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,fi).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,hi)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*rm(t){let e=t.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:r,value:o}=await e.read();if(r)break;n+=a.decode(o,{stream:!0}).replace(/\r\n/g,`
|
|
16153
16153
|
`);let s;for(;(s=n.indexOf(`
|
|
16154
16154
|
|
|
16155
16155
|
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let d of i.split(`
|
|
@@ -16159,12 +16159,160 @@ data: ${JSON.stringify(s)}
|
|
|
16159
16159
|
|
|
16160
16160
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
16161
16161
|
|
|
16162
|
-
`)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function vi(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=
|
|
16163
|
-
`)){let n=bi(a);if(n)return qa(n,e)}return""}function
|
|
16164
|
-
`).map(bi).filter(Boolean);return a.length?qa(a[a.length-1],e):""}function bi(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function qa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Xt=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Kt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var xi=140;function Jt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${za(r||"",xi-18)||"something went wrong."}`:za(n,xi)||"Answered.";return{deviceId:t,title:qa(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var wi=8e3,
|
|
16162
|
+
`)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function vi(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=om(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:za(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function za(t,e=120){for(let a of t.split(`
|
|
16163
|
+
`)){let n=bi(a);if(n)return qa(n,e)}return""}function om(t,e=120){let a=t.split(`
|
|
16164
|
+
`).map(bi).filter(Boolean);return a.length?qa(a[a.length-1],e):""}function bi(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function qa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Xt=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Kt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var xi=140;function Jt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${za(r||"",xi-18)||"something went wrong."}`:za(n,xi)||"Answered.";return{deviceId:t,title:qa(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var wi=8e3,im=/^[A-Za-z0-9_.:-]{1,64}$/,Re=new Map,Fa=new Map,Ga=new Xt;function ki(){return Ga}async function _i(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??Ga;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await Si(o)});let i=o.store();if(!i)return H(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),H(e,200,{conversations:vi(r.id,dm(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let d=i.get(r.id,decodeURIComponent(l[1]));if(!d)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,d.id);let u=Re.get(d.id);return H(e,200,{...d,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let d=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=d&&Re.get(d.id);if(!d||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,d.id),Ei(e);let{id:m,title:h,node:k,nodeName:v,agent:S,agentName:g}=d;return e.write(Ua("conversation",{id:m,title:h,node:k,nodeName:v,agent:S,agentName:g})),e.write(Ua("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await yt(t,64*1024)}catch(d){return H(e,400,{error:d.message})}if(a==="/api/app/chat/stop"){let d=i.get(r.id,String(c.conversationId??""));if(!d)return H(e,404,{error:"no such conversation"});let u=Re.get(d.id);return u?(u.ac.abort(),Wa(d,o,r.name),H(e,200,{stopped:!0})):await Wa(d,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await cm(e,c,r,i,o),!0}function lm(t,e,a){let n=Fe(e.url),r=new Set,o=[];for(let s of t){let i=Fe(s.url),l=a.find(u=>Fe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,d=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:d.map(u=>{let m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Si(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return lm(e.nodes,t.daemon,a)}async function cm(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>wi){H(t,400,{error:`message must be 1\u2013${wi} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",v=typeof e.agent=="string"?e.agent:"";if(!im.test(v)){H(t,400,{error:"pick an agent"});return}let S=(await Si(r)).find(p=>p.target===k);if(!S){H(t,400,{error:`unknown node "${k}"`});return}if(!S.online){H(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(p=>p.id===v);if(!g){H(t,400,{error:`no agent "${v}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:v,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Re.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Gt(r.orphanLimitMs??18e5);Re.set(s.id,i);let{id:l,title:c,node:d,nodeName:u,agent:m,agentName:h}=s;Fa.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Ei(t),t.write(Ua("conversation",{id:l,title:c,node:d,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let k=e.spoken===!0,v=await gi(r.daemon,{node:d,agent:m,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(v.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Wa(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:v.text,status:v.status,at:Date.now(),...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...v.tools.length?{tools:v.tools}:{}},v.files)??[];i.broadcast("final",{status:v.status,content:v.text,...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let p={status:v.status,attached:g,appOpen:(r.presence??Ga).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Kt(p)&&r.notifyFinish(Jt(a.id,s,v.status,v.text,v.error)).catch(()=>{})}finally{Re.delete(l),Fa.delete(l),i.finish()}}function dm(){let t=[];for(let[e,a]of Fa){let n=Re.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Ei(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Ua(t,e){return`event: ${t}
|
|
16165
16165
|
data: ${JSON.stringify(e)}
|
|
16166
16166
|
|
|
16167
|
-
`}async function Wa(t,e,a){try{let n=Fe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Fe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Fe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Fe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as cm}from"stream";var dm=/^\/api\/app\/files\/([^/]+)$/,pm=15e3;async function Ai(t,e,a,n,r,o){let s=dm.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let d=await um(c.node,o);if(!d)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),pm),h;try{let p=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${d.url}${Fn}?${p}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let p=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,f,{error:p||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let v=h.headers.get("content-range");if(e.writeHead(h.status,{...Un(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=cm.fromWeb(h.body);return g.on("data",p=>{S+=p.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function um(t,e){if(t==="local")return{url:Ti(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Ti(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Ti(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var Ii=8e3;async function Mi(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Zn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Qn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let v=await Ne(t,Yn.bytes);if(!v)return Q(e,413,{error:er()});if(!v.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Ci(e,o.daemon,"/voice/transcribe",v,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,Ii):"";if(!d.trim())return Q(e,400,{error:"text is required"});if(!fm(c.messages,d))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Ci(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ci(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(mm(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function mm(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function fm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Ii&&a.content.startsWith(e)))}var hm=new Set(["ring","offer","answer","ice","hangup"]),Vt=/^[A-Za-z0-9_-]{4,64}$/,gm=128*1024;async function Li(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),d=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,gm);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=xm(c,r.nodeName);if(typeof d=="string")return P(e,400,{error:d});let u=Ri(d.to);if(u&&d.kind==="ring"){let m=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:u});return P(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return P(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Vt.test(l)?vm(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Vt.test(d))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:u},18e4);return P(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Qe(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Qe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Vt.test(l))return P(e,400,{error:"callId is required"});let c=await Qe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function Ri(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Qe(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function xm(t,e){let a=String(t?.kind??"");if(!hm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Vt.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!Ri(r))return"to must be bot:<agent id> for an agent";if(Xe(r)===Xe(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function vm(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var $i=`
|
|
16167
|
+
`}async function Wa(t,e,a){try{let n=Fe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Fe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Fe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Fe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as pm}from"stream";var um=/^\/api\/app\/files\/([^/]+)$/,mm=15e3;async function Ai(t,e,a,n,r,o){let s=um.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let d=await fm(c.node,o);if(!d)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),mm),h;try{let p=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${d.url}${Fn}?${p}`,{method:n,headers:{...d.token?{Authorization:`Bearer ${d.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let p=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,f,{error:p||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let v=h.headers.get("content-range");if(e.writeHead(h.status,{...Un(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&v?{"Content-Range":v}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=pm.fromWeb(h.body);return g.on("data",p=>{S+=p.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function fm(t,e){if(t==="local")return{url:Ti(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Ti(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Ti(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var Ii=8e3;async function Mi(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Zn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Qn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let v=await Ne(t,Yn.bytes);if(!v)return Q(e,413,{error:er()});if(!v.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return Ci(e,o.daemon,"/voice/transcribe",v,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let d=typeof s?.text=="string"?s.text.slice(0,Ii):"";if(!d.trim())return Q(e,400,{error:"text is required"});if(!gm(c.messages,d))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${d}`:d,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Ci(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Ci(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(hm(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function hm(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function gm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Ii&&a.content.startsWith(e)))}var xm=new Set(["ring","offer","answer","ice","hangup"]),Vt=/^[A-Za-z0-9_-]{4,64}$/,vm=128*1024;async function Li(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),d=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==d),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,vm);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=bm(c,r.nodeName);if(typeof d=="string")return P(e,400,{error:d});let u=Ri(d.to);if(u&&d.kind==="ring"){let m=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:d.callId,agentId:u});return P(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(d),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return P(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Vt.test(l)?ym(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let d=String(c?.callId??"");if(!Vt.test(d))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(d)}/look`,{note:u},18e4);return P(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Qe(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(d=>({id:d.id,agentId:d.agentId,reason:d.reason,createdAt:d.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Qe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Vt.test(l))return P(e,400,{error:"callId is required"});let c=await Qe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function Ri(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Qe(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function bm(t,e){let a=String(t?.kind??"");if(!xm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Vt.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!Ri(r))return"to must be bot:<agent id> for an agent";if(Xe(r)===Xe(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function ym(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var $i=`
|
|
16168
|
+
:root {
|
|
16169
|
+
--ax-bg: #fff; --ax-surface: #fff; --ax-surface-2: #f4f5f7; --ax-surface-3: #f6f7f9;
|
|
16170
|
+
--ax-text: #0b0d10; --ax-text-2: #5a616c; --ax-border: #e5e7eb;
|
|
16171
|
+
--ax-accent: #1f66e5; --ax-accent-2: #1f66e5; --ax-accent-t: #e8f0ff;
|
|
16172
|
+
--ax-radius: 20px; --ax-radius-sm: 12px; --ax-border-w: 1px;
|
|
16173
|
+
--phone-bubble: #e8f0ff; --phone-green: #1e8e4e;
|
|
16174
|
+
}
|
|
16175
|
+
:root[data-theme=dark] {
|
|
16176
|
+
--ax-bg: #14161a; --ax-surface: #1c1f24; --ax-surface-2: #1b1e23; --ax-surface-3: #101215;
|
|
16177
|
+
--ax-text: #f2f4f7; --ax-text-2: #a3aab5; --ax-border: #2a2e35;
|
|
16178
|
+
--ax-accent: #6aa0ff; --ax-accent-2: #6aa0ff; --ax-accent-t: #1c2b47;
|
|
16179
|
+
--phone-bubble: #1d2f52; --phone-green: #3dbe74;
|
|
16180
|
+
}
|
|
16181
|
+
[hidden] { display: none !important; }
|
|
16182
|
+
main > .sw-peek[hidden] { display: block !important; }
|
|
16183
|
+
main > #panel-chat.sw-peek[hidden] { display: flex !important; }
|
|
16184
|
+
body { overflow: hidden; font-size: 16px; -webkit-font-smoothing: antialiased; }
|
|
16185
|
+
body > * { flex-shrink: 0; }
|
|
16186
|
+
.bar { min-height: 56px; gap: 8px; padding: calc(4px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right)) 4px calc(20px + env(safe-area-inset-left)); background: var(--ax-bg); border: 0; }
|
|
16187
|
+
.bar > div:first-child { min-width: 0; flex: 1; }
|
|
16188
|
+
.bar h1 { font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
|
|
16189
|
+
.who { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
16190
|
+
.bar-btns { flex: none; }
|
|
16191
|
+
.icon-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0 12px; gap: 8px; }
|
|
16192
|
+
.icon-btn svg, .cx-head svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
16193
|
+
#cam-btn span { font-size: 14px; font-weight: 500; }
|
|
16194
|
+
body:has(#tab-chat[aria-selected=false]) > .bar { display: none; }
|
|
16195
|
+
body:has(#tab-chat[aria-selected=false]) main { padding-top: calc(16px + env(safe-area-inset-top)); }
|
|
16196
|
+
.cx-msg .md th, .cx-msg .md td { white-space: nowrap; padding: 8px 12px; }
|
|
16197
|
+
.cx-msg .md table { max-width: 100%; }
|
|
16198
|
+
|
|
16199
|
+
.icon-btn, .cam-share { background: var(--ax-surface); }
|
|
16200
|
+
.offline { background: #ffc94d; color: #2b1d00; font-size: 13px; }
|
|
16201
|
+
main { flex: 1 1 0; min-width: 0; overflow-x: hidden; padding-top: 8px; }
|
|
16202
|
+
main h2 { font-size: 28px; font-weight: 600; letter-spacing: -.02em; }
|
|
16203
|
+
#panel-chat { height: 100%; min-height: 0 !important; }
|
|
16204
|
+
.cx { min-height: 0; gap: 0; }
|
|
16205
|
+
.cx-top { display: flex; align-items: center; justify-content: flex-end; flex: none; position: static; margin: 0; padding: 0 0 8px; gap: 6px; }
|
|
16206
|
+
.cx-head { flex: none; justify-content: flex-end; gap: 8px; }
|
|
16207
|
+
.cx-head .fx-btn { width: 44px; padding: 10px; min-height: 44px; border-radius: 22px; }
|
|
16208
|
+
.cs { flex: 1; min-width: 0; }
|
|
16209
|
+
.cs-list { gap: 8px; touch-action: pan-x; }
|
|
16210
|
+
.cs-state { font-weight: 400; color: var(--ax-text-2); }
|
|
16211
|
+
.cs-chip { border-color: var(--ax-border); background: var(--ax-surface); }
|
|
16212
|
+
.cs-chip[aria-current=true] { border-color: #2979ff; background: var(--ax-accent-t); }
|
|
16213
|
+
.cx-log { min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; gap: 16px; padding: 8px 0 16px; }
|
|
16214
|
+
#cx-empty { padding: 16px 4px; }
|
|
16215
|
+
.cx-msg { flex: none; padding: 12px 14px; font-size: 16px; line-height: 1.45; }
|
|
16216
|
+
.cx-user { max-width: 80%; background: var(--phone-bubble); border: 0; border-radius: 20px 20px 6px 20px; }
|
|
16217
|
+
.cx-agent { border-radius: 6px 20px 20px 20px; }
|
|
16218
|
+
.cx-msg .md pre { border: 1px solid var(--ax-border); padding: 10px 12px; touch-action: pan-x; }
|
|
16219
|
+
.cx-msg .md table { touch-action: pan-x; }
|
|
16220
|
+
.cx-tools summary { min-height: 44px; }
|
|
16221
|
+
.vx { flex: none; position: static; margin: 0 -16px -16px; padding: 12px 16px 10px; gap: 12px; border-top: 1px solid var(--ax-border); }
|
|
16222
|
+
.cx-pick { flex: none; flex-direction: row; align-items: center; gap: 6px; min-height: 44px; max-width: 100%; padding: 0 14px; border-radius: 22px; font-size: 15px; }
|
|
16223
|
+
.cx-pick-intro { color: var(--ax-text-2); flex: none; }
|
|
16224
|
+
.cx-pick::after { content: '\u2304'; margin-left: 4px; }
|
|
16225
|
+
.cx-pick-label { font-weight: 600; }
|
|
16226
|
+
.cx-pick-sub { display: none; }
|
|
16227
|
+
.vx-row { gap: 32px; }
|
|
16228
|
+
.vx-side { width: 52px; height: 52px; color: var(--ax-text); }
|
|
16229
|
+
.vx-orb { position: relative; width: 96px; height: 96px; flex: none; }
|
|
16230
|
+
.vx-orb canvas { position: absolute; width: 160px; height: 160px; top: -32px; left: -32px; }
|
|
16231
|
+
.vx-mic { position: absolute; width: 34px; height: 34px; left: 31px; top: 31px; fill: none; stroke: #fff; stroke-width: 1.9; stroke-linecap: round; pointer-events: none; }
|
|
16232
|
+
.vx-status { font-size: 14px; min-height: 18px; line-height: 1.3; }
|
|
16233
|
+
.vx .cx-composer { order: 3; }
|
|
16234
|
+
.cx:not(.cx-typing-on) .cx-composer:has(#cx-stop[hidden]) { display: none; }
|
|
16235
|
+
.cx-typing-on .vx-row { gap: 24px; }
|
|
16236
|
+
.cx-typing-on .vx-orb { width: 44px; height: 44px; }
|
|
16237
|
+
.cx-typing-on .vx-orb canvas { width: 74px; height: 74px; top: -15px; left: -15px; }
|
|
16238
|
+
.cx-typing-on .vx-mic { width: 22px; height: 22px; top: 11px; left: 11px; }
|
|
16239
|
+
.cx-typing-on .vx { gap: 8px; }
|
|
16240
|
+
.cam-primary { background: #1f66e5; border-color: #1f66e5; color: #fff; }
|
|
16241
|
+
.cx-send { background: #1f66e5; color: #fff; border: 0; border-radius: 22px; }
|
|
16242
|
+
.tabs { flex: none; position: relative; padding: 2px env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); background: var(--ax-bg); }
|
|
16243
|
+
.tabs [role=tab] { position: relative; min-width: 0; min-height: 56px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 12px; font-weight: 500; border-radius: 16px; }
|
|
16244
|
+
.tabs [role=tab][aria-selected=true], [data-theme=dark] .tabs [role=tab][aria-selected=true] { background: transparent; color: var(--ax-accent); font-weight: 600; }
|
|
16245
|
+
.tab-icon { display: grid; place-items: center; width: 56px; height: 30px; border-radius: 16px; }
|
|
16246
|
+
.tab-icon svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
16247
|
+
.tabs::before { content: ''; position: absolute; pointer-events: none; top: 4px; width: 56px; height: 30px; border-radius: 16px; background: var(--ax-accent-t); left: calc((var(--tab-position, 0) + .5) * 25% - 28px); }
|
|
16248
|
+
.tab-icon { position: relative; }
|
|
16249
|
+
.tabs button:active .tab-icon { background: var(--ax-surface-2); transform: scale(.92); }
|
|
16250
|
+
.fx-card { border-radius: 16px; padding: 16px; }
|
|
16251
|
+
.fx-row > h3, .fx-row > h4, .fx-row > strong { min-width: 0; overflow-wrap: anywhere; }
|
|
16252
|
+
.fx-row > .fx-muted { text-align: right; }
|
|
16253
|
+
.fx-working { color: var(--ax-accent); font-size: 14px; }
|
|
16254
|
+
.fx-sub { font-weight: 600; font-size: 14px; margin-top: 24px; }
|
|
16255
|
+
.fx-machine { display: flex; align-items: center; gap: 12px; }
|
|
16256
|
+
.fx-machine svg { flex: none; width: 44px; height: 44px; padding: 10px; border-radius: 12px; background: var(--ax-surface-2); fill: none; stroke: currentColor; stroke-width: 1.7; }
|
|
16257
|
+
.fx-offline { border-style: dashed; background: var(--ax-surface-2); }
|
|
16258
|
+
.fx-offline .fx-off { background: transparent; color: var(--ax-text-2); }
|
|
16259
|
+
.fx-on { background: transparent; color: var(--phone-green); }
|
|
16260
|
+
.fx-switch { height: 44px; border-radius: 22px; }
|
|
16261
|
+
.fx-switch span { top: 9px; }
|
|
16262
|
+
.fx-sheet { max-height: 85dvh; border-radius: 24px 24px 0 0; padding: 0 0 env(safe-area-inset-bottom); overscroll-behavior: contain; }
|
|
16263
|
+
.fx-sheet::backdrop { background: rgb(11 13 16 / .34); }
|
|
16264
|
+
[data-theme=dark] .fx-sheet { background: #1f2228; }
|
|
16265
|
+
[data-theme=dark] .fx-sheet::backdrop { background: rgb(0 0 0 / .55); }
|
|
16266
|
+
.sheet-handle { display: block; width: 100%; height: 44px; padding: 0; border: 0; background: transparent; touch-action: none; cursor: grab; }
|
|
16267
|
+
.sheet-handle::after { content: ''; display: block; width: 36px; height: 5px; border-radius: 3px; margin: auto; background: var(--ax-text-2); opacity: .5; }
|
|
16268
|
+
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 0 20px 8px; gap: 8px; }
|
|
16269
|
+
.sheet-head h3 { margin: 0; font-size: 20px; }
|
|
16270
|
+
.cx-sheet { border: 0; border-radius: 0; padding: 0 20px 20px; max-height: 60dvh; background: transparent; }
|
|
16271
|
+
.cx-sheet li button { min-height: 48px; background: transparent; border: 0; border-bottom: 1px solid var(--ax-border); border-radius: 0; }
|
|
16272
|
+
#al-list { background: var(--ax-surface); border: 1px solid var(--ax-border); border-radius: 20px; overflow: hidden; }
|
|
16273
|
+
#al-list li { padding: 16px; }
|
|
16274
|
+
#al-list li:first-child { border-top: 0; }
|
|
16275
|
+
#al-list p { line-height: 1.45; margin: 8px 0 0; overflow-wrap: anywhere; }
|
|
16276
|
+
#al-list a { display: inline-flex; align-items: center; min-height: 44px; color: var(--ax-accent); }
|
|
16277
|
+
.tabs .has-unread .tab-icon::after { content: ''; position: absolute; width: 7px; height: 7px; border-radius: 50%; background: #2979ff; top: 6px; margin-left: 24px; }
|
|
16278
|
+
#al-list .al-unread { background: var(--ax-accent-t); }
|
|
16279
|
+
.al-item { width: 100%; min-height: 44px; padding: 0; font: inherit; text-align: left; border: 0; color: inherit; background: none; cursor: pointer; }
|
|
16280
|
+
.al-body { display: block; margin-top: 8px; line-height: 1.45; overflow-wrap: anywhere; }
|
|
16281
|
+
.al-unread strong::before { content: '\u25CF'; color: var(--ax-accent); margin-right: 8px; font-size: 10px; }
|
|
16282
|
+
main > #panel-chat.sw-peek { height: 100%; padding-top: 8px; }
|
|
16283
|
+
@media (max-width: 360px) { #cam-btn span { display: none; } .bar { padding-left: 12px; } .bar-btns { gap: 4px; } .vx-row { gap: 24px; } }
|
|
16284
|
+
@media (max-height: 540px) { .vx { gap: 4px; padding-top: 4px; } .cx-top { padding-bottom: 4px; } }
|
|
16285
|
+
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } }
|
|
16286
|
+
`;var Pi=`
|
|
16287
|
+
window.AXSheet = function (sheet, onClose) {
|
|
16288
|
+
var handle = document.createElement('button');
|
|
16289
|
+
handle.type = 'button'; handle.className = 'sheet-handle';
|
|
16290
|
+
handle.setAttribute('aria-label', 'Close sheet');
|
|
16291
|
+
sheet.insertBefore(handle, sheet.firstChild);
|
|
16292
|
+
function close() { sheet.close('cancel'); }
|
|
16293
|
+
handle.addEventListener('click', function (ev) { if (distance > 5) { ev.preventDefault(); distance = 0; return; } close(); });
|
|
16294
|
+
sheet.addEventListener('click', function (ev) {
|
|
16295
|
+
if (ev.target !== sheet) return;
|
|
16296
|
+
var r = sheet.getBoundingClientRect();
|
|
16297
|
+
if (ev.clientX < r.left || ev.clientX > r.right || ev.clientY < r.top || ev.clientY > r.bottom) close();
|
|
16298
|
+
});
|
|
16299
|
+
var start = null, distance = 0;
|
|
16300
|
+
handle.addEventListener('pointerdown', function (ev) {
|
|
16301
|
+
if (ev.button > 0) return;
|
|
16302
|
+
start = ev.clientY; distance = 0;
|
|
16303
|
+
handle.setPointerCapture(ev.pointerId);
|
|
16304
|
+
});
|
|
16305
|
+
handle.addEventListener('pointermove', function (ev) {
|
|
16306
|
+
if (start == null) return;
|
|
16307
|
+
distance = Math.max(0, ev.clientY - start);
|
|
16308
|
+
sheet.style.transform = 'translateY(' + distance + 'px)';
|
|
16309
|
+
});
|
|
16310
|
+
function reset() { start = null; sheet.style.transform = ''; }
|
|
16311
|
+
handle.addEventListener('pointerup', function () { var dismiss = distance > 90; reset(); if (dismiss) close(); });
|
|
16312
|
+
handle.addEventListener('pointercancel', reset);
|
|
16313
|
+
sheet.addEventListener('close', function () { reset(); if (onClose) onClose(); });
|
|
16314
|
+
};
|
|
16315
|
+
`;var ji=`
|
|
16168
16316
|
(function () {
|
|
16169
16317
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
16170
16318
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -16210,12 +16358,14 @@ data: ${JSON.stringify(e)}
|
|
|
16210
16358
|
// One shared bottom sheet for every confirmation and the follow-up box.
|
|
16211
16359
|
var sheet = document.createElement('dialog');
|
|
16212
16360
|
sheet.className = 'fx-sheet';
|
|
16361
|
+
sheet.setAttribute('aria-labelledby', 'fx-title');
|
|
16213
16362
|
sheet.innerHTML = '<form method="dialog"><h3 id="fx-title"></h3><p id="fx-text"></p>' +
|
|
16214
16363
|
'<label id="fx-field" hidden><span>Message</span><textarea id="fx-input" rows="3"></textarea></label>' +
|
|
16215
16364
|
'<p id="fx-error" class="fx-error" role="alert"></p>' +
|
|
16216
16365
|
'<div class="fx-actions"><button value="cancel" class="fx-btn">Cancel</button>' +
|
|
16217
16366
|
'<button value="ok" id="fx-ok" class="fx-btn fx-primary">OK</button></div></form>';
|
|
16218
16367
|
document.body.appendChild(sheet);
|
|
16368
|
+
window.AXSheet(sheet);
|
|
16219
16369
|
var pending = null;
|
|
16220
16370
|
function ask(opts) {
|
|
16221
16371
|
document.getElementById('fx-title').textContent = opts.title;
|
|
@@ -16260,9 +16410,9 @@ data: ${JSON.stringify(e)}
|
|
|
16260
16410
|
}
|
|
16261
16411
|
|
|
16262
16412
|
function statusPill(n) {
|
|
16263
|
-
if (!n.reachable) return '<span class="fx-pill fx-off">Offline</span>';
|
|
16413
|
+
if (!n.reachable) return '<span class="fx-pill fx-off"><span aria-hidden="true">\u2298 </span>Offline</span>';
|
|
16264
16414
|
if (n.restart) return '<span class="fx-pill fx-warn">Restart ' + esc(n.restart.state) + '</span>';
|
|
16265
|
-
return '<span class="fx-pill fx-on">Online</span>';
|
|
16415
|
+
return '<span class="fx-pill fx-on"><span aria-hidden="true">\u25CF </span>Online</span>';
|
|
16266
16416
|
}
|
|
16267
16417
|
function renderFleet(data) {
|
|
16268
16418
|
// Redraws every 15 seconds; keep the sections the user opened open.
|
|
@@ -16273,23 +16423,20 @@ data: ${JSON.stringify(e)}
|
|
|
16273
16423
|
if (!data.nodes.length) html += '<p class="soon">No machines found.</p>';
|
|
16274
16424
|
data.nodes.forEach(function (n, i) {
|
|
16275
16425
|
var running = n.agents.reduce(function (sum, a) { return sum + (a.active || 0); }, 0);
|
|
16276
|
-
html += '<article class="fx-card"><div class="fx-row"><h3>' + esc(n.name) + '</h3>' + statusPill(n) + '</div>';
|
|
16426
|
+
html += '<article class="fx-card' + (n.reachable ? '' : ' fx-offline') + '"><div class="fx-row"><h3 class="fx-machine"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v12H4zM2 20h20' + (n.reachable ? '' : 'M2 2l20 20') + '"/></svg>' + esc(n.name) + '</h3>' + statusPill(n) + '</div>';
|
|
16277
16427
|
if (!n.reachable) {
|
|
16278
16428
|
html += '<p class="fx-muted">Not reachable' + (n.error ? ': ' + esc(n.error) : '') + '. The rest of the fleet still works.</p></article>';
|
|
16279
16429
|
return;
|
|
16280
16430
|
}
|
|
16281
16431
|
html += '<p class="fx-muted">' + esc(uptime(n.uptimeSec)) + ' \xB7 ' + plural(n.agents.length, 'agent') + ' \xB7 ' + running + ' running \xB7 schedules today: ' +
|
|
16282
16432
|
n.crons.today.success + ' ok, ' + n.crons.today.failed + ' failed</p>';
|
|
16283
|
-
html += '<
|
|
16284
|
-
(n.restart ? '<button type="button" class="fx-btn" data-act="unrestart" data-i="' + i + '">Cancel restart</button>'
|
|
16285
|
-
: '<button type="button" class="fx-btn fx-danger-o" data-act="restart" data-i="' + i + '">Restart when idle</button>') + '</div>';
|
|
16286
|
-
html += '<details data-key="' + esc(n.url) + '|agents"' + (openKeys[n.url + '|agents'] ? ' open' : '') + '><summary>Agents (' + n.agents.length + ')</summary><ul class="fx-list">';
|
|
16433
|
+
html += '<ul class="fx-list fx-agents">';
|
|
16287
16434
|
n.agents.forEach(function (a) {
|
|
16288
16435
|
html += '<li><div class="fx-row"><strong>' + esc(a.name) + '</strong><span class="fx-muted">' +
|
|
16289
16436
|
(a.active ? a.active + ' running' : (a.lastActive ? ago(a.lastActive) : 'idle')) + (a.errors ? ' \xB7 ' + a.errors + ' errors' : '') + '</span></div>' +
|
|
16290
16437
|
(a.last ? '<p class="fx-muted' + (a.last.ok ? '' : ' fx-bad') + '">' + esc(a.last.text) + '</p>' : '') + '</li>';
|
|
16291
16438
|
});
|
|
16292
|
-
html += '</ul
|
|
16439
|
+
html += '</ul><details data-key="' + esc(n.url) + '|crons"' + (openKeys[n.url + '|crons'] ? ' open' : '') + '><summary>Schedules (' + n.crons.items.length + ')</summary><ul class="fx-list">';
|
|
16293
16440
|
n.crons.items.forEach(function (c, j) {
|
|
16294
16441
|
var last = c.last ? '<span class="fx-pill ' + (c.last.status === 'success' ? 'fx-on' : 'fx-off') + '">' + esc(c.last.status) + '</span>' : '';
|
|
16295
16442
|
html += '<li><div class="fx-row"><strong>' + esc(c.id) + '</strong>' +
|
|
@@ -16298,7 +16445,11 @@ data: ${JSON.stringify(e)}
|
|
|
16298
16445
|
'<p class="fx-muted">' + esc(c.schedule) + ' \xB7 ' + esc(c.agent) + (c.consecutiveErrors ? ' \xB7 failed ' + c.consecutiveErrors + ' times in a row' : '') + ' ' + last + '</p>' +
|
|
16299
16446
|
(c.last && c.last.text ? '<p class="fx-muted">' + esc(c.last.text) + '</p>' : '') + '</li>';
|
|
16300
16447
|
});
|
|
16301
|
-
html += '</ul></details
|
|
16448
|
+
html += '</ul></details>';
|
|
16449
|
+
html += '<details data-key="' + esc(n.url) + '|manage"' + (openKeys[n.url + '|manage'] ? ' open' : '') + '><summary>Manage computer</summary><div class="fx-row fx-gap"><button type="button" class="fx-btn" data-act="reload" data-i="' + i + '">Reload config</button>' +
|
|
16450
|
+
(n.restart ? '<button type="button" class="fx-btn" data-act="unrestart" data-i="' + i + '">Cancel restart</button>'
|
|
16451
|
+
: '<button type="button" class="fx-btn fx-danger-o" data-act="restart" data-i="' + i + '">Restart when idle</button>') + '</div></details>';
|
|
16452
|
+
html += '</article>';
|
|
16302
16453
|
});
|
|
16303
16454
|
fleetPanel.innerHTML = html;
|
|
16304
16455
|
fleetPanel._data = data;
|
|
@@ -16312,7 +16463,7 @@ data: ${JSON.stringify(e)}
|
|
|
16312
16463
|
html += '<h3 class="fx-sub">Needs you (' + items.length + ')</h3>';
|
|
16313
16464
|
if (!items.length) html += '<p class="fx-muted">Nothing is waiting for a decision.</p>';
|
|
16314
16465
|
items.forEach(function (x, k) {
|
|
16315
|
-
html += '<article class="fx-card"><h4>' + esc(x.it.title) + '</h4><p>' + esc(x.it.ask) + '</p>' +
|
|
16466
|
+
html += '<article class="fx-card"><div class="fx-row"><h4>' + esc(x.it.title) + '</h4><span class="fx-pill fx-warn">\u2161 Waiting</span></div><p>' + esc(x.it.ask) + '</p>' +
|
|
16316
16467
|
(x.it.recommend ? '<p class="fx-muted">Suggested: ' + esc(x.it.recommend) + '</p>' : '') +
|
|
16317
16468
|
'<p class="fx-muted">' + esc(x.it.raisedBy || '') + ' \xB7 ' + esc(x.node.nodeName) + '</p>' +
|
|
16318
16469
|
'<div class="fx-row fx-gap"><button type="button" class="fx-btn fx-primary" data-act="decide" data-k="' + k + '" data-v="yes">Yes</button>' +
|
|
@@ -16323,7 +16474,7 @@ data: ${JSON.stringify(e)}
|
|
|
16323
16474
|
html += '<h3 class="fx-sub">Running now (' + act.tasks.length + ')</h3>';
|
|
16324
16475
|
if (!act.tasks.length) html += '<p class="fx-muted">No agent is working right now.</p>';
|
|
16325
16476
|
act.tasks.forEach(function (t, k) {
|
|
16326
|
-
html += '<article class="fx-card"><div class="fx-row"><h4>' + esc(t.agentName) + '</h4><span class="fx-muted">' + esc(ago(t.startedAt)) + '</span></div>' +
|
|
16477
|
+
html += '<article class="fx-card"><div class="fx-row"><h4>' + esc(t.agentName) + '</h4><span class="fx-muted">' + esc(ago(t.startedAt)) + '</span></div><p class="fx-working"><span aria-hidden="true">\u25D4</span> Working</p>' +
|
|
16327
16478
|
'<p>' + esc(t.preview) + '</p><p class="fx-muted">' + esc(t.nodeName) + ' \xB7 ' + esc(t.channel) + '</p>' +
|
|
16328
16479
|
'<div class="fx-row fx-gap"><button type="button" class="fx-btn" data-act="followup" data-k="' + k + '">Follow up</button>' +
|
|
16329
16480
|
'<button type="button" class="fx-btn fx-danger-o" data-act="cancel" data-k="' + k + '">Stop</button></div></article>';
|
|
@@ -16402,13 +16553,13 @@ data: ${JSON.stringify(e)}
|
|
|
16402
16553
|
[fleetPanel, activityPanel].forEach(function (p) {
|
|
16403
16554
|
if (!p.querySelector('.fx-status')) p.insertAdjacentHTML('beforeend', '<p class="fx-status" role="status" aria-live="polite"></p>');
|
|
16404
16555
|
});
|
|
16405
|
-
document.
|
|
16556
|
+
document.addEventListener('ax-tab', function () { setTimeout(refresh, 0); });
|
|
16406
16557
|
document.addEventListener('visibilitychange', refresh);
|
|
16407
16558
|
window.addEventListener('online', refresh);
|
|
16408
16559
|
setInterval(refresh, 15000);
|
|
16409
16560
|
refresh();
|
|
16410
16561
|
})();
|
|
16411
|
-
`;var
|
|
16562
|
+
`;var Oi=`
|
|
16412
16563
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
16413
16564
|
.fx-head h2 { margin: 4px 0 0; }
|
|
16414
16565
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -16465,7 +16616,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16465
16616
|
}
|
|
16466
16617
|
.fx-error:empty { display: none; }
|
|
16467
16618
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
16468
|
-
`;var
|
|
16619
|
+
`;var Ni=`
|
|
16469
16620
|
(function () {
|
|
16470
16621
|
var panel = document.getElementById('panel-alerts');
|
|
16471
16622
|
if (!panel) return;
|
|
@@ -16476,7 +16627,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16476
16627
|
'<div id="al-finish" class="fx-row al-finish" hidden><p id="al-finish-l">When a chat answer finishes<small>Only for conversations you are not looking at</small></p>' +
|
|
16477
16628
|
'<button type="button" id="al-finish-sw" class="fx-switch" role="switch" aria-checked="true" aria-labelledby="al-finish-l"><span></span></button></div>' +
|
|
16478
16629
|
'<p id="al-error" class="fx-error fx-bad" role="alert"></p></div>' +
|
|
16479
|
-
'<h3 class="fx-sub">Recent</h3><ul id="al-list" class="fx-list"></ul>';
|
|
16630
|
+
'<div id="al-recent-head" class="fx-row"><h3 class="fx-sub">Recent</h3><button type="button" id="al-read-all" class="fx-btn">Mark all read</button></div><ul id="al-list" class="fx-list"></ul>';
|
|
16480
16631
|
var pill = document.getElementById('al-pill');
|
|
16481
16632
|
var text = document.getElementById('al-text');
|
|
16482
16633
|
var btn = document.getElementById('al-btn');
|
|
@@ -16619,19 +16770,49 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16619
16770
|
}).catch(function (e) { err.textContent = e.message; }).then(function () { finishSw.disabled = false; });
|
|
16620
16771
|
});
|
|
16621
16772
|
|
|
16773
|
+
var read = [], recent = [];
|
|
16774
|
+
try { var saved = JSON.parse(localStorage.getItem('ax-alerts-read') || '[]'); if (Array.isArray(saved)) read = saved.slice(-200); } catch (e) {}
|
|
16775
|
+
function key(it) { return String(it.id) + ':' + String(it.at); }
|
|
16776
|
+
function saveRead() { read = read.slice(-200); try { localStorage.setItem('ax-alerts-read', JSON.stringify(read)); } catch (e) {} }
|
|
16777
|
+
function paintRecent() {
|
|
16778
|
+
var unread = recent.filter(function (it) { return read.indexOf(key(it)) < 0; }).length;
|
|
16779
|
+
var tab = document.getElementById('tab-alerts');
|
|
16780
|
+
tab.classList.toggle('has-unread', unread > 0);
|
|
16781
|
+
tab.setAttribute('aria-label', unread ? 'Alerts, ' + unread + ' unread' : 'Alerts');
|
|
16782
|
+
document.getElementById('al-read-all').disabled = !unread;
|
|
16783
|
+
if (!recent.length) { list.innerHTML = '<li class="fx-muted">No notifications yet.</li>'; return; }
|
|
16784
|
+
list.innerHTML = recent.map(function (it, i) {
|
|
16785
|
+
var unseen = read.indexOf(key(it)) < 0;
|
|
16786
|
+
var link = /^https?:/i.test(it.url || '')
|
|
16787
|
+
? '<a href="' + esc(it.url) + '" target="_blank" rel="noopener noreferrer">Open</a>'
|
|
16788
|
+
: /^[/]app#chat=c[a-z0-9]+$/.test(it.url || '') ? '<a href="' + esc(it.url) + '">Open</a>' : '';
|
|
16789
|
+
return '<li data-alert="' + i + '" class="' + (unseen ? 'al-unread' : '') + '"><button type="button" class="al-item" aria-label="' + esc(it.title + (unseen ? ', unread. Mark as read' : ', read')) + '">' +
|
|
16790
|
+
'<span class="fx-row"><strong>' + esc(it.title) + '</strong><span class="fx-muted">' + esc(ago(it.at)) + '</span></span>' +
|
|
16791
|
+
'<span class="al-body">' + esc(it.body) + '</span></button>' + link + '</li>';
|
|
16792
|
+
}).join('');
|
|
16793
|
+
}
|
|
16794
|
+
list.addEventListener('click', function (ev) {
|
|
16795
|
+
var row = ev.target.closest('[data-alert]');
|
|
16796
|
+
if (!row) return;
|
|
16797
|
+
var it = recent[+row.getAttribute('data-alert')];
|
|
16798
|
+
if (!it || read.indexOf(key(it)) >= 0) return;
|
|
16799
|
+
read.push(key(it)); saveRead();
|
|
16800
|
+
// Do not replace a focused button or interrupt a link's default action.
|
|
16801
|
+
row.classList.remove('al-unread');
|
|
16802
|
+
row.querySelector('button').setAttribute('aria-label', it.title + ', read');
|
|
16803
|
+
var unread = recent.filter(function (x) { return read.indexOf(key(x)) < 0; }).length;
|
|
16804
|
+
var tab = document.getElementById('tab-alerts');
|
|
16805
|
+
tab.classList.toggle('has-unread', unread > 0);
|
|
16806
|
+
tab.setAttribute('aria-label', unread ? 'Alerts, ' + unread + ' unread' : 'Alerts');
|
|
16807
|
+
document.getElementById('al-read-all').disabled = !unread;
|
|
16808
|
+
});
|
|
16809
|
+
document.getElementById('al-read-all').addEventListener('click', function () {
|
|
16810
|
+
recent.forEach(function (it) { if (read.indexOf(key(it)) < 0) read.push(key(it)); });
|
|
16811
|
+
saveRead(); paintRecent();
|
|
16812
|
+
});
|
|
16622
16813
|
function loadRecent() {
|
|
16623
16814
|
return api('GET', '/api/app/alerts').then(function (b) {
|
|
16624
|
-
|
|
16625
|
-
if (!items.length) { list.innerHTML = '<li class="fx-muted">No notifications yet.</li>'; return; }
|
|
16626
|
-
list.innerHTML = items.map(function (it) {
|
|
16627
|
-
// Only web links: a button URL comes from an agent's message.
|
|
16628
|
-
// A finished chat answer links back into the app (/app#chat=<id>).
|
|
16629
|
-
var link = /^https?:/i.test(it.url || '')
|
|
16630
|
-
? ' <a href="' + esc(it.url) + '" target="_blank" rel="noopener noreferrer">Open</a>'
|
|
16631
|
-
: /^[/]app#chat=c[a-z0-9]+$/.test(it.url || '') ? ' <a href="' + esc(it.url) + '">Open</a>' : '';
|
|
16632
|
-
return '<li><div class="fx-row"><strong>' + esc(it.title) + '</strong><span class="fx-muted">' + esc(ago(it.at)) + '</span></div>' +
|
|
16633
|
-
'<p>' + esc(it.body) + link + '</p></li>';
|
|
16634
|
-
}).join('');
|
|
16815
|
+
recent = b.items || []; paintRecent();
|
|
16635
16816
|
}).catch(function (e) { list.innerHTML = '<li class="fx-bad">Could not load notifications: ' + esc(e.message) + '</li>'; });
|
|
16636
16817
|
}
|
|
16637
16818
|
|
|
@@ -16646,7 +16827,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16646
16827
|
refresh();
|
|
16647
16828
|
loadRecent();
|
|
16648
16829
|
})();
|
|
16649
|
-
`;var
|
|
16830
|
+
`;var Di=`
|
|
16650
16831
|
(function () {
|
|
16651
16832
|
var panel = document.getElementById('panel-alerts');
|
|
16652
16833
|
if (!panel) return;
|
|
@@ -16695,7 +16876,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16695
16876
|
card.appendChild(err);
|
|
16696
16877
|
card.appendChild(list);
|
|
16697
16878
|
// Above "Recent", under the notifications card.
|
|
16698
|
-
var recent = panel.querySelector('
|
|
16879
|
+
var recent = panel.querySelector('#al-recent-head');
|
|
16699
16880
|
if (recent) panel.insertBefore(card, recent); else panel.appendChild(card);
|
|
16700
16881
|
|
|
16701
16882
|
var busy = false;
|
|
@@ -16759,20 +16940,20 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16759
16940
|
}
|
|
16760
16941
|
load();
|
|
16761
16942
|
})();
|
|
16762
|
-
`;var
|
|
16943
|
+
`;var Hi=`
|
|
16763
16944
|
(function () {
|
|
16764
16945
|
var panel = document.getElementById('panel-chat');
|
|
16765
16946
|
var V = window.AXChatView;
|
|
16766
16947
|
if (!panel || !V || !window.AXChatSheets || !window.AXChatLog) return;
|
|
16767
|
-
//
|
|
16768
|
-
//
|
|
16948
|
+
// History and New stay above the scrolling log. Voice moves the agent
|
|
16949
|
+
// picker into the bottom dock; its lists open in a native modal sheet.
|
|
16769
16950
|
panel.innerHTML = '<h2 class="cx-sr">Chat</h2><div class="cx"><div class="cx-top">' +
|
|
16770
|
-
'<div class="cx-head"><button type="button" id="cx-pick" class="cx-pick" aria-controls="cx-picker" aria-expanded="false">' +
|
|
16771
|
-
'<span class="cx-pick-label">Choose an agent</span><span class="cx-pick-sub">Tap to see the agents on your machines</span></button>' +
|
|
16772
|
-
'<button type="button" id="cx-history-btn" class="fx-btn" aria-controls="cx-history" aria-expanded="false"
|
|
16773
|
-
'<button type="button" id="cx-new" class="fx-btn"
|
|
16774
|
-
'
|
|
16775
|
-
'<div id="cx-history" class="cx-sheet" role="region" aria-label="Past conversations" hidden></div></
|
|
16951
|
+
'<div class="cx-head"><button type="button" id="cx-pick" class="cx-pick" aria-haspopup="dialog" aria-controls="cx-picker" aria-expanded="false">' +
|
|
16952
|
+
'<span class="cx-pick-intro">Talking to</span><span class="cx-pick-label">Choose an agent</span><span class="cx-pick-sub">Tap to see the agents on your machines</span></button>' +
|
|
16953
|
+
'<button type="button" id="cx-history-btn" class="fx-btn" aria-haspopup="dialog" aria-label="History" title="History" aria-controls="cx-history" aria-expanded="false"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 10a9 9 0 1 1 1 7M3 4v6h6M12 7v5l3 2"/></svg></button>' +
|
|
16954
|
+
'<button type="button" id="cx-new" class="fx-btn" aria-label="New conversation" title="New conversation"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button></div>' +
|
|
16955
|
+
'</div><dialog id="cx-dialog" class="fx-sheet" aria-labelledby="cx-sheet-title"><div class="sheet-head"><h3 id="cx-sheet-title">Choose an agent</h3><button type="button" class="fx-btn" id="cx-sheet-done">Done</button></div><div id="cx-picker" class="cx-sheet" role="region" aria-label="Agents" hidden></div>' +
|
|
16956
|
+
'<div id="cx-history" class="cx-sheet" role="region" aria-label="Past conversations" hidden></div></dialog>' +
|
|
16776
16957
|
'<p id="cx-empty" class="soon">Pick an agent, then ask it anything. Its answer appears here as it writes.</p>' +
|
|
16777
16958
|
'<div id="cx-log" class="cx-log" role="log" aria-live="polite"></div>' +
|
|
16778
16959
|
'<form id="cx-form" class="cx-composer"><label for="cx-input" class="cx-sr">Message</label>' +
|
|
@@ -16783,6 +16964,12 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16783
16964
|
function $(id) { return document.getElementById(id); }
|
|
16784
16965
|
var log = $('cx-log'), empty = $('cx-empty'), form = $('cx-form'), input = $('cx-input'), stopBtn = $('cx-stop');
|
|
16785
16966
|
var pickBtn = $('cx-pick'), picker = $('cx-picker'), hist = $('cx-history'), histBtn = $('cx-history-btn'), newBtn = $('cx-new');
|
|
16967
|
+
var dialog = $('cx-dialog');
|
|
16968
|
+
document.body.appendChild(dialog);
|
|
16969
|
+
window.AXSheet(dialog, function () {
|
|
16970
|
+
[[picker, pickBtn], [hist, histBtn]].forEach(function (p) { p[0].hidden = true; p[1].setAttribute('aria-expanded', 'false'); });
|
|
16971
|
+
});
|
|
16972
|
+
$('cx-sheet-done').addEventListener('click', function () { dialog.close(); });
|
|
16786
16973
|
// flow: the stream this view follows; a stream from before a switch is ignored.
|
|
16787
16974
|
var state = { conv: null, target: null, busy: false, queue: [], stopWanted: false, view: 0, flow: 0, ac: null };
|
|
16788
16975
|
// Follow-ups typed for a conversation the phone switched away from, and
|
|
@@ -16812,6 +16999,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16812
16999
|
|
|
16813
17000
|
// --- Agent, conversation and the sheets ---
|
|
16814
17001
|
function showTarget(t) {
|
|
17002
|
+
pickBtn.querySelector('.cx-pick-intro').hidden = !t;
|
|
16815
17003
|
pickBtn.querySelector('.cx-pick-label').textContent = t ? (t.agentName || t.agent) : 'Choose an agent';
|
|
16816
17004
|
pickBtn.querySelector('.cx-pick-sub').textContent = t ? 'on ' + t.nodeName : 'Tap to see the agents on your machines';
|
|
16817
17005
|
emit('target', { target: t, conversationId: state.conv && state.conv.id });
|
|
@@ -16829,9 +17017,13 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16829
17017
|
var on = p[0] === sheet && open;
|
|
16830
17018
|
p[0].hidden = !on; p[1].setAttribute('aria-expanded', on ? 'true' : 'false');
|
|
16831
17019
|
});
|
|
17020
|
+
if (open) {
|
|
17021
|
+
$('cx-sheet-title').textContent = sheet === picker ? 'Choose an agent' : 'Past conversations';
|
|
17022
|
+
if (!dialog.open) dialog.showModal();
|
|
17023
|
+
} else if (dialog.open) dialog.close();
|
|
16832
17024
|
}
|
|
16833
17025
|
var sheets = window.AXChatSheets({ V: V, api: api, picker: picker, hist: hist,
|
|
16834
|
-
onPick: function (t) { state.target = t; remember('ax-chat-target', t); startNew(); toggle(picker, false); input.focus(); },
|
|
17026
|
+
onPick: function (t) { state.target = t; remember('ax-chat-target', t); startNew(); toggle(picker, false); if (document.querySelector('.cx').classList.contains('cx-typing-on')) input.focus(); },
|
|
16835
17027
|
onOpen: function (id) { toggle(hist, false); openConversation(id); } });
|
|
16836
17028
|
|
|
16837
17029
|
// Lets go of the stream being followed; the computer keeps the turn going.
|
|
@@ -17031,7 +17223,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
17031
17223
|
var last = recall('ax-chat-conv');
|
|
17032
17224
|
if (!fromHash() && last) openConversation(last);
|
|
17033
17225
|
})();
|
|
17034
|
-
`;var
|
|
17226
|
+
`;var Bi=`
|
|
17035
17227
|
window.AXChatView = (function () {
|
|
17036
17228
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
17037
17229
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -17312,7 +17504,7 @@ window.AXChatView = (function () {
|
|
|
17312
17504
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
17313
17505
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
17314
17506
|
})();
|
|
17315
|
-
`;var
|
|
17507
|
+
`;var zi=`
|
|
17316
17508
|
window.AXChatSheets = function (o) {
|
|
17317
17509
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
17318
17510
|
function loadPicker() {
|
|
@@ -17358,10 +17550,10 @@ window.AXChatSheets = function (o) {
|
|
|
17358
17550
|
});
|
|
17359
17551
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
17360
17552
|
};
|
|
17361
|
-
`;var
|
|
17553
|
+
`;var qi=`
|
|
17362
17554
|
window.AXChatLog = function (o) {
|
|
17363
17555
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
17364
|
-
function scrollDown() { var m =
|
|
17556
|
+
function scrollDown() { var m = log; if (m) m.scrollTop = m.scrollHeight; }
|
|
17365
17557
|
function clear() { log.innerHTML = ''; empty.hidden = false; }
|
|
17366
17558
|
function bubble(cls) {
|
|
17367
17559
|
var el = document.createElement('div');
|
|
@@ -17421,7 +17613,7 @@ window.AXChatLog = function (o) {
|
|
|
17421
17613
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
17422
17614
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
17423
17615
|
};
|
|
17424
|
-
`;var
|
|
17616
|
+
`;var Fi=`
|
|
17425
17617
|
(function () {
|
|
17426
17618
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
17427
17619
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -17461,7 +17653,7 @@ window.AXChatLog = function (o) {
|
|
|
17461
17653
|
return '<li><button type="button" class="cs-chip cs-' + c.state + '" data-id="' + V.esc(c.id) + '" style="--cs-c:' + colorOf(c) + '"' +
|
|
17462
17654
|
(here ? ' aria-current="true"' : '') + ' aria-label="' + V.esc(label) + '" title="' + V.esc(c.preview || '') + '">' +
|
|
17463
17655
|
'<span class="cs-dot" aria-hidden="true"></span><span class="cs-name">' + V.esc(nameOf(c)) + '</span>' +
|
|
17464
|
-
(fresh ? '<span class="cs-new" aria-hidden="true">New</span>' : '') + '</button></li>';
|
|
17656
|
+
(fresh ? '<span class="cs-new" aria-hidden="true">New</span>' : '<span class="cs-state" aria-hidden="true">' + V.esc(SAY[c.state] || '') + '</span>') + '</button></li>';
|
|
17465
17657
|
}).join('');
|
|
17466
17658
|
// Redrawn only when something changed, so a poll never steals focus
|
|
17467
17659
|
// or a tap; a focused chip keeps focus across a redraw.
|
|
@@ -17571,7 +17763,7 @@ window.AXChatLog = function (o) {
|
|
|
17571
17763
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
17572
17764
|
poll();
|
|
17573
17765
|
})();
|
|
17574
|
-
`;var
|
|
17766
|
+
`;var Ui=`
|
|
17575
17767
|
.cs { margin: 0 -2px; }
|
|
17576
17768
|
.cs[hidden] { display: none; }
|
|
17577
17769
|
.cs-list {
|
|
@@ -17627,7 +17819,7 @@ window.AXChatLog = function (o) {
|
|
|
17627
17819
|
@media (prefers-reduced-motion: reduce) {
|
|
17628
17820
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
17629
17821
|
}
|
|
17630
|
-
`;function
|
|
17822
|
+
`;function Wi(t,e,a=5){if(t.some(o=>o.key===e.key))return{queue:t.slice(),dropped:[]};let n=t.concat([e]),r=Math.max(0,n.length-Math.max(1,a));return{queue:n.slice(r),dropped:n.slice(0,r)}}function Gi(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Xi=`
|
|
17631
17823
|
body { height: 100dvh; }
|
|
17632
17824
|
main { min-height: 0; }
|
|
17633
17825
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -17737,7 +17929,7 @@ main { min-height: 0; }
|
|
|
17737
17929
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
17738
17930
|
}
|
|
17739
17931
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
17740
|
-
`;var
|
|
17932
|
+
`;var Ki=`
|
|
17741
17933
|
window.AXOrb = (function () {
|
|
17742
17934
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
17743
17935
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -17790,10 +17982,6 @@ window.AXOrb = (function () {
|
|
|
17790
17982
|
if (o.phase === 'speaking') return s ? 0.7 : o.meter ? 0.15 + 0.85 * o.level : speakingEnvelope(t);
|
|
17791
17983
|
return 0;
|
|
17792
17984
|
}
|
|
17793
|
-
function speed() {
|
|
17794
|
-
return o.phase === 'listening' ? 0.5 + o.level * 1.5 : o.phase === 'thinking' ? 1.3 : o.phase === 'speaking' ? 0.9 : 0;
|
|
17795
|
-
}
|
|
17796
|
-
|
|
17797
17985
|
function draw(t) {
|
|
17798
17986
|
var dpr = window.devicePixelRatio || 1, css = canvas.clientWidth || 150, px = Math.round(css * dpr);
|
|
17799
17987
|
// Both sides: a canvas starts at 300x150, so at 2x the width alone already matches.
|
|
@@ -17802,30 +17990,20 @@ window.AXOrb = (function () {
|
|
|
17802
17990
|
var W = canvas.width, k = W / 160;
|
|
17803
17991
|
ctx.setTransform(k, 0, 0, k, W / 2, W / 2);
|
|
17804
17992
|
ctx.clearRect(-80, -80, 160, 160);
|
|
17805
|
-
var e = energy(t), sc =
|
|
17993
|
+
var e = energy(t), sc = 1 + 0.08 * e, R = 48 * sc, base = hexToHsb(o.tint);
|
|
17806
17994
|
var drift = o.phase === 'thinking' && !still() ? Math.sin(t * 0.8) * 0.04 : 0;
|
|
17807
17995
|
function shade(dh, ds, db, a) { var h = (base.h + dh + drift) % 1; return hsb(h < 0 ? h + 1 : h, clamp(base.s + ds), clamp(base.b + db), a); }
|
|
17808
|
-
var core = 0.12 + 0.3 * e;
|
|
17809
|
-
var sh = [[0, 0, 0], [0.07, -0.05, 0.08], [-0.06, 0.05, -0.12], [0.13, -0.1, 0.02], [0.02, -0.7 * core, core]];
|
|
17810
|
-
|
|
17811
17996
|
// Glow: a disc of the tint, blurred 10 + 12e points.
|
|
17812
17997
|
var blur = 10 + 12 * e, gr = 48 * sc * 1.08, g = ctx.createRadialGradient(0, 0, Math.max(0, gr - blur), 0, 0, gr + blur);
|
|
17813
17998
|
g.addColorStop(0, shade(0, 0, 0, 0.28 + 0.32 * e)); g.addColorStop(1, shade(0, 0, 0, 0));
|
|
17814
17999
|
ctx.fillStyle = g; ctx.beginPath(); ctx.arc(0, 0, gr + blur, 0, Math.PI * 2); ctx.fill();
|
|
17815
18000
|
|
|
17816
|
-
// The body: the
|
|
18001
|
+
// The body: the approved radial highlight, clipped to the circle.
|
|
17817
18002
|
ctx.save(); ctx.beginPath(); ctx.arc(0, 0, R, 0, Math.PI * 2); ctx.clip();
|
|
17818
18003
|
ctx.fillStyle = shade(0, 0, 0); ctx.fillRect(-R, -R, 2 * R, 2 * R);
|
|
17819
|
-
var
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
[0, 1, 2], [0.5 + sway(3.7), 1, 3], [1, 1, 0], [0.5 + Math.cos(s * 1.3) * reach, 0.5 + Math.sin(s * 1.7) * reach, 4]];
|
|
17823
|
-
pts.forEach(function (p, i) {
|
|
17824
|
-
var x = (p[0] - 0.5) * 2 * R, y = (p[1] - 0.5) * 2 * R, rad = (i === 8 ? 0.95 : 1.05) * R, c = sh[p[2]];
|
|
17825
|
-
var bl = ctx.createRadialGradient(x, y, 0, x, y, rad);
|
|
17826
|
-
bl.addColorStop(0, shade(c[0], c[1], c[2], 1)); bl.addColorStop(1, shade(c[0], c[1], c[2], 0));
|
|
17827
|
-
ctx.fillStyle = bl; ctx.fillRect(-R, -R, 2 * R, 2 * R);
|
|
17828
|
-
});
|
|
18004
|
+
var body = ctx.createRadialGradient(-16, -21, 0, 0, 0, R * 1.2);
|
|
18005
|
+
body.addColorStop(0, '#9cc1ff'); body.addColorStop(0.48, '#2979ff'); body.addColorStop(1, '#1747c2');
|
|
18006
|
+
ctx.fillStyle = body; ctx.fillRect(-R, -R, 2 * R, 2 * R);
|
|
17829
18007
|
ctx.restore();
|
|
17830
18008
|
|
|
17831
18009
|
if (o.phase === 'thinking') {
|
|
@@ -17868,7 +18046,7 @@ window.AXOrb = (function () {
|
|
|
17868
18046
|
}
|
|
17869
18047
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
17870
18048
|
})();
|
|
17871
|
-
`;var
|
|
18049
|
+
`;var Ji=`
|
|
17872
18050
|
window.AXVoiceIO = (function () {
|
|
17873
18051
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
17874
18052
|
var ac = null, playing = null;
|
|
@@ -17986,7 +18164,7 @@ window.AXVoiceIO = (function () {
|
|
|
17986
18164
|
|
|
17987
18165
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
17988
18166
|
})();
|
|
17989
|
-
`;var
|
|
18167
|
+
`;var Vi=`
|
|
17990
18168
|
(function () {
|
|
17991
18169
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
17992
18170
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -17998,13 +18176,18 @@ window.AXVoiceIO = (function () {
|
|
|
17998
18176
|
bar.className = 'vx';
|
|
17999
18177
|
bar.innerHTML = '<p id="vx-status" class="vx-status" role="status" aria-live="polite"></p><div class="vx-row">' +
|
|
18000
18178
|
'<button type="button" id="vx-keys" class="vx-side" aria-pressed="false" aria-label="Type a message">' + KEYS + '</button>' +
|
|
18001
|
-
'<button type="button" id="vx-orb" class="vx-orb" aria-describedby="vx-status"><canvas aria-hidden="true"></canvas><span class="cx-sr">Hold to talk</span></button>' +
|
|
18179
|
+
'<button type="button" id="vx-orb" class="vx-orb" aria-describedby="vx-status"><canvas aria-hidden="true"></canvas><svg class="vx-mic" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3ZM5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21"/></svg><span class="cx-sr">Hold to talk</span></button>' +
|
|
18002
18180
|
'<button type="button" id="vx-speaker" class="vx-side" aria-pressed="true" aria-label="Speak answers aloud">' + SPK + '</button></div>';
|
|
18003
18181
|
cx.appendChild(bar);
|
|
18004
|
-
// The text box and Stop move into the
|
|
18182
|
+
// The text box and Stop move into the dock; CSS places them below the orb.
|
|
18005
18183
|
bar.insertBefore(document.getElementById('cx-form'), bar.firstChild);
|
|
18006
18184
|
var status = document.getElementById('vx-status'), orbBtn = document.getElementById('vx-orb');
|
|
18007
18185
|
var keysBtn = document.getElementById('vx-keys'), spkBtn = document.getElementById('vx-speaker');
|
|
18186
|
+
bar.insertBefore(document.getElementById('cx-pick'), bar.firstChild);
|
|
18187
|
+
bar.appendChild(status);
|
|
18188
|
+
var row = bar.querySelector('.vx-row');
|
|
18189
|
+
row.insertBefore(spkBtn, row.firstChild);
|
|
18190
|
+
row.appendChild(keysBtn);
|
|
18008
18191
|
var orb = O.create(orbBtn.querySelector('canvas'));
|
|
18009
18192
|
empty.textContent = 'Pick an agent, then hold the orb and speak. Let go to send. Its answer appears here, and is read out when it is done.';
|
|
18010
18193
|
|
|
@@ -18029,7 +18212,7 @@ window.AXVoiceIO = (function () {
|
|
|
18029
18212
|
orbBtn.querySelector('.cx-sr').textContent = state === 'speaking' ? 'Stop speaking' : 'Hold to talk';
|
|
18030
18213
|
}
|
|
18031
18214
|
function idle(msg, bad) { show(C.busy() ? 'thinking' : 'idle', msg, bad); setTimeout(pump, 0); }
|
|
18032
|
-
function tint() {
|
|
18215
|
+
function tint() { orb.tint('#2979FF'); }
|
|
18033
18216
|
function buzz(ms) { try { if (navigator.vibrate) navigator.vibrate(ms); } catch (e) {} }
|
|
18034
18217
|
|
|
18035
18218
|
// --- Typing and the speaker ---
|
|
@@ -18194,7 +18377,7 @@ window.AXVoiceIO = (function () {
|
|
|
18194
18377
|
idle();
|
|
18195
18378
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
18196
18379
|
})();
|
|
18197
|
-
`;var
|
|
18380
|
+
`;var Yi=`
|
|
18198
18381
|
.vx {
|
|
18199
18382
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
18200
18383
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -18230,7 +18413,7 @@ window.AXVoiceIO = (function () {
|
|
|
18230
18413
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
18231
18414
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
18232
18415
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
18233
|
-
`;var
|
|
18416
|
+
`;var Qi=`
|
|
18234
18417
|
<main class="card">
|
|
18235
18418
|
<h1>This phone isn't paired</h1>
|
|
18236
18419
|
<p>On the computer running AgentX, open a terminal in the folder that holds <code>agentx.json</code> and run <code>agentx app pair</code>. Scan the QR code it shows, or type the code under it.</p>
|
|
@@ -18244,7 +18427,7 @@ window.AXVoiceIO = (function () {
|
|
|
18244
18427
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
18245
18428
|
</form>
|
|
18246
18429
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
18247
|
-
</main>`,
|
|
18430
|
+
</main>`,Zi=`
|
|
18248
18431
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
18249
18432
|
.pair-form label { font-weight: 600; }
|
|
18250
18433
|
.pair-form input {
|
|
@@ -18266,7 +18449,7 @@ window.AXVoiceIO = (function () {
|
|
|
18266
18449
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
18267
18450
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
18268
18451
|
}
|
|
18269
|
-
`,
|
|
18452
|
+
`,el=`
|
|
18270
18453
|
(function () {
|
|
18271
18454
|
var form = document.getElementById('pair-form');
|
|
18272
18455
|
var input = document.getElementById('pair-code');
|
|
@@ -18358,7 +18541,7 @@ window.AXVoiceIO = (function () {
|
|
|
18358
18541
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18359
18542
|
}
|
|
18360
18543
|
})();
|
|
18361
|
-
`;var
|
|
18544
|
+
`;var tl=`
|
|
18362
18545
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
18363
18546
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
18364
18547
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -18367,7 +18550,7 @@ window.AXVoiceIO = (function () {
|
|
|
18367
18550
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
18368
18551
|
</div>
|
|
18369
18552
|
<p id="scan-msg" class="scan-msg" role="status" aria-live="polite">Point the camera at the QR code shown by agentx app pair.</p>
|
|
18370
|
-
</div>`,
|
|
18553
|
+
</div>`,al=`
|
|
18371
18554
|
.pair-form .scan-btn {
|
|
18372
18555
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
18373
18556
|
}
|
|
@@ -18396,7 +18579,7 @@ window.AXVoiceIO = (function () {
|
|
|
18396
18579
|
}
|
|
18397
18580
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
18398
18581
|
body.scanning { overflow: hidden; }
|
|
18399
|
-
`,
|
|
18582
|
+
`,nl=`
|
|
18400
18583
|
(function () {
|
|
18401
18584
|
var openBtn = document.getElementById('scan-btn');
|
|
18402
18585
|
var box = document.getElementById('scan');
|
|
@@ -18604,7 +18787,7 @@ body.scanning { overflow: hidden; }
|
|
|
18604
18787
|
border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
|
|
18605
18788
|
}
|
|
18606
18789
|
.cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
|
|
18607
|
-
`;var
|
|
18790
|
+
`;var rl='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h12v12H3zM15 10l6-3v10l-6-3"/></svg><span>Share camera</span></button>',ol=`
|
|
18608
18791
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
18609
18792
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
18610
18793
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -18629,7 +18812,7 @@ body.scanning { overflow: hidden; }
|
|
|
18629
18812
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
18630
18813
|
</div>
|
|
18631
18814
|
</div>
|
|
18632
|
-
</div>`,
|
|
18815
|
+
</div>`,sl=`
|
|
18633
18816
|
(function () {
|
|
18634
18817
|
var btn = document.getElementById('cam-btn');
|
|
18635
18818
|
var sheet = document.getElementById('cam');
|
|
@@ -18898,7 +19081,7 @@ body.scanning { overflow: hidden; }
|
|
|
18898
19081
|
});
|
|
18899
19082
|
window.addEventListener('pagehide', function () { stop(); });
|
|
18900
19083
|
})();
|
|
18901
|
-
`;var
|
|
19084
|
+
`;var il=`
|
|
18902
19085
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
18903
19086
|
<div class="cam-askbar-text">
|
|
18904
19087
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -18908,7 +19091,7 @@ body.scanning { overflow: hidden; }
|
|
|
18908
19091
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
18909
19092
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
18910
19093
|
</div>
|
|
18911
|
-
</div>`,
|
|
19094
|
+
</div>`,ll=`
|
|
18912
19095
|
.cam-askbar[hidden] { display: none; }
|
|
18913
19096
|
.cam-askbar {
|
|
18914
19097
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -18923,7 +19106,7 @@ body.scanning { overflow: hidden; }
|
|
|
18923
19106
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
18924
19107
|
}
|
|
18925
19108
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
18926
|
-
`,
|
|
19109
|
+
`,cl=`
|
|
18927
19110
|
(function () {
|
|
18928
19111
|
var bar = document.getElementById('cam-ask-bar');
|
|
18929
19112
|
if (!bar) return;
|
|
@@ -18993,12 +19176,13 @@ body.scanning { overflow: hidden; }
|
|
|
18993
19176
|
setInterval(poll, 5000);
|
|
18994
19177
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
18995
19178
|
})();
|
|
18996
|
-
`;function
|
|
19179
|
+
`;function dl(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function pl(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var ul=`
|
|
18997
19180
|
(function () {
|
|
18998
19181
|
var main = document.querySelector('main');
|
|
18999
19182
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
19000
19183
|
if (!main || tabs.length < 2) return;
|
|
19001
19184
|
var reduce = window.matchMedia ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
19185
|
+
var tabBar = document.querySelector('.tabs');
|
|
19002
19186
|
var SLIDE_MS = 220;
|
|
19003
19187
|
var g = null; // the touch being followed
|
|
19004
19188
|
var sliding = false; // the landing slide is running
|
|
@@ -19040,6 +19224,7 @@ body.scanning { overflow: hidden; }
|
|
|
19040
19224
|
g.peek.classList.add('sw-peek');
|
|
19041
19225
|
}
|
|
19042
19226
|
function place(x) {
|
|
19227
|
+
tabBar.style.setProperty('--tab-position', String(g.index - x / g.width));
|
|
19043
19228
|
g.from.style.transform = 'translateX(' + x + 'px)';
|
|
19044
19229
|
if (g.peek) g.peek.style.transform = 'translateX(' + (x + g.side * g.width) + 'px)';
|
|
19045
19230
|
}
|
|
@@ -19058,6 +19243,7 @@ body.scanning { overflow: hidden; }
|
|
|
19058
19243
|
unpeek();
|
|
19059
19244
|
g = null;
|
|
19060
19245
|
sliding = false;
|
|
19246
|
+
tabBar.style.setProperty('--tab-position', String(to));
|
|
19061
19247
|
if (to === s.index) return;
|
|
19062
19248
|
tabs[to].click();
|
|
19063
19249
|
main.scrollTop = 0;
|
|
@@ -19102,7 +19288,7 @@ body.scanning { overflow: hidden; }
|
|
|
19102
19288
|
main.addEventListener('touchend', function () { end(false); });
|
|
19103
19289
|
main.addEventListener('touchcancel', function () { end(true); });
|
|
19104
19290
|
})();
|
|
19105
|
-
`,
|
|
19291
|
+
`,ml=`
|
|
19106
19292
|
main { position: relative; }
|
|
19107
19293
|
main.sw-on { overflow: hidden; }
|
|
19108
19294
|
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
@@ -19113,7 +19299,7 @@ main > .sw-peek {
|
|
|
19113
19299
|
}
|
|
19114
19300
|
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
19115
19301
|
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
19116
|
-
`;function
|
|
19302
|
+
`;function fl(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function hl(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function gl(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function xl(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var Ka=`
|
|
19117
19303
|
${z({afterUnauthorized:Ur})}
|
|
19118
19304
|
var CACHE = 'agentx-app-v3';
|
|
19119
19305
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
@@ -19205,7 +19391,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19205
19391
|
return self.clients.openWindow(target);
|
|
19206
19392
|
}));
|
|
19207
19393
|
});
|
|
19208
|
-
`;var
|
|
19394
|
+
`;var wm="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})();</script>";function Ja(t){return`<meta charset="utf-8">
|
|
19209
19395
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
19210
19396
|
<meta name="theme-color" content="#2979FF">
|
|
19211
19397
|
<meta name="referrer" content="no-referrer">
|
|
@@ -19216,38 +19402,39 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19216
19402
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
19217
19403
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
19218
19404
|
<title>${t}</title>
|
|
19219
|
-
${
|
|
19220
|
-
<style>${At}${
|
|
19405
|
+
${wm}
|
|
19406
|
+
<style>${At}${Em}</style>`}var km={chat:"M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-2 2V11.5a9.5 9.5 0 0 1 19 0Z",fleet:"M3 3h18v13H3zM8 21h8M12 16v5",activity:"M3 12h4l3-8 4 16 3-8h4",alerts:"M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"},vl=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function bl(){let t=vl.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}"><span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="${km[a.id]}"/></svg></span><span>${a.label}</span></button>`).join(""),e=vl.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
19221
19407
|
<h2>${a.label}</h2>
|
|
19222
19408
|
<p class="soon">${a.soon}</p>
|
|
19223
19409
|
</section>`).join("");return`<!doctype html>
|
|
19224
19410
|
<html lang="en">
|
|
19225
|
-
<head>${Ja("AgentX")}<style>${
|
|
19411
|
+
<head>${Ja("AgentX")}<style>${Tm}${Oi}${Xi}${Ui}${Yi}${Xa}${ll}${ml}${$i}</style></head>
|
|
19226
19412
|
<body>
|
|
19227
19413
|
<header class="bar">
|
|
19228
19414
|
<div>
|
|
19229
19415
|
<h1>AgentX</h1>
|
|
19230
19416
|
<p id="who" class="who">Connecting\u2026</p>
|
|
19231
19417
|
</div>
|
|
19232
|
-
<div class="bar-btns">${
|
|
19418
|
+
<div class="bar-btns">${rl}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 15.5A9 9 0 0 1 8.5 4 9 9 0 1 0 20 15.5Z"/></svg></button></div>
|
|
19233
19419
|
</header>
|
|
19234
19420
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
19235
|
-
${
|
|
19421
|
+
${il}
|
|
19236
19422
|
<main>${e}</main>
|
|
19237
19423
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
19238
|
-
${
|
|
19239
|
-
<script>${
|
|
19240
|
-
<script>${z({swipeMayStart:
|
|
19241
|
-
<script>${
|
|
19424
|
+
${ol}
|
|
19425
|
+
<script>${_m}</script>
|
|
19426
|
+
<script>${z({swipeMayStart:fl,swipeAxis:hl,swipeOffset:gl,swipeLanding:xl})}${ul}</script>
|
|
19427
|
+
<script>${Pi}</script>
|
|
19242
19428
|
<script>${ji}</script>
|
|
19243
|
-
<script>${
|
|
19244
|
-
<script>${
|
|
19245
|
-
<script>${z({
|
|
19246
|
-
<script>${
|
|
19247
|
-
<script>${
|
|
19248
|
-
<script>${
|
|
19429
|
+
<script>${Ni}</script>
|
|
19430
|
+
<script>${Di}</script>
|
|
19431
|
+
<script>${z({markdownToHtml:Bn})}${Bi}${qi}${zi}${Hi}</script>
|
|
19432
|
+
<script>${z({queueSpeech:Wi,nextSpeech:Gi})}${Ki}${Ji}${Vi}</script>
|
|
19433
|
+
<script>${Fi}</script>
|
|
19434
|
+
<script>${z({cameraConstraints:dl,shareClock:pl})}${sl}</script>
|
|
19435
|
+
<script>${cl}</script>
|
|
19249
19436
|
</body>
|
|
19250
|
-
</html>`}function
|
|
19437
|
+
</html>`}function yl(){return`<!doctype html>
|
|
19251
19438
|
<html lang="en">
|
|
19252
19439
|
<head>${Ja("Pair \xB7 AgentX")}</head>
|
|
19253
19440
|
<body>
|
|
@@ -19255,26 +19442,28 @@ ${nl}
|
|
|
19255
19442
|
<h1>Pairing this phone\u2026</h1>
|
|
19256
19443
|
<p id="msg" role="status">One moment.</p>
|
|
19257
19444
|
</main>
|
|
19258
|
-
<script>${
|
|
19445
|
+
<script>${Sm}</script>
|
|
19259
19446
|
</body>
|
|
19260
|
-
</html>`}function
|
|
19447
|
+
</html>`}function wl(){return`<!doctype html>
|
|
19261
19448
|
<html lang="en">
|
|
19262
|
-
<head>${Ja("Not paired \xB7 AgentX")}<style>${
|
|
19263
|
-
<body>${
|
|
19449
|
+
<head>${Ja("Not paired \xB7 AgentX")}<style>${Zi}${al}</style></head>
|
|
19450
|
+
<body>${Qi}${tl}
|
|
19264
19451
|
<script>${z({mayBounce:Wr,formatPairInput:Nt,parsePairScan:Gr})}</script>
|
|
19265
|
-
<script>${
|
|
19266
|
-
<script>${
|
|
19452
|
+
<script>${el}</script>
|
|
19453
|
+
<script>${nl}</script>
|
|
19267
19454
|
</body>
|
|
19268
|
-
</html>`}function
|
|
19455
|
+
</html>`}function kl(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var _m=`
|
|
19269
19456
|
(function () {
|
|
19270
19457
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
19271
19458
|
function select(tab, focus, keepHash) {
|
|
19459
|
+
document.querySelector('.tabs').style.setProperty('--tab-position', String(tabs.indexOf(tab)));
|
|
19272
19460
|
tabs.forEach(function (t) {
|
|
19273
19461
|
var on = t === tab;
|
|
19274
19462
|
t.setAttribute('aria-selected', on ? 'true' : 'false');
|
|
19275
19463
|
t.tabIndex = on ? 0 : -1;
|
|
19276
19464
|
document.getElementById(t.getAttribute('aria-controls')).hidden = !on;
|
|
19277
19465
|
});
|
|
19466
|
+
document.dispatchEvent(new CustomEvent('ax-tab'));
|
|
19278
19467
|
if (focus) tab.focus();
|
|
19279
19468
|
if (keepHash) return;
|
|
19280
19469
|
try { history.replaceState(null, '', '#' + tab.dataset.tab); } catch (e) {}
|
|
@@ -19335,7 +19524,7 @@ ${nl}
|
|
|
19335
19524
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
19336
19525
|
}
|
|
19337
19526
|
})();
|
|
19338
|
-
`,
|
|
19527
|
+
`,Sm=`
|
|
19339
19528
|
(function () {
|
|
19340
19529
|
var msg = document.getElementById('msg');
|
|
19341
19530
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -19352,7 +19541,7 @@ ${nl}
|
|
|
19352
19541
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
19353
19542
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
19354
19543
|
})();
|
|
19355
|
-
`,
|
|
19544
|
+
`,Em=`
|
|
19356
19545
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
19357
19546
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
19358
19547
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -19364,7 +19553,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
19364
19553
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
19365
19554
|
.muted { color: var(--ax-text-2); }
|
|
19366
19555
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
19367
|
-
`,
|
|
19556
|
+
`,Tm=`
|
|
19368
19557
|
body { display: flex; flex-direction: column; }
|
|
19369
19558
|
.bar {
|
|
19370
19559
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -19402,8 +19591,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19402
19591
|
}
|
|
19403
19592
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
19404
19593
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
19405
|
-
`;var Yt="agentx_app",
|
|
19406
|
-
`;Ze=Buffer.concat([Buffer.from(a),
|
|
19594
|
+
`;var Yt="agentx_app",Im=400*86400,Mm=new wt,Lm=new Ee;async function _l(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new F;if(n==="GET"){if(a==="/app/manifest.webmanifest")return xe(e,200,"application/manifest+json",kl());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),xe(e,200,"text/javascript; charset=utf-8",Ka);if(a==="/app/icon-192.png")return xe(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/app/icon-512.png")return xe(e,200,"image/png",Be(512),"public, max-age=86400");if(a==="/app/pair")return xe(e,200,"text/html; charset=utf-8",yl());if(a==="/app/qr.js"){let i=Rm();return i?xe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Pe(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Va(et(t),o);return i?(e.setHeader("Set-Cookie",Ya(et(t))),Pe(e,200,{device:i.name})):Pe(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Hn(t,{codes:r.pairCodes??new ht,limiter:r.pairLimiter??Mm,verify:l=>Va(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ya(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Pe(e,i.status,i.body)}let s=Va($m(t),o);if(!s){let i=et(t);return(r.rejectLog??Lm).record(a.slice(0,120),Pt(t,He(Qa(t,Yt),o),i?He(i,o):null)),a==="/app"?xe(e,401,"text/html; charset=utf-8",wl()):Pe(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Qa(t,Yt);return i&&!et(t)&&e.setHeader("Set-Cookie",Ya(i)),xe(e,200,"text/html; charset=utf-8",bl())}return n==="GET"&&a==="/api/app/me"?Pe(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Dn(t,e,a,n,s.name,r.fleet)||r.push&&await ci(t,e,a,n,s,r.push)||r.announce&&await ui(t,e,a,n,s,r.announce)||r.chat&&await _i(t,e,a,n,s,r.chat)||r.chat&&await Ai(t,e,a,n,s,r.chat)||r.voice&&await Mi(t,e,a,n,s,r.voice)||r.camera&&await Li(t,e,a,n,r.camera)?!0:Pe(e,404,{error:"not found"})}var Ze;function Rm(){if(Ze!==void 0)return Ze;try{let t=Cm(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
19595
|
+
`;Ze=Buffer.concat([Buffer.from(a),Am(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ze=null}return Ze}function Va(t,e){if(!t)return null;let a=e.verify(t);return a&&ke(a,"app")?a:null}function Ya(t){return`${Yt}=${t}; Path=/; Max-Age=${Im}; HttpOnly; Secure; SameSite=Lax`}function $m(t){return et(t)??Qa(t,Yt)}function et(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Qa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Pe(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Sl}from"crypto";var je={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},Pm=/^[a-f0-9]{32}$/,jm=/^c[a-z0-9]{8,32}$/,Om=/^#[0-9a-fA-F]{6}$/;function Za(t){return jm.test(t)}var tt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
19407
19596
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
19408
19597
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
19409
19598
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -19416,39 +19605,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19416
19605
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
19417
19606
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
19418
19607
|
CREATE INDEX IF NOT EXISTS app_chat_files_conversation ON app_chat_files(conversation_id);`),e.prepare("PRAGMA table_info(app_chat_messages)").all().some(r=>r.name==="files")||e.exec("ALTER TABLE app_chat_messages ADD COLUMN files TEXT");let n=e.prepare("PRAGMA table_info(app_chat_conversations)").all();n.some(r=>r.name==="read_at")||e.transaction(()=>{e.prepare("PRAGMA table_info(app_chat_conversations)").all().some(o=>o.name==="read_at")||(e.exec("ALTER TABLE app_chat_conversations ADD COLUMN read_at INTEGER"),e.exec("UPDATE app_chat_conversations SET read_at = updated_at"))}).immediate(),n.some(r=>r.name==="color")||e.exec("ALTER TABLE app_chat_conversations ADD COLUMN color TEXT"),e.exec(`CREATE TABLE IF NOT EXISTS app_chat_delivered (
|
|
19419
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Za(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${
|
|
19420
|
-
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Za(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(
|
|
19608
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Za(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${Sl(4).toString("hex")}`,{color:s,...i}=a,l=s&&Om.test(s)?s:void 0,c={id:o,title:Dm(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
19609
|
+
(id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Za(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(Nm);return{...El(n),messages:r}}list(e,a=je.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
19421
19610
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
19422
19611
|
(SELECT substr(m.content, 1, 240) FROM app_chat_messages m WHERE m.conversation_id = c.id ORDER BY m.id DESC LIMIT 1) AS last
|
|
19423
|
-
FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...
|
|
19612
|
+
FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...El(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Za(a)&&this.db.prepare("UPDATE app_chat_conversations SET read_at = MAX(COALESCE(read_at, 0), ?) WHERE id = ? AND device_id = ?").run(n,a,e)}unread(e,a){return this.db.prepare(`SELECT c.id, c.title, c.agent, c.agent_name, c.color,
|
|
19424
19613
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
19425
19614
|
FROM app_chat_conversations c
|
|
19426
19615
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
19427
19616
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
19428
19617
|
ORDER BY m.at DESC, m.id DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>({id:r.id,title:r.title,agent:r.agent,...r.agent_name?{agentName:r.agent_name}:{},...r.color?{color:r.color}:{},answer:String(r.answer??"").trim(),status:r.status==="error"||r.status==="stopped"?r.status:"done",at:r.at}))}append(e,a,n){return this.appendWithFiles(e,a,n)!==null}appendWithFiles(e,a,n,r=[]){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return null;let s=n.content.length>je.content?n.content.slice(0,je.content)+`
|
|
19429
19618
|
|
|
19430
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let m of r){if(l.length>=je.filesPerMessage)break;let h=m.filename.trim(),k=Tn(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let v=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:
|
|
19619
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let m of r){if(l.length>=je.filesPerMessage)break;let h=m.filename.trim(),k=Tn(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let v=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Sl(16).toString("hex"),name:v,mime:k.mime,kind:k.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),d=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
19431
19620
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),u=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
|
|
19432
19621
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)u.run(m.id,a,Number(d.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
19433
19622
|
(SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,je.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
|
|
19434
|
-
(SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!
|
|
19623
|
+
(SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!Pm.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
19435
19624
|
JOIN app_chat_conversations c ON c.id = f.conversation_id WHERE f.id = ? AND c.device_id = ?`).get(a,e);return n?{id:n.id,name:n.name,mime:n.mime,kind:n.kind,path:n.path,conversationId:n.conversation_id,node:n.node,agent:n.agent}:null}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
|
|
19436
|
-
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function
|
|
19625
|
+
ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function El(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function Nm(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{},...r?{files:r}:{}}}function Dm(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Hm=4e3,en=100,Bm=15,Tl=t=>t.replace(/\/+$/,""),Qt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Hm){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,en);e=Array.isArray(o)?o:o.events,a=!Array.isArray(o)&&o.gap===!0}catch{return 0}this.warnIfSkipped(e.length,a),e.length&&(this.cursor=e[e.length-1].id);let n=[...this.retry.values()].map(o=>o.event);for(let o of e)o.kind==="delegation"&&o.type==="reply"&&typeof o.ref=="string"&&o.ref&&!this.retry.has(o.id)&&n.push(o);let r=0;for(let o of n){let s=await this.file(o).catch(()=>"retry");if(s==="retry"){let i=(this.retry.get(o.id)?.left??Bm)-1;i>0?this.retry.set(o.id,{event:o,left:i}):(this.retry.delete(o.id),this.deps.log?.(`[app] callback reply ${o.ref} from ${o.node} could not be read; it stays in the agent's session`))}else this.retry.delete(o.id),s==="filed"&&r++}return r}finally{this.running=!1}}warnIfSkipped(e,a){let n=this.deps.warn??this.deps.log,r=this.cursor?`after event ${this.cursor}`:"on the first read";a&&n?.(`[app] warning: callback event cursor ${this.cursor} is no longer in the daemon's event ring; replies published before the oldest kept event were skipped`),e>=en&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${en}); older replies ${r} may have been skipped`)}async file(e){let a=this.deps.store();if(!a)return"retry";let n=await this.deps.nodeUrl(e.node);if(!n)return"retry";let r=await this.deps.fetchReply(n,e.ref);if(!r||r.taskId!==e.ref||r.channel!=="app"||!r.chatId.startsWith("app:"))return"skip";let o=r.chatId.slice(4),s=a.ownerOf(o);if(!s)return"skip";let i=a.get(s,o);if(!i)return"skip";let l=await this.deps.conversationUrl(i);if(!l||Tl(l)!==Tl(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=zm(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&Kt(h)&&this.deps.notifyFinish(Jt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function zm(t,e){let a=t.plain?{text:ut(t.text,!1),artifacts:[]}:pt(t.text,le.perMessage,!1),{cleanText:n,ui:r}=ft(a.text),o=t.plain?void 0:Ba(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:qm(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function qm(t){return t.replace(/\s+/g," ").trim().slice(0,300)}fn();function Ue(){let t=it();return t&&ye(t,"dashboard"),t}function ww(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,ef(h,t))}catch(k){console.error(` Board "${h.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?at(process.cwd(),t.workflows.dir):void 0,c=new kn(l?{baseDir:l}:void 0),d=new _n(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new Sn(l?{baseDir:l}:void 0);Cs(t),Ue(),Xn({business:t.business?.enabled===!0});let m=Fm(async(h,k)=>{try{await Vm(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:d,workflowLayouts:u})}catch(v){y(k,500,{error:v.message||"internal error"})}});vf(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
19437
19626
|
Live dashboard: http://${h}:${n}
|
|
19438
19627
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
19439
19628
|
Kanban dashboard: http://${h}:${n}
|
|
19440
|
-
`),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Gm=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Xm(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){y(e,404,{error:"not found"});return}if(Wn(t.headers)==="foreign"&&Gn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ho(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:El(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(p,f)=>Br(p,f,{gitlab:a.config.channels.gitlab?.host})})||await wl(t,e,r,o,{nodeName:a.config.node?.name,fleet:Ll(a.config),push:Ml(a.config),announce:mi(a.config),chat:Rl(a.config),voice:gf(a.config),camera:xf(a.config)}))return;if(o==="GET"&&Gm.has(r)&&Ar("page",r),o==="GET"&&r==="/"){let p=mr();if(!p.configExists||p.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ei({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[p]=await we(a.config);if(!p){y(e,503,{error:"no node available"});return}let f=await new Promise(b=>{let _="";t.on("data",T=>_+=T),t.on("end",()=>b(_)),t.on("error",()=>b(""))}),x=await fetch(p.url+r,{method:"POST",headers:{"Content-Type":"application/json",...p.token?{Authorization:`Bearer ${p.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(p){y(e,502,{error:"could not reach the node",message:String(p?.message||p)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let p=await we(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await pe(t):void 0,b=x?.node??f,_=b?p.find(I=>I.url===b):p[0];if(!_){y(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",w=await fetch(_.url+r+T,{method:o,headers:{"Content-Type":"application/json",..._.token?{Authorization:`Bearer ${_.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,w.status,await w.json().catch(()=>({error:`HTTP ${w.status}`})))}catch(p){y(e,502,{error:"could not reach the node",message:p?.message||String(p)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let p=await pe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(p??{})}),_=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,_)}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[p]=await we(a.config);if(!p){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(p.url+"/api/n8n/workflows",{headers:p.token?{Authorization:`Bearer ${p.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Or({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let p=new AbortController,f=setTimeout(()=>p.abort(),8e3);try{let x=Cn(await we(a.config,p.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:p.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));y(e,200,{nodes:I});return}let b=x.find(I=>I.url===n.searchParams.get("node"));if(!b){y(e,400,{error:"Select a known node"});return}let _=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(_)||o==="POST"&&["register","ended","action","retry","clear"].includes(_))){y(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await An(t)):void 0,w=await fetch(b.url+"/monitor/"+_+(_==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):_==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:p.signal,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}}});y(e,w.status,await w.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Js({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await pe(t).catch(()=>({})):void 0,b=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:p,...x!==void 0?{body:JSON.stringify(x??{})}:{}});y(e,b.status,await b.json().catch(()=>({error:`HTTP ${b.status}`})))}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ti({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ai({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let p=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!p){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ri({taskId:decodeURIComponent(i[1]),agentId:p,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oi({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){fr(t,e);return}if(o==="POST"&&r==="/api/setup"){await hr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await gr(t,e);return}if(o==="GET"&&r==="/admin"){To(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Fo(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){$o(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Zo(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let p=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(p==="fleet"){if(r==="/api/admin/activity-graph"){await _f(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Oa(t,e,r,x=>Pl(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),b=x.indexOf("::");if(b>0){let _=x.slice(0,b),T=x.slice(b+2),w=a.config.node?.id||a.config.node?.name||"local";if(_===w)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===_);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await Al(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}y(e,404,{error:`unknown node "${_}" in fleet dispatch id`});return}}}}else if(p&&p!=="primary"){let f=nt(p,a.config);if(!f){y(e,404,{error:`unknown peer: ${p}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,_=>_.startsWith("?")?"?":"");await Al(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await es(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Sf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:p}=await import("./doctor-P3QQP33C.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",b=await p({running:x});y(e,200,b)}catch(p){y(e,500,{error:p?.message||String(p)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await ns(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(os({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ss({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await ef(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){e.writeHead(302,{Location:"/activity?view=map"}),e.end();return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await Is(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Oa(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ls(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ps(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ao(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,Vn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Uo(t,e,r,n);return}if(await Go(t,e,r,{people:()=>Ke(a.config.people),members:El(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Po(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await js(t,e,r);return}if(r.startsWith("/api/admin/")){await Co(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(go);return}if(o==="GET"&&r.startsWith("/assets/")){let p=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(p)){y(e,400,{error:"invalid asset name"});return}let f=wf("web/"+p);try{let x=await kf(f),b=p.endsWith(".map")?"application/json; charset=utf-8":p.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",_=n.searchParams.has("v");e.writeHead(200,{"Content-Type":b,"Cache-Control":_?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let p=await We(a.config);y(e,200,p)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let p=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:p,timezone:f});y(e,200,x)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let p=(f,x,b,_)=>{let T=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(T)?Math.max(b,Math.min(_,T)):x};try{let f=await we(a.config);y(e,200,await Ys(f,{days:p("days",30,0,180),tzOffsetMinutes:p("tzOffset",0,-840,840),limit:p("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let p=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(p)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,b,_,T)=>{let w=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(w)?Math.max(_,Math.min(T,w)):b};try{let x=await we(a.config);y(e,200,await Zs(x,{day:p,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[b,_]=[f.get("kind"),f.get("key")];if(!b||!_){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(b)}&key=${encodeURIComponent(_)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let b=f.get("task");if(!b){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(b)}`}try{await Qs(e,await we(a.config),p,x)}catch(b){y(e,502,{error:b.message})}return}if(o==="GET"&&r==="/api/live/stream"){lf(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task");if(!f||!x||!b){y(e,400,{error:"node, agent, task query params required"});return}await cf(t,e,a,f,x,b);return}if(o==="GET"&&r==="/api/task/history"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task"),_=p.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await uf(e,a,f,x,b,_);return}if(o==="POST"&&r==="/api/task/action"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("task"),b=p.searchParams.get("kind");if(!f||!x||b!=="cancel"&&b!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await mf(t,e,a,f,x,b);return}if(o==="POST"&&r==="/api/voice/stop"){let p=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:p});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(p){y(e,502,{error:p.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:p});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(p){y(e,502,{error:p.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let p=await pe(t);try{let f=await bf(a.config,p);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let p=d[1];if(!df(t,e,[`agent:${p}`]))return;await pf(t,e,a.config,p);return}if(o==="GET"&&r==="/api/node/build"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:p,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);y(e,200,Jn(await f.json()))}catch(p){y(e,502,{error:p.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await tf(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(w=>({name:w.name,url:w.url,token:w.token}))],b={flag:!1},_=[];t.on("close",()=>{b.flag=!0;for(let w of _)try{w.abort()}catch{}});let T=setInterval(()=>{if(!b.flag)try{e.write(`: ping
|
|
19629
|
+
`),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Jm=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Vm(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if((t.url||"/").split(/[?#]/)[0]!==r){y(e,404,{error:"not found"});return}if(Wn(t.headers)==="foreign"&&Gn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ho(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:Al(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(p,f)=>Br(p,f,{gitlab:a.config.channels.gitlab?.host})})||await _l(t,e,r,o,{nodeName:a.config.node?.name,fleet:$l(a.config),push:Rl(a.config),announce:mi(a.config),chat:Pl(a.config),voice:bf(a.config),camera:yf(a.config)}))return;if(o==="GET"&&Jm.has(r)&&Ar("page",r),o==="GET"&&r==="/"){let p=mr();if(!p.configExists||p.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ei({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Da({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[p]=await we(a.config);if(!p){y(e,503,{error:"no node available"});return}let f=await new Promise(b=>{let _="";t.on("data",T=>_+=T),t.on("end",()=>b(_)),t.on("error",()=>b(""))}),x=await fetch(p.url+r,{method:"POST",headers:{"Content-Type":"application/json",...p.token?{Authorization:`Bearer ${p.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(p){y(e,502,{error:"could not reach the node",message:String(p?.message||p)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let p=await we(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await pe(t):void 0,b=x?.node??f,_=b?p.find(I=>I.url===b):p[0];if(!_){y(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",w=await fetch(_.url+r+T,{method:o,headers:{"Content-Type":"application/json",..._.token?{Authorization:`Bearer ${_.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,w.status,await w.json().catch(()=>({error:`HTTP ${w.status}`})))}catch(p){y(e,502,{error:"could not reach the node",message:p?.message||String(p)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let p=await pe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(p??{})}),_=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,_)}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[p]=await we(a.config);if(!p){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(p.url+"/api/n8n/workflows",{headers:p.token?{Authorization:`Bearer ${p.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Nr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Or({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rr({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let p=new AbortController,f=setTimeout(()=>p.abort(),8e3);try{let x=Cn(await we(a.config,p.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:p.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));y(e,200,{nodes:I});return}let b=x.find(I=>I.url===n.searchParams.get("node"));if(!b){y(e,400,{error:"Select a known node"});return}let _=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(_)||o==="POST"&&["register","ended","action","retry","clear"].includes(_))){y(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await An(t)):void 0,w=await fetch(b.url+"/monitor/"+_+(_==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):_==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:p.signal,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}}});y(e,w.status,await w.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Js({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vs({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let p={"Content-Type":"application/json"};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await pe(t).catch(()=>({})):void 0,b=await fetch(`${f}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:p,...x!==void 0?{body:JSON.stringify(x??{})}:{}});y(e,b.status,await b.json().catch(()=>({error:`HTTP ${b.status}`})))}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ti({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ai({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ni({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let p=n.searchParams.get("agent")||"",f=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!p){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ri({taskId:decodeURIComponent(i[1]),agentId:p,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:f,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oi({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){fr(t,e);return}if(o==="POST"&&r==="/api/setup"){await hr(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await gr(t,e);return}if(o==="GET"&&r==="/admin"){To(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Fo(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){$o(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Zo(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let p=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(p==="fleet"){if(r==="/api/admin/activity-graph"){await Tf(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Oa(t,e,r,x=>Ol(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),b=x.indexOf("::");if(b>0){let _=x.slice(0,b),T=x.slice(b+2),w=a.config.node?.id||a.config.node?.name||"local";if(_===w)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===_);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await Il(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}y(e,404,{error:`unknown node "${_}" in fleet dispatch id`});return}}}}else if(p&&p!=="primary"){let f=nt(p,a.config);if(!f){y(e,404,{error:`unknown peer: ${p}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,_=>_.startsWith("?")?"?":"");await Il(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await es(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Af(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:p}=await import("./doctor-P3QQP33C.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",b=await p({running:x});y(e,200,b)}catch(p){y(e,500,{error:p?.message||String(p)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rs({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await ns(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(os({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ss({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await nf(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){e.writeHead(302,{Location:"/activity?view=map"}),e.end();return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await Is(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Oa(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ls(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Ps(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Ao(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,Vn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Uo(t,e,r,n);return}if(await Go(t,e,r,{people:()=>Ke(a.config.people),members:Al(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await Po(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await js(t,e,r);return}if(r.startsWith("/api/admin/")){await Co(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(go);return}if(o==="GET"&&r.startsWith("/assets/")){let p=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(p)){y(e,400,{error:"invalid asset name"});return}let f=Sf("web/"+p);try{let x=await Ef(f),b=p.endsWith(".map")?"application/json; charset=utf-8":p.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",_=n.searchParams.has("v");e.writeHead(200,{"Content-Type":b,"Cache-Control":_?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let p=await We(a.config);y(e,200,p)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let p=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:p,timezone:f});y(e,200,x)}catch(p){y(e,502,{error:p.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let p=(f,x,b,_)=>{let T=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(T)?Math.max(b,Math.min(_,T)):x};try{let f=await we(a.config);y(e,200,await Ys(f,{days:p("days",30,0,180),tzOffsetMinutes:p("tzOffset",0,-840,840),limit:p("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let p=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(p)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,b,_,T)=>{let w=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(w)?Math.max(_,Math.min(T,w)):b};try{let x=await we(a.config);y(e,200,await Zs(x,{day:p,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[b,_]=[f.get("kind"),f.get("key")];if(!b||!_){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(b)}&key=${encodeURIComponent(_)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[b,_,T]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!b||!_||!T){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(_)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let b=f.get("task");if(!b){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(b)}`}try{await Qs(e,await we(a.config),p,x)}catch(b){y(e,502,{error:b.message})}return}if(o==="GET"&&r==="/api/live/stream"){pf(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task");if(!f||!x||!b){y(e,400,{error:"node, agent, task query params required"});return}await uf(t,e,a,f,x,b);return}if(o==="GET"&&r==="/api/task/history"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("agent"),b=p.searchParams.get("task"),_=p.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await hf(e,a,f,x,b,_);return}if(o==="POST"&&r==="/api/task/action"){let p=new URL(t.url||"/","http://localhost"),f=p.searchParams.get("node"),x=p.searchParams.get("task"),b=p.searchParams.get("kind");if(!f||!x||b!=="cancel"&&b!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await gf(t,e,a,f,x,b);return}if(o==="POST"&&r==="/api/voice/stop"){let p=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:p});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(p){y(e,502,{error:p.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:p});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(p){y(e,502,{error:p.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let p=await pe(t);try{let f=await kf(a.config,p);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let d=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(d&&o==="POST"){let p=d[1];if(!mf(t,e,[`agent:${p}`]))return;await ff(t,e,a.config,p);return}if(o==="GET"&&r==="/api/node/build"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:p,signal:AbortSignal.timeout(3e3)});if(!f.ok)throw new Error(`HTTP ${f.status}`);y(e,200,Jn(await f.json()))}catch(p){y(e,502,{error:p.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let p=t.headers.authorization||"",f=p.startsWith("Bearer ")?p.slice(7):"";if(f!==a.token){let x=new F,b=f?x.verify(f):null;if(!b||!ke(b,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await rf(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let p=n.searchParams.get("node");if(!p){y(e,400,{error:"node query param required"});return}await on(t,e,a,p,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(w=>({name:w.name,url:w.url,token:w.token}))],b={flag:!1},_=[];t.on("close",()=>{b.flag=!0;for(let w of _)try{w.abort()}catch{}});let T=setInterval(()=>{if(!b.flag)try{e.write(`: ping
|
|
19441
19630
|
|
|
19442
19631
|
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let w of x)(async()=>{let I={Accept:"text/event-stream"};w.token&&(I.Authorization=`Bearer ${w.token}`);let C=new AbortController;_.push(C);try{let E=await fetch(`${w.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:I,signal:C.signal});if(!E.ok||!E.body)return;let $=E.body.getReader(),L=new TextDecoder,j="";for(;!b.flag;){let{done:W,value:q}=await $.read();if(W)break;j+=L.decode(q,{stream:!0});let G;for(;(G=j.indexOf(`
|
|
19443
19632
|
|
|
19444
19633
|
`))>=0;){let ie=j.slice(0,G);if(j=j.slice(G+2),b.flag)break;try{e.write(ie+`
|
|
19445
19634
|
|
|
19446
|
-
`)}catch{b.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let p=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(p.searchParams.get("limit")||50))),x=p.searchParams.get("workflowId")||void 0,b=p.searchParams.get("summary")==="1"||p.searchParams.get("summary")==="true",_=a.workflowRuns.list({limit:f,workflowId:x}),T=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${b?"&summary=1":""}`,w=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(w.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of _)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,f),$=b?E.map(L=>
|
|
19447
|
-
`;
|
|
19635
|
+
`)}catch{b.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let p=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(p.searchParams.get("limit")||50))),x=p.searchParams.get("workflowId")||void 0,b=p.searchParams.get("summary")==="1"||p.searchParams.get("summary")==="true",_=a.workflowRuns.list({limit:f,workflowId:x}),T=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${b?"&summary=1":""}`,w=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(w.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of _)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,f),$=b?E.map(L=>Zm(L)):E;y(e,200,{runs:$})}catch(p){y(e,502,{error:"runs fetch failed",message:p.message||String(p)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let p=decodeURIComponent(m[1]),f=a.workflowRuns.get(p);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(b=>({url:b.url,token:b.token}))];for(let b of x)try{let _={};b.token&&(_.Authorization=`Bearer ${b.token}`);let T=await fetch(`${b.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(p)}`,{headers:_});if(T.ok){y(e,200,await T.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let p={};a.config.dashboard.token&&(p.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:p}),b=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,b)}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let p=await pe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(p??{})}),_=await b.json().catch(()=>({error:`HTTP ${b.status}`}));y(e,b.status,_)}catch(p){y(e,502,{error:"daemon unreachable",message:p.message||String(p)})}return}if(r.startsWith("/api/workflows")&&ii(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,b)=>{if(a.token)return!0;let _=pa(f);if(!_)return!0;let T=new F().verify(_);if(!T)return y(x,401,{error:"invalid or revoked token"}),!1;for(let w of b)if(!ke(T,w))return y(x,403,{error:`token missing scope: ${w}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(p=>({id:p.id,name:p.name,source:p.source,primaryToolLabel:p.primaryToolLabel,labels:p.labels,columns:p.columns,timeRangeDays:p.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let p=a.sources.get(k[1]);if(!p){y(e,404,{error:"unknown board"});return}try{let f=typeof p.listMembers=="function"?await p.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let v=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(v&&o==="GET"){let p=a.sources.get(v[1]);if(!p){y(e,404,{error:"unknown board"});return}try{let f=typeof p.listMilestones=="function"?await p.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,p,f]=S,x=decodeURIComponent(f),b=a.boards.find(C=>C.id===p);if(!b){y(e,404,{error:`unknown board: ${p}`});return}let _=a.sources.get(p);if(!_){y(e,503,{error:`board "${p}" source unavailable`});return}let T=await pe(t),w=b.columns.find(C=>C.id===T.to),I=b.columns.find(C=>C.id===T.from);if(!w){y(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await Qm(_,x,I,w),tn({actor:an(t),action:"move",boardId:p,itemId:x,payload:{from:T.from,to:T.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,p,f]=g,x=f?decodeURIComponent(f):void 0,b=a.boards.find(T=>T.id===p);if(!b){y(e,404,{error:`unknown board: ${p}`});return}let _=a.sources.get(p);if(!_){y(e,503,{error:`board "${p}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:w}=await Ym(b,_,n.searchParams);y(e,200,{columns:T,totals:w});return}if(o==="GET"&&x){try{let T=typeof _.getItem=="function"?await _.getItem(x):null;if(!T){y(e,404,{error:"not found"});return}y(e,200,T)}catch(T){y(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await pe(t);try{let w=typeof _.updateItem=="function"?await _.updateItem(x,T):null;if(!w){y(e,501,{error:"update unsupported"});return}tn({actor:an(t),action:"update",boardId:p,itemId:x,payload:T}),y(e,200,w)}catch(w){y(e,502,{error:w.message})}return}if(o==="POST"&&!x){let T=await pe(t);if(!T.title){y(e,400,{error:"title required"});return}if(!_.capabilities.create||!_.create){y(e,400,{error:`source ${_.type} does not support create`});return}try{let w=await _.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});tn({actor:an(t),action:"create",boardId:p,itemId:w.id,payload:{title:T.title}}),y(e,201,w)}catch(w){y(e,502,{error:w.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let p=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[p];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Ym(t,e,a){if(!e.capabilities.listAll||!e.listAll){let p={};for(let f of t.columns)p[f.id]=[];return{columns:p,totals:Object.fromEntries(t.columns.map(f=>[f.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),d=t.columns.some(p=>p.kind!=="closed"),u=t.columns.some(p=>p.kind==="closed"),m=d?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let p of t.columns)k[p.id]=[];let v=t.columns.find(p=>p.kind==="closed");for(let p of h)v&&k[v.id].push({...p,stage:v.id});let S=t.columns.filter(p=>p.kind!=="closed");for(let p of m){let f=cn(p,S);if(!f)continue;let x=k[f];x&&x.push({...p,stage:f})}if(i)for(let p of Object.keys(k))k[p]=k[p].filter(f=>f.assignee===i);for(let p of Object.keys(k))k[p].sort((f,x)=>{let b=(f.priority??99)-(x.priority??99);return b!==0?b:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([p,f])=>[p,f.length]));return{columns:k,totals:g}}async function Qm(t,e,a,n){let r=dn(a,n),o=t;r.closeIssue&&typeof o.setState=="function"?await o.setState(e,"close"):r.reopen&&typeof o.setState=="function"&&await o.setState(e,"reopen"),(r.addLabels?.length||r.removeLabels?.length)&&typeof o.transitionMany=="function"?await o.transitionMany(e,r.addLabels||[],r.removeLabels||[]):r.addLabels?.length&&t.transition&&await t.transition(e,r.addLabels[0],r.removeLabels?.[0])}function Zm(t){return{id:t.id,workflowId:t.workflowId,workflowVersion:t.workflowVersion,homeNode:t.homeNode,status:t.status,pending:t.pending,entityRef:t.entityRef,history:(t.history||[]).slice(-5),parentRunId:t.parentRunId,parentNodeId:t.parentNodeId,rootRunId:t.rootRunId,depth:t.depth,createdAt:t.createdAt,updatedAt:t.updatedAt}}function ef(t,e){if(t.source.type==="gitlab"){let a=e.channels.gitlab;if(!a?.token)throw new Error("channels.gitlab.token is required for gitlab boards");let n={};for(let r of a.agentMappings)r.gitlabUsernames.length&&(n[r.agentId]=r.gitlabUsernames);return new tr(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function tn(t){try{let e=at(process.cwd(),".agentx");Ml(e)||Wm(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
19636
|
+
`;Um(at(e,"board-audit.jsonl"),a)}catch{}}function an(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var tf=2e3;async function af(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",i=g=>{let p=new AbortController,f=setTimeout(()=>p.abort(),tf),x=()=>p.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:p.signal}).then(async b=>{let _=b.ok?await b.json().catch(()=>{}):void 0;return{ok:_!==void 0,json:async()=>_}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,d,u,m,h,k,v]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(p=>Array.isArray(p)?p:[],()=>[]);o.crons=g.map(p=>({id:p.id,enabled:p.enabled===!0,schedule:String(p.schedule||""),timezone:p.timezone,agent:String(p.agent||""),kind:typeof p.command=="string"&&p.command.trim()?"command":"agent",model:p.model,nextRun:p.nextRun,retryPending:p.retryPending===!0,consecutiveErrors:Number(p.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(k&&k.ok){let g=await k.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Ln.routines))}if(h&&h.ok){let g=await h.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(v&&v.ok){let g=await v.json().catch(()=>null);g&&Array.isArray(g.sessions)&&df(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(d?.ok?await d.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Zt=null;function nf(t){if(Zt)return Zt;let e=at(process.cwd(),".agentx/wiki");return Zt=Mr({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Zt}async function ta(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function rf(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function we(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await ta(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var of=3e3,sf=6e3,lf=5*6e4,rn=new Map,ea=new Map;function We(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=ea.get(a);if(n)return n;let r=(async()=>{let o=await we(t,AbortSignal.timeout(of)),s=await Promise.all(o.map(async i=>{let l=await af(i.url,i.token,AbortSignal.timeout(sf),e);return e?l:cf(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>ea.delete(a));return ea.set(a,r),r}function cf(t,e,a=Date.now()){if(e.reachable&&!e.error)return rn.set(t,{node:e,at:a}),e;let n=rn.get(t);return!n||a-n.at>lf?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function kw(){rn.clear(),ea.clear()}function df(t,e,a){let n=s=>s?s.replace(/\/+$/,"").split("/").pop()||s:"",r=e.map(s=>({session:String(s.sessionId).slice(0,8),project:n(s.cwd),agentIds:Array.isArray(s.agentIds)?s.agentIds:[],mode:String(s.mode||"notify"),lastSeenAt:Number(s.lastSeenAt)||0,pending:Number(s.pending)||0})),o=new Set(e.map(s=>s.sessionId));for(let[s,i]of Object.entries(a))o.has(s)||!Array.isArray(i.agentIds)||i.agentIds.length===0||r.push({session:s.slice(0,8),project:n(i.cwd),agentIds:i.agentIds,mode:String(i.mode||"notify"),lastSeenAt:Number(i.savedAt)||0,pending:0,waiting:!0});t.attachSessions=r;for(let s of t.agents){let i=r.find(l=>l.agentIds.includes(s.id)&&!l.waiting)??r.find(l=>l.agentIds.includes(s.id));i&&(s.attached={session:i.session,project:i.project,mode:i.mode,lastSeenAt:i.lastSeenAt,waiting:i.waiting})}}function pf(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,c)=>{n||e.write(`event: ${l}
|
|
19448
19637
|
data: ${JSON.stringify(c)}
|
|
19449
19638
|
|
|
19450
|
-
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await We(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function
|
|
19451
|
-
${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function
|
|
19639
|
+
`)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await We(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function uf(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await ta(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let v of k)i.add(v.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let d=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:d.signal})}catch(k){y(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:v}=await m.read();if(v)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{d.abort();try{e.end()}catch{}})}function mf(t,e,a){let n=pa(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ke(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function ff(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await pe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),d=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(d)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function hf(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await ta(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let d=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${d}`,{headers:c}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function gf(t,e,a,n,r,o){await on(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function on(t,e,a,n,r){let o={};try{o=await pe(t)??{}}catch{}let s=await Ll(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Ll(t,e,a,n){let r=(c,d)=>({status:c,text:JSON.stringify(d),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await ta(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let d of c)s.add(d.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function Rl(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=jn(e.keysFile);return{store:()=>{let r=Ue();return r?new lr(r):null},publicKey:()=>On(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function $l(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>We(t,n),async nodePost(n,r,o){let s=await Ll(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=vt({root:process.cwd()}).items.map(Cl)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=nt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(Cl)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=_e(),d=await bt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return d.ok?{status:200,body:{ok:!0,message:d.message}}:{status:409,body:{error:d.error}}}let l=nt(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}var nn=null;function Al(t){return nn?.days!==t&&(nn={days:t,store:new dt(process.cwd(),Date.now,t)}),nn.store}function Pl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=$l(t);return{store:()=>{let r=Ue();return r?new tt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:hn(process.cwd())??void 0},snapshot:()=>We(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s),tokenFor:r=>U(t.dashboard,r.replace(/\/+$/,"")),...xf(t,e,a)}}function xf(t,e,a){let n=Rl(t);return{finishAlerts:r=>{let o=n.store();return!!o&&o.chatFinishOn(r)&&o.list(r).length>0},notifyFinish:async r=>{try{let o=await fetch(e+"/channel/send",{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${a}`}:{}},body:JSON.stringify({channel:"push",chatId:r.deviceId,text:`${r.title}
|
|
19640
|
+
${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function vf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Pl(t);return new Qt({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await We(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:ki(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function bf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ue();return a?new tt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function yf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function Cl(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var wf=`
|
|
19452
19641
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
19453
19642
|
|
|
19454
19643
|
Title pattern:
|
|
@@ -19480,10 +19669,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
19480
19669
|
Shape:
|
|
19481
19670
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
19482
19671
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
19483
|
-
`;async function
|
|
19672
|
+
`;async function kf(t,e){let a=(e?.rough||"").toString().trim();if(!a)throw new Error("rough description required");let n=e?.agent||t.dashboard.draftAgent;if(!n)throw new Error("no draft agent configured (set dashboard.draftAgent or pass agent in body)");let r=e?.context||{},o=["Rough description from the user:",'"""',a,'"""',"",`Board: ${r.boardName||"(unspecified)"}`,r.primaryLabel?`Primary board label (include in labels): ${r.primaryLabel}`:"",r.columnLabel?`Target column label (include in labels): ${r.columnLabel}`:"",r.project?`GitLab project: ${r.project}`:"",r.knownLabels?.length?`Known labels in this project (prefer picking from these when they fit):
|
|
19484
19673
|
- ${r.knownLabels.slice(0,60).join(`
|
|
19485
19674
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
19486
|
-
`),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:
|
|
19675
|
+
`),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:wf}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let d=(c.content||"").toString(),u=_f(d);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+d.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:d}}function _f(t){if(!t)return null;try{return JSON.parse(t)}catch{}let e=t.match(/```(?:json)?\s*([\s\S]*?)```/);if(e)try{return JSON.parse(e[1])}catch{}let a=t.indexOf("{");if(a===-1)return null;let n=0;for(let r=a;r<t.length;r++){let o=t[r];if(o==="{")n++;else if(o==="}"&&(n--,n===0))try{return JSON.parse(t.slice(a,r+1))}catch{return null}}return null}function Sf(t){let e=Km(Xm(import.meta.url));return at(e,t)}async function Ef(t){return Gm(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function pe(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function jl(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:jl(s),tokenScope:s.dashboardToken||s.token?"proxy-ready":void 0})),o=r.length>0?[{id:"fleet",name:"Fleet (all peers)",dashboardUrl:"",tokenScope:"merged across nodes"}]:[];return[n,...r,...o]}async function Tf(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await Ut(await Ol(r,a.config)))}async function Ol(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=ja(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=nt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,d=setTimeout(()=>c.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(d)}}catch{return null}}));for(let i of s)i&&n.push(i);return Ts(n)}async function Af(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(k=>Ml(k));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
|
|
19487
19676
|
|
|
19488
19677
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let m;for(;(m=i.indexOf(`
|
|
19489
19678
|
`))>=0;){let h=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
|
|
@@ -19491,5 +19680,5 @@ data: ${h.replace(/\n/g," ")}
|
|
|
19491
19680
|
|
|
19492
19681
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
19493
19682
|
|
|
19494
|
-
`)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function
|
|
19495
|
-
//# sourceMappingURL=board-dashboard-
|
|
19683
|
+
`)}catch{}},15e3),d=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",d),s.on("exit",d),s.on("error",d)}async function Il(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let d=t.headers["x-requested-with"];d&&(l["X-Requested-With"]=Array.isArray(d)?d[0]:d),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function nt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:jl(n),token:n.dashboardToken||n.token}:null}export{df as applyAttachSessions,af as fetchDaemonAgents,Vm as handleBoardRequest,kw as resetLiveCaches,we as resolveNodeTargets,ww as startBoardDashboard,cf as withLastGood};
|
|
19684
|
+
//# sourceMappingURL=board-dashboard-5EPKRDEW.js.map
|