agentix-cli 0.66.0 → 0.67.0

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.
Files changed (32) hide show
  1. package/dist/{agent-BQ5CCARE.js → agent-LKL3XATA.js} +2 -2
  2. package/dist/{board-dashboard-K3P2M7A7.js → board-dashboard-ZE2A3ARS.js} +88 -83
  3. package/dist/{board-dashboard-K3P2M7A7.js.map → board-dashboard-ZE2A3ARS.js.map} +1 -1
  4. package/dist/{chunk-BBXBSM4R.js → chunk-3DNBE7WD.js} +109 -109
  5. package/dist/chunk-3DNBE7WD.js.map +1 -0
  6. package/dist/{chunk-ZIEUP56T.js → chunk-6H3U3CII.js} +16 -16
  7. package/dist/chunk-6H3U3CII.js.map +1 -0
  8. package/dist/{chunk-YDHI2CJG.js → chunk-A5COMJRC.js} +2 -2
  9. package/dist/{chunk-6CFAF5CH.js → chunk-F2LML4IL.js} +2 -2
  10. package/dist/{chunk-EPTZ6JMA.js → chunk-PRHIW6SQ.js} +4 -4
  11. package/dist/{chunk-AWKZ3BF2.js → chunk-UHUYGEXK.js} +5 -5
  12. package/dist/chunk-UHUYGEXK.js.map +1 -0
  13. package/dist/cli.js +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/{program-4W45H3J2.js → program-ZRGI76RT.js} +2 -2
  16. package/dist/{registry-TERSIHOC.js → registry-EUO2D6JT.js} +2 -2
  17. package/dist/rotation-memo-5MTSJ4FH.js +15 -0
  18. package/dist/rotation-memo-5MTSJ4FH.js.map +1 -0
  19. package/dist/web/activity-graph.global.js +7 -7
  20. package/dist/web/activity-graph.global.js.map +1 -1
  21. package/package.json +1 -1
  22. package/dist/chunk-AWKZ3BF2.js.map +0 -1
  23. package/dist/chunk-BBXBSM4R.js.map +0 -1
  24. package/dist/chunk-ZIEUP56T.js.map +0 -1
  25. package/dist/rotation-memo-453FXKHQ.js +0 -13
  26. package/dist/rotation-memo-453FXKHQ.js.map +0 -1
  27. /package/dist/{agent-BQ5CCARE.js.map → agent-LKL3XATA.js.map} +0 -0
  28. /package/dist/{chunk-YDHI2CJG.js.map → chunk-A5COMJRC.js.map} +0 -0
  29. /package/dist/{chunk-6CFAF5CH.js.map → chunk-F2LML4IL.js.map} +0 -0
  30. /package/dist/{chunk-EPTZ6JMA.js.map → chunk-PRHIW6SQ.js.map} +0 -0
  31. /package/dist/{program-4W45H3J2.js.map → program-ZRGI76RT.js.map} +0 -0
  32. /package/dist/{registry-TERSIHOC.js.map → registry-EUO2D6JT.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as Va}from"./chunk-2NYP4OQU.js";import{a as se,b as Ja}from"./chunk-JWDJMFU6.js";import{a as an}from"./chunk-62EJKQFX.js";import{a as A,b as nn,c as rn,d as on,e as sn,h as ln,i as Ie,j as cn,k as dn,l as un,m as mn,n as fn}from"./chunk-WMDDQVCI.js";import{a as pn}from"./chunk-Z3IP66SL.js";import{a as Ya,b as V,c as Qa,d as L,e as j,j as et,k as tt,l as ne,m as U,n as at,o as Za,p as en,q as tn}from"./chunk-C4CDVE2E.js";import{A as Xe,B as Ke,Ba as Me,C as Ra,Ca as Je,D as Pa,Da as Ve,Ea as Ye,Fa as Qe,Ga as Ua,Ha as Wa,Ia as Ga,Ja as Ze,K as q,L as ja,La as Xa,M as Oa,Oa as Ka,X as Ha,Y as Ba,Z as za,a as Ea,c as Ge,d as St,e as Sa,i as Ta,k as Aa,m as ae,n as be,o as Ia,p as Tt,sa as Fa,ua as At,za as qa}from"./chunk-YDHI2CJG.js";import{g as ka,h as _a}from"./chunk-5QP56S4O.js";import{p as Ca,s as Ma}from"./chunk-BYJ3A55Y.js";import{a as Na,b as Da}from"./chunk-LQRBGQIR.js";import"./chunk-I2SD4XZ6.js";import"./chunk-XT3E5MLX.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as La,c as $a}from"./chunk-2D3RYIDU.js";import{a as ha,c as _t,d as Et,h as ga,i as xa,j as va,p as ba,q as ya,r as ge,s as wa}from"./chunk-ZIEUP56T.js";import{a as Ce}from"./chunk-N6EWZGIX.js";import"./chunk-WP6KLXTP.js";import"./chunk-DP7RTNDM.js";import"./chunk-BHE5TJSN.js";import"./chunk-EA7H3EUX.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-AZBOYKQA.js";import{b as fa}from"./chunk-WGWNVLVW.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-PTB2TPOC.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as ua,b as ma,c as xs,w as te,z as kt}from"./chunk-OVF37EXJ.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ct(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 hn(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ct(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var re={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"/>'},ye=(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>",nt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ye(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function gn(t={}){return L({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as Va}from"./chunk-2NYP4OQU.js";import{a as se,b as Ja}from"./chunk-JWDJMFU6.js";import{a as an}from"./chunk-62EJKQFX.js";import{a as A,b as nn,c as rn,d as on,e as sn,h as ln,i as Ie,j as cn,k as dn,l as un,m as mn,n as fn}from"./chunk-WMDDQVCI.js";import{a as pn}from"./chunk-Z3IP66SL.js";import{a as Ya,b as V,c as Qa,d as L,e as j,j as et,k as tt,l as ne,m as U,n as at,o as Za,p as en,q as tn}from"./chunk-C4CDVE2E.js";import{A as Xe,B as Ke,Ba as Me,C as Ra,Ca as Je,D as Pa,Da as Ve,Ea as Ye,Fa as Qe,Ga as Ua,Ha as Wa,Ia as Ga,Ja as Ze,K as q,L as ja,La as Xa,M as Oa,Oa as Ka,X as Ha,Y as Ba,Z as za,a as Ea,c as Ge,d as St,e as Sa,i as Ta,k as Aa,m as ae,n as be,o as Ia,p as Tt,sa as Fa,ua as At,za as qa}from"./chunk-A5COMJRC.js";import{g as ka,h as _a}from"./chunk-5QP56S4O.js";import{p as Ca,s as Ma}from"./chunk-BYJ3A55Y.js";import{a as Na,b as Da}from"./chunk-LQRBGQIR.js";import"./chunk-I2SD4XZ6.js";import"./chunk-XT3E5MLX.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as La,c as $a}from"./chunk-2D3RYIDU.js";import{a as ha,c as _t,d as Et,h as ga,i as xa,j as va,p as ba,q as ya,r as ge,s as wa}from"./chunk-6H3U3CII.js";import{a as Ce}from"./chunk-N6EWZGIX.js";import"./chunk-WP6KLXTP.js";import"./chunk-DP7RTNDM.js";import"./chunk-BHE5TJSN.js";import"./chunk-EA7H3EUX.js";import"./chunk-AFRHKA7B.js";import"./chunk-QD6IICK7.js";import"./chunk-AZBOYKQA.js";import{b as fa}from"./chunk-WGWNVLVW.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-PTB2TPOC.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import{a as ua,b as ma,c as xs,w as te,z as kt}from"./chunk-OVF37EXJ.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Ct(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 hn(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Ct(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var re={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"/>'},ye=(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>",nt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ye(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function gn(t={}){return L({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>
@@ -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 Mt(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 It(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 xn(t,e=[],a){let{bands:n,gaps:r}=Mt(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(T=>l.startedAt>=T.from&&l.startedAt<=T.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),v=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};v.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,v)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>It(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 ys}from"crypto";import{readFileSync as ws,statSync as ks}from"fs";import{resolve as _s,dirname as Es}from"path";import{fileURLToPath as Ss}from"url";var vn=new Map;function rt(t){let e=vn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Es(Ss(import.meta.url)),r=_s(n,"web",t),o=ks(r),s=o.size<8e6?ys("sha1").update(ws(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return vn.set(t,a),a}var ie={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"/>'},ot=(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>",Ts=[["agent","Agent",ie.bot],["client","Client",ie.user],["project","Project",ie.folder],["channel","Channel",ie.route],["node","Node",ie.mesh]],bn={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; 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 yn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return L({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function Mt(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 It(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 xn(t,e=[],a){let{bands:n,gaps:r}=Mt(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),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>It(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 ys}from"crypto";import{readFileSync as ws,statSync as ks}from"fs";import{resolve as _s,dirname as Es}from"path";import{fileURLToPath as Ss}from"url";var vn=new Map;function rt(t){let e=vn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Es(Ss(import.meta.url)),r=_s(n,"web",t),o=ks(r),s=o.size<8e6?ys("sha1").update(ws(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return vn.set(t,a),a}var ie={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"/>'},ot=(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>",Ts=[["agent","Agent",ie.bot],["client","Client",ie.user],["project","Project",ie.folder],["channel","Channel",ie.route],["node","Node",ie.mesh]],bn={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; 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 yn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return L({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>
@@ -1043,7 +1043,7 @@ body { margin: 0; overflow: hidden; }
1043
1043
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1044
1044
  text-align: center;
1045
1045
  }
1046
- `;import{createServer as zd}from"http";import{appendFileSync as Fd,existsSync as cs,mkdirSync as qd}from"fs";import{readFile as Ud}from"fs/promises";import{fileURLToPath as Wd}from"url";import{dirname as Gd,resolve as qe}from"path";xs();var kn='/*! 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 st,readFileSync as En,writeFileSync as Sn,rmSync as Kp,mkdirSync as js,copyFileSync as Os,readdirSync as Ns}from"fs";import{resolve as Le}from"path";kt();var le={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 _n(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=et({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.`})+tt([{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">');return L({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ls()+Za,css:Rs,scripts:`${e}<script>${en}
1046
+ `;import{createServer as Ud}from"http";import{appendFileSync as Wd,existsSync as cs,mkdirSync as Gd}from"fs";import{readFile as Xd}from"fs/promises";import{fileURLToPath as Kd}from"url";import{dirname as Jd,resolve as qe}from"path";xs();var kn='/*! 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 st,readFileSync as En,writeFileSync as Sn,rmSync as Yp,mkdirSync as js,copyFileSync as Os,readdirSync as Ns}from"fs";import{resolve as Le}from"path";kt();var le={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 _n(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=et({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.`})+tt([{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">');return L({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+Ls()+Za,css:Rs,scripts:`${e}<script>${en}
1047
1047
  ${tn}
1048
1048
  ${Is}
1049
1049
  ${Ps}</script>`})}var Is=`
@@ -4760,7 +4760,7 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
4760
4760
  })();
4761
4761
 
4762
4762
  refresh();
4763
- `;function Tn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:a,localToken:n}))}async function An(t,e){let a=Rt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Cn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ys(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ds(t),r={"GET /api/admin/state":()=>Bs(),"POST /api/admin/agents":()=>Gs(n),"PATCH /api/admin/agents":()=>Xs(n),"DELETE /api/admin/agents":()=>Ks(n),"POST /api/admin/agents/access":()=>zs(n),"POST /api/admin/channels/telegram":()=>Js(n),"DELETE /api/admin/channels/telegram":()=>bi(n),"POST /api/admin/channels/telegram/toggle":()=>yi(n),"POST /api/admin/crons":()=>wi(n),"DELETE /api/admin/crons":()=>ki(n),"POST /api/admin/config/raw":()=>_i(n),"GET /api/admin/tokens":()=>Fs(),"POST /api/admin/tokens":()=>qs(n),"DELETE /api/admin/tokens":()=>Us(n),"POST /api/admin/agents/test":()=>Ws(n),"POST /api/admin/agents/integrations":()=>ni(n),"DELETE /api/admin/agents/integrations":()=>ri(n),"PATCH /api/admin/agents/integrations":()=>oi(n),"PATCH /api/admin/channels/telegram":()=>Vs(n),"POST /api/admin/channels/slack":()=>ui(n),"POST /api/admin/channels/slack/toggle":()=>mi(n),"POST /api/admin/channels/discord":()=>fi(n),"POST /api/admin/channels/discord/toggle":()=>hi(n),"POST /api/admin/channels/gitlab":()=>gi(n),"POST /api/admin/channels/gitlab/toggle":()=>xi(n),"GET /api/admin/channels/whatsapp/state":()=>Oe("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Oe("/webrtc/history"),"POST /api/admin/actions":()=>Oi(n),"DELETE /api/admin/actions":()=>Ni(n),"POST /api/admin/actions/run":()=>Di(n),"GET /api/admin/channels/whatsapp/chats":()=>Oe("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Oe("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>de("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>vi(n),"POST /api/admin/webhooks":()=>si(n),"PATCH /api/admin/webhooks":()=>ii(n),"DELETE /api/admin/webhooks":()=>pi(n),"POST /api/admin/mesh/peers":()=>li(n),"DELETE /api/admin/mesh/peers":()=>ci(n),"POST /api/admin/mesh/toggle":()=>di(n),"GET /api/admin/files":()=>Qs(t),"GET /api/admin/files/read":()=>Zs(t),"PUT /api/admin/files":()=>ei(n),"POST /api/admin/files/skill":()=>ti(n),"DELETE /api/admin/files/skill":()=>ai(n),"POST /api/admin/business/orgchart":()=>Ei(n),"DELETE /api/admin/business/orgchart":()=>Si(n),"POST /api/admin/business/project":()=>Ti(n),"DELETE /api/admin/business/project":()=>Mi(n),"POST /api/admin/business/client":()=>Ai(n),"DELETE /api/admin/business/client":()=>Ci(n),"POST /api/admin/business/contact":()=>Ii(n),"DELETE /api/admin/business/contact":()=>Li(n),"POST /api/admin/boards":()=>$i(n),"DELETE /api/admin/boards":()=>Ri(n),"POST /api/admin/boards/columns":()=>Pi(n),"DELETE /api/admin/boards/columns":()=>ji(n),"POST /api/admin/notifications":()=>Bi(n),"POST /api/admin/screen":()=>zi(n),"POST /api/admin/webhooks/triggers":()=>Fi(n),"POST /api/admin/mesh/health":()=>Hi(n),"GET /api/admin/projects":()=>Oe("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>de("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>de("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>de("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>de("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>de("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>de("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>de("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>de("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Lt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Lt(e,200,i)}catch(n){Lt(e,400,{error:n.message||"admin op failed"})}}function Lt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ds(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 Hs(t){let e=Le(process.cwd(),t);if(!st(e))return[];let a=[];for(let n of Ns(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(En(Le(e,n.name),"utf-8")))}catch{}return a}function Rt(){let t=Le(process.cwd(),"agentx.json");return st(t)?JSON.parse(En(t,"utf-8")):null}function Bs(){let t=Rt();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 b=x.credentials||{},k={};for(let[y,_]of Object.entries(b))typeof _=="string"&&/^[A-Z][A-Z0-9_]*$/.test(_)?k[y]=process.env[_]?"set":"unset":typeof _=="string"&&(k[y]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:b,credStatus:k,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:{}},v=t.notifications||{},T={longTaskThreshold:v.longTaskThreshold??30,destination:v.destination||null,on:{taskComplete:v.on?.taskComplete!==!1,taskError:v.on?.taskError!==!1,taskQueued:!!v.on?.taskQueued},local:Ca(v.local),ntfy:un(t.channels?.ntfy)},E=[];try{E=Hs(".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,crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:T,screen:Xa(t.screen),actions:E}}function zs(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 Fs(){return new ae().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 qs(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 ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Us(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ws(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=te();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 Gs(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=In(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=Le(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=Le(i,"CLAUDE.md");if(!st(c))try{js(i,{recursive:!0}),Sn(c,`# ${a}
4763
+ `;function Tn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_n({peers:a,localToken:n}))}async function An(t,e){let a=Rt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Cn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Ys(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await Ds(t),r={"GET /api/admin/state":()=>Bs(),"POST /api/admin/agents":()=>Gs(n),"PATCH /api/admin/agents":()=>Xs(n),"DELETE /api/admin/agents":()=>Ks(n),"POST /api/admin/agents/access":()=>zs(n),"POST /api/admin/channels/telegram":()=>Js(n),"DELETE /api/admin/channels/telegram":()=>bi(n),"POST /api/admin/channels/telegram/toggle":()=>yi(n),"POST /api/admin/crons":()=>wi(n),"DELETE /api/admin/crons":()=>ki(n),"POST /api/admin/config/raw":()=>_i(n),"GET /api/admin/tokens":()=>Fs(),"POST /api/admin/tokens":()=>qs(n),"DELETE /api/admin/tokens":()=>Us(n),"POST /api/admin/agents/test":()=>Ws(n),"POST /api/admin/agents/integrations":()=>ni(n),"DELETE /api/admin/agents/integrations":()=>ri(n),"PATCH /api/admin/agents/integrations":()=>oi(n),"PATCH /api/admin/channels/telegram":()=>Vs(n),"POST /api/admin/channels/slack":()=>ui(n),"POST /api/admin/channels/slack/toggle":()=>mi(n),"POST /api/admin/channels/discord":()=>fi(n),"POST /api/admin/channels/discord/toggle":()=>hi(n),"POST /api/admin/channels/gitlab":()=>gi(n),"POST /api/admin/channels/gitlab/toggle":()=>xi(n),"GET /api/admin/channels/whatsapp/state":()=>Oe("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Oe("/webrtc/history"),"POST /api/admin/actions":()=>Oi(n),"DELETE /api/admin/actions":()=>Ni(n),"POST /api/admin/actions/run":()=>Di(n),"GET /api/admin/channels/whatsapp/chats":()=>Oe("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Oe("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>de("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>vi(n),"POST /api/admin/webhooks":()=>si(n),"PATCH /api/admin/webhooks":()=>ii(n),"DELETE /api/admin/webhooks":()=>pi(n),"POST /api/admin/mesh/peers":()=>li(n),"DELETE /api/admin/mesh/peers":()=>ci(n),"POST /api/admin/mesh/toggle":()=>di(n),"GET /api/admin/files":()=>Qs(t),"GET /api/admin/files/read":()=>Zs(t),"PUT /api/admin/files":()=>ei(n),"POST /api/admin/files/skill":()=>ti(n),"DELETE /api/admin/files/skill":()=>ai(n),"POST /api/admin/business/orgchart":()=>Ei(n),"DELETE /api/admin/business/orgchart":()=>Si(n),"POST /api/admin/business/project":()=>Ti(n),"DELETE /api/admin/business/project":()=>Mi(n),"POST /api/admin/business/client":()=>Ai(n),"DELETE /api/admin/business/client":()=>Ci(n),"POST /api/admin/business/contact":()=>Ii(n),"DELETE /api/admin/business/contact":()=>Li(n),"POST /api/admin/boards":()=>$i(n),"DELETE /api/admin/boards":()=>Ri(n),"POST /api/admin/boards/columns":()=>Pi(n),"DELETE /api/admin/boards/columns":()=>ji(n),"POST /api/admin/notifications":()=>Bi(n),"POST /api/admin/screen":()=>zi(n),"POST /api/admin/webhooks/triggers":()=>Fi(n),"POST /api/admin/mesh/health":()=>Hi(n),"GET /api/admin/projects":()=>Oe("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>de("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>de("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>de("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>de("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>de("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>de("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>de("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>de("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){Lt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();Lt(e,200,i)}catch(n){Lt(e,400,{error:n.message||"admin op failed"})}}function Lt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ds(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 Hs(t){let e=Le(process.cwd(),t);if(!st(e))return[];let a=[];for(let n of Ns(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(En(Le(e,n.name),"utf-8")))}catch{}return a}function Rt(){let t=Le(process.cwd(),"agentx.json");return st(t)?JSON.parse(En(t,"utf-8")):null}function Bs(){let t=Rt();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||{},k={};for(let[b,E]of Object.entries(v))typeof E=="string"&&/^[A-Z][A-Z0-9_]*$/.test(E)?k[b]=process.env[E]?"set":"unset":typeof E=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,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:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Ca(w.local),ntfy:un(t.channels?.ntfy)},S=[];try{S=Hs(".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,crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:Xa(t.screen),actions:S}}function zs(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 Fs(){return new ae().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 qs(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 ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Us(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ws(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=te();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 Gs(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=In(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=Le(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=Le(i,"CLAUDE.md");if(!st(c))try{js(i,{recursive:!0}),Sn(c,`# ${a}
4764
4764
 
4765
4765
  ${s||"You are "+a+"."}
4766
4766
  `)}catch{}return{summary:l}}function Xs(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=In(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 Ks(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 Js(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 Vs(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 Oe(t){let{url:e,headers:a}=Pt(),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 de(t,e){let{url:a,headers:n}=Pt(),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 Ys(t,e){try{let{url:a,headers:n}=Pt(),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 Pt(){let t="http://127.0.0.1:18800",e={};try{let a=te();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ne(t){let a=Rt()?.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 $t(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Qs(t){let e=$t(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Me(Ne(e));return{agentId:e,...a}}function Zs(t){let e=$t(t,"agent").trim(),a=$t(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return Je(Ne(e),a)}function ei(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=Ve(Ne(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function ti(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=Ye(Ne(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function ai(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=Qe(Ne(e),a);return{summary:`removed skill "${a}"`,...n}}function ni(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 ri(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 oi(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 Mn=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function si(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(!Mn.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 ii(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"&&Mn.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 li(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 ci(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 di(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 pi(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 ui(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 mi(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 fi(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 hi(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 gi(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 xi(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 vi(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-VPPKD4FY.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 bi(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 yi(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 wi(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 ki(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 _i(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=Le(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(st(n))try{Os(n,r)}catch{}Sn(n,JSON.stringify(a,null,2)+`
@@ -6015,7 +6015,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6015
6015
  WHERE ${i.join(" AND ")}
6016
6016
  ORDER BY started_at DESC LIMIT @limit
6017
6017
  `,u=r.db.prepare(c).all(l).map(f=>({...f,plain:Xn(f.error)}));return ue(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return ue(e,200,pl(r.db)),!0;if(n==="activity")return ue(e,200,ul(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=zn(i.searchParams.get("range"));return ue(e,200,Fn(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=zn(i.searchParams.get("range")),c=Fn(r.db,l),p=ml(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 ue(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return ue(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Xn(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(`
6018
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function pl(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=_=>p.length?p[Math.min(p.length-1,Math.floor(p.length*_))].duration_ms:0,f=u(.5),h=u(.95),T=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((_,M)=>_+Nt(M),0),E=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((_,M)=>_+Nt(M),0),g=t.prepare(`
6018
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function pl(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=E=>p.length?p[Math.min(p.length-1,Math.floor(p.length*E))].duration_ms:0,f=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((E,M)=>E+Nt(M),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((E,M)=>E+Nt(M),0),g=t.prepare(`
6019
6019
  SELECT agent_id,
6020
6020
  COUNT(*) AS tasks,
6021
6021
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6033,12 +6033,12 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6033
6033
  WHERE started_at >= ?
6034
6034
  GROUP BY channel
6035
6035
  ORDER BY tasks DESC
6036
- `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(_=>_.agent_id),x=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(_=>_.agent_id)),b=m.filter(_=>!x.has(_)),y=t.prepare(`
6036
+ `).all(a),m=t.prepare("SELECT DISTINCT agent_id FROM usage_daily WHERE day >= date('now', '-7 day')").all().map(E=>E.agent_id),x=new Set(t.prepare("SELECT DISTINCT agent_id FROM task_history WHERE started_at >= ?").all(o).map(E=>E.agent_id)),v=m.filter(E=>!x.has(E)),b=t.prepare(`
6037
6037
  SELECT started_at, agent_id, channel, message_preview, error
6038
6038
  FROM task_history
6039
6039
  WHERE status='error' AND started_at >= ?
6040
6040
  ORDER BY started_at DESC LIMIT 5
6041
- `).all(o).map(_=>({..._,plain:Xn(_.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:T,spendDelta:T-E,idleAgentCount:b.length},perAgent:g,perChannel:d,idleAgents:b,recentErrors:y}}function ul(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(`
6041
+ `).all(o).map(E=>({...E,plain:Xn(E.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:b}}function ul(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(`
6042
6042
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6043
6043
  COUNT(*) AS tasks,
6044
6044
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6073,15 +6073,15 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6073
6073
  FROM usage_daily
6074
6074
  ${a}
6075
6075
  ORDER BY day
6076
- `).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,v=0,T=0,E=0,g={},d={};for(let S of n){let I=Nt(S),R=Un(S.model),P=qn[R],B=(S.tier2_input_tokens||0)/1e6*P.input*.5+(S.tier2_output_tokens||0)/1e6*P.output*.5+(S.tier2_cache_read_tokens||0)/1e6*P.cacheRead*.5+(S.tier2_cache_create_tokens||0)/1e6*P.cacheCreate*.5,oe=(S.input_tokens||0)+(S.tier2_input_tokens||0),z=(S.output_tokens||0)+(S.tier2_output_tokens||0),D=(S.cache_read_tokens||0)+(S.tier2_cache_read_tokens||0),H=(S.cache_create_tokens||0)+(S.tier2_cache_create_tokens||0);u+=I,S.day>=s&&(p+=I,v+=S.tasks||0),S.day>=i&&S.day<s&&(E+=I,T+=S.tasks||0),S.day===r&&(l+=I),S.day===o&&(c+=I),S.day===r&&(f+=B),S.day>=s&&(h+=B);let Z=g[S.day]||(g[S.day]={date:S.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=S.tasks||0,Z.input+=oe,Z.output+=z,Z.cacheRead+=D,Z.cacheCreate+=H,Z.cost+=I,Z.tier2+=B;let F=Z.agents[S.agent_id]||(Z.agents[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});F.tasks+=S.tasks||0,F.cost+=I,F.tier2+=B,F.input+=oe,F.output+=z,F.cacheRead+=D,F.cacheCreate+=H,S.model&&(F.model=S.model);let ee=d[S.agent_id]||(d[S.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:S.model});ee.tasks+=S.tasks||0,ee.cost+=I,ee.tier2+=B,ee.input+=oe,ee.output+=z,ee.cacheRead+=D,ee.cacheCreate+=H,S.model&&(ee.model=S.model)}let m=Object.values(g).sort((S,I)=>S.date<I.date?-1:1),x=0,b=0,k=0,y=0,_=0,M=0;for(let S of m)x+=S.tasks,b+=S.input,k+=S.output,y+=S.cacheRead,_+=S.cacheCreate,M+=S.cost;let C=Object.entries(d).map(([S,I])=>({agent_id:S,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((S,I)=>I.cost-S.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:M,avgDailyRange:m.length?M/m.length:0,tasksRange:x,tokensRange:b+k+y+_,cacheHitRange:y+b>0?y/(y+b):0,costPerTaskRange:x>0?M/x:0,spendDeltaWoW:E>0?(p-E)/E:0,tasksDeltaWoW:T>0?(v-T)/T:0},days:m,perAgent:C}}function ml(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+`
6076
+ `).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,w=0,_=0,S=0,g={},d={};for(let T of n){let I=Nt(T),R=Un(T.model),P=qn[R],B=(T.tier2_input_tokens||0)/1e6*P.input*.5+(T.tier2_output_tokens||0)/1e6*P.output*.5+(T.tier2_cache_read_tokens||0)/1e6*P.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*P.cacheCreate*.5,oe=(T.input_tokens||0)+(T.tier2_input_tokens||0),z=(T.output_tokens||0)+(T.tier2_output_tokens||0),D=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),H=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);u+=I,T.day>=s&&(p+=I,w+=T.tasks||0),T.day>=i&&T.day<s&&(S+=I,_+=T.tasks||0),T.day===r&&(l+=I),T.day===o&&(c+=I),T.day===r&&(f+=B),T.day>=s&&(h+=B);let Z=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=T.tasks||0,Z.input+=oe,Z.output+=z,Z.cacheRead+=D,Z.cacheCreate+=H,Z.cost+=I,Z.tier2+=B;let F=Z.agents[T.agent_id]||(Z.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});F.tasks+=T.tasks||0,F.cost+=I,F.tier2+=B,F.input+=oe,F.output+=z,F.cacheRead+=D,F.cacheCreate+=H,T.model&&(F.model=T.model);let ee=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});ee.tasks+=T.tasks||0,ee.cost+=I,ee.tier2+=B,ee.input+=oe,ee.output+=z,ee.cacheRead+=D,ee.cacheCreate+=H,T.model&&(ee.model=T.model)}let m=Object.values(g).sort((T,I)=>T.date<I.date?-1:1),x=0,v=0,k=0,b=0,E=0,M=0;for(let T of m)x+=T.tasks,v+=T.input,k+=T.output,b+=T.cacheRead,E+=T.cacheCreate,M+=T.cost;let C=Object.entries(d).map(([T,I])=>({agent_id:T,...I,tokens:I.input+I.output+I.cacheRead+I.cacheCreate})).sort((T,I)=>I.cost-T.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:M,avgDailyRange:m.length?M/m.length:0,tasksRange:x,tokensRange:v+k+b+E,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?M/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(w-_)/_:0},days:m,perAgent:C}}function ml(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+`
6077
6077
  `+a.join(`
6078
6078
  `)+`
6079
- `}import{resolve as fl}from"path";import{existsSync as hl}from"fs";import gl from"better-sqlite3";function xl(){let t=fl(process.cwd(),".agentx/intent/ledger.sqlite");if(!hl(t))return null;try{let e=new gl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Kn>6e4&&(Kn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Kn=0;function we(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function vl(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 Jn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=xl();if(!r)return we(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=vl(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}),v=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,T=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),E=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(`
6079
+ `}import{resolve as fl}from"path";import{existsSync as hl}from"fs";import gl from"better-sqlite3";function xl(){let t=fl(process.cwd(),".agentx/intent/ledger.sqlite");if(!hl(t))return null;try{let e=new gl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Kn>6e4&&(Kn=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Kn=0;function we(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function vl(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 Jn(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=xl();if(!r)return we(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=vl(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}),w=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(`
6080
6080
  SELECT COUNT(*) AS n FROM intent_decisions d
6081
6081
  LEFT JOIN intent_resolutions r
6082
6082
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6083
6083
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
6084
- `).get().n;return we(e,200,{since:s??null,eventsBySource:h,totalDecisions:v,decisionsByOutcome:T,totalDivergences:E,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let h=`
6084
+ `).get().n;return we(e,200,{since:s??null,eventsBySource:h,totalDecisions:w,decisionsByOutcome:_,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],f={limit:p};s!==void 0&&(u.push("ts >= @since"),f.since=s),i&&(u.push("source = @source"),f.source=i),l&&(u.push("project = @project"),f.project=l);let h=`
6085
6085
  SELECT id, ts, source, source_event_id, project, subject, intent
6086
6086
  FROM intent_events
6087
6087
  ${u.length?"WHERE "+u.join(" AND "):""}
@@ -7745,18 +7745,18 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7745
7745
  load();
7746
7746
  });
7747
7747
  })();
7748
- `;import{resolve as Bt,join as Pl}from"path";import{existsSync as zt,readdirSync as jl,readFileSync as Ol}from"fs";import Nl from"better-sqlite3";var er=String.raw`[\w.-]+(?:/[\w.-]+)+`,wl=new RegExp(`^(?:chat:)?(${er}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),kl=new RegExp(`^\\[(?:GitLab|GitHub) (${er}) `);function Zn(t){if(!t)return null;let e=t.match(wl);return e?e[1]:null}function Dt(t){if(!t)return null;let e=t.trimStart().match(kl);return e?e[1]:null}function it(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Zn(typeof n?.chatId=="string"?n.chatId:null)??Zn(e)??Dt(a)}function _l(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function lt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var El=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Sl=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Tl=t=>/^issue/i.test(t)?"issue":"mr";function Al(t){let e=t.subject.match(El)??t.inputPreview.trimStart().match(Sl);return e?{kind:Tl(e[1]),n:Number(e[2])}:null}function Cl(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 tr(t){if(!_l(t.projectId))return[];let e=Al(t);return e?[e]:Cl(t.inputPreview)}var Ml=6e4,Il=5*6e4,Ll=40,ar=6,nr=new Map;function rr(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 tr(n)){let s=lt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Ll)return[...e.values()]}}return[...e.values()]}async function or(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=lt(s.project,s.ref),l=nr.get(i);l&&n-l.at<(s.github?Il:Ml)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ar)await Promise.all(o.slice(s,s+ar).map(async i=>{let l=lt(i.project,i.ref),c=null;try{c=i.github?await Rl(i,e,a):await $l(i,e,a)}catch{}nr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function sr(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 $l(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 sr(`${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 Rl(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 sr(`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}function Ft(){let t=Bt(process.cwd(),".agentx/intent/ledger.sqlite");if(!zt(t))return null;try{let e=new Nl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ir>6e4&&(ir=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ir=0;function me(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var $e={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"},opencode:{label:"OpenCode",color:"#57606a"}};function Dl(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in $e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in $e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in $e)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 $e)return s}return"workflow"}return t}function dr(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 Hl(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 pr(t,e,a){return Sa(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 Bl(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:W(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&&!Ht(l))return{id:l,name:l,avatar:W(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ht(r||o||"")){let l=r||o||s,c=e==="mesh.github"?"github":e==="mesh.gitlab"?"gitlab":e==="mesh.a2a"?"a2a":e==="mesh.voice"?"voice":e==="mesh.desktop"?"desktop":"mesh";return{id:l,name:o||r||l,avatar:W(i),kind:c}}}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&&!Ht(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=lr(p);return{id:c,name:l||i||c,avatar:W(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:W(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:W(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:W(i),kind:lr(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:W(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:W(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:W(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:W(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:W(o),kind:"whatsapp"}}}return null}function lr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ht(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 W(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 ur(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}
7748
+ `;import{resolve as Bt,join as Pl}from"path";import{existsSync as zt,readdirSync as jl,readFileSync as Ol}from"fs";import Nl from"better-sqlite3";var er=String.raw`[\w.-]+(?:/[\w.-]+)+`,wl=new RegExp(`^(?:chat:)?(${er}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),kl=new RegExp(`^\\[(?:GitLab|GitHub) (${er}) `);function Zn(t){if(!t)return null;let e=t.match(wl);return e?e[1]:null}function Dt(t){if(!t)return null;let e=t.trimStart().match(kl);return e?e[1]:null}function it(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Zn(typeof n?.chatId=="string"?n.chatId:null)??Zn(e)??Dt(a)}function _l(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function lt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var El=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,Sl=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,Tl=t=>/^issue/i.test(t)?"issue":"mr";function Al(t){let e=t.subject.match(El)??t.inputPreview.trimStart().match(Sl);return e?{kind:Tl(e[1]),n:Number(e[2])}:null}function Cl(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 tr(t){if(!_l(t.projectId))return[];let e=Al(t);return e?[e]:Cl(t.inputPreview)}var Ml=6e4,Il=5*6e4,Ll=40,ar=6,nr=new Map;function rr(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 tr(n)){let s=lt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=Ll)return[...e.values()]}}return[...e.values()]}async function or(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=lt(s.project,s.ref),l=nr.get(i);l&&n-l.at<(s.github?Il:Ml)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=ar)await Promise.all(o.slice(s,s+ar).map(async i=>{let l=lt(i.project,i.ref),c=null;try{c=i.github?await Rl(i,e,a):await $l(i,e,a)}catch{}nr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function sr(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 $l(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 sr(`${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 Rl(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 sr(`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}function Ft(){let t=Bt(process.cwd(),".agentx/intent/ledger.sqlite");if(!zt(t))return null;try{let e=new Nl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-ir>6e4&&(ir=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var ir=0;function me(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var $e={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 Dl(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in $e)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in $e)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in $e)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 $e)return s}return"workflow"}return t}function dr(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 Hl(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 pr(t,e,a){return Sa(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 Bl(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:W(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&&!Ht(l))return{id:l,name:l,avatar:W(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ht(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:W(i),kind:Fl(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&&!Ht(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=lr(p);return{id:c,name:l||i||c,avatar:W(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:W(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:W(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:W(i),kind:lr(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:W(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:W(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:W(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:W(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:W(o),kind:"whatsapp"}}}return null}var zl={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Fl(t,e){let a=zl[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function lr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ht(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 W(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 ur(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}
7749
7749
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
7750
- ${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 zl(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 mr(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7750
+ ${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 ql(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 mr(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7751
7751
  SELECT id, ts, source, project, subject, intent, raw_json
7752
7752
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
7753
- `).all(r),s=new Map,i=new Map;if(o.length>0){let y=o.map(I=>I.id),_=y.map((I,R)=>`@id${R}`).join(","),M=Object.fromEntries(y.map((I,R)=>[`id${R}`,I])),C=t.prepare(`
7753
+ `).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(I=>I.id),E=b.map((I,R)=>`@id${R}`).join(","),M=Object.fromEntries(b.map((I,R)=>[`id${R}`,I])),C=t.prepare(`
7754
7754
  SELECT event_id, decided_at, decided_by, agent_id, outcome, reason
7755
- FROM intent_decisions WHERE event_id IN (${_}) ORDER BY decided_at ASC
7756
- `).all(M);for(let I of C)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let S=t.prepare(`
7755
+ FROM intent_decisions WHERE event_id IN (${E}) ORDER BY decided_at ASC
7756
+ `).all(M);for(let I of C)s.has(I.event_id)||s.set(I.event_id,[]),s.get(I.event_id).push(I);let T=t.prepare(`
7757
7757
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
7758
- FROM intent_resolutions WHERE decision_event_id IN (${_})
7759
- `).all(M);for(let I of S)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],v=e?.business?.contactMap??[],T=St(e?.business??{});for(let y of o){let _=null;try{_=JSON.parse(y.raw_json)}catch{}let M=pr(y.source,_,v),C=ur(y.source,_),S=y.project??it(_,y.subject,C),I=null,R=null;M?(I=M.client,R=M.project||`${M.client}/_chat`):S&&(I=Ge(S,h),R=S);let P=Dl(y.source,y.intent||"",_),B=$e[P]||{label:P,color:"#6b7280"};p.has(P)||p.set(P,{id:P,label:B.label,color:B.color});let oe="__system",z,D=Bl(y.source,y.intent||"",_);if(D){oe=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:W(H),kind:D.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(y.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let Z=`${y.id}|${H.decided_by}`,F=i.get(Z),ee=H.decided_at,pa=F?.resolved_at??null,yt=pa===null,hs=F?.duration_ms??(yt?n-ee:0),gs=yt?"active":F?.status==="error"||F?.status==="fail"?"error":"completed",J,je;if(I)J=I,je=R;else{let wt=T.get(H.agent_id);wt?(J=wt,je=`${wt}/_${y.source}`):(J="unmapped",je=`unmapped/_${y.source}`)}l.has(J)||l.set(J,{id:J,name:J,color:dr(J),projects:[]}),c.has(J)||c.set(J,new Set),c.get(J).add(je),f.push({id:`${y.id}|${H.decided_by}`,agentId:H.agent_id,clientId:J,projectId:je,channelId:P,initiatorId:oe,initiatorKind:z,subject:zl(y.subject),intent:y.intent||"",startedAt:ee,resolvedAt:pa,duration:hs,active:yt,outcome:gs,tokens:0,inputPreview:C,system:Hl(H.agent_id,e)})}}let E=[...l.values()].map(y=>({...y,projects:[...c.get(y.id)||[]].sort()})).sort((y,_)=>y.id.localeCompare(_.id)),g=[],d=new Set;if(e){let y=e.business??{},_=M=>{let C=y.orgChart?.[M]?.role,S=C?y.roles?.[C]?.title:void 0;return typeof S=="string"&&S.trim()?S.trim():void 0};for(let[M,C]of Object.entries(e.agents||{})){let S={id:M,name:C.name||M,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:_(M)};g.push(S),d.add(M)}}for(let y of f)d.has(y.agentId)||(g.push({id:y.agentId,name:y.agentId,tier:"worker",model:"",role:""}),d.add(y.agentId));g.sort((y,_)=>y.id.localeCompare(_.id));let m=[],x=new Set;for(let[y,_]of Object.entries($e))m.push({id:y,label:_.label,color:_.color}),x.add(y);for(let y of p.values())x.has(y.id)||m.push(y);let b=[...u.values()];b.find(y=>y.id==="__system")||b.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:E,agents:g,channels:m,initiators:b,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function qt(t){let e=Ft();if(!e)return null;try{return mr(e.db,xe,t)}finally{e.close()}}function fr(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=Fl(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:dr(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 Fl(t){if(t.clientId!=="unmapped")return t;let e=Dt(t.inputPreview);if(!e)return t;let a=xe?.business?.projects??[];return{...t,projectId:e,clientId:Ge(e,a)}}async function ct(t){let e=xe?.channels?.gitlab,a=await or(rr(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 xe=null;function hr(t){xe=t}async function gr(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ft();if(!n)return me(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=xr(parseInt(r.searchParams.get("hours")||"6",10));me(e,200,await ct(mr(n.db,xe,o)))}catch(r){me(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var ql=5e3;async function Ut(t,e,a,n=qt){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
7758
+ FROM intent_resolutions WHERE decision_event_id IN (${E})
7759
+ `).all(M);for(let I of T)i.set(`${I.decision_event_id}|${I.decision_decided_by}`,I)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],w=e?.business?.contactMap??[],_=St(e?.business??{});for(let b of o){let E=null;try{E=JSON.parse(b.raw_json)}catch{}let M=pr(b.source,E,w),C=ur(b.source,E),T=b.project??it(E,b.subject,C),I=null,R=null;M?(I=M.client,R=M.project||`${M.client}/_chat`):T&&(I=Ge(T,h),R=T);let P=Dl(b.source,b.intent||"",E),B=$e[P]||{label:P,color:"#6b7280"};p.has(P)||p.set(P,{id:P,label:B.label,color:B.color});let oe="__system",z,D=Bl(b.source,b.intent||"",E);if(D){oe=D.id,z=D.kind;let H=M?.displayName||D.name;(!u.has(D.id)||M?.displayName)&&u.set(D.id,{id:D.id,name:H,avatar:W(H),kind:D.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let H of s.get(b.id)??[]){if(H.outcome!=="dispatched"||!H.agent_id)continue;let Z=`${b.id}|${H.decided_by}`,F=i.get(Z),ee=H.decided_at,pa=F?.resolved_at??null,yt=pa===null,hs=F?.duration_ms??(yt?n-ee:0),gs=yt?"active":F?.status==="error"||F?.status==="fail"?"error":"completed",J,je;if(I)J=I,je=R;else{let wt=_.get(H.agent_id);wt?(J=wt,je=`${wt}/_${b.source}`):(J="unmapped",je=`unmapped/_${b.source}`)}l.has(J)||l.set(J,{id:J,name:J,color:dr(J),projects:[]}),c.has(J)||c.set(J,new Set),c.get(J).add(je),f.push({id:`${b.id}|${H.decided_by}`,agentId:H.agent_id,clientId:J,projectId:je,channelId:P,initiatorId:oe,initiatorKind:z,subject:ql(b.subject),intent:b.intent||"",startedAt:ee,resolvedAt:pa,duration:hs,active:yt,outcome:gs,tokens:0,inputPreview:C,system:Hl(H.agent_id,e)})}}let S=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,E)=>b.id.localeCompare(E.id)),g=[],d=new Set;if(e){let b=e.business??{},E=M=>{let C=b.orgChart?.[M]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[M,C]of Object.entries(e.agents||{})){let T={id:M,name:C.name||M,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:E(M)};g.push(T),d.add(M)}}for(let b of f)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,E)=>b.id.localeCompare(E.id));let m=[],x=new Set;for(let[b,E]of Object.entries($e))m.push({id:b,label:E.label,color:E.color}),x.add(b);for(let b of p.values())x.has(b.id)||m.push(b);let v=[...u.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:S,agents:g,channels:m,initiators:v,dispatches:f,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function qt(t){let e=Ft();if(!e)return null;try{return mr(e.db,xe,t)}finally{e.close()}}function fr(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=Ul(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:dr(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 Ul(t){if(t.clientId!=="unmapped")return t;let e=Dt(t.inputPreview);if(!e)return t;let a=xe?.business?.projects??[];return{...t,projectId:e,clientId:Ge(e,a)}}async function ct(t){let e=xe?.channels?.gitlab,a=await or(rr(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 xe=null;function hr(t){xe=t}async function gr(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ft();if(!n)return me(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=xr(parseInt(r.searchParams.get("hours")||"6",10));me(e,200,await ct(mr(n.db,xe,o)))}catch(r){me(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Wl=5e3;async function Ut(t,e,a,n=qt){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
7760
7760
 
7761
7761
  `);let r=new URL(t.url||"/","http://_"),o=xr(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
7762
7762
 
@@ -7769,7 +7769,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
7769
7769
  `)}catch(p){e.write(`event: error
7770
7770
  data: ${JSON.stringify({error:p?.message??String(p)})}
7771
7771
 
7772
- `)}let c=Date.now();for(;!s&&Date.now()-c<ql;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function xr(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ul(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Bt(process.cwd(),".agentx/task-history",t,n);if(!zt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Bt(process.cwd(),".agentx/task-history",t,o);return zt(s)?cr(s,e,a):null}return cr(r,e,a)}function cr(t,e,a){let n=null,r=1/0;for(let o of jl(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Ol(Pl(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 vr(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 me(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Ft();if(!l)return me(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 me(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 me(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=ur(c.source,f),v=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,T=null,E=null;if(p.agent_id){let k=Ul(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(T=k.responseText);let y=k.transcript;Array.isArray(y)&&(E=y.length)}}let g=xe?.business?.projects??[],d=xe?.business?.contactMap??[],m=St(xe?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},b=pr(c.source,f,d);if(b)x={client:b.client,project:b.project||`${b.client}/_chat`,via:`contactMap (channel=${b.channel??"*"}${b.username?` username=${b.username}`:""}${b.chatId?` chatId=${b.chatId}`:""})`};else if(c.project||it(f,c.subject,h)){let k=c.project||it(f,c.subject,h);x={client:Ge(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}me(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:v,response:T,transcriptLen:E,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){me(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Kl,readFileSync as Jl}from"fs";import{resolve as yr}from"path";kt();function br(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=Wl.replace(/__AGENT_ID__/g,j(e));return L({title:`AgentX \xB7 ${j(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${j(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Gl,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>${Xl}</script>`})}var Wl=`
7772
+ `)}let c=Date.now();for(;!s&&Date.now()-c<Wl;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function xr(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Gl(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Bt(process.cwd(),".agentx/task-history",t,n);if(!zt(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Bt(process.cwd(),".agentx/task-history",t,o);return zt(s)?cr(s,e,a):null}return cr(r,e,a)}function cr(t,e,a){let n=null,r=1/0;for(let o of jl(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Ol(Pl(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 vr(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 me(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Ft();if(!l)return me(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 me(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 me(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=ur(c.source,f),w=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 k=Gl(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(_=k.responseText);let b=k.transcript;Array.isArray(b)&&(S=b.length)}}let g=xe?.business?.projects??[],d=xe?.business?.contactMap??[],m=St(xe?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=pr(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||it(f,c.subject,h)){let k=c.project||it(f,c.subject,h);x={client:Ge(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=m.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}me(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:w,response:_,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){me(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Vl,readFileSync as Yl}from"fs";import{resolve as yr}from"path";kt();function br(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=Xl.replace(/__AGENT_ID__/g,j(e));return L({title:`AgentX \xB7 ${j(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${j(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Kl,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>${Jl}</script>`})}var Xl=`
7773
7773
  <!-- Breadcrumb -->
7774
7774
  <div class="ax-crumb">
7775
7775
  <a href="/admin">Settings</a>
@@ -8358,7 +8358,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
8358
8358
  </div>
8359
8359
  </div>
8360
8360
  </div>
8361
- `,Gl=`
8361
+ `,Kl=`
8362
8362
  /* Agent-specific layout + legacy styles for bits the migration left in
8363
8363
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
8364
8364
  * primitives live in components.css.ts. */
@@ -8477,7 +8477,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
8477
8477
 
8478
8478
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
8479
8479
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
8480
- `,Xl=`
8480
+ `,Jl=`
8481
8481
  const $ = (id) => document.getElementById(id);
8482
8482
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8483
8483
 
@@ -9333,15 +9333,15 @@ document.addEventListener('keydown', (e) => {
9333
9333
  /* ===== Boot ===== */
9334
9334
  initOptsToggles();
9335
9335
  loadAgent();
9336
- `;function wr(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(br({agentId:a,peers:n,localToken:r}))}async function kr(t,e,a){try{let n=t.method==="GET"?void 0:await xc(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){dt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>De(i),"PATCH ":()=>Vl(i,n),"PATCH capability":()=>Zl(i,n),"POST mcp":()=>Yl(i,n),"DELETE mcp":()=>Ql(i,n),"GET identity":()=>ec(i),"GET identity/file":()=>tc(i,String(o.path||"")),"PUT identity/file":()=>ac(i,n),"GET skills":()=>nc(i),"POST skills":()=>rc(i,n),"DELETE skills":()=>oc(i,n),"GET skills/tree":()=>sc(i,String(o.slug||"")),"GET skills/file":()=>ic(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>lc(i,n),"GET skills/deps":()=>cc(i,String(o.slug||"")),"POST skills/install":()=>dc(i,n,t),"POST skills/deps":()=>pc(i,n,t),"GET channels":()=>uc(i),"GET activity":()=>mc(i,t),"GET handovers":()=>fc(i),"POST handovers":()=>hc(i,n),"DELETE handovers":()=>gc(n)}[c];if(!u){dt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();dt(e,200,f)}catch(n){dt(e,400,{error:n?.message||"agent op failed"})}}function _r(){let t=yr(process.cwd(),"agentx.json");return Kl(t)?JSON.parse(Jl(t,"utf-8")):null}function G(t){let e=_r();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 De(t){let{def:e,cfg:a}=G(t),n=e.workspace?Me(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 Vl(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:De(t)}}function Yl(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:De(t)}}function Ql(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:De(t)}}function Zl(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:De(t)}}function ec(t){let{def:e}=G(t);return Me(e.workspace)}function tc(t,e){if(!e)throw new Error("path query param required");let{def:a}=G(t);return Je(a.workspace,e)}function ac(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=G(t);return Ve(n.workspace,a,String(e?.content??""))}function nc(t){let{def:e}=G(t),a=Me(e.workspace);return{skills:a.skills,workspace:a.workspace}}function rc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=G(t);return Ye(n.workspace,a,{title:e?.title,content:e?.content})}function oc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=G(t);return Qe(n.workspace,a)}function sc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=G(t),n=Ua(a.workspace,e),r=Ze(a.workspace,e);return{slug:e,tree:n,deps:r}}function ic(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=G(t);return Wa(n.workspace,e,a)}function lc(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=G(t);return Ga(r.workspace,a,n,String(e?.content??""))}function cc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=G(t);return Ze(a.workspace,e)}async function dc(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=Er(e?.worker),{def:o}=G(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(`
9337
- `);return Sr(a,r,s,`install-${n}:${Date.now()}`)}async function pc(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Er(e?.worker),{def:o}=G(t),s=Ze(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=yr(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(`
9338
- `);return Sr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Er(t){if(t&&typeof t=="string")return t;let e=te();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Sr(t,e,a,n){let r=te(),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 uc(t){let e=_r(),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 mc(t,e){try{let n=(te().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 Wt(){return new ha}function fc(t){let e=Wt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function hc(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=Wt().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 gc(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:Wt().remove(e,a,n)?"Released":"No active handover for that chat"}}function dt(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)})}var ke={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 Tr=[{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 Gt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ke)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9336
+ `;function wr(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(br({agentId:a,peers:n,localToken:r}))}async function kr(t,e,a){try{let n=t.method==="GET"?void 0:await bc(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){dt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>De(i),"PATCH ":()=>Ql(i,n),"PATCH capability":()=>tc(i,n),"POST mcp":()=>Zl(i,n),"DELETE mcp":()=>ec(i,n),"GET identity":()=>ac(i),"GET identity/file":()=>nc(i,String(o.path||"")),"PUT identity/file":()=>rc(i,n),"GET skills":()=>oc(i),"POST skills":()=>sc(i,n),"DELETE skills":()=>ic(i,n),"GET skills/tree":()=>lc(i,String(o.slug||"")),"GET skills/file":()=>cc(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>dc(i,n),"GET skills/deps":()=>pc(i,String(o.slug||"")),"POST skills/install":()=>uc(i,n,t),"POST skills/deps":()=>mc(i,n,t),"GET channels":()=>fc(i),"GET activity":()=>hc(i,t),"GET handovers":()=>gc(i),"POST handovers":()=>xc(i,n),"DELETE handovers":()=>vc(n)}[c];if(!u){dt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();dt(e,200,f)}catch(n){dt(e,400,{error:n?.message||"agent op failed"})}}function _r(){let t=yr(process.cwd(),"agentx.json");return Vl(t)?JSON.parse(Yl(t,"utf-8")):null}function G(t){let e=_r();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 De(t){let{def:e,cfg:a}=G(t),n=e.workspace?Me(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 Ql(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:De(t)}}function Zl(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:De(t)}}function ec(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:De(t)}}function tc(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:De(t)}}function ac(t){let{def:e}=G(t);return Me(e.workspace)}function nc(t,e){if(!e)throw new Error("path query param required");let{def:a}=G(t);return Je(a.workspace,e)}function rc(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=G(t);return Ve(n.workspace,a,String(e?.content??""))}function oc(t){let{def:e}=G(t),a=Me(e.workspace);return{skills:a.skills,workspace:a.workspace}}function sc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=G(t);return Ye(n.workspace,a,{title:e?.title,content:e?.content})}function ic(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=G(t);return Qe(n.workspace,a)}function lc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=G(t),n=Ua(a.workspace,e),r=Ze(a.workspace,e);return{slug:e,tree:n,deps:r}}function cc(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=G(t);return Wa(n.workspace,e,a)}function dc(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=G(t);return Ga(r.workspace,a,n,String(e?.content??""))}function pc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=G(t);return Ze(a.workspace,e)}async function uc(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=Er(e?.worker),{def:o}=G(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(`
9337
+ `);return Sr(a,r,s,`install-${n}:${Date.now()}`)}async function mc(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Er(e?.worker),{def:o}=G(t),s=Ze(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=yr(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(`
9338
+ `);return Sr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Er(t){if(t&&typeof t=="string")return t;let e=te();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Sr(t,e,a,n){let r=te(),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 fc(t){let e=_r(),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 hc(t,e){try{let n=(te().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 Wt(){return new ha}function gc(t){let e=Wt(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function xc(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=Wt().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 vc(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:Wt().remove(e,a,n)?"Released":"No active handover for that chat"}}function dt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function bc(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 ke={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 Tr=[{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 Gt(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(ke)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9339
9339
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9340
9340
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9341
9341
  <section id="statstrip" class="ax-statstrip"></section>
9342
9342
  <main id="grid" class="ax-live__body"></main>
9343
9343
  </div>
9344
- `;return L({title:`${ke.brand} \xB7 ${ke.subtitle}`,activeTab:"live",subtitle:ke.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:vc,scripts:e+`<script>${bc}</script>`,headExtras:`<script>
9344
+ `;return L({title:`${ke.brand} \xB7 ${ke.subtitle}`,activeTab:"live",subtitle:ke.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:yc,scripts:e+`<script>${wc}</script>`,headExtras:`<script>
9345
9345
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9346
9346
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9347
9347
  document.addEventListener('DOMContentLoaded', () => {
@@ -9352,7 +9352,7 @@ loadAgent();
9352
9352
  extras.innerHTML = ${JSON.stringify(a)};
9353
9353
  right.insertBefore(extras, right.firstChild);
9354
9354
  });
9355
- </script>`})}var vc=`
9355
+ </script>`})}var yc=`
9356
9356
  /* --- Page frame --- */
9357
9357
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9358
9358
 
@@ -9559,7 +9559,7 @@ loadAgent();
9559
9559
  border-top-color: var(--ax-accent); border-radius: 50%;
9560
9560
  animation: ax-spin 800ms linear infinite; display: inline-block;
9561
9561
  }
9562
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,bc=`
9562
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,wc=`
9563
9563
  'use strict';
9564
9564
 
9565
9565
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -11364,12 +11364,12 @@ window.MXD=(function(){
11364
11364
  }
11365
11365
  load();setInterval(load,5000);
11366
11366
  })();
11367
- </script>`;var Y={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 Q(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var yc=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],wc=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],kc=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Or(t){let e=et({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+tt([{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">
11367
+ </script>`;var Y={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 Q(t,e,a,n,r=""){return U({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var kc=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],_c=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],Ec=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Or(t){let e=et({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+tt([{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">
11368
11368
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11369
- ${wc.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("")}
11369
+ ${_c.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("")}
11370
11370
  </div>
11371
11371
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11372
- ${kc.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11372
+ ${Ec.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11373
11373
  </div>
11374
11374
  </div>
11375
11375
  <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">
@@ -11422,7 +11422,7 @@ window.MXD=(function(){
11422
11422
  <section class="mx-section" aria-labelledby="mx-routines-title">
11423
11423
  ${Q(Y.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>')}
11424
11424
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11425
- ${yc.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11425
+ ${kc.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11426
11426
  </div>
11427
11427
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11428
11428
  </section>
@@ -11463,7 +11463,7 @@ window.MXD=(function(){
11463
11463
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11464
11464
  </header>
11465
11465
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11466
- </aside>`;return L({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ar+$r,scripts:Cr+_c+Mr+Ir+Rr+Lr+jr})}var _c=`<script>
11466
+ </aside>`;return L({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ar+$r,scripts:Cr+Sc+Mr+Ir+Rr+Lr+jr})}var Sc=`<script>
11467
11467
  (function(){
11468
11468
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11469
11469
  var range=document.getElementById('mx-range');
@@ -11491,7 +11491,7 @@ window.MXD=(function(){
11491
11491
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11492
11492
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11493
11493
  })();
11494
- </script>`;async function Nr(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 Ec(s,e.days)}function Ec(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,v=0;for(let{node:E,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,v+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:E.name,nodeUrl:E.url});for(let d of g.threads)l.push({...d,node:E.name,nodeUrl:E.url})}let T=t.filter(E=>E.data).map(E=>E.data.since).filter(E=>Number.isFinite(E));return{generatedAt:Date.now(),windowDays:e,since:T.length?Math.min(...T):Date.now()-e*864e5,nodes:t.map(E=>({name:E.node.name,url:E.node.url,ok:!!E.data,error:E.error,runs:E.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((E,g)=>E.day.localeCompare(g.day)),origins:[...r.values()].map(E=>({...E,hours:Math.round(E.hours*100)/100})).sort((E,g)=>g.runs-E.runs),causes:[...o.values()].sort((E,g)=>g.count-E.count),jobs:i.sort((E,g)=>g.hours-E.hours),threads:l.sort((E,g)=>g.lastAt-g.firstAt-(E.lastAt-E.firstAt)||g.runs-E.runs),rotations:{total:c,byReason:[...s.entries()].map(([E,g])=>({reason:E,count:g})).sort((E,g)=>g.count-E.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:h,tracesWithSteps:v}}}async function Dr(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 Hr(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 Sc(s,e.day)}function Sc(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 Br(t={}){let e=`
11494
+ </script>`;async function Nr(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 Tc(s,e.days)}function Tc(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,w=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,w+=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:w}}}async function Dr(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 Hr(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 Ac(s,e.day)}function Ac(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 Br(t={}){let e=`
11495
11495
  <select id="boardPicker" title="Switch board"></select>
11496
11496
  <div class="search">
11497
11497
  <span class="icon">\u2315</span>
@@ -11592,7 +11592,7 @@ window.MXD=(function(){
11592
11592
  </footer>
11593
11593
  </div>
11594
11594
  </div>
11595
- <script src="/sortable.min.js"></script>`;return L({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Tc,scripts:`<script>${Ac}</script>`,headExtras:`<script>
11595
+ <script src="/sortable.min.js"></script>`;return L({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:Cc,scripts:`<script>${Mc}</script>`,headExtras:`<script>
11596
11596
  // The boards page has its own connection dot + wants body height:100%
11597
11597
  // for the full-viewport kanban layout. Inject the dot into the topbar
11598
11598
  // and override body height at runtime so the shared shell doesn't
@@ -11608,7 +11608,7 @@ window.MXD=(function(){
11608
11608
  right.insertBefore(dot, right.firstChild);
11609
11609
  }
11610
11610
  });
11611
- </script>`})}var Tc=`
11611
+ </script>`})}var Cc=`
11612
11612
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11613
11613
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11614
11614
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -11861,7 +11861,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
11861
11861
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
11862
11862
  .draft-box .draft-row .hint.err { color: var(--red); }
11863
11863
  .draft-box .draft-row .hint.ok { color: var(--green); }
11864
- `,Ac=`
11864
+ `,Mc=`
11865
11865
  'use strict';
11866
11866
  const state = {
11867
11867
  boards: [], current: null, items: {},
@@ -12916,7 +12916,7 @@ function appendEvents(events) {
12916
12916
  loadBoards().catch(e => toast('Init failed: ' + e.message));
12917
12917
  `;function zr(t={}){let a=`<h1>Plain-English glossary</h1>
12918
12918
  <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>
12919
- ${Tr.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${j(n.alias)}</span>`:"";return`<article class="term"><h3>${j(n.term)}${r}</h3><p>${j(n.definition)}</p></article>`}).join("")}`;return L({title:`${ke.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Cc})}var Cc=`
12919
+ ${Tr.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${j(n.alias)}</span>`:"";return`<article class="term"><h3>${j(n.term)}${r}</h3><p>${j(n.definition)}</p></article>`}).join("")}`;return L({title:`${ke.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Ic})}var Ic=`
12920
12920
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
12921
12921
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
12922
12922
  .lead {
@@ -13023,7 +13023,7 @@ article.term p {
13023
13023
  </aside>
13024
13024
  </div>
13025
13025
 
13026
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return L({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Mc,scripts:`<script>${V({workflowHealth:Ea})}${Ic}</script>`})}var Mc=`
13026
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return L({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Lc,scripts:`<script>${V({workflowHealth:Ea})}${$c}</script>`})}var Lc=`
13027
13027
  .ax-wf__root {
13028
13028
  display: grid;
13029
13029
  grid-template-columns: 340px 1fr;
@@ -13407,7 +13407,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13407
13407
  font-size: 12px; z-index: 50;
13408
13408
  }
13409
13409
  .hint { color: var(--ax-muted); font-size: 11px; }
13410
- `,Ic=`
13410
+ `,$c=`
13411
13411
  (() => {
13412
13412
  const $ = (sel) => document.querySelector(sel)
13413
13413
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14240,7 +14240,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14240
14240
  <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>
14241
14241
  <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>
14242
14242
  </section>
14243
- </div>`;return L({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Lc,scripts:`<script>${$c}</script>`})}var Lc=`
14243
+ </div>`;return L({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Rc,scripts:`<script>${Pc}</script>`})}var Rc=`
14244
14244
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14245
14245
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14246
14246
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14266,7 +14266,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14266
14266
  .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); }
14267
14267
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14268
14268
  .ax-proc__link:hover { text-decoration: underline; }
14269
- `,$c=`
14269
+ `,Pc=`
14270
14270
  (function(){
14271
14271
  function $(sel){ return document.querySelector(sel) }
14272
14272
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14409,7 +14409,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14409
14409
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14410
14410
  </div>
14411
14411
  </footer>
14412
- </div>`;return L({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Rc,scripts:`<script>${Pc}</script>`})}var Rc=`
14412
+ </div>`;return L({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:jc,scripts:`<script>${Oc}</script>`})}var jc=`
14413
14413
  /* The shell gives <main> no padding, so page content butted straight against
14414
14414
  the sticky topbar. Breathe. */
14415
14415
  .ax-task-page {
@@ -14551,7 +14551,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14551
14551
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14552
14552
  }
14553
14553
 
14554
- `,Pc=`
14554
+ `,Oc=`
14555
14555
  (function () {
14556
14556
  var root = document.querySelector('.ax-task-page');
14557
14557
  if (!root) return;
@@ -14965,7 +14965,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14965
14965
  <div class="ax-history__list" id="hist-list">
14966
14966
  <div class="ax-history__empty">loading\u2026</div>
14967
14967
  </div>
14968
- </div>`;return L({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:jc,scripts:`<script>${Oc}</script>`})}var jc=`
14968
+ </div>`;return L({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Nc,scripts:`<script>${Dc}</script>`})}var Nc=`
14969
14969
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
14970
14970
  flush against the sticky topbar. */
14971
14971
  .ax-history {
@@ -15017,7 +15017,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15017
15017
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15018
15018
  }
15019
15019
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15020
- `,Oc=`
15020
+ `,Dc=`
15021
15021
  (function () {
15022
15022
  var root = document.querySelector('.ax-history');
15023
15023
  if (!root) return;
@@ -15117,11 +15117,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15117
15117
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15118
15118
  });
15119
15119
  })();
15120
- `;function Xr(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"])?$(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 Re(t,e,l=>Gr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Dc(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return $(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return $(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Re(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return $(e,200,{ok:!0,emission:c})}):$(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"])?$(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Re(t,e,l=>{try{let c=a.layouts.save(s,l);return $(e,200,{layout:c})}catch(c){return $(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Re(t,e,l=>{let c=_t.safeParse(l);if(!c.success)return $(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=Et(c.data).map(u=>({path:"",message:u}));return $(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?$(e,200,{workflow:l}):$(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 Re(t,e,p=>Gr(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),$(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return $(e,404,{error:"unknown workflows endpoint",path:n})}var Nc=["mesh"];function Gr(t,e,a,n){let r=_t.safeParse(a);if(!r.success)return $(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=Et(o);if(s.length>0)return $(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return $(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return $(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 Nc)!(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 $(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)),$(t,200,{workflow:i})}function Dc(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 $(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 $(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return $(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Re(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?$(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?$(e,200,{ok:!0,runId:l,status:p}):$(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return Hc(t,e,a,l);let c=a.runs.get(l);return c?$(e,200,{run:c}):$(e,404,{error:"run not found"})}return $(e,404,{error:"unknown runs endpoint"})}function Hc(t,e,a,n){let r=a.runs.get(n);if(!r)return $(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)}
15120
+ `;function Xr(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"])?$(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 Re(t,e,l=>Gr(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Bc(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return $(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return $(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?Re(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return $(e,200,{ok:!0,emission:c})}):$(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"])?$(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?Re(t,e,l=>{try{let c=a.layouts.save(s,l);return $(e,200,{layout:c})}catch(c){return $(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?Re(t,e,l=>{let c=_t.safeParse(l);if(!c.success)return $(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=Et(c.data).map(u=>({path:"",message:u}));return $(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?$(e,200,{workflow:l}):$(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 Re(t,e,p=>Gr(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),$(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return $(e,404,{error:"unknown workflows endpoint",path:n})}var Hc=["mesh"];function Gr(t,e,a,n){let r=_t.safeParse(a);if(!r.success)return $(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=Et(o);if(s.length>0)return $(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return $(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return $(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 Hc)!(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 $(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)),$(t,200,{workflow:i})}function Bc(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 $(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 $(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return $(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return Re(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?$(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?$(e,200,{ok:!0,runId:l,status:p}):$(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return zc(t,e,a,l);let c=a.runs.get(l);return c?$(e,200,{run:c}):$(e,404,{error:"run not found"})}return $(e,404,{error:"unknown runs endpoint"})}function zc(t,e,a,n){let r=a.runs.get(n);if(!r)return $(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)}
15121
15121
 
15122
15122
  `);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)}
15123
15123
 
15124
- `)}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 Re(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){$(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{$(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{$(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>$(e,400,{error:"body read failed",message:r.message})),!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as Md}from"fs";import{createRequire as Id}from"module";import{deflateSync as Bc}from"zlib";var zc=[41,121,255],Fc=[255,255,255],Kr=new Map;function Kt(t){let e=Kr.get(t);return e||(e=Uc(t,qc(t)),Kr.set(t,e)),e}function qc(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?Fc:zc;a.set(c,o*e+1+s*3)}return a}function Uc(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]),Xt("IHDR",a),Xt("IDAT",Bc(e)),Xt("IEND",Buffer.alloc(0))])}function Xt(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(Gc(n)),Buffer.concat([a,n,r])}var Wc=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 Gc(t){let e=4294967295;for(let a of t)e=Wc[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function pt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Xc(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:pt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:pt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:pt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Kc(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:pt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Jc=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Jr(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let h=Vc(s.searchParams.get("timezone")),v=await o.snapshot({date:Yc(h),timezone:h});return a==="/api/app/activity"?ce(e,200,{ts:v.ts,tasks:Kc(v.nodes)}):ce(e,200,{ts:v.ts,nodes:v.nodes.map(Xc)})}if(n==="GET"&&a==="/api/app/approvals")return ce(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Jc);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await _e(t)}catch(h){return ce(e,400,{error:h.message})}let p=He(c.node);if(!p)return ce(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let h=He(c.taskId);if(!h)return ce(e,400,{error:"taskId is required"});let v=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,v,{reason:`cancelled by ${u}`});else{let T=He(c.message);if(!T)return ce(e,400,{error:"message is required"});f=await o.nodePost(p,v,{message:T,sender:u})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=He(c.cronId);if(!h||typeof c.enabled!="boolean")return ce(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=He(c.key),v=c.action;if(!h||v!=="yes"&&v!=="no"&&v!=="later")return ce(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,h,v,u)}return ce(e,f.status,f.body)}function He(t){return typeof t=="string"?t.trim():""}function Vc(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Yc(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function _e(t,e=16*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").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ce(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Qc=2048,Vr=/^[A-Za-z0-9_-]{8,256}$/;async function Yr(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 X(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):Zc()});if(n==="GET"&&a==="/api/app/alerts")return X(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 X(e,404,{error:"not found"});if(!s||l)return X(e,503,{error:l});let c;try{c=await _e(t)}catch(h){return X(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(se).filter(g=>c[se[g].field]!==void 0),v=h.map(g=>se[g].field).join(", "),T=Object.values(se).map(g=>g.field).join(" or ");if(h.length===0)return X(e,400,{error:`send ${T}, true or false`});if(h.some(g=>typeof c[se[g].field]!="boolean"))return X(e,400,{error:`${v} must be true or false`});let E={};for(let g of h)s.prefs.set(r.id,g,c[se[g].field]),E[se[g].field]=c[se[g].field];return X(e,200,{ok:!0,...E})}let p=ed(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return X(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return X(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Vr.test(u)||typeof f!="string"||!Vr.test(f)?X(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?X(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}),X(e,200,{ok:!0}))}function Zc(){let t={};for(let e of Object.values(se))t[e.field]=e.default;return t}function ed(t,e){if(typeof t!="string"||t.length>Qc)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 X(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zr=50,td=280;async function eo(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=ad(await o.recent(Zr))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Qr(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Qr(e,404,{error:"not found"})}function to(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||q(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=Ce();return r?new Ja(r):null}}}function ad(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:Jt(typeof n.summary=="string"?n.summary:"",td),by:typeof n.agentId=="string"?Jt(n.agentId,100):null,node:Jt(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,Zr)}function Jt(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Qr(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var nd=50,ao=4,no=500;function rd(t){let e={channel:"app",chatId:t.chatId};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 ro(t,e,a,n){let{path:r,body:o}=rd(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let v=u!=="done",T=i?{text:ya(f,v),artifacts:[]}:ba(f,ge.perMessage,v),{cleanText:E,ui:g}=u==="done"?Ta(T.text):{cleanText:T.text,ui:void 0},d=i?void 0:sd(g);return{status:u,text:E,tools:l,files:T.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}`}:{}},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 id(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<nd){let v={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(v),h.id&&c.set(String(h.id),v)}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,od(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 od(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function sd(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,ao).map(s=>s.slice(0,no));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,ao).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,no)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*id(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,`
15124
+ `)}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 Re(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){$(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{$(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{$(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>$(e,400,{error:"body read failed",message:r.message})),!0}function $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as $d}from"fs";import{createRequire as Rd}from"module";import{deflateSync as Fc}from"zlib";var qc=[41,121,255],Uc=[255,255,255],Kr=new Map;function Kt(t){let e=Kr.get(t);return e||(e=Gc(t,Wc(t)),Kr.set(t,e)),e}function Wc(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?Uc:qc;a.set(c,o*e+1+s*3)}return a}function Gc(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]),Xt("IHDR",a),Xt("IDAT",Fc(e)),Xt("IEND",Buffer.alloc(0))])}function Xt(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(Kc(n)),Buffer.concat([a,n,r])}var Xc=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 Kc(t){let e=4294967295;for(let a of t)e=Xc[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function pt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Jc(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:pt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:pt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:pt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Vc(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:pt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Yc=/^\/api\/app\/tasks\/(cancel|followup)$/;async function Jr(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let h=Qc(s.searchParams.get("timezone")),w=await o.snapshot({date:Zc(h),timezone:h});return a==="/api/app/activity"?ce(e,200,{ts:w.ts,tasks:Vc(w.nodes)}):ce(e,200,{ts:w.ts,nodes:w.nodes.map(Jc)})}if(n==="GET"&&a==="/api/app/approvals")return ce(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Yc);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await _e(t)}catch(h){return ce(e,400,{error:h.message})}let p=He(c.node);if(!p)return ce(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,f;if(i){let h=He(c.taskId);if(!h)return ce(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")f=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=He(c.message);if(!_)return ce(e,400,{error:"message is required"});f=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")f=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")f=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=He(c.cronId);if(!h||typeof c.enabled!="boolean")return ce(e,400,{error:"cronId and enabled (true or false) are required"});f=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=He(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return ce(e,400,{error:"key and action (yes, no or later) are required"});f=await o.decide(p,h,w,u)}return ce(e,f.status,f.body)}function He(t){return typeof t=="string"?t.trim():""}function Qc(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Zc(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function _e(t,e=16*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").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ce(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var ed=2048,Vr=/^[A-Za-z0-9_-]{8,256}$/;async function Yr(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 X(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):td()});if(n==="GET"&&a==="/api/app/alerts")return X(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 X(e,404,{error:"not found"});if(!s||l)return X(e,503,{error:l});let c;try{c=await _e(t)}catch(h){return X(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(se).filter(g=>c[se[g].field]!==void 0),w=h.map(g=>se[g].field).join(", "),_=Object.values(se).map(g=>g.field).join(" or ");if(h.length===0)return X(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[se[g].field]!="boolean"))return X(e,400,{error:`${w} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[se[g].field]),S[se[g].field]=c[se[g].field];return X(e,200,{ok:!0,...S})}let p=ad(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return X(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return X(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Vr.test(u)||typeof f!="string"||!Vr.test(f)?X(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?X(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}),X(e,200,{ok:!0}))}function td(){let t={};for(let e of Object.values(se))t[e.field]=e.default;return t}function ad(t,e){if(typeof t!="string"||t.length>ed)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 X(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Zr=50,nd=280;async function eo(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=rd(await o.recent(Zr))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Qr(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Qr(e,404,{error:"not found"})}function to(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||q(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=Ce();return r?new Ja(r):null}}}function rd(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:Jt(typeof n.summary=="string"?n.summary:"",nd),by:typeof n.agentId=="string"?Jt(n.agentId,100):null,node:Jt(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,Zr)}function Jt(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Qr(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var od="operator",sd=50,ao=4,no=500;function id(t){let e={channel:"app",chatId:t.chatId,sender:od,...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 ro(t,e,a,n){let{path:r,body:o}=id(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let w=u!=="done",_=i?{text:ya(f,w),artifacts:[]}:ba(f,ge.perMessage,w),{cleanText:S,ui:g}=u==="done"?Ta(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:cd(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}`}:{}},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 dd(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<sd){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}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,ld(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 ld(t){let e=String(t||"The agent could not answer.");return e.startsWith("__queued__")?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function cd(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,ao).map(s=>s.slice(0,no));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,ao).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,no)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*dd(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,`
15125
15125
  `);let s;for(;(s=n.indexOf(`
15126
15126
 
15127
15127
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
@@ -15131,12 +15131,12 @@ data: ${JSON.stringify(s)}
15131
15131
 
15132
15132
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15133
15133
 
15134
- `)},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 so(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=ld(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:Vt(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Vt(t,e=120){for(let a of t.split(`
15135
- `)){let n=io(a);if(n)return Yt(n,e)}return""}function ld(t,e=120){let a=t.split(`
15136
- `).map(io).filter(Boolean);return a.length?Yt(a[a.length-1],e):""}function io(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Yt(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var mt=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 lo(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var oo=140;function co(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Vt(r||"",oo-18)||"something went wrong."}`:Vt(n,oo)||"Answered.";return{deviceId:t,title:Yt(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var uo=8e3,dd=/^[A-Za-z0-9_.:-]{1,64}$/,Ee=new Map,Qt=new Map,mo=new mt;async function fo(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??mo;if(n==="GET"&&a==="/api/app/agents")return O(e,200,{nodes:await ho(o)});let i=o.store();if(!i)return O(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),O(e,200,{conversations:so(r.id,md(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),O(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return O(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 O(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=Ee.get(p.id);return O(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&&Ee.get(p.id);if(!p||!u)return O(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),go(e);let{id:f,title:h,node:v,nodeName:T,agent:E,agentName:g}=p;return e.write(Zt("conversation",{id:f,title:h,node:v,nodeName:T,agent:E,agentName:g})),e.write(Zt("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 O(e,404,{error:"not found"});let c;try{c=await _e(t,64*1024)}catch(p){return O(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return O(e,404,{error:"no such conversation"});let u=Ee.get(p.id);return u?(u.ac.abort(),ea(p,o,r.name),O(e,200,{stopped:!0})):await ea(p,o,r.name)?O(e,200,{stopped:!0}):O(e,404,{error:"nothing is running in this conversation"})}return await ud(e,c,r,i,o),!0}function pd(t,e,a){let n=Pe(e.url),r=new Set,o=[];for(let s of t){let i=Pe(s.url),l=a.find(u=>Pe(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 ho(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return pd(e.nodes,t.daemon,a)}async function ud(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>uo){O(t,400,{error:`message must be 1\u2013${uo} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){O(t,404,{error:"no such conversation"});return}}else{let v=typeof e.node=="string"?e.node:"",T=typeof e.agent=="string"?e.agent:"";if(!dd.test(T)){O(t,400,{error:"pick an agent"});return}let E=(await ho(r)).find(d=>d.target===v);if(!E){O(t,400,{error:`unknown node "${v}"`});return}if(!E.online){O(t,409,{error:`${E.name} is offline`});return}let g=E.agents.find(d=>d.id===T);if(!g){O(t,400,{error:`no agent "${T}" on ${E.name}`});return}s=n.create(a.id,{node:v,nodeName:E.name,agent:T,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Ee.has(s.id)){O(t,409,{error:"The agent is still answering in this conversation."});return}let i=new ut(r.orphanLimitMs??18e5);Ee.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Qt.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()}),go(t),t.write(Zt("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let v=await ro(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`},i.ac.signal,(d,m)=>i.broadcast(d,m));i.orphaned&&(v.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,ea(s,r,a.name));let T=n.appendWithFiles(a.id,l,{role:"assistant",content:v.text,status:v.status,at:Date.now(),...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...v.tools.length?{tools:v.tools}:{}},v.files)??[];i.broadcast("final",{status:v.status,content:v.text,...v.error?{error:v.error}:{},...v.ui?{ui:v.ui}:{},...T.length?{files:T}:{}});let E=i.watched();E&&n.markRead(a.id,l);let g={status:v.status,attached:E,appOpen:(r.presence??mo).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&lo(g)&&r.notifyFinish(co(a.id,s,v.status,v.text,v.error)).catch(()=>{})}finally{Ee.delete(l),Qt.delete(l),i.finish()}}function md(){let t=[];for(let[e,a]of Qt){let n=Ee.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function go(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Zt(t,e){return`event: ${t}
15134
+ `)},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 so(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=pd(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:Vt(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Vt(t,e=120){for(let a of t.split(`
15135
+ `)){let n=io(a);if(n)return Yt(n,e)}return""}function pd(t,e=120){let a=t.split(`
15136
+ `).map(io).filter(Boolean);return a.length?Yt(a[a.length-1],e):""}function io(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Yt(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var mt=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 lo(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var oo=140;function co(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Vt(r||"",oo-18)||"something went wrong."}`:Vt(n,oo)||"Answered.";return{deviceId:t,title:Yt(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var uo=8e3,md=/^[A-Za-z0-9_.:-]{1,64}$/,Ee=new Map,Qt=new Map,mo=new mt;async function fo(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??mo;if(n==="GET"&&a==="/api/app/agents")return O(e,200,{nodes:await ho(o)});let i=o.store();if(!i)return O(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),O(e,200,{conversations:so(r.id,gd(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),O(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return O(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 O(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=Ee.get(p.id);return O(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&&Ee.get(p.id);if(!p||!u)return O(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),go(e);let{id:f,title:h,node:w,nodeName:_,agent:S,agentName:g}=p;return e.write(Zt("conversation",{id:f,title:h,node:w,nodeName:_,agent:S,agentName:g})),e.write(Zt("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 O(e,404,{error:"not found"});let c;try{c=await _e(t,64*1024)}catch(p){return O(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return O(e,404,{error:"no such conversation"});let u=Ee.get(p.id);return u?(u.ac.abort(),ea(p,o,r.name),O(e,200,{stopped:!0})):await ea(p,o,r.name)?O(e,200,{stopped:!0}):O(e,404,{error:"nothing is running in this conversation"})}return await hd(e,c,r,i,o),!0}function fd(t,e,a){let n=Pe(e.url),r=new Set,o=[];for(let s of t){let i=Pe(s.url),l=a.find(u=>Pe(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 ho(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return fd(e.nodes,t.daemon,a)}async function hd(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>uo){O(t,400,{error:`message must be 1\u2013${uo} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){O(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!md.test(_)){O(t,400,{error:"pick an agent"});return}let S=(await ho(r)).find(d=>d.target===w);if(!S){O(t,400,{error:`unknown node "${w}"`});return}if(!S.online){O(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){O(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:w,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Ee.has(s.id)){O(t,409,{error:"The agent is still answering in this conversation."});return}let i=new ut(r.orphanLimitMs??18e5);Ee.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Qt.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()}),go(t),t.write(Zt("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let w=e.spoken===!0,_=await ro(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`,spoken:w},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.`,ea(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??mo).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&lo(d)&&r.notifyFinish(co(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Ee.delete(l),Qt.delete(l),i.finish()}}function gd(){let t=[];for(let[e,a]of Qt){let n=Ee.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function go(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Zt(t,e){return`event: ${t}
15137
15137
  data: ${JSON.stringify(e)}
15138
15138
 
15139
- `}async function ea(t,e,a){try{let n=Pe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Pe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Pe(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 Pe(t){return t.replace(/\/+$/,"")}function O(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as fd}from"stream";var hd=/^\/api\/app\/files\/([^/]+)$/,gd=15e3;async function vo(t,e,a,n,r,o){let s=hd.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Se(e,405,{error:"GET only"});let i=o.store();if(!i)return Se(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 Se(e,404,{error:"no such file"});let p=await xd(c.node,o);if(!p)return Se(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(),gd),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Ra}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Se(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 Se(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let v=Number(h.headers.get("content-length")||0);if(v>ge.bytes)return u.abort(),Se(e,413,{error:"the file is too large"});let T=h.headers.get("content-range");if(e.writeHead(h.status,{...Pa(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(v)}:{},...h.status===206&&T?{"Content-Range":T}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let E=0,g=fd.fromWeb(h.body);return g.on("data",d=>{E+=d.length,E>ge.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function xd(t,e){if(t==="local")return{url:xo(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=xo(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function xo(t){return t.replace(/\/+$/,"")}function Se(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 yo=8e3;async function wo(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return K(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!za(h))return K(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let v=Ba(t.headers["x-audio-duration-ms"]);if(v)return t.resume(),K(e,v.status,{error:v.error});let T=await At(t,Ha.bytes);if(!T)return K(e,413,{error:Fa()});if(!T.length)return K(e,400,{error:"The recording is empty."});let E={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return bo(e,o.daemon,"/voice/transcribe",T,E,18e4)}let s,i=await At(t,64*1024);if(!i)return K(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return K(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return K(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return K(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,yo):"";if(!p.trim())return K(e,400,{error:"text is required"});if(!bd(c.messages,p))return K(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 bo(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function bo(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(vd(l)?.endpoints)?K(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 K(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function vd(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function bd(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===yo&&a.content.startsWith(e)))}var yd={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},ft=class{constructor(e=yd,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},wd="That code didn't work. Check it, or run agentx app pair for a new one.",kd=400;async function ko(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await _e(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await _d(a,e.minMs??kd),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:wd}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function _d(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ta(t,e){if(!t)return"absent";let a=Ia(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var ht=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 Eo(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=_o(t.headers["sec-fetch-mode"]),n.site=_o(t.headers["sec-fetch-site"]),n}function _o(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var So=`
15139
+ `}async function ea(t,e,a){try{let n=Pe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Pe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Pe(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 Pe(t){return t.replace(/\/+$/,"")}function O(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as xd}from"stream";var vd=/^\/api\/app\/files\/([^/]+)$/,bd=15e3;async function vo(t,e,a,n,r,o){let s=vd.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Se(e,405,{error:"GET only"});let i=o.store();if(!i)return Se(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 Se(e,404,{error:"no such file"});let p=await yd(c.node,o);if(!p)return Se(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(),bd),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Ra}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Se(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 Se(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>ge.bytes)return u.abort(),Se(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...Pa(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=xd.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>ge.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function yd(t,e){if(t==="local")return{url:xo(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=xo(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function xo(t){return t.replace(/\/+$/,"")}function Se(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 yo=8e3;async function wo(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return K(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!za(h))return K(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=Ba(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),K(e,w.status,{error:w.error});let _=await At(t,Ha.bytes);if(!_)return K(e,413,{error:Fa()});if(!_.length)return K(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 bo(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await At(t,64*1024);if(!i)return K(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return K(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return K(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return K(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,yo):"";if(!p.trim())return K(e,400,{error:"text is required"});if(!kd(c.messages,p))return K(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 bo(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function bo(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(wd(l)?.endpoints)?K(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 K(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function wd(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function kd(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===yo&&a.content.startsWith(e)))}var _d={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},ft=class{constructor(e=_d,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},Ed="That code didn't work. Check it, or run agentx app pair for a new one.",Sd=400;async function ko(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await _e(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await Td(a,e.minMs??Sd),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:Ed}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function Td(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ta(t,e){if(!t)return"absent";let a=Ia(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var ht=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 Eo(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=_o(t.headers["sec-fetch-mode"]),n.site=_o(t.headers["sec-fetch-site"]),n}function _o(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var So=`
15140
15140
  (function () {
15141
15141
  var fleetPanel = document.getElementById('panel-fleet');
15142
15142
  var activityPanel = document.getElementById('panel-activity');
@@ -15870,14 +15870,18 @@ details[open] > summary::before { transform: rotate(90deg); }
15870
15870
  input.value = ''; input.style.height = '';
15871
15871
  }
15872
15872
  // False when the text was neither sent nor queued, so a quick reply
15873
- // stays tappable.
15874
- function send(text) {
15873
+ // stays tappable. opts.spoken: the text came from voice, which the
15874
+ // computer records as a spoken turn (Activity shows it as Voice).
15875
+ function send(text, opts) {
15875
15876
  text = String(text || '').trim();
15876
15877
  if (!text) return false;
15878
+ var spoken = !!(opts && opts.spoken);
15877
15879
  if (state.busy) {
15878
15880
  // A follow-up while the agent answers: shown now, sent as the next
15879
15881
  // turn so its answer streams here as well.
15880
- state.queue.push(queuedMsg(text));
15882
+ var q = queuedMsg(text);
15883
+ q.spoken = spoken;
15884
+ state.queue.push(q);
15881
15885
  clearInput(text);
15882
15886
  scrollDown();
15883
15887
  return true;
@@ -15887,6 +15891,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15887
15891
  var body = state.conv
15888
15892
  ? { conversationId: state.conv.id, message: text }
15889
15893
  : { node: state.target.node, agent: state.target.agent, message: text };
15894
+ if (spoken) body.spoken = true;
15890
15895
  state.stopWanted = false;
15891
15896
  userMsg(text);
15892
15897
  clearInput(text);
@@ -15897,7 +15902,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15897
15902
  if (!state.queue.length || state.busy) return;
15898
15903
  var next = state.queue.splice(0);
15899
15904
  next.forEach(function (x) { x.el.remove(); });
15900
- send(next.map(function (x) { return x.text; }).join(V.NL + V.NL));
15905
+ send(next.map(function (x) { return x.text; }).join(V.NL + V.NL), { spoken: next.every(function (x) { return x.spoken; }) });
15901
15906
  }
15902
15907
  // Streams one turn into the bubble el, from a send or from attaching
15903
15908
  // to a turn that is still running. The phone losing its connection does
@@ -17060,7 +17065,7 @@ window.AXVoiceIO = (function () {
17060
17065
  return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok, status: r.status, j: j }; });
17061
17066
  }).then(function (x) {
17062
17067
  if (!x) return;
17063
- if (x.ok && x.j.text) { C.send(x.j.text); idle(); return; }
17068
+ if (x.ok && x.j.text) { C.send(x.j.text, { spoken: true }); idle(); return; }
17064
17069
  if (x.status === 503 && x.j.hint) { idle(x.j.error + ' ' + x.j.hint + ' You can type instead.', true); setTyping(true, false); return; }
17065
17070
  idle(x.j.error || ('Speech to text failed (HTTP ' + x.status + ').'), true);
17066
17071
  }).catch(function () { idle('Could not reach AgentX. Check the connection and try again.', true); });
@@ -17620,7 +17625,7 @@ self.addEventListener('notificationclick', function (e) {
17620
17625
  return self.clients.openWindow(target);
17621
17626
  }));
17622
17627
  });
17623
- `;var Ed="<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 na(t){return`<meta charset="utf-8">
17628
+ `;var Ad="<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 na(t){return`<meta charset="utf-8">
17624
17629
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
17625
17630
  <meta name="theme-color" content="#2979FF">
17626
17631
  <meta name="referrer" content="no-referrer">
@@ -17631,13 +17636,13 @@ self.addEventListener('notificationclick', function (e) {
17631
17636
  <link rel="icon" type="image/png" href="/app/icon-192.png">
17632
17637
  <link rel="apple-touch-icon" href="/app/icon-192.png">
17633
17638
  <title>${t}</title>
17634
- ${Ed}
17635
- <style>${Ya}${Ad}</style>`}var Qo=[{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 Zo(){let t=Qo.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=Qo.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
17639
+ ${Ad}
17640
+ <style>${Ya}${Id}</style>`}var Qo=[{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 Zo(){let t=Qo.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=Qo.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
17636
17641
  <h2>${a.label}</h2>
17637
17642
  <p class="soon">${a.soon}</p>
17638
17643
  </section>`).join("");return`<!doctype html>
17639
17644
  <html lang="en">
17640
- <head>${na("AgentX")}<style>${Cd}${To}${No}${Po}${zo}</style></head>
17645
+ <head>${na("AgentX")}<style>${Ld}${To}${No}${Po}${zo}</style></head>
17641
17646
  <body>
17642
17647
  <header class="bar">
17643
17648
  <div>
@@ -17649,7 +17654,7 @@ ${Ed}
17649
17654
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
17650
17655
  <main>${e}</main>
17651
17656
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
17652
- <script>${Sd}</script>
17657
+ <script>${Cd}</script>
17653
17658
  <script>${So}</script>
17654
17659
  <script>${Ao}</script>
17655
17660
  <script>${Co}</script>
@@ -17665,7 +17670,7 @@ ${Ed}
17665
17670
  <h1>Pairing this phone\u2026</h1>
17666
17671
  <p id="msg" role="status">One moment.</p>
17667
17672
  </main>
17668
- <script>${Td}</script>
17673
+ <script>${Md}</script>
17669
17674
  </body>
17670
17675
  </html>`}function ts(){return`<!doctype html>
17671
17676
  <html lang="en">
@@ -17675,7 +17680,7 @@ ${Ed}
17675
17680
  <script>${Uo}</script>
17676
17681
  <script>${Yo}</script>
17677
17682
  </body>
17678
- </html>`}function as(){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 Sd=`
17683
+ </html>`}function as(){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 Cd=`
17679
17684
  (function () {
17680
17685
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
17681
17686
  function select(tab, focus, keepHash) {
@@ -17745,7 +17750,7 @@ ${Ed}
17745
17750
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
17746
17751
  }
17747
17752
  })();
17748
- `,Td=`
17753
+ `,Md=`
17749
17754
  (function () {
17750
17755
  var msg = document.getElementById('msg');
17751
17756
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -17762,7 +17767,7 @@ ${Ed}
17762
17767
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
17763
17768
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
17764
17769
  })();
17765
- `,Ad=`
17770
+ `,Id=`
17766
17771
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
17767
17772
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
17768
17773
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -17774,7 +17779,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
17774
17779
  .card h1 { font-size: 22px; margin: 0 0 12px; }
17775
17780
  .muted { color: var(--ax-text-2); }
17776
17781
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
17777
- `,Cd=`
17782
+ `,Ld=`
17778
17783
  body { display: flex; flex-direction: column; }
17779
17784
  .bar {
17780
17785
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -17811,8 +17816,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
17811
17816
  }
17812
17817
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
17813
17818
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
17814
- `;var gt="agentx_app",Ld=400*86400,$d=new ft,Rd=new ht;async function ns(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ae;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",as());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",aa);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Kt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Kt(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",es());if(a==="/app/qr.js"){let i=Pd();return i?fe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Te(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=ra(ze(t),o);return i?(e.setHeader("Set-Cookie",oa(ze(t))),Te(e,200,{device:i.name})):Te(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await ko(t,{codes:r.pairCodes??new ln,limiter:r.pairLimiter??$d,verify:l=>ra(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",oa(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Te(e,i.status,i.body)}let s=ra(jd(t),o);if(!s){let i=ze(t);return(r.rejectLog??Rd).record(a.slice(0,120),Eo(t,ta(sa(t,gt),o),i?ta(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",ts()):Te(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=sa(t,gt);return i&&!ze(t)&&e.setHeader("Set-Cookie",oa(i)),fe(e,200,"text/html; charset=utf-8",Zo())}return n==="GET"&&a==="/api/app/me"?Te(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Jr(t,e,a,n,s.name,r.fleet)||r.push&&await Yr(t,e,a,n,s,r.push)||r.announce&&await eo(t,e,a,n,s,r.announce)||r.chat&&await fo(t,e,a,n,s,r.chat)||r.chat&&await vo(t,e,a,n,s,r.chat)||r.voice&&await wo(t,e,a,n,s,r.voice)?!0:Te(e,404,{error:"not found"})}var Be;function Pd(){if(Be!==void 0)return Be;try{let t=Id(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
17815
- `;Be=Buffer.concat([Buffer.from(a),Md(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Be=null}return Be}function ra(t,e){if(!t)return null;let a=e.verify(t);return a&&be(a,"app")?a:null}function oa(t){return`${gt}=${t}; Path=/; Max-Age=${Ld}; HttpOnly; Secure; SameSite=Lax`}function jd(t){return ze(t)??sa(t,gt)}function ze(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function sa(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 fe(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 fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as rs}from"crypto";var Ae={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ge.perMessage},Od=/^[a-f0-9]{32}$/,Nd=/^c[a-z0-9]{8,32}$/,Dd=/^#[0-9a-fA-F]{6}$/;function os(t){return Nd.test(t)}var Fe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
17819
+ `;var gt="agentx_app",Pd=400*86400,jd=new ft,Od=new ht;async function ns(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ae;if(n==="GET"){if(a==="/app/manifest.webmanifest")return fe(e,200,"application/manifest+json",as());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),fe(e,200,"text/javascript; charset=utf-8",aa);if(a==="/app/icon-192.png")return fe(e,200,"image/png",Kt(192),"public, max-age=86400");if(a==="/app/icon-512.png")return fe(e,200,"image/png",Kt(512),"public, max-age=86400");if(a==="/app/pair")return fe(e,200,"text/html; charset=utf-8",es());if(a==="/app/qr.js"){let i=Nd();return i?fe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Te(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=ra(ze(t),o);return i?(e.setHeader("Set-Cookie",oa(ze(t))),Te(e,200,{device:i.name})):Te(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await ko(t,{codes:r.pairCodes??new ln,limiter:r.pairLimiter??jd,verify:l=>ra(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",oa(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Te(e,i.status,i.body)}let s=ra(Dd(t),o);if(!s){let i=ze(t);return(r.rejectLog??Od).record(a.slice(0,120),Eo(t,ta(sa(t,gt),o),i?ta(i,o):null)),a==="/app"?fe(e,401,"text/html; charset=utf-8",ts()):Te(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=sa(t,gt);return i&&!ze(t)&&e.setHeader("Set-Cookie",oa(i)),fe(e,200,"text/html; charset=utf-8",Zo())}return n==="GET"&&a==="/api/app/me"?Te(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await Jr(t,e,a,n,s.name,r.fleet)||r.push&&await Yr(t,e,a,n,s,r.push)||r.announce&&await eo(t,e,a,n,s,r.announce)||r.chat&&await fo(t,e,a,n,s,r.chat)||r.chat&&await vo(t,e,a,n,s,r.chat)||r.voice&&await wo(t,e,a,n,s,r.voice)?!0:Te(e,404,{error:"not found"})}var Be;function Nd(){if(Be!==void 0)return Be;try{let t=Rd(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
17820
+ `;Be=Buffer.concat([Buffer.from(a),$d(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Be=null}return Be}function ra(t,e){if(!t)return null;let a=e.verify(t);return a&&be(a,"app")?a:null}function oa(t){return`${gt}=${t}; Path=/; Max-Age=${Pd}; HttpOnly; Secure; SameSite=Lax`}function Dd(t){return ze(t)??sa(t,gt)}function ze(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function sa(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 fe(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 fe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as rs}from"crypto";var Ae={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ge.perMessage},Hd=/^[a-f0-9]{32}$/,Bd=/^c[a-z0-9]{8,32}$/,zd=/^#[0-9a-fA-F]{6}$/;function os(t){return Bd.test(t)}var Fe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
17816
17821
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
17817
17822
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
17818
17823
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -17824,8 +17829,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
17824
17829
  CREATE TABLE IF NOT EXISTS app_chat_files (
17825
17830
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
17826
17831
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
17827
- 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")}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${rs(4).toString("hex")}`,{color:s,...i}=a,l=s&&Dd.test(s)?s:void 0,c={id:o,title:Bd(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
17828
- (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(!os(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(Hd);return{...ss(n),messages:r}}list(e,a=Ae.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
17832
+ 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")}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${rs(4).toString("hex")}`,{color:s,...i}=a,l=s&&zd.test(s)?s:void 0,c={id:o,title:qd(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
17833
+ (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(!os(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(Fd);return{...ss(n),messages:r}}list(e,a=Ae.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
17829
17834
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
17830
17835
  (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
17831
17836
  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{...ss(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){os(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,
@@ -17835,28 +17840,28 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
17835
17840
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
17836
17841
  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>Ae.content?n.content.slice(0,Ae.content)+`
17837
17842
 
17838
- [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ae.toolsPerMessage),l=[];for(let f of r){if(l.length>=Ae.filesPerMessage)break;let h=f.filename.trim(),v=wa(h);if(!v||!h||h.length>ge.pathChars||h.includes("\0"))continue;let T=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:rs(16).toString("hex"),name:T,mime:v.mime,kind:v.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)
17843
+ [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ae.toolsPerMessage),l=[];for(let f of r){if(l.length>=Ae.filesPerMessage)break;let h=f.filename.trim(),w=wa(h);if(!w||!h||h.length>ge.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:rs(16).toString("hex"),name:_,mime:w.mime,kind:w.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)
17839
17844
  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)
17840
17845
  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
17841
17846
  (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ae.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
17842
- (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(!Od.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
17847
+ (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(!Hd.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
17843
17848
  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 = ?
17844
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ae.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 ss(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 Hd(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 Bd(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Cg(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,Qd(h,t))}catch(v){console.error(` Board "${h.id}" failed to initialize: ${v.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?qe(process.cwd(),t.workflows.dir):void 0,c=new ga(l?{baseDir:l}:void 0),p=new xa(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new va(l?{baseDir:l}:void 0);hr(t),Na({business:t.business?.enabled===!0}),zd(async(h,v)=>{try{await Kd(h,v,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(T){w(v,500,{error:T.message||"internal error"})}}).listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
17849
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ae.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 ss(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 Fd(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 qd(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}function Lg(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,tp(h,t))}catch(w){console.error(` Board "${h.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?qe(process.cwd(),t.workflows.dir):void 0,c=new ga(l?{baseDir:l}:void 0),p=new xa(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new va(l?{baseDir:l}:void 0);hr(t),Na({business:t.business?.enabled===!0}),Ud(async(h,w)=>{try{await Yd(h,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){y(w,500,{error:_.message||"internal error"})}}).listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
17845
17850
  Live dashboard: http://${h}:${n}
17846
17851
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
17847
17852
  Kanban dashboard: http://${h}:${n}
17848
- `),console.log(` Boards: ${a.map(v=>v.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 Xd=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Kd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ja(t.headers)==="foreign"&&Oa(o)){w(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ns(t,e,r,o,{nodeName:a.config.node?.name,fleet:us(a.config),push:ps(a.config),announce:to(a.config),chat:fp(a.config),voice:gp(a.config)}))return;if(o==="GET"&&Xd.has(r)&&pn("page",r),o==="GET"&&r==="/"){let d=nn();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(Gt({peers:N(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({peers:N(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gt({peers:N(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ve(a.config);if(!d){w(e,503,{error:"no node available"});return}let m=await new Promise(b=>{let k="";t.on("data",y=>k+=y),t.on("end",()=>b(k)),t.on("error",()=>b(""))}),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){w(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 ve(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await he(t):void 0,b=x?.node??m,k=b?d.find(M=>M.url===b):d[0];if(!k){w(e,400,{error:"unknown node"});return}let y=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",_=await fetch(k.url+r+y,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});w(e,_.status,await _.json().catch(()=>({error:`HTTP ${_.status}`})))}catch(d){w(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 he(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),b=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),k=await b.json().catch(()=>({error:`HTTP ${b.status}`}));w(e,b.status,k)}catch(d){w(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ve(a.config);if(!d){w(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});w(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{w(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wn({peers:N(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yn({peers:N(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(gn({peers:N(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=_a(await ve(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(x.map(async C=>{try{let S=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!S.ok)throw new Error(`HTTP ${S.status}`);return{name:C.name,url:C.url,ok:!0,data:await S.json()}}catch(S){return{name:C.name,url:C.url,ok:!1,error:S.message}}}));w(e,200,{nodes:M});return}let b=x.find(M=>M.url===n.searchParams.get("node"));if(!b){w(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){w(e,405,{error:"Unknown monitor operation"});return}let y=o==="POST"?JSON.stringify(await ka(t)):void 0,_=await fetch(b.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:y,signal:d.signal,headers:{"Content-Type":"application/json",...b.token?{Authorization:`Bearer ${b.token}`}:{}}});w(e,_.status,await _.json())}catch(x){w(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(Or({peers:N(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zr({peers:N(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fr({peers:N(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qr({peers:N(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({}));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(Ur({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:N(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(Wr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:N(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){rn(t,e);return}if(o==="POST"&&r==="/api/setup"){await on(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await sn(t,e);return}if(o==="GET"&&r==="/admin"){Tn(t,e,N(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Dn(e,N(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Rn(t,e,N(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}Wn(t,e,N(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 kp(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Ut(t,e,r,x=>fs(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),b=x.indexOf("::");if(b>0){let k=x.slice(0,b),y=x.slice(b+2),_=a.config.node?.id||a.config.node?.name||"local";if(k===_)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`;else{let M=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(M){let C=We(M.url.replace(/\/+$/,""),a.config);if(C){await ls(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(y)}`);return}}w(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=We(d,a.config);if(!m){w(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await ls(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Gn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await _p(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-IITNYJU5.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",b=await d({running:x});w(e,200,b)}catch(d){w(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(Vn({peers:N(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Jn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Yn({peers:N(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qn({peers:N(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 tp(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 gr(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ut(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await vr(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){wr(t,e,c[1],N(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 ae,b=m?x.verify(m):null;if(!b||!be(b,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await An(t,e);return}if(r.startsWith("/api/admin/approvals")){await Hn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Pn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await kr(t,e,r);return}if(r.startsWith("/api/admin/")){await Cn(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(kn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){w(e,400,{error:"invalid asset name"});return}let m=yp("web/"+d);try{let x=await wp(m),b=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":b,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{w(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ue(a.config);w(e,200,d)}catch(d){w(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 Ue(a.config,{date:d,timezone:m});w(e,200,x)}catch(d){w(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,b,k)=>{let y=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(y)?Math.max(b,Math.min(k,y)):x};try{let m=await ve(a.config);w(e,200,await Nr(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){w(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)){w(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,b,k,y)=>{let _=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(_)?Math.max(k,Math.min(y,_)):b};try{let x=await ve(a.config);w(e,200,await Hr(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){w(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){w(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[b,k,y]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!b||!k||!y){w(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(y)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[b,k]=[m.get("kind"),m.get("key")];if(!b||!k){w(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(b)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[b,k,y]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!b||!k||!y){w(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(b)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(y)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let b=m.get("task");if(!b){w(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(b)}`}try{await Dr(e,await ve(a.config),d,x)}catch(b){w(e,502,{error:b.message})}return}if(o==="GET"&&r==="/api/live/stream"){lp(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"),b=d.searchParams.get("task");if(!m||!x||!b){w(e,400,{error:"node, agent, task query params required"});return}await cp(t,e,a,m,x,b);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"),b=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!m||!x){w(e,400,{error:"node and agent query params required"});return}await up(e,a,m,x,b,k);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"),b=d.searchParams.get("kind");if(!m||!x||b!=="cancel"&&b!=="followup"){w(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await mp(t,e,a,m,x,b);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){w(e,400,{error:"node query param required"});return}await da(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();w(e,200,x)}catch(d){w(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){w(e,m.status,{error:`HTTP ${m.status}`});return}w(e,200,await m.json())}catch(d){w(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await he(t);try{let m=await vp(a.config,d);w(e,200,m)}catch(m){w(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(!dp(t,e,[`agent:${d}`]))return;await pp(t,e,a.config,d);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 ae,b=m?x.verify(m):null;if(!b||!be(b,"dashboard:write")){w(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await ap(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"){w(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){w(e,400,{error:"node query param required"});return}await da(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(_=>({name:_.name,url:_.url,token:_.token}))],b={flag:!1},k=[];t.on("close",()=>{b.flag=!0;for(let _ of k)try{_.abort()}catch{}});let y=setInterval(()=>{if(!b.flag)try{e.write(`: ping
17853
+ `),console.log(` Boards: ${a.map(w=>w.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 Vd=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Yd(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(ja(t.headers)==="foreign"&&Oa(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await ns(t,e,r,o,{nodeName:a.config.node?.name,fleet:us(a.config),push:ps(a.config),announce:to(a.config),chat:xp(a.config),voice:bp(a.config)}))return;if(o==="GET"&&Vd.has(r)&&pn("page",r),o==="GET"&&r==="/"){let d=nn();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(Gt({peers:N(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Br({peers:N(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gt({peers:N(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await ve(a.config);if(!d){y(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),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){y(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 ve(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await he(t):void 0,v=x?.node??m,k=v?d.find(M=>M.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",E=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,E.status,await E.json().catch(()=>({error:`HTTP ${E.status}`})))}catch(d){y(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 he(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??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await ve(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wn({peers:N(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(yn({peers:N(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(gn({peers:N(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=_a(await ve(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let M=await Promise.all(x.map(async C=>{try{let T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:M});return}let v=x.find(M=>M.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await ka(t)):void 0,E=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,E.status,await E.json())}catch(x){y(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(Or({peers:N(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zr({peers:N(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fr({peers:N(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qr({peers:N(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(an({}));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(Ur({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:N(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(Wr({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:N(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){rn(t,e);return}if(o==="POST"&&r==="/api/setup"){await on(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await sn(t,e);return}if(o==="GET"&&r==="/admin"){Tn(t,e,N(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Dn(e,N(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){Rn(t,e,N(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}Wn(t,e,N(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 Sp(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await Ut(t,e,r,x=>fs(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 k=x.slice(0,v),b=x.slice(v+2),E=a.config.node?.id||a.config.node?.name||"local";if(k===E)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let M=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(M){let C=We(M.url.replace(/\/+$/,""),a.config);if(C){await ls(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=We(d,a.config);if(!m){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await ls(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Gn(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await Tp(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-IITNYJU5.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(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(Vn({peers:N(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Jn(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Yn({peers:N(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Qn({peers:N(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 rp(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 gr(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await Ut(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await vr(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){wr(t,e,c[1],N(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 ae,v=m?x.verify(m):null;if(!v||!be(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await An(t,e);return}if(r.startsWith("/api/admin/approvals")){await Hn(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await Pn(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await kr(t,e,r);return}if(r.startsWith("/api/admin/")){await Cn(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(kn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let m=_p("web/"+d);try{let x=await Ep(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ue(a.config);y(e,200,d)}catch(d){y(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 Ue(a.config,{date:d,timezone:m});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,k)=>{let b=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let m=await ve(a.config);y(e,200,await Nr(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){y(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)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,k,b)=>{let E=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(E)?Math.max(k,Math.min(b,E)):v};try{let x=await ve(a.config);y(e,200,await Hr(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[m.get("kind"),m.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Dr(e,await ve(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){pp(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){y(e,400,{error:"node, agent, task query params required"});return}await up(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"),k=d.searchParams.get("limit")||"50";if(!m||!x){y(e,400,{error:"node and agent query params required"});return}await hp(e,a,m,x,v,k);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"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await gp(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){y(e,400,{error:"node query param required"});return}await da(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();y(e,200,x)}catch(d){y(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){y(e,m.status,{error:`HTTP ${m.status}`});return}y(e,200,await m.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await he(t);try{let m=await wp(a.config,d);y(e,200,m)}catch(m){y(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(!mp(t,e,[`agent:${d}`]))return;await fp(t,e,a.config,d);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 ae,v=m?x.verify(m):null;if(!v||!be(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await op(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await da(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(E=>({name:E.name,url:E.url,token:E.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let E of k)try{E.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
17849
17854
 
17850
- `)}catch{}},15e3);t.on("close",()=>clearInterval(y));for(let _ of x)(async()=>{let M={Accept:"text/event-stream"};_.token&&(M.Authorization=`Bearer ${_.token}`);let C=new AbortController;k.push(C);try{let S=await fetch(`${_.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:C.signal});if(!S.ok||!S.body)return;let I=S.body.getReader(),R=new TextDecoder,P="";for(;!b.flag;){let{done:B,value:oe}=await I.read();if(B)break;P+=R.decode(oe,{stream:!0});let z;for(;(z=P.indexOf(`
17855
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let E of x)(async()=>{let M={Accept:"text/event-stream"};E.token&&(M.Authorization=`Bearer ${E.token}`);let C=new AbortController;k.push(C);try{let T=await fetch(`${E.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:M,signal:C.signal});if(!T.ok||!T.body)return;let I=T.body.getReader(),R=new TextDecoder,P="";for(;!v.flag;){let{done:B,value:oe}=await I.read();if(B)break;P+=R.decode(oe,{stream:!0});let z;for(;(z=P.indexOf(`
17851
17856
 
17852
- `))>=0;){let D=P.slice(0,z);if(P=P.slice(z+2),b.flag)break;try{e.write(D+`
17857
+ `))>=0;){let D=P.slice(0,z);if(P=P.slice(z+2),v.flag)break;try{e.write(D+`
17853
17858
 
17854
- `)}catch{b.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,b=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:m,workflowId:x}),y=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${b?"&summary=1":""}`,_=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(R=>({url:R.url,token:R.token}))],M=await Promise.all(_.map(async R=>{let P={};R.token&&(P.Authorization=`Bearer ${R.token}`);try{let B=new AbortController,oe=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${R.url.replace(/\/+$/,"")}/api/workflows/runs${y}`,{headers:P,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(oe)}}catch{return[]}})),C=new Map;for(let R of k)C.set(R.id,R);for(let R of M)for(let P of R)C.set(P.id,P);let S=Array.from(C.values()).sort((R,P)=>R.updatedAt<P.updatedAt?1:-1).slice(0,m),I=b?S.map(R=>Yd(R)):S;w(e,200,{runs:I})}catch(d){w(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){w(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(b=>({url:b.url,token:b.token}))];for(let b of x)try{let k={};b.token&&(k.Authorization=`Bearer ${b.token}`);let y=await fetch(`${b.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(y.ok){w(e,200,await y.json());return}}catch{}w(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}),b=await x.json().catch(()=>({error:`HTTP ${x.status}`}));w(e,x.status,b)}catch(d){w(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 he(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(/\/+$/,""),b=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),k=await b.json().catch(()=>({error:`HTTP ${b.status}`}));w(e,b.status,k)}catch(d){w(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Xr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,b)=>{if(a.token)return!0;let k=Tt(m);if(!k)return!0;let y=new ae().verify(k);if(!y)return w(x,401,{error:"invalid or revoked token"}),!1;for(let _ of b)if(!be(y,_))return w(x,403,{error:`token missing scope: ${_}`,scopes:y.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){w(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 v=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(v&&o==="GET"){let d=a.sources.get(v[1]);if(!d){w(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];w(e,200,m)}catch(m){w(e,502,{error:m.message})}return}let T=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(T&&o==="GET"){let d=a.sources.get(T[1]);if(!d){w(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];w(e,200,m)}catch(m){w(e,502,{error:m.message})}return}let E=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(E&&o==="PATCH"){let[,d,m]=E,x=decodeURIComponent(m),b=a.boards.find(C=>C.id===d);if(!b){w(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){w(e,503,{error:`board "${d}" source unavailable`});return}let y=await he(t),_=b.columns.find(C=>C.id===y.to),M=b.columns.find(C=>C.id===y.from);if(!_){w(e,400,{error:`unknown 'to' column: ${y.to}`});return}try{await Vd(k,x,M,_),ia({actor:la(t),action:"move",boardId:d,itemId:x,payload:{from:y.from,to:y.to}}),w(e,200,{ok:!0})}catch(C){w(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,b=a.boards.find(y=>y.id===d);if(!b){w(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){w(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:y,totals:_}=await Jd(b,k,n.searchParams);w(e,200,{columns:y,totals:_});return}if(o==="GET"&&x){try{let y=typeof k.getItem=="function"?await k.getItem(x):null;if(!y){w(e,404,{error:"not found"});return}w(e,200,y)}catch(y){w(e,502,{error:y.message})}return}if(o==="PATCH"&&x){let y=await he(t);try{let _=typeof k.updateItem=="function"?await k.updateItem(x,y):null;if(!_){w(e,501,{error:"update unsupported"});return}ia({actor:la(t),action:"update",boardId:d,itemId:x,payload:y}),w(e,200,_)}catch(_){w(e,502,{error:_.message})}return}if(o==="POST"&&!x){let y=await he(t);if(!y.title){w(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){w(e,400,{error:`source ${k.type} does not support create`});return}try{let _=await k.create({title:y.title,description:y.description,labels:y.labels,assigneeUsernames:y.assigneeUsernames,milestoneTitle:y.milestoneTitle,projectHint:y.projectHint});ia({actor:la(t),action:"create",boardId:d,itemId:_.id,payload:{title:y.title}}),w(e,201,_)}catch(_){w(e,502,{error:_.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}}w(e,404,{error:"not found",path:r})}async function Jd(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"}):[],v={};for(let d of t.columns)v[d.id]=[];let T=t.columns.find(d=>d.kind==="closed");for(let d of h)T&&v[T.id].push({...d,stage:T.id});let E=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=ua(d,E);if(!m)continue;let x=v[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(v))v[d]=v[d].filter(m=>m.assignee===i);for(let d of Object.keys(v))v[d].sort((m,x)=>{let b=(m.priority??99)-(x.priority??99);return b!==0?b:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(v).map(([d,m])=>[d,m.length]));return{columns:v,totals:g}}async function Vd(t,e,a,n){let r=ma(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 Yd(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 Qd(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 qa(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function ia(t){try{let e=qe(process.cwd(),".agentx");cs(e)||qd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
17855
- `;Fd(qe(e,"board-audit.jsonl"),a)}catch{}}function la(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Zd=2e3;async function ep(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(),Zd),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async b=>{let k=b.ok?await b.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,v,T]=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 E=await c.json();if(o.agents=E.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(v&&v.ok){let g=await v.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Aa.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(T&&T.ok){let g=await T.json().catch(()=>null);g&&Array.isArray(g.sessions)&&ip(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 xt=null;function tp(t){if(xt)return xt;let e=qe(process.cwd(),".agentx/wiki");return xt=fn({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),xt}async function bt(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 ap(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||q(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){w(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();w(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){w(t,502,{error:s.message||"daemon unreachable"})}}async function ve(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=q(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:q(a,l)})}let s=await bt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:q(a,i.url)});return[...o.values()]}var np=3e3,rp=6e3,op=5*6e4,ca=new Map,vt=new Map;function Ue(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=vt.get(a);if(n)return n;let r=(async()=>{let o=await ve(t,AbortSignal.timeout(np)),s=await Promise.all(o.map(async i=>{let l=await ep(i.url,i.token,AbortSignal.timeout(rp),e);return e?l:sp(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>vt.delete(a));return vt.set(a,r),r}function sp(t,e,a=Date.now()){if(e.reachable&&!e.error)return ca.set(t,{node:e,at:a}),e;let n=ca.get(t);return!n||a-n.at>op?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Mg(){ca.clear(),vt.clear()}function ip(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 lp(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}
17859
+ `)}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",k=a.workflowRuns.list({limit:m,workflowId:x}),b=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,E=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(R=>({url:R.url,token:R.token}))],M=await Promise.all(E.map(async R=>{let P={};R.token&&(P.Authorization=`Bearer ${R.token}`);try{let B=new AbortController,oe=setTimeout(()=>B.abort(),5e3);try{let z=await fetch(`${R.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:P,signal:B.signal});if(!z.ok)return[];let D=await z.json();return Array.isArray(D.runs)?D.runs:[]}finally{clearTimeout(oe)}}catch{return[]}})),C=new Map;for(let R of k)C.set(R.id,R);for(let R of M)for(let P of R)C.set(P.id,P);let T=Array.from(C.values()).sort((R,P)=>R.updatedAt<P.updatedAt?1:-1).slice(0,m),I=v?T.map(R=>ep(R)):T;y(e,200,{runs:I})}catch(d){y(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){y(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 k={};v.token&&(k.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(b.ok){y(e,200,await b.json());return}}catch{}y(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}`}));y(e,x.status,v)}catch(d){y(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 he(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??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Xr(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let k=Tt(m);if(!k)return!0;let b=new ae().verify(k);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let E of v)if(!be(b,E))return y(x,403,{error:`token missing scope: ${E}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(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 w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,m)}catch(m){y(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){y(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,m)}catch(m){y(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){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await he(t),E=v.columns.find(C=>C.id===b.to),M=v.columns.find(C=>C.id===b.from);if(!E){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Zd(k,x,M,E),ia({actor:la(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:E}=await Qd(v,k,n.searchParams);y(e,200,{columns:b,totals:E});return}if(o==="GET"&&x){try{let b=typeof k.getItem=="function"?await k.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await he(t);try{let E=typeof k.updateItem=="function"?await k.updateItem(x,b):null;if(!E){y(e,501,{error:"update unsupported"});return}ia({actor:la(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,E)}catch(E){y(e,502,{error:E.message})}return}if(o==="POST"&&!x){let b=await he(t);if(!b.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let E=await k.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});ia({actor:la(t),action:"create",boardId:d,itemId:E.id,payload:{title:b.title}}),y(e,201,E)}catch(E){y(e,502,{error:E.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}}y(e,404,{error:"not found",path:r})}async function Qd(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"}):[],w={};for(let d of t.columns)w[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&w[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=ua(d,S);if(!m)continue;let x=w[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(m=>m.assignee===i);for(let d of Object.keys(w))w[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(w).map(([d,m])=>[d,m.length]));return{columns:w,totals:g}}async function Zd(t,e,a,n){let r=ma(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 ep(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 tp(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 qa(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function ia(t){try{let e=qe(process.cwd(),".agentx");cs(e)||Gd(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
17860
+ `;Wd(qe(e,"board-audit.jsonl"),a)}catch{}}function la(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var ap=2e3;async function np(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(),ap),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let k=v.ok?await v.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,w,_]=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(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Aa.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)&&dp(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 xt=null;function rp(t){if(xt)return xt;let e=qe(process.cwd(),".agentx/wiki");return xt=fn({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),xt}async function bt(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 op(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||q(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function ve(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=q(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:q(a,l)})}let s=await bt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:q(a,i.url)});return[...o.values()]}var sp=3e3,ip=6e3,lp=5*6e4,ca=new Map,vt=new Map;function Ue(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=vt.get(a);if(n)return n;let r=(async()=>{let o=await ve(t,AbortSignal.timeout(sp)),s=await Promise.all(o.map(async i=>{let l=await np(i.url,i.token,AbortSignal.timeout(ip),e);return e?l:cp(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>vt.delete(a));return vt.set(a,r),r}function cp(t,e,a=Date.now()){if(e.reachable&&!e.error)return ca.set(t,{node:e,at:a}),e;let n=ca.get(t);return!n||a-n.at>lp?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function $g(){ca.clear(),vt.clear()}function dp(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 pp(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}
17856
17861
  data: ${JSON.stringify(c)}
17857
17862
 
17858
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ue(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 cp(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let v of a.config.dashboard.daemons)i.add(v.url.replace(/\/+$/,""));try{let v=await bt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let T of v)i.add(T.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(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(v){w(e,502,{error:v.message||"upstream connect failed"});return}if(!u.ok||!u.body){w(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:v,done:T}=await f.read();if(T)break;v&&e.write(v)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function dp(t,e,a){let n=Tt(t);if(!n)return w(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ae().verify(n);if(!r)return w(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!be(r,o))return w(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function pp(t,e,a,n){let r=a.agents?.[n];if(!r){w(e,404,{error:"unknown agent"});return}if(r.access!=="public"){w(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await he(t)}catch{w(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){w(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){w(e,502,{error:c.message||"upstream call failed"})}}async function up(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 bt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){w(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(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){w(t,502,{error:u.message||"upstream fetch failed"})}}async function mp(t,e,a,n,r,o){await da(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function da(t,e,a,n,r){let o={};try{o=await he(t)??{}}catch{}let s=await ds(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ds(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 bt(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=q(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 ps(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=La(e.keysFile);return{store:()=>{let r=Ce();return r?new Va(r):null},publicKey:()=>$a(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function us(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ue(t,n),async nodePost(n,r,o){let s=await ds(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=Xe({root:process.cwd()}).items.map(is)}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=We(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(is)}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=Ie(),p=await Ke({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=We(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"}}}}}}function fp(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=q(t.dashboard,e),n=us(t);return{store:()=>{let r=Ce();return r?new Fe(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ue(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=>q(t.dashboard,r.replace(/\/+$/,"")),...hp(t,e,a)}}function hp(t,e,a){let n=ps(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}
17859
- ${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 gp(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ce();return a?new Fe(a):null},daemon:{url:e,token:q(t.dashboard,e)}}}function is(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 xp=`
17863
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ue(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 up(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await bt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of w)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(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(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:_}=await f.read();if(_)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function mp(t,e,a){let n=Tt(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ae().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!be(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function fp(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await he(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),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){y(e,502,{error:c.message||"upstream call failed"})}}async function hp(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 bt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=q(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){y(t,502,{error:u.message||"upstream fetch failed"})}}async function gp(t,e,a,n,r,o){await da(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function da(t,e,a,n,r){let o={};try{o=await he(t)??{}}catch{}let s=await ds(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ds(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 bt(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=q(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 ps(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=La(e.keysFile);return{store:()=>{let r=Ce();return r?new Va(r):null},publicKey:()=>$a(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function us(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ue(t,n),async nodePost(n,r,o){let s=await ds(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=Xe({root:process.cwd()}).items.map(is)}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=We(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(is)}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=Ie(),p=await Ke({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=We(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"}}}}}}function xp(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=q(t.dashboard,e),n=us(t);return{store:()=>{let r=Ce();return r?new Fe(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ue(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=>q(t.dashboard,r.replace(/\/+$/,"")),...vp(t,e,a)}}function vp(t,e,a){let n=ps(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}
17864
+ ${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 bp(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ce();return a?new Fe(a):null},daemon:{url:e,token:q(t.dashboard,e)}}}function is(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 yp=`
17860
17865
  You are helping draft a new GitLab issue. Follow these conventions strictly.
17861
17866
 
17862
17867
  Title pattern:
@@ -17888,10 +17893,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
17888
17893
  Shape:
17889
17894
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
17890
17895
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
17891
- `;async function vp(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):
17896
+ `;async function wp(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):
17892
17897
  - ${r.knownLabels.slice(0,60).join(`
17893
17898
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
17894
- `),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:xp}})});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=bp(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 bp(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 yp(t){let e=Gd(Wd(import.meta.url));return qe(e,t)}async function wp(t){return Ud(t)}function w(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function he(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 ms(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function N(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:ms(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 kp(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;w(e,200,await ct(await fs(r,a.config)))}async function fs(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=qt(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=We(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 fr(n)}async function _p(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(v=>cs(v));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}
17899
+ `),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:yp}})});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=kp(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 kp(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 _p(t){let e=Jd(Kd(import.meta.url));return qe(e,t)}async function Ep(t){return Xd(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function he(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 ms(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function N(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:ms(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 Sp(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await ct(await fs(r,a.config)))}async function fs(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=qt(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=We(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 fr(n)}async function Tp(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(w=>cs(w));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}
17895
17900
 
17896
17901
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
17897
17902
  `))>=0;){let h=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
@@ -17899,5 +17904,5 @@ data: ${h.replace(/\n/g," ")}
17899
17904
 
17900
17905
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
17901
17906
 
17902
- `)}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 ls(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",v=>h.push(v)),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){w(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function We(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:ms(n),token:n.dashboardToken||n.token}:null}export{ip as applyAttachSessions,ep as fetchDaemonAgents,Kd as handleBoardRequest,Mg as resetLiveCaches,ve as resolveNodeTargets,Cg as startBoardDashboard,sp as withLastGood};
17903
- //# sourceMappingURL=board-dashboard-K3P2M7A7.js.map
17907
+ `)}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 ls(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",w=>h.push(w)),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){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function We(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:ms(n),token:n.dashboardToken||n.token}:null}export{dp as applyAttachSessions,np as fetchDaemonAgents,Yd as handleBoardRequest,$g as resetLiveCaches,ve as resolveNodeTargets,Lg as startBoardDashboard,cp as withLastGood};
17908
+ //# sourceMappingURL=board-dashboard-ZE2A3ARS.js.map