agentix-cli 0.92.2 → 0.92.4
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-PVRIWBSD.js → board-dashboard-MHMYOBKA.js} +283 -249
- package/dist/board-dashboard-MHMYOBKA.js.map +1 -0
- package/dist/{chunk-GNSYQB2P.js → chunk-GWOJJ7FE.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-W3XWXPKS.js → program-IAOEFLZP.js} +4 -4
- package/package.json +1 -1
- package/dist/board-dashboard-PVRIWBSD.js.map +0 -1
- /package/dist/{chunk-GNSYQB2P.js.map → chunk-GWOJJ7FE.js.map} +0 -0
- /package/dist/{program-W3XWXPKS.js.map → program-IAOEFLZP.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as A,b as dr,c as pr,d as ur,e as mr,f as _e,g as fr,h as hr,i as It,k as gr,n as xr,o as vr,p as br,q as yr,r as wr,v as kr,w as _r,x as Er,y as Tr,z as Ar}from"./chunk-Q4R4OS5S.js";import{a as Sr}from"./chunk-UVMCAZL7.js";import{a as cr}from"./chunk-QAIYUMHW.js";import{a as Tt,b as z,c as M,h as ve,i as At,j as re,k as K,l as Ct,m as sr,n as ir,o as lr}from"./chunk-N7HKIMMR.js";import{a as or}from"./chunk-2NYP4OQU.js";import{a as ce,b as rr}from"./chunk-JWDJMFU6.js";import{$a as nr,A as vt,B as Dn,E as Hn,F as Bn,Fa as Yn,G as zn,Ha as Ne,Ma as Qn,N as U,O as qn,Oa as De,P as Fn,Pa as wt,Qa as kt,Ra as _t,Sa as St,Ta as Zn,Ua as er,Va as tr,Wa as Et,Ya as ar,a as Tn,c as ut,d as sa,e as An,i as mt,l as Xe,n as Cn,ta as Xn,va as Kn,w as ht,wa as Jn,x as Pn,xa as Vn,y as gt,z as xt}from"./chunk-LKBUTSYP.js";import"./chunk-GTJIKXDB.js";import{g as Sn,h as En}from"./chunk-PS3UB5PH.js";import{a as Nn,b as N,c as Un,d as Wn,h as Gn}from"./chunk-DG5I6PPM.js";import{p as In,t as Mn}from"./chunk-S2GAEH2F.js";import"./chunk-IWEN3YNQ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Ln,e as ia}from"./chunk-ACFQBLPX.js";import{g as ft}from"./chunk-LQE73AZR.js";import{b as Rn,c as $n}from"./chunk-2D3RYIDU.js";import{m as jn,n as bt,o as yt,q as On}from"./chunk-E5OV6RTG.js";import{a as xn,f as vn,g as ra,h as oa,l as bn,m as yn,n as wn,u as ct,v as dt,w as pt,x as le,y as _n}from"./chunk-5PFTUGP4.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5EOFTPQB.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-M56MKNAG.js";import{a as kn}from"./chunk-HJUBCA7O.js";import"./chunk-DS7CDASP.js";import"./chunk-T2IDDOSX.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 gn}from"./chunk-OQHC7TJL.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-MIRBKQHA.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 dn,J as
|
|
1
|
+
import{a as A,b as dr,c as pr,d as ur,e as mr,f as _e,g as fr,h as hr,i as It,k as gr,n as xr,o as vr,p as br,q as yr,r as wr,v as kr,w as _r,x as Er,y as Tr,z as Ar}from"./chunk-Q4R4OS5S.js";import{a as Sr}from"./chunk-UVMCAZL7.js";import{a as cr}from"./chunk-QAIYUMHW.js";import{a as Tt,b as z,c as M,h as ve,i as At,j as re,k as K,l as Ct,m as sr,n as ir,o as lr}from"./chunk-N7HKIMMR.js";import{a as or}from"./chunk-2NYP4OQU.js";import{a as ce,b as rr}from"./chunk-JWDJMFU6.js";import{$a as nr,A as vt,B as Dn,E as Hn,F as Bn,Fa as Yn,G as zn,Ha as Ne,Ma as Qn,N as U,O as qn,Oa as De,P as Fn,Pa as wt,Qa as kt,Ra as _t,Sa as St,Ta as Zn,Ua as er,Va as tr,Wa as Et,Ya as ar,a as Tn,c as ut,d as sa,e as An,i as mt,l as Xe,n as Cn,ta as Xn,va as Kn,w as ht,wa as Jn,x as Pn,xa as Vn,y as gt,z as xt}from"./chunk-LKBUTSYP.js";import"./chunk-GTJIKXDB.js";import{g as Sn,h as En}from"./chunk-PS3UB5PH.js";import{a as Nn,b as N,c as Un,d as Wn,h as Gn}from"./chunk-DG5I6PPM.js";import{p as In,t as Mn}from"./chunk-S2GAEH2F.js";import"./chunk-IWEN3YNQ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Ln,e as ia}from"./chunk-ACFQBLPX.js";import{g as ft}from"./chunk-LQE73AZR.js";import{b as Rn,c as $n}from"./chunk-2D3RYIDU.js";import{m as jn,n as bt,o as yt,q as On}from"./chunk-E5OV6RTG.js";import{a as xn,f as vn,g as ra,h as oa,l as bn,m as yn,n as wn,u as ct,v as dt,w as pt,x as le,y as _n}from"./chunk-5PFTUGP4.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5EOFTPQB.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-M56MKNAG.js";import{a as kn}from"./chunk-HJUBCA7O.js";import"./chunk-DS7CDASP.js";import"./chunk-T2IDDOSX.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 gn}from"./chunk-OQHC7TJL.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-MIRBKQHA.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 dn,J as Al,K as pn,L as un,N as mn,P as fn,T as hn,a as nn,b as rn,c as Sl,ea as X,ha as lt,r as ot,s as El,t as aa,u as na,x as Tl}from"./chunk-VUSDWZ6L.js";import{a as it,i as cn}from"./chunk-RJ7DASOU.js";import{a as on,b as st,c as ta,d as sn,h as ln}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function la(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 Cr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:la(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>",Mt=(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 Ir(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 @@ ${Mt(oe.file,"Session briefings","brief-count")}
|
|
|
85
85
|
</div>
|
|
86
86
|
</details>
|
|
87
87
|
</section>
|
|
88
|
-
</div>`,css:
|
|
88
|
+
</div>`,css:Cl,scripts:`<script>${z({decayOf:la,rankByDecay:Cr})}const ICON = ${JSON.stringify(oe)};${Il}</script>`})}var Cl=`
|
|
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
|
+
}`,Il=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 ca(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),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}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 da(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 Mr(t,e=[],a){let{bands:n,gaps:r}=ca(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(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),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:f,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,p)=>da(l.runs.filter(u=>u.band===p))),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 ca(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),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}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 da(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 Mr(t,e=[],a){let{bands:n,gaps:r}=ca(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(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),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:f,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,p)=>da(l.runs.filter(u=>u.band===p))),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 Ml}from"crypto";import{readFileSync as Ll,statSync as Rl}from"fs";import{resolve as $l,dirname as Pl}from"path";import{fileURLToPath as jl}from"url";var Lr=new Map;function Lt(t){let e=Lr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Pl(jl(import.meta.url)),r=$l(n,"web",t),o=Rl(r),s=o.size<8e6?Ml("sha1").update(Ll(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Lr.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"/>'},Rt=(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>",Ol=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],Rr={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 $r(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
|
+
${Ol.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Rt(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="${Lt("activity-graph.global.js")}"></div>
|
|
820
820
|
</div>
|
|
821
821
|
|
|
822
|
-
</div>`,css:
|
|
822
|
+
</div>`,css:Nl,scripts:`<script>${z({computeBands:ca,packTracks:da,buildTimeline:Mr})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(Rr)};${Dl}</script>`})}var Nl=`
|
|
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
|
+
`,Dl=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 Pr(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 Pr(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:Hl,scripts:`<script src="${Lt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Hl=`
|
|
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,8 +1045,101 @@ 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
|
|
1049
|
-
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...na,n-
|
|
1048
|
+
`;import{createServer as Im}from"http";import{appendFileSync as Mm,existsSync as fl,mkdirSync as Lm}from"fs";import{readFile as Rm}from"fs/promises";import{fileURLToPath as $m}from"url";import{dirname as Pm,resolve as at}from"path";Al();function He(t,e){if(!t)return"absent";let a=Ln(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 $t(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=jr(t.headers["sec-fetch-mode"]),n.site=jr(t.headers["sec-fetch-site"]),n}function jr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Bl}from"zlib";var zl=[41,121,255],ql=[255,255,255],Or=new Map;function Be(t){let e=Or.get(t);return e||(e=Ul(t,Fl(t)),Or.set(t,e)),e}function Fl(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?ql:zl;a.set(c,o*e+1+s*3)}return a}function Ul(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]),pa("IHDR",a),pa("IDAT",Bl(e)),pa("IEND",Buffer.alloc(0))])}function pa(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(Gl(n)),Buffer.concat([a,n,r])}var Wl=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 Gl(t){let e=4294967295;for(let a of t)e=Wl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}lt();Tl();var Xl=7,Kl={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Jl(t,e){let a=t.toLowerCase().split("@")[0],n=Kl[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 Nr(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 Dr(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(u=>u.name==="person"),i=u=>({id:u.id,state:u.state,agentId:u.agent_id,text:u.text,channel:u.channel,chatId:u.chat_id,createdAt:u.created_at,updatedAt:u.updated_at,closedAt:u.closed_at??null,question:u.question??null,attentionReason:u.attention_reason??null,evidence:u.evidence??null,where:{label:Jl(u.channel,u.chat_id),url:a.linkFor?.(u.channel,u.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${aa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...aa).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${na.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
|
|
1049
|
+
ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...na,n-Xl*864e5).map(i):[],p=[];try{p=It(t,e,10)}catch{}return{open:l,recent:c,runs:p}}function Hr(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Br(t,e){return!t||e-t>=3e4||t>e}function Pt(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 zr(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 qr(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 Fr(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()}var Ur=`
|
|
1050
|
+
(function () {
|
|
1051
|
+
var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
|
|
1052
|
+
var who = document.getElementById('who');
|
|
1053
|
+
var strip = document.getElementById('offline');
|
|
1054
|
+
var stripText = document.getElementById('offline-text');
|
|
1055
|
+
var retry = document.getElementById('retry');
|
|
1056
|
+
var install = document.getElementById('install');
|
|
1057
|
+
var updated = document.getElementById('updated');
|
|
1058
|
+
var theme = document.getElementById('theme');
|
|
1059
|
+
// No network counts as a failed load until a load works (#496).
|
|
1060
|
+
var failed = navigator.onLine === false, loaded = false, named = false, busy = false, timer = null;
|
|
1061
|
+
theme.addEventListener('click', function () {
|
|
1062
|
+
var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
1063
|
+
document.documentElement.setAttribute('data-theme', cur);
|
|
1064
|
+
try { localStorage.setItem('ax-theme', cur); } catch (e) {}
|
|
1065
|
+
});
|
|
1066
|
+
if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
|
|
1067
|
+
var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
|
|
1068
|
+
if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
|
|
1069
|
+
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
|
|
1070
|
+
function showConn() {
|
|
1071
|
+
var note = connectionNote(failed, navigator.onLine !== false, RETRY_S, loaded);
|
|
1072
|
+
strip.hidden = !note;
|
|
1073
|
+
if (!note) return;
|
|
1074
|
+
// Same words are not written again: a screen reader would repeat them on every failed round.
|
|
1075
|
+
if (stripText.textContent !== note.text) stripText.textContent = note.text;
|
|
1076
|
+
retry.hidden = !note.retry;
|
|
1077
|
+
}
|
|
1078
|
+
window.addEventListener('online', function () { failed = false; showConn(); load(); });
|
|
1079
|
+
window.addEventListener('offline', function () { failed = true; showConn(); });
|
|
1080
|
+
retry.addEventListener('click', function () { load(); });
|
|
1081
|
+
// A 401 or 403 means this machine's key ended: /member then shows the pairing page.
|
|
1082
|
+
function get(url) {
|
|
1083
|
+
var ac = new AbortController();
|
|
1084
|
+
var giveUp = setTimeout(function () { ac.abort(); }, GIVE_UP_MS);
|
|
1085
|
+
return fetch(url, { credentials: 'same-origin', cache: 'no-store', signal: ac.signal }).then(function (r) {
|
|
1086
|
+
if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
|
|
1087
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
1088
|
+
return r.json();
|
|
1089
|
+
}).then(function (j) { clearTimeout(giveUp); return j; }, function (e) { clearTimeout(giveUp); throw e; });
|
|
1090
|
+
}
|
|
1091
|
+
function where(r) {
|
|
1092
|
+
var label = esc(r.where && r.where.label || r.channel);
|
|
1093
|
+
return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
|
|
1094
|
+
}
|
|
1095
|
+
function item(r, now, closed) {
|
|
1096
|
+
var st = workState(r.state);
|
|
1097
|
+
var note = '';
|
|
1098
|
+
if (r.state === 'waiting_owner' && r.question) note = '<p class="note"><b>The owner is asked:</b> ' + esc(r.question) + '</p>';
|
|
1099
|
+
else if (r.state === 'needs_attention' && r.attentionReason) note = '<p class="note">' + esc(r.attentionReason) + '</p>';
|
|
1100
|
+
else if (closed && r.evidence) note = /^https?:\\/\\//i.test(r.evidence)
|
|
1101
|
+
? '<p class="note"><a href="' + esc(r.evidence) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>'
|
|
1102
|
+
: '<p class="note"><b>What was delivered:</b> ' + esc(r.evidence) + '</p>';
|
|
1103
|
+
var age = closed ? 'closed ' + ageText(r.closedAt || r.updatedAt, now) + ' ago' : 'for ' + ageText(r.createdAt, now);
|
|
1104
|
+
return '<li class="item"><p class="text">' + esc(r.text) + '</p>' +
|
|
1105
|
+
'<p class="meta"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span>' + esc(r.agentId) + '</span><span>' + age + '</span><span>asked on ' + where(r) + '</span></p>' + note + '</li>';
|
|
1106
|
+
}
|
|
1107
|
+
function run(r, now) {
|
|
1108
|
+
var mark = r.status === 'ok' ? 'finished' : r.status === 'in-flight' ? 'running' : esc(r.status);
|
|
1109
|
+
return '<li class="item"><p class="text">' + esc(plainPreview(r.messagePreview)) + '</p><p class="meta"><span class="state ' + (r.status === 'ok' ? 'ok' : r.status === 'in-flight' ? 'warn' : 'bad') + '">' + mark + '</span><span>' + esc(r.agentId) + '</span><span>' + ageText(r.startedAt, now) + ' ago</span><span>' + esc(r.channel || '') + '</span></p></li>';
|
|
1110
|
+
}
|
|
1111
|
+
function fill(id, html, empty) { document.getElementById(id).innerHTML = html || '<li class="muted">' + empty + '</li>'; }
|
|
1112
|
+
function loadName() {
|
|
1113
|
+
if (named) return;
|
|
1114
|
+
get('/api/member/me').then(function (me) {
|
|
1115
|
+
if (!me) return;
|
|
1116
|
+
named = true;
|
|
1117
|
+
who.textContent = me.name + ' \xB7 ' + me.device + (me.node ? ' \xB7 ' + me.node : '');
|
|
1118
|
+
}).catch(function () { /* the next round asks again; the work load of this round reports the failure */ });
|
|
1119
|
+
}
|
|
1120
|
+
function load() {
|
|
1121
|
+
if (busy) return;
|
|
1122
|
+
busy = true; retry.disabled = true; clearTimeout(timer);
|
|
1123
|
+
loadName();
|
|
1124
|
+
get('/api/member/work').then(function (w) {
|
|
1125
|
+
if (!w) return;
|
|
1126
|
+
failed = false;
|
|
1127
|
+
var now = Date.now();
|
|
1128
|
+
document.getElementById('n-open').textContent = w.open.length ? '(' + w.open.length + ')' : '';
|
|
1129
|
+
fill('open', w.open.map(function (r) { return item(r, now, false); }).join(''), 'Nothing open. What you ask the agents for shows up here while it is being worked on.');
|
|
1130
|
+
fill('recent', w.recent.map(function (r) { return item(r, now, true); }).join(''), 'Nothing finished in the last 7 days.');
|
|
1131
|
+
fill('runs', w.runs.map(function (r) { return run(r, now); }).join(''), 'No turns recorded yet.');
|
|
1132
|
+
updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString();
|
|
1133
|
+
loaded = true;
|
|
1134
|
+
}).catch(function () { failed = true; }).then(function () {
|
|
1135
|
+
busy = false; retry.disabled = false; showConn();
|
|
1136
|
+
timer = setTimeout(load, (failed ? RETRY_S : POLL_S) * 1000);
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
showConn();
|
|
1140
|
+
load();
|
|
1141
|
+
})();
|
|
1142
|
+
`;var Vl="<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 ua(t){return`<meta charset="utf-8">
|
|
1050
1143
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
1051
1144
|
<meta name="theme-color" content="#2979FF">
|
|
1052
1145
|
<meta name="referrer" content="no-referrer">
|
|
@@ -1056,8 +1149,8 @@ body { margin: 0; overflow: hidden; }
|
|
|
1056
1149
|
<link rel="icon" type="image/png" href="/member/icon-192.png">
|
|
1057
1150
|
<link rel="apple-touch-icon" href="/member/icon-192.png">
|
|
1058
1151
|
<title>${t}</title>
|
|
1059
|
-
${
|
|
1060
|
-
<style>${Tt}${
|
|
1152
|
+
${Vl}
|
|
1153
|
+
<style>${Tt}${Zl}</style>`}function Wr(){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 Gr=`
|
|
1061
1154
|
var CACHE = 'agentx-member-v1';
|
|
1062
1155
|
var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
|
|
1063
1156
|
self.addEventListener('install', function (e) {
|
|
@@ -1087,15 +1180,15 @@ self.addEventListener('fetch', function (e) {
|
|
|
1087
1180
|
e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
|
|
1088
1181
|
}
|
|
1089
1182
|
});
|
|
1090
|
-
`;function
|
|
1183
|
+
`;function Xr(){return`<!doctype html>
|
|
1091
1184
|
<html lang="en">
|
|
1092
|
-
<head>${ua("My work \xB7 AgentX")}<style>${
|
|
1185
|
+
<head>${ua("My work \xB7 AgentX")}<style>${ec}</style></head>
|
|
1093
1186
|
<body>
|
|
1094
1187
|
<header class="bar">
|
|
1095
1188
|
<div><h1>My work</h1><p id="who" class="who">Connecting\u2026</p></div>
|
|
1096
1189
|
<button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>
|
|
1097
1190
|
</header>
|
|
1098
|
-
<p id="offline" class="offline" role="status" hidden>
|
|
1191
|
+
<p id="offline" class="offline" role="status" hidden><span id="offline-text"></span> <button type="button" id="retry" hidden>Try now</button></p>
|
|
1099
1192
|
<p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
|
|
1100
1193
|
<main>
|
|
1101
1194
|
<section aria-labelledby="h-open"><h2 id="h-open">Open <span id="n-open" class="count"></span></h2><ul id="open" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
@@ -1103,11 +1196,11 @@ self.addEventListener('fetch', function (e) {
|
|
|
1103
1196
|
<section aria-labelledby="h-runs"><h2 id="h-runs">Latest turns</h2><ul id="runs" class="list"><li class="muted">Loading\u2026</li></ul></section>
|
|
1104
1197
|
<p id="updated" class="muted small"></p>
|
|
1105
1198
|
</main>
|
|
1106
|
-
<script>${z({workState:
|
|
1199
|
+
<script>${z({workState:Yl,ageText:Ql,connectionNote:qr,plainPreview:Fr})}${Ur}</script>
|
|
1107
1200
|
</body>
|
|
1108
|
-
</html>`}function
|
|
1201
|
+
</html>`}function Kr(){return`<!doctype html>
|
|
1109
1202
|
<html lang="en">
|
|
1110
|
-
<head>${ua("Pair this machine \xB7 AgentX")}<style>${
|
|
1203
|
+
<head>${ua("Pair this machine \xB7 AgentX")}<style>${tc}</style></head>
|
|
1111
1204
|
<body>
|
|
1112
1205
|
<main class="card">
|
|
1113
1206
|
<h1>Pair this machine</h1>
|
|
@@ -1124,9 +1217,9 @@ self.addEventListener('fetch', function (e) {
|
|
|
1124
1217
|
</form>
|
|
1125
1218
|
<p class="muted">No code? Ask the owner to run <code>agentx people invite <you></code>. A code works once, for 10 minutes.</p>
|
|
1126
1219
|
</main>
|
|
1127
|
-
<script>${z({formatPairInput:Pt})}${
|
|
1220
|
+
<script>${z({formatPairInput:Pt})}${ac}</script>
|
|
1128
1221
|
</body>
|
|
1129
|
-
</html>`}function
|
|
1222
|
+
</html>`}function Jr(){return`<!doctype html>
|
|
1130
1223
|
<html lang="en">
|
|
1131
1224
|
<head>${ua("Waiting for the owner \xB7 AgentX")}</head>
|
|
1132
1225
|
<body>
|
|
@@ -1135,9 +1228,9 @@ self.addEventListener('fetch', function (e) {
|
|
|
1135
1228
|
<p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens by itself when they do.</p>
|
|
1136
1229
|
<p class="muted">If they said no, this page will ask for a new code.</p>
|
|
1137
1230
|
</main>
|
|
1138
|
-
<script>${
|
|
1231
|
+
<script>${nc}</script>
|
|
1139
1232
|
</body>
|
|
1140
|
-
</html>`}function
|
|
1233
|
+
</html>`}function Yl(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 Ql(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 Zl=`
|
|
1141
1234
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
1142
1235
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
1143
1236
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -1146,13 +1239,15 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
1146
1239
|
.muted { color: var(--ax-text-2); }
|
|
1147
1240
|
.small { font-size: var(--ax-fs-xs); }
|
|
1148
1241
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
1149
|
-
`,
|
|
1242
|
+
`,ec=`
|
|
1150
1243
|
body { display: flex; flex-direction: column; }
|
|
1151
1244
|
.bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; background: var(--ax-surface); border-bottom: var(--ax-border-w) solid var(--ax-border); }
|
|
1152
1245
|
.bar h1 { font-size: 18px; margin: 0; font-weight: 700; }
|
|
1153
1246
|
.who { margin: 2px 0 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
1154
1247
|
.icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-pill); background: var(--ax-surface-2); color: var(--ax-text); cursor: pointer; }
|
|
1155
1248
|
.offline, .install { margin: 0; padding: 8px 16px; font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: 1px solid var(--ax-amber-e); }
|
|
1249
|
+
.offline button { margin-left: 8px; min-height: 32px; padding: 4px 14px; font: inherit; font-weight: 600; color: inherit; background: transparent; border: 1px solid currentColor; border-radius: var(--ax-radius-pill); cursor: pointer; }
|
|
1250
|
+
.offline button:disabled { opacity: 0.55; cursor: default; }
|
|
1156
1251
|
.install { background: var(--ax-surface-2); color: var(--ax-text-2); border-bottom: var(--ax-border-w) solid var(--ax-border); }
|
|
1157
1252
|
main { flex: 1; overflow-y: auto; padding: 16px; max-width: 720px; width: 100%; box-sizing: border-box; margin: 0 auto; }
|
|
1158
1253
|
main h2 { font-size: 16px; margin: 12px 0 8px; }
|
|
@@ -1169,7 +1264,7 @@ main h2 { font-size: 16px; margin: 12px 0 8px; }
|
|
|
1169
1264
|
[data-theme="dark"] .state.bad { color: var(--ax-red); }
|
|
1170
1265
|
.state.muted { color: var(--ax-text-2); }
|
|
1171
1266
|
a { color: var(--ax-accent); }
|
|
1172
|
-
`,
|
|
1267
|
+
`,tc=`
|
|
1173
1268
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
1174
1269
|
.pair-form label { font-weight: 600; }
|
|
1175
1270
|
.pair-form input { box-sizing: border-box; width: 100%; min-height: 48px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: 2px solid var(--ax-border); border-radius: var(--ax-radius-sm); }
|
|
@@ -1181,7 +1276,7 @@ a { color: var(--ax-accent); }
|
|
|
1181
1276
|
.pair-msg.bad { color: var(--ax-red-ink); }
|
|
1182
1277
|
[data-theme="dark"] .pair-msg.bad { color: var(--ax-red); }
|
|
1183
1278
|
.pair-offline { margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
|
|
1184
|
-
`,
|
|
1279
|
+
`,ac=`
|
|
1185
1280
|
(function () {
|
|
1186
1281
|
var form = document.getElementById('pair-form');
|
|
1187
1282
|
var machine = document.getElementById('machine');
|
|
@@ -1225,7 +1320,7 @@ a { color: var(--ax-accent); }
|
|
|
1225
1320
|
}).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
|
|
1226
1321
|
});
|
|
1227
1322
|
})();
|
|
1228
|
-
`,
|
|
1323
|
+
`,nc=`
|
|
1229
1324
|
(function () {
|
|
1230
1325
|
var msg = document.getElementById('msg');
|
|
1231
1326
|
function check() {
|
|
@@ -1236,71 +1331,10 @@ a { color: var(--ax-accent); }
|
|
|
1236
1331
|
}
|
|
1237
1332
|
setInterval(check, 5000);
|
|
1238
1333
|
})();
|
|
1239
|
-
`,tc=`
|
|
1240
|
-
(function () {
|
|
1241
|
-
var who = document.getElementById('who');
|
|
1242
|
-
var offline = document.getElementById('offline');
|
|
1243
|
-
var install = document.getElementById('install');
|
|
1244
|
-
var updated = document.getElementById('updated');
|
|
1245
|
-
var theme = document.getElementById('theme');
|
|
1246
|
-
theme.addEventListener('click', function () {
|
|
1247
|
-
var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
1248
|
-
document.documentElement.setAttribute('data-theme', cur);
|
|
1249
|
-
try { localStorage.setItem('ax-theme', cur); } catch (e) {}
|
|
1250
|
-
});
|
|
1251
|
-
if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
|
|
1252
|
-
var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
|
|
1253
|
-
if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
|
|
1254
|
-
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
|
|
1255
|
-
function setOnline(on) { offline.hidden = on; }
|
|
1256
|
-
window.addEventListener('online', function () { setOnline(true); load(); });
|
|
1257
|
-
window.addEventListener('offline', function () { setOnline(false); });
|
|
1258
|
-
function where(r) {
|
|
1259
|
-
var label = esc(r.where && r.where.label || r.channel);
|
|
1260
|
-
return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
|
|
1261
|
-
}
|
|
1262
|
-
function item(r, now, closed) {
|
|
1263
|
-
var st = workState(r.state);
|
|
1264
|
-
var note = '';
|
|
1265
|
-
if (r.state === 'waiting_owner' && r.question) note = '<p class="note"><b>The owner is asked:</b> ' + esc(r.question) + '</p>';
|
|
1266
|
-
else if (r.state === 'needs_attention' && r.attentionReason) note = '<p class="note">' + esc(r.attentionReason) + '</p>';
|
|
1267
|
-
else if (closed && r.evidence) note = /^https?:\\/\\//i.test(r.evidence)
|
|
1268
|
-
? '<p class="note"><a href="' + esc(r.evidence) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>'
|
|
1269
|
-
: '<p class="note"><b>What was delivered:</b> ' + esc(r.evidence) + '</p>';
|
|
1270
|
-
var age = closed ? 'closed ' + ageText(r.closedAt || r.updatedAt, now) + ' ago' : 'for ' + ageText(r.createdAt, now);
|
|
1271
|
-
return '<li class="item"><p class="text">' + esc(r.text) + '</p>' +
|
|
1272
|
-
'<p class="meta"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span>' + esc(r.agentId) + '</span><span>' + age + '</span><span>asked on ' + where(r) + '</span></p>' + note + '</li>';
|
|
1273
|
-
}
|
|
1274
|
-
function run(r, now) {
|
|
1275
|
-
var mark = r.status === 'ok' ? 'finished' : r.status === 'in-flight' ? 'running' : esc(r.status);
|
|
1276
|
-
return '<li class="item"><p class="text">' + esc(r.messagePreview || '') + '</p><p class="meta"><span class="state ' + (r.status === 'ok' ? 'ok' : r.status === 'in-flight' ? 'warn' : 'bad') + '">' + mark + '</span><span>' + esc(r.agentId) + '</span><span>' + ageText(r.startedAt, now) + ' ago</span><span>' + esc(r.channel || '') + '</span></p></li>';
|
|
1277
|
-
}
|
|
1278
|
-
function fill(id, html, empty) { document.getElementById(id).innerHTML = html || '<li class="muted">' + empty + '</li>'; }
|
|
1279
|
-
function load() {
|
|
1280
|
-
fetch('/api/member/work', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
|
|
1281
|
-
if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
|
|
1282
|
-
return r.json();
|
|
1283
|
-
}).then(function (w) {
|
|
1284
|
-
if (!w) return;
|
|
1285
|
-
setOnline(true);
|
|
1286
|
-
var now = Date.now();
|
|
1287
|
-
document.getElementById('n-open').textContent = w.open.length ? '(' + w.open.length + ')' : '';
|
|
1288
|
-
fill('open', w.open.map(function (r) { return item(r, now, false); }).join(''), 'Nothing open. What you ask the agents for shows up here while it is being worked on.');
|
|
1289
|
-
fill('recent', w.recent.map(function (r) { return item(r, now, true); }).join(''), 'Nothing finished in the last 7 days.');
|
|
1290
|
-
fill('runs', w.runs.map(function (r) { return run(r, now); }).join(''), 'No turns recorded yet.');
|
|
1291
|
-
updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString();
|
|
1292
|
-
}).catch(function () { setOnline(false); });
|
|
1293
|
-
}
|
|
1294
|
-
fetch('/api/member/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.ok ? r.json() : null; }).then(function (me) {
|
|
1295
|
-
if (me) who.textContent = me.name + ' \xB7 ' + me.device + (me.node ? ' \xB7 ' + me.node : '');
|
|
1296
|
-
}).catch(function () {});
|
|
1297
|
-
load();
|
|
1298
|
-
setInterval(load, 30000);
|
|
1299
|
-
})();
|
|
1300
|
-
`;var jt="agentx_member",ac=90*86400,nc=new yt,Vr=t=>t.replace(/^\[app\]/,"[member]"),rc=new Ee(t=>console.log(Vr(t))),Xr=new WeakMap;function oc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return rc;let e=Xr.get(t.log);return e||Xr.set(t.log,e=new Ee(a=>t.log(Vr(a)))),e}var Kr=null;function Ke(t,e=X){try{return Kr=e().people}catch{return Kr??t}}async function Yr(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 ct(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ft(r.root),limiter:r.pairLimiter??nc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",qr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",Fr);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 p=await vr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Jr(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Te(e,p.status,p.body)}let l=yr(sc(t),i,xr(t));if(!l.ok){if(l.status===401){let p=ma(t);return oc(r).record(a.slice(0,120),$t(t,He(fa(t,jt),o),p?He(p,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",Wr()):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",Gr()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=fa(t,jt);return p&&!ma(t)&&e.setHeader("Set-Cookie",Jr(p)),be(e,200,"text/html; charset=utf-8",Ur())}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 p=r.db?.()??null;return p?Te(e,200,Dr(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Te(e,503,{error:"the work list needs the database"})}return Te(e,404,{error:"not found"})}function Jr(t){return`${jt}=${t}; Path=/; Max-Age=${ac}; HttpOnly; Secure; SameSite=Lax`}function sc(t){return ma(t)??fa(t,jt)}function ma(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function fa(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))}wl();var Qr='/*! 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 Nt,readFileSync as so,writeFileSync as io,rmSync as lh,mkdirSync as uc,copyFileSync as mc,readdirSync as fc}from"fs";import{resolve as ze}from"path";kl();function eo(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 Ot(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 Zr=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function to(t){return Ot(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 ao(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ot((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:Zr(t?.chats),senders:Zr(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 no(t){let e=String(t?.id??"");return Ot(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 ro(t){let e=String(t?.id??"");return Ot(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}"`})}lt();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 oo(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.`})+At([{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+lc()+sr,css:dc,scripts:`${e}<script>${ir}
|
|
1334
|
+
`;var jt="agentx_member",rc=90*86400,oc=new yt,Zr=t=>t.replace(/^\[app\]/,"[member]"),sc=new Ee(t=>console.log(Zr(t))),Vr=new WeakMap;function ic(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return sc;let e=Vr.get(t.log);return e||Vr.set(t.log,e=new Ee(a=>t.log(Zr(a)))),e}var Yr=null;function Ke(t,e=X){try{return Yr=e().people}catch{return Yr??t}}async function eo(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 ct(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ft(r.root),limiter:r.pairLimiter??oc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",Wr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",Gr);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 p=await vr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Qr(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Te(e,p.status,p.body)}let l=yr(lc(t),i,xr(t));if(!l.ok){if(l.status===401){let p=ma(t);return ic(r).record(a.slice(0,120),$t(t,He(fa(t,jt),o),p?He(p,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",Kr()):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",Jr()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=fa(t,jt);return p&&!ma(t)&&e.setHeader("Set-Cookie",Qr(p)),be(e,200,"text/html; charset=utf-8",Xr())}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 p=r.db?.()??null;return p?Te(e,200,Dr(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Te(e,503,{error:"the work list needs the database"})}return Te(e,404,{error:"not found"})}function Qr(t){return`${jt}=${t}; Path=/; Max-Age=${rc}; HttpOnly; Secure; SameSite=Lax`}function lc(t){return ma(t)??fa(t,jt)}function ma(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function fa(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))}Sl();var to='/*! 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 Nt,readFileSync as co,writeFileSync as po,rmSync as fh,mkdirSync as fc,copyFileSync as hc,readdirSync as gc}from"fs";import{resolve as ze}from"path";El();function no(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 Ot(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 ao=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function ro(t){return Ot(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 oo(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ot((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:ao(t?.chats),senders:ao(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 so(t){let e=String(t?.id??"");return Ot(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 io(t){let e=String(t?.id??"");return Ot(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}"`})}lt();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 lo(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.`})+At([{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+dc()+sr,css:uc,scripts:`${e}<script>${ir}
|
|
1301
1335
|
${lr}
|
|
1302
|
-
${
|
|
1303
|
-
${
|
|
1336
|
+
${cc}
|
|
1337
|
+
${mc}</script>`})}var cc=`
|
|
1304
1338
|
(function(){
|
|
1305
1339
|
function fmt(n) { return n == null ? '\u2014' : String(n); }
|
|
1306
1340
|
async function voiceMissing() {
|
|
@@ -1394,8 +1428,8 @@ ${pc}</script>`})}var ic=`
|
|
|
1394
1428
|
refresh();
|
|
1395
1429
|
// Refresh again after the main admin script has had a chance to mutate config.
|
|
1396
1430
|
document.addEventListener('ax-config-saved', refresh);
|
|
1397
|
-
})();`;function
|
|
1398
|
-
`:"";return
|
|
1431
|
+
})();`;function dc(){let t=Wn().business?`<button data-tab="business">Business</button>
|
|
1432
|
+
`:"";return pc.replace("__BUSINESS_TABS__",t)}var pc=`
|
|
1399
1433
|
<div id="peer-banner" class="peer-banner">
|
|
1400
1434
|
<span class="label">Managing</span>
|
|
1401
1435
|
<span class="name" id="peer-banner-name">\u2014</span>
|
|
@@ -2054,7 +2088,7 @@ ${pc}</script>`})}var ic=`
|
|
|
2054
2088
|
<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>
|
|
2055
2089
|
</section>
|
|
2056
2090
|
</main>
|
|
2057
|
-
`,
|
|
2091
|
+
`,uc=`
|
|
2058
2092
|
|
|
2059
2093
|
/* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
|
|
2060
2094
|
nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
|
|
@@ -2262,7 +2296,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
|
|
|
2262
2296
|
.peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
|
|
2263
2297
|
padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
|
|
2264
2298
|
.peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
|
|
2265
|
-
`,
|
|
2299
|
+
`,mc=`
|
|
2266
2300
|
const $ = (id) => document.getElementById(id);
|
|
2267
2301
|
let state = null;
|
|
2268
2302
|
|
|
@@ -5146,11 +5180,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
|
|
|
5146
5180
|
})();
|
|
5147
5181
|
|
|
5148
5182
|
refresh();
|
|
5149
|
-
`;function lo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oo({peers:a,localToken:n}))}async function co(t,e){let a=xa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function po(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Cc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await hc(t),r={"GET /api/admin/state":()=>xc(),"POST /api/admin/agents":()=>_c(n),"PATCH /api/admin/agents":()=>Sc(n),"DELETE /api/admin/agents":()=>Ec(n),"POST /api/admin/agents/access":()=>vc(n),"POST /api/admin/channels/telegram":()=>Tc(n),"DELETE /api/admin/channels/telegram":()=>Vc(n),"POST /api/admin/channels/telegram/toggle":()=>Yc(n),"POST /api/admin/crons":()=>Qc(n),"DELETE /api/admin/crons":()=>Zc(n),"POST /api/admin/config/raw":()=>ed(n),"GET /api/admin/tokens":()=>bc(),"POST /api/admin/tokens":()=>yc(n),"DELETE /api/admin/tokens":()=>wc(n),"POST /api/admin/agents/test":()=>kc(n),"POST /api/admin/agents/integrations":()=>Pc(n),"DELETE /api/admin/agents/integrations":()=>jc(n),"PATCH /api/admin/agents/integrations":()=>Oc(n),"PATCH /api/admin/channels/telegram":()=>Ac(n),"POST /api/admin/channels/slack":()=>Fc(n),"POST /api/admin/channels/slack/toggle":()=>Uc(n),"POST /api/admin/channels/discord":()=>Wc(n),"POST /api/admin/channels/discord/toggle":()=>Gc(n),"POST /api/admin/channels/gitlab":()=>Xc(n),"POST /api/admin/channels/gitlab/toggle":()=>Kc(n),"POST /api/admin/channels/request-status":()=>_r(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>md(n),"DELETE /api/admin/actions":()=>fd(n),"POST /api/admin/actions/run":()=>hd(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":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Jc(n),"POST /api/admin/webhooks":()=>Nc(n),"PATCH /api/admin/webhooks":()=>Dc(n),"DELETE /api/admin/webhooks":()=>qc(n),"POST /api/admin/whatsapp-triage":()=>to(n),"POST /api/admin/whatsapp-triage/rules":()=>ao(n),"PATCH /api/admin/whatsapp-triage/rules":()=>no(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ro(n),"POST /api/admin/mesh/peers":()=>Hc(n),"DELETE /api/admin/mesh/peers":()=>Bc(n),"POST /api/admin/mesh/toggle":()=>zc(n),"GET /api/admin/files":()=>Ic(t),"GET /api/admin/files/read":()=>Mc(t),"PUT /api/admin/files":()=>Lc(n),"POST /api/admin/files/skill":()=>Rc(n),"DELETE /api/admin/files/skill":()=>$c(n),"POST /api/admin/business/orgchart":()=>td(n),"DELETE /api/admin/business/orgchart":()=>ad(n),"POST /api/admin/business/project":()=>nd(n),"DELETE /api/admin/business/project":()=>sd(n),"POST /api/admin/business/client":()=>rd(n),"DELETE /api/admin/business/client":()=>od(n),"POST /api/admin/business/contact":()=>id(n),"DELETE /api/admin/business/contact":()=>ld(n),"POST /api/admin/boards":()=>cd(n),"DELETE /api/admin/boards":()=>dd(n),"POST /api/admin/boards/columns":()=>pd(n),"DELETE /api/admin/boards/columns":()=>ud(n),"POST /api/admin/notifications":()=>xd(n),"POST /api/admin/screen":()=>vd(n),"POST /api/admin/webhooks/triggers":()=>bd(n),"POST /api/admin/mesh/health":()=>gd(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ha(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ha(e,200,i)}catch(n){ha(e,400,{error:n.message||"admin op failed"})}}function ha(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function hc(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 gc(t){let e=ze(process.cwd(),t);if(!Nt(e))return[];let a=[];for(let n of fc(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 xa(){let t=ze(process.cwd(),"agentx.json");return Nt(t)?JSON.parse(so(t,"utf-8")):null}function xc(){let t=xa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.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(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:In(k.local),ntfy:Er(t.channels?.ntfy)},S=[];try{S=gc(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:kr(t),whatsappTriage:eo(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:ar(t.screen),actions:S}}function vc(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 bc(){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 yc(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 wc(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 kc(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 p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.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 _c(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(p=>{if(p.agents=p.agents||{},p.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)),p.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Nt(c))try{uc(i,{recursive:!0}),io(c,`# ${a}
|
|
5183
|
+
`;function uo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lo({peers:a,localToken:n}))}async function mo(t,e){let a=xa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function fo(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Mc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await xc(t),r={"GET /api/admin/state":()=>bc(),"POST /api/admin/agents":()=>Ec(n),"PATCH /api/admin/agents":()=>Tc(n),"DELETE /api/admin/agents":()=>Ac(n),"POST /api/admin/agents/access":()=>yc(n),"POST /api/admin/channels/telegram":()=>Cc(n),"DELETE /api/admin/channels/telegram":()=>Qc(n),"POST /api/admin/channels/telegram/toggle":()=>Zc(n),"POST /api/admin/crons":()=>ed(n),"DELETE /api/admin/crons":()=>td(n),"POST /api/admin/config/raw":()=>ad(n),"GET /api/admin/tokens":()=>wc(),"POST /api/admin/tokens":()=>kc(n),"DELETE /api/admin/tokens":()=>_c(n),"POST /api/admin/agents/test":()=>Sc(n),"POST /api/admin/agents/integrations":()=>Oc(n),"DELETE /api/admin/agents/integrations":()=>Nc(n),"PATCH /api/admin/agents/integrations":()=>Dc(n),"PATCH /api/admin/channels/telegram":()=>Ic(n),"POST /api/admin/channels/slack":()=>Wc(n),"POST /api/admin/channels/slack/toggle":()=>Gc(n),"POST /api/admin/channels/discord":()=>Xc(n),"POST /api/admin/channels/discord/toggle":()=>Kc(n),"POST /api/admin/channels/gitlab":()=>Jc(n),"POST /api/admin/channels/gitlab/toggle":()=>Vc(n),"POST /api/admin/channels/request-status":()=>_r(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>hd(n),"DELETE /api/admin/actions":()=>gd(n),"POST /api/admin/actions/run":()=>xd(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":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Yc(n),"POST /api/admin/webhooks":()=>Hc(n),"PATCH /api/admin/webhooks":()=>Bc(n),"DELETE /api/admin/webhooks":()=>Uc(n),"POST /api/admin/whatsapp-triage":()=>ro(n),"POST /api/admin/whatsapp-triage/rules":()=>oo(n),"PATCH /api/admin/whatsapp-triage/rules":()=>so(n),"DELETE /api/admin/whatsapp-triage/rules":()=>io(n),"POST /api/admin/mesh/peers":()=>zc(n),"DELETE /api/admin/mesh/peers":()=>qc(n),"POST /api/admin/mesh/toggle":()=>Fc(n),"GET /api/admin/files":()=>Lc(t),"GET /api/admin/files/read":()=>Rc(t),"PUT /api/admin/files":()=>$c(n),"POST /api/admin/files/skill":()=>Pc(n),"DELETE /api/admin/files/skill":()=>jc(n),"POST /api/admin/business/orgchart":()=>nd(n),"DELETE /api/admin/business/orgchart":()=>rd(n),"POST /api/admin/business/project":()=>od(n),"DELETE /api/admin/business/project":()=>ld(n),"POST /api/admin/business/client":()=>sd(n),"DELETE /api/admin/business/client":()=>id(n),"POST /api/admin/business/contact":()=>cd(n),"DELETE /api/admin/business/contact":()=>dd(n),"POST /api/admin/boards":()=>pd(n),"DELETE /api/admin/boards":()=>ud(n),"POST /api/admin/boards/columns":()=>md(n),"DELETE /api/admin/boards/columns":()=>fd(n),"POST /api/admin/notifications":()=>bd(n),"POST /api/admin/screen":()=>yd(n),"POST /api/admin/webhooks/triggers":()=>wd(n),"POST /api/admin/mesh/health":()=>vd(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ha(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ha(e,200,i)}catch(n){ha(e,400,{error:n.message||"admin op failed"})}}function ha(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function xc(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 vc(t){let e=ze(process.cwd(),t);if(!Nt(e))return[];let a=[];for(let n of gc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(co(ze(e,n.name),"utf-8")))}catch{}return a}function xa(){let t=ze(process.cwd(),"agentx.json");return Nt(t)?JSON.parse(co(t,"utf-8")):null}function bc(){let t=xa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.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(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:In(k.local),ntfy:Er(t.channels?.ntfy)},S=[];try{S=vc(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:kr(t),whatsappTriage:no(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:ar(t.screen),actions:S}}function yc(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 wc(){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 kc(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 _c(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 Sc(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 p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.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 Ec(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=go(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(p=>{if(p.agents=p.agents||{},p.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)),p.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Nt(c))try{fc(i,{recursive:!0}),po(c,`# ${a}
|
|
5150
5184
|
|
|
5151
5185
|
${s||"You are "+a+"."}
|
|
5152
|
-
`)}catch{}return{summary:l}}function Sc(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 Ec(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 Tc(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 Ac(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}=va(),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 me(t,e){let{url:a,headers:n}=va(),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 Cc(t,e){try{let{url:a,headers:n}=va(),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 va(){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=xa()?.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 ga(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Ic(t){let e=ga(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Mc(t){let e=ga(t,"agent").trim(),a=ga(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return wt(Ve(e),a)}function Lc(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=kt(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Rc(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=_t(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function $c(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=St(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Pc(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 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{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 Oc(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(p=>p.kind===a&&p.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 uo=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Nc(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(!uo.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(p=>p.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 Dc(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"&&uo.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 Hc(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 Bc(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 zc(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 qc(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 Fc(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 Uc(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 Wc(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 Gc(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 Xc(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 Kc(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 Jc(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-4RLL7YOW.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 Vc(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 Yc(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 Qc(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 Zc(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 ed(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(Nt(n))try{mc(n,r)}catch{}io(n,JSON.stringify(a,null,2)+`
|
|
5153
|
-
`,"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 td(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 ad(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 nd(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 rd(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 od(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 sd(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 id(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 ld(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 cd(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),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function dd(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 pd(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 p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function ud(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 md(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 fd(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 hd(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 gd(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 xd(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=Mn(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=Tr(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 vd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=nr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function bd(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}}lt();import{resolve as kd}from"path";function fo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5186
|
+
`)}catch{}return{summary:l}}function Tc(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=go(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 Ac(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 Cc(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 Ic(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}=va(),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 me(t,e){let{url:a,headers:n}=va(),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 Mc(t,e){try{let{url:a,headers:n}=va(),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 va(){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=xa()?.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 ga(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Lc(t){let e=ga(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Rc(t){let e=ga(t,"agent").trim(),a=ga(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return wt(Ve(e),a)}function $c(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=kt(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Pc(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=_t(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function jc(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=St(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Oc(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 Nc(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 Dc(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(p=>p.kind===a&&p.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 ho=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Hc(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(!ho.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(p=>p.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 Bc(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"&&ho.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 zc(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 qc(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 Fc(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 Uc(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 Wc(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 Gc(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 Xc(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 Kc(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 Jc(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 Vc(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 Yc(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-4RLL7YOW.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 Qc(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 Zc(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 ed(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 td(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 ad(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(Nt(n))try{hc(n,r)}catch{}po(n,JSON.stringify(a,null,2)+`
|
|
5187
|
+
`,"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 go(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function nd(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 rd(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 od(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 sd(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 id(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 ld(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 cd(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 dd(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 pd(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),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function ud(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 md(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 p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function fd(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 hd(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 gd(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 xd(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 vd(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 bd(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=Mn(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=Tr(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 yd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=nr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function wd(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}}lt();import{resolve as Sd}from"path";function xo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
|
|
5154
5188
|
|
|
5155
5189
|
<div id="disabled-banner" class="banner warn" style="display:none">
|
|
5156
5190
|
<b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
|
|
@@ -5205,7 +5239,7 @@ ${s||"You are "+a+"."}
|
|
|
5205
5239
|
<h2>Recent classifications</h2>
|
|
5206
5240
|
<p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
|
|
5207
5241
|
<div id="recent"></div>
|
|
5208
|
-
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5242
|
+
</section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:kd,scripts:`${e}<script>${_d}</script>`})}var kd=`
|
|
5209
5243
|
main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
|
|
5210
5244
|
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
|
|
5211
5245
|
.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
|
|
@@ -5309,7 +5343,7 @@ details {
|
|
|
5309
5343
|
border-radius: 4px; padding: 8px 12px; margin-top: 8px;
|
|
5310
5344
|
}
|
|
5311
5345
|
details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
|
|
5312
|
-
details[open] summary { margin-bottom: 8px; }`,
|
|
5346
|
+
details[open] summary { margin-bottom: 8px; }`,_d=`
|
|
5313
5347
|
const $ = (id) => document.getElementById(id);
|
|
5314
5348
|
const state = { schema: null, nodes: [], pending: [], recent: [] };
|
|
5315
5349
|
|
|
@@ -5529,7 +5563,7 @@ $('btn-save-schema').addEventListener('click', async () => {
|
|
|
5529
5563
|
$('btn-reload-schema').addEventListener('click', refresh);
|
|
5530
5564
|
|
|
5531
5565
|
refresh();
|
|
5532
|
-
`;function
|
|
5566
|
+
`;function bo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xo({peers:a,localToken:n}))}async function yo(t,e,a){try{let n=t.method==="GET"?void 0:await $d(t),r=Ed(),o={"GET /api/admin/graph/state":()=>Td(r),"POST /api/admin/graph/classifications/approve":()=>Ad(r,n),"POST /api/admin/graph/classifications/reject":()=>Cd(r,n),"POST /api/admin/graph/nodes":()=>Id(r,n),"PATCH /api/admin/graph/nodes":()=>Md(r,n),"DELETE /api/admin/graph/nodes":()=>Ld(r,n),"PUT /api/admin/graph/schema":()=>Rd(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){ba(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();ba(e,200,l)}catch(n){ba(e,400,{error:n?.message||"graph op failed"})}}function Ed(){let t=X(),e=Sd(process.cwd(),t.graph.baseDir);return new gn({baseDir:e})}function Td(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 Ad(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wo(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=ya(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Cd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function wo(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 Id(t,e){let a=vo(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?vo(String(e.parentId)):null,o=ya({[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 Md(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=ya({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ld(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Rd(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 ya(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 vo(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function ba(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $d(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 ko=`
|
|
5533
5567
|
<section class="apv__req" id="req-section" aria-labelledby="req-h">
|
|
5534
5568
|
<h2 id="req-h">Open requests <span id="req-n"></span></h2>
|
|
5535
5569
|
<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>
|
|
@@ -5546,7 +5580,7 @@ refresh();
|
|
|
5546
5580
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5547
5581
|
</form>
|
|
5548
5582
|
</details>
|
|
5549
|
-
</section>`,
|
|
5583
|
+
</section>`,_o=`
|
|
5550
5584
|
.apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
|
|
5551
5585
|
.apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
|
|
5552
5586
|
.apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
|
|
@@ -5568,7 +5602,7 @@ refresh();
|
|
|
5568
5602
|
.apv__req select { min-height: 40px; max-width: 100%; }
|
|
5569
5603
|
.apv__mic.is-on { border-color: var(--ax-err); color: var(--ax-err); }
|
|
5570
5604
|
.apv__acts + .apv__acts { margin-top: 8px; }
|
|
5571
|
-
`,
|
|
5605
|
+
`,So=`
|
|
5572
5606
|
(function(){
|
|
5573
5607
|
var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
|
|
5574
5608
|
function $(id){ return document.getElementById(id); }
|
|
@@ -5710,7 +5744,7 @@ function busy(){
|
|
|
5710
5744
|
}
|
|
5711
5745
|
setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
|
|
5712
5746
|
})();
|
|
5713
|
-
`;function
|
|
5747
|
+
`;function Eo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
|
|
5714
5748
|
<header class="apv__head">
|
|
5715
5749
|
<div>
|
|
5716
5750
|
<h1>Approvals</h1>
|
|
@@ -5732,7 +5766,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
|
|
|
5732
5766
|
<ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
|
|
5733
5767
|
<p id="apv-snoozed" class="apv__foot"></p>
|
|
5734
5768
|
|
|
5735
|
-
${
|
|
5769
|
+
${ko}
|
|
5736
5770
|
|
|
5737
5771
|
<details class="apv__settings" id="apv-settings">
|
|
5738
5772
|
<summary>Settings: expiry, later, daily digest</summary>
|
|
@@ -5747,7 +5781,7 @@ ${bo}
|
|
|
5747
5781
|
<div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
|
|
5748
5782
|
</form>
|
|
5749
5783
|
</details>
|
|
5750
|
-
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
5784
|
+
</div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Pd+_o,scripts:`${e}<script>${jd}</script><script>${So}</script>`})}var Pd=`
|
|
5751
5785
|
.apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
|
|
5752
5786
|
.apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
|
|
5753
5787
|
.apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
@@ -5796,7 +5830,7 @@ ${bo}
|
|
|
5796
5830
|
@media (max-width: 560px) {
|
|
5797
5831
|
.apv__acts .ax-btn { flex: 1 1 0; }
|
|
5798
5832
|
}
|
|
5799
|
-
|
|
5833
|
+
`,jd=`
|
|
5800
5834
|
(function(){
|
|
5801
5835
|
var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
|
|
5802
5836
|
var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
|
|
@@ -5964,7 +5998,7 @@ $('apv-form').addEventListener('submit', async function(ev){
|
|
|
5964
5998
|
load();
|
|
5965
5999
|
setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
|
|
5966
6000
|
})();
|
|
5967
|
-
`;import{existsSync as
|
|
6001
|
+
`;import{existsSync as Od,readFileSync as Nd}from"fs";var Ae="/api/admin/approvals/requests";function To(t){let e=kn(t);if(!Od(e))return[];try{let a=JSON.parse(Nd(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 Ao=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Co(t,e,a,n){try{return await Dd(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Dd(t,e,a,n){if(t==="GET"&&e===Ae){let o=gt(n);return{status:200,body:{items:o?o.listOpen().map(s=>Dn(s,o)):[],agents:To(n.configPath),settings:ht(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=gt(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",u=To(n.configPath).find(h=>h.id===p);if(r==="handoff"&&!u)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!ht(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,p,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let f=u?.name??p;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${f} will go on with ${o}`:`${f} 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=gt(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=Ao(a.from),o.channels=Ao(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await Pn(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:ht(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var Hd=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Dt(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 Io(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Eo({peers:e,localToken:a}))}async function Mo(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 Co(o,a,o==="POST"?await Dt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=xt(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 Dt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Hd.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await vt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.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 Dt(t),l=Hn(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 Dt(t),l={},c=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};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 f=fr(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await hr(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(te(e,400,{error:p.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}hn();function Lo(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."})+`
|
|
5968
6002
|
<div class="pp">
|
|
5969
6003
|
<div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
|
|
5970
6004
|
<section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
|
|
@@ -5977,7 +6011,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
5977
6011
|
</ol>
|
|
5978
6012
|
</section>
|
|
5979
6013
|
<ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
|
|
5980
|
-
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:
|
|
6014
|
+
</div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Bd,scripts:`${e}<script>${zd}</script>`})}var Bd=`
|
|
5981
6015
|
.pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
|
|
5982
6016
|
.pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
|
|
5983
6017
|
.pp-msg.is-bad { color: var(--ax-red-ink); }
|
|
@@ -6018,7 +6052,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6018
6052
|
.pp-text { overflow-wrap: anywhere; }
|
|
6019
6053
|
.pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
|
|
6020
6054
|
@media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
|
|
6021
|
-
`,
|
|
6055
|
+
`,zd=`
|
|
6022
6056
|
(function () {
|
|
6023
6057
|
var list = document.getElementById('pp-list');
|
|
6024
6058
|
var msg = document.getElementById('pp-msg');
|
|
@@ -6156,7 +6190,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6156
6190
|
load();
|
|
6157
6191
|
setInterval(load, 30000);
|
|
6158
6192
|
})();
|
|
6159
|
-
`;var wa="/api/admin/people";function
|
|
6193
|
+
`;var wa="/api/admin/people";function qd(t,e){let a=br(t,e);return a?{...e,answer:a}:e}function Fd(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function Ud(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&Fd(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:pn,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Wd=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ro(t,e,a,n){if(a!=="/people"&&a!==wa&&!a.startsWith(`${wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if((t.url||"").split(/[?#]/)[0]!==a)return pe(e,404,{error:"not found"}),!0;if(a==="/people")return r!=="GET"?(pe(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Lo({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return pe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(p=>qd(n.root,p)),s=()=>Ud(n.people(),o());if(r==="GET"&&a===wa){let c=s();return pe(e,200,{people:c,paired:c.reduce((p,u)=>p+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 pe(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),u=[],f=[];try{p&&(u=gr(p,c.id))}catch{}try{p&&(f=It(p,c.id,20))}catch{}return pe(e,200,{person:c,devices:o(c.id).sort(Wd),requests:u,runs:f,database:!!p}),!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,p]=l,u=n.members.byToken(p);if(!u||u.personId!==c)return pe(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return pe(e,409,{error:"this machine's access has already ended"}),!0;let f=wr({tokens:n.tokens??new F,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return pe(e,200,{ok:!0,device:f}),!0}return pe(e,404,{error:"not found"}),!0}import{resolve as Vd}from"path";import{existsSync as Yd}from"fs";import Qd from"better-sqlite3";var $o=new WeakSet;function Gd(t,e,a={}){if($o.has(t))return;$o.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]=(...p)=>{let u=r();try{return c(...p)}finally{let f=r()-u;f>=n&&e({sql:s,ms:f})}}}return i}}function Xd(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){Gd(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Xd(a)}`))}function Po(t={}){let e=`<div class="ax-obs">
|
|
6160
6194
|
<header class="ax-obs__head">
|
|
6161
6195
|
<h1>Health</h1>
|
|
6162
6196
|
<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>
|
|
@@ -6278,7 +6312,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6278
6312
|
</div>
|
|
6279
6313
|
<div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
|
|
6280
6314
|
</section>
|
|
6281
|
-
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
6315
|
+
</div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Kd,scripts:`<script>${Jd}</script>`})}var Kd=`
|
|
6282
6316
|
.ax-obs { padding: 16px 24px; }
|
|
6283
6317
|
.ax-obs__head { margin-bottom: 16px; }
|
|
6284
6318
|
.ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
|
|
@@ -6395,7 +6429,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6395
6429
|
.ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
|
|
6396
6430
|
.ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
|
|
6397
6431
|
.ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
|
|
6398
|
-
`,
|
|
6432
|
+
`,Jd=`
|
|
6399
6433
|
(function(){
|
|
6400
6434
|
var panes = document.querySelectorAll('.ax-obs__pane');
|
|
6401
6435
|
var tabs = document.querySelectorAll('.ax-obs__tab');
|
|
@@ -6779,7 +6813,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6779
6813
|
|
|
6780
6814
|
load(current);
|
|
6781
6815
|
})();
|
|
6782
|
-
`;var
|
|
6816
|
+
`;var No={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 Do(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function ka(t){let e=No[Do(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 Zd(){let t=Vd(process.cwd(),".agentx/db.sqlite");if(!Yd(t))return null;try{let e=new Qd(t,{readonly:!0,fileMustExist:!0});return ye(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Ho(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Po({peers:a}))}function ep(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 Bo(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Zd();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ep(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
|
|
6783
6817
|
SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
|
|
6784
6818
|
FROM route_traces
|
|
6785
6819
|
${i.length?"WHERE "+i.join(" AND "):""}
|
|
@@ -6794,8 +6828,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6794
6828
|
FROM task_history
|
|
6795
6829
|
WHERE ${i.join(" AND ")}
|
|
6796
6830
|
ORDER BY started_at DESC LIMIT @limit
|
|
6797
|
-
`,u=r.db.prepare(c).all(l).map(f=>({...f,plain:
|
|
6798
|
-
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function
|
|
6831
|
+
`,u=r.db.prepare(c).all(l).map(f=>({...f,plain:zo(f.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,tp(r.db)),!0;if(n==="activity")return fe(e,200,ap(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,Oo(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=jo(i.searchParams.get("range")),c=Oo(r.db,l),p=np(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(p),!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 zo(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(`
|
|
6832
|
+
`)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function tp(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,p=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=y=>p.length?p[Math.min(p.length-1,Math.floor(p.length*y))].duration_ms:0,f=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((y,I)=>y+ka(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((y,I)=>y+ka(I),0),g=t.prepare(`
|
|
6799
6833
|
SELECT agent_id,
|
|
6800
6834
|
COUNT(*) AS tasks,
|
|
6801
6835
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
|
|
@@ -6818,7 +6852,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6818
6852
|
FROM task_history
|
|
6819
6853
|
WHERE status='error' AND started_at >= ?
|
|
6820
6854
|
ORDER BY started_at DESC LIMIT 5
|
|
6821
|
-
`).all(o).map(y=>({...y,plain:
|
|
6855
|
+
`).all(o).map(y=>({...y,plain:zo(y.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:T}}function ap(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(`
|
|
6822
6856
|
SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
|
|
6823
6857
|
COUNT(*) AS tasks,
|
|
6824
6858
|
SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
|
|
@@ -6845,7 +6879,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6845
6879
|
WHERE started_at >= @since
|
|
6846
6880
|
GROUP BY agent_id
|
|
6847
6881
|
ORDER BY tasks_24h DESC, tasks_7d DESC
|
|
6848
|
-
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function
|
|
6882
|
+
`).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function jo(t){if(!t)return 30;if(t==="all"||t==="0")return 0;let e=parseInt(t,10);return!Number.isFinite(e)||e<=0?30:Math.min(e,365)}function Oo(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
|
|
6849
6883
|
SELECT day, agent_id, model,
|
|
6850
6884
|
input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
|
|
6851
6885
|
tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
|
|
@@ -6853,10 +6887,10 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6853
6887
|
FROM usage_daily
|
|
6854
6888
|
${a}
|
|
6855
6889
|
ORDER BY day
|
|
6856
|
-
`).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,p=0,u=0,f=0,h=0,k=0,_=0,S=0,g={},d={};for(let E of n){let $=ka(E),L=
|
|
6890
|
+
`).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,p=0,u=0,f=0,h=0,k=0,_=0,S=0,g={},d={};for(let E of n){let $=ka(E),L=Do(E.model),j=No[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&&(p+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,_+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(f+=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=d[E.agent_id]||(d[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 m=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,v=0,w=0,T=0,y=0,I=0;for(let E of m)x+=E.tasks,v+=E.input,w+=E.output,T+=E.cacheRead,y+=E.cacheCreate,I+=E.cost;let C=Object.entries(d).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:p,spend30d:u,tier2Today:f,tier2_7d:h,tier2PctToday:l>0?f/l:0,spendRange:I,avgDailyRange:m.length?I/m.length:0,tasksRange:x,tokensRange:v+w+T+y,cacheHitRange:T+v>0?T/(T+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(k-_)/_:0},days:m,perAgent:C}}function np(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+`
|
|
6857
6891
|
`+a.join(`
|
|
6858
6892
|
`)+`
|
|
6859
|
-
`}import{resolve as
|
|
6893
|
+
`}import{resolve as rp}from"path";import{existsSync as op}from"fs";import sp from"better-sqlite3";function ip(){let t=rp(process.cwd(),".agentx/intent/ledger.sqlite");if(!op(t))return null;try{let e=new sp(t,{readonly:!0,fileMustExist:!0});return ye(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-qo>6e4&&(qo=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var qo=0;function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function lp(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 Fo(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ip();if(!r)return Ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=lp(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=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 ${f}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} 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}),d=r.db.prepare(`
|
|
6860
6894
|
SELECT COUNT(*) AS n FROM intent_decisions d
|
|
6861
6895
|
LEFT JOIN intent_resolutions r
|
|
6862
6896
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
@@ -6883,7 +6917,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
6883
6917
|
ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
|
|
6884
6918
|
WHERE ${u.join(" AND ")}
|
|
6885
6919
|
ORDER BY d.decided_at DESC LIMIT @limit
|
|
6886
|
-
`;return Ce(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function
|
|
6920
|
+
`;return Ce(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Uo(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
|
|
6887
6921
|
<header class="ax-led__head">
|
|
6888
6922
|
<h1>Intent ledger</h1>
|
|
6889
6923
|
<p class="ax-led__sub">Read-only view over <code>.agentx/intent/ledger.sqlite</code> \u2014 same source as <code>agentx ledger</code>. Replay and lineage live in the CLI for now.</p>
|
|
@@ -7088,7 +7122,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7088
7122
|
}
|
|
7089
7123
|
load();
|
|
7090
7124
|
})();
|
|
7091
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7125
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Wo(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
|
|
7092
7126
|
<header class="ax-cost__head">
|
|
7093
7127
|
<div>
|
|
7094
7128
|
<h1>Cost</h1>
|
|
@@ -7661,7 +7695,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7661
7695
|
load();
|
|
7662
7696
|
setInterval(load, 30000);
|
|
7663
7697
|
})();
|
|
7664
|
-
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function
|
|
7698
|
+
</script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Go(t={}){let e=`<div class="ax-pj__root">
|
|
7665
7699
|
<aside class="ax-pj__list">
|
|
7666
7700
|
<header>
|
|
7667
7701
|
<h2>Projects</h2>
|
|
@@ -7688,7 +7722,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7688
7722
|
</header>
|
|
7689
7723
|
<div id="pj-detail-body" class="ax-pj__detail-body"></div>
|
|
7690
7724
|
</section>
|
|
7691
|
-
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
7725
|
+
</div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:cp,scripts:`<script>${dp}</script>`})}var cp=`
|
|
7692
7726
|
.ax-pj__root {
|
|
7693
7727
|
display: grid;
|
|
7694
7728
|
grid-template-columns: 360px 1fr;
|
|
@@ -7875,7 +7909,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
7875
7909
|
}
|
|
7876
7910
|
.ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
|
|
7877
7911
|
.ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
|
|
7878
|
-
`,
|
|
7912
|
+
`,dp=`
|
|
7879
7913
|
(function(){
|
|
7880
7914
|
const $ = (sel) => document.querySelector(sel);
|
|
7881
7915
|
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&","<":"<",">":">","\\"":"""}[c]));
|
|
@@ -8525,9 +8559,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
|
|
|
8525
8559
|
load();
|
|
8526
8560
|
});
|
|
8527
8561
|
})();
|
|
8528
|
-
`;import{resolve as Aa,join as Sp}from"path";import{existsSync as Ca,readdirSync as Ep,readFileSync as Tp}from"fs";import Ap from"better-sqlite3";var Wo=String.raw`[\w.-]+(?:/[\w.-]+)+`,cp=new RegExp(`^(?:chat:)?(${Wo}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),dp=new RegExp(`^\\[(?:GitLab|GitHub) (${Wo}) `);function Uo(t){if(!t)return null;let e=t.match(cp);return e?e[1]:null}function _a(t){if(!t)return null;let e=t.trimStart().match(dp);return e?e[1]:null}function Ht(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Uo(typeof n?.chatId=="string"?n.chatId:null)??Uo(e)??_a(a)}function pp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var up=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,mp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,fp=t=>/^issue/i.test(t)?"issue":"mr";function hp(t){let e=t.subject.match(up)??t.inputPreview.trimStart().match(mp);return e?{kind:fp(e[1]),n:Number(e[2])}:null}function gp(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 Go(t){if(!pp(t.projectId))return[];let e=hp(t);return e?[e]:gp(t.inputPreview)}var xp=6e4,vp=5*6e4,bp=40,Xo=6,Ko=new Map;function Jo(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 Go(n)){let s=Bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=bp)return[...e.values()]}}return[...e.values()]}async function Vo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Bt(s.project,s.ref),l=Ko.get(i);l&&n-l.at<(s.github?vp:xp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Xo)await Promise.all(o.slice(s,s+Xo).map(async i=>{let l=Bt(i.project,i.ref),c=null;try{c=i.github?await wp(i,e,a):await yp(i,e,a)}catch{}Ko.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Yo(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 yp(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 Yo(`${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 wp(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 Yo(`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}ln();var Sa=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Qo(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=Sa(o.from,80);if(s){a.callback={from:s,status:Sa(o.status,20)??"done"};let i=Sa(o.peer,80);i&&(a.callback.peer=i)}}return a}ln();hn();var Zo={kind:"agentx",id:"agentx",name:"AgentX"},Ea={kind:"person",id:"unknown",name:"Unknown"},kp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),es=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 _p(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 ts(t){let e=s=>({kind:"person",id:`person:${s}`,name:un(t.people,s)}),a=(s,i)=>i||kp.has(s)?Zo:{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)??fn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(sn(s)==="human")return es(s?.senderUsername)?a(c,!1):Ea;let p=!!Ie(n.senderAgentId)||ta(l?l.sender:s?.sender);return c==="desktop"&&!p?Ea:a(c,p)}let r=_p(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=mn(t.people,t.channel,r);return o?e(o.id):ta(r.name)?Zo:on.has(t.channel)&&!es(r.username)?Ea:a(t.channel,!1)}function Ia(){let t=Aa(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ca(t))return null;try{let e=new Ap(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-as>6e4&&(as=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var as=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 Cp(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 os(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 Ip(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 ss(t,e,a){return An(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 Mp(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&&!Ta(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ta(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Rp(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&&!Ta(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=ns(p);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:ns(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 Lp={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Rp(t,e){let a=Lp[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ns(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ta(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 is(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}
|
|
8562
|
+
`;import{resolve as Aa,join as Tp}from"path";import{existsSync as Ca,readdirSync as Ap,readFileSync as Cp}from"fs";import Ip from"better-sqlite3";var Ko=String.raw`[\w.-]+(?:/[\w.-]+)+`,pp=new RegExp(`^(?:chat:)?(${Ko}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),up=new RegExp(`^\\[(?:GitLab|GitHub) (${Ko}) `);function Xo(t){if(!t)return null;let e=t.match(pp);return e?e[1]:null}function _a(t){if(!t)return null;let e=t.trimStart().match(up);return e?e[1]:null}function Ht(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Xo(typeof n?.chatId=="string"?n.chatId:null)??Xo(e)??_a(a)}function mp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var fp=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,hp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,gp=t=>/^issue/i.test(t)?"issue":"mr";function xp(t){let e=t.subject.match(fp)??t.inputPreview.trimStart().match(hp);return e?{kind:gp(e[1]),n:Number(e[2])}:null}function vp(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 Jo(t){if(!mp(t.projectId))return[];let e=xp(t);return e?[e]:vp(t.inputPreview)}var bp=6e4,yp=5*6e4,wp=40,Vo=6,Yo=new Map;function Qo(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 Jo(n)){let s=Bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=wp)return[...e.values()]}}return[...e.values()]}async function Zo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Bt(s.project,s.ref),l=Yo.get(i);l&&n-l.at<(s.github?yp:bp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Vo)await Promise.all(o.slice(s,s+Vo).map(async i=>{let l=Bt(i.project,i.ref),c=null;try{c=i.github?await _p(i,e,a):await kp(i,e,a)}catch{}Yo.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function es(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 kp(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 es(`${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 _p(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 es(`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}ln();var Sa=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function ts(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=Sa(o.from,80);if(s){a.callback={from:s,status:Sa(o.status,20)??"done"};let i=Sa(o.peer,80);i&&(a.callback.peer=i)}}return a}ln();hn();var as={kind:"agentx",id:"agentx",name:"AgentX"},Ea={kind:"person",id:"unknown",name:"Unknown"},Sp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),ns=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 Ep(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 rs(t){let e=s=>({kind:"person",id:`person:${s}`,name:un(t.people,s)}),a=(s,i)=>i||Sp.has(s)?as:{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)??fn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(sn(s)==="human")return ns(s?.senderUsername)?a(c,!1):Ea;let p=!!Ie(n.senderAgentId)||ta(l?l.sender:s?.sender);return c==="desktop"&&!p?Ea:a(c,p)}let r=Ep(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=mn(t.people,t.channel,r);return o?e(o.id):ta(r.name)?as:on.has(t.channel)&&!ns(r.username)?Ea:a(t.channel,!1)}function Ia(){let t=Aa(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ca(t))return null;try{let e=new Ip(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-os>6e4&&(os=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var os=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 Mp(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 ls(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 Lp(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 cs(t,e,a){return An(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 Rp(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&&!Ta(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ta(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Pp(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&&!Ta(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=ss(p);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:ss(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 $p={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Pp(t,e){let a=$p[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ss(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ta(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 ds(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}
|
|
8529
8563
|
${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
|
|
8530
|
-
${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
|
|
8564
|
+
${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 jp(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 ps(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
|
|
8531
8565
|
SELECT id, ts, source, project, subject, intent, raw_json
|
|
8532
8566
|
FROM intent_events WHERE ts >= ? ORDER BY ts ASC
|
|
8533
8567
|
`).all(r),s=new Map,i=new Map;if(o.length>0){let y=o.map(L=>L.id),I=y.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(y.map((L,j)=>[`id${j}`,L])),E=t.prepare(`
|
|
@@ -8536,9 +8570,9 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
|
|
|
8536
8570
|
`).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(`
|
|
8537
8571
|
SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
|
|
8538
8572
|
FROM intent_resolutions WHERE decision_event_id IN (${I})
|
|
8539
|
-
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=sa(e?.business??{}),S=e?.people??[];for(let y of o){let I=null;try{I=JSON.parse(y.raw_json)}catch{}let C=
|
|
8573
|
+
`).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=sa(e?.business??{}),S=e?.people??[];for(let y of o){let I=null;try{I=JSON.parse(y.raw_json)}catch{}let C=cs(y.source,I,k),E=ds(y.source,I),$=ts(I),L=y.project??Ht(I,y.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=ut(L,h),W=L);let q=Mp(y.source,y.intent||"",I),G=Me[q]||{label:q,color:"#6b7280"};p.has(q)||p.set(q,{id:q,label:G.label,color:G.color});let ie=rs({source:y.source,channel:q,raw:I,people:S,channelLabel:O=>Me[O]?.label??O}),Oe="__system",Z,B=Rp(y.source,y.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(y.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let wl=`${y.id}|${O.decided_by}`,rt=i.get(wl),tn=O.decided_at,an=rt?.resolved_at??null,Zt=an===null,kl=rt?.duration_ms??(Zt?n-tn:0),_l=Zt?"active":rt?.status==="error"||rt?.status==="fail"?"error":"completed",ee,Ge;if(j)ee=j,Ge=W;else{let ea=_.get(O.agent_id);ea?(ee=ea,Ge=`${ea}/_${y.source}`):(ee="unmapped",Ge=`unmapped/_${y.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:ls(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ge),f.push({id:`${y.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ge,channelId:q,initiatorId:Oe,initiatorKind:Z,subject:jp(y.subject),intent:y.intent||"",startedAt:tn,resolvedAt:an,duration:kl,active:Zt,outcome:_l,tokens:0,inputPreview:E,system:Lp(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(y=>({...y,projects:[...c.get(y.id)||[]].sort()})).sort((y,I)=>y.id.localeCompare(I.id)),d=[],m=new Set;if(e){let y=e.business??{},I=C=>{let E=y.orgChart?.[C]?.role,$=E?y.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)};d.push($),m.add(C)}}for(let y of f)m.has(y.agentId)||(d.push({id:y.agentId,name:y.agentId,tier:"worker",model:"",role:""}),m.add(y.agentId));d.sort((y,I)=>y.id.localeCompare(I.id));let x=[],v=new Set;for(let[y,I]of Object.entries(Me))x.push({id:y,label:I.label,color:I.color}),v.add(y);for(let y of p.values())v.has(y.id)||x.push(y);let w=[...u.values()];w.find(y=>y.id==="__system")||w.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:d,channels:x,initiators:w,dispatches:f,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function Ma(t){let e=Ia();if(!e)return null;try{return ps(e.db,ms(),t)}finally{e.close()}}function us(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:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:h})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=Op(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:ls(f.clientId),projects:[]}),f.projectId!==u.projectId){let h=e.get(f.clientId);h.projects.includes(f.projectId)||e.set(f.clientId,{...h,projects:[...h.projects,f.projectId].sort()})}o.push({...f,nodeId:c,id:`${c}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function Op(t){if(t.clientId!=="unmapped")return t;let e=_a(t.inputPreview);if(!e)return t;let a=ge?.business?.projects??[];return{...t,projectId:e,clientId:ut(e,a)}}async function zt(t){let e=ge?.channels?.gitlab,a=await Zo(Qo(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 ms(){return ge&&{...ge,people:Ke(ge.people)}}function fs(t){ge=t}async function hs(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ia();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=gs(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await zt(ps(n.db,ms(),o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Np=5e3;async function La(t,e,a,n=Ma){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
|
|
8540
8574
|
|
|
8541
|
-
`);let r=new URL(t.url||"/","http://_"),o=
|
|
8575
|
+
`);let r=new URL(t.url||"/","http://_"),o=gs(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
|
|
8542
8576
|
|
|
8543
8577
|
`)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await zt(p);if(s)break;u?(e.write(`event: snapshot
|
|
8544
8578
|
`),e.write(`data: ${JSON.stringify(u)}
|
|
@@ -8549,7 +8583,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
|
|
|
8549
8583
|
`)}catch(p){e.write(`event: error
|
|
8550
8584
|
data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
8551
8585
|
|
|
8552
|
-
`)}let c=Date.now();for(;!s&&Date.now()-c<
|
|
8586
|
+
`)}let c=Date.now();for(;!s&&Date.now()-c<Np;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function gs(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Dp(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Aa(process.cwd(),".agentx/task-history",t,n);if(!Ca(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Aa(process.cwd(),".agentx/task-history",t,o);return Ca(s)?is(s,e,a):null}return is(r,e,a)}function is(t,e,a){let n=null,r=1/0;for(let o of Ap(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Cp(Tp(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function xs(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=Ia();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 p=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(!p)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),f=null;try{f=JSON.parse(c.raw_json)}catch{}let h=ds(c.source,f),k=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let w=Dp(p.agent_id,p.decided_at);if(w){typeof w.responseText=="string"&&(_=w.responseText);let T=w.transcript;Array.isArray(T)&&(S=T.length)}}let g=ge?.business?.projects??[],d=ge?.business?.contactMap??[],m=sa(ge?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=cs(c.source,f,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||Ht(f,c.subject,h)){let w=c.project||Ht(f,c.subject,h);x={client:ut(w,g),project:w,via:c.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(p.agent_id){let w=m.get(p.agent_id);w&&(x={client:w,project:`${w}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${w})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:_,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 qp,readFileSync as Fp}from"fs";import{resolve as bs}from"path";lt();function vs(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=Hp.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:Bp,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>${zp}</script>`})}var Hp=`
|
|
8553
8587
|
<!-- Breadcrumb -->
|
|
8554
8588
|
<div class="ax-crumb">
|
|
8555
8589
|
<a href="/admin">Settings</a>
|
|
@@ -9138,7 +9172,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
|
|
|
9138
9172
|
</div>
|
|
9139
9173
|
</div>
|
|
9140
9174
|
</div>
|
|
9141
|
-
`,
|
|
9175
|
+
`,Bp=`
|
|
9142
9176
|
/* Agent-specific layout + legacy styles for bits the migration left in
|
|
9143
9177
|
* place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
|
|
9144
9178
|
* primitives live in components.css.ts. */
|
|
@@ -9257,7 +9291,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
|
|
|
9257
9291
|
|
|
9258
9292
|
/* Agent-specific button variant used in rail context (no ax-btn wrapper) */
|
|
9259
9293
|
.ax-btn.lg { padding: 9px 16px; font-size: 13px; }
|
|
9260
|
-
`,
|
|
9294
|
+
`,zp=`
|
|
9261
9295
|
const $ = (id) => document.getElementById(id);
|
|
9262
9296
|
const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
|
|
9263
9297
|
|
|
@@ -10113,15 +10147,15 @@ document.addEventListener('keydown', (e) => {
|
|
|
10113
10147
|
/* ===== Boot ===== */
|
|
10114
10148
|
initOptsToggles();
|
|
10115
10149
|
loadAgent();
|
|
10116
|
-
`;function
|
|
10117
|
-
`);return
|
|
10118
|
-
`);return
|
|
10150
|
+
`;function ys(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vs({agentId:a,peers:n,localToken:r}))}async function ws(t,e,a){try{let n=t.method==="GET"?void 0:await pu(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){qt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Ye(i),"PATCH ":()=>Up(i,n),"PATCH capability":()=>Xp(i,n),"POST mcp":()=>Wp(i,n),"DELETE mcp":()=>Gp(i,n),"GET identity":()=>Kp(i),"GET identity/file":()=>Jp(i,String(o.path||"")),"PUT identity/file":()=>Vp(i,n),"GET skills":()=>Yp(i),"POST skills":()=>Qp(i,n),"DELETE skills":()=>Zp(i,n),"GET skills/tree":()=>eu(i,String(o.slug||"")),"GET skills/file":()=>tu(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>au(i,n),"GET skills/deps":()=>nu(i,String(o.slug||"")),"POST skills/install":()=>ru(i,n,t),"POST skills/deps":()=>ou(i,n,t),"GET channels":()=>su(i),"GET activity":()=>iu(i,t),"GET handovers":()=>lu(i),"POST handovers":()=>cu(i,n),"DELETE handovers":()=>du(n)}[c];if(!u){qt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();qt(e,200,f)}catch(n){qt(e,400,{error:n?.message||"agent op failed"})}}function ks(){let t=bs(process.cwd(),"agentx.json");return qp(t)?JSON.parse(Fp(t,"utf-8")):null}function V(t){let e=ks();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 Up(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 Wp(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 Gp(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 Xp(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 Kp(t){let{def:e}=V(t);return De(e.workspace)}function Jp(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return wt(a.workspace,e)}function Vp(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return kt(n.workspace,a,String(e?.content??""))}function Yp(t){let{def:e}=V(t),a=De(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Qp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return _t(n.workspace,a,{title:e?.title,content:e?.content})}function Zp(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)}function eu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Zn(a.workspace,e),r=Et(a.workspace,e);return{slug:e,tree:n,deps:r}}function tu(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return er(n.workspace,e,a)}function au(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 tr(r.workspace,a,n,String(e?.content??""))}function nu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Et(a.workspace,e)}async function ru(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=_s(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(`
|
|
10151
|
+
`);return Ss(a,r,s,`install-${n}:${Date.now()}`)}async function ou(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=_s(e?.worker),{def:o}=V(t),s=Et(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=bs(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(`
|
|
10152
|
+
`);return Ss(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function _s(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 Ss(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(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function su(t){let e=ks(),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 iu(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 Ra(){return new xn}function lu(t){let e=Ra(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function cu(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=Ra().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 du(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:Ra().remove(e,a,n)?"Released":"No active handover for that chat"}}function qt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function pu(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 Es=[{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 $a(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
|
|
10119
10153
|
<span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
|
|
10120
10154
|
<span id="conn-label">live</span>`,n=`<div class="ax-app-live">
|
|
10121
10155
|
<section id="statstrip" class="ax-statstrip"></section>
|
|
10122
10156
|
<main id="grid" class="ax-live__body"></main>
|
|
10123
10157
|
</div>
|
|
10124
|
-
`;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:
|
|
10158
|
+
`;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:uu,scripts:e+`<script>${mu}</script>`,headExtras:`<script>
|
|
10125
10159
|
// rightExtras for the topbar are injected at runtime \u2014 they reference
|
|
10126
10160
|
// IDs (#ts, #conn-dot) that the script below addresses directly.
|
|
10127
10161
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -10132,7 +10166,7 @@ loadAgent();
|
|
|
10132
10166
|
extras.innerHTML = ${JSON.stringify(a)};
|
|
10133
10167
|
right.insertBefore(extras, right.firstChild);
|
|
10134
10168
|
});
|
|
10135
|
-
</script>`})}var
|
|
10169
|
+
</script>`})}var uu=`
|
|
10136
10170
|
/* --- Page frame --- */
|
|
10137
10171
|
.ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
|
|
10138
10172
|
|
|
@@ -10339,7 +10373,7 @@ loadAgent();
|
|
|
10339
10373
|
border-top-color: var(--ax-accent); border-radius: 50%;
|
|
10340
10374
|
animation: ax-spin 800ms linear infinite; display: inline-block;
|
|
10341
10375
|
}
|
|
10342
|
-
@keyframes ax-spin { to { transform: rotate(360deg); } }`,
|
|
10376
|
+
@keyframes ax-spin { to { transform: rotate(360deg); } }`,mu=`
|
|
10343
10377
|
'use strict';
|
|
10344
10378
|
|
|
10345
10379
|
const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
|
|
@@ -10910,7 +10944,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
10910
10944
|
});
|
|
10911
10945
|
}
|
|
10912
10946
|
|
|
10913
|
-
`;var
|
|
10947
|
+
`;var Ts=`
|
|
10914
10948
|
.mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
|
|
10915
10949
|
.mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
|
|
10916
10950
|
.mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
|
|
@@ -11084,7 +11118,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
|
|
|
11084
11118
|
.mx-summary{max-width:56vw}
|
|
11085
11119
|
}
|
|
11086
11120
|
@media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
|
|
11087
|
-
`;var
|
|
11121
|
+
`;var As=`<script>
|
|
11088
11122
|
window.MX=(function(){
|
|
11089
11123
|
var ENT={'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
11090
11124
|
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
|
|
@@ -11193,7 +11227,7 @@ window.MX=(function(){
|
|
|
11193
11227
|
verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
|
|
11194
11228
|
setHealth:setHealth,get:get};
|
|
11195
11229
|
})();
|
|
11196
|
-
</script>`;var
|
|
11230
|
+
</script>`;var Cs=`<script>
|
|
11197
11231
|
window.MXD=(function(){
|
|
11198
11232
|
function el(id){return document.getElementById(id)}
|
|
11199
11233
|
function tz(){return -new Date().getTimezoneOffset()}
|
|
@@ -11407,7 +11441,7 @@ window.MXD=(function(){
|
|
|
11407
11441
|
|
|
11408
11442
|
return {openDay:openDay,openJob:openJob,openConversation:openConversation};
|
|
11409
11443
|
})();
|
|
11410
|
-
</script>`;var
|
|
11444
|
+
</script>`;var Is=`<script>
|
|
11411
11445
|
(function(){
|
|
11412
11446
|
var LANES=[
|
|
11413
11447
|
{id:'cron',name:'Scheduled',hint:'cron jobs'},
|
|
@@ -11723,7 +11757,7 @@ window.MXD=(function(){
|
|
|
11723
11757
|
window.addEventListener('scroll',hideTip,{passive:true});
|
|
11724
11758
|
load();
|
|
11725
11759
|
})();
|
|
11726
|
-
</script>`;var
|
|
11760
|
+
</script>`;var Ms=`<script>
|
|
11727
11761
|
(function(){
|
|
11728
11762
|
var showAll=document.getElementById('mx-show-all'),expanded=false;
|
|
11729
11763
|
var esc=MX.esc;
|
|
@@ -11901,7 +11935,7 @@ window.MXD=(function(){
|
|
|
11901
11935
|
}
|
|
11902
11936
|
load();setInterval(load,5000);
|
|
11903
11937
|
})();
|
|
11904
|
-
</script>`;var
|
|
11938
|
+
</script>`;var Ls=`
|
|
11905
11939
|
.mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
|
|
11906
11940
|
.mx-rt-wrap{border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-lg);background:var(--ax-surface);overflow-x:auto}
|
|
11907
11941
|
.mx-rt-wrap > .mx-empty{border:0}
|
|
@@ -11942,7 +11976,7 @@ window.MXD=(function(){
|
|
|
11942
11976
|
.mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
|
|
11943
11977
|
.mx-rt-name{max-width:100%}
|
|
11944
11978
|
}
|
|
11945
|
-
`,
|
|
11979
|
+
`,Rs=`<script>
|
|
11946
11980
|
(function(){
|
|
11947
11981
|
var root=document.getElementById('mx-routines');
|
|
11948
11982
|
var bar=document.getElementById('mx-rt-filter');
|
|
@@ -12069,7 +12103,7 @@ window.MXD=(function(){
|
|
|
12069
12103
|
syncBar();
|
|
12070
12104
|
document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
|
|
12071
12105
|
})();
|
|
12072
|
-
</script>`;var
|
|
12106
|
+
</script>`;var $s=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Ps=`<script>
|
|
12073
12107
|
(function(){
|
|
12074
12108
|
var root=document.getElementById('mx-feed');
|
|
12075
12109
|
if(!root)return;
|
|
@@ -12144,12 +12178,12 @@ window.MXD=(function(){
|
|
|
12144
12178
|
}
|
|
12145
12179
|
load();setInterval(load,5000);
|
|
12146
12180
|
})();
|
|
12147
|
-
</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
|
|
12181
|
+
</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 fu=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],hu=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],gu=[{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."})+At([{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">
|
|
12148
12182
|
<div class="mx-tabs" role="tablist" aria-label="Mesh views">
|
|
12149
|
-
${
|
|
12183
|
+
${hu.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("")}
|
|
12150
12184
|
</div>
|
|
12151
12185
|
<div class="mx-range" id="mx-range" role="group" aria-label="History window">
|
|
12152
|
-
${
|
|
12186
|
+
${gu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
|
|
12153
12187
|
</div>
|
|
12154
12188
|
</div>
|
|
12155
12189
|
<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">
|
|
@@ -12202,7 +12236,7 @@ window.MXD=(function(){
|
|
|
12202
12236
|
<section class="mx-section" aria-labelledby="mx-routines-title">
|
|
12203
12237
|
${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>')}
|
|
12204
12238
|
<div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
|
|
12205
|
-
${
|
|
12239
|
+
${fu.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12206
12240
|
</div>
|
|
12207
12241
|
<div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
|
|
12208
12242
|
</section>
|
|
@@ -12210,7 +12244,7 @@ window.MXD=(function(){
|
|
|
12210
12244
|
<section class="mx-section" aria-labelledby="mx-feed-title">
|
|
12211
12245
|
${ne(ae.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
|
|
12212
12246
|
<div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
|
|
12213
|
-
${
|
|
12247
|
+
${$s.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
|
|
12214
12248
|
</div>
|
|
12215
12249
|
<div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
|
|
12216
12250
|
</section>
|
|
@@ -12243,7 +12277,7 @@ window.MXD=(function(){
|
|
|
12243
12277
|
<button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
|
|
12244
12278
|
</header>
|
|
12245
12279
|
<div class="mx-drawer__body" id="mx-drawer-body"></div>
|
|
12246
|
-
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:
|
|
12280
|
+
</aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ts+Ls,scripts:As+xu+Cs+Is+Rs+Ms+Ps})}var xu=`<script>
|
|
12247
12281
|
(function(){
|
|
12248
12282
|
var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
|
|
12249
12283
|
var range=document.getElementById('mx-range');
|
|
@@ -12271,10 +12305,10 @@ window.MXD=(function(){
|
|
|
12271
12305
|
var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
|
|
12272
12306
|
select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
|
|
12273
12307
|
})();
|
|
12274
|
-
</script>`;function
|
|
12308
|
+
</script>`;function Os(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."})+`
|
|
12275
12309
|
<div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
|
|
12276
12310
|
<ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
|
|
12277
|
-
<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:
|
|
12311
|
+
<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:vu,scripts:`<script>${bu}</script>`})}var vu=`
|
|
12278
12312
|
.gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
|
|
12279
12313
|
.gm-empty { color: var(--ax-text-2); }
|
|
12280
12314
|
.gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
|
|
@@ -12292,7 +12326,7 @@ window.MXD=(function(){
|
|
|
12292
12326
|
.gm-msg { min-height: 1.4em; margin: 8px 0 0; }
|
|
12293
12327
|
.gm-msg.is-bad { color: var(--ax-red-ink); }
|
|
12294
12328
|
.gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
|
|
12295
|
-
`,
|
|
12329
|
+
`,bu=`
|
|
12296
12330
|
(function () {
|
|
12297
12331
|
var list = document.getElementById('gm-list');
|
|
12298
12332
|
var msg = document.getElementById('gm-msg');
|
|
@@ -12339,7 +12373,7 @@ window.MXD=(function(){
|
|
|
12339
12373
|
load();
|
|
12340
12374
|
setInterval(load, 30000);
|
|
12341
12375
|
})();
|
|
12342
|
-
`;async function
|
|
12376
|
+
`;async function Ns(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 yu(s,e.days)}function yu(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,p=0,u=0,f=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 d of g.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])m[x][0]+=d[x]?.[0]||0,m[x][1]+=d[x]?.[1]||0;n.set(d.day,m)}for(let d of g.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of g.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let x of d.agents)m.agents.includes(x)||m.agents.push(x);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,f=Math.max(f,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):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:p,tokenSamples:u,maxTokens:f},retention:{traces:h,tracesWithSteps:k}}}async function Ds(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 Hs(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 wu(s,e.day)}function wu(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 Bs(t={}){let e=`
|
|
12343
12377
|
<select id="boardPicker" title="Switch board"></select>
|
|
12344
12378
|
<div class="search">
|
|
12345
12379
|
<span class="icon">\u2315</span>
|
|
@@ -12440,7 +12474,7 @@ window.MXD=(function(){
|
|
|
12440
12474
|
</footer>
|
|
12441
12475
|
</div>
|
|
12442
12476
|
</div>
|
|
12443
|
-
<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:
|
|
12477
|
+
<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:ku,scripts:`<script>${_u}</script>`,headExtras:`<script>
|
|
12444
12478
|
// The boards page has its own connection dot + wants body height:100%
|
|
12445
12479
|
// for the full-viewport kanban layout. Inject the dot into the topbar
|
|
12446
12480
|
// and override body height at runtime so the shared shell doesn't
|
|
@@ -12456,7 +12490,7 @@ window.MXD=(function(){
|
|
|
12456
12490
|
right.insertBefore(dot, right.firstChild);
|
|
12457
12491
|
}
|
|
12458
12492
|
});
|
|
12459
|
-
</script>`})}var
|
|
12493
|
+
</script>`})}var ku=`
|
|
12460
12494
|
/* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
|
|
12461
12495
|
.ax-subheader select, .ax-subheader input, .ax-subheader button {
|
|
12462
12496
|
background: var(--col); color: var(--text); border: 1px solid var(--border);
|
|
@@ -12709,7 +12743,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
|
|
|
12709
12743
|
.draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
|
|
12710
12744
|
.draft-box .draft-row .hint.err { color: var(--red); }
|
|
12711
12745
|
.draft-box .draft-row .hint.ok { color: var(--green); }
|
|
12712
|
-
`,
|
|
12746
|
+
`,_u=`
|
|
12713
12747
|
'use strict';
|
|
12714
12748
|
const state = {
|
|
12715
12749
|
boards: [], current: null, items: {},
|
|
@@ -13762,9 +13796,9 @@ function appendEvents(events) {
|
|
|
13762
13796
|
}
|
|
13763
13797
|
|
|
13764
13798
|
loadBoards().catch(e => toast('Init failed: ' + e.message));
|
|
13765
|
-
`;function
|
|
13799
|
+
`;function zs(t={}){let a=`<h1>Plain-English glossary</h1>
|
|
13766
13800
|
<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>
|
|
13767
|
-
${
|
|
13801
|
+
${Es.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:Su})}var Su=`
|
|
13768
13802
|
main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
|
|
13769
13803
|
h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
|
|
13770
13804
|
.lead {
|
|
@@ -13794,7 +13828,7 @@ article.term .alias {
|
|
|
13794
13828
|
}
|
|
13795
13829
|
article.term p {
|
|
13796
13830
|
margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
|
|
13797
|
-
}`;function
|
|
13831
|
+
}`;function qs(t={}){let e=`<div class="ax-wf__root">
|
|
13798
13832
|
<aside class="ax-wf__list">
|
|
13799
13833
|
<header>
|
|
13800
13834
|
<h2>Workflows</h2>
|
|
@@ -13871,7 +13905,7 @@ article.term p {
|
|
|
13871
13905
|
</aside>
|
|
13872
13906
|
</div>
|
|
13873
13907
|
|
|
13874
|
-
<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:
|
|
13908
|
+
<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:Eu,scripts:`<script>${z({workflowHealth:Tn})}${Tu}</script>`})}var Eu=`
|
|
13875
13909
|
.ax-wf__root {
|
|
13876
13910
|
display: grid;
|
|
13877
13911
|
grid-template-columns: 340px 1fr;
|
|
@@ -14255,7 +14289,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
14255
14289
|
font-size: 12px; z-index: 50;
|
|
14256
14290
|
}
|
|
14257
14291
|
.hint { color: var(--ax-muted); font-size: 11px; }
|
|
14258
|
-
`,
|
|
14292
|
+
`,Tu=`
|
|
14259
14293
|
(() => {
|
|
14260
14294
|
const $ = (sel) => document.querySelector(sel)
|
|
14261
14295
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel))
|
|
@@ -15044,7 +15078,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15044
15078
|
setInterval(refresh, 15000)
|
|
15045
15079
|
})
|
|
15046
15080
|
})();
|
|
15047
|
-
`;function
|
|
15081
|
+
`;function Fs(t={}){let e=`<div class="ax-proc__root">
|
|
15048
15082
|
<header class="ax-proc__header">
|
|
15049
15083
|
<h1>Procedures</h1>
|
|
15050
15084
|
<p class="hint">Reusable building blocks workflows compose. See <a href="/admin/wiki/architecture/three-tier" target="_blank">three-tier model</a> for how this fits with System and Processes.</p>
|
|
@@ -15088,7 +15122,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15088
15122
|
<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>
|
|
15089
15123
|
<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>
|
|
15090
15124
|
</section>
|
|
15091
|
-
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:
|
|
15125
|
+
</div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Au,scripts:`<script>${Cu}</script>`})}var Au=`
|
|
15092
15126
|
.ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
|
|
15093
15127
|
.ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
|
15094
15128
|
.ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
|
|
@@ -15114,7 +15148,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15114
15148
|
.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); }
|
|
15115
15149
|
.ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
|
|
15116
15150
|
.ax-proc__link:hover { text-decoration: underline; }
|
|
15117
|
-
`,
|
|
15151
|
+
`,Cu=`
|
|
15118
15152
|
(function(){
|
|
15119
15153
|
function $(sel){ return document.querySelector(sel) }
|
|
15120
15154
|
function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] }) }
|
|
@@ -15214,7 +15248,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15214
15248
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
|
|
15215
15249
|
else bootAll()
|
|
15216
15250
|
})();
|
|
15217
|
-
`;function
|
|
15251
|
+
`;function Us(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
|
|
15218
15252
|
data-task-id="${N(t.taskId)}"
|
|
15219
15253
|
data-agent-id="${N(t.agentId)}"
|
|
15220
15254
|
data-node-url="${N(t.nodeUrl)}"
|
|
@@ -15257,7 +15291,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15257
15291
|
<button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
|
|
15258
15292
|
</div>
|
|
15259
15293
|
</footer>
|
|
15260
|
-
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15294
|
+
</div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Iu,scripts:`<script>${Mu}</script>`})}var Iu=`
|
|
15261
15295
|
/* The shell gives <main> no padding, so page content butted straight against
|
|
15262
15296
|
the sticky topbar. Breathe. */
|
|
15263
15297
|
.ax-task-page {
|
|
@@ -15399,7 +15433,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15399
15433
|
line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
|
|
15400
15434
|
}
|
|
15401
15435
|
|
|
15402
|
-
`,
|
|
15436
|
+
`,Mu=`
|
|
15403
15437
|
(function () {
|
|
15404
15438
|
var root = document.querySelector('.ax-task-page');
|
|
15405
15439
|
if (!root) return;
|
|
@@ -15784,7 +15818,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15784
15818
|
});
|
|
15785
15819
|
|
|
15786
15820
|
})();
|
|
15787
|
-
`;function
|
|
15821
|
+
`;function Ws(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
|
|
15788
15822
|
data-agent-id="${N(t.agentId)}"
|
|
15789
15823
|
data-agent-name="${N(e)}"
|
|
15790
15824
|
data-node-url="${N(t.nodeUrl)}">
|
|
@@ -15813,7 +15847,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15813
15847
|
<div class="ax-history__list" id="hist-list">
|
|
15814
15848
|
<div class="ax-history__empty">loading\u2026</div>
|
|
15815
15849
|
</div>
|
|
15816
|
-
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:
|
|
15850
|
+
</div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Lu,scripts:`<script>${Ru}</script>`})}var Lu=`
|
|
15817
15851
|
/* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
|
|
15818
15852
|
flush against the sticky topbar. */
|
|
15819
15853
|
.ax-history {
|
|
@@ -15865,7 +15899,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15865
15899
|
-webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
15866
15900
|
}
|
|
15867
15901
|
.ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
|
|
15868
|
-
`,
|
|
15902
|
+
`,Ru=`
|
|
15869
15903
|
(function () {
|
|
15870
15904
|
var root = document.querySelector('.ax-history');
|
|
15871
15905
|
if (!root) return;
|
|
@@ -15965,11 +15999,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
|
|
|
15965
15999
|
listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
|
|
15966
16000
|
});
|
|
15967
16001
|
})();
|
|
15968
|
-
`;function
|
|
16002
|
+
`;function Xs(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=>Gs(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Pu(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=ra.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 p=oa(c.data).map(u=>({path:"",message:u}));return R(e,200,{ok:p.length===0,issues:p,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,p=>Gs(e,a,p,{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 $u=["mesh"];function Gs(t,e,a,n){let r=ra.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=oa(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 p of $u)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/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",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function Pu(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,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return R(e,200,{runs:u});let f=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:f})}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 p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?R(e,200,{ok:!0,runId:l,status:p}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return ju(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 ju(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)}
|
|
15969
16003
|
|
|
15970
16004
|
`);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
|
|
15971
16005
|
|
|
15972
|
-
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=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
|
|
16006
|
+
`)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=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 mm}from"fs";import{createRequire as fm}from"module";var Ou=2048,Ks=/^[A-Za-z0-9_-]{8,256}$/;async function Js(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):Nu()});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 bt(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(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${_}, 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 p=Du(c.endpoint,o.allowedHosts);if(!p){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(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Ks.test(u)||typeof f!="string"||!Ks.test(f)?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:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function Nu(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Du(t,e){if(typeof t!="string"||t.length>Ou)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}cn();var Ys=50,Hu=280;async function Qs(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=Bu(await o.recent(Ys))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Vs(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Vs(e,404,{error:"not found"})}function Zs(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 rr(r):null}}}function Bu(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:Pa(typeof n.summary=="string"?n.summary:"",Hu),by:typeof n.agentId=="string"?Pa(n.agentId,100):null,node:Pa(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,Ys)}function Pa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Vs(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var zu="operator",qu=50,ei=4,ti=500;function Fu(t){let e={channel:"app",chatId:t.chatId,sender:zu,...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 ai(t,e,a,n){let{path:r,body:o}=Fu(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let k=u!=="done",_=i?{text:pt(f,k),artifacts:[]}:dt(f,le.perMessage,k),{cleanText:S,ui:g}=u==="done"?mt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ja(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...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 f=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,f||`AgentX answered HTTP ${u.status}.`)}for await(let f of Wu(u.body)){n(f.event,f.data);let h=f.data??{};if(f.event==="start")i=h.rich===!1;else if(f.event==="text"&&typeof h.text=="string")s+=h.text;else if(f.event==="tool"&&h.status==="start"&&l.length<qu){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(f.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(f.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(f.event==="error")return p("error",s,Uu(h.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function Uu(t){let e=String(t||"The agent could not answer.");return vn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ja(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,ei).map(s=>s.slice(0,ti));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,ei).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,ti)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Wu(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,`
|
|
15973
16007
|
`);let s;for(;(s=n.indexOf(`
|
|
15974
16008
|
|
|
15975
16009
|
`))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
|
|
@@ -15979,12 +16013,12 @@ data: ${JSON.stringify(s)}
|
|
|
15979
16013
|
|
|
15980
16014
|
`)},r=setInterval(()=>{a()&&e.write(`: ping
|
|
15981
16015
|
|
|
15982
|
-
`)},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
|
|
15983
|
-
`)){let n=
|
|
15984
|
-
`).map(
|
|
16016
|
+
`)},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 ri(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=Gu(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:Oa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Oa(t,e=120){for(let a of t.split(`
|
|
16017
|
+
`)){let n=oi(a);if(n)return Na(n,e)}return""}function Gu(t,e=120){let a=t.split(`
|
|
16018
|
+
`).map(oi).filter(Boolean);return a.length?Na(a[a.length-1],e):""}function oi(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Na(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Ut=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 Wt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var ni=140;function Gt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Oa(r||"",ni-18)||"something went wrong."}`:Oa(n,ni)||"Answered.";return{deviceId:t,title:Na(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var ii=8e3,Ku=/^[A-Za-z0-9_.:-]{1,64}$/,Re=new Map,Da=new Map,za=new Ut;function li(){return za}async function ci(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??za;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await di(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:ri(r.id,Yu(),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 p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Re.get(p.id);return H(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Re.get(p.id);if(!p||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),pi(e);let{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g}=p;return e.write(Ha("conversation",{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g})),e.write(Ha("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 bt(t,64*1024)}catch(p){return H(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return H(e,404,{error:"no such conversation"});let u=Re.get(p.id);return u?(u.ac.abort(),Ba(p,o,r.name),H(e,200,{stopped:!0})):await Ba(p,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await Vu(e,c,r,i,o),!0}function Ju(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,p=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:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...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 di(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ju(e.nodes,t.daemon,a)}async function Vu(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>ii){H(t,400,{error:`message must be 1\u2013${ii} 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:"",_=typeof e.agent=="string"?e.agent:"";if(!Ku.test(_)){H(t,400,{error:"pick an agent"});return}let S=(await di(r)).find(d=>d.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(d=>d.id===_);if(!g){H(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:_,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 Ft(r.orphanLimitMs??18e5);Re.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Da.set(l,{id:l,deviceId:a.id,title:c,agent:f,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),pi(t),t.write(Ha("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let k=e.spoken===!0,_=await ai(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(m,x)=>i.broadcast(m,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ba(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:_.text,status:_.status,at:Date.now(),..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},..._.tools.length?{tools:_.tools}:{}},_.files)??[];i.broadcast("final",{status:_.status,content:_.text,..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:_.status,attached:g,appOpen:(r.presence??za).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Wt(d)&&r.notifyFinish(Gt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Re.delete(l),Da.delete(l),i.finish()}}function Yu(){let t=[];for(let[e,a]of Da){let n=Re.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function pi(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Ha(t,e){return`event: ${t}
|
|
15985
16019
|
data: ${JSON.stringify(e)}
|
|
15986
16020
|
|
|
15987
|
-
`}async function Ba(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 Vu}from"stream";var Yu=/^\/api\/app\/files\/([^/]+)$/,Qu=15e3;async function di(t,e,a,n,r,o){let s=Yu.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 p=await Zu(c.node,o);if(!p)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 f=setTimeout(()=>u.abort(),Qu),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Bn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.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(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,m,{error:d||`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 _=h.headers.get("content-range");if(e.writeHead(h.status,{...zn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Vu.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function Zu(t,e){if(t==="local")return{url:ci(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ci(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ci(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 ui=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(!Vn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Jn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Ne(t,Kn.bytes);if(!_)return Q(e,413,{error:Yn()});if(!_.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 pi(e,o.daemon,"/voice/transcribe",_,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 p=typeof s?.text=="string"?s.text.slice(0,ui):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!tm(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return pi(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function pi(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(em(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 em(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function tm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===ui&&a.content.startsWith(e)))}var am=new Set(["ring","offer","answer","ice","hangup"]),Xt=/^[A-Za-z0-9_-]{4,64}$/,nm=128*1024;async function fi(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(),p=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==p),f=(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:f,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,nm);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 p=rm(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=hi(p.to);if(u&&p.kind==="ring"){let f=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.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 Xt.test(l)?om(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 p=String(c?.callId??"");if(!Xt.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.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(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.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(!Xt.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 hi(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 rm(t,e){let a=String(t?.kind??"");if(!am.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Xt.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:")&&!hi(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 om(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 gi=`
|
|
16021
|
+
`}async function Ba(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 Qu}from"stream";var Zu=/^\/api\/app\/files\/([^/]+)$/,em=15e3;async function mi(t,e,a,n,r,o){let s=Zu.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 p=await tm(c.node,o);if(!p)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 f=setTimeout(()=>u.abort(),em),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Bn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.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(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,m,{error:d||`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 _=h.headers.get("content-range");if(e.writeHead(h.status,{...zn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Qu.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function tm(t,e){if(t==="local")return{url:ui(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ui(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ui(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 hi=8e3;async function gi(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(!Vn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Jn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Ne(t,Kn.bytes);if(!_)return Q(e,413,{error:Yn()});if(!_.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 fi(e,o.daemon,"/voice/transcribe",_,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 p=typeof s?.text=="string"?s.text.slice(0,hi):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!nm(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return fi(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function fi(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(am(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 am(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function nm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===hi&&a.content.startsWith(e)))}var rm=new Set(["ring","offer","answer","ice","hangup"]),Xt=/^[A-Za-z0-9_-]{4,64}$/,om=128*1024;async function xi(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(),p=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==p),f=(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:f,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,om);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 p=sm(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=vi(p.to);if(u&&p.kind==="ring"){let f=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.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 Xt.test(l)?im(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 p=String(c?.callId??"");if(!Xt.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.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(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.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(!Xt.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 vi(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 sm(t,e){let a=String(t?.kind??"");if(!rm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Xt.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:")&&!vi(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 im(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 bi=`
|
|
15988
16022
|
(function () {
|
|
15989
16023
|
var fleetPanel = document.getElementById('panel-fleet');
|
|
15990
16024
|
var activityPanel = document.getElementById('panel-activity');
|
|
@@ -16228,7 +16262,7 @@ data: ${JSON.stringify(e)}
|
|
|
16228
16262
|
setInterval(refresh, 15000);
|
|
16229
16263
|
refresh();
|
|
16230
16264
|
})();
|
|
16231
|
-
`;var
|
|
16265
|
+
`;var yi=`
|
|
16232
16266
|
.fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
16233
16267
|
.fx-head h2 { margin: 4px 0 0; }
|
|
16234
16268
|
.fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
|
|
@@ -16285,7 +16319,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16285
16319
|
}
|
|
16286
16320
|
.fx-error:empty { display: none; }
|
|
16287
16321
|
.fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
|
|
16288
|
-
`;var
|
|
16322
|
+
`;var wi=`
|
|
16289
16323
|
(function () {
|
|
16290
16324
|
var panel = document.getElementById('panel-alerts');
|
|
16291
16325
|
if (!panel) return;
|
|
@@ -16466,7 +16500,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16466
16500
|
refresh();
|
|
16467
16501
|
loadRecent();
|
|
16468
16502
|
})();
|
|
16469
|
-
`;var
|
|
16503
|
+
`;var ki=`
|
|
16470
16504
|
(function () {
|
|
16471
16505
|
var panel = document.getElementById('panel-alerts');
|
|
16472
16506
|
if (!panel) return;
|
|
@@ -16579,7 +16613,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16579
16613
|
}
|
|
16580
16614
|
load();
|
|
16581
16615
|
})();
|
|
16582
|
-
`;var
|
|
16616
|
+
`;var _i=`
|
|
16583
16617
|
(function () {
|
|
16584
16618
|
var panel = document.getElementById('panel-chat');
|
|
16585
16619
|
var V = window.AXChatView;
|
|
@@ -16851,7 +16885,7 @@ details[open] > summary::before { transform: rotate(90deg); }
|
|
|
16851
16885
|
var last = recall('ax-chat-conv');
|
|
16852
16886
|
if (!fromHash() && last) openConversation(last);
|
|
16853
16887
|
})();
|
|
16854
|
-
`;var
|
|
16888
|
+
`;var Si=`
|
|
16855
16889
|
window.AXChatView = (function () {
|
|
16856
16890
|
var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
|
|
16857
16891
|
// Cut a half-written agentx:ui block from a streaming reply so its raw
|
|
@@ -17132,7 +17166,7 @@ window.AXChatView = (function () {
|
|
|
17132
17166
|
openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
|
|
17133
17167
|
cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
|
|
17134
17168
|
})();
|
|
17135
|
-
`;var
|
|
17169
|
+
`;var Ei=`
|
|
17136
17170
|
window.AXChatSheets = function (o) {
|
|
17137
17171
|
var V = o.V, picker = o.picker, hist = o.hist;
|
|
17138
17172
|
function loadPicker() {
|
|
@@ -17178,7 +17212,7 @@ window.AXChatSheets = function (o) {
|
|
|
17178
17212
|
});
|
|
17179
17213
|
return { loadPicker: loadPicker, loadHistory: loadHistory };
|
|
17180
17214
|
};
|
|
17181
|
-
`;var
|
|
17215
|
+
`;var Ti=`
|
|
17182
17216
|
window.AXChatLog = function (o) {
|
|
17183
17217
|
var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
|
|
17184
17218
|
function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
|
|
@@ -17241,7 +17275,7 @@ window.AXChatLog = function (o) {
|
|
|
17241
17275
|
return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
|
|
17242
17276
|
setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
|
|
17243
17277
|
};
|
|
17244
|
-
`;var
|
|
17278
|
+
`;var Ai=`
|
|
17245
17279
|
(function () {
|
|
17246
17280
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
|
|
17247
17281
|
var top = panel && panel.querySelector('.cx-top');
|
|
@@ -17391,7 +17425,7 @@ window.AXChatLog = function (o) {
|
|
|
17391
17425
|
window.AXStrip = { poll: poll, update: update, banner: banner };
|
|
17392
17426
|
poll();
|
|
17393
17427
|
})();
|
|
17394
|
-
`;var
|
|
17428
|
+
`;var Ci=`
|
|
17395
17429
|
.cs { margin: 0 -2px; }
|
|
17396
17430
|
.cs[hidden] { display: none; }
|
|
17397
17431
|
.cs-list {
|
|
@@ -17447,7 +17481,7 @@ window.AXChatLog = function (o) {
|
|
|
17447
17481
|
@media (prefers-reduced-motion: reduce) {
|
|
17448
17482
|
.cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
|
|
17449
17483
|
}
|
|
17450
|
-
`;function
|
|
17484
|
+
`;function Ii(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 Mi(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Li=`
|
|
17451
17485
|
body { height: 100dvh; }
|
|
17452
17486
|
main { min-height: 0; }
|
|
17453
17487
|
#panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
|
|
@@ -17557,7 +17591,7 @@ main { min-height: 0; }
|
|
|
17557
17591
|
background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
|
|
17558
17592
|
}
|
|
17559
17593
|
.cx-composer .fx-btn { border-radius: var(--ax-radius); }
|
|
17560
|
-
`;var
|
|
17594
|
+
`;var Ri=`
|
|
17561
17595
|
window.AXOrb = (function () {
|
|
17562
17596
|
// Same list, order and hash as presenceLook (src/voice/presence.ts) and
|
|
17563
17597
|
// OrbMath.colorHex, for an agent whose colour did not come with it.
|
|
@@ -17688,7 +17722,7 @@ window.AXOrb = (function () {
|
|
|
17688
17722
|
}
|
|
17689
17723
|
return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
|
|
17690
17724
|
})();
|
|
17691
|
-
`;var
|
|
17725
|
+
`;var $i=`
|
|
17692
17726
|
window.AXVoiceIO = (function () {
|
|
17693
17727
|
var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
|
|
17694
17728
|
var ac = null, playing = null;
|
|
@@ -17806,7 +17840,7 @@ window.AXVoiceIO = (function () {
|
|
|
17806
17840
|
|
|
17807
17841
|
return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
|
|
17808
17842
|
})();
|
|
17809
|
-
`;var
|
|
17843
|
+
`;var Pi=`
|
|
17810
17844
|
(function () {
|
|
17811
17845
|
var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
|
|
17812
17846
|
if (!panel || !C || !IO || !O) return;
|
|
@@ -18014,7 +18048,7 @@ window.AXVoiceIO = (function () {
|
|
|
18014
18048
|
idle();
|
|
18015
18049
|
window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
|
|
18016
18050
|
})();
|
|
18017
|
-
`;var
|
|
18051
|
+
`;var ji=`
|
|
18018
18052
|
.vx {
|
|
18019
18053
|
position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
|
|
18020
18054
|
margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
|
|
@@ -18050,7 +18084,7 @@ window.AXVoiceIO = (function () {
|
|
|
18050
18084
|
.cx-typing-on .vx-orb { width: 88px; height: 88px; }
|
|
18051
18085
|
.cx-typing-on .vx-row { gap: 16px; }
|
|
18052
18086
|
@media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
|
|
18053
|
-
`;var
|
|
18087
|
+
`;var Oi=`
|
|
18054
18088
|
<main class="card">
|
|
18055
18089
|
<h1>This phone isn't paired</h1>
|
|
18056
18090
|
<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>
|
|
@@ -18064,7 +18098,7 @@ window.AXVoiceIO = (function () {
|
|
|
18064
18098
|
<p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
|
|
18065
18099
|
</form>
|
|
18066
18100
|
<p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
|
|
18067
|
-
</main>`,
|
|
18101
|
+
</main>`,Ni=`
|
|
18068
18102
|
.pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
|
|
18069
18103
|
.pair-form label { font-weight: 600; }
|
|
18070
18104
|
.pair-form input {
|
|
@@ -18086,7 +18120,7 @@ window.AXVoiceIO = (function () {
|
|
|
18086
18120
|
margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
|
|
18087
18121
|
background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
|
|
18088
18122
|
}
|
|
18089
|
-
`,
|
|
18123
|
+
`,Di=`
|
|
18090
18124
|
(function () {
|
|
18091
18125
|
var form = document.getElementById('pair-form');
|
|
18092
18126
|
var input = document.getElementById('pair-code');
|
|
@@ -18178,7 +18212,7 @@ window.AXVoiceIO = (function () {
|
|
|
18178
18212
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
18179
18213
|
}
|
|
18180
18214
|
})();
|
|
18181
|
-
`;var
|
|
18215
|
+
`;var Hi=`
|
|
18182
18216
|
<div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
|
|
18183
18217
|
<video id="scan-video" playsinline muted autoplay></video>
|
|
18184
18218
|
<div class="scan-frame" aria-hidden="true"></div>
|
|
@@ -18187,7 +18221,7 @@ window.AXVoiceIO = (function () {
|
|
|
18187
18221
|
<button type="button" id="scan-close" class="scan-close">Close</button>
|
|
18188
18222
|
</div>
|
|
18189
18223
|
<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>
|
|
18190
|
-
</div>`,
|
|
18224
|
+
</div>`,Bi=`
|
|
18191
18225
|
.pair-form .scan-btn {
|
|
18192
18226
|
color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
|
|
18193
18227
|
}
|
|
@@ -18216,7 +18250,7 @@ window.AXVoiceIO = (function () {
|
|
|
18216
18250
|
}
|
|
18217
18251
|
.scan-msg.bad { color: #ffd0cc; font-weight: 600; }
|
|
18218
18252
|
body.scanning { overflow: hidden; }
|
|
18219
|
-
`,
|
|
18253
|
+
`,zi=`
|
|
18220
18254
|
(function () {
|
|
18221
18255
|
var openBtn = document.getElementById('scan-btn');
|
|
18222
18256
|
var box = document.getElementById('scan');
|
|
@@ -18424,7 +18458,7 @@ body.scanning { overflow: hidden; }
|
|
|
18424
18458
|
border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
|
|
18425
18459
|
}
|
|
18426
18460
|
.cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
|
|
18427
|
-
`;var
|
|
18461
|
+
`;var qi='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Fi=`
|
|
18428
18462
|
<div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
|
|
18429
18463
|
<div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
|
|
18430
18464
|
<span class="cam-dot" aria-hidden="true"></span>
|
|
@@ -18449,7 +18483,7 @@ body.scanning { overflow: hidden; }
|
|
|
18449
18483
|
<button type="button" id="cam-close" class="cam-secondary">Close</button>
|
|
18450
18484
|
</div>
|
|
18451
18485
|
</div>
|
|
18452
|
-
</div>`,
|
|
18486
|
+
</div>`,Ui=`
|
|
18453
18487
|
(function () {
|
|
18454
18488
|
var btn = document.getElementById('cam-btn');
|
|
18455
18489
|
var sheet = document.getElementById('cam');
|
|
@@ -18718,7 +18752,7 @@ body.scanning { overflow: hidden; }
|
|
|
18718
18752
|
});
|
|
18719
18753
|
window.addEventListener('pagehide', function () { stop(); });
|
|
18720
18754
|
})();
|
|
18721
|
-
`;var
|
|
18755
|
+
`;var Wi=`
|
|
18722
18756
|
<div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
|
|
18723
18757
|
<div class="cam-askbar-text">
|
|
18724
18758
|
<strong id="cam-ask-who">An agent</strong> wants to see through your camera
|
|
@@ -18728,7 +18762,7 @@ body.scanning { overflow: hidden; }
|
|
|
18728
18762
|
<button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
|
|
18729
18763
|
<button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
|
|
18730
18764
|
</div>
|
|
18731
|
-
</div>`,
|
|
18765
|
+
</div>`,Gi=`
|
|
18732
18766
|
.cam-askbar[hidden] { display: none; }
|
|
18733
18767
|
.cam-askbar {
|
|
18734
18768
|
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
|
@@ -18743,7 +18777,7 @@ body.scanning { overflow: hidden; }
|
|
|
18743
18777
|
border: 2px solid #fff; background: #fff; color: var(--ax-accent);
|
|
18744
18778
|
}
|
|
18745
18779
|
.cam-askbar-no { background: transparent; color: #fff; }
|
|
18746
|
-
`,
|
|
18780
|
+
`,Xi=`
|
|
18747
18781
|
(function () {
|
|
18748
18782
|
var bar = document.getElementById('cam-ask-bar');
|
|
18749
18783
|
if (!bar) return;
|
|
@@ -18813,7 +18847,7 @@ body.scanning { overflow: hidden; }
|
|
|
18813
18847
|
setInterval(poll, 5000);
|
|
18814
18848
|
document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
|
|
18815
18849
|
})();
|
|
18816
|
-
`;function
|
|
18850
|
+
`;function Ki(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 Ji(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 Vi=`
|
|
18817
18851
|
(function () {
|
|
18818
18852
|
var main = document.querySelector('main');
|
|
18819
18853
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
@@ -18922,7 +18956,7 @@ body.scanning { overflow: hidden; }
|
|
|
18922
18956
|
main.addEventListener('touchend', function () { end(false); });
|
|
18923
18957
|
main.addEventListener('touchcancel', function () { end(true); });
|
|
18924
18958
|
})();
|
|
18925
|
-
`,
|
|
18959
|
+
`,Yi=`
|
|
18926
18960
|
main { position: relative; }
|
|
18927
18961
|
main.sw-on { overflow: hidden; }
|
|
18928
18962
|
.sw-on > [role=tabpanel] { will-change: transform; }
|
|
@@ -18933,7 +18967,7 @@ main > .sw-peek {
|
|
|
18933
18967
|
}
|
|
18934
18968
|
main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
|
|
18935
18969
|
@media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
|
|
18936
|
-
`;function
|
|
18970
|
+
`;function Qi(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 Zi(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function el(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function tl(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 Fa=`
|
|
18937
18971
|
${z({afterUnauthorized:Hr})}
|
|
18938
18972
|
var CACHE = 'agentx-app-v3';
|
|
18939
18973
|
var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
|
|
@@ -19025,7 +19059,7 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19025
19059
|
return self.clients.openWindow(target);
|
|
19026
19060
|
}));
|
|
19027
19061
|
});
|
|
19028
|
-
`;var
|
|
19062
|
+
`;var lm="<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 Ua(t){return`<meta charset="utf-8">
|
|
19029
19063
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
19030
19064
|
<meta name="theme-color" content="#2979FF">
|
|
19031
19065
|
<meta name="referrer" content="no-referrer">
|
|
@@ -19036,38 +19070,38 @@ self.addEventListener('notificationclick', function (e) {
|
|
|
19036
19070
|
<link rel="icon" type="image/png" href="/app/icon-192.png">
|
|
19037
19071
|
<link rel="apple-touch-icon" href="/app/icon-192.png">
|
|
19038
19072
|
<title>${t}</title>
|
|
19039
|
-
${
|
|
19040
|
-
<style>${Tt}${
|
|
19073
|
+
${lm}
|
|
19074
|
+
<style>${Tt}${pm}</style>`}var al=[{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 nl(){let t=al.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}">${a.label}</button>`).join(""),e=al.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
|
|
19041
19075
|
<h2>${a.label}</h2>
|
|
19042
19076
|
<p class="soon">${a.soon}</p>
|
|
19043
19077
|
</section>`).join("");return`<!doctype html>
|
|
19044
19078
|
<html lang="en">
|
|
19045
|
-
<head>${Ua("AgentX")}<style>${
|
|
19079
|
+
<head>${Ua("AgentX")}<style>${um}${yi}${Li}${Ci}${ji}${qa}${Gi}${Yi}</style></head>
|
|
19046
19080
|
<body>
|
|
19047
19081
|
<header class="bar">
|
|
19048
19082
|
<div>
|
|
19049
19083
|
<h1>AgentX</h1>
|
|
19050
19084
|
<p id="who" class="who">Connecting\u2026</p>
|
|
19051
19085
|
</div>
|
|
19052
|
-
<div class="bar-btns">${
|
|
19086
|
+
<div class="bar-btns">${qi}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
|
|
19053
19087
|
</header>
|
|
19054
19088
|
<p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
|
|
19055
|
-
${
|
|
19089
|
+
${Wi}
|
|
19056
19090
|
<main>${e}</main>
|
|
19057
19091
|
<nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
|
|
19058
|
-
${
|
|
19059
|
-
<script>${
|
|
19060
|
-
<script>${z({swipeMayStart:
|
|
19061
|
-
<script>${gi}</script>
|
|
19062
|
-
<script>${vi}</script>
|
|
19092
|
+
${Fi}
|
|
19093
|
+
<script>${cm}</script>
|
|
19094
|
+
<script>${z({swipeMayStart:Qi,swipeAxis:Zi,swipeOffset:el,swipeLanding:tl})}${Vi}</script>
|
|
19063
19095
|
<script>${bi}</script>
|
|
19064
|
-
<script>${
|
|
19065
|
-
<script>${
|
|
19066
|
-
<script>${Si}</script>
|
|
19067
|
-
<script>${z({
|
|
19068
|
-
<script>${
|
|
19096
|
+
<script>${wi}</script>
|
|
19097
|
+
<script>${ki}</script>
|
|
19098
|
+
<script>${z({markdownToHtml:Nn})}${Si}${Ti}${Ei}${_i}</script>
|
|
19099
|
+
<script>${z({queueSpeech:Ii,nextSpeech:Mi})}${Ri}${$i}${Pi}</script>
|
|
19100
|
+
<script>${Ai}</script>
|
|
19101
|
+
<script>${z({cameraConstraints:Ki,shareClock:Ji})}${Ui}</script>
|
|
19102
|
+
<script>${Xi}</script>
|
|
19069
19103
|
</body>
|
|
19070
|
-
</html>`}function
|
|
19104
|
+
</html>`}function rl(){return`<!doctype html>
|
|
19071
19105
|
<html lang="en">
|
|
19072
19106
|
<head>${Ua("Pair \xB7 AgentX")}</head>
|
|
19073
19107
|
<body>
|
|
@@ -19075,17 +19109,17 @@ ${Bi}
|
|
|
19075
19109
|
<h1>Pairing this phone\u2026</h1>
|
|
19076
19110
|
<p id="msg" role="status">One moment.</p>
|
|
19077
19111
|
</main>
|
|
19078
|
-
<script>${
|
|
19112
|
+
<script>${dm}</script>
|
|
19079
19113
|
</body>
|
|
19080
|
-
</html>`}function
|
|
19114
|
+
</html>`}function ol(){return`<!doctype html>
|
|
19081
19115
|
<html lang="en">
|
|
19082
|
-
<head>${Ua("Not paired \xB7 AgentX")}<style>${
|
|
19083
|
-
<body>${
|
|
19116
|
+
<head>${Ua("Not paired \xB7 AgentX")}<style>${Ni}${Bi}</style></head>
|
|
19117
|
+
<body>${Oi}${Hi}
|
|
19084
19118
|
<script>${z({mayBounce:Br,formatPairInput:Pt,parsePairScan:zr})}</script>
|
|
19085
|
-
<script>${ji}</script>
|
|
19086
19119
|
<script>${Di}</script>
|
|
19120
|
+
<script>${zi}</script>
|
|
19087
19121
|
</body>
|
|
19088
|
-
</html>`}function
|
|
19122
|
+
</html>`}function sl(){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 cm=`
|
|
19089
19123
|
(function () {
|
|
19090
19124
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
|
|
19091
19125
|
function select(tab, focus, keepHash) {
|
|
@@ -19155,7 +19189,7 @@ ${Bi}
|
|
|
19155
19189
|
navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
|
|
19156
19190
|
}
|
|
19157
19191
|
})();
|
|
19158
|
-
`,
|
|
19192
|
+
`,dm=`
|
|
19159
19193
|
(function () {
|
|
19160
19194
|
var msg = document.getElementById('msg');
|
|
19161
19195
|
var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
|
|
@@ -19172,7 +19206,7 @@ ${Bi}
|
|
|
19172
19206
|
: 'Pairing failed (HTTP ' + r.status + '). Try again.';
|
|
19173
19207
|
}).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
|
|
19174
19208
|
})();
|
|
19175
|
-
`,
|
|
19209
|
+
`,pm=`
|
|
19176
19210
|
html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
|
|
19177
19211
|
body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
|
|
19178
19212
|
code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
|
|
@@ -19184,7 +19218,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
|
|
|
19184
19218
|
.card h1 { font-size: 22px; margin: 0 0 12px; }
|
|
19185
19219
|
.muted { color: var(--ax-text-2); }
|
|
19186
19220
|
:focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
|
|
19187
|
-
`,
|
|
19221
|
+
`,um=`
|
|
19188
19222
|
body { display: flex; flex-direction: column; }
|
|
19189
19223
|
.bar {
|
|
19190
19224
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
@@ -19222,8 +19256,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19222
19256
|
}
|
|
19223
19257
|
.tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
|
|
19224
19258
|
[data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
|
|
19225
|
-
`;var Kt="agentx_app",
|
|
19226
|
-
`;Ze=Buffer.concat([Buffer.from(a),
|
|
19259
|
+
`;var Kt="agentx_app",hm=400*86400,gm=new yt,xm=new Ee;async function il(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",sl());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),xe(e,200,"text/javascript; charset=utf-8",Fa);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",rl());if(a==="/app/qr.js"){let i=vm();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=Wa(et(t),o);return i?(e.setHeader("Set-Cookie",Ga(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 On(t,{codes:r.pairCodes??new ft,limiter:r.pairLimiter??gm,verify:l=>Wa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ga(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Pe(e,i.status,i.body)}let s=Wa(bm(t),o);if(!s){let i=et(t);return(r.rejectLog??xm).record(a.slice(0,120),$t(t,He(Xa(t,Kt),o),i?He(i,o):null)),a==="/app"?xe(e,401,"text/html; charset=utf-8",ol()):Pe(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Xa(t,Kt);return i&&!et(t)&&e.setHeader("Set-Cookie",Ga(i)),xe(e,200,"text/html; charset=utf-8",nl())}return n==="GET"&&a==="/api/app/me"?Pe(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await jn(t,e,a,n,s.name,r.fleet)||r.push&&await Js(t,e,a,n,s,r.push)||r.announce&&await Qs(t,e,a,n,s,r.announce)||r.chat&&await ci(t,e,a,n,s,r.chat)||r.chat&&await mi(t,e,a,n,s,r.chat)||r.voice&&await gi(t,e,a,n,s,r.voice)||r.camera&&await xi(t,e,a,n,r.camera)?!0:Pe(e,404,{error:"not found"})}var Ze;function vm(){if(Ze!==void 0)return Ze;try{let t=fm(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
|
|
19260
|
+
`;Ze=Buffer.concat([Buffer.from(a),mm(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ze=null}return Ze}function Wa(t,e){if(!t)return null;let a=e.verify(t);return a&&ke(a,"app")?a:null}function Ga(t){return`${Kt}=${t}; Path=/; Max-Age=${hm}; HttpOnly; Secure; SameSite=Lax`}function bm(t){return et(t)??Xa(t,Kt)}function et(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Xa(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 ll}from"crypto";var je={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},ym=/^[a-f0-9]{32}$/,wm=/^c[a-z0-9]{8,32}$/,km=/^#[0-9a-fA-F]{6}$/;function Ka(t){return wm.test(t)}var tt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
|
|
19227
19261
|
id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
|
|
19228
19262
|
node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
|
|
19229
19263
|
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
|
|
@@ -19236,39 +19270,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
|
|
|
19236
19270
|
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
|
|
19237
19271
|
path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
|
|
19238
19272
|
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 (
|
|
19239
|
-
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ka(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)}${
|
|
19240
|
-
(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(!Ka(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(
|
|
19273
|
+
key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ka(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)}${ll(4).toString("hex")}`,{color:s,...i}=a,l=s&&km.test(s)?s:void 0,c={id:o,title:Sm(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
|
|
19274
|
+
(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(!Ka(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(_m);return{...cl(n),messages:r}}list(e,a=je.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
|
|
19241
19275
|
(SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
|
|
19242
19276
|
(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
|
|
19243
|
-
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{...
|
|
19277
|
+
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{...cl(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Ka(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,
|
|
19244
19278
|
substr(m.content, 1, 240) AS answer, m.status, m.at
|
|
19245
19279
|
FROM app_chat_conversations c
|
|
19246
19280
|
JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
|
|
19247
19281
|
WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
|
|
19248
19282
|
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)+`
|
|
19249
19283
|
|
|
19250
|
-
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let f of r){if(l.length>=je.filesPerMessage)break;let h=f.filename.trim(),k=_n(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:
|
|
19284
|
+
[Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let f of r){if(l.length>=je.filesPerMessage)break;let h=f.filename.trim(),k=_n(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:ll(16).toString("hex"),name:_,mime:k.mime,kind:k.kind,path:h})}let c=l.map(f=>({id:f.id,name:f.name,mime:f.mime,kind:f.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
|
|
19251
19285
|
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)
|
|
19252
19286
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let f of l)u.run(f.id,a,Number(p.lastInsertRowid),f.path,f.name,f.mime,f.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
|
|
19253
19287
|
(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
|
|
19254
|
-
(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(!
|
|
19288
|
+
(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(!ym.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
|
|
19255
19289
|
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 = ?
|
|
19256
|
-
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
|
|
19290
|
+
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 cl(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 _m(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 Sm(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Em=4e3,Ja=100,Tm=15,dl=t=>t.replace(/\/+$/,""),Jt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Em){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,Ja);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??Tm)-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>=Ja&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ja}); 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||dl(l)!==dl(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=Am(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,f=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:f};return this.deps.notifyFinish&&Wt(h)&&this.deps.notifyFinish(Gt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Am(t,e){let a=t.plain?{text:pt(t.text,!1),artifacts:[]}:dt(t.text,le.perMessage,!1),{cleanText:n,ui:r}=mt(a.text),o=t.plain?void 0:ja(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Cm(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Cm(t){return t.replace(/\s+/g," ").trim().slice(0,300)}cn();function Ue(){let t=it();return t&&ye(t,"dashboard"),t}function Yy(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,Bm(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 bn(l?{baseDir:l}:void 0),p=new yn(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new wn(l?{baseDir:l}:void 0);fs(t),Ue(),Un({business:t.business?.enabled===!0});let f=Im(async(h,k)=>{try{await Om(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){b(k,500,{error:_.message||"internal error"})}});nf(t).start(),f.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
|
|
19257
19291
|
Live dashboard: http://${h}:${n}
|
|
19258
19292
|
`),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
|
|
19259
19293
|
Kanban dashboard: http://${h}:${n}
|
|
19260
|
-
`),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 $m=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 Pm(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(qn(t.headers)==="foreign"&&Fn(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Yr(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:ll(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(d,m)=>Nr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await rl(t,e,r,o,{nodeName:a.config.node?.name,fleet:fl(a.config),push:ml(a.config),announce:Vs(a.config),chat:hl(a.config),voice:af(a.config),camera:nf(a.config)}))return;if(o==="GET"&&$m.has(r)&&Sr("page",r),o==="GET"&&r==="/"){let d=dr();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ns({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await we(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await we(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ue(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await we(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({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(Ir({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=En(await we(a.config,d.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:d.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}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await Sn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rs({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($s({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await ue(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ds({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){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(zs({taskId:decodeURIComponent(i[1]),agentId:d,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:m,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(qs({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"){pr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ur(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await mr(t,e);return}if(o==="GET"&&r==="/admin"){lo(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){To(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){go(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}Oo(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await df(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await La(t,e,r,x=>xl(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await dl(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=nt(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await dl(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await No(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await pf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-W6OQ7JI2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zo({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Bo(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qo({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fo({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 zm(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 us(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await La(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await fs(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){xs(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await co(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,Xn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Ao(t,e,r,n);return}if(await Io(t,e,r,{people:()=>Ke(a.config.people),members:ll(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await xo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await vs(t,e,r);return}if(r.startsWith("/api/admin/")){await po(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(Qr);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=lf("web/"+d);try{let x=await cf(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await We(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await we(a.config);b(e,200,await Ps(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await we(a.config);b(e,200,await Os(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(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 d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await js(e,await we(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Km(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await Jm(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await Qm(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Zm(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ue(t);try{let m=await of(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Vm(t,e,[`agent:${d}`]))return;await Ym(t,e,a.config,d);return}if(o==="GET"&&r==="/api/node/build"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:d,signal:AbortSignal.timeout(3e3)});if(!m.ok)throw new Error(`HTTP ${m.status}`);b(e,200,Gn(await m.json()))}catch(d){b(e,502,{error:d.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await qm(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"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=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(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
19294
|
+
`),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 Om(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(qn(t.headers)==="foreign"&&Fn(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await eo(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:pl(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(d,m)=>Nr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await il(t,e,r,o,{nodeName:a.config.node?.name,fleet:xl(a.config),push:gl(a.config),announce:Zs(a.config),chat:vl(a.config),voice:rf(a.config),camera:of(a.config)}))return;if(o==="GET"&&jm.has(r)&&Sr("page",r),o==="GET"&&r==="/"){let d=dr();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await we(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await we(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ue(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await we(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({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(Ir({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=En(await we(a.config,d.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:d.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}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await Sn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}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(Os({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await ue(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zs({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qs({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fs({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){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(Us({taskId:decodeURIComponent(i[1]),agentId:d,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:m,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(Ws({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"){pr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ur(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await mr(t,e);return}if(o==="GET"&&r==="/admin"){uo(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Io(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){bo(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}Ho(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await uf(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await La(t,e,r,x=>yl(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await ml(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=nt(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await ml(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Bo(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await mf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-W6OQ7JI2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Uo({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Fo(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wo({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Go({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 Fm(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 hs(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await La(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await xs(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){ys(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await mo(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,Xn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Mo(t,e,r,n);return}if(await Ro(t,e,r,{people:()=>Ke(a.config.people),members:pl(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await yo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await ws(t,e,r);return}if(r.startsWith("/api/admin/")){await fo(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(to);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=df("web/"+d);try{let x=await pf(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await We(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await we(a.config);b(e,200,await Ns(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await we(a.config);b(e,200,await Hs(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(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 d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Ds(e,await we(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Vm(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await Ym(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await ef(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await tf(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ue(t);try{let m=await lf(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Qm(t,e,[`agent:${d}`]))return;await Zm(t,e,a.config,d);return}if(o==="GET"&&r==="/api/node/build"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:d,signal:AbortSignal.timeout(3e3)});if(!m.ok)throw new Error(`HTTP ${m.status}`);b(e,200,Gn(await m.json()))}catch(d){b(e,502,{error:d.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Um(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"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=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(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
|
|
19261
19295
|
|
|
19262
19296
|
`)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let y of x)(async()=>{let I={Accept:"text/event-stream"};y.token&&(I.Authorization=`Bearer ${y.token}`);let C=new AbortController;w.push(C);try{let E=await fetch(`${y.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:I,signal:C.signal});if(!E.ok||!E.body)return;let $=E.body.getReader(),L=new TextDecoder,j="";for(;!v.flag;){let{done:W,value:q}=await $.read();if(W)break;j+=L.decode(q,{stream:!0});let G;for(;(G=j.indexOf(`
|
|
19263
19297
|
|
|
19264
19298
|
`))>=0;){let ie=j.slice(0,G);if(j=j.slice(G+2),v.flag)break;try{e.write(ie+`
|
|
19265
19299
|
|
|
19266
|
-
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{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(y.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 w)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,m),$=v?E.map(L=>
|
|
19267
|
-
`;
|
|
19300
|
+
`)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{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(y.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 w)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,m),$=v?E.map(L=>Hm(L)):E;b(e,200,{runs:$})}catch(d){b(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){b(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let w={};v.token&&(w.Authorization=`Bearer ${v.token}`);let T=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:w});if(T.ok){b(e,200,await T.json());return}}catch{}b(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,v)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Xs(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let w=ia(m);if(!w)return!0;let T=new F().verify(w);if(!T)return b(x,401,{error:"invalid or revoked token"}),!1;for(let y of v)if(!ke(T,y))return b(x,403,{error:`token missing scope: ${y}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.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[,d,m]=S,x=decodeURIComponent(m),v=a.boards.find(C=>C.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}let T=await ue(t),y=v.columns.find(C=>C.id===T.to),I=v.columns.find(C=>C.id===T.from);if(!y){b(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await Dm(w,x,I,y),Va({actor:Ya(t),action:"move",boardId:d,itemId:x,payload:{from:T.from,to:T.to}}),b(e,200,{ok:!0})}catch(C){b(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(T=>T.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:y}=await Nm(v,w,n.searchParams);b(e,200,{columns:T,totals:y});return}if(o==="GET"&&x){try{let T=typeof w.getItem=="function"?await w.getItem(x):null;if(!T){b(e,404,{error:"not found"});return}b(e,200,T)}catch(T){b(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await ue(t);try{let y=typeof w.updateItem=="function"?await w.updateItem(x,T):null;if(!y){b(e,501,{error:"update unsupported"});return}Va({actor:Ya(t),action:"update",boardId:d,itemId:x,payload:T}),b(e,200,y)}catch(y){b(e,502,{error:y.message})}return}if(o==="POST"&&!x){let T=await ue(t);if(!T.title){b(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){b(e,400,{error:`source ${w.type} does not support create`});return}try{let y=await w.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});Va({actor:Ya(t),action:"create",boardId:d,itemId:y.id,payload:{title:T.title}}),b(e,201,y)}catch(y){b(e,502,{error:y.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=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"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}b(e,404,{error:"not found",path:r})}async function Nm(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.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),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),f=p?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 d of t.columns)k[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&k[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=nn(d,S);if(!m)continue;let x=k[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(k))k[d]=k[d].filter(m=>m.assignee===i);for(let d of Object.keys(k))k[d].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([d,m])=>[d,m.length]));return{columns:k,totals:g}}async function Dm(t,e,a,n){let r=rn(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 Hm(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 Bm(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 Qn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Va(t){try{let e=at(process.cwd(),".agentx");fl(e)||Lm(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
|
|
19301
|
+
`;Mm(at(e,"board-audit.jsonl"),a)}catch{}}function Ya(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var zm=2e3;async function qm(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 d=new AbortController,m=setTimeout(()=>d.abort(),zm),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let w=v.ok?await v.json().catch(()=>{}):void 0;return{ok:w!==void 0,json:async()=>w}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,k,_]=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(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let g=await f.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,Cn.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(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Jm(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Vt=null;function Fm(t){if(Vt)return Vt;let e=at(process.cwd(),".agentx/wiki");return Vt=Ar({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Vt}async function Qt(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 Um(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){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(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 Qt(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 Wm=3e3,Gm=6e3,Xm=5*6e4,Za=new Map,Yt=new Map;function We(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Yt.get(a);if(n)return n;let r=(async()=>{let o=await we(t,AbortSignal.timeout(Wm)),s=await Promise.all(o.map(async i=>{let l=await qm(i.url,i.token,AbortSignal.timeout(Gm),e);return e?l:Km(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Yt.delete(a));return Yt.set(a,r),r}function Km(t,e,a=Date.now()){if(e.reachable&&!e.error)return Za.set(t,{node:e,at:a}),e;let n=Za.get(t);return!n||a-n.at>Xm?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Qy(){Za.clear(),Yt.clear()}function Jm(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 Vm(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}
|
|
19268
19302
|
data: ${JSON.stringify(c)}
|
|
19269
19303
|
|
|
19270
|
-
`)},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
|
|
19271
|
-
${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
|
|
19304
|
+
`)},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 Ym(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 Qt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of k)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(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 p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){b(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(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 f=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:_}=await f.read();if(_)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Qm(t,e,a){let n=ia(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ke(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Zm(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(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||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){b(e,502,{error:c.message||"upstream call failed"})}}async function ef(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 Qt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(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 p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function tf(t,e,a,n,r,o){await en(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function en(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await hl(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function hl(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),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 Qt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.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 gl(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=Rn(e.keysFile);return{store:()=>{let r=Ue();return r?new or(r):null},publicKey:()=>$n(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function xl(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 hl(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=xt({root:process.cwd()}).items.map(ul)}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(ul)}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(),p=await vt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.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 Qa=null;function pl(t){return Qa?.days!==t&&(Qa={days:t,store:new ct(process.cwd(),Date.now,t)}),Qa.store}function vl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=xl(t);return{store:()=>{let r=Ue();return r?new tt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:dn(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(/\/+$/,"")),...af(t,e,a)}}function af(t,e,a){let n=gl(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}
|
|
19305
|
+
${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 nf(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=vl(t);return new Jt({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:li(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function rf(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 of(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function ul(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 sf=`
|
|
19272
19306
|
You are helping draft a new GitLab issue. Follow these conventions strictly.
|
|
19273
19307
|
|
|
19274
19308
|
Title pattern:
|
|
@@ -19300,10 +19334,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
|
|
|
19300
19334
|
Shape:
|
|
19301
19335
|
{ "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
|
|
19302
19336
|
If you don't have enough information to pick a label confidently, omit it rather than guessing.
|
|
19303
|
-
`;async function
|
|
19337
|
+
`;async function lf(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):
|
|
19304
19338
|
- ${r.knownLabels.slice(0,60).join(`
|
|
19305
19339
|
- `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
|
|
19306
|
-
`),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:
|
|
19340
|
+
`),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:sf}})});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 p=(c.content||"").toString(),u=cf(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function cf(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 df(t){let e=Pm($m(import.meta.url));return at(e,t)}async function pf(t){return Rm(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(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 bl(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:bl(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 uf(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await zt(await yl(r,a.config)))}async function yl(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ma(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,p=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(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return us(n)}async function mf(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||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=f.find(k=>fl(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:f}));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}
|
|
19307
19341
|
|
|
19308
19342
|
`);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
|
|
19309
19343
|
`))>=0;){let h=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
|
|
@@ -19311,5 +19345,5 @@ data: ${h.replace(/\n/g," ")}
|
|
|
19311
19345
|
|
|
19312
19346
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
19313
19347
|
|
|
19314
|
-
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function
|
|
19315
|
-
//# sourceMappingURL=board-dashboard-
|
|
19348
|
+
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function ml(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),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}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(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:bl(n),token:n.dashboardToken||n.token}:null}export{Jm as applyAttachSessions,qm as fetchDaemonAgents,Om as handleBoardRequest,Qy as resetLiveCaches,we as resolveNodeTargets,Yy as startBoardDashboard,Km as withLastGood};
|
|
19349
|
+
//# sourceMappingURL=board-dashboard-MHMYOBKA.js.map
|