agentix-cli 0.92.2 → 0.92.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{a as A,b as dr,c as pr,d as ur,e as mr,f as _e,g as fr,h as hr,i as It,k as gr,n as xr,o as vr,p as br,q as yr,r as wr,v as kr,w as _r,x as Er,y as Tr,z as Ar}from"./chunk-Q4R4OS5S.js";import{a as Sr}from"./chunk-UVMCAZL7.js";import{a as cr}from"./chunk-QAIYUMHW.js";import{a as Tt,b as z,c as M,h as ve,i as At,j as re,k as K,l as Ct,m as sr,n as ir,o as lr}from"./chunk-N7HKIMMR.js";import{a as or}from"./chunk-2NYP4OQU.js";import{a as ce,b as rr}from"./chunk-JWDJMFU6.js";import{$a as nr,A as vt,B as Dn,E as Hn,F as Bn,Fa as Yn,G as zn,Ha as Ne,Ma as Qn,N as U,O as qn,Oa as De,P as Fn,Pa as wt,Qa as kt,Ra as _t,Sa as St,Ta as Zn,Ua as er,Va as tr,Wa as Et,Ya as ar,a as Tn,c as ut,d as sa,e as An,i as mt,l as Xe,n as Cn,ta as Xn,va as Kn,w as ht,wa as Jn,x as Pn,xa as Vn,y as gt,z as xt}from"./chunk-LKBUTSYP.js";import"./chunk-GTJIKXDB.js";import{g as Sn,h as En}from"./chunk-PS3UB5PH.js";import{a as Nn,b as N,c as Un,d as Wn,h as Gn}from"./chunk-DG5I6PPM.js";import{p as In,t as Mn}from"./chunk-S2GAEH2F.js";import"./chunk-IWEN3YNQ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Ln,e as ia}from"./chunk-ACFQBLPX.js";import{g as ft}from"./chunk-LQE73AZR.js";import{b as Rn,c as $n}from"./chunk-2D3RYIDU.js";import{m as jn,n as bt,o as yt,q as On}from"./chunk-E5OV6RTG.js";import{a as xn,f as vn,g as ra,h as oa,l as bn,m as yn,n as wn,u as ct,v as dt,w as pt,x as le,y as _n}from"./chunk-5PFTUGP4.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5EOFTPQB.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-M56MKNAG.js";import{a as kn}from"./chunk-HJUBCA7O.js";import"./chunk-DS7CDASP.js";import"./chunk-T2IDDOSX.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as gn}from"./chunk-OQHC7TJL.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-MIRBKQHA.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{G as dn,J as Sl,K as pn,L as un,N as mn,P as fn,T as hn,a as nn,b as rn,c as wl,ea as X,ha as lt,r as ot,s as kl,t as aa,u as na,x as _l}from"./chunk-VUSDWZ6L.js";import{a as it,i as cn}from"./chunk-RJ7DASOU.js";import{a as on,b as st,c as ta,d as sn,h as ln}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function la(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function Cr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:la(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Se=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Mt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Se(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ir(t={}){return M({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as A,b as dr,c as pr,d as ur,e as mr,f as _e,g as fr,h as hr,i as It,k as gr,n as xr,o as vr,p as br,q as yr,r as wr,v as kr,w as _r,x as Er,y as Tr,z as Ar}from"./chunk-Q4R4OS5S.js";import{a as Sr}from"./chunk-UVMCAZL7.js";import{a as cr}from"./chunk-QAIYUMHW.js";import{a as Tt,b as z,c as M,h as ve,i as At,j as re,k as K,l as Ct,m as sr,n as ir,o as lr}from"./chunk-N7HKIMMR.js";import{a as or}from"./chunk-2NYP4OQU.js";import{a as ce,b as rr}from"./chunk-JWDJMFU6.js";import{$a as nr,A as vt,B as Dn,E as Hn,F as Bn,Fa as Yn,G as zn,Ha as Ne,Ma as Qn,N as U,O as qn,Oa as De,P as Fn,Pa as wt,Qa as kt,Ra as _t,Sa as St,Ta as Zn,Ua as er,Va as tr,Wa as Et,Ya as ar,a as Tn,c as ut,d as sa,e as An,i as mt,l as Xe,n as Cn,ta as Xn,va as Kn,w as ht,wa as Jn,x as Pn,xa as Vn,y as gt,z as xt}from"./chunk-LKBUTSYP.js";import"./chunk-GTJIKXDB.js";import{g as Sn,h as En}from"./chunk-PS3UB5PH.js";import{a as Nn,b as N,c as Un,d as Wn,h as Gn}from"./chunk-DG5I6PPM.js";import{p as In,t as Mn}from"./chunk-S2GAEH2F.js";import"./chunk-IWEN3YNQ.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as F,c as ke,d as Ln,e as ia}from"./chunk-ACFQBLPX.js";import{g as ft}from"./chunk-LQE73AZR.js";import{b as Rn,c as $n}from"./chunk-2D3RYIDU.js";import{m as jn,n as bt,o as yt,q as On}from"./chunk-E5OV6RTG.js";import{a as xn,f as vn,g as ra,h as oa,l as bn,m as yn,n as wn,u as ct,v as dt,w as pt,x as le,y as _n}from"./chunk-5PFTUGP4.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5EOFTPQB.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-M56MKNAG.js";import{a as kn}from"./chunk-HJUBCA7O.js";import"./chunk-DS7CDASP.js";import"./chunk-T2IDDOSX.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as gn}from"./chunk-OQHC7TJL.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-MIRBKQHA.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{G as dn,J as Al,K as pn,L as un,N as mn,P as fn,T as hn,a as nn,b as rn,c as Sl,ea as X,ha as lt,r as ot,s as El,t as aa,u as na,x as Tl}from"./chunk-VUSDWZ6L.js";import{a as it,i as cn}from"./chunk-RJ7DASOU.js";import{a as on,b as st,c as ta,d as sn,h as ln}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function la(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function Cr(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:la(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},Se=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Mt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+Se(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Ir(t={}){return M({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -85,7 +85,7 @@ ${Mt(oe.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:El,scripts:`<script>${z({decayOf:la,rankByDecay:Cr})}const ICON = ${JSON.stringify(oe)};${Tl}</script>`})}var El=`
88
+ </div>`,css:Cl,scripts:`<script>${z({decayOf:la,rankByDecay:Cr})}const ICON = ${JSON.stringify(oe)};${Il}</script>`})}var Cl=`
89
89
  .bf{max-width:1240px;margin:0 auto;padding:22px 24px 48px}
90
90
  .bf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
91
91
  .bf :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
@@ -361,7 +361,7 @@ button.bf-tag.is-on{background:color-mix(in oklch,var(--ax-accent) 14%,transpare
361
361
  .bf{padding:16px 14px 36px}
362
362
  .bf-head{flex-direction:column;gap:14px;align-items:stretch}
363
363
  .bf-sync{justify-content:space-between}
364
- }`,Tl=String.raw`
364
+ }`,Il=String.raw`
365
365
  (function(){
366
366
  const $=id=>document.getElementById(id), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
367
367
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -776,7 +776,7 @@ if(document.querySelector('form :focus'))return;
776
776
  if(document.querySelector('.bf-trace[open]'))return; // don't yank an open trace
777
777
  refresh();
778
778
  },15000);
779
- })();`;function ca(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function da(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function Mr(t,e=[],a){let{bands:n,gaps:r}=ca(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>da(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Al}from"crypto";import{readFileSync as Cl,statSync as Il}from"fs";import{resolve as Ml,dirname as Ll}from"path";import{fileURLToPath as Rl}from"url";var Lr=new Map;function Lt(t){let e=Lr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Ll(Rl(import.meta.url)),r=Ml(n,"web",t),o=Il(r),s=o.size<8e6?Al("sha1").update(Cl(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Lr.set(t,a),a}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Rt=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",$l=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],Rr={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &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 $r(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return M({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function ca(t,e=20*6e4,a=6){let n=[...t].sort((l,c)=>l.startedAt-c.startedAt);if(!n.length)return{bands:[],gaps:[]};let r=[];for(let l of n){let c=l.startedAt+Math.max(l.durationMs||0,0),p=r[r.length-1];p&&l.startedAt-p.to<=e?(p.to=Math.max(p.to,c),p.runs++):r.push({from:l.startedAt,to:c,runs:1})}for(;r.length>a;){let l=0,c=1/0;for(let p=1;p<r.length;p++){let u=r[p].from-r[p-1].to;u<c&&(c=u,l=p)}r[l-1].to=r[l].to,r[l-1].runs+=r[l].runs,r.splice(l,1)}let o=r.reduce((l,c)=>l+c.runs,0)||1,s=r.map(l=>({from:l.from,to:Math.max(l.to,l.from+1),weight:l.runs/o,runs:l.runs})),i=r.slice(1).map((l,c)=>l.from-r[c].to);return{bands:s,gaps:i}}function da(t){let e=[];for(let a of t.sort((n,r)=>n.startedAt-r.startedAt)){let n=a.startedAt+Math.max(a.durationMs||0,0),r=e.findIndex(o=>o<=a.startedAt);r===-1?(r=e.length,e.push(n)):e[r]=n,a.track=r}return Math.max(e.length,1)}function Mr(t,e=[],a){let{bands:n,gaps:r}=ca(t,a);if(!n.length)return{bands:[],gaps:[],lanes:[],from:0,to:0};let o=new Map;for(let l of e){let c=o.get(l.runId);c?c.push(l):o.set(l.runId,[l])}let s=new Map;for(let l of t){let c=n.findIndex(_=>l.startedAt>=_.from&&l.startedAt<=_.to);if(c===-1)continue;let p=n[c],u=p.to-p.from||1,f=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-f),k=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};k.runs.push({...l,band:c,track:0,left:f,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,k)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>da(l.runs.filter(u=>u.band===p))),1);return i.sort((l,c)=>c.runs.length-l.runs.length||l.label.localeCompare(c.label)),{bands:n,gaps:r,lanes:i,from:n[0].from,to:n[n.length-1].to}}import{createHash as Ml}from"crypto";import{readFileSync as Ll,statSync as Rl}from"fs";import{resolve as $l,dirname as Pl}from"path";import{fileURLToPath as jl}from"url";var Lr=new Map;function Lt(t){let e=Lr.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=Pl(jl(import.meta.url)),r=$l(n,"web",t),o=Rl(r),s=o.size<8e6?Ml("sha1").update(Ll(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Lr.set(t,a),a}var se={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',bot:'<rect x="4" y="8" width="16" height="12" rx="2"/><path d="M12 8V5M9 14h.01M15 14h.01"/>',user:'<circle cx="12" cy="8" r="3.5"/><path d="M5 21a7 7 0 0 1 14 0"/>',folder:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',map:'<path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z"/><path d="M9 4v14M15 6v14"/>',timeline:'<path d="M3 6h10M7 12h14M3 18h8"/>',mesh:'<circle cx="5" cy="19" r="2.5"/><circle cx="19" cy="19" r="2.5"/><circle cx="12" cy="5" r="2.5"/><path d="M7 17.5l4-10M17 17.5l-4-10"/>',route:'<circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h6a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h6"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',x:'<path d="M18 6L6 18M6 6l12 12"/>',alert:'<path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/>'},Rt=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",Ol=[["agent","Agent",se.bot],["client","Client",se.user],["project","Project",se.folder],["channel","Channel",se.route],["person","Person",se.user],["node","Node",se.mesh]],Rr={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &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 $r(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return M({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
780
780
 
781
781
  <div class="ac-head">
782
782
  <div>
@@ -799,7 +799,7 @@ refresh();
799
799
  <div class="ac-bar">
800
800
  <span class="ac-lbl">Lanes by</span>
801
801
  <div class="ac-seg" id="persp" role="radiogroup" aria-label="Perspective">
802
- ${$l.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Rt(o,13)}${r}</button>`).join("")}
802
+ ${Ol.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${Rt(o,13)}${r}</button>`).join("")}
803
803
  </div>
804
804
  <div class="ac-key">
805
805
  <span class="ac-k"><i class="ac-d ac-d--decision"></i>decision</span>
@@ -819,7 +819,7 @@ refresh();
819
819
  <div id="ax-fleet-root" data-hours="24" data-src="${Lt("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:Pl,scripts:`<script>${z({computeBands:ca,packTracks:da,buildTimeline:Mr})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(Rr)};${jl}</script>`})}var Pl=`
822
+ </div>`,css:Nl,scripts:`<script>${z({computeBands:ca,packTracks:da,buildTimeline:Mr})}const ICON = ${JSON.stringify(se)};const SUB = ${JSON.stringify(Rr)};${Dl}</script>`})}var Nl=`
823
823
  .ac{max-width:1440px;margin:0 auto;padding:22px 24px 48px}
824
824
  .ac :focus-visible{outline:2px solid var(--ax-accent);outline-offset:2px;border-radius:4px}
825
825
  .ac-head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:14px}
@@ -905,7 +905,7 @@ refresh();
905
905
  @media (max-width:640px){.ac{padding:16px 16px 32px}.ac-head{flex-direction:column;gap:10px}
906
906
  .ac-tools{flex-wrap:wrap;padding-top:0}.ac-map{height:calc(100vh - 250px);margin:0 -16px;
907
907
  border-left:none;border-right:none;border-radius:0}}
908
- `,jl=String.raw`
908
+ `,Dl=String.raw`
909
909
  const $=id=>document.getElementById(id);
910
910
  const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
911
911
  const ic=(n,s)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+(s||14)+'" height="'+(s||14)+'" aria-hidden="true">'+ICON[n]+'</svg>';
@@ -1024,7 +1024,7 @@ history.replaceState(null,'',u);
1024
1024
  if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
1025
1025
  $('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
1026
1026
  show(view);
1027
- `;function Pr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Ol,scripts:`<script src="${Lt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Ol=`
1027
+ `;function Pr(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return M({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Hl,scripts:`<script src="${Lt("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var Hl=`
1028
1028
  /* Preload the fonts the redesign's CSS references. Placed in the shell so
1029
1029
  * they start fetching while the React bundle is still parsing. */
1030
1030
  @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Instrument+Serif&display=swap");
@@ -1045,8 +1045,101 @@ body { margin: 0; overflow: hidden; }
1045
1045
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1046
1046
  text-align: center;
1047
1047
  }
1048
- `;import{createServer as Am}from"http";import{appendFileSync as Cm,existsSync as pl,mkdirSync as Im}from"fs";import{readFile as Mm}from"fs/promises";import{fileURLToPath as Lm}from"url";import{dirname as Rm,resolve as at}from"path";Sl();function He(t,e){if(!t)return"absent";let a=Ln(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ee=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function $t(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=jr(t.headers["sec-fetch-mode"]),n.site=jr(t.headers["sec-fetch-site"]),n}function jr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Nl}from"zlib";var Dl=[41,121,255],Hl=[255,255,255],Or=new Map;function Be(t){let e=Or.get(t);return e||(e=zl(t,Bl(t)),Or.set(t,e)),e}function Bl(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?Hl:Dl;a.set(c,o*e+1+s*3)}return a}function zl(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),pa("IHDR",a),pa("IDAT",Nl(e)),pa("IEND",Buffer.alloc(0))])}function pa(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Fl(n)),Buffer.concat([a,n,r])}var ql=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 Fl(t){let e=4294967295;for(let a of t)e=ql[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}lt();_l();var Ul=7,Wl={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Gl(t,e){let a=t.toLowerCase().split("@")[0],n=Wl[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Nr(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function Dr(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(u=>u.name==="person"),i=u=>({id:u.id,state:u.state,agentId:u.agent_id,text:u.text,channel:u.channel,chatId:u.chat_id,createdAt:u.created_at,updatedAt:u.updated_at,closedAt:u.closed_at??null,question:u.question??null,attentionReason:u.attention_reason??null,evidence:u.evidence??null,where:{label:Gl(u.channel,u.chat_id),url:a.linkFor?.(u.channel,u.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${aa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...aa).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${na.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
- ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...na,n-Ul*864e5).map(i):[],p=[];try{p=It(t,e,10)}catch{}return{open:l,recent:c,runs:p}}function Hr(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Br(t,e){return!t||e-t>=3e4||t>e}function Pt(t,e){let a="23456789ABCDEFGHJKMNPQRSTUVWXYZ",n=String(t||"").toUpperCase(),r=Math.max(0,Math.min(Number(e)||0,n.length)),o="",s=0;for(let l=0;l<n.length&&o.length<8;l++)a.indexOf(n.charAt(l))<0||(o+=n.charAt(l),l<r&&s++);let i=o.length>4?o.slice(0,4)+"-"+o.slice(4):o;return{value:i,caret:Math.min(s>4?s+1:s,i.length)}}function zr(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}var Xl="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})()</script>";function ua(t){return`<meta charset="utf-8">
1048
+ `;import{createServer as Im}from"http";import{appendFileSync as Mm,existsSync as fl,mkdirSync as Lm}from"fs";import{readFile as Rm}from"fs/promises";import{fileURLToPath as $m}from"url";import{dirname as Pm,resolve as at}from"path";Al();function He(t,e){if(!t)return"absent";let a=Ln(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var Ee=class{constructor(e=r=>console.log(r),a=Date.now,n=6e4){this.log=e;this.now=a;this.everyMs=n}last=new Map;record(e,a){let n=Object.entries(a).map(([i,l])=>`${i}=${l}`).join(" "),r=`${e} ${a.cookie??""} ${a.bearer??""}`,o=this.now(),s=this.last.get(r);s!==void 0&&o-s<this.everyMs||(this.last.size>500&&this.prune(o),this.last.set(r,o),this.log(`[app] unauthenticated ${e} ${n}`))}prune(e){for(let[a,n]of this.last)e-n>=this.everyMs&&this.last.delete(a);this.last.size>500&&this.last.clear()}};function $t(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=jr(t.headers["sec-fetch-mode"]),n.site=jr(t.headers["sec-fetch-site"]),n}function jr(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}import{deflateSync as Bl}from"zlib";var zl=[41,121,255],ql=[255,255,255],Or=new Map;function Be(t){let e=Or.get(t);return e||(e=Ul(t,Fl(t)),Or.set(t,e)),e}function Fl(t){let e=1+t*3,a=Buffer.alloc(e*t),n=t/2,r=t*.22;for(let o=0;o<t;o++)for(let s=0;s<t;s++){let i=s+.5-n,l=o+.5-n,c=i*i+l*l<=r*r?ql:zl;a.set(c,o*e+1+s*3)}return a}function Ul(t,e){let a=Buffer.alloc(13);return a.writeUInt32BE(t,0),a.writeUInt32BE(t,4),a[8]=8,a[9]=2,Buffer.concat([Buffer.from([137,80,78,71,13,10,26,10]),pa("IHDR",a),pa("IDAT",Bl(e)),pa("IEND",Buffer.alloc(0))])}function pa(t,e){let a=Buffer.alloc(4);a.writeUInt32BE(e.length);let n=Buffer.concat([Buffer.from(t,"ascii"),e]),r=Buffer.alloc(4);return r.writeUInt32BE(Gl(n)),Buffer.concat([a,n,r])}var Wl=Array.from({length:256},(t,e)=>{let a=e;for(let n=0;n<8;n++)a=a&1?3988292384^a>>>1:a>>>1;return a>>>0});function Gl(t){let e=4294967295;for(let a of t)e=Wl[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}lt();Tl();var Xl=7,Kl={gitlab:"GitLab",github:"GitHub",telegram:"Telegram",whatsapp:"WhatsApp",slack:"Slack",discord:"Discord",voice:"Voice",app:"Phone app",dashboard:"Dashboard",webrtc:"Call"};function Jl(t,e){let a=t.toLowerCase().split("@")[0],n=Kl[a]??t,r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(r){let o=r[2]==="issue"?"issue":r[2]==="pull"?"pull request":"merge request";return`${n} ${o} #${r[3]} in ${r[1]}`}return n}function Nr(t,e,a){let n=t.toLowerCase().split("@")[0],r=/^(.+):(issue|merge_request|pull):(\d+)$/.exec(e);if(!r)return null;let[,o,s,i]=r;return n==="gitlab"?`${(a.gitlab||"https://gitlab.com").replace(/\/+$/,"")}/${o}/-/${s==="issue"?"issues":"merge_requests"}/${i}`:n==="github"?`${(a.github||"https://github.com").replace(/\/+$/,"")}/${o}/${s==="issue"?"issues":"pull"}/${i}`:null}function Dr(t,e,a={}){let n=a.now??Date.now(),s=(t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?t.prepare("PRAGMA table_info(requests)").all():[]).some(u=>u.name==="person"),i=u=>({id:u.id,state:u.state,agentId:u.agent_id,text:u.text,channel:u.channel,chatId:u.chat_id,createdAt:u.created_at,updatedAt:u.updated_at,closedAt:u.closed_at??null,question:u.question??null,attentionReason:u.attention_reason??null,evidence:u.evidence??null,where:{label:Jl(u.channel,u.chat_id),url:a.linkFor?.(u.channel,u.chat_id)??null}}),l=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${aa.map(()=>"?").join(",")}) ORDER BY created_at, rowid`).all(e,...aa).map(i):[],c=s?t.prepare(`SELECT * FROM requests WHERE person = ? AND state IN (${na.map(()=>"?").join(",")}) AND COALESCE(closed_at, updated_at) >= ?
1049
+ ORDER BY COALESCE(closed_at, updated_at) DESC LIMIT 50`).all(e,...na,n-Xl*864e5).map(i):[],p=[];try{p=It(t,e,10)}catch{}return{open:l,recent:c,runs:p}}function Hr(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function Br(t,e){return!t||e-t>=3e4||t>e}function Pt(t,e){let a="23456789ABCDEFGHJKMNPQRSTUVWXYZ",n=String(t||"").toUpperCase(),r=Math.max(0,Math.min(Number(e)||0,n.length)),o="",s=0;for(let l=0;l<n.length&&o.length<8;l++)a.indexOf(n.charAt(l))<0||(o+=n.charAt(l),l<r&&s++);let i=o.length>4?o.slice(0,4)+"-"+o.slice(4):o;return{value:i,caret:Math.min(s>4?s+1:s,i.length)}}function zr(t){let e=String(t||"").trim(),a=/^https?:[/][/][^/#?]+[/]app[/]pair[/]?#(.*)$/i.exec(e);if(a){let r=a[1].split("&");for(let o=0;o<r.length;o++){if(r[o].indexOf("token=")!==0)continue;let s="";try{s=decodeURIComponent(r[o].slice(6))}catch{return{kind:"none"}}return/^agx_live_[0-9a-f]{64}$/.test(s)?{kind:"token",token:s}:{kind:"none"}}return{kind:"none"}}let n=e.toUpperCase();return/^[A-Z0-9]{4}-?[A-Z0-9]{4}$/.test(n)?{kind:"code",code:n.slice(0,4)+"-"+n.slice(-4)}:{kind:"none"}}function qr(t,e,a,n){return t?e?{text:"Can't reach the server. "+(n?"Showing what was last loaded. ":"")+"Trying again every "+a+" seconds.",retry:!0}:{text:"Offline. Showing what was last loaded; live state needs a connection.",retry:!1}:null}function Fr(t){return String(t??"").replace(/```[\w-]*|`/g,"").replace(/!?\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/^[ \t]*(?:#{1,6}|>+|[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm,"").replace(/\*\*|~~/g,"").replace(/(^|[\s(])\*(\S(?:[^*\n]*\S)?)\*(?=[\s).,;:!?]|$)/gm,"$1$2").replace(/\s+/g," ").trim()}var Ur=`
1050
+ (function () {
1051
+ var POLL_S = 30, RETRY_S = 20, GIVE_UP_MS = 15000;
1052
+ var who = document.getElementById('who');
1053
+ var strip = document.getElementById('offline');
1054
+ var stripText = document.getElementById('offline-text');
1055
+ var retry = document.getElementById('retry');
1056
+ var install = document.getElementById('install');
1057
+ var updated = document.getElementById('updated');
1058
+ var theme = document.getElementById('theme');
1059
+ // No network counts as a failed load until a load works (#496).
1060
+ var failed = navigator.onLine === false, loaded = false, named = false, busy = false, timer = null;
1061
+ theme.addEventListener('click', function () {
1062
+ var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
1063
+ document.documentElement.setAttribute('data-theme', cur);
1064
+ try { localStorage.setItem('ax-theme', cur); } catch (e) {}
1065
+ });
1066
+ if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
1067
+ var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
1068
+ if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
1069
+ function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]; }); }
1070
+ function showConn() {
1071
+ var note = connectionNote(failed, navigator.onLine !== false, RETRY_S, loaded);
1072
+ strip.hidden = !note;
1073
+ if (!note) return;
1074
+ // Same words are not written again: a screen reader would repeat them on every failed round.
1075
+ if (stripText.textContent !== note.text) stripText.textContent = note.text;
1076
+ retry.hidden = !note.retry;
1077
+ }
1078
+ window.addEventListener('online', function () { failed = false; showConn(); load(); });
1079
+ window.addEventListener('offline', function () { failed = true; showConn(); });
1080
+ retry.addEventListener('click', function () { load(); });
1081
+ // A 401 or 403 means this machine's key ended: /member then shows the pairing page.
1082
+ function get(url) {
1083
+ var ac = new AbortController();
1084
+ var giveUp = setTimeout(function () { ac.abort(); }, GIVE_UP_MS);
1085
+ return fetch(url, { credentials: 'same-origin', cache: 'no-store', signal: ac.signal }).then(function (r) {
1086
+ if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
1087
+ if (!r.ok) throw new Error('HTTP ' + r.status);
1088
+ return r.json();
1089
+ }).then(function (j) { clearTimeout(giveUp); return j; }, function (e) { clearTimeout(giveUp); throw e; });
1090
+ }
1091
+ function where(r) {
1092
+ var label = esc(r.where && r.where.label || r.channel);
1093
+ return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
1094
+ }
1095
+ function item(r, now, closed) {
1096
+ var st = workState(r.state);
1097
+ var note = '';
1098
+ if (r.state === 'waiting_owner' && r.question) note = '<p class="note"><b>The owner is asked:</b> ' + esc(r.question) + '</p>';
1099
+ else if (r.state === 'needs_attention' && r.attentionReason) note = '<p class="note">' + esc(r.attentionReason) + '</p>';
1100
+ else if (closed && r.evidence) note = /^https?:\\/\\//i.test(r.evidence)
1101
+ ? '<p class="note"><a href="' + esc(r.evidence) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>'
1102
+ : '<p class="note"><b>What was delivered:</b> ' + esc(r.evidence) + '</p>';
1103
+ var age = closed ? 'closed ' + ageText(r.closedAt || r.updatedAt, now) + ' ago' : 'for ' + ageText(r.createdAt, now);
1104
+ return '<li class="item"><p class="text">' + esc(r.text) + '</p>' +
1105
+ '<p class="meta"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span>' + esc(r.agentId) + '</span><span>' + age + '</span><span>asked on ' + where(r) + '</span></p>' + note + '</li>';
1106
+ }
1107
+ function run(r, now) {
1108
+ var mark = r.status === 'ok' ? 'finished' : r.status === 'in-flight' ? 'running' : esc(r.status);
1109
+ return '<li class="item"><p class="text">' + esc(plainPreview(r.messagePreview)) + '</p><p class="meta"><span class="state ' + (r.status === 'ok' ? 'ok' : r.status === 'in-flight' ? 'warn' : 'bad') + '">' + mark + '</span><span>' + esc(r.agentId) + '</span><span>' + ageText(r.startedAt, now) + ' ago</span><span>' + esc(r.channel || '') + '</span></p></li>';
1110
+ }
1111
+ function fill(id, html, empty) { document.getElementById(id).innerHTML = html || '<li class="muted">' + empty + '</li>'; }
1112
+ function loadName() {
1113
+ if (named) return;
1114
+ get('/api/member/me').then(function (me) {
1115
+ if (!me) return;
1116
+ named = true;
1117
+ who.textContent = me.name + ' \xB7 ' + me.device + (me.node ? ' \xB7 ' + me.node : '');
1118
+ }).catch(function () { /* the next round asks again; the work load of this round reports the failure */ });
1119
+ }
1120
+ function load() {
1121
+ if (busy) return;
1122
+ busy = true; retry.disabled = true; clearTimeout(timer);
1123
+ loadName();
1124
+ get('/api/member/work').then(function (w) {
1125
+ if (!w) return;
1126
+ failed = false;
1127
+ var now = Date.now();
1128
+ document.getElementById('n-open').textContent = w.open.length ? '(' + w.open.length + ')' : '';
1129
+ fill('open', w.open.map(function (r) { return item(r, now, false); }).join(''), 'Nothing open. What you ask the agents for shows up here while it is being worked on.');
1130
+ fill('recent', w.recent.map(function (r) { return item(r, now, true); }).join(''), 'Nothing finished in the last 7 days.');
1131
+ fill('runs', w.runs.map(function (r) { return run(r, now); }).join(''), 'No turns recorded yet.');
1132
+ updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString();
1133
+ loaded = true;
1134
+ }).catch(function () { failed = true; }).then(function () {
1135
+ busy = false; retry.disabled = false; showConn();
1136
+ timer = setTimeout(load, (failed ? RETRY_S : POLL_S) * 1000);
1137
+ });
1138
+ }
1139
+ showConn();
1140
+ load();
1141
+ })();
1142
+ `;var Vl="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})()</script>";function ua(t){return`<meta charset="utf-8">
1050
1143
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
1051
1144
  <meta name="theme-color" content="#2979FF">
1052
1145
  <meta name="referrer" content="no-referrer">
@@ -1056,8 +1149,8 @@ body { margin: 0; overflow: hidden; }
1056
1149
  <link rel="icon" type="image/png" href="/member/icon-192.png">
1057
1150
  <link rel="apple-touch-icon" href="/member/icon-192.png">
1058
1151
  <title>${t}</title>
1059
- ${Xl}
1060
- <style>${Tt}${Vl}</style>`}function qr(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Fr=`
1152
+ ${Vl}
1153
+ <style>${Tt}${Zl}</style>`}function Wr(){return JSON.stringify({id:"/member",name:"My work \xB7 AgentX",short_name:"My work",description:"What you asked the agents for, and where it stands.",start_url:"/member",scope:"/member",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/member/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/member/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var Gr=`
1061
1154
  var CACHE = 'agentx-member-v1';
1062
1155
  var STATIC = ['/member/manifest.webmanifest', '/member/icon-192.png', '/member/icon-512.png'];
1063
1156
  self.addEventListener('install', function (e) {
@@ -1087,15 +1180,15 @@ self.addEventListener('fetch', function (e) {
1087
1180
  e.respondWith(caches.match(url.pathname).then(function (hit) { return hit || fetch(req); }));
1088
1181
  }
1089
1182
  });
1090
- `;function Ur(){return`<!doctype html>
1183
+ `;function Xr(){return`<!doctype html>
1091
1184
  <html lang="en">
1092
- <head>${ua("My work \xB7 AgentX")}<style>${Yl}</style></head>
1185
+ <head>${ua("My work \xB7 AgentX")}<style>${ec}</style></head>
1093
1186
  <body>
1094
1187
  <header class="bar">
1095
1188
  <div><h1>My work</h1><p id="who" class="who">Connecting\u2026</p></div>
1096
1189
  <button type="button" id="theme" class="icon-btn" aria-label="Switch theme">\u25D0</button>
1097
1190
  </header>
1098
- <p id="offline" class="offline" role="status" hidden>Offline. Showing what was last loaded; live state needs a connection.</p>
1191
+ <p id="offline" class="offline" role="status" hidden><span id="offline-text"></span> <button type="button" id="retry" hidden>Try now</button></p>
1099
1192
  <p id="install" class="install" hidden>To keep this window on your desktop: in Edge or Chrome open the browser menu, then <b>Apps</b>, then <b>Install this site as an app</b>.</p>
1100
1193
  <main>
1101
1194
  <section aria-labelledby="h-open"><h2 id="h-open">Open <span id="n-open" class="count"></span></h2><ul id="open" class="list"><li class="muted">Loading\u2026</li></ul></section>
@@ -1103,11 +1196,11 @@ self.addEventListener('fetch', function (e) {
1103
1196
  <section aria-labelledby="h-runs"><h2 id="h-runs">Latest turns</h2><ul id="runs" class="list"><li class="muted">Loading\u2026</li></ul></section>
1104
1197
  <p id="updated" class="muted small"></p>
1105
1198
  </main>
1106
- <script>${z({workState:Kl,ageText:Jl})}${tc}</script>
1199
+ <script>${z({workState:Yl,ageText:Ql,connectionNote:qr,plainPreview:Fr})}${Ur}</script>
1107
1200
  </body>
1108
- </html>`}function Wr(){return`<!doctype html>
1201
+ </html>`}function Kr(){return`<!doctype html>
1109
1202
  <html lang="en">
1110
- <head>${ua("Pair this machine \xB7 AgentX")}<style>${Ql}</style></head>
1203
+ <head>${ua("Pair this machine \xB7 AgentX")}<style>${tc}</style></head>
1111
1204
  <body>
1112
1205
  <main class="card">
1113
1206
  <h1>Pair this machine</h1>
@@ -1124,9 +1217,9 @@ self.addEventListener('fetch', function (e) {
1124
1217
  </form>
1125
1218
  <p class="muted">No code? Ask the owner to run <code>agentx people invite &lt;you&gt;</code>. A code works once, for 10 minutes.</p>
1126
1219
  </main>
1127
- <script>${z({formatPairInput:Pt})}${Zl}</script>
1220
+ <script>${z({formatPairInput:Pt})}${ac}</script>
1128
1221
  </body>
1129
- </html>`}function Gr(){return`<!doctype html>
1222
+ </html>`}function Jr(){return`<!doctype html>
1130
1223
  <html lang="en">
1131
1224
  <head>${ua("Waiting for the owner \xB7 AgentX")}</head>
1132
1225
  <body>
@@ -1135,9 +1228,9 @@ self.addEventListener('fetch', function (e) {
1135
1228
  <p id="msg" role="status">This machine is paired. The owner has to approve it once; this page opens by itself when they do.</p>
1136
1229
  <p class="muted">If they said no, this page will ask for a new code.</p>
1137
1230
  </main>
1138
- <script>${ec}</script>
1231
+ <script>${nc}</script>
1139
1232
  </body>
1140
- </html>`}function Kl(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function Jl(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min":Math.floor(r/24)+" d "+r%24+" h"}var Vl=`
1233
+ </html>`}function Yl(t){let e=String(t||"");return e==="in_progress"?{label:"In progress",tone:"ok"}:e==="waiting_owner"?{label:"Waiting on the owner",tone:"warn"}:e==="waiting_other"?{label:"Waiting on another agent",tone:"warn"}:e==="needs_attention"?{label:"Stuck: needs attention",tone:"bad"}:e==="done"?{label:"Done",tone:"ok"}:e==="declined"?{label:"Declined",tone:"bad"}:e==="dropped"?{label:"Dropped",tone:"muted"}:{label:e.replace(/_/g," "),tone:"muted"}}function Ql(t,e){let a=Math.max(0,Number(e)-Number(t)),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return n+" min";let r=Math.floor(n/60);return r<24?r+" h "+n%60+" min":Math.floor(r/24)+" d "+r%24+" h"}var Zl=`
1141
1234
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
1142
1235
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
1143
1236
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -1146,13 +1239,15 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
1146
1239
  .muted { color: var(--ax-text-2); }
1147
1240
  .small { font-size: var(--ax-fs-xs); }
1148
1241
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
1149
- `,Yl=`
1242
+ `,ec=`
1150
1243
  body { display: flex; flex-direction: column; }
1151
1244
  .bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; background: var(--ax-surface); border-bottom: var(--ax-border-w) solid var(--ax-border); }
1152
1245
  .bar h1 { font-size: 18px; margin: 0; font-weight: 700; }
1153
1246
  .who { margin: 2px 0 0; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
1154
1247
  .icon-btn { min-width: 44px; min-height: 44px; font-size: 20px; line-height: 1; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius-pill); background: var(--ax-surface-2); color: var(--ax-text); cursor: pointer; }
1155
1248
  .offline, .install { margin: 0; padding: 8px 16px; font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border-bottom: 1px solid var(--ax-amber-e); }
1249
+ .offline button { margin-left: 8px; min-height: 32px; padding: 4px 14px; font: inherit; font-weight: 600; color: inherit; background: transparent; border: 1px solid currentColor; border-radius: var(--ax-radius-pill); cursor: pointer; }
1250
+ .offline button:disabled { opacity: 0.55; cursor: default; }
1156
1251
  .install { background: var(--ax-surface-2); color: var(--ax-text-2); border-bottom: var(--ax-border-w) solid var(--ax-border); }
1157
1252
  main { flex: 1; overflow-y: auto; padding: 16px; max-width: 720px; width: 100%; box-sizing: border-box; margin: 0 auto; }
1158
1253
  main h2 { font-size: 16px; margin: 12px 0 8px; }
@@ -1169,7 +1264,7 @@ main h2 { font-size: 16px; margin: 12px 0 8px; }
1169
1264
  [data-theme="dark"] .state.bad { color: var(--ax-red); }
1170
1265
  .state.muted { color: var(--ax-text-2); }
1171
1266
  a { color: var(--ax-accent); }
1172
- `,Ql=`
1267
+ `,tc=`
1173
1268
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
1174
1269
  .pair-form label { font-weight: 600; }
1175
1270
  .pair-form input { box-sizing: border-box; width: 100%; min-height: 48px; padding: 10px 14px; font: inherit; font-size: 17px; color: var(--ax-text); background: var(--ax-surface); border: 2px solid var(--ax-border); border-radius: var(--ax-radius-sm); }
@@ -1181,7 +1276,7 @@ a { color: var(--ax-accent); }
1181
1276
  .pair-msg.bad { color: var(--ax-red-ink); }
1182
1277
  [data-theme="dark"] .pair-msg.bad { color: var(--ax-red); }
1183
1278
  .pair-offline { margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm); background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e); }
1184
- `,Zl=`
1279
+ `,ac=`
1185
1280
  (function () {
1186
1281
  var form = document.getElementById('pair-form');
1187
1282
  var machine = document.getElementById('machine');
@@ -1225,7 +1320,7 @@ a { color: var(--ax-accent); }
1225
1320
  }).catch(function () { busy = false; btn.disabled = false; say('No connection. Check the private network and try again.', true); });
1226
1321
  });
1227
1322
  })();
1228
- `,ec=`
1323
+ `,nc=`
1229
1324
  (function () {
1230
1325
  var msg = document.getElementById('msg');
1231
1326
  function check() {
@@ -1236,71 +1331,10 @@ a { color: var(--ax-accent); }
1236
1331
  }
1237
1332
  setInterval(check, 5000);
1238
1333
  })();
1239
- `,tc=`
1240
- (function () {
1241
- var who = document.getElementById('who');
1242
- var offline = document.getElementById('offline');
1243
- var install = document.getElementById('install');
1244
- var updated = document.getElementById('updated');
1245
- var theme = document.getElementById('theme');
1246
- theme.addEventListener('click', function () {
1247
- var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
1248
- document.documentElement.setAttribute('data-theme', cur);
1249
- try { localStorage.setItem('ax-theme', cur); } catch (e) {}
1250
- });
1251
- if ('serviceWorker' in navigator) { try { navigator.serviceWorker.register('/member/sw.js', { scope: '/member' }); } catch (e) {} }
1252
- var standalone = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
1253
- if (!standalone && /Windows|Macintosh|Linux/.test(navigator.userAgent) && !/Mobile/.test(navigator.userAgent)) install.hidden = false;
1254
- function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]; }); }
1255
- function setOnline(on) { offline.hidden = on; }
1256
- window.addEventListener('online', function () { setOnline(true); load(); });
1257
- window.addEventListener('offline', function () { setOnline(false); });
1258
- function where(r) {
1259
- var label = esc(r.where && r.where.label || r.channel);
1260
- return r.where && r.where.url ? '<a href="' + esc(r.where.url) + '" target="_blank" rel="noopener noreferrer">' + label + '</a>' : label;
1261
- }
1262
- function item(r, now, closed) {
1263
- var st = workState(r.state);
1264
- var note = '';
1265
- if (r.state === 'waiting_owner' && r.question) note = '<p class="note"><b>The owner is asked:</b> ' + esc(r.question) + '</p>';
1266
- else if (r.state === 'needs_attention' && r.attentionReason) note = '<p class="note">' + esc(r.attentionReason) + '</p>';
1267
- else if (closed && r.evidence) note = /^https?:\\/\\//i.test(r.evidence)
1268
- ? '<p class="note"><a href="' + esc(r.evidence) + '" target="_blank" rel="noopener noreferrer">What was delivered</a></p>'
1269
- : '<p class="note"><b>What was delivered:</b> ' + esc(r.evidence) + '</p>';
1270
- var age = closed ? 'closed ' + ageText(r.closedAt || r.updatedAt, now) + ' ago' : 'for ' + ageText(r.createdAt, now);
1271
- return '<li class="item"><p class="text">' + esc(r.text) + '</p>' +
1272
- '<p class="meta"><span class="state ' + st.tone + '">' + esc(st.label) + '</span><span>' + esc(r.agentId) + '</span><span>' + age + '</span><span>asked on ' + where(r) + '</span></p>' + note + '</li>';
1273
- }
1274
- function run(r, now) {
1275
- var mark = r.status === 'ok' ? 'finished' : r.status === 'in-flight' ? 'running' : esc(r.status);
1276
- return '<li class="item"><p class="text">' + esc(r.messagePreview || '') + '</p><p class="meta"><span class="state ' + (r.status === 'ok' ? 'ok' : r.status === 'in-flight' ? 'warn' : 'bad') + '">' + mark + '</span><span>' + esc(r.agentId) + '</span><span>' + ageText(r.startedAt, now) + ' ago</span><span>' + esc(r.channel || '') + '</span></p></li>';
1277
- }
1278
- function fill(id, html, empty) { document.getElementById(id).innerHTML = html || '<li class="muted">' + empty + '</li>'; }
1279
- function load() {
1280
- fetch('/api/member/work', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) {
1281
- if (r.status === 401 || r.status === 403) { location.replace('/member'); return null; }
1282
- return r.json();
1283
- }).then(function (w) {
1284
- if (!w) return;
1285
- setOnline(true);
1286
- var now = Date.now();
1287
- document.getElementById('n-open').textContent = w.open.length ? '(' + w.open.length + ')' : '';
1288
- fill('open', w.open.map(function (r) { return item(r, now, false); }).join(''), 'Nothing open. What you ask the agents for shows up here while it is being worked on.');
1289
- fill('recent', w.recent.map(function (r) { return item(r, now, true); }).join(''), 'Nothing finished in the last 7 days.');
1290
- fill('runs', w.runs.map(function (r) { return run(r, now); }).join(''), 'No turns recorded yet.');
1291
- updated.textContent = 'Updated ' + new Date(now).toLocaleTimeString();
1292
- }).catch(function () { setOnline(false); });
1293
- }
1294
- fetch('/api/member/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.ok ? r.json() : null; }).then(function (me) {
1295
- if (me) who.textContent = me.name + ' \xB7 ' + me.device + (me.node ? ' \xB7 ' + me.node : '');
1296
- }).catch(function () {});
1297
- load();
1298
- setInterval(load, 30000);
1299
- })();
1300
- `;var jt="agentx_member",ac=90*86400,nc=new yt,Vr=t=>t.replace(/^\[app\]/,"[member]"),rc=new Ee(t=>console.log(Vr(t))),Xr=new WeakMap;function oc(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return rc;let e=Xr.get(t.log);return e||Xr.set(t.log,e=new Ee(a=>t.log(Vr(a)))),e}var Kr=null;function Ke(t,e=X){try{return Kr=e().people}catch{return Kr??t}}async function Yr(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new ct(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ft(r.root),limiter:r.pairLimiter??nc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",qr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",Fr);if(a==="/member/icon-192.png")return be(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/member/icon-512.png")return be(e,200,"image/png",Be(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await vr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Jr(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Te(e,p.status,p.body)}let l=yr(sc(t),i,xr(t));if(!l.ok){if(l.status===401){let p=ma(t);return oc(r).record(a.slice(0,120),$t(t,He(fa(t,jt),o),p?He(p,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",Wr()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?be(e,202,"text/html; charset=utf-8",Gr()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=fa(t,jt);return p&&!ma(t)&&e.setHeader("Set-Cookie",Jr(p)),be(e,200,"text/html; charset=utf-8",Ur())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;return p?Te(e,200,Dr(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Te(e,503,{error:"the work list needs the database"})}return Te(e,404,{error:"not found"})}function Jr(t){return`${jt}=${t}; Path=/; Max-Age=${ac}; HttpOnly; Secure; SameSite=Lax`}function sc(t){return ma(t)??fa(t,jt)}function ma(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function fa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function be(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return be(t,e,"application/json",JSON.stringify(a))}wl();var Qr='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Nt,readFileSync as so,writeFileSync as io,rmSync as lh,mkdirSync as uc,copyFileSync as mc,readdirSync as fc}from"fs";import{resolve as ze}from"path";kl();function eo(t){let e=ot.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ot.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function Ot(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=ot.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var Zr=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function to(t){return Ot(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function ao(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ot((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:Zr(t?.chats),senders:Zr(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function no(t){let e=String(t?.id??"");return Ot(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function ro(t){let e=String(t?.id??"");return Ot(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}lt();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function oo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+At([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+lc()+sr,css:dc,scripts:`${e}<script>${ir}
1334
+ `;var jt="agentx_member",rc=90*86400,oc=new yt,Zr=t=>t.replace(/^\[app\]/,"[member]"),sc=new Ee(t=>console.log(Zr(t))),Vr=new WeakMap;function ic(t){if(t.rejectLog)return t.rejectLog;if(!t.log)return sc;let e=Vr.get(t.log);return e||Vr.set(t.log,e=new Ee(a=>t.log(Zr(a)))),e}var Yr=null;function Ke(t,e=X){try{return Yr=e().people}catch{return Yr??t}}async function eo(t,e,a,n,r){if(a!=="/member"&&!a.startsWith("/member/")&&!a.startsWith("/api/member/"))return!1;let o=r.tokens??new F(r.root),s=r.members??new ct(r.root),i={tokens:o,members:s,people:r.people,root:r.root,codes:r.pairCodes??new ft(r.root),limiter:r.pairLimiter??oc,minMs:r.pairMinMs,log:r.log,now:r.now};if(n==="GET"){if(a==="/member/manifest.webmanifest")return be(e,200,"application/manifest+json",Wr());if(a==="/member/sw.js")return e.setHeader("Service-Worker-Allowed","/member"),be(e,200,"text/javascript; charset=utf-8",Gr);if(a==="/member/icon-192.png")return be(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/member/icon-512.png")return be(e,200,"image/png",Be(512),"public, max-age=86400")}if(n==="POST"&&a==="/api/member/pair-code"){let p=await vr(t,i);return p.status===200&&e.setHeader("Set-Cookie",Qr(p.token)),p.status===429&&e.setHeader("Retry-After",String(p.retryAfter)),Te(e,p.status,p.body)}let l=yr(lc(t),i,xr(t));if(!l.ok){if(l.status===401){let p=ma(t);return ic(r).record(a.slice(0,120),$t(t,He(fa(t,jt),o),p?He(p,o):null)),a==="/member"?be(e,401,"text/html; charset=utf-8",Kr()):Te(e,401,{error:l.error,hint:"ask the owner to run: agentx people invite <you>"})}return a==="/member"?be(e,202,"text/html; charset=utf-8",Jr()):Te(e,403,{error:l.error,waiting:!0})}let c=r.people().find(p=>p.id===l.personId);if(n==="GET"&&a==="/member"){let p=fa(t,jt);return p&&!ma(t)&&e.setHeader("Set-Cookie",Qr(p)),be(e,200,"text/html; charset=utf-8",Xr())}if(n==="GET"&&a==="/api/member/me")return Te(e,200,{person:l.personId,name:c?.name??l.personId,device:l.device.name,since:l.device.approvedAt??l.device.createdAt,node:r.nodeName??null});if(n==="GET"&&a==="/api/member/work"){let p=r.db?.()??null;return p?Te(e,200,Dr(p,l.personId,{now:(r.now??Date.now)(),linkFor:r.linkFor})):Te(e,503,{error:"the work list needs the database"})}return Te(e,404,{error:"not found"})}function Qr(t){return`${jt}=${t}; Path=/; Max-Age=${rc}; HttpOnly; Secure; SameSite=Lax`}function lc(t){return ma(t)??fa(t,jt)}function ma(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function fa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function be(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Te(t,e,a){return be(t,e,"application/json",JSON.stringify(a))}Sl();var to='/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */\n!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,t=i[n=t],n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t}).apply(this,arguments)}function i(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};for(var n,o={},i=Object.keys(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function r(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return l(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),s=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),c=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1};function h(t,e,n){t.addEventListener(e,n,!y&&d)}function f(t,e,n){t.removeEventListener(e,n,!y&&d)}function p(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=v(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ft.ghost&&(o||a[r]!==Ft.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ft.ghost||"none"===R(n,"display")||e&&!p(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ft.clone||e&&!p(t,e)||n++;return n}function E(t){var e=0,n=0,o=O();if(t)do{var i=v(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function D(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function S(e,n){return function(){var t;g||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),g=setTimeout(function(){g=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function _(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function C(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function T(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function x(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ft.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=v(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&D(r,i)&&!D(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),D(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=v(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var A=[],N={initializeByDefault:!0},W={mount:function(e){for(var t in N)!N.hasOwnProperty(t)||t in e||(e[t]=N[t]);A.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),A.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";A.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in A.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return A.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return A.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function z(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),W.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function G(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=i(o,U);W.pluginEvent.bind(Ft)(t,e,I({dragEl:V,parentEl:Z,ghostEl:$,rootEl:Q,nextEl:J,lastDownEl:tt,cloneEl:et,cloneHidden:nt,dragStarted:gt,putSortable:st,activeSortable:Ft.active,originalEvent:n,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at,hideGhostForTarget:Rt,unhideGhostForTarget:Xt,cloneNowHidden:function(){nt=!0},cloneNowShown:function(){nt=!1},dispatchSortableEvent:function(t){q({sortable:e,name:t,originalEvent:n})}},o))}var U=["evt"];function q(t){z(I({putSortable:st,cloneEl:et,targetEl:V,rootEl:Q,oldIndex:ot,oldDraggableIndex:rt,newIndex:it,newDraggableIndex:at},t))}var V,Z,$,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt=!1,Et=!1,Dt=[],St=!1,_t=!1,Ct=[],Tt=!1,xt=[],Ot="undefined"!=typeof document,Mt=n,At=w||y?"cssFloat":"float",Nt=Ot&&!c&&!n&&"draggable"in document.createElement("div"),It=function(){if(Ot){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Pt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[At]||r&&"none"===n[At]&&o<s+t)?"vertical":"horizontal"},kt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Rt=function(){!It&&$&&R($,"display","none")},Xt=function(){!It&&$&&R($,"display","")};Ot&&!c&&document.addEventListener("click",function(t){if(Et)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Et=!1},!0);function Yt(t){if(V){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,Dt.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}$&&(r?(r.e+=a-(dt||0),r.f+=l-(ht||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R($,"webkitTransform",r),R($,"mozTransform",r),R($,"msTransform",r),R($,"transform",r),dt=a,ht=l,ut=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!$){var t=this.options.fallbackOnBody?document.body:Q,e=X(V,!0,Mt,!0,t),n=this.options;if(Mt){for(yt=t;"static"===R(yt,"position")&&"none"===R(yt,"transform")&&yt!==document;)yt=yt.parentNode;yt!==document.body&&yt!==document.documentElement?(yt===document&&(yt=O()),e.top+=yt.scrollTop,e.left+=yt.scrollLeft):yt=O(),Ct=E(yt)}k($=V.cloneNode(!0),n.ghostClass,!1),k($,n.fallbackClass,!0),k($,n.dragClass,!0),R($,"transition",""),R($,"transform",""),R($,"box-sizing","border-box"),R($,"margin",0),R($,"top",e.top),R($,"left",e.left),R($,"width",e.width),R($,"height",e.height),R($,"opacity","0.8"),R($,"position",Mt?"absolute":"fixed"),R($,"zIndex","100000"),R($,"pointerEvents","none"),Ft.ghost=$,t.appendChild($),R($,"transform-origin",ft/parseInt($.style.width)*100+"% "+pt/parseInt($.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;G("dragStart",this,{evt:t}),Ft.eventCanceled?this._onDrop():(G("setupClone",this),Ft.eventCanceled||((et=_(V)).removeAttribute("id"),et.draggable=!1,et.style["will-change"]="",this._hideClone(),k(et,this.options.chosenClass,!1),Ft.clone=et),n.cloneId=Kt(function(){G("clone",n),Ft.eventCanceled||(n.options.removeCloneOnHide||Q.insertBefore(et,V),n._hideClone(),q({sortable:n,name:"clone"}))}),e||k(V,i.dragClass,!0),e?(Et=!0,n._loopId=setInterval(n._emulateDragOver,50)):(f(document,"mouseup",n._onDrop),f(document,"touchend",n._onDrop),f(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,V)),h(document,"drop",n),R(V,"transform","translateZ(0)")),wt=!0,n._dragStartId=Kt(n._dragStarted.bind(n,e,t)),h(document,"selectstart",n),gt=!0,u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ft.active,d=lt===c,h=s.sort,f=st||u,p=this,g=!1;if(!Tt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ft.eventCanceled)return g;if(V.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(Et=!1,u&&!s.disabled&&(d?h||(i=Z!==Q):st===this||(this.lastPutMode=lt.checkPull(this,u,V,n))&&c.checkPut(this,u,V,n))){if(r="vertical"===this._getDirection(n,l),o=X(V),O("dragOverValid"),Ft.eventCanceled)return g;if(i)return Z=Q,M(),this._hideClone(),O("revert"),Ft.eventCanceled||(J?Q.insertBefore(V,J):Q.appendChild(V)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((D=this).el,D.options.draggable)),D=L(D.el,D.options,$),!(c?S.clientX>D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===V)return A(!1);if(E=X(l=v),!1!==jt(Q,a,V,o,l,E,n,!1))return M(),a.insertBefore(V,v),Z=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,E=X(l),D=V.parentNode!==a,S=(S=V.animated&&V.toRect||o,x=l.animated&&l.toRect||E,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y(V,"top","top"),v=C?C.scrollTop:void 0;if(mt!==l&&(y=E[_],St=!1,_t=!S&&s.invertSwap||D),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&bt<c*i){if(St=!St&&(1===vt?t+c*r/2<s:s<o-c*r/2)?!0:St)n=!0;else if(1===vt?s<t+bt:o-bt<s)return-vt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j(V)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,E,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,_t,mt===l)))for(var T=j(V);(w=Z.children[T-=b])&&("none"===R(w,"display")||w===$););if(0===b||w===l)return A(!1);vt=b;var x=(mt=l).nextElementSibling,D=!1,S=jt(Q,a,V,o,l,E,n,D=1===b);if(!1!==S)return 1!==S&&-1!==S||(D=1===S),Tt=!0,setTimeout(Lt,30),M(),D&&!x?a.appendChild(V):l.parentNode.insertBefore(V,D?x:l),C&&H(C,0,v-C.scrollTop),Z=V.parentNode,void 0===y||_t||(bt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===V)return A(!1);if((l=m&&a===n.target?m:l)&&(E=X(l)),!1!==jt(Q,a,V,o,l,E,n,!!l))return M(),m&&m.nextSibling?a.insertBefore(V,m.nextSibling):a.appendChild(V),Z=a,N(),A(!0)}if(a.contains(V))return A(!1)}return!1}function O(t,e){G(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:E,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return jt(Q,a,V,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k(V,(st||u).options.ghostClass,!1),k(V,s.ghostClass,!0)),st!==p&&p!==Ft.active?st=p:p===Ft.active&&st&&(st=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===V&&!V.animated||l===a&&!l.animated)&&(mt=null),s.dragoverBubble||n.rootEl||l===document||(V.parentNode[K]._isOutsideThisEl(n.target),t||Yt(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){it=j(V),at=j(V,s.draggable),q({sortable:p,name:"change",toEl:a,newIndex:it,newDraggableIndex:at,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){f(document,"mousemove",this._onTouchMove),f(document,"touchmove",this._onTouchMove),f(document,"pointermove",this._onTouchMove),f(document,"dragover",Yt),f(document,"mousemove",Yt),f(document,"touchmove",Yt)},_offUpEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._onDrop),f(t,"touchend",this._onDrop),f(t,"pointerup",this._onDrop),f(t,"touchcancel",this._onDrop),f(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;it=j(V),at=j(V,n.draggable),G("drop",this,{evt:t}),Z=V&&V.parentNode,it=j(V),at=j(V,n.draggable),Ft.eventCanceled||(St=_t=wt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Wt(this.cloneId),Wt(this._dragStartId),this.nativeDraggable&&(f(document,"drop",this),f(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R(V,"transform",""),t&&(gt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),$&&$.parentNode&&$.parentNode.removeChild($),(Q===Z||st&&"clone"!==st.lastPutMode)&&et&&et.parentNode&&et.parentNode.removeChild(et),V&&(this.nativeDraggable&&f(V,"dragend",this),Ht(V),V.style["will-change"]="",gt&&!wt&&k(V,(st||this).options.ghostClass,!1),k(V,this.options.chosenClass,!1),q({sortable:this,name:"unchoose",toEl:Z,newIndex:null,newDraggableIndex:null,originalEvent:t}),Q!==Z?(0<=it&&(q({rootEl:Z,name:"add",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"remove",toEl:Z,originalEvent:t}),q({rootEl:Z,name:"sort",toEl:Z,fromEl:Q,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),st&&st.save()):it!==ot&&0<=it&&(q({sortable:this,name:"update",toEl:Z,originalEvent:t}),q({sortable:this,name:"sort",toEl:Z,originalEvent:t})),Ft.active&&(null!=it&&-1!==it||(it=ot,at=rt),q({sortable:this,name:"end",toEl:Z,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){G("nulling",this),Q=V=Z=$=J=et=tt=nt=ct=ut=gt=it=at=ot=rt=mt=vt=st=lt=Ft.dragged=Ft.ghost=Ft.clone=Ft.active=null,xt.forEach(function(t){t.checked=!0}),xt.length=dt=ht=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":V&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=W.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&kt(n)},destroy:function(){G("destroy",this);var t=this.el;t[K]=null,f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart),f(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),Dt.splice(Dt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){nt||(G("hideClone",this),Ft.eventCanceled||(R(et,"display","none"),this.options.removeCloneOnHide&&et.parentNode&&et.parentNode.removeChild(et),nt=!0))},_showClone:function(t){"clone"===t.lastPutMode?nt&&(G("showClone",this),Ft.eventCanceled||(V.parentNode!=Q||this.options.group.revertClone?J?Q.insertBefore(et,J):Q.appendChild(et):Q.insertBefore(et,V),this.options.group.revertClone&&this.animate(V,et),R(et,"display",""),nt=!1)):this._hideClone()}},Ot&&h(document,"touchmove",function(t){(Ft.active||wt)&&t.cancelable&&t.preventDefault()}),Ft.utils={on:h,off:f,css:R,find:b,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:S,closest:P,toggleClass:k,clone:_,index:j,nextTick:Kt,cancelNextTick:Wt,detectDirection:Pt,getChild:B},Ft.get=function(t){return t[K]},Ft.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ft.utils=I(I({},Ft.utils),t.utils)),W.mount(t)})},Ft.create=function(t,e){return new Ft(t,e)};var zt,Gt,Ut,qt,Vt,Zt,$t=[],Qt=!(Ft.version="1.15.2");function Jt(){$t.forEach(function(t){clearInterval(t.pid)}),$t=[]}function te(){clearInterval(Zt)}var ee,ne=S(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;Gt!==e&&(Gt=e,Jt(),zt=t.scroll,i=t.scrollFn,!0===zt&&(zt=M(e,!0)));var d=0,h=zt;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=D&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!$t[d])for(var x=0;x<=d;x++)$t[x]||($t[x]={});$t[d].vx==T&&$t[d].vy==p&&$t[d].el===f||($t[d].el=f,$t[d].vx=T,$t[d].vy=p,clearInterval($t[d].pid),0==T&&0==p||(u=!0,$t[d].pid=setInterval(function(){o&&0===this.layer&&Ft.active._onTouchMove(Vt);var t=$t[this.layer].vy?$t[this.layer].vy*s:0,e=$t[this.layer].vx?$t[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ft.dragged.parentNode[K],e,t,n,Vt,$t[this.layer].el)||H($t[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));Qt=u}},30),c=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function oe(){}function ie(){}oe.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:c},a(oe,{pluginName:"revertOnSpill"}),ie.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:c},a(ie,{pluginName:"removeOnSpill"});var re,ae,le,se,ce,ue=[],de=[],he=!1,fe=!1,pe=!1;function ge(n,o){de.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function me(){ue.forEach(function(t){t!==le&&t.parentNode&&t.parentNode.removeChild(t)})}return Ft.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?h(document,"dragover",this._handleAutoScroll):this.options.supportPointer?h(document,"pointermove",this._handleFallbackAutoScroll):t.touches?h(document,"touchmove",this._handleFallbackAutoScroll):h(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):(f(document,"pointermove",this._handleFallbackAutoScroll),f(document,"touchmove",this._handleFallbackAutoScroll),f(document,"mousemove",this._handleFallbackAutoScroll)),te(),Jt(),clearTimeout(g),g=void 0},nulling:function(){Vt=Gt=zt=Qt=Zt=Ut=qt=null,$t.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);Vt=e,n||this.options.forceAutoScrollFallback||w||y||u?(ne(e,this.options,t,n),o=M(t,!0),!Qt||Zt&&r===Ut&&a===qt||(Zt&&te(),Zt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,Jt()),ne(e,i.options,t,n)},10),Ut=r,qt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ne(e,this.options,M(t,!1),!1):Jt()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ft.mount(ie,oe),Ft.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;ee=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=ee,ee=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==ee&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;ee&&k(ee,l.swapClass,!1),ee&&(l.swap||i&&i.options.swap)&&r!==ee&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=ee,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){ee=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:ee}}})}),Ft.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?h(document,"pointerup",this._deselectMultiDrag):(h(document,"mouseup",this._deselectMultiDrag),h(document,"touchend",this._deselectMultiDrag))),h(document,"keydown",this._checkKeyDown),h(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";ue.length&&ae===o?ue.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;le=t},delayEnded:function(){this.isMultiDrag=~ue.indexOf(le)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<ue.length;n++)de.push(_(ue[n])),de[n].sortableIndex=ue[n].sortableIndex,de[n].draggable=!1,de[n].style["will-change"]="",k(de[n],this.options.selectedClass,!1),ue[n]===le&&k(de[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||ue.length&&ae===e&&(ge(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ge(!1,n),de.forEach(function(t){R(t,"display","")}),e(),ce=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(de.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),ce=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ae&&ae.multiDrag._deselectMultiDrag(),ue.forEach(function(t){t.sortableIndex=j(t)}),ue=ue.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),pe=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(ue.forEach(function(t){t!==le&&R(t,"position","absolute")}),e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&C(t,e)}),he=fe=!0)),t.animateAll(function(){he=fe=!1,n.options.animation&&ue.forEach(function(t){T(t)}),n.options.sort&&me()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;fe&&~ue.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<ue.length&&(ue.forEach(function(t){r.addAnimationState({target:t,rect:fe?X(t):a}),T(t),t.fromRect=a,e.removeAnimationState(t)}),fe=!1,n=!this.options.removeCloneOnHide,o=i,ue.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),he=!1,t.animation&&1<ue.length&&(fe||!o&&!r.options.sort&&!l)&&(e=X(le,!1,!0,!0),ue.forEach(function(t){t!==le&&(C(t,e),a.appendChild(t))}),fe=!0),o||(fe||me(),1<ue.length?(o=ce,r._showClone(n),r.options.animation&&!ce&&o&&de.forEach(function(t){r.addAnimationState({target:t,rect:se}),t.fromRect=se,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;ue.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(se=a({},e),e=v(le,!0),se.top-=e.f,se.left-=e.e)},dragOverAnimationComplete:function(){fe&&(fe=!1,me())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c,u,d,h=this.options,f=o.children;if(!pe)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(le,h.selectedClass,!~ue.indexOf(le)),~ue.indexOf(le))ue.splice(ue.indexOf(le),1),re=null,z({sortable:i,rootEl:n,name:"deselect",targetEl:le,originalEvent:e});else{if(ue.push(le),z({sortable:i,rootEl:n,name:"select",targetEl:le,originalEvent:e}),e.shiftKey&&re&&i.el.contains(re)){var p=j(re),t=j(le);if(~p&&~t&&p!==t)for(var g,m=p<t?(g=p,t):(g=t,p+1);g<m;g++)~ue.indexOf(f[g])||(k(f[g],h.selectedClass,!0),ue.push(f[g]),z({sortable:i,rootEl:n,name:"select",targetEl:f[g],originalEvent:e}))}else re=le;ae=s}pe&&this.isMultiDrag&&(fe=!1,(o[K].options.sort||o!==n)&&1<ue.length&&(c=X(le),u=j(le,":not(."+this.options.selectedClass+")"),!he&&h.animation&&(le.thisAnimationDuration=null),s.captureAnimationState(),he||(h.animation&&(le.fromRect=c,ue.forEach(function(t){var e;t.thisAnimationDuration=null,t!==le&&(e=fe?X(t):c,t.fromRect=e,s.addAnimationState({target:t,rect:e}))})),me(),ue.forEach(function(t){f[u]?o.insertBefore(t,f[u]):o.appendChild(t),u++}),a===j(le)&&(d=!1,ue.forEach(function(t){t.sortableIndex!==j(t)&&(d=!0)}),d&&(r("update"),r("sort")))),ue.forEach(function(t){T(t)}),s.animateAll()),ae=s),(n===o||l&&"clone"!==l.lastPutMode)&&de.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=pe=!1,de.length=0},destroyGlobal:function(){this._deselectMultiDrag(),f(document,"pointerup",this._deselectMultiDrag),f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==pe&&pe||ae!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;ue.length;){var e=ue[0];k(e,this.options.selectedClass,!1),ue.shift(),z({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~ue.indexOf(t)&&(ae&&ae!==e&&(ae.multiDrag._deselectMultiDrag(),ae=e),k(t,e.options.selectedClass,!0),ue.push(t))},deselect:function(t){var e=t.parentNode[K],n=ue.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),ue.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return ue.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=fe&&t!==le?-1:fe?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:r(ue),clones:[].concat(de),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ft});';import{existsSync as Nt,readFileSync as co,writeFileSync as po,rmSync as fh,mkdirSync as fc,copyFileSync as hc,readdirSync as gc}from"fs";import{resolve as ze}from"path";El();function no(t){let e=ot.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:ot.parse({});return{enabled:a.enabled,secretEnv:a.secretEnv,secretSet:!!process.env[a.secretEnv],batchSeconds:a.batchSeconds,allowAutoAck:a.allowAutoAck,rules:a.rules,...e.success?{}:{error:e.error.issues[0]?.message??"invalid whatsappTriage section"}}}function Ot(t){return A(e=>{let a=e.whatsappTriage&&typeof e.whatsappTriage=="object"?e.whatsappTriage:{};a.rules=Array.isArray(a.rules)?a.rules:[];let n=t(a,e),r=ot.safeParse(a);if(!r.success){let o=r.error.issues[0];throw new Error(`${o?.path.join(".")||"whatsappTriage"}: ${o?.message??"invalid"}`)}return e.whatsappTriage=a,n})}var ao=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function ro(t){return Ot(e=>(typeof t?.enabled=="boolean"&&(e.enabled=t.enabled),typeof t?.allowAutoAck=="boolean"&&(e.allowAutoAck=t.allowAutoAck),t?.batchSeconds!==void 0&&(e.batchSeconds=Number(t.batchSeconds)),`WhatsApp triage ${e.enabled?"on":"off"}`))}function oo(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return Ot((n,r)=>{if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);if(n.rules.some(i=>i.id===e))throw new Error(`Watch rule "${e}" already exists.`);let o={id:e,agent:a,chats:ao(t?.chats),senders:ao(t?.senders)},s=String(t?.prompt??"").trim();return s&&(o.prompt=s),t?.quietStart&&t?.quietEnd&&(o.quietHours={start:String(t.quietStart),end:String(t.quietEnd)}),t?.autoAck===!0&&(o.autoAck=!0),n.rules.push(o),`added watch rule "${e}" \u2192 ${a}`})}function so(t){let e=String(t?.id??"");return Ot(a=>{let n=a.rules.find(r=>r.id===e);if(!n)throw new Error(`Watch rule "${e}" not found.`);return typeof t?.patch?.enabled=="boolean"&&(n.enabled=t.patch.enabled),typeof t?.patch?.autoAck=="boolean"&&(n.autoAck=t.patch.autoAck),`updated watch rule "${e}"`})}function io(t){let e=String(t?.id??"");return Ot(a=>{if(!a.rules.some(n=>n.id===e))throw new Error(`Watch rule "${e}" not found.`);return a.rules=a.rules.filter(n=>n.id!==e),`removed watch rule "${e}"`})}lt();var de={agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>',channels:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',webhooks:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 12a3 3 0 1 0 3-3m-8 11a3 3 0 1 0 2.6-1.5L10 12m7 3a3 3 0 1 0-2-5.5"/></svg>',mesh:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="6" cy="18" r="2"/><circle cx="18" cy="18" r="2"/><circle cx="12" cy="12" r="2"/><path d="M7.4 7.4l3.2 3.2M13.4 13.4l3.2 3.2M16.6 7.4l-3.2 3.2M10.6 13.4l-3.2 3.2"/></svg>',tokens:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-8 8a4 4 0 1 1-6 6m6-6l5-5 3 3-5 5m-3-3l3 3"/></svg>',advanced:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 4h8l4 4v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M9 13l2 2 4-4"/></svg>',actions:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>'};function lo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+At([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return M({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+dc()+sr,css:uc,scripts:`${e}<script>${ir}
1301
1335
  ${lr}
1302
- ${ic}
1303
- ${pc}</script>`})}var ic=`
1336
+ ${cc}
1337
+ ${mc}</script>`})}var cc=`
1304
1338
  (function(){
1305
1339
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1306
1340
  async function voiceMissing() {
@@ -1394,8 +1428,8 @@ ${pc}</script>`})}var ic=`
1394
1428
  refresh();
1395
1429
  // Refresh again after the main admin script has had a chance to mutate config.
1396
1430
  document.addEventListener('ax-config-saved', refresh);
1397
- })();`;function lc(){let t=Wn().business?`<button data-tab="business">Business</button>
1398
- `:"";return cc.replace("__BUSINESS_TABS__",t)}var cc=`
1431
+ })();`;function dc(){let t=Wn().business?`<button data-tab="business">Business</button>
1432
+ `:"";return pc.replace("__BUSINESS_TABS__",t)}var pc=`
1399
1433
  <div id="peer-banner" class="peer-banner">
1400
1434
  <span class="label">Managing</span>
1401
1435
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -2054,7 +2088,7 @@ ${pc}</script>`})}var ic=`
2054
2088
  <div class="hint-block">Every setting is documented in the <code>docs/reference/config.md</code> reference. Invalid JSON is refused; schema-level errors only surface after the daemon tries to use the new config.</div>
2055
2089
  </section>
2056
2090
  </main>
2057
- `,dc=`
2091
+ `,uc=`
2058
2092
 
2059
2093
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
2060
2094
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -2262,7 +2296,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
2262
2296
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
2263
2297
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
2264
2298
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
2265
- `,pc=`
2299
+ `,mc=`
2266
2300
  const $ = (id) => document.getElementById(id);
2267
2301
  let state = null;
2268
2302
 
@@ -5146,11 +5180,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
5146
5180
  })();
5147
5181
 
5148
5182
  refresh();
5149
- `;function lo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oo({peers:a,localToken:n}))}async function co(t,e){let a=xa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function po(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Cc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await hc(t),r={"GET /api/admin/state":()=>xc(),"POST /api/admin/agents":()=>_c(n),"PATCH /api/admin/agents":()=>Sc(n),"DELETE /api/admin/agents":()=>Ec(n),"POST /api/admin/agents/access":()=>vc(n),"POST /api/admin/channels/telegram":()=>Tc(n),"DELETE /api/admin/channels/telegram":()=>Vc(n),"POST /api/admin/channels/telegram/toggle":()=>Yc(n),"POST /api/admin/crons":()=>Qc(n),"DELETE /api/admin/crons":()=>Zc(n),"POST /api/admin/config/raw":()=>ed(n),"GET /api/admin/tokens":()=>bc(),"POST /api/admin/tokens":()=>yc(n),"DELETE /api/admin/tokens":()=>wc(n),"POST /api/admin/agents/test":()=>kc(n),"POST /api/admin/agents/integrations":()=>Pc(n),"DELETE /api/admin/agents/integrations":()=>jc(n),"PATCH /api/admin/agents/integrations":()=>Oc(n),"PATCH /api/admin/channels/telegram":()=>Ac(n),"POST /api/admin/channels/slack":()=>Fc(n),"POST /api/admin/channels/slack/toggle":()=>Uc(n),"POST /api/admin/channels/discord":()=>Wc(n),"POST /api/admin/channels/discord/toggle":()=>Gc(n),"POST /api/admin/channels/gitlab":()=>Xc(n),"POST /api/admin/channels/gitlab/toggle":()=>Kc(n),"POST /api/admin/channels/request-status":()=>_r(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>md(n),"DELETE /api/admin/actions":()=>fd(n),"POST /api/admin/actions/run":()=>hd(n),"GET /api/admin/channels/whatsapp/chats":()=>Je("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Je("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Jc(n),"POST /api/admin/webhooks":()=>Nc(n),"PATCH /api/admin/webhooks":()=>Dc(n),"DELETE /api/admin/webhooks":()=>qc(n),"POST /api/admin/whatsapp-triage":()=>to(n),"POST /api/admin/whatsapp-triage/rules":()=>ao(n),"PATCH /api/admin/whatsapp-triage/rules":()=>no(n),"DELETE /api/admin/whatsapp-triage/rules":()=>ro(n),"POST /api/admin/mesh/peers":()=>Hc(n),"DELETE /api/admin/mesh/peers":()=>Bc(n),"POST /api/admin/mesh/toggle":()=>zc(n),"GET /api/admin/files":()=>Ic(t),"GET /api/admin/files/read":()=>Mc(t),"PUT /api/admin/files":()=>Lc(n),"POST /api/admin/files/skill":()=>Rc(n),"DELETE /api/admin/files/skill":()=>$c(n),"POST /api/admin/business/orgchart":()=>td(n),"DELETE /api/admin/business/orgchart":()=>ad(n),"POST /api/admin/business/project":()=>nd(n),"DELETE /api/admin/business/project":()=>sd(n),"POST /api/admin/business/client":()=>rd(n),"DELETE /api/admin/business/client":()=>od(n),"POST /api/admin/business/contact":()=>id(n),"DELETE /api/admin/business/contact":()=>ld(n),"POST /api/admin/boards":()=>cd(n),"DELETE /api/admin/boards":()=>dd(n),"POST /api/admin/boards/columns":()=>pd(n),"DELETE /api/admin/boards/columns":()=>ud(n),"POST /api/admin/notifications":()=>xd(n),"POST /api/admin/screen":()=>vd(n),"POST /api/admin/webhooks/triggers":()=>bd(n),"POST /api/admin/mesh/health":()=>gd(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ha(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ha(e,200,i)}catch(n){ha(e,400,{error:n.message||"admin op failed"})}}function ha(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function hc(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function gc(t){let e=ze(process.cwd(),t);if(!Nt(e))return[];let a=[];for(let n of fc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(so(ze(e,n.name),"utf-8")))}catch{}return a}function xa(){let t=ze(process.cwd(),"agentx.json");return Nt(t)?JSON.parse(so(t,"utf-8")):null}function xc(){let t=xa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:In(k.local),ntfy:Er(t.channels?.ntfy)},S=[];try{S=gc(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:kr(t),whatsappTriage:eo(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:ar(t.screen),actions:S}}function vc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function bc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function yc(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function wc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function kc(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function _c(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(t?.tier)?t.tier:"claude-code",r=mo(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ze(process.cwd(),"agents",e),{summary:l}=A(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Nt(c))try{uc(i,{recursive:!0}),io(c,`# ${a}
5183
+ `;function uo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lo({peers:a,localToken:n}))}async function mo(t,e){let a=xa();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function fo(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Mc(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await xc(t),r={"GET /api/admin/state":()=>bc(),"POST /api/admin/agents":()=>Ec(n),"PATCH /api/admin/agents":()=>Tc(n),"DELETE /api/admin/agents":()=>Ac(n),"POST /api/admin/agents/access":()=>yc(n),"POST /api/admin/channels/telegram":()=>Cc(n),"DELETE /api/admin/channels/telegram":()=>Qc(n),"POST /api/admin/channels/telegram/toggle":()=>Zc(n),"POST /api/admin/crons":()=>ed(n),"DELETE /api/admin/crons":()=>td(n),"POST /api/admin/config/raw":()=>ad(n),"GET /api/admin/tokens":()=>wc(),"POST /api/admin/tokens":()=>kc(n),"DELETE /api/admin/tokens":()=>_c(n),"POST /api/admin/agents/test":()=>Sc(n),"POST /api/admin/agents/integrations":()=>Oc(n),"DELETE /api/admin/agents/integrations":()=>Nc(n),"PATCH /api/admin/agents/integrations":()=>Dc(n),"PATCH /api/admin/channels/telegram":()=>Ic(n),"POST /api/admin/channels/slack":()=>Wc(n),"POST /api/admin/channels/slack/toggle":()=>Gc(n),"POST /api/admin/channels/discord":()=>Xc(n),"POST /api/admin/channels/discord/toggle":()=>Kc(n),"POST /api/admin/channels/gitlab":()=>Jc(n),"POST /api/admin/channels/gitlab/toggle":()=>Vc(n),"POST /api/admin/channels/request-status":()=>_r(n),"GET /api/admin/channels/whatsapp/state":()=>Je("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Je("/webrtc/history"),"POST /api/admin/actions":()=>hd(n),"DELETE /api/admin/actions":()=>gd(n),"POST /api/admin/actions/run":()=>xd(n),"GET /api/admin/channels/whatsapp/chats":()=>Je("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Je("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>Yc(n),"POST /api/admin/webhooks":()=>Hc(n),"PATCH /api/admin/webhooks":()=>Bc(n),"DELETE /api/admin/webhooks":()=>Uc(n),"POST /api/admin/whatsapp-triage":()=>ro(n),"POST /api/admin/whatsapp-triage/rules":()=>oo(n),"PATCH /api/admin/whatsapp-triage/rules":()=>so(n),"DELETE /api/admin/whatsapp-triage/rules":()=>io(n),"POST /api/admin/mesh/peers":()=>zc(n),"DELETE /api/admin/mesh/peers":()=>qc(n),"POST /api/admin/mesh/toggle":()=>Fc(n),"GET /api/admin/files":()=>Lc(t),"GET /api/admin/files/read":()=>Rc(t),"PUT /api/admin/files":()=>$c(n),"POST /api/admin/files/skill":()=>Pc(n),"DELETE /api/admin/files/skill":()=>jc(n),"POST /api/admin/business/orgchart":()=>nd(n),"DELETE /api/admin/business/orgchart":()=>rd(n),"POST /api/admin/business/project":()=>od(n),"DELETE /api/admin/business/project":()=>ld(n),"POST /api/admin/business/client":()=>sd(n),"DELETE /api/admin/business/client":()=>id(n),"POST /api/admin/business/contact":()=>cd(n),"DELETE /api/admin/business/contact":()=>dd(n),"POST /api/admin/boards":()=>pd(n),"DELETE /api/admin/boards":()=>ud(n),"POST /api/admin/boards/columns":()=>md(n),"DELETE /api/admin/boards/columns":()=>fd(n),"POST /api/admin/notifications":()=>bd(n),"POST /api/admin/screen":()=>yd(n),"POST /api/admin/webhooks/triggers":()=>wd(n),"POST /api/admin/mesh/health":()=>vd(n),"GET /api/admin/projects":()=>Je("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>me("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>me("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>me("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>me("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>me("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>me("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>me("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>me("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){ha(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();ha(e,200,i)}catch(n){ha(e,400,{error:n.message||"admin op failed"})}}function ha(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function xc(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}function vc(t){let e=ze(process.cwd(),t);if(!Nt(e))return[];let a=[];for(let n of gc(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(co(ze(e,n.name),"utf-8")))}catch{}return a}function xa(){let t=ze(process.cwd(),"agentx.json");return Nt(t)?JSON.parse(co(t,"utf-8")):null}function bc(){let t=xa();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,m])=>({id:d,name:m.name,tier:m.tier,model:m.model,mentions:m.mentions||[],workspace:m.workspace,access:m.access||"private",systemPrompt:m.systemPrompt||"",maxConcurrent:m.maxConcurrent??1,maxExecutionMinutes:m.maxExecutionMinutes??20,permissionMode:m.permissionMode||"default",integrations:(Array.isArray(m.integrations)?m.integrations:[]).map(x=>{let v=x.credentials||{},w={};for(let[T,y]of Object.entries(v))typeof y=="string"&&/^[A-Z][A-Z0-9_]*$/.test(y)?w[T]=process.env[y]?"set":"unset":typeof y=="string"&&(w[T]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:w,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,m])=>({id:d,botUsername:m.botUsername||"",agentBinding:m.agentBinding||"",botTokenRef:m.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,m])=>({id:d,schedule:m.schedule,agent:m.agent,prompt:(m.prompt||"").slice(0,200),enabled:m.enabled!==!1})),c=Array.isArray(t.webhooks)?t.webhooks.map(d=>({id:d.id,source:d.source,agentId:d.agentId,secretEnv:d.secretEnv||"",description:d.description||"",enabled:d.enabled!==!1,triggers:d.triggers&&typeof d.triggers=="object"?d.triggers:{},defaultWorkflow:d.defaultWorkflow||""})):[],p={enabled:!!t.mesh?.enabled,discovery:t.mesh?.discovery||"static",peers:(t.mesh?.peers||[]).map(d=>({url:d.url,name:d.name,hasToken:!!d.token})),healthCheck:{interval:t.mesh?.healthCheck?.interval??60,timeout:t.mesh?.healthCheck?.timeout??10}},u=t.dashboard?.daemonUrl||"http://localhost:18800",f=t.business||{},h={enabled:!!f.enabled,timezone:f.timezone||"UTC",orgChart:f.orgChart||{},projects:Array.isArray(f.projects)?f.projects:[],contactMap:Array.isArray(f.contactMap)?f.contactMap:[],clients:f.clients&&typeof f.clients=="object"?f.clients:{}},k=t.notifications||{},_={longTaskThreshold:k.longTaskThreshold??30,destination:k.destination||null,on:{taskComplete:k.on?.taskComplete!==!1,taskError:k.on?.taskError!==!1,taskQueued:!!k.on?.taskQueued},local:In(k.local),ntfy:Er(t.channels?.ntfy)},S=[];try{S=vc(".agentx/actions").filter(m=>m&&typeof m=="object"&&m.id).map(m=>({id:m.id,title:m.title,kind:m.kind,description:m.description||"",inputs:Array.isArray(m.inputs)?m.inputs:[],timeoutMs:m.timeoutMs??3e4,command:m.kind==="shell"?m.command:void 0,url:m.kind==="http"?m.url:void 0,method:m.kind==="http"?m.method:void 0})).sort((m,x)=>m.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(d=>({id:d.id,name:d.name,source:d.source||{type:"gitlab",projects:[]},primaryToolLabel:d.primaryToolLabel||"",timeRangeDays:d.timeRangeDays??30,closedWindowDays:d.closedWindowDays??30,columns:Array.isArray(d.columns)?d.columns:[]}));return{exists:!0,agents:e,telegram:n,slack:r,discord:o,gitlab:s,whatsapp:i,requestStatus:kr(t),whatsappTriage:no(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:ar(t.screen),actions:S}}function yc(t){let e=String(t?.id||"").trim(),a=t?.access==="public"?"public":"private";if(!e)throw new Error("Agent id is required.");let{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);return r.agents[e].access=a,`agent "${e}" is now ${a}`});return{summary:n}}function wc(){return new F().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function kc(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new F().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function _c(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new F().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Sc(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=X();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Ec(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(t?.tier)?t.tier:"claude-code",r=go(t?.triggerWords),o=t?.model?String(t.model).trim():void 0,s=t?.personality?String(t.personality).trim():void 0;if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Agent id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Agent name is required.");if(r.length===0)throw new Error("At least one trigger word is required.");let i=ze(process.cwd(),"agents",e),{summary:l}=A(p=>{if(p.agents=p.agents||{},p.agents[e])throw new Error(`Agent "${e}" already exists.`);let u={name:a,workspace:i,tier:n,mentions:r,maxConcurrent:2,permissionMode:"default"};return o&&(u.model=o),s&&(u.systemPrompt=s.slice(0,400)),p.agents[e]=u,`added agent "${e}"`}),c=ze(i,"CLAUDE.md");if(!Nt(c))try{fc(i,{recursive:!0}),po(c,`# ${a}
5150
5184
 
5151
5185
  ${s||"You are "+a+"."}
5152
- `)}catch{}return{summary:l}}function Sc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=mo(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Ec(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Tc(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Ac(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Je(t){let{url:e,headers:a}=va(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function me(t,e){let{url:a,headers:n}=va(),r=await fetch(a+t,{method:"POST",headers:{...n,"Content-Type":"application/json"},body:JSON.stringify(e||{})}),o=await r.text();if(!r.ok)throw new Error(`daemon ${r.status}: ${o.slice(0,200)}`);try{return JSON.parse(o)}catch{return{raw:o}}}async function Cc(t,e){try{let{url:a,headers:n}=va(),r=await fetch(a+e,{headers:n}),o=await r.text();t.writeHead(r.status,{"Content-Type":r.headers.get("content-type")||"image/svg+xml","Cache-Control":"no-store"}),t.end(o)}catch(a){t.writeHead(502,{"Content-Type":"text/plain; charset=utf-8"}),t.end("daemon unreachable: "+(a?.message||"unknown"))}}function va(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ve(t){let a=xa()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function ga(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Ic(t){let e=ga(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Mc(t){let e=ga(t,"agent").trim(),a=ga(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return wt(Ve(e),a)}function Lc(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=kt(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Rc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=_t(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function $c(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=St(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Pc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function jc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Oc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var uo=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Nc(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!uo.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Dc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&uo.includes(a.source)&&(o.source=a.source),typeof a.agentId=="string"&&a.agentId.trim()){if(!r.agents?.[a.agentId])throw new Error(`Unknown agent "${a.agentId}".`);o.agentId=a.agentId.trim()}return typeof a.secretEnv=="string"&&(o.secretEnv=a.secretEnv.trim()||void 0),typeof a.description=="string"&&(o.description=a.description.trim()||void 0),typeof a.enabled=="boolean"&&(o.enabled=a.enabled),`updated webhook "${e}"`});return{summary:n}}function Hc(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function Bc(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function zc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function qc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function Fc(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function Uc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function Wc(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Gc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Xc(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Kc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Jc(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-4RLL7YOW.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function Vc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Yc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function Qc(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function Zc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function ed(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ze(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Nt(n))try{mc(n,r)}catch{}io(n,JSON.stringify(a,null,2)+`
5153
- `,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function mo(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function td(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function ad(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function nd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function rd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function od(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function sd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function id(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function ld(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function cd(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function dd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function pd(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function ud(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function md(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function fd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function hd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function gd(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function xd(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=Mn(a.notifications.local,t.local),n.push("local="+JSON.stringify(a.notifications.local))),"ntfy"in t&&t.ntfy&&typeof t.ntfy=="object"&&(a.channels=a.channels||{},a.channels.ntfy=Tr(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function vd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=nr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function bd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}lt();import{resolve as kd}from"path";function fo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5186
+ `)}catch{}return{summary:l}}function Tc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let a=t?.patch||{},{summary:n}=A(r=>{if(!r.agents?.[e])throw new Error(`Agent "${e}" not found.`);let o=r.agents[e];return typeof a.name=="string"&&a.name.trim()&&(o.name=a.name.trim()),typeof a.model=="string"&&(o.model=a.model.trim()||void 0),typeof a.tier=="string"&&["claude-code","codex-cli","opencode","sdk","orchestrator"].includes(a.tier)&&(o.tier=a.tier),typeof a.systemPrompt=="string"&&(o.systemPrompt=a.systemPrompt.trim()||void 0),Array.isArray(a.mentions)?o.mentions=a.mentions.map(s=>String(s).trim()).filter(Boolean):typeof a.triggerWords=="string"&&(o.mentions=go(a.triggerWords)),typeof a.maxConcurrent=="number"&&a.maxConcurrent>=1&&(o.maxConcurrent=a.maxConcurrent),typeof a.maxExecutionMinutes=="number"&&a.maxExecutionMinutes>=1&&a.maxExecutionMinutes<=240&&(o.maxExecutionMinutes=a.maxExecutionMinutes),typeof a.permissionMode=="string"&&(o.permissionMode=a.permissionMode),(a.access==="public"||a.access==="private")&&(o.access=a.access),`updated agent "${e}"`});return{summary:n}}function Ac(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Agent id is required.");let{summary:a}=A(n=>{if(!n.agents||!n.agents[e])throw new Error(`Agent "${e}" not found.`);if(delete n.agents[e],n.channels?.telegram?.accounts)for(let r of Object.keys(n.channels.telegram.accounts))n.channels.telegram.accounts[r]?.agentBinding===e&&(n.channels.telegram.accounts[r].agentBinding="");return`removed agent "${e}"`});return{summary:a}}function Cc(t){let e=String(t?.id||"").trim(),a=String(t?.agentBinding||"").trim(),n=String(t?.botUsername||"").trim(),r=String(t?.botTokenEnv||"").trim();if(!e)throw new Error("Account id is required.");if(!a)throw new Error("Choose an agent to bind this account to.");if(!r)throw new Error("Bot token env-var name is required (e.g. TG_SUPPORT_BOT_TOKEN).");let{summary:o}=A(s=>{if(s.channels=s.channels||{},s.channels.telegram=s.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},s.channels.telegram.enabled=!0,s.channels.telegram.accounts=s.channels.telegram.accounts||{},s.channels.telegram.accounts[e])throw new Error(`Telegram account "${e}" already exists.`);if(!s.agents?.[a])throw new Error(`Unknown agent "${a}".`);return s.channels.telegram.accounts[e]={token:"${"+r+"}",agentBinding:a},`added telegram account "${e}"`});return{summary:o,hint:`Add ${r}=<bot-token> to your .env file.`}}function Ic(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=r.channels?.telegram?.accounts?.[e];if(!o)throw new Error(`Account "${e}" not found.`);if(typeof a.agentBinding=="string"&&a.agentBinding.trim()){if(!r.agents?.[a.agentBinding])throw new Error(`Unknown agent "${a.agentBinding}".`);o.agentBinding=a.agentBinding.trim()}return typeof a.botUsername=="string"&&(o.botUsername=a.botUsername.trim()),typeof a.botTokenEnv=="string"&&a.botTokenEnv.trim()&&(o.token="${"+a.botTokenEnv.trim()+"}"),`updated telegram account "${e}"`});return{summary:n}}async function Je(t){let{url:e,headers:a}=va(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function me(t,e){let{url:a,headers:n}=va(),r=await fetch(a+t,{method:"POST",headers:{...n,"Content-Type":"application/json"},body:JSON.stringify(e||{})}),o=await r.text();if(!r.ok)throw new Error(`daemon ${r.status}: ${o.slice(0,200)}`);try{return JSON.parse(o)}catch{return{raw:o}}}async function Mc(t,e){try{let{url:a,headers:n}=va(),r=await fetch(a+e,{headers:n}),o=await r.text();t.writeHead(r.status,{"Content-Type":r.headers.get("content-type")||"image/svg+xml","Cache-Control":"no-store"}),t.end(o)}catch(a){t.writeHead(502,{"Content-Type":"text/plain; charset=utf-8"}),t.end("daemon unreachable: "+(a?.message||"unknown"))}}function va(){let t="http://127.0.0.1:18800",e={};try{let a=X();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function Ve(t){let a=xa()?.agents?.[t];if(!a)throw new Error(`Unknown agent "${t}".`);if(!a.workspace)throw new Error(`Agent "${t}" has no workspace configured.`);return a.workspace}function ga(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Lc(t){let e=ga(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=De(Ve(e));return{agentId:e,...a}}function Rc(t){let e=ga(t,"agent").trim(),a=ga(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return wt(Ve(e),a)}function $c(t){let e=String(t?.agent||"").trim(),a=String(t?.path||"").trim(),n=typeof t?.content=="string"?t.content:"";if(!e||!a)throw new Error("agent and path are required.");let r=kt(Ve(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Pc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim(),n=t?.title?String(t.title):void 0,r=t?.content?String(t.content):void 0;if(!e)throw new Error("agent is required.");let o=_t(Ve(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function jc(t){let e=String(t?.agent||"").trim(),a=String(t?.slug||"").trim();if(!e||!a)throw new Error("agent and slug are required.");let n=St(Ve(e),a);return{summary:`removed skill "${a}"`,...n}}function Oc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a)throw new Error("kind is required");if(!n)throw new Error("label is required");let r={},o=t?.credentials||{};for(let l of["tokenEnv","privateAppTokenEnv","apiKeyEnv","refreshTokenEnv","clientIdEnv","clientSecretEnv"]){let c=o[l];if(typeof c=="string"&&c.trim()){if(!/^[A-Z][A-Z0-9_]*$/.test(c.trim()))throw new Error(`${l} must be uppercase identifier (got "${c}")`);r[l]=c.trim()}}if(o.auth==="keyring"&&(r.auth="keyring"),typeof o.sessionDir=="string"&&o.sessionDir.trim()&&(r.sessionDir=o.sessionDir.trim()),Object.keys(r).length===0)throw new Error("at least one credential field required");let s={};for(let[l,c]of Object.entries(t?.metadata||{}))(typeof c=="string"||typeof c=="number"||typeof c=="boolean")&&(s[l]=c);let{summary:i}=A(l=>{if(!l.agents?.[e])throw new Error(`Unknown agent "${e}"`);if(l.agents[e].integrations=Array.isArray(l.agents[e].integrations)?l.agents[e].integrations:[],l.agents[e].integrations.find(c=>c.kind===a&&c.label===n))throw new Error(`integration (${a}, ${n}) already exists on ${e}`);return l.agents[e].integrations.push({kind:a,label:n,credentials:r,metadata:s,enabled:!0}),`added ${a} integration "${n}" to ${e}`});return{summary:i}}function Nc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let{summary:r}=A(o=>{let s=o.agents?.[e];if(!s)throw new Error(`Unknown agent "${e}"`);let i=s.integrations||[],l=i.findIndex(c=>c.kind===a&&c.label===n);if(l===-1)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return i.splice(l,1),`removed ${a} integration "${n}" from ${e}`});return{summary:r}}function Dc(t){let e=String(t?.agentId||"").trim(),a=String(t?.kind||"").trim(),n=String(t?.label||"").trim();if(!e)throw new Error("agentId is required");if(!a||!n)throw new Error("kind and label are required");let r=t?.patch||{},{summary:o}=A(s=>{let i=s.agents?.[e];if(!i)throw new Error(`Unknown agent "${e}"`);let c=(i.integrations||[]).find(p=>p.kind===a&&p.label===n);if(!c)throw new Error(`integration (${a}, ${n}) not found on ${e}`);return typeof r.enabled=="boolean"&&(c.enabled=r.enabled),r.metadata&&typeof r.metadata=="object"&&(c.metadata={...c.metadata||{},...r.metadata}),`updated integration (${a}, ${n}) on ${e}`});return{summary:o}}var ho=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Hc(t){let e=String(t?.id||"").trim(),a=String(t?.source||"").trim(),n=String(t?.agentId||"").trim(),r=String(t?.secretEnv||"").trim(),o=String(t?.description||"").trim(),s=String(t?.node||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Webhook id must be lowercase (letters, digits, -, _).");if(!ho.includes(a))throw new Error(`Unknown source: ${a}`);if(!n)throw new Error("Pick an agent to bind the webhook to.");let{summary:i}=A(l=>{if(s){if(!(l.mesh?.peers||[]).find(u=>u.name===s))throw new Error(`Mesh peer "${s}" not found in mesh.peers. Add the peer first or remove the node field.`)}else if(!l.agents?.[n])throw new Error(`Unknown agent "${n}". Add it locally, or set --node <peer> to forward to a mesh peer.`);if(l.webhooks=Array.isArray(l.webhooks)?l.webhooks:[],l.webhooks.find(p=>p.id===e))throw new Error(`Webhook "${e}" already exists.`);let c={id:e,source:a,agentId:n,enabled:!0};return r&&(c.secretEnv=r),o&&(c.description=o),s&&(c.node=s),l.webhooks.push(c),`added webhook "${e}" (${a} \u2192 ${n}${s?` @ ${s}`:""})`});return{summary:i}}function Bc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let a=t?.patch||{},{summary:n}=A(r=>{let o=(r.webhooks||[]).find(s=>s.id===e);if(!o)throw new Error(`Webhook "${e}" not found.`);if(typeof a.source=="string"&&ho.includes(a.source)&&(o.source=a.source),typeof a.agentId=="string"&&a.agentId.trim()){if(!r.agents?.[a.agentId])throw new Error(`Unknown agent "${a.agentId}".`);o.agentId=a.agentId.trim()}return typeof a.secretEnv=="string"&&(o.secretEnv=a.secretEnv.trim()||void 0),typeof a.description=="string"&&(o.description=a.description.trim()||void 0),typeof a.enabled=="boolean"&&(o.enabled=a.enabled),`updated webhook "${e}"`});return{summary:n}}function zc(t){let e=String(t?.url||"").trim().replace(/\/+$/,""),a=String(t?.name||"").trim(),n=String(t?.token||"").trim()||void 0;if(!e||!/^https?:\/\//.test(e))throw new Error("Peer URL must start with http:// or https://");if(!a)throw new Error("Peer name is required.");let{summary:r}=A(o=>{if(o.mesh=o.mesh||{enabled:!0,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},o.mesh.enabled=!0,o.mesh.peers=Array.isArray(o.mesh.peers)?o.mesh.peers:[],o.mesh.peers.find(i=>i.url===e))throw new Error(`Peer at ${e} already registered.`);let s={url:e,name:a};return n&&(s.token=n),o.mesh.peers.push(s),`added mesh peer "${a}"`});return{summary:r}}function qc(t){let e=String(t?.url||"").trim().replace(/\/+$/,"");if(!e)throw new Error("Peer URL is required.");let{summary:a}=A(n=>{let r=(n.mesh?.peers||[]).length;if(n.mesh=n.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.peers=(n.mesh.peers||[]).filter(o=>o.url.replace(/\/+$/,"")!==e),n.mesh.peers.length===r)throw new Error(`Peer at ${e} not found.`);return`removed mesh peer ${e}`});return{summary:a}}function Fc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.mesh=n.mesh||{enabled:e,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},n.mesh.enabled=e,`mesh ${e?"enabled":"disabled"}`));return{summary:a}}function Uc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Webhook id is required.");let{summary:a}=A(n=>{let r=(n.webhooks||[]).length;if(n.webhooks=(n.webhooks||[]).filter(o=>o.id!==e),n.webhooks.length===r)throw new Error(`Webhook "${e}" not found.`);return`removed webhook "${e}"`});return{summary:a}}function Wc(t){let e=String(t?.botTokenEnv||"").trim(),a=String(t?.appTokenEnv||"").trim(),n=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. SLACK_BOT_TOKEN).");if(!a)throw new Error("App-level token env-var name is required (e.g. SLACK_APP_TOKEN).");let{summary:r}=A(o=>{if(o.channels=o.channels||{},o.channels.slack=o.channels.slack||{enabled:!1},o.channels.slack.enabled=!0,o.channels.slack.botToken="${"+e+"}",o.channels.slack.appToken="${"+a+"}",n){if(!o.agents?.[n])throw new Error(`Unknown agent "${n}".`);o.channels.slack.agentBinding=n}return"configured slack connector"});return{summary:r,hint:`Add ${e}=xoxb-\u2026 and ${a}=xapp-\u2026 to your .env.`}}function Gc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.slack=n.channels.slack||{enabled:!1},n.channels.slack.enabled=e,`slack ${e?"enabled":"disabled"}`));return{summary:a}}function Xc(t){let e=String(t?.tokenEnv||"").trim(),a=String(t?.agentBinding||"").trim();if(!e)throw new Error("Bot token env-var name is required (e.g. DISCORD_BOT_TOKEN).");let{summary:n}=A(r=>{if(r.channels=r.channels||{},r.channels.discord=r.channels.discord||{enabled:!1},r.channels.discord.enabled=!0,r.channels.discord.token="${"+e+"}",a){if(!r.agents?.[a])throw new Error(`Unknown agent "${a}".`);r.channels.discord.agentBinding=a}return"configured discord connector"});return{summary:n,hint:`Add ${e}=<bot-token> to your .env.`}}function Kc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.discord=n.channels.discord||{enabled:!1},n.channels.discord.enabled=e,`discord ${e?"enabled":"disabled"}`));return{summary:a}}function Jc(t){let e=String(t?.host||"").trim().replace(/\/+$/,""),a=String(t?.tokenEnv||"").trim(),n=parseInt(String(t?.webhookPort||"18810"),10);if(!e||!/^https?:\/\//.test(e))throw new Error("Host must start with http:// or https://");if(!a)throw new Error("Admin token env-var name is required (e.g. GITLAB_TOKEN).");if(!Number.isFinite(n)||n<1||n>65535)throw new Error("Webhook port must be between 1 and 65535.");let{summary:r}=A(o=>(o.channels=o.channels||{},o.channels.gitlab=o.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},o.channels.gitlab.enabled=!0,o.channels.gitlab.host=e,o.channels.gitlab.token="${"+a+"}",o.channels.gitlab.webhookPort=n,"configured gitlab connector"));return{summary:r,hint:`Add ${a}=<personal-access-token> to your .env. Per-project routes + per-agent tokens stay in the Advanced JSON editor.`}}function Vc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.gitlab=n.channels.gitlab||{enabled:!1,routes:[],agentMappings:[]},n.channels.gitlab.enabled=e,`gitlab ${e?"enabled":"disabled"}`));return{summary:a}}async function Yc(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-4RLL7YOW.js"),n;try{n=(await import("cronstrue")).default.toString(e,{use24HourTimeFormat:!1})}catch(i){throw new Error(`Invalid cron: ${i.message||"unknown"}`)}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC",o=[],s=new Date;try{for(let i=0;i<3;i++)s=a(e,s,r),o.push(s.toISOString())}catch(i){throw new Error(`Cron preview failed: ${i.message}`)}return{human:n,next:o,timezone:r}}function Qc(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Account id is required.");let{summary:a}=A(n=>{if(!n.channels?.telegram?.accounts?.[e])throw new Error(`Account "${e}" not found.`);return delete n.channels.telegram.accounts[e],`removed telegram account "${e}"`});return{summary:a}}function Zc(t){let e=!!t?.enabled,{summary:a}=A(n=>(n.channels=n.channels||{},n.channels.telegram=n.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},n.channels.telegram.enabled=e,`telegram ${e?"enabled":"disabled"}`));return{summary:a}}function ed(t){let e=String(t?.id||"").trim(),a=String(t?.schedule||"").trim(),n=String(t?.agent||"").trim(),r=String(t?.prompt||"").trim();if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Cron id must be lowercase (letters, digits, -, _).");if(!a)throw new Error("Cron expression is required (e.g. '0 9 * * 1' for Mondays at 9am).");if(!n)throw new Error("Pick an agent to run this schedule.");if(!r)throw new Error("A prompt is required (what should the agent do?).");let{summary:o}=A(s=>{if(s.crons=s.crons||{},s.crons[e])throw new Error(`Cron "${e}" already exists.`);if(!s.agents?.[n])throw new Error(`Unknown agent "${n}".`);return s.crons[e]={schedule:a,agent:n,prompt:r,enabled:!0},`added cron "${e}"`});return{summary:o}}function td(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Cron id is required.");let{summary:a}=A(n=>{if(!n.crons?.[e])throw new Error(`Cron "${e}" not found.`);return delete n.crons[e],`removed cron "${e}"`});return{summary:a}}function ad(t){let e=String(t?.raw||"");if(!e.trim())throw new Error("Config body is empty.");let a;try{a=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON: ${o.message}`)}let n=ze(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(Nt(n))try{hc(n,r)}catch{}po(n,JSON.stringify(a,null,2)+`
5187
+ `,"utf-8");try{let s=X().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";fetch(`${s}/reload`,{method:"POST"}).catch(()=>null)}catch{}return{summary:"agentx.json replaced",backupPath:r}}function go(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function nd(t){let e=String(t?.agentId||"").trim(),a=String(t?.role||"").trim();if(!e)throw new Error("agentId required");if(!a)throw new Error("role required");let n=Array.isArray(t?.days)&&t.days.length>0?t.days:["mon","tue","wed","thu","fri"],r=String(t?.start||"09:00"),o=String(t?.end||"17:00"),s=t?.reportsTo?String(t.reportsTo).trim():"",i=typeof t?.utilizationTarget=="number"?t.utilizationTarget:.8,{summary:l}=A(c=>(c.business=c.business||{},c.business.orgChart=c.business.orgChart||{},c.business.orgChart[e]={role:a,...s?{reportsTo:s}:{},schedule:{days:n,start:r,end:o},utilizationTarget:i},`orgChart "${e}" upserted`));return{summary:l}}async function rd(t){let e=String(t?.agentId||"").trim();if(!e)throw new Error("agentId required");let{summary:a}=A(n=>{if(!n.business?.orgChart||!(e in n.business.orgChart))throw new Error(`no orgChart entry for "${e}"`);return delete n.business.orgChart[e],`orgChart "${e}" removed`});return{summary:a}}async function od(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let a=t?.pm?String(t.pm).trim():"",n=t?.client?String(t.client).trim():"",{summary:r}=A(o=>{o.business=o.business||{},o.business.projects=o.business.projects||[];let s=o.business.projects.findIndex(l=>l.id===e),i={id:e,...a?{pm:a}:{},...n?{client:n}:{}};return s>=0?o.business.projects[s]={...o.business.projects[s],...i}:o.business.projects.push(i),s>=0?`project "${e}" updated`:`project "${e}" added`});return{summary:r}}async function sd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let a=String(t?.kind||"").trim();if(a&&!["client","internal","own"].includes(a))throw new Error("kind must be client, internal or own");let n=String(t?.respondWithin||"").trim();if(n&&!/^\d+\s*[mhd]$/.test(n))throw new Error('respondWithin must look like "4h", "90m" or "2d"');let r=Array.isArray(t?.standing)?t.standing.map(s=>String(s).trim()).filter(Boolean):String(t?.standing||"").split(",").map(s=>s.trim()).filter(Boolean),{summary:o}=A(s=>{s.business=s.business||{},s.business.clients=s.business.clients||{};let i=!!s.business.clients[e];return s.business.clients[e]={...s.business.clients[e]||{},...t?.name?{name:String(t.name).trim()}:{},...a?{kind:a}:{},...n?{respondWithin:n}:{},standing:r},i?`client "${e}" updated`:`client "${e}" configured`});return{summary:o}}async function id(t){let e=String(t?.id||"").trim();if(!e)throw new Error("client id required");let{summary:a}=A(n=>{if(!n.business?.clients?.[e])throw new Error(`no client override "${e}"`);return delete n.business.clients[e],`client "${e}" reset to defaults`});return{summary:a}}async function ld(t){let e=String(t?.id||"").trim();if(!e)throw new Error("project id required");let{summary:a}=A(n=>{let r=n.business?.projects||[],o=r.length;if(n.business.projects=r.filter(s=>s.id!==e),n.business.projects.length===o)throw new Error(`no project "${e}"`);return`project "${e}" removed`});return{summary:a}}async function cd(t){let e=String(t?.client||"").trim();if(!e)throw new Error("client required");if(!t?.chatId&&!t?.username&&!t?.senderId)throw new Error("one of chatId / username / senderId required");let{summary:a}=A(n=>{n.business=n.business||{},n.business.contactMap=n.business.contactMap||[];let r={client:e};t?.channel&&(r.channel=String(t.channel)),t?.chatId&&(r.chatId=String(t.chatId)),t?.username&&(r.username=String(t.username)),t?.senderId&&(r.senderId=String(t.senderId)),t?.project&&(r.project=String(t.project)),t?.displayName&&(r.displayName=String(t.displayName)),n.business.contactMap.push(r);let o=r.chatId||r.username||r.senderId;return`contact ${r.channel?r.channel+"/":""}${o} \u2192 ${e} added`});return{summary:a}}async function dd(t){let a=["channel","chatId","username","senderId"].filter(r=>t?.[r]);if(a.length===0)throw new Error("at least one filter (channel/chatId/username/senderId) required");let{summary:n}=A(r=>{let o=r.business?.contactMap||[],s=o.length;if(r.business.contactMap=o.filter(i=>{for(let l of a)if(i[l]!==t[l])return!0;return!1}),r.business.contactMap.length===s)throw new Error("no matching contact entry");return`${s-r.business.contactMap.length} contact entry/entries removed`});return{summary:n}}async function pd(t){let e=String(t?.id||"").trim(),a=String(t?.name||"").trim(),n=String(t?.projects||"").split(/[,\n]/).map(l=>l.trim()).filter(Boolean);if(!e)throw new Error("id required");if(!a)throw new Error("name required");if(n.length===0)throw new Error("at least one project path required");let r=t?.primaryToolLabel?String(t.primaryToolLabel).trim():"",o=Number.isFinite(Number(t?.timeRangeDays))?Number(t.timeRangeDays):30,s=Number.isFinite(Number(t?.closedWindowDays))?Number(t.closedWindowDays):30,{summary:i}=A(l=>{l.boards=Array.isArray(l.boards)?l.boards:[];let c=l.boards.findIndex(u=>u.id===e),p={id:e,name:a,source:{type:"gitlab",projects:n},timeRangeDays:o,closedWindowDays:s};if(r&&(p.primaryToolLabel=r),c>=0){let u=l.boards[c];return l.boards[c]={...u,...p,columns:u.columns,labels:u.labels},`board "${e}" updated`}return l.boards.push(p),`board "${e}" added`});return{summary:i}}async function ud(t){let e=String(t?.id||"").trim();if(!e)throw new Error("id required");let{summary:a}=A(n=>{let r=Array.isArray(n.boards)?n.boards:[],o=r.length;if(n.boards=r.filter(s=>s.id!==e),n.boards.length===o)throw new Error(`board "${e}" not found`);return`board "${e}" removed`});return{summary:a}}async function md(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"-"),n=String(t?.title||"").trim(),r=String(t?.kind||"scoped-label");if(!e)throw new Error("boardId required");if(!a)throw new Error("columnId required");if(!n)throw new Error("title required");if(!["open-backlog","scoped-label","closed","label"].includes(r))throw new Error("kind must be open-backlog | scoped-label | closed | label");let{summary:o}=A(s=>{let l=(Array.isArray(s.boards)?s.boards:[]).find(u=>u.id===e);if(!l)throw new Error(`board "${e}" not found`);l.columns=Array.isArray(l.columns)?l.columns:[];let c={id:a,title:n,kind:r,scopedPrefix:t?.scopedPrefix||"Status"};if(r==="scoped-label"){if(!t?.scopedLabel)throw new Error("scopedLabel required for kind=scoped-label");c.scopedLabel=String(t.scopedLabel)}if(r==="label"){if(!t?.mapsToLabel)throw new Error("mapsToLabel required for kind=label");c.mapsToLabel=String(t.mapsToLabel)}t?.accent&&(c.accent=String(t.accent));let p=l.columns.findIndex(u=>u.id===a);return p>=0?(l.columns[p]={...l.columns[p],...c},`column "${a}" updated`):(l.columns.push(c),`column "${a}" added to board "${e}"`)});return{summary:o}}async function fd(t){let e=String(t?.boardId||"").trim(),a=String(t?.columnId||"").trim();if(!e||!a)throw new Error("boardId and columnId required");let{summary:n}=A(r=>{let s=(Array.isArray(r.boards)?r.boards:[]).find(l=>l.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(l=>l.id!==a),s.columns.length===i)throw new Error(`column "${a}" not found`);return`column "${a}" removed from board "${e}"`});return{summary:n}}async function hd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{actionSchema:a}=await import("./types-DO3KLIBS.js");if(!t||typeof t!="object")throw new Error("body required");let n=a.safeParse(t);if(!n.success){let o=n.error.issues[0];throw new Error(`${o.path.join(".")||"<root>"}: ${o.message}`)}let r=new e().save(n.data);return{summary:`action "${r.id}" saved (${r.kind})`,action:r}}async function gd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),a=String(t?.id||"").trim();if(!a)throw new Error("id required");if(!new e().delete(a))throw new Error(`action "${a}" not found`);return{summary:`action "${a}" removed`}}async function xd(t){let{ActionStore:e}=await import("./store-TWQPEM5V.js"),{runAction:a}=await import("./runner-56G3N7M4.js"),n=String(t?.id||"").trim();if(!n)throw new Error("id required");let r=new e().get(n);if(!r)throw new Error(`action "${n}" not found`);let o=t?.inputs&&typeof t.inputs=="object"?t.inputs:{},s=await a(r,o);return{summary:`action "${n}" ${s.ok?"ok":"failed"} (${s.durationMs}ms)`,result:s}}async function vd(t){let e=t?.interval!==void 0?Number(t.interval):void 0,a=t?.timeout!==void 0?Number(t.timeout):void 0;if(e!==void 0&&(!Number.isFinite(e)||e<5||e>3600))throw new Error("interval must be 5..3600 seconds");if(a!==void 0&&(!Number.isFinite(a)||a<1||a>60))throw new Error("timeout must be 1..60 seconds");if(e===void 0&&a===void 0)throw new Error("nothing to update");let{summary:n}=A(r=>(r.mesh=r.mesh||{},r.mesh.healthCheck=r.mesh.healthCheck||{},e!==void 0&&(r.mesh.healthCheck.interval=e),a!==void 0&&(r.mesh.healthCheck.timeout=a),`mesh.healthCheck updated (interval=${r.mesh.healthCheck.interval}s, timeout=${r.mesh.healthCheck.timeout}s)`));return{summary:n}}async function bd(t){let{summary:e}=A(a=>{a.notifications=a.notifications||{};let n=[];if(t&&typeof t=="object"){if("destination"in t)if(!t.destination)delete a.notifications.destination,n.push("destination cleared");else if(t.destination.channel&&t.destination.chatId)a.notifications.destination={channel:String(t.destination.channel),chatId:String(t.destination.chatId),...t.destination.accountId?{accountId:String(t.destination.accountId)}:{}},n.push(`destination=${t.destination.channel}:${t.destination.chatId}`);else throw new Error("destination requires channel + chatId");if("on"in t&&t.on&&typeof t.on=="object"){a.notifications.on=a.notifications.on||{};for(let r of["taskComplete","taskError","taskQueued"])r in t.on&&(a.notifications.on[r]=!!t.on[r]);n.push("on="+JSON.stringify(a.notifications.on))}if("longTaskThreshold"in t){let r=Number(t.longTaskThreshold);if(!Number.isFinite(r)||r<0)throw new Error("longTaskThreshold must be a non-negative number");a.notifications.longTaskThreshold=r,n.push(`threshold=${r}s`)}"local"in t&&t.local&&typeof t.local=="object"&&(a.notifications.local=Mn(a.notifications.local,t.local),n.push("local="+JSON.stringify(a.notifications.local))),"ntfy"in t&&t.ntfy&&typeof t.ntfy=="object"&&(a.channels=a.channels||{},a.channels.ntfy=Tr(a.channels.ntfy,t.ntfy),n.push(`ntfy ${a.channels.ntfy.enabled?"on":"off"} (restart the daemon to apply)`))}if(n.length===0)throw new Error("nothing to update");return`notifications updated (${n.join(", ")})`});return{summary:e}}async function yd(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=nr(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function wd(t){let e=String(t?.id||"").trim();if(!e)throw new Error("webhook id required");let{summary:a}=A(n=>{let o=(Array.isArray(n.webhooks)?n.webhooks:[]).find(s=>s.id===e);if(!o)throw new Error(`webhook "${e}" not found`);if("triggers"in t){if(t.triggers===null||typeof t.triggers=="object"&&Object.keys(t.triggers).length===0)delete o.triggers;else if(typeof t.triggers=="object"){let s={};for(let[i,l]of Object.entries(t.triggers))typeof l=="string"&&l.trim()&&(s[String(i)]=l.trim());Object.keys(s).length===0?delete o.triggers:o.triggers=s}}return"defaultWorkflow"in t&&(t.defaultWorkflow?o.defaultWorkflow=String(t.defaultWorkflow).trim():delete o.defaultWorkflow),`webhook "${e}" triggers/defaultWorkflow updated`});return{summary:a}}lt();import{resolve as Sd}from"path";function xo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
5154
5188
 
5155
5189
  <div id="disabled-banner" class="banner warn" style="display:none">
5156
5190
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -5205,7 +5239,7 @@ ${s||"You are "+a+"."}
5205
5239
  <h2>Recent classifications</h2>
5206
5240
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
5207
5241
  <div id="recent"></div>
5208
- </section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:yd,scripts:`${e}<script>${wd}</script>`})}var yd=`
5242
+ </section>`;return M({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:kd,scripts:`${e}<script>${_d}</script>`})}var kd=`
5209
5243
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
5210
5244
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
5211
5245
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -5309,7 +5343,7 @@ details {
5309
5343
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
5310
5344
  }
5311
5345
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
5312
- details[open] summary { margin-bottom: 8px; }`,wd=`
5346
+ details[open] summary { margin-bottom: 8px; }`,_d=`
5313
5347
  const $ = (id) => document.getElementById(id);
5314
5348
  const state = { schema: null, nodes: [], pending: [], recent: [] };
5315
5349
 
@@ -5529,7 +5563,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5529
5563
  $('btn-reload-schema').addEventListener('click', refresh);
5530
5564
 
5531
5565
  refresh();
5532
- `;function go(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fo({peers:a,localToken:n}))}async function xo(t,e,a){try{let n=t.method==="GET"?void 0:await Ld(t),r=_d(),o={"GET /api/admin/graph/state":()=>Sd(r),"POST /api/admin/graph/classifications/approve":()=>Ed(r,n),"POST /api/admin/graph/classifications/reject":()=>Td(r,n),"POST /api/admin/graph/nodes":()=>Ad(r,n),"PATCH /api/admin/graph/nodes":()=>Cd(r,n),"DELETE /api/admin/graph/nodes":()=>Id(r,n),"PUT /api/admin/graph/schema":()=>Md(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){ba(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();ba(e,200,l)}catch(n){ba(e,400,{error:n?.message||"graph op failed"})}}function _d(){let t=X(),e=kd(process.cwd(),t.graph.baseDir);return new gn({baseDir:e})}function Sd(t){let e=X(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function Ed(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=vo(t,a);return Array.isArray(e?.path)&&e.path.length>0&&(n.path=e.path.map(r=>String(r))),e?.proposedAxes&&typeof e.proposedAxes=="object"&&(n.proposedAxes=ya(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Td(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=vo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function vo(t,e){let n=t.readRecentClassifications(500).find(r=>r.msgHash===e);if(!n)throw new Error(`No classification found for ${e}`);return n}function Ad(t,e){let a=ho(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?ho(String(e.parentId)):null,o=ya({[a]:e?.axes||{}})[a]||{};if(!a)throw new Error("id is required");if(!n)throw new Error("level is required");let s={id:a,level:n,parentId:r,axes:o,createdAt:new Date().toISOString(),createdBy:"admin-ui"};return t.addNode(s),{node:s}}function Cd(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=ya({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Id(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Md(t,e){if(!e?.schema||typeof e.schema!="object")throw new Error("schema object is required");return t.saveSchema(e.schema),{summary:"Schema saved"}}function ya(t){let e={};for(let[a,n]of Object.entries(t||{})){if(!n||typeof n!="object")continue;let r={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(r[o]=s);e[a]=r}return e}function ho(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function ba(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ld(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 bo=`
5566
+ `;function bo(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xo({peers:a,localToken:n}))}async function yo(t,e,a){try{let n=t.method==="GET"?void 0:await $d(t),r=Ed(),o={"GET /api/admin/graph/state":()=>Td(r),"POST /api/admin/graph/classifications/approve":()=>Ad(r,n),"POST /api/admin/graph/classifications/reject":()=>Cd(r,n),"POST /api/admin/graph/nodes":()=>Id(r,n),"PATCH /api/admin/graph/nodes":()=>Md(r,n),"DELETE /api/admin/graph/nodes":()=>Ld(r,n),"PUT /api/admin/graph/schema":()=>Rd(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){ba(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();ba(e,200,l)}catch(n){ba(e,400,{error:n?.message||"graph op failed"})}}function Ed(){let t=X(),e=Sd(process.cwd(),t.graph.baseDir);return new gn({baseDir:e})}function Td(t){let e=X(),a=t.loadSchema(),n=t.loadNodes().nodes,r=t.readRecentClassifications(100),o=t.loadIndex().entries,s=new Map;for(let l of r)s.has(l.msgHash)||s.set(l.msgHash,l);let i=[];for(let l of s.values())l.status==="pending"&&!o[l.msgHash]&&i.push(l);return{enabled:e.graph.enabled,schema:a,nodes:n,pending:i,recent:r.slice(0,25),counts:{nodes:n.length,pending:i.length,fingerprints:Object.keys(o).length}}}function Ad(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wo(t,a);return Array.isArray(e?.path)&&e.path.length>0&&(n.path=e.path.map(r=>String(r))),e?.proposedAxes&&typeof e.proposedAxes=="object"&&(n.proposedAxes=ya(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Cd(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=wo(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function wo(t,e){let n=t.readRecentClassifications(500).find(r=>r.msgHash===e);if(!n)throw new Error(`No classification found for ${e}`);return n}function Id(t,e){let a=vo(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?vo(String(e.parentId)):null,o=ya({[a]:e?.axes||{}})[a]||{};if(!a)throw new Error("id is required");if(!n)throw new Error("level is required");let s={id:a,level:n,parentId:r,axes:o,createdAt:new Date().toISOString(),createdBy:"admin-ui"};return t.addNode(s),{node:s}}function Md(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=ya({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Ld(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Rd(t,e){if(!e?.schema||typeof e.schema!="object")throw new Error("schema object is required");return t.saveSchema(e.schema),{summary:"Schema saved"}}function ya(t){let e={};for(let[a,n]of Object.entries(t||{})){if(!n||typeof n!="object")continue;let r={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(r[o]=s);e[a]=r}return e}function vo(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function ba(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function $d(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var ko=`
5533
5567
  <section class="apv__req" id="req-section" aria-labelledby="req-h">
5534
5568
  <h2 id="req-h">Open requests <span id="req-n"></span></h2>
5535
5569
  <p class="apv__lead">What you asked agents for that is not finished, oldest first. Reply, hand it to an agent, close it as done, or drop it. Nothing leaves this list by getting old.</p>
@@ -5546,7 +5580,7 @@ refresh();
5546
5580
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5547
5581
  </form>
5548
5582
  </details>
5549
- </section>`,yo=`
5583
+ </section>`,_o=`
5550
5584
  .apv__req { margin-top: 32px; border-top: 1px solid var(--ax-border); padding-top: 16px; }
5551
5585
  .apv__req h2 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
5552
5586
  .apv__req h2 span { color: var(--ax-muted); font-family: var(--ax-mono); font-size: 12px; font-weight: 400; }
@@ -5568,7 +5602,7 @@ refresh();
5568
5602
  .apv__req select { min-height: 40px; max-width: 100%; }
5569
5603
  .apv__mic.is-on { border-color: var(--ax-err); color: var(--ax-err); }
5570
5604
  .apv__acts + .apv__acts { margin-top: 8px; }
5571
- `,wo=`
5605
+ `,So=`
5572
5606
  (function(){
5573
5607
  var STATE = { in_progress: 'In progress', waiting_owner: 'Waiting on you', waiting_other: 'Waiting on another agent', needs_attention: 'Needs attention' };
5574
5608
  function $(id){ return document.getElementById(id); }
@@ -5710,7 +5744,7 @@ function busy(){
5710
5744
  }
5711
5745
  setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) load(); }, 60000);
5712
5746
  })();
5713
- `;function ko(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5747
+ `;function Eo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5714
5748
  <header class="apv__head">
5715
5749
  <div>
5716
5750
  <h1>Approvals</h1>
@@ -5732,7 +5766,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !busy()) l
5732
5766
  <ol id="apv-list" class="apv__list" aria-label="Waiting for you"></ol>
5733
5767
  <p id="apv-snoozed" class="apv__foot"></p>
5734
5768
 
5735
- ${bo}
5769
+ ${ko}
5736
5770
 
5737
5771
  <details class="apv__settings" id="apv-settings">
5738
5772
  <summary>Settings: expiry, later, daily digest</summary>
@@ -5747,7 +5781,7 @@ ${bo}
5747
5781
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5748
5782
  </form>
5749
5783
  </details>
5750
- </div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Rd+yo,scripts:`${e}<script>${$d}</script><script>${wo}</script>`})}var Rd=`
5784
+ </div>`;return M({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Pd+_o,scripts:`${e}<script>${jd}</script><script>${So}</script>`})}var Pd=`
5751
5785
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
5752
5786
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
5753
5787
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -5796,7 +5830,7 @@ ${bo}
5796
5830
  @media (max-width: 560px) {
5797
5831
  .apv__acts .ax-btn { flex: 1 1 0; }
5798
5832
  }
5799
- `,$d=`
5833
+ `,jd=`
5800
5834
  (function(){
5801
5835
  var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
5802
5836
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply', request: 'Request' };
@@ -5964,7 +5998,7 @@ $('apv-form').addEventListener('submit', async function(ev){
5964
5998
  load();
5965
5999
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
5966
6000
  })();
5967
- `;import{existsSync as Pd,readFileSync as jd}from"fs";var Ae="/api/admin/approvals/requests";function _o(t){let e=kn(t);if(!Pd(e))return[];try{let a=JSON.parse(jd(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var So=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Eo(t,e,a,n){try{return await Od(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Od(t,e,a,n){if(t==="GET"&&e===Ae){let o=gt(n);return{status:200,body:{items:o?o.listOpen().map(s=>Dn(s,o)):[],agents:_o(n.configPath),settings:ht(n.configPath)}}}let r=e===`${Ae}/reply`?"reply":e===`${Ae}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=gt(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",u=_o(n.configPath).find(h=>h.id===p);if(r==="handoff"&&!u)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!ht(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,p,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let f=u?.name??p;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${f} will go on with ${o}`:`${f} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Ae}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=gt(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Ae}/settings`){let o={},s=l=>{let c=a[l];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${l} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=So(a.from),o.channels=So(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await Pn(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:ht(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var Nd=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Dt(t,e=64*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8");if(!r.trim())return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function To(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(ko({peers:e,localToken:a}))}async function Ao(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Ae)){let i=await Eo(o,a,o==="POST"?await Dt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=xt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Dt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Nd.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await vt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(te(e,200,{ok:!0,message:u.message}),!0):(te(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Dt(t),l=Hn(s,typeof i.key=="string"?i.key:"",!!_e(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Dt(t),l={},c=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=fr(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await hr(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(te(e,400,{error:p.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}hn();function Co(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates and guests. Open a person to see the machines they paired and what they asked for."})+`
6001
+ `;import{existsSync as Od,readFileSync as Nd}from"fs";var Ae="/api/admin/approvals/requests";function To(t){let e=kn(t);if(!Od(e))return[];try{let a=JSON.parse(Nd(e,"utf-8"))?.agents??{};return Object.entries(a).map(([n,r])=>({id:n,name:typeof r?.name=="string"&&r.name?r.name:n}))}catch{return[]}}var Ao=t=>typeof t=="string"?t.split(",").map(e=>e.trim()).filter(Boolean):void 0;async function Co(t,e,a,n){try{return await Dd(t,e,a,n)}catch(r){return{status:400,body:{error:String(r?.message??r).slice(0,300)}}}}async function Dd(t,e,a,n){if(t==="GET"&&e===Ae){let o=gt(n);return{status:200,body:{items:o?o.listOpen().map(s=>Dn(s,o)):[],agents:To(n.configPath),settings:ht(n.configPath)}}}let r=e===`${Ae}/reply`?"reply":e===`${Ae}/handoff`?"handoff":null;if(t==="POST"&&r){let o=typeof a.id=="string"?a.id:"",s=r==="reply"?a.text:a.note,i=typeof s=="string"?s.trim():"";if(!o||r==="reply"&&!i)return{status:400,body:{error:r==="reply"?"send { id, text }":"send { id, agentId, note? }"}};let l=gt(n),c=l?.get(o);if(!l||!c||c.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let p=r==="reply"?c.agentId:typeof a.agentId=="string"?a.agentId:"",u=To(n.configPath).find(h=>h.id===p);if(r==="handoff"&&!u)return{status:400,body:{error:`"${p}" is not an agent on this node`}};if(!ht(n.configPath).enabled)return{status:409,body:{error:"Requests are off, so nothing would tell the agent. Turn them on in the settings below."}};if(!l.handOff(o,p,i,n.now??Date.now()))return{status:409,body:{error:`${o} is already closed`}};let f=u?.name??p;return{status:200,body:{ok:!0,message:r==="reply"?`Reply sent: ${f} will go on with ${o}`:`${f} has ${o} now and will be told within a minute`}}}if(t==="POST"&&e===`${Ae}/close`){let o=typeof a.id=="string"?a.id:"",s=a.action;if(!o||s!=="done"&&s!=="drop")return{status:400,body:{error:"send { id, action: done | drop }"}};let i=gt(n),l=i?.get(o);if(!i||!l||l.state==="candidate")return{status:404,body:{error:`no request "${o}"`}};let c=s==="done"?typeof a.evidence=="string"&&a.evidence.trim()?a.evidence:"closed by the owner (dashboard)":typeof a.reason=="string"&&a.reason.trim()?a.reason:"dropped by the owner (dashboard)";return i.close(o,s==="done"?"done":"dropped",c,n.now??Date.now())?{status:200,body:{ok:!0,message:s==="done"?`${o} closed as done`:`${o} dropped`}}:{status:409,body:{error:`${o} is already closed`}}}if(t==="POST"&&e===`${Ae}/settings`){let o={},s=l=>{let c=a[l];if(c!==void 0){if(typeof c!="number"||!(c>0))throw new Error(`${l} must be a positive number`);return c}};typeof a.enabled=="boolean"&&(o.enabled=a.enabled),o.from=Ao(a.from),o.channels=Ao(a.channels),o.staleAfterHours=s("staleAfterHours"),o.retentionDays=s("retentionDays");let i=await Pn(o,{configPath:n.configPath,reload:n.reload});return i.success?{status:200,body:{ok:!0,settings:ht(n.configPath)}}:{status:400,body:{error:i.error}}}return{status:404,body:{error:"Not found"}}}var Hd=["yes","no","later"];function te(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Dt(t,e=64*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8");if(!r.trim())return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function Io(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(Eo({peers:e,localToken:a}))}async function Mo(t,e,a,n,r={}){if(!a.startsWith("/api/admin/approvals"))return!1;let o=(t.method||"GET").toUpperCase(),s=r.ctx??{root:process.cwd(),configPath:r.configPath,reload:r.reload};if(o!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return te(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(a.startsWith(Ae)){let i=await Co(o,a,o==="POST"?await Dt(t):{},s);return te(e,i.status,i.body),!0}if(o==="GET"&&a==="/api/admin/approvals"){let i=xt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return te(e,200,{...i,settings:_e(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Dt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Hd.includes(c))return te(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=_e(s.configPath),u=await vt(s,l,c,{note:typeof i.note=="string"?i.note:void 0,force:i.force===!0,laterHours:p.laterHours,by:"operator (dashboard)"});return u.ok?(te(e,200,{ok:!0,message:u.message}),!0):(te(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Dt(t),l=Hn(s,typeof i.key=="string"?i.key:"",!!_e(s.configPath).popup?.enabled);return l.ok?(te(e,200,{ok:!0,message:l.message}),!0):(te(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Dt(t),l={},c=u=>{let f=i[u];if(f!==void 0){if(typeof f!="number"||!(f>0))throw new Error(`${u} must be a positive number`);return f}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let f=fr(u);if(!f)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=f}}let p=await hr(l,{configPath:s.configPath,reload:s.reload});return p.success?(te(e,200,{ok:!0,settings:_e(s.configPath)}),!0):(te(e,400,{error:p.error}),!0)}}catch(i){return te(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return te(e,404,{error:"Not found"}),!0}hn();function Lo(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=ve({kicker:"Operations",title:"People",lead:"Everyone who talks to your agents: you, your teammates and guests. Open a person to see the machines they paired and what they asked for."})+`
5968
6002
  <div class="pp">
5969
6003
  <div id="pp-msg" class="pp-msg" role="status" aria-live="polite"></div>
5970
6004
  <section id="pp-none" class="pp-none" hidden aria-labelledby="pp-none-title">
@@ -5977,7 +6011,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5977
6011
  </ol>
5978
6012
  </section>
5979
6013
  <ol id="pp-list" class="pp-list" aria-label="People"><li class="pp-empty">Loading\u2026</li></ol>
5980
- </div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Dd,scripts:`${e}<script>${Hd}</script>`})}var Dd=`
6014
+ </div>`;return M({title:"AgentX \xB7 People",activeTab:"people",subtitle:"People",peers:t.peers,body:a,css:Bd,scripts:`${e}<script>${zd}</script>`})}var Bd=`
5981
6015
  .pp { max-width: 1040px; margin: 0 auto; padding: 0 24px 64px; }
5982
6016
  .pp-msg { min-height: 1.4em; margin: 4px 0 8px; font-size: var(--ax-fs-sm); }
5983
6017
  .pp-msg.is-bad { color: var(--ax-red-ink); }
@@ -6018,7 +6052,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6018
6052
  .pp-text { overflow-wrap: anywhere; }
6019
6053
  .pp-meta { margin-top: 2px; display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--ax-fs-xs); color: var(--ax-text-2); }
6020
6054
  @media (prefers-reduced-motion: reduce) { .pp-caret { transition: none; } }
6021
- `,Hd=`
6055
+ `,zd=`
6022
6056
  (function () {
6023
6057
  var list = document.getElementById('pp-list');
6024
6058
  var msg = document.getElementById('pp-msg');
@@ -6156,7 +6190,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6156
6190
  load();
6157
6191
  setInterval(load, 30000);
6158
6192
  })();
6159
- `;var wa="/api/admin/people";function Bd(t,e){let a=br(t,e);return a?{...e,answer:a}:e}function zd(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function qd(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&zd(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:pn,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Fd=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Io(t,e,a,n){if(a!=="/people"&&a!==wa&&!a.startsWith(`${wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if((t.url||"").split(/[?#]/)[0]!==a)return pe(e,404,{error:"not found"}),!0;if(a==="/people")return r!=="GET"?(pe(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Co({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return pe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(p=>Bd(n.root,p)),s=()=>qd(n.people(),o());if(r==="GET"&&a===wa){let c=s();return pe(e,200,{people:c,paired:c.reduce((p,u)=>p+u.machines.active+u.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return pe(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),u=[],f=[];try{p&&(u=gr(p,c.id))}catch{}try{p&&(f=It(p,c.id,20))}catch{}return pe(e,200,{person:c,devices:o(c.id).sort(Fd),requests:u,runs:f,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,c,p]=l,u=n.members.byToken(p);if(!u||u.personId!==c)return pe(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return pe(e,409,{error:"this machine's access has already ended"}),!0;let f=wr({tokens:n.tokens??new F,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return pe(e,200,{ok:!0,device:f}),!0}return pe(e,404,{error:"not found"}),!0}import{resolve as Kd}from"path";import{existsSync as Jd}from"fs";import Vd from"better-sqlite3";var Mo=new WeakSet;function Ud(t,e,a={}){if(Mo.has(t))return;Mo.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let c=i[l].bind(i);i[l]=(...p)=>{let u=r();try{return c(...p)}finally{let f=r()-u;f>=n&&e({sql:s,ms:f})}}}return i}}function Wd(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ye(t,e){Ud(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Wd(a)}`))}function Lo(t={}){let e=`<div class="ax-obs">
6193
+ `;var wa="/api/admin/people";function qd(t,e){let a=br(t,e);return a?{...e,answer:a}:e}function Fd(t){return t.state!=="pending"||!t.answer?t.state:t.answer==="yes"?"active":"removed"}function pe(t,e,a){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a))}function Ud(t,e){let a=(o,s)=>e.filter(i=>i.personId===o&&Fd(i)===s).length,n=o=>({id:o.id,name:o.name,role:o.role,identities:o.identities,agents:o.agents??[],machines:{active:a(o.id,"active"),pending:a(o.id,"pending")}}),r=t.map(n);return t.some(o=>o.role==="owner")||r.unshift({...n({id:pn,name:"Owner of this machine",role:"owner",identities:[]}),builtIn:!0}),r}var Wd=(t,e)=>e.createdAt.localeCompare(t.createdAt);async function Ro(t,e,a,n){if(a!=="/people"&&a!==wa&&!a.startsWith(`${wa}/`))return!1;let r=(t.method||"GET").toUpperCase();if((t.url||"").split(/[?#]/)[0]!==a)return pe(e,404,{error:"not found"}),!0;if(a==="/people")return r!=="GET"?(pe(e,405,{error:"GET only"}),!0):(e.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),e.end(Lo({peers:n.peers,localToken:n.localToken})),!0);if(r!=="GET"&&t.headers["x-requested-with"]!=="agentx-board")return pe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;let o=c=>n.members.devices(c).map(p=>qd(n.root,p)),s=()=>Ud(n.people(),o());if(r==="GET"&&a===wa){let c=s();return pe(e,200,{people:c,paired:c.reduce((p,u)=>p+u.machines.active+u.machines.pending,0)}),!0}let i=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})$/);if(r==="GET"&&i){let c=s().find(h=>h.id===i[1]);if(!c)return pe(e,404,{error:`no person "${i[1]}"`}),!0;let p=n.db(),u=[],f=[];try{p&&(u=gr(p,c.id))}catch{}try{p&&(f=It(p,c.id,20))}catch{}return pe(e,200,{person:c,devices:o(c.id).sort(Wd),requests:u,runs:f,database:!!p}),!0}let l=a.match(/^\/api\/admin\/people\/([a-z0-9][a-z0-9_-]{0,39})\/devices\/([A-Za-z0-9_-]{1,80})\/end$/);if(r==="POST"&&l){let[,c,p]=l,u=n.members.byToken(p);if(!u||u.personId!==c)return pe(e,404,{error:"no such machine for this person"}),!0;if(u.state==="removed")return pe(e,409,{error:"this machine's access has already ended"}),!0;let f=wr({tokens:n.tokens??new F,members:n.members,now:n.now},p,"removed by the owner (dashboard)");return pe(e,200,{ok:!0,device:f}),!0}return pe(e,404,{error:"not found"}),!0}import{resolve as Vd}from"path";import{existsSync as Yd}from"fs";import Qd from"better-sqlite3";var $o=new WeakSet;function Gd(t,e,a={}){if($o.has(t))return;$o.add(t);let n=a.thresholdMs??200,r=a.now??(()=>performance.now()),o=t.prepare.bind(t);t.prepare=s=>{let i=o(s);for(let l of["all","get","run"]){let c=i[l].bind(i);i[l]=(...p)=>{let u=r();try{return c(...p)}finally{let f=r()-u;f>=n&&e({sql:s,ms:f})}}}return i}}function Xd(t,e=160){let a=t.replace(/\s+/g," ").trim();return a.length>e?`${a.slice(0,e-1)}\u2026`:a}function ye(t,e){Gd(t,({sql:a,ms:n})=>console.error(`[${e}] slow query, ${Math.round(n)} ms: ${Xd(a)}`))}function Po(t={}){let e=`<div class="ax-obs">
6160
6194
  <header class="ax-obs__head">
6161
6195
  <h1>Health</h1>
6162
6196
  <p class="ax-obs__sub">Platform-health view: what each agent ran, what failed, and how the router decided. <span class="ax-obs__sub-link">Spend lives on the <a href="/admin/cost">Cost</a> page.</span></p>
@@ -6278,7 +6312,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6278
6312
  </div>
6279
6313
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
6280
6314
  </section>
6281
- </div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Gd,scripts:`<script>${Xd}</script>`})}var Gd=`
6315
+ </div>`;return M({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Kd,scripts:`<script>${Jd}</script>`})}var Kd=`
6282
6316
  .ax-obs { padding: 16px 24px; }
6283
6317
  .ax-obs__head { margin-bottom: 16px; }
6284
6318
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -6395,7 +6429,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6395
6429
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
6396
6430
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
6397
6431
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
6398
- `,Xd=`
6432
+ `,Jd=`
6399
6433
  (function(){
6400
6434
  var panes = document.querySelectorAll('.ax-obs__pane');
6401
6435
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -6779,7 +6813,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6779
6813
 
6780
6814
  load(current);
6781
6815
  })();
6782
- `;var Po={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function jo(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function ka(t){let e=Po[jo(t.model)],a=t.input_tokens/1e6*e.input+t.output_tokens/1e6*e.output+t.cache_read_tokens/1e6*e.cacheRead+t.cache_create_tokens/1e6*e.cacheCreate,n=(t.tier2_input_tokens??0)/1e6*e.input*.5+(t.tier2_output_tokens??0)/1e6*e.output*.5+(t.tier2_cache_read_tokens??0)/1e6*e.cacheRead*.5+(t.tier2_cache_create_tokens??0)/1e6*e.cacheCreate*.5;return a+n}function Yd(){let t=Kd(process.cwd(),".agentx/db.sqlite");if(!Jd(t))return null;try{let e=new Vd(t,{readonly:!0,fileMustExist:!0});return ye(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Oo(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Lo({peers:a}))}function Qd(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function No(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Yd();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Qd(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6816
+ `;var No={opus:{input:15,output:75,cacheRead:1.5,cacheCreate:18.75},sonnet:{input:3,output:15,cacheRead:.3,cacheCreate:3.75},haiku:{input:.25,output:1.25,cacheRead:.025,cacheCreate:.3125},external:{input:0,output:0,cacheRead:0,cacheCreate:0}};function Do(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function ka(t){let e=No[Do(t.model)],a=t.input_tokens/1e6*e.input+t.output_tokens/1e6*e.output+t.cache_read_tokens/1e6*e.cacheRead+t.cache_create_tokens/1e6*e.cacheCreate,n=(t.tier2_input_tokens??0)/1e6*e.input*.5+(t.tier2_output_tokens??0)/1e6*e.output*.5+(t.tier2_cache_read_tokens??0)/1e6*e.cacheRead*.5+(t.tier2_cache_create_tokens??0)/1e6*e.cacheCreate*.5;return a+n}function Zd(){let t=Vd(process.cwd(),".agentx/db.sqlite");if(!Yd(t))return null;try{let e=new Qd(t,{readonly:!0,fileMustExist:!0});return ye(e,"health"),{db:e,close:()=>e.close()}}catch{return null}}function Ho(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Po({peers:a}))}function ep(t){let e=new URL(t.url||"/","http://_"),a=parseInt(e.searchParams.get("limit")||"50",10),n=Number.isFinite(a)?Math.max(1,Math.min(500,a)):50,r=e.searchParams.get("agent")||void 0;return{limit:n,agent:r&&r.length>0?r:void 0}}function fe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Bo(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Zd();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=ep(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6783
6817
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
6784
6818
  FROM route_traces
6785
6819
  ${i.length?"WHERE "+i.join(" AND "):""}
@@ -6794,8 +6828,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6794
6828
  FROM task_history
6795
6829
  WHERE ${i.join(" AND ")}
6796
6830
  ORDER BY started_at DESC LIMIT @limit
6797
- `,u=r.db.prepare(c).all(l).map(f=>({...f,plain:Do(f.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,Zd(r.db)),!0;if(n==="activity")return fe(e,200,ep(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=Ro(i.searchParams.get("range"));return fe(e,200,$o(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=Ro(i.searchParams.get("range")),c=$o(r.db,l),p=tp(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return fe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Do(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(`
6798
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Zd(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=y=>p.length?p[Math.min(p.length-1,Math.floor(p.length*y))].duration_ms:0,f=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((y,I)=>y+ka(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((y,I)=>y+ka(I),0),g=t.prepare(`
6831
+ `,u=r.db.prepare(c).all(l).map(f=>({...f,plain:zo(f.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,tp(r.db)),!0;if(n==="activity")return fe(e,200,ap(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=jo(i.searchParams.get("range"));return fe(e,200,Oo(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=jo(i.searchParams.get("range")),c=Oo(r.db,l),p=np(c.days);return e.writeHead(200,{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="agentx-cost-${l||"all"}d-${Date.now()}.csv"`}),e.end(p),!0}return fe(e,404,{error:"unknown observability slice",rows:[]}),!0}catch(o){return fe(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function zo(t){let e=String(t||"");return e?/timed out|SIGTERM|exit 143|maxExecutionMinutes/i.test(e)?"Agent ran past its time limit":/ECONNREFUSED|fetch failed|getaddrinfo|ENOTFOUND/i.test(e)?"Couldn't reach a service over the network":/401|403|Unauthorized|Forbidden|invalid token|missing scope/i.test(e)?"Authentication or permission denied":/rate limit|429|too many requests/i.test(e)?"Hit a rate limit (too many calls)":/quota|insufficient_quota/i.test(e)?"Provider account out of quota or credits":/tier-?2|tier two|200K|200,000/i.test(e)?"Hit Anthropic tier-2 billing threshold":/JSON|parse|unexpected token/i.test(e)?"Got a response in the wrong shape":/permission denied|EACCES|EPERM/i.test(e)?"File permission denied":/ENOENT|no such file/i.test(e)?"Expected file is missing":/abort|cancel/i.test(e)?"Task was cancelled before it finished":e.split(`
6832
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function tp(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=y=>p.length?p[Math.min(p.length-1,Math.floor(p.length*y))].duration_ms:0,f=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((y,I)=>y+ka(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((y,I)=>y+ka(I),0),g=t.prepare(`
6799
6833
  SELECT agent_id,
6800
6834
  COUNT(*) AS tasks,
6801
6835
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6818,7 +6852,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6818
6852
  FROM task_history
6819
6853
  WHERE status='error' AND started_at >= ?
6820
6854
  ORDER BY started_at DESC LIMIT 5
6821
- `).all(o).map(y=>({...y,plain:Do(y.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:T}}function ep(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(`
6855
+ `).all(o).map(y=>({...y,plain:zo(y.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:f,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:T}}function ap(t,e){let a=new Date(Date.now()-864e5).toISOString(),n=new Date(Date.now()-7*864e5).toISOString(),r=e.agent?"AND agent_id = @agent":"",o=e.agent?{agent:e.agent}:{},s=t.prepare(`
6822
6856
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6823
6857
  COUNT(*) AS tasks,
6824
6858
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6845,7 +6879,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6845
6879
  WHERE started_at >= @since
6846
6880
  GROUP BY agent_id
6847
6881
  ORDER BY tasks_24h DESC, tasks_7d DESC
6848
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function Ro(t){if(!t)return 30;if(t==="all"||t==="0")return 0;let e=parseInt(t,10);return!Number.isFinite(e)||e<=0?30:Math.min(e,365)}function $o(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6882
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function jo(t){if(!t)return 30;if(t==="all"||t==="0")return 0;let e=parseInt(t,10);return!Number.isFinite(e)||e<=0?30:Math.min(e,365)}function Oo(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6849
6883
  SELECT day, agent_id, model,
6850
6884
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
6851
6885
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -6853,10 +6887,10 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6853
6887
  FROM usage_daily
6854
6888
  ${a}
6855
6889
  ORDER BY day
6856
- `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,f=0,h=0,k=0,_=0,S=0,g={},d={};for(let E of n){let $=ka(E),L=jo(E.model),j=Po[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),Oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(p+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,_+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(f+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=Oe,Z.cost+=$,Z.tier2+=W;let B=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});B.tasks+=E.tasks||0,B.cost+=$,B.tier2+=W,B.input+=q,B.output+=G,B.cacheRead+=ie,B.cacheCreate+=Oe,E.model&&(B.model=E.model);let O=d[E.agent_id]||(d[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=Oe,E.model&&(O.model=E.model)}let m=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,v=0,w=0,T=0,y=0,I=0;for(let E of m)x+=E.tasks,v+=E.input,w+=E.output,T+=E.cacheRead,y+=E.cacheCreate,I+=E.cost;let C=Object.entries(d).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:h,tier2PctToday:l>0?f/l:0,spendRange:I,avgDailyRange:m.length?I/m.length:0,tasksRange:x,tokensRange:v+w+T+y,cacheHitRange:T+v>0?T/(T+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(k-_)/_:0},days:m,perAgent:C}}function tp(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+`
6890
+ `).all(),r=new Date().toISOString().slice(0,10),o=new Date(Date.now()-864e5).toISOString().slice(0,10),s=new Date(Date.now()-7*864e5).toISOString().slice(0,10),i=new Date(Date.now()-14*864e5).toISOString().slice(0,10),l=0,c=0,p=0,u=0,f=0,h=0,k=0,_=0,S=0,g={},d={};for(let E of n){let $=ka(E),L=Do(E.model),j=No[L],W=(E.tier2_input_tokens||0)/1e6*j.input*.5+(E.tier2_output_tokens||0)/1e6*j.output*.5+(E.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(E.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,q=(E.input_tokens||0)+(E.tier2_input_tokens||0),G=(E.output_tokens||0)+(E.tier2_output_tokens||0),ie=(E.cache_read_tokens||0)+(E.tier2_cache_read_tokens||0),Oe=(E.cache_create_tokens||0)+(E.tier2_cache_create_tokens||0);u+=$,E.day>=s&&(p+=$,k+=E.tasks||0),E.day>=i&&E.day<s&&(S+=$,_+=E.tasks||0),E.day===r&&(l+=$),E.day===o&&(c+=$),E.day===r&&(f+=W),E.day>=s&&(h+=W);let Z=g[E.day]||(g[E.day]={date:E.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});Z.tasks+=E.tasks||0,Z.input+=q,Z.output+=G,Z.cacheRead+=ie,Z.cacheCreate+=Oe,Z.cost+=$,Z.tier2+=W;let B=Z.agents[E.agent_id]||(Z.agents[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});B.tasks+=E.tasks||0,B.cost+=$,B.tier2+=W,B.input+=q,B.output+=G,B.cacheRead+=ie,B.cacheCreate+=Oe,E.model&&(B.model=E.model);let O=d[E.agent_id]||(d[E.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:E.model});O.tasks+=E.tasks||0,O.cost+=$,O.tier2+=W,O.input+=q,O.output+=G,O.cacheRead+=ie,O.cacheCreate+=Oe,E.model&&(O.model=E.model)}let m=Object.values(g).sort((E,$)=>E.date<$.date?-1:1),x=0,v=0,w=0,T=0,y=0,I=0;for(let E of m)x+=E.tasks,v+=E.input,w+=E.output,T+=E.cacheRead,y+=E.cacheCreate,I+=E.cost;let C=Object.entries(d).map(([E,$])=>({agent_id:E,...$,tokens:$.input+$.output+$.cacheRead+$.cacheCreate})).sort((E,$)=>$.cost-E.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:f,tier2_7d:h,tier2PctToday:l>0?f/l:0,spendRange:I,avgDailyRange:m.length?I/m.length:0,tasksRange:x,tokensRange:v+w+T+y,cacheHitRange:T+v>0?T/(T+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(k-_)/_:0},days:m,perAgent:C}}function np(t){let e="date,tasks,input,output,cache_read,cache_create,cost_usd,top_agent",a=t.map(n=>{let r=Object.entries(n.agents).sort(([,o],[,s])=>s.cost-o.cost)[0];return[n.date,n.tasks,n.input,n.output,n.cacheRead,n.cacheCreate,n.cost.toFixed(6),r?r[0]:""].join(",")});return e+`
6857
6891
  `+a.join(`
6858
6892
  `)+`
6859
- `}import{resolve as ap}from"path";import{existsSync as np}from"fs";import rp from"better-sqlite3";function op(){let t=ap(process.cwd(),".agentx/intent/ledger.sqlite");if(!np(t))return null;try{let e=new rp(t,{readonly:!0,fileMustExist:!0});return ye(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Ho>6e4&&(Ho=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var Ho=0;function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function sp(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 Bo(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=op();if(!r)return Ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=sp(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6893
+ `}import{resolve as rp}from"path";import{existsSync as op}from"fs";import sp from"better-sqlite3";function ip(){let t=rp(process.cwd(),".agentx/intent/ledger.sqlite");if(!op(t))return null;try{let e=new sp(t,{readonly:!0,fileMustExist:!0});return ye(e,"ledger-panel"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-qo>6e4&&(qo=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var qo=0;function Ce(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function lp(t){if(!t)return;let e=String(t).trim().match(/^(\d+)\s*(s|m|h|d|w)?$/i);if(!e)return;let a=parseInt(e[1],10),n=(e[2]||"h").toLowerCase(),r=n==="s"?1e3:n==="m"?6e4:n==="h"?36e5:n==="d"?864e5:n==="w"?7*864e5:0;return Date.now()-a*r}async function Fo(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ip();if(!r)return Ce(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=lp(o.searchParams.get("since")),i=o.searchParams.get("source")||"",l=o.searchParams.get("project")||"",c=parseInt(o.searchParams.get("limit")||"50",10),p=Number.isFinite(c)?Math.max(1,Math.min(500,c)):50;if(n==="stats"){let u=s!==void 0?"WHERE ts >= @since":"",f=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),k=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${f}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${f} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6860
6894
  SELECT COUNT(*) AS n FROM intent_decisions d
6861
6895
  LEFT JOIN intent_resolutions r
6862
6896
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
@@ -6883,7 +6917,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6883
6917
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6884
6918
  WHERE ${u.join(" AND ")}
6885
6919
  ORDER BY d.decided_at DESC LIMIT @limit
6886
- `;return Ce(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function zo(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6920
+ `;return Ce(e,200,{rows:r.db.prepare(h).all(f)}),!0}return Ce(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return Ce(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function Uo(t={}){return M({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6887
6921
  <header class="ax-led__head">
6888
6922
  <h1>Intent ledger</h1>
6889
6923
  <p class="ax-led__sub">Read-only view over <code>.agentx/intent/ledger.sqlite</code> \u2014 same source as <code>agentx ledger</code>. Replay and lineage live in the CLI for now.</p>
@@ -7088,7 +7122,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7088
7122
  }
7089
7123
  load();
7090
7124
  })();
7091
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function qo(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7125
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Wo(t={}){return M({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
7092
7126
  <header class="ax-cost__head">
7093
7127
  <div>
7094
7128
  <h1>Cost</h1>
@@ -7661,7 +7695,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7661
7695
  load();
7662
7696
  setInterval(load, 30000);
7663
7697
  })();
7664
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Fo(t={}){let e=`<div class="ax-pj__root">
7698
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Go(t={}){let e=`<div class="ax-pj__root">
7665
7699
  <aside class="ax-pj__list">
7666
7700
  <header>
7667
7701
  <h2>Projects</h2>
@@ -7688,7 +7722,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7688
7722
  </header>
7689
7723
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
7690
7724
  </section>
7691
- </div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ip,scripts:`<script>${lp}</script>`})}var ip=`
7725
+ </div>`;return M({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:cp,scripts:`<script>${dp}</script>`})}var cp=`
7692
7726
  .ax-pj__root {
7693
7727
  display: grid;
7694
7728
  grid-template-columns: 360px 1fr;
@@ -7875,7 +7909,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7875
7909
  }
7876
7910
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
7877
7911
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
7878
- `,lp=`
7912
+ `,dp=`
7879
7913
  (function(){
7880
7914
  const $ = (sel) => document.querySelector(sel);
7881
7915
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -8525,9 +8559,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
8525
8559
  load();
8526
8560
  });
8527
8561
  })();
8528
- `;import{resolve as Aa,join as Sp}from"path";import{existsSync as Ca,readdirSync as Ep,readFileSync as Tp}from"fs";import Ap from"better-sqlite3";var Wo=String.raw`[\w.-]+(?:/[\w.-]+)+`,cp=new RegExp(`^(?:chat:)?(${Wo}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),dp=new RegExp(`^\\[(?:GitLab|GitHub) (${Wo}) `);function Uo(t){if(!t)return null;let e=t.match(cp);return e?e[1]:null}function _a(t){if(!t)return null;let e=t.trimStart().match(dp);return e?e[1]:null}function Ht(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Uo(typeof n?.chatId=="string"?n.chatId:null)??Uo(e)??_a(a)}function pp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var up=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,mp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,fp=t=>/^issue/i.test(t)?"issue":"mr";function hp(t){let e=t.subject.match(up)??t.inputPreview.trimStart().match(mp);return e?{kind:fp(e[1]),n:Number(e[2])}:null}function gp(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function Go(t){if(!pp(t.projectId))return[];let e=hp(t);return e?[e]:gp(t.inputPreview)}var xp=6e4,vp=5*6e4,bp=40,Xo=6,Ko=new Map;function Jo(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of Go(n)){let s=Bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=bp)return[...e.values()]}}return[...e.values()]}async function Vo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Bt(s.project,s.ref),l=Ko.get(i);l&&n-l.at<(s.github?vp:xp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Xo)await Promise.all(o.slice(s,s+Xo).map(async i=>{let l=Bt(i.project,i.ref),c=null;try{c=i.github?await wp(i,e,a):await yp(i,e,a)}catch{}Ko.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Yo(t,e,a){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3);try{let o=await a(t,{headers:e,signal:n.signal});return o.ok?await o.json():null}finally{clearTimeout(r)}}async function yp(t,e,a){let n=e.gitlab;if(!n?.host||!n.token)return null;let r=`${n.host.replace(/\/+$/,"")}/api/v4/projects/${encodeURIComponent(t.project)}`,o=t.ref.kind==="mr"?`merge_requests/${t.ref.n}`:`issues/${t.ref.n}`,s=await Yo(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function wp(t,e,a){let n=t.ref.kind==="mr"?`pulls/${t.ref.n}`:`issues/${t.ref.n}`,r={Accept:"application/vnd.github+json","User-Agent":"agentx-dashboard"};e.githubToken&&(r.Authorization=`Bearer ${e.githubToken}`);let o=await Yo(`https://api.github.com/repos/${t.project}/${n}`,r,a);return o?{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(o.title??""),state:o.merged_at?"merged":o.state==="open"?"opened":String(o.state??"opened"),draft:!!o.draft,url:String(o.html_url??""),pipeline:null,mergedAt:o.merged_at?Date.parse(o.merged_at):null}:null}ln();var Sa=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Qo(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=st(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Sa(o.from,80);if(s){a.callback={from:s,status:Sa(o.status,20)??"done"};let i=Sa(o.peer,80);i&&(a.callback.peer=i)}}return a}ln();hn();var Zo={kind:"agentx",id:"agentx",name:"AgentX"},Ea={kind:"person",id:"unknown",name:"Unknown"},kp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),es=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function _p(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function ts(t){let e=s=>({kind:"person",id:`person:${s}`,name:un(t.people,s)}),a=(s,i)=>i||kp.has(s)?Zo:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??fn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(sn(s)==="human")return es(s?.senderUsername)?a(c,!1):Ea;let p=!!Ie(n.senderAgentId)||ta(l?l.sender:s?.sender);return c==="desktop"&&!p?Ea:a(c,p)}let r=_p(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=mn(t.people,t.channel,r);return o?e(o.id):ta(r.name)?Zo:on.has(t.channel)&&!es(r.username)?Ea:a(t.channel,!1)}function Ia(){let t=Aa(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ca(t))return null;try{let e=new Ap(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-as>6e4&&(as=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var as=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Cp(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function os(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function Ip(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function ss(t,e,a){return An(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function Mp(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!Ta(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ta(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Rp(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!Ta(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=ns(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:ns(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var Lp={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Rp(t,e){let a=Lp[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ns(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ta(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function is(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
8562
+ `;import{resolve as Aa,join as Tp}from"path";import{existsSync as Ca,readdirSync as Ap,readFileSync as Cp}from"fs";import Ip from"better-sqlite3";var Ko=String.raw`[\w.-]+(?:/[\w.-]+)+`,pp=new RegExp(`^(?:chat:)?(${Ko}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),up=new RegExp(`^\\[(?:GitLab|GitHub) (${Ko}) `);function Xo(t){if(!t)return null;let e=t.match(pp);return e?e[1]:null}function _a(t){if(!t)return null;let e=t.trimStart().match(up);return e?e[1]:null}function Ht(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Xo(typeof n?.chatId=="string"?n.chatId:null)??Xo(e)??_a(a)}function mp(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function Bt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var fp=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,hp=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,gp=t=>/^issue/i.test(t)?"issue":"mr";function xp(t){let e=t.subject.match(fp)??t.inputPreview.trimStart().match(hp);return e?{kind:gp(e[1]),n:Number(e[2])}:null}function vp(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function Jo(t){if(!mp(t.projectId))return[];let e=xp(t);return e?[e]:vp(t.inputPreview)}var bp=6e4,yp=5*6e4,wp=40,Vo=6,Yo=new Map;function Qo(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of Jo(n)){let s=Bt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=wp)return[...e.values()]}}return[...e.values()]}async function Zo(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=Bt(s.project,s.ref),l=Yo.get(i);l&&n-l.at<(s.github?yp:bp)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Vo)await Promise.all(o.slice(s,s+Vo).map(async i=>{let l=Bt(i.project,i.ref),c=null;try{c=i.github?await _p(i,e,a):await kp(i,e,a)}catch{}Yo.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function es(t,e,a){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3);try{let o=await a(t,{headers:e,signal:n.signal});return o.ok?await o.json():null}finally{clearTimeout(r)}}async function kp(t,e,a){let n=e.gitlab;if(!n?.host||!n.token)return null;let r=`${n.host.replace(/\/+$/,"")}/api/v4/projects/${encodeURIComponent(t.project)}`,o=t.ref.kind==="mr"?`merge_requests/${t.ref.n}`:`issues/${t.ref.n}`,s=await es(`${r}/${o}`,{"PRIVATE-TOKEN":n.token},a);if(!s)return null;let i=s.head_pipeline??s.pipeline;return{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(s.title??""),state:String(s.state??"opened"),draft:!!(s.draft??s.work_in_progress),url:String(s.web_url??""),pipeline:i&&typeof i.status=="string"?{status:i.status,url:String(i.web_url??"")}:null,mergedAt:s.merged_at?Date.parse(s.merged_at):null}}async function _p(t,e,a){let n=t.ref.kind==="mr"?`pulls/${t.ref.n}`:`issues/${t.ref.n}`,r={Accept:"application/vnd.github+json","User-Agent":"agentx-dashboard"};e.githubToken&&(r.Authorization=`Bearer ${e.githubToken}`);let o=await es(`https://api.github.com/repos/${t.project}/${n}`,r,a);return o?{kind:t.ref.kind,project:t.project,n:t.ref.n,title:String(o.title??""),state:o.merged_at?"merged":o.state==="open"?"opened":String(o.state??"opened"),draft:!!o.draft,url:String(o.html_url??""),pipeline:null,mergedAt:o.merged_at?Date.parse(o.merged_at):null}:null}ln();var Sa=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function ts(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=st(e);n&&(a.root={kind:n.kind,channel:n.channel},n.sender&&(a.root.sender=n.sender),n.agentId&&(a.root.agentId=n.agentId));let r=e.delegation;if(r&&typeof r=="object"){let o=r,s=Sa(o.from,80);if(s){a.callback={from:s,status:Sa(o.status,20)??"done"};let i=Sa(o.peer,80);i&&(a.callback.peer=i)}}return a}ln();hn();var as={kind:"agentx",id:"agentx",name:"AgentX"},Ea={kind:"person",id:"unknown",name:"Unknown"},Sp=new Set(["cron","workflow","a2a","mcp","mesh","events","reminder","heartbeat","system","internal","business"]),ns=t=>typeof t=="string"&&/\[bot\]$|^(project|group)_\d+_bot/i.test(t),Ie=t=>typeof t=="string"&&t?t:typeof t=="number"?String(t):void 0;function Ep(t,e,a){let n=t==="workflow"?a?.event?.payload:a,r=n?.issueEvent||n?.webhookEvent,o=n?.sender??r?.sender??n?.message?.from??n?.user??r?.user,s=Ie(o?.id)??(e==="whatsapp"?Ie(n?.from):void 0),i=Ie(o?.username)??Ie(o?.login);return s||i?{id:s,username:i,name:Ie(o?.name)}:null}function rs(t){let e=s=>({kind:"person",id:`person:${s}`,name:un(t.people,s)}),a=(s,i)=>i||Sp.has(s)?as:{kind:"external",id:`ext:${s}`,name:t.channelLabel(s)},n=t.raw&&typeof t.raw=="object"?t.raw:{};if(t.source==="mesh"){let s=n.context&&typeof n.context=="object"?n.context:void 0,i=Ie(n.person)??fn(t.people,s)?.id;if(i)return e(i);let l=st(s),c=l?.channel??t.channel;if(sn(s)==="human")return ns(s?.senderUsername)?a(c,!1):Ea;let p=!!Ie(n.senderAgentId)||ta(l?l.sender:s?.sender);return c==="desktop"&&!p?Ea:a(c,p)}let r=Ep(t.source,t.channel,n);if(!r)return a(t.channel,!1);let o=mn(t.people,t.channel,r);return o?e(o.id):ta(r.name)?as:on.has(t.channel)&&!ns(r.username)?Ea:a(t.channel,!1)}function Ia(){let t=Aa(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ca(t))return null;try{let e=new Ip(t,{readonly:!0,fileMustExist:!0});return ye(e,"activity-graph"),{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-os>6e4&&(os=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var os=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Me={gitlab:{label:"GitLab",color:"#fc6d26"},github:{label:"GitHub",color:"#6e7681"},telegram:{label:"Telegram",color:"#0088cc"},whatsapp:{label:"WhatsApp",color:"#25d366"},slack:{label:"Slack",color:"#4a154b"},discord:{label:"Discord",color:"#5865f2"},mesh:{label:"Mesh (a2a)",color:"#bf8700"},a2a:{label:"Agent \u2192 Agent",color:"#bf8700"},cron:{label:"Cron",color:"#6b7280"},workflow:{label:"Workflow",color:"#9333ea"},api:{label:"Web API",color:"#3a7bd5"},mcp:{label:"Agent tools (MCP)",color:"#bf8700"},voice:{label:"Voice",color:"#e5534b"},desktop:{label:"Desktop assistant",color:"#8957e5"},app:{label:"Phone app",color:"#0f9d8a"},opencode:{label:"OpenCode",color:"#57606a"}};function Mp(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Me)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Me)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Me)return r;let o=n?.issueEvent||n?.webhookEvent;if(o){if(o.user?.username||o.project?.path_with_namespace)return"gitlab";if(o.sender?.login)return"github"}if(e.startsWith("workflow.")){let s=e.slice(9).split("-")[0];if(s in Me)return s}return"workflow"}return t}function ls(t){let e={globex:"#e07a3a",initech:"#3a7bd5",acme:"#10b981",umbrella:"#bc8cff","umbrella-lab":"#bc8cff",hexastack:"#06b6d4",demosite:"#ec775c",internal:"#6b7280",unmapped:"#d29922"};if(e[t])return e[t];let a=["#e07a3a","#3a7bd5","#10b981","#bc8cff","#ec775c","#bf8700","#5865f2","#cf222e"],n=0;for(let r=0;r<t.length;r++)n=n*31+t.charCodeAt(r)|0;return a[Math.abs(n)%a.length]}function Lp(t,e){if(!t)return!1;let a=e?.agents?.[t];return a&&typeof a.system=="boolean"?a.system:!!(t==="graph-agent"||t==="intent-classifier"||/-classifier$/.test(t))}function cs(t,e,a){return An(t,{chatId:String(e?.chatId??e?.message?.chat?.id??""),username:String(e?.sender?.username??e?.message?.from?.username??""),senderId:String(e?.sender?.id??e?.message?.from?.id??"")},a)}function Rp(t,e,a){if(!a||typeof a!="object")return null;if(t==="mesh"){if(typeof a.senderAgentId=="string"&&a.senderAgentId.trim()){let r=a.senderAgentId.trim();return{id:r,name:r,avatar:J(r),kind:"a2a"}}let n=a.context&&typeof a.context=="object"?a.context:null;if(n){let r=typeof n.senderUsername=="string"?n.senderUsername:null,o=typeof n.sender=="string"?n.sender:null,s=typeof n.senderId=="string"?n.senderId:null;if(o&&o.startsWith("agent:")){let l=o.slice(6);if(l&&!Ta(l))return{id:l,name:l,avatar:J(l),kind:"a2a"}}let i=o||r||s;if(i&&!Ta(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:J(i),kind:Pp(e,n)}}}return e==="mesh.task"||e==="mesh.a2a"?{id:"__a2a",name:"Internal (A2A)",avatar:"\u21BB",kind:"a2a"}:null}if(t==="cron"){let n=typeof a.jobId=="string"?a.jobId:null;if(n)return{id:`cron:${n}`,name:`Cron: ${n}`,avatar:"\u23F1",kind:"cron"}}if(t==="workflow"){let n=a.event?.payload;if(n&&typeof n=="object"){if(n.sender&&typeof n.sender=="object"){let s=n.sender,i=typeof s.username=="string"?s.username:null,l=typeof s.name=="string"?s.name:null,c=i||(s.id!=null?String(s.id):null)||l;if(c&&!Ta(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=ss(p);return{id:c,name:l||i||c,avatar:J(l||i||c),kind:u}}}let o=n.issueEvent||n.webhookEvent;if(o&&typeof o=="object"){let s=o.user;if(s&&typeof s=="object"&&(s.username||s.name)){let l=s.username||s.name,c=s.name||s.username;return{id:l,name:c,avatar:J(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:J(i.login),kind:"github"}}}let r=typeof a.workflowId=="string"&&a.workflowId||typeof a.runId=="string"&&a.runId||typeof a.workflow=="string"&&a.workflow||typeof a.event?.id=="string"&&a.event.id.split(":")[0];if(r)return{id:`workflow:${r}`,name:`Workflow: ${r}`,avatar:"\u25B6",kind:"workflow"}}if(a.sender&&typeof a.sender=="object"){let n=a.sender,r=typeof n.username=="string"?n.username:null,o=typeof n.name=="string"?n.name:null,s=r||(n.id!=null?String(n.id):null)||o;if(s){let i=o||r||s;return{id:s,name:i,avatar:J(i),kind:ss(t)}}}if(t==="gitlab"){let n=a.user||a.payload?.user;if(n&&typeof n=="object"&&(n.username||n.name)){let r=n.username||n.name,o=n.name||n.username;return{id:r,name:o,avatar:J(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:J(n.login),kind:"github"}}if(t==="telegram"){let n=a.message?.from||a.from;if(n?.username){let r=n.first_name||n.username;return{id:n.username,name:r,avatar:J(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:J(n.first_name||`tg${n.id}`),kind:"telegram"}}if(t==="whatsapp"){let n=a.from||a.payload?.from;if(n){let r=String(n),o=r.replace(/@.*$/,"");return{id:r,name:o,avatar:J(o),kind:"whatsapp"}}}return null}var $p={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Pp(t,e){let a=$p[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function ss(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Ta(t){if(!t)return!1;let e=t.toLowerCase();return e==="graph-classifier"||e==="graph-agent"||e.startsWith("system:")||e.startsWith("internal:")||e.endsWith("-system")}function J(t){let e=String(t||"?").trim().split(/\s+/).filter(Boolean);return e.length>=2?(e[0][0]+e[1][0]).toUpperCase():String(t||"?").slice(0,2).toUpperCase()}function ds(t,e){if(!e||typeof e!="object")return"";let a=[];if(typeof e.text=="string"&&a.push(e.text),e.message?.text&&a.push(e.message.text),e.message?.caption&&a.push(e.message.caption),e.object_attributes?.note&&a.push(e.object_attributes.note),e.object_attributes?.title){let n=e.object_attributes.title,r=e.object_attributes.description;a.push(r?`${n}
8529
8563
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
8530
- ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function $p(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 ls(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8564
+ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof e.message=="string"&&a.push(e.message),typeof e.prompt=="string"&&a.push(e.prompt),typeof e.input=="string"&&a.push(e.input),e.payload&&typeof e.payload.text=="string"&&a.push(e.payload.text),e.payload&&typeof e.payload.message=="string"&&a.push(e.payload.message);for(let n of a)if(typeof n=="string"&&n.trim().length>0){let r=n.trim();return r.length>220?r.slice(0,217)+"\u2026":r}return""}function jp(t){if(!t)return"(no subject)";let e;return(e=t.match(/^merge_request:(\d+)(?::note:(\d+))?/))?e[2]?`MR #${e[1]} \xB7 note ${e[2]}`:`MR #${e[1]}`:(e=t.match(/^issue:(\d+)(?::note:(\d+))?/))?e[2]?`Issue #${e[1]} \xB7 note ${e[2]}`:`Issue #${e[1]}`:(e=t.match(/^chat:(.+?):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,40)}`:(e=t.match(/^mesh:agent:(.+)$/))?`\u2192 ${e[1]}`:(e=t.match(/^workflow:([^:]+):(.+)$/))?`${e[1]} \xB7 ${e[2].slice(0,30)}`:t.length>60?t.slice(0,57)+"\u2026":t}function ps(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
8531
8565
  SELECT id, ts, source, project, subject, intent, raw_json
8532
8566
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
8533
8567
  `).all(r),s=new Map,i=new Map;if(o.length>0){let y=o.map(L=>L.id),I=y.map((L,j)=>`@id${j}`).join(","),C=Object.fromEntries(y.map((L,j)=>[`id${j}`,L])),E=t.prepare(`
@@ -8536,9 +8570,9 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
8536
8570
  `).all(C);for(let L of E)s.has(L.event_id)||s.set(L.event_id,[]),s.get(L.event_id).push(L);let $=t.prepare(`
8537
8571
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
8538
8572
  FROM intent_resolutions WHERE decision_event_id IN (${I})
8539
- `).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=sa(e?.business??{}),S=e?.people??[];for(let y of o){let I=null;try{I=JSON.parse(y.raw_json)}catch{}let C=ss(y.source,I,k),E=is(y.source,I),$=Qo(I),L=y.project??Ht(I,y.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=ut(L,h),W=L);let q=Cp(y.source,y.intent||"",I),G=Me[q]||{label:q,color:"#6b7280"};p.has(q)||p.set(q,{id:q,label:G.label,color:G.color});let ie=ts({source:y.source,channel:q,raw:I,people:S,channelLabel:O=>Me[O]?.label??O}),Oe="__system",Z,B=Mp(y.source,y.intent||"",I);if(B){Oe=B.id,Z=B.kind;let O=C?.displayName||B.name;(!u.has(B.id)||C?.displayName)&&u.set(B.id,{id:B.id,name:O,avatar:J(O),kind:B.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let O of s.get(y.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let vl=`${y.id}|${O.decided_by}`,rt=i.get(vl),tn=O.decided_at,an=rt?.resolved_at??null,Zt=an===null,bl=rt?.duration_ms??(Zt?n-tn:0),yl=Zt?"active":rt?.status==="error"||rt?.status==="fail"?"error":"completed",ee,Ge;if(j)ee=j,Ge=W;else{let ea=_.get(O.agent_id);ea?(ee=ea,Ge=`${ea}/_${y.source}`):(ee="unmapped",Ge=`unmapped/_${y.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:os(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ge),f.push({id:`${y.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ge,channelId:q,initiatorId:Oe,initiatorKind:Z,subject:$p(y.subject),intent:y.intent||"",startedAt:tn,resolvedAt:an,duration:bl,active:Zt,outcome:yl,tokens:0,inputPreview:E,system:Ip(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(y=>({...y,projects:[...c.get(y.id)||[]].sort()})).sort((y,I)=>y.id.localeCompare(I.id)),d=[],m=new Set;if(e){let y=e.business??{},I=C=>{let E=y.orgChart?.[C]?.role,$=E?y.roles?.[E]?.title:void 0;return typeof $=="string"&&$.trim()?$.trim():void 0};for(let[C,E]of Object.entries(e.agents||{})){let $={id:C,name:E.name||C,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:I(C)};d.push($),m.add(C)}}for(let y of f)m.has(y.agentId)||(d.push({id:y.agentId,name:y.agentId,tier:"worker",model:"",role:""}),m.add(y.agentId));d.sort((y,I)=>y.id.localeCompare(I.id));let x=[],v=new Set;for(let[y,I]of Object.entries(Me))x.push({id:y,label:I.label,color:I.color}),v.add(y);for(let y of p.values())v.has(y.id)||x.push(y);let w=[...u.values()];w.find(y=>y.id==="__system")||w.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:d,channels:x,initiators:w,dispatches:f,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function Ma(t){let e=Ia();if(!e)return null;try{return ls(e.db,ds(),t)}finally{e.close()}}function cs(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=Pp(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:os(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 Pp(t){if(t.clientId!=="unmapped")return t;let e=_a(t.inputPreview);if(!e)return t;let a=ge?.business?.projects??[];return{...t,projectId:e,clientId:ut(e,a)}}async function zt(t){let e=ge?.channels?.gitlab,a=await Vo(Jo(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ge=null;function ds(){return ge&&{...ge,people:Ke(ge.people)}}function ps(t){ge=t}async function us(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ia();if(!n)return he(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=ms(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await zt(ls(n.db,ds(),o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var jp=5e3;async function La(t,e,a,n=Ma){if(a!=="/api/admin/activity-graph/stream"&&!a.startsWith("/api/admin/activity-graph/stream?"))return!1;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: connected
8573
+ `).all(C);for(let L of $)i.set(`${L.decision_event_id}|${L.decision_decided_by}`,L)}let l=new Map,c=new Map,p=new Map,u=new Map,f=[],h=e?.business?.projects??[],k=e?.business?.contactMap??[],_=sa(e?.business??{}),S=e?.people??[];for(let y of o){let I=null;try{I=JSON.parse(y.raw_json)}catch{}let C=cs(y.source,I,k),E=ds(y.source,I),$=ts(I),L=y.project??Ht(I,y.subject,E),j=null,W=null;C?(j=C.client,W=C.project||`${C.client}/_chat`):L&&(j=ut(L,h),W=L);let q=Mp(y.source,y.intent||"",I),G=Me[q]||{label:q,color:"#6b7280"};p.has(q)||p.set(q,{id:q,label:G.label,color:G.color});let ie=rs({source:y.source,channel:q,raw:I,people:S,channelLabel:O=>Me[O]?.label??O}),Oe="__system",Z,B=Rp(y.source,y.intent||"",I);if(B){Oe=B.id,Z=B.kind;let O=C?.displayName||B.name;(!u.has(B.id)||C?.displayName)&&u.set(B.id,{id:B.id,name:O,avatar:J(O),kind:B.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let O of s.get(y.id)??[]){if(O.outcome!=="dispatched"||!O.agent_id)continue;let wl=`${y.id}|${O.decided_by}`,rt=i.get(wl),tn=O.decided_at,an=rt?.resolved_at??null,Zt=an===null,kl=rt?.duration_ms??(Zt?n-tn:0),_l=Zt?"active":rt?.status==="error"||rt?.status==="fail"?"error":"completed",ee,Ge;if(j)ee=j,Ge=W;else{let ea=_.get(O.agent_id);ea?(ee=ea,Ge=`${ea}/_${y.source}`):(ee="unmapped",Ge=`unmapped/_${y.source}`)}l.has(ee)||l.set(ee,{id:ee,name:ee,color:ls(ee),projects:[]}),c.has(ee)||c.set(ee,new Set),c.get(ee).add(Ge),f.push({id:`${y.id}|${O.decided_by}`,agentId:O.agent_id,clientId:ee,projectId:Ge,channelId:q,initiatorId:Oe,initiatorKind:Z,subject:jp(y.subject),intent:y.intent||"",startedAt:tn,resolvedAt:an,duration:kl,active:Zt,outcome:_l,tokens:0,inputPreview:E,system:Lp(O.agent_id,e),...$,starter:ie})}}let g=[...l.values()].map(y=>({...y,projects:[...c.get(y.id)||[]].sort()})).sort((y,I)=>y.id.localeCompare(I.id)),d=[],m=new Set;if(e){let y=e.business??{},I=C=>{let E=y.orgChart?.[C]?.role,$=E?y.roles?.[E]?.title:void 0;return typeof $=="string"&&$.trim()?$.trim():void 0};for(let[C,E]of Object.entries(e.agents||{})){let $={id:C,name:E.name||C,tier:E.tier==="claude-code"?"lead":"worker",model:E.model||"",role:E.systemPrompt?E.systemPrompt.split(/[.\n]/)[0].slice(0,60):E.tier||"",title:I(C)};d.push($),m.add(C)}}for(let y of f)m.has(y.agentId)||(d.push({id:y.agentId,name:y.agentId,tier:"worker",model:"",role:""}),m.add(y.agentId));d.sort((y,I)=>y.id.localeCompare(I.id));let x=[],v=new Set;for(let[y,I]of Object.entries(Me))x.push({id:y,label:I.label,color:I.color}),v.add(y);for(let y of p.values())v.has(y.id)||x.push(y);let w=[...u.values()];w.find(y=>y.id==="__system")||w.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let T=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:g,agents:d,channels:x,initiators:w,dispatches:f,forges:{gitlab:typeof T=="string"?T:void 0,github:"https://github.com"}}}function Ma(t){let e=Ia();if(!e)return null;try{return ps(e.db,ms(),t)}finally{e.close()}}function us(t){let e=new Map,a=new Map,n=new Map,r=new Map,o=[],s=0,i=0,l={};for(let{nodeId:c,snap:p}of t){l.gitlab??=p.forges?.gitlab,l.github??=p.forges?.github,p.now>s&&(s=p.now),p.windowH>i&&(i=p.windowH);for(let u of p.clients){let f=e.get(u.id);if(!f)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...f.projects,...u.projects])).sort();e.set(u.id,{...f,projects:h})}}for(let u of p.agents)a.has(u.id)||a.set(u.id,u);for(let u of p.channels)n.has(u.id)||n.set(u.id,u);for(let u of p.initiators)r.has(u.id)||r.set(u.id,u);for(let u of p.dispatches){let f=Op(u);if(f.clientId!==u.clientId&&!e.has(f.clientId)&&e.set(f.clientId,{id:f.clientId,name:f.clientId,color:ls(f.clientId),projects:[]}),f.projectId!==u.projectId){let h=e.get(f.clientId);h.projects.includes(f.projectId)||e.set(f.clientId,{...h,projects:[...h.projects,f.projectId].sort()})}o.push({...f,nodeId:c,id:`${c}::${f.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,p)=>c.id.localeCompare(p.id)),agents:[...a.values()].sort((c,p)=>c.id.localeCompare(p.id)),channels:[...n.values()],initiators:[...r.values()],dispatches:o.sort((c,p)=>p.startedAt-c.startedAt)}}function Op(t){if(t.clientId!=="unmapped")return t;let e=_a(t.inputPreview);if(!e)return t;let a=ge?.business?.projects??[];return{...t,projectId:e,clientId:ut(e,a)}}async function zt(t){let e=ge?.channels?.gitlab,a=await Zo(Qo(t.dispatches),{gitlab:e?.host&&e?.token?{host:e.host,token:e.token}:void 0,githubToken:process.env.GITHUB_TOKEN||void 0});return{...t,forge:a}}var ge=null;function ms(){return ge&&{...ge,people:Ke(ge.people)}}function fs(t){ge=t}async function hs(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=Ia();if(!n)return he(e,503,{error:"intent ledger not available",clients:[],agents:[],channels:[],initiators:[],dispatches:[]}),!0;try{let r=new URL(t.url||"/","http://_"),o=gs(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await zt(ps(n.db,ms(),o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Np=5e3;async function La(t,e,a,n=Ma){if(a!=="/api/admin/activity-graph/stream"&&!a.startsWith("/api/admin/activity-graph/stream?"))return!1;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: connected
8540
8574
 
8541
- `);let r=new URL(t.url||"/","http://_"),o=ms(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,i=()=>{s=!0};t.on("close",i),t.on("error",i),e.on("close",i),e.on("error",i);let l=setInterval(()=>{if(!s)try{e.write(`: hb
8575
+ `);let r=new URL(t.url||"/","http://_"),o=gs(parseInt(r.searchParams.get("hours")||"6",10)),s=!1,i=()=>{s=!0};t.on("close",i),t.on("error",i),e.on("close",i),e.on("error",i);let l=setInterval(()=>{if(!s)try{e.write(`: hb
8542
8576
 
8543
8577
  `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await zt(p);if(s)break;u?(e.write(`event: snapshot
8544
8578
  `),e.write(`data: ${JSON.stringify(u)}
@@ -8549,7 +8583,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
8549
8583
  `)}catch(p){e.write(`event: error
8550
8584
  data: ${JSON.stringify({error:p?.message??String(p)})}
8551
8585
 
8552
- `)}let c=Date.now();for(;!s&&Date.now()-c<jp;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function ms(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Op(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Aa(process.cwd(),".agentx/task-history",t,n);if(!Ca(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Aa(process.cwd(),".agentx/task-history",t,o);return Ca(s)?rs(s,e,a):null}return rs(r,e,a)}function rs(t,e,a){let n=null,r=1/0;for(let o of Ep(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Tp(Sp(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 fs(t,e,a){let n=a.match(/^\/api\/admin\/activity-graph\/dispatch\/([^/?]+)(?:\?.*)?$/);if(!n)return!1;let r=decodeURIComponent(n[1]),o=r.indexOf("|");if(o<0)return he(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Ia();if(!l)return he(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return he(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return he(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(c.raw_json)}catch{}let h=is(c.source,f),k=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let w=Op(p.agent_id,p.decided_at);if(w){typeof w.responseText=="string"&&(_=w.responseText);let T=w.transcript;Array.isArray(T)&&(S=T.length)}}let g=ge?.business?.projects??[],d=ge?.business?.contactMap??[],m=sa(ge?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=ss(c.source,f,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||Ht(f,c.subject,h)){let w=c.project||Ht(f,c.subject,h);x={client:ut(w,g),project:w,via:c.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(p.agent_id){let w=m.get(p.agent_id);w&&(x={client:w,project:`${w}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${w})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:_,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as Bp,readFileSync as zp}from"fs";import{resolve as gs}from"path";lt();function hs(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=Np.replace(/__AGENT_ID__/g,N(e));return M({title:`AgentX \xB7 ${N(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${N(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Dp,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>${Hp}</script>`})}var Np=`
8586
+ `)}let c=Date.now();for(;!s&&Date.now()-c<Np;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function gs(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Dp(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Aa(process.cwd(),".agentx/task-history",t,n);if(!Ca(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Aa(process.cwd(),".agentx/task-history",t,o);return Ca(s)?is(s,e,a):null}return is(r,e,a)}function is(t,e,a){let n=null,r=1/0;for(let o of Ap(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(Cp(Tp(t,o),"utf-8"))}catch{continue}let i=s.startedAt,l;if(typeof i=="number")l=i;else if(typeof i=="string"){let p=Date.parse(i);if(!Number.isFinite(p))continue;l=p}else continue;let c=Math.abs(l-e);c<r&&c<=a&&(n=s,r=c)}return n}async function xs(t,e,a){let n=a.match(/^\/api\/admin\/activity-graph\/dispatch\/([^/?]+)(?:\?.*)?$/);if(!n)return!1;let r=decodeURIComponent(n[1]),o=r.indexOf("|");if(o<0)return he(e,400,{error:"invalid dispatch id"}),!0;let s=r.slice(0,o),i=r.slice(o+1),l=Ia();if(!l)return he(e,503,{error:"ledger not available"}),!0;try{let c=l.db.prepare("SELECT id, ts, source, project, subject, intent, raw_json FROM intent_events WHERE id = ?").get(s);if(!c)return he(e,404,{error:"event not found"}),!0;let p=l.db.prepare("SELECT decided_at, decided_by, agent_id, outcome, reason FROM intent_decisions WHERE event_id = ? AND decided_by = ?").get(s,i);if(!p)return he(e,404,{error:"decision not found"}),!0;let u=l.db.prepare("SELECT resolved_at, status, duration_ms, result_summary FROM intent_resolutions WHERE decision_event_id = ? AND decision_decided_by = ?").get(s,i),f=null;try{f=JSON.parse(c.raw_json)}catch{}let h=ds(c.source,f),k=f&&typeof f=="object"&&(f.text||f.message?.text||f.message?.caption||f.object_attributes?.note||f.object_attributes?.description||f.comment?.body||f.issue?.body||(typeof f.message=="string"?f.message:null)||(typeof f.prompt=="string"?f.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let w=Dp(p.agent_id,p.decided_at);if(w){typeof w.responseText=="string"&&(_=w.responseText);let T=w.transcript;Array.isArray(T)&&(S=T.length)}}let g=ge?.business?.projects??[],d=ge?.business?.contactMap??[],m=sa(ge?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=cs(c.source,f,d);if(v)x={client:v.client,project:v.project||`${v.client}/_chat`,via:`contactMap (channel=${v.channel??"*"}${v.username?` username=${v.username}`:""}${v.chatId?` chatId=${v.chatId}`:""})`};else if(c.project||Ht(f,c.subject,h)){let w=c.project||Ht(f,c.subject,h);x={client:ut(w,g),project:w,via:c.project?`project namespace prefix (${w})`:`forge path in chat id / message (${w})`}}else if(p.agent_id){let w=m.get(p.agent_id);w&&(x={client:w,project:`${w}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${w})`})}he(e,200,{id:r,eventId:s,source:c.source,subject:c.subject,intent:c.intent,project:c.project,decidedBy:p.decided_by,agentId:p.agent_id,outcome:p.outcome,reason:p.reason,startedAt:p.decided_at,resolvedAt:u?.resolved_at??null,durationMs:u?.duration_ms??null,input:k,response:_,transcriptLen:S,resolutionStatus:u?.status??null,resultSummary:u?.result_summary??null,attribution:x})}catch(c){he(e,500,{error:c?.message??String(c)})}finally{l.close()}return!0}import{existsSync as qp,readFileSync as Fp}from"fs";import{resolve as bs}from"path";lt();function vs(t){let e=t.agentId,a=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",n=`<script>window.AGENT_ID = ${JSON.stringify(e)};</script>`,r=Hp.replace(/__AGENT_ID__/g,N(e));return M({title:`AgentX \xB7 ${N(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${N(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Bp,headExtras:'<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">',scripts:`${n}${a}<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script><script>${zp}</script>`})}var Hp=`
8553
8587
  <!-- Breadcrumb -->
8554
8588
  <div class="ax-crumb">
8555
8589
  <a href="/admin">Settings</a>
@@ -9138,7 +9172,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
9138
9172
  </div>
9139
9173
  </div>
9140
9174
  </div>
9141
- `,Dp=`
9175
+ `,Bp=`
9142
9176
  /* Agent-specific layout + legacy styles for bits the migration left in
9143
9177
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
9144
9178
  * primitives live in components.css.ts. */
@@ -9257,7 +9291,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
9257
9291
 
9258
9292
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
9259
9293
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
9260
- `,Hp=`
9294
+ `,zp=`
9261
9295
  const $ = (id) => document.getElementById(id);
9262
9296
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
9263
9297
 
@@ -10113,15 +10147,15 @@ document.addEventListener('keydown', (e) => {
10113
10147
  /* ===== Boot ===== */
10114
10148
  initOptsToggles();
10115
10149
  loadAgent();
10116
- `;function xs(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(hs({agentId:a,peers:n,localToken:r}))}async function vs(t,e,a){try{let n=t.method==="GET"?void 0:await cu(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){qt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Ye(i),"PATCH ":()=>qp(i,n),"PATCH capability":()=>Wp(i,n),"POST mcp":()=>Fp(i,n),"DELETE mcp":()=>Up(i,n),"GET identity":()=>Gp(i),"GET identity/file":()=>Xp(i,String(o.path||"")),"PUT identity/file":()=>Kp(i,n),"GET skills":()=>Jp(i),"POST skills":()=>Vp(i,n),"DELETE skills":()=>Yp(i,n),"GET skills/tree":()=>Qp(i,String(o.slug||"")),"GET skills/file":()=>Zp(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>eu(i,n),"GET skills/deps":()=>tu(i,String(o.slug||"")),"POST skills/install":()=>au(i,n,t),"POST skills/deps":()=>nu(i,n,t),"GET channels":()=>ru(i),"GET activity":()=>ou(i,t),"GET handovers":()=>su(i),"POST handovers":()=>iu(i,n),"DELETE handovers":()=>lu(n)}[c];if(!u){qt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();qt(e,200,f)}catch(n){qt(e,400,{error:n?.message||"agent op failed"})}}function bs(){let t=gs(process.cwd(),"agentx.json");return Bp(t)?JSON.parse(zp(t,"utf-8")):null}function V(t){let e=bs();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function Ye(t){let{def:e,cfg:a}=V(t),n=e.workspace?De(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function qp(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function Fp(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=A(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:Ye(t)}}function Up(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:Ye(t)}}function Wp(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function Gp(t){let{def:e}=V(t);return De(e.workspace)}function Xp(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return wt(a.workspace,e)}function Kp(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return kt(n.workspace,a,String(e?.content??""))}function Jp(t){let{def:e}=V(t),a=De(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Vp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return _t(n.workspace,a,{title:e?.title,content:e?.content})}function Yp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return St(n.workspace,a)}function Qp(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Zn(a.workspace,e),r=Et(a.workspace,e);return{slug:e,tree:n,deps:r}}function Zp(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return er(n.workspace,e,a)}function eu(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return tr(r.workspace,a,n,String(e?.content??""))}function tu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Et(a.workspace,e)}async function au(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=ys(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
10117
- `);return ws(a,r,s,`install-${n}:${Date.now()}`)}async function nu(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=ys(e?.worker),{def:o}=V(t),s=Et(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=gs(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(`
10118
- `);return ws(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function ys(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function ws(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function ru(t){let e=bs(),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 ou(t,e){try{let n=(X().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function Ra(){return new xn}function su(t){let e=Ra(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function iu(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=Ra().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function lu(t){let e=String(t?.channel||"").trim(),a=String(t?.chatId||"").trim();if(!e||!a)throw new Error("channel and chatId required");let n=t?.accountId?String(t.accountId):void 0;return{summary:Ra().remove(e,a,n)?"Released":"No active handover for that chat"}}function qt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function cu(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var Le={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var ks=[{term:"Agent",definition:'An AI worker with its own role, instructions, and channels it responds on. Think of each agent as a job title \u2014 "support", "devops", "sales".'},{term:"Trigger word",alias:"mention",definition:"A word that activates an agent. When the trigger appears in a message (e.g. @support), AgentX routes the message to that agent."},{term:"Channel",definition:"Where messages come from \u2014 Telegram, WhatsApp, Discord, GitLab comments, a scheduled cron, or an HTTP webhook."},{term:"AI engine",alias:"tier",definition:"Which backend answers: Claude Code, Codex CLI, Anthropic Agent SDK, or AgentX's provider-agnostic orchestrator."},{term:"Agent folder",alias:"workspace",definition:"The directory on disk where the agent lives. It holds the agent's personality (CLAUDE.md), its knowledge (wiki), and the tools it can use."},{term:"Team network",alias:"mesh",definition:'When you run AgentX on more than one machine, the machines find each other and share work. Each machine is a "node"; together they are your team network.'},{term:"Status check-in",alias:"heartbeat",definition:"A lightweight ping between machines so each one knows the others are alive and responsive."},{term:"Board",definition:"A Kanban view of tasks (issues, tickets) pulled from GitLab. Drag cards between columns to move work forward \u2014 the labels update upstream automatically."},{term:"Task",definition:"A single conversation or job an agent handles, from trigger message to final reply. Every task is logged and replayable."},{term:"Schedule",alias:"cron",definition:'A recurring job \u2014 e.g. "every Monday at 9am" \u2014 that nudges an agent without a human trigger.'},{term:"Status label",alias:"scopedLabel",definition:"A GitLab label that moves an issue between Kanban columns (e.g. Status::Doing). Labels are mutually exclusive by prefix."}];function $a(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10150
+ `;function ys(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(vs({agentId:a,peers:n,localToken:r}))}async function ws(t,e,a){try{let n=t.method==="GET"?void 0:await pu(t),r=new URL(t.url||"/","http://localhost"),o=Object.fromEntries(r.searchParams),s=a.match(/^\/api\/admin\/agent\/([a-z0-9][a-z0-9_-]*)(?:\/(.+))?$/);if(!s){qt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Ye(i),"PATCH ":()=>Up(i,n),"PATCH capability":()=>Xp(i,n),"POST mcp":()=>Wp(i,n),"DELETE mcp":()=>Gp(i,n),"GET identity":()=>Kp(i),"GET identity/file":()=>Jp(i,String(o.path||"")),"PUT identity/file":()=>Vp(i,n),"GET skills":()=>Yp(i),"POST skills":()=>Qp(i,n),"DELETE skills":()=>Zp(i,n),"GET skills/tree":()=>eu(i,String(o.slug||"")),"GET skills/file":()=>tu(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>au(i,n),"GET skills/deps":()=>nu(i,String(o.slug||"")),"POST skills/install":()=>ru(i,n,t),"POST skills/deps":()=>ou(i,n,t),"GET channels":()=>su(i),"GET activity":()=>iu(i,t),"GET handovers":()=>lu(i),"POST handovers":()=>cu(i,n),"DELETE handovers":()=>du(n)}[c];if(!u){qt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let f=await u();qt(e,200,f)}catch(n){qt(e,400,{error:n?.message||"agent op failed"})}}function ks(){let t=bs(process.cwd(),"agentx.json");return qp(t)?JSON.parse(Fp(t,"utf-8")):null}function V(t){let e=ks();if(!e)throw new Error("agentx.json not found");let a=e.agents?.[t];if(!a)throw new Error(`Agent "${t}" not found`);return{def:a,cfg:e}}function Ye(t){let{def:e,cfg:a}=V(t),n=e.workspace?De(e.workspace):null;return{id:t,name:e.name||t,tier:e.tier,model:e.model,workspace:e.workspace,systemPrompt:e.systemPrompt||"",mentions:e.mentions||[],access:e.access||"private",maxConcurrent:e.maxConcurrent??1,maxExecutionMinutes:e.maxExecutionMinutes??20,permissionMode:e.permissionMode||"default",intents:Array.isArray(e.intents)?e.intents:[],maxDelegationDepth:e.maxDelegationDepth??5,contextReferences:!!e.contextReferences,contextStrategy:e.contextStrategy||"",mcp:e.mcp&&typeof e.mcp=="object"?e.mcp:{},overview:n,defaultWorker:a.node?.defaultAgent,draftAgent:a.dashboard?.draftAgent}}function Up(t,e){let a={};for(let r of["name","tier","model","systemPrompt","mentions","access","maxConcurrent","maxExecutionMinutes","permissionMode"])e?.[r]!==void 0&&(a[r]=e[r]);let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);return r.agents[t]={...r.agents[t],...a},`agent "${t}" updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function Wp(t,e){let a=String(e?.name||"").trim(),n=String(e?.command||"").trim();if(!a)throw new Error("name required");if(!/^[a-zA-Z0-9_-]+$/.test(a))throw new Error("name must be identifier-safe (alnum, _, -)");if(!n)throw new Error("command required");let r=Array.isArray(e?.args)?e.args.map(i=>String(i)):[],o;if(e?.env&&typeof e.env=="object"){o={};for(let[i,l]of Object.entries(e.env))typeof l=="string"&&(o[i]=l);Object.keys(o).length===0&&(o=void 0)}let{summary:s}=A(i=>{if(!i.agents?.[t])throw new Error(`Agent "${t}" not found`);return i.agents[t].mcp=i.agents[t].mcp||{},i.agents[t].mcp[a]={command:n,args:r,...o?{env:o}:{}},`agent "${t}" mcp.${a} upserted`});return{summary:s,agent:Ye(t)}}function Gp(t,e){let a=String(e?.name||"").trim();if(!a)throw new Error("name required");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);if(!r.agents[t].mcp||!(a in r.agents[t].mcp))throw new Error(`no mcp.${a} on "${t}"`);return delete r.agents[t].mcp[a],Object.keys(r.agents[t].mcp).length===0&&delete r.agents[t].mcp,`agent "${t}" mcp.${a} removed`});return{summary:n,agent:Ye(t)}}function Xp(t,e){let a={};if(Array.isArray(e?.intents)&&(a.intents=e.intents.map(r=>String(r)).filter(Boolean)),e?.maxDelegationDepth!==void 0){let r=Number(e.maxDelegationDepth);if(!Number.isFinite(r)||r<0||r>50)throw new Error("maxDelegationDepth must be 0..50");a.maxDelegationDepth=r}if(e?.contextReferences!==void 0&&(a.contextReferences=!!e.contextReferences),e?.contextStrategy!==void 0){if(e.contextStrategy&&!["layered","planner"].includes(e.contextStrategy))throw new Error("contextStrategy must be layered|planner|empty");e.contextStrategy?a.contextStrategy=e.contextStrategy:a.contextStrategy=void 0}if(e?.maxExecutionMinutes!==void 0){let r=Number(e.maxExecutionMinutes);if(!Number.isFinite(r)||r<1||r>240)throw new Error("maxExecutionMinutes must be 1..240");a.maxExecutionMinutes=r}if(Object.keys(a).length===0)throw new Error("nothing to update");let{summary:n}=A(r=>{if(!r.agents?.[t])throw new Error(`Agent "${t}" not found`);let o={...r.agents[t]};for(let[s,i]of Object.entries(a))i===void 0?delete o[s]:o[s]=i;return r.agents[t]=o,`agent "${t}" capability updated (${Object.keys(a).join(", ")})`});return{summary:n,agent:Ye(t)}}function Kp(t){let{def:e}=V(t);return De(e.workspace)}function Jp(t,e){if(!e)throw new Error("path query param required");let{def:a}=V(t);return wt(a.workspace,e)}function Vp(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=V(t);return kt(n.workspace,a,String(e?.content??""))}function Yp(t){let{def:e}=V(t),a=De(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Qp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return _t(n.workspace,a,{title:e?.title,content:e?.content})}function Zp(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=V(t);return St(n.workspace,a)}function eu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t),n=Zn(a.workspace,e),r=Et(a.workspace,e);return{slug:e,tree:n,deps:r}}function tu(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=V(t);return er(n.workspace,e,a)}function au(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=V(t);return tr(r.workspace,a,n,String(e?.content??""))}function nu(t,e){if(!e)throw new Error("slug query param required");let{def:a}=V(t);return Et(a.workspace,e)}async function ru(t,e,a){let n=String(e?.package||"").trim();if(!n||!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)?$/.test(n))throw new Error("package must be in 'owner/repo' or 'owner/repo/skill' form");let r=_s(e?.worker),{def:o}=V(t),s=[`Install the skills.sh package "${n}" into agent "${t}".`,`Workspace: ${o.workspace}`,`Run: cd ${o.workspace} && npx -y skills add ${n}`,`If that fails, fall back to: agentx skill install ${n}`,`Skills should land under ${o.workspace}/.claude/skills/. Report what was installed and any errors.`].join(`
10151
+ `);return Ss(a,r,s,`install-${n}:${Date.now()}`)}async function ou(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=_s(e?.worker),{def:o}=V(t),s=Et(o.workspace,n);if(!s.manager)throw new Error(`No dependency manifest detected in .claude/skills/${n}. Expected one of: package.json, requirements.txt, Gemfile.`);let i=bs(o.workspace,".claude","skills",n),l=[`Install dependencies for skill "${n}" in agent "${t}".`,`cd to: ${i}`,`Detected manifest: ${s.file}`,`Run: ${s.command}`,"Stream the install output. On success, summarise the packages installed.","On failure, report the exit code and the last 20 lines of output."].join(`
10152
+ `);return Ss(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function _s(t){if(t&&typeof t=="string")return t;let e=X();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Ss(t,e,a,n){let r=X(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function su(t){let e=ks(),a=[],n=e?.channels?.telegram?.accounts||{};for(let[o,s]of Object.entries(n))s?.agentBinding===t&&a.push({channel:"telegram",account:o,detail:s?.botUsername||o});e?.channels?.slack?.agentBinding===t&&a.push({channel:"slack",detail:"bound"}),e?.channels?.discord?.agentBinding===t&&a.push({channel:"discord",detail:"bound"});let r=e?.channels?.gitlab?.agentMappings||[];for(let o of r)o?.agentId===t&&a.push({channel:"gitlab",detail:(o?.gitlabUsernames||[]).join(", ")||"mapped"});return{bindings:a}}async function iu(t,e){try{let n=(X().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function Ra(){return new xn}function lu(t){let e=Ra(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function cu(t,e){let a=String(e?.channel||"").trim(),n=String(e?.chatId||"").trim(),r=String(e?.toAgent||"").trim();if(!a||!n||!r)throw new Error("channel, chatId, toAgent required");let o=String(e?.fromAgent||t||"").trim()||t,s=e?.accountId?String(e.accountId):void 0,i=e?.summary?String(e.summary):void 0,l=e?.expiresAt?String(e.expiresAt):void 0,c=Ra().set({channel:a,chatId:n,accountId:s,fromAgent:o,toAgent:r,summary:i,expiresAt:l,createdBy:"admin-ui"});return{summary:`Handed off ${a}:${n} from ${o} to ${r}`,record:c}}function du(t){let e=String(t?.channel||"").trim(),a=String(t?.chatId||"").trim();if(!e||!a)throw new Error("channel and chatId required");let n=t?.accountId?String(t.accountId):void 0;return{summary:Ra().remove(e,a,n)?"Released":"No active handover for that chat"}}function qt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function pu(t){return new Promise((e,a)=>{let n="";t.on("data",r=>{n+=r}),t.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(r){a(r)}}),t.on("error",a)})}var Le={brand:"AgentX",subtitle:"Team AI ops",nodes:"machines",agentsCount:"agents",activeNow:"handling now",errorsCount:"failed",stats:{active:"Handling",total:"Today",errors:"Failed"},idle:"idle",runningNoPreview:"working \xB7 preparing reply",recentActivities:"Recent activities \u2192",noAgentsOnNode:"No agents set up on this machine.",unreachable:"This machine is unreachable.",neverRan:"not used yet",tierLabels:{"claude-code":"Claude Code","codex-cli":"Codex CLI",opencode:"OpenCode",sdk:"SDK",orchestrator:"Orchestrator"},taskModalTitle:"Task activity",taskModalConnecting:"connecting\u2026",taskModalLive:"live",taskModalFinished:"finished",taskModalArchived:"archived",taskModalLoadFailed:"couldn't load",taskModalFinalResponse:"Final reply",historyPanelTitle:"Recent activities",historyEmpty:"No activity yet.",historyLoading:"loading\u2026"};var Es=[{term:"Agent",definition:'An AI worker with its own role, instructions, and channels it responds on. Think of each agent as a job title \u2014 "support", "devops", "sales".'},{term:"Trigger word",alias:"mention",definition:"A word that activates an agent. When the trigger appears in a message (e.g. @support), AgentX routes the message to that agent."},{term:"Channel",definition:"Where messages come from \u2014 Telegram, WhatsApp, Discord, GitLab comments, a scheduled cron, or an HTTP webhook."},{term:"AI engine",alias:"tier",definition:"Which backend answers: Claude Code, Codex CLI, Anthropic Agent SDK, or AgentX's provider-agnostic orchestrator."},{term:"Agent folder",alias:"workspace",definition:"The directory on disk where the agent lives. It holds the agent's personality (CLAUDE.md), its knowledge (wiki), and the tools it can use."},{term:"Team network",alias:"mesh",definition:'When you run AgentX on more than one machine, the machines find each other and share work. Each machine is a "node"; together they are your team network.'},{term:"Status check-in",alias:"heartbeat",definition:"A lightweight ping between machines so each one knows the others are alive and responsive."},{term:"Board",definition:"A Kanban view of tasks (issues, tickets) pulled from GitLab. Drag cards between columns to move work forward \u2014 the labels update upstream automatically."},{term:"Task",definition:"A single conversation or job an agent handles, from trigger message to final reply. Every task is logged and replayable."},{term:"Schedule",alias:"cron",definition:'A recurring job \u2014 e.g. "every Monday at 9am" \u2014 that nudges an agent without a human trigger.'},{term:"Status label",alias:"scopedLabel",definition:"A GitLab label that moves an issue between Kanban columns (e.g. Status::Doing). Labels are mutually exclusive by prefix."}];function $a(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Le)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
10119
10153
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
10120
10154
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
10121
10155
  <section id="statstrip" class="ax-statstrip"></section>
10122
10156
  <main id="grid" class="ax-live__body"></main>
10123
10157
  </div>
10124
- `;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:du,scripts:e+`<script>${pu}</script>`,headExtras:`<script>
10158
+ `;return M({title:`${Le.brand} \xB7 ${Le.subtitle}`,activeTab:"live",subtitle:Le.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:uu,scripts:e+`<script>${mu}</script>`,headExtras:`<script>
10125
10159
  // rightExtras for the topbar are injected at runtime \u2014 they reference
10126
10160
  // IDs (#ts, #conn-dot) that the script below addresses directly.
10127
10161
  document.addEventListener('DOMContentLoaded', () => {
@@ -10132,7 +10166,7 @@ loadAgent();
10132
10166
  extras.innerHTML = ${JSON.stringify(a)};
10133
10167
  right.insertBefore(extras, right.firstChild);
10134
10168
  });
10135
- </script>`})}var du=`
10169
+ </script>`})}var uu=`
10136
10170
  /* --- Page frame --- */
10137
10171
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
10138
10172
 
@@ -10339,7 +10373,7 @@ loadAgent();
10339
10373
  border-top-color: var(--ax-accent); border-radius: 50%;
10340
10374
  animation: ax-spin 800ms linear infinite; display: inline-block;
10341
10375
  }
10342
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,pu=`
10376
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,mu=`
10343
10377
  'use strict';
10344
10378
 
10345
10379
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -10910,7 +10944,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10910
10944
  });
10911
10945
  }
10912
10946
 
10913
- `;var _s=`
10947
+ `;var Ts=`
10914
10948
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10915
10949
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10916
10950
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -11084,7 +11118,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
11084
11118
  .mx-summary{max-width:56vw}
11085
11119
  }
11086
11120
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
11087
- `;var Ss=`<script>
11121
+ `;var As=`<script>
11088
11122
  window.MX=(function(){
11089
11123
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
11090
11124
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -11193,7 +11227,7 @@ window.MX=(function(){
11193
11227
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
11194
11228
  setHealth:setHealth,get:get};
11195
11229
  })();
11196
- </script>`;var Es=`<script>
11230
+ </script>`;var Cs=`<script>
11197
11231
  window.MXD=(function(){
11198
11232
  function el(id){return document.getElementById(id)}
11199
11233
  function tz(){return -new Date().getTimezoneOffset()}
@@ -11407,7 +11441,7 @@ window.MXD=(function(){
11407
11441
 
11408
11442
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
11409
11443
  })();
11410
- </script>`;var Ts=`<script>
11444
+ </script>`;var Is=`<script>
11411
11445
  (function(){
11412
11446
  var LANES=[
11413
11447
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -11723,7 +11757,7 @@ window.MXD=(function(){
11723
11757
  window.addEventListener('scroll',hideTip,{passive:true});
11724
11758
  load();
11725
11759
  })();
11726
- </script>`;var As=`<script>
11760
+ </script>`;var Ms=`<script>
11727
11761
  (function(){
11728
11762
  var showAll=document.getElementById('mx-show-all'),expanded=false;
11729
11763
  var esc=MX.esc;
@@ -11901,7 +11935,7 @@ window.MXD=(function(){
11901
11935
  }
11902
11936
  load();setInterval(load,5000);
11903
11937
  })();
11904
- </script>`;var Cs=`
11938
+ </script>`;var Ls=`
11905
11939
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11906
11940
  .mx-rt-wrap{border:var(--ax-border-w) solid var(--ax-border);border-radius:var(--ax-radius-lg);background:var(--ax-surface);overflow-x:auto}
11907
11941
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11942,7 +11976,7 @@ window.MXD=(function(){
11942
11976
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11943
11977
  .mx-rt-name{max-width:100%}
11944
11978
  }
11945
- `,Is=`<script>
11979
+ `,Rs=`<script>
11946
11980
  (function(){
11947
11981
  var root=document.getElementById('mx-routines');
11948
11982
  var bar=document.getElementById('mx-rt-filter');
@@ -12069,7 +12103,7 @@ window.MXD=(function(){
12069
12103
  syncBar();
12070
12104
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
12071
12105
  })();
12072
- </script>`;var Ms=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Ls=`<script>
12106
+ </script>`;var $s=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],Ps=`<script>
12073
12107
  (function(){
12074
12108
  var root=document.getElementById('mx-feed');
12075
12109
  if(!root)return;
@@ -12144,12 +12178,12 @@ window.MXD=(function(){
12144
12178
  }
12145
12179
  load();setInterval(load,5000);
12146
12180
  })();
12147
- </script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var uu=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],mu=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],fu=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function Rs(t){let e=ve({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+At([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
12181
+ </script>`;var ae={activity:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h3l2-6 4 12 2-6h5"/></svg>',breakage:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6l-3 3 3 3v6"/><path d="M5 5l14 14"/></svg>',effort:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V4M4 20h16"/><circle cx="9" cy="15" r="2"/><circle cx="15" cy="8" r="2"/></svg>',lifetime:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M7 8v8M13 8v8M19 8v8"/></svg>',cuts:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><path d="M8 8l12 10M8 16L20 6"/></svg>',schedules:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',routines:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h11M4 12h7M4 17h9"/><path d="M17 5l3 3-3 3M16 14l4 4M20 14l-4 4"/></svg>',nodes:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M8 6h8M7 8l4 8M17 8l-4 8"/></svg>',feed:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1.5"/></svg>',agents:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4M8 16h.01M16 16h.01"/></svg>'};function ne(t,e,a,n,r=""){return K({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var fu=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],hu=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],gu=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function js(t){let e=ve({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+At([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
12148
12182
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
12149
- ${mu.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("")}
12183
+ ${hu.map((i,l)=>`<button class="mx-tab" type="button" role="tab" id="mx-tab-${i.id}" aria-controls="mx-view-${i.id}" aria-selected="${l===0}" data-view="${i.id}">${i.label}</button>`).join("")}
12150
12184
  </div>
12151
12185
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
12152
- ${fu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12186
+ ${gu.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
12153
12187
  </div>
12154
12188
  </div>
12155
12189
  <p id="mx-analytics-updated" class="mx-updated" aria-live="polite">Reading node histories...</p>`,n=`<div class="mx-view" id="mx-view-activity" role="tabpanel" aria-labelledby="mx-tab-activity">
@@ -12202,7 +12236,7 @@ window.MXD=(function(){
12202
12236
  <section class="mx-section" aria-labelledby="mx-routines-title">
12203
12237
  ${ne(ae.routines,"Routines","Everything that runs on its own: schedules and cron- or event-triggered workflows, per node. Flags mark routines that keep failing, went quiet, never ran, or sat disabled.","mx-routines-title",'<span class="ax-tab-count" id="mx-rt-count">0 routines</span>')}
12204
12238
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
12205
- ${uu.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12239
+ ${fu.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12206
12240
  </div>
12207
12241
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
12208
12242
  </section>
@@ -12210,7 +12244,7 @@ window.MXD=(function(){
12210
12244
  <section class="mx-section" aria-labelledby="mx-feed-title">
12211
12245
  ${ne(ae.feed,"Mesh feed","The newest events from this machine and every machine it follows. Unreachable machines and announcements show here too. Select an event for its details.","mx-feed-title",'<div class="mx-section-actions"><span class="ax-tab-count" id="mx-feed-count">0 events</span><button class="ax-btn ax-btn--ghost" id="mx-feed-more" type="button" hidden>Show all</button></div>')}
12212
12246
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
12213
- ${Ms.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12247
+ ${$s.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
12214
12248
  </div>
12215
12249
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
12216
12250
  </section>
@@ -12243,7 +12277,7 @@ window.MXD=(function(){
12243
12277
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
12244
12278
  </header>
12245
12279
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
12246
- </aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:_s+Cs,scripts:Ss+hu+Es+Ts+Is+As+Ls})}var hu=`<script>
12280
+ </aside>`;return M({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Ts+Ls,scripts:As+xu+Cs+Is+Rs+Ms+Ps})}var xu=`<script>
12247
12281
  (function(){
12248
12282
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
12249
12283
  var range=document.getElementById('mx-range');
@@ -12271,10 +12305,10 @@ window.MXD=(function(){
12271
12305
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
12272
12306
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
12273
12307
  })();
12274
- </script>`;function $s(t){let e=ve({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
12308
+ </script>`;function Os(t){let e=ve({kicker:"Operations",title:"Guest meshes",lead:"Other organisations let into part of this mesh. Each grant names one agent of yours, what it may touch for them, how much freedom it has and until when. Nothing is shared until you open it."})+`
12275
12309
  <div id="gm-msg" class="gm-msg" role="status" aria-live="polite"></div>
12276
12310
  <ol id="gm-list" class="gm-list" aria-label="Grants"><li class="gm-empty">Loading\u2026</li></ol>
12277
- <p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent &lt;id&gt;</code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:gu,scripts:`<script>${xu}</script>`})}var gu=`
12311
+ <p class="gm-note">Open a grant from a terminal: <code>agentx mesh guests invite --name "\u2026" --guest "\u2026" --agent &lt;id&gt;</code>. The guest joins with the code; its join arrives as a card in Approvals.</p>`;return M({title:"AgentX \xB7 Guest meshes",activeTab:"mesh",subtitle:"Guest meshes",peers:t.peers,body:e,css:vu,scripts:`<script>${bu}</script>`})}var vu=`
12278
12312
  .gm-list { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
12279
12313
  .gm-empty { color: var(--ax-text-2); }
12280
12314
  .gm-item { padding: 14px 16px; border: var(--ax-border-w) solid var(--ax-border); border-radius: var(--ax-radius); background: var(--ax-surface); }
@@ -12292,7 +12326,7 @@ window.MXD=(function(){
12292
12326
  .gm-msg { min-height: 1.4em; margin: 8px 0 0; }
12293
12327
  .gm-msg.is-bad { color: var(--ax-red-ink); }
12294
12328
  .gm-note { color: var(--ax-text-2); font-size: var(--ax-fs-sm); }
12295
- `,xu=`
12329
+ `,bu=`
12296
12330
  (function () {
12297
12331
  var list = document.getElementById('gm-list');
12298
12332
  var msg = document.getElementById('gm-msg');
@@ -12339,7 +12373,7 @@ window.MXD=(function(){
12339
12373
  load();
12340
12374
  setInterval(load, 30000);
12341
12375
  })();
12342
- `;async function Ps(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 vu(s,e.days)}function vu(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,u=0,f=0,h=0,k=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])m[x][0]+=d[x]?.[0]||0,m[x][1]+=d[x]?.[1]||0;n.set(d.day,m)}for(let d of g.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of g.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let x of d.agents)m.agents.includes(x)||m.agents.push(x);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,f=Math.max(f,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:h,tracesWithSteps:k}}}async function js(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 Os(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 bu(s,e.day)}function bu(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 Ns(t={}){let e=`
12376
+ `;async function Ns(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?days=${e.days}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/mesh"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return yu(s,e.days)}function yu(t,e){let a={runs:0,errors:0,hours:0,agents:0,threads:0},n=new Map,r=new Map,o=new Map,s=new Map,i=[],l=[],c=0,p=0,u=0,f=0,h=0,k=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let m=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])m[x][0]+=d[x]?.[0]||0,m[x][1]+=d[x]?.[1]||0;n.set(d.day,m)}for(let d of g.origins){let m=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};m.runs+=d.runs,m.errors+=d.errors,m.hours+=d.hours,r.set(d.channel,m)}for(let d of g.causes){let m=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};m.count+=d.count;for(let x of d.agents)m.agents.includes(x)||m.agents.push(x);m.example||(m.example=d.example),o.set(d.cause,m)}for(let d of g.rotations.byReason)s.set(d.reason,(s.get(d.reason)||0)+d.count);c+=g.rotations.total,p+=g.rotations.tokenSum||0,u+=g.rotations.tokenSamples||0,f=Math.max(f,g.rotations.maxTokens),h+=g.retention.traces,k+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:f},retention:{traces:h,tracesWithSteps:k}}}async function Ds(t,e,a,n){let r=a.replace(/\/+$/,""),o=e.find(i=>i.url.replace(/\/+$/,"")===r);if(!o){t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"node not in dashboard allowlist",target:r}));return}let s={Accept:"application/json"};o.token&&(s.Authorization=`Bearer ${o.token}`);try{let i=await fetch(r+n,{headers:s}),l=await i.text();t.writeHead(i.status,{"Content-Type":"application/json; charset=utf-8"}),t.end(l)}catch(i){t.writeHead(502,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:i?.message||"upstream fetch failed"}))}}async function Hs(t,e,a=6e3){let n=new AbortController,r=setTimeout(()=>n.abort(),a),o=`?day=${encodeURIComponent(e.day)}&tzOffset=${e.tzOffsetMinutes}&limit=${e.limit}`,s;try{s=await Promise.all(t.map(async i=>{let l={Accept:"application/json"};i.token&&(l.Authorization=`Bearer ${i.token}`);try{let c=await fetch(i.url+"/analytics/day"+o,{headers:l,signal:n.signal});return c.ok?{node:i,data:await c.json()}:{node:i,error:`HTTP ${c.status}`}}catch(c){return{node:i,error:c?.name==="AbortError"?"timeout":c?.message||"unreachable"}}}))}finally{clearTimeout(r)}return wu(s,e.day)}function wu(t,e){let a={runs:0,errors:0,ms:0,inputTokens:0,outputTokens:0},n=new Map,r=new Map,o=[];for(let{node:s,data:i}of t)if(i){a.runs+=i.totals.runs,a.errors+=i.totals.errors,a.ms+=i.totals.ms,a.inputTokens+=i.totals.inputTokens,a.outputTokens+=i.totals.outputTokens;for(let l of i.origins){let c=n.get(l.channel)||{channel:l.channel,runs:0,errors:0,ms:0};c.runs+=l.runs,c.errors+=l.errors,c.ms+=l.ms,n.set(l.channel,c)}for(let l of i.causes)r.set(l.cause,(r.get(l.cause)||0)+l.count);for(let l of i.conversations)o.push({...l,node:s.name,nodeUrl:s.url})}return{day:e,nodes:t.map(s=>({name:s.node.name,url:s.node.url,ok:!!s.data,error:s.error,runs:s.data?.totals.runs||0})),totals:a,origins:[...n.values()].sort((s,i)=>i.runs-s.runs),causes:[...r.entries()].map(([s,i])=>({cause:s,count:i})).sort((s,i)=>i.count-s.count),conversations:o.sort((s,i)=>i.ms-s.ms||i.turns-s.turns)}}function Bs(t={}){let e=`
12343
12377
  <select id="boardPicker" title="Switch board"></select>
12344
12378
  <div class="search">
12345
12379
  <span class="icon">\u2315</span>
@@ -12440,7 +12474,7 @@ window.MXD=(function(){
12440
12474
  </footer>
12441
12475
  </div>
12442
12476
  </div>
12443
- <script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:yu,scripts:`<script>${wu}</script>`,headExtras:`<script>
12477
+ <script src="/sortable.min.js"></script>`;return M({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:ku,scripts:`<script>${_u}</script>`,headExtras:`<script>
12444
12478
  // The boards page has its own connection dot + wants body height:100%
12445
12479
  // for the full-viewport kanban layout. Inject the dot into the topbar
12446
12480
  // and override body height at runtime so the shared shell doesn't
@@ -12456,7 +12490,7 @@ window.MXD=(function(){
12456
12490
  right.insertBefore(dot, right.firstChild);
12457
12491
  }
12458
12492
  });
12459
- </script>`})}var yu=`
12493
+ </script>`})}var ku=`
12460
12494
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
12461
12495
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
12462
12496
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -12709,7 +12743,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
12709
12743
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
12710
12744
  .draft-box .draft-row .hint.err { color: var(--red); }
12711
12745
  .draft-box .draft-row .hint.ok { color: var(--green); }
12712
- `,wu=`
12746
+ `,_u=`
12713
12747
  'use strict';
12714
12748
  const state = {
12715
12749
  boards: [], current: null, items: {},
@@ -13762,9 +13796,9 @@ function appendEvents(events) {
13762
13796
  }
13763
13797
 
13764
13798
  loadBoards().catch(e => toast('Init failed: ' + e.message));
13765
- `;function Ds(t={}){let a=`<h1>Plain-English glossary</h1>
13799
+ `;function zs(t={}){let a=`<h1>Plain-English glossary</h1>
13766
13800
  <p class="lead">What the terms on the dashboard mean. Schema keys (shown in the pill on the right of each term) are what you'd write in <code>agentx.json</code> \u2014 the dashboard just relabels them for readability.</p>
13767
- ${ks.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ku})}var ku=`
13801
+ ${Es.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${N(n.alias)}</span>`:"";return`<article class="term"><h3>${N(n.term)}${r}</h3><p>${N(n.definition)}</p></article>`}).join("")}`;return M({title:`${Le.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Su})}var Su=`
13768
13802
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
13769
13803
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
13770
13804
  .lead {
@@ -13794,7 +13828,7 @@ article.term .alias {
13794
13828
  }
13795
13829
  article.term p {
13796
13830
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
13797
- }`;function Hs(t={}){let e=`<div class="ax-wf__root">
13831
+ }`;function qs(t={}){let e=`<div class="ax-wf__root">
13798
13832
  <aside class="ax-wf__list">
13799
13833
  <header>
13800
13834
  <h2>Workflows</h2>
@@ -13871,7 +13905,7 @@ article.term p {
13871
13905
  </aside>
13872
13906
  </div>
13873
13907
 
13874
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:_u,scripts:`<script>${z({workflowHealth:Tn})}${Su}</script>`})}var _u=`
13908
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return M({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Eu,scripts:`<script>${z({workflowHealth:Tn})}${Tu}</script>`})}var Eu=`
13875
13909
  .ax-wf__root {
13876
13910
  display: grid;
13877
13911
  grid-template-columns: 340px 1fr;
@@ -14255,7 +14289,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14255
14289
  font-size: 12px; z-index: 50;
14256
14290
  }
14257
14291
  .hint { color: var(--ax-muted); font-size: 11px; }
14258
- `,Su=`
14292
+ `,Tu=`
14259
14293
  (() => {
14260
14294
  const $ = (sel) => document.querySelector(sel)
14261
14295
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -15044,7 +15078,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15044
15078
  setInterval(refresh, 15000)
15045
15079
  })
15046
15080
  })();
15047
- `;function Bs(t={}){let e=`<div class="ax-proc__root">
15081
+ `;function Fs(t={}){let e=`<div class="ax-proc__root">
15048
15082
  <header class="ax-proc__header">
15049
15083
  <h1>Procedures</h1>
15050
15084
  <p class="hint">Reusable building blocks workflows compose. See <a href="/admin/wiki/architecture/three-tier" target="_blank">three-tier model</a> for how this fits with System and Processes.</p>
@@ -15088,7 +15122,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15088
15122
  <p class="hint">AgentX is layered: <strong>System</strong> (agents, channels, mesh) \u2192 <strong>Processes</strong> (workflows that turn intent into work) \u2192 <strong>Procedures</strong> (this page: reusable steps a process composes). Higher tiers depend on lower; never the reverse.</p>
15089
15123
  <p class="hint">Adding a new procedure is a code change (a new <code>action.builtin</code> module under <code>src/actions/builtin/</code> or a new template YAML in <code>src/workflows/templates/</code>) \u2014 not a UI flow. This page is the read-only catalog.</p>
15090
15124
  </section>
15091
- </div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Eu,scripts:`<script>${Tu}</script>`})}var Eu=`
15125
+ </div>`;return M({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Au,scripts:`<script>${Cu}</script>`})}var Au=`
15092
15126
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
15093
15127
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
15094
15128
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -15114,7 +15148,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15114
15148
  .ax-proc__req { display: inline-block; padding: 1px 6px; font-size: 10px; font-family: var(--ax-mono); border: 1px solid color-mix(in oklch, var(--ax-warn, #f59e0b) 40%, var(--ax-border)); border-radius: 3px; color: var(--ax-warn, #f59e0b); }
15115
15149
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
15116
15150
  .ax-proc__link:hover { text-decoration: underline; }
15117
- `,Tu=`
15151
+ `,Cu=`
15118
15152
  (function(){
15119
15153
  function $(sel){ return document.querySelector(sel) }
15120
15154
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -15214,7 +15248,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15214
15248
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
15215
15249
  else bootAll()
15216
15250
  })();
15217
- `;function zs(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
15251
+ `;function Us(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
15218
15252
  data-task-id="${N(t.taskId)}"
15219
15253
  data-agent-id="${N(t.agentId)}"
15220
15254
  data-node-url="${N(t.nodeUrl)}"
@@ -15257,7 +15291,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15257
15291
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
15258
15292
  </div>
15259
15293
  </footer>
15260
- </div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Au,scripts:`<script>${Cu}</script>`})}var Au=`
15294
+ </div>`;return M({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Iu,scripts:`<script>${Mu}</script>`})}var Iu=`
15261
15295
  /* The shell gives <main> no padding, so page content butted straight against
15262
15296
  the sticky topbar. Breathe. */
15263
15297
  .ax-task-page {
@@ -15399,7 +15433,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15399
15433
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
15400
15434
  }
15401
15435
 
15402
- `,Cu=`
15436
+ `,Mu=`
15403
15437
  (function () {
15404
15438
  var root = document.querySelector('.ax-task-page');
15405
15439
  if (!root) return;
@@ -15784,7 +15818,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15784
15818
  });
15785
15819
 
15786
15820
  })();
15787
- `;function qs(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15821
+ `;function Ws(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15788
15822
  data-agent-id="${N(t.agentId)}"
15789
15823
  data-agent-name="${N(e)}"
15790
15824
  data-node-url="${N(t.nodeUrl)}">
@@ -15813,7 +15847,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15813
15847
  <div class="ax-history__list" id="hist-list">
15814
15848
  <div class="ax-history__empty">loading\u2026</div>
15815
15849
  </div>
15816
- </div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Iu,scripts:`<script>${Mu}</script>`})}var Iu=`
15850
+ </div>`;return M({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Lu,scripts:`<script>${Ru}</script>`})}var Lu=`
15817
15851
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
15818
15852
  flush against the sticky topbar. */
15819
15853
  .ax-history {
@@ -15865,7 +15899,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15865
15899
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15866
15900
  }
15867
15901
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15868
- `,Mu=`
15902
+ `,Ru=`
15869
15903
  (function () {
15870
15904
  var root = document.querySelector('.ax-history');
15871
15905
  if (!root) return;
@@ -15965,11 +15999,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15965
15999
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15966
16000
  });
15967
16001
  })();
15968
- `;function Us(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return qe(t,e,l=>Fs(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Ru(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return R(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?qe(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return R(e,200,{ok:!0,emission:c})}):R(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?qe(t,e,l=>{try{let c=a.layouts.save(s,l);return R(e,200,{layout:c})}catch(c){return R(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?qe(t,e,l=>{let c=ra.safeParse(l);if(!c.success)return R(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=oa(c.data).map(u=>({path:"",message:u}));return R(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?R(e,200,{workflow:l}):R(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return qe(t,e,p=>Fs(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),R(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return R(e,404,{error:"unknown workflows endpoint",path:n})}var Lu=["mesh"];function Fs(t,e,a,n){let r=ra.safeParse(a);if(!r.success)return R(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=oa(o);if(s.length>0)return R(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return R(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return R(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,c=e.store.get(n.id);if(c)for(let p of Lu)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);return R(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function Ru(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return R(e,200,{runs:u});let f=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return qe(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?R(e,200,{ok:!0,runId:l,status:p}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return $u(t,e,a,l);let c=a.runs.get(l);return c?R(e,200,{run:c}):R(e,404,{error:"run not found"})}return R(e,404,{error:"unknown runs endpoint"})}function $u(t,e,a,n){let r=a.runs.get(n);if(!r)return R(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
16002
+ `;function Xs(t,e,a){let n=t.url||"";if(!n.startsWith("/api/workflows"))return!1;let r=t.method||"GET";if(n==="/api/workflows"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{workflows:a.store.list()}):!0;if(r==="POST"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let s=new URL(n,"http://_").searchParams,i=s.get("convertFromYaml")==="true"||s.get("convertFromYaml")==="1";return qe(t,e,l=>Gs(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:Pu(t,e,a,n);if(n.startsWith("/api/workflows/signal/")){if(r!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;if(!a.dispatcher)return R(e,501,{error:"dispatcher not enabled"});let s=decodeURIComponent(n.replace(/^\/api\/workflows\/signal\//,"").split("?")[0]);return s?qe(t,e,i=>{let l=i,c=a.dispatcher.emitSignal({name:s,scope:l?.scope,workflowId:l?.workflowId,payload:l?.payload});return R(e,200,{ok:!0,emission:c})}):R(e,400,{error:"signal name required"})}let o=n.match(/^\/api\/workflows\/([^\/?]+)(\/layout|\/validate)?(\?.*)?$/);if(o){let s=decodeURIComponent(o[1]),i=o[2];if(i==="/layout"){if(r==="GET")return a.requireScope(t,e,["dashboard:read"])?R(e,200,{layout:a.layouts.get(s)}):!0;if(r==="PUT")return a.requireScope(t,e,["dashboard:write"])?qe(t,e,l=>{try{let c=a.layouts.save(s,l);return R(e,200,{layout:c})}catch(c){return R(e,400,{error:"invalid layout",message:c.message})}}):!0}if(i==="/validate"&&r==="POST")return a.requireScope(t,e,["dashboard:read"])?qe(t,e,l=>{let c=ra.safeParse(l);if(!c.success)return R(e,200,{ok:!1,issues:c.error.issues.map(u=>({path:u.path.join("."),message:u.message}))});let p=oa(c.data).map(u=>({path:"",message:u}));return R(e,200,{ok:p.length===0,issues:p,workflow:c.data})}):!0;if(!i){if(r==="GET"){if(!a.requireScope(t,e,["dashboard:read"]))return!0;let l=a.store.get(s);return l?R(e,200,{workflow:l}):R(e,404,{error:"workflow not found"})}if(r==="PUT"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=new URL(n,"http://_").searchParams,c=l.get("convertFromYaml")==="true"||l.get("convertFromYaml")==="1";return qe(t,e,p=>Gs(e,a,p,{mode:"update",id:s,convertFromYaml:c}))}if(r==="DELETE"){if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=a.store.delete(s);return a.layouts.delete(s),R(e,l?200:404,l?{ok:!0}:{error:"workflow not found"})}}}return R(e,404,{error:"unknown workflows endpoint",path:n})}var $u=["mesh"];function Gs(t,e,a,n){let r=ra.safeParse(a);if(!r.success)return R(t,400,{error:"invalid workflow",issues:r.error.issues.map(l=>({path:l.path.join("."),message:l.message}))});let o=r.data,s=oa(o);if(s.length>0)return R(t,400,{error:"lint errors",issues:s.map(l=>({path:"",message:l}))});if(n.mode==="update"&&o.id!==n.id)return R(t,400,{error:"workflow id does not match path"});if(n.mode==="create"&&e.store.get(o.id))return R(t,409,{error:`workflow "${o.id}" already exists`});if(n.mode==="update"&&a&&typeof a=="object"){let l=a,c=e.store.get(n.id);if(c)for(let p of $u)!(p in l)&&p in c&&(o[p]=c[p])}let i;try{i=e.store.save(o,{convertFromYaml:n.convertFromYaml})}catch(l){let c=l?.message||String(l),p=l?.yamlPath,u=!!p||/yaml round-trip failed/.test(c);return R(t,u?409:500,{error:u?"couldn't preserve comments while saving back to the YAML file. Re-submit with ?convertFromYaml=true to convert this workflow to JSON (comments will be lost).":c,kind:u?"yaml-authored":"save-failed",...p?{path:p}:{}})}return e.layouts.sync(i.id,i.nodes.map(l=>l.id)),R(t,200,{workflow:i})}function Pu(t,e,a,n){let r=new URL(n,"http://_").searchParams,o=n.replace(/^\/api\/workflows\/runs/,"");if(o===""||o.startsWith("?")){let l=Math.max(1,Math.min(500,Number(r.get("limit")||50))),c=r.get("workflowId")||void 0,p=r.get("summary")==="1"||r.get("summary")==="true",u=a.runs.list({workflowId:c,limit:l});if(!p)return R(e,200,{runs:u});let f=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:f})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return qe(t,e,c=>{let p=c?.status;return p!=="paused"&&p!=="running"&&p!=="canceled"?R(e,400,{error:"status must be paused|running|canceled"}):a.runs.setStatus(l,p)?R(e,200,{ok:!0,runId:l,status:p}):R(e,404,{error:"run not found"})})}let i=o.match(/^\/([^\/?]+)(\/stream)?$/);if(i){let l=decodeURIComponent(i[1]);if(i[2])return ju(t,e,a,l);let c=a.runs.get(l);return c?R(e,200,{run:c}):R(e,404,{error:"run not found"})}return R(e,404,{error:"unknown runs endpoint"})}function ju(t,e,a,n){let r=a.runs.get(n);if(!r)return R(e,404,{error:"run not found"}),!0;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`data: ${JSON.stringify(r)}
15969
16003
 
15970
16004
  `);let o=!1,s=()=>{o=!0,l?.(),clearInterval(p);try{e.end()}catch{}};t.on("close",s);let i=u=>{if(!o)try{e.write(`data: ${JSON.stringify(u)}
15971
16005
 
15972
- `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function qe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){R(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{R(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{R(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>R(e,400,{error:"body read failed",message:r.message})),!0}function R(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as pm}from"fs";import{createRequire as um}from"module";var Pu=2048,Ws=/^[A-Za-z0-9_-]{8,256}$/;async function Gs(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return Y(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):ju()});if(n==="GET"&&a==="/api/app/alerts")return Y(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return Y(e,404,{error:"not found"});if(!s||l)return Y(e,503,{error:l});let c;try{c=await bt(t)}catch(h){return Y(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),k=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return Y(e,400,{error:`${k} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return Y(e,200,{ok:!0,...S})}let p=Ou(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Ws.test(u)||typeof f!="string"||!Ws.test(f)?Y(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?Y(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function ju(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Ou(t,e){if(typeof t!="string"||t.length>Pu)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}cn();var Ks=50,Nu=280;async function Js(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=Du(await o.recent(Ks))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Xs(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Xs(e,404,{error:"not found"})}function Vs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=it();return r?new rr(r):null}}}function Du(t){let e=[];for(let a of Array.isArray(t)?t:[]){let n=a;!n||n.kind!=="announce"||typeof n.id!="string"||typeof n.at!="string"||e.push({id:n.id.slice(0,64),text:Pa(typeof n.summary=="string"?n.summary:"",Nu),by:typeof n.agentId=="string"?Pa(n.agentId,100):null,node:Pa(typeof n.node=="string"?n.node:"",100),at:n.at.slice(0,40)})}return e.sort((a,n)=>(Date.parse(n.at)||0)-(Date.parse(a.at)||0)),e.slice(0,Ks)}function Pa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Xs(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Hu="operator",Bu=50,Ys=4,Qs=500;function zu(t){let e={channel:"app",chatId:t.chatId,sender:Hu,...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 Zs(t,e,a,n){let{path:r,body:o}=zu(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let k=u!=="done",_=i?{text:pt(f,k),artifacts:[]}:dt(f,le.perMessage,k),{cleanText:S,ui:g}=u==="done"?mt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ja(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let f=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,f||`AgentX answered HTTP ${u.status}.`)}for await(let f of Fu(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<Bu){let k={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(k),h.id&&c.set(String(h.id),k)}else if(f.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(f.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(f.event==="error")return p("error",s,qu(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 qu(t){let e=String(t||"The agent could not answer.");return vn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ja(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}});let r=(t.quickReplies??[]).slice(0,Ys).map(s=>s.slice(0,Qs));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Ys).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Qs)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Fu(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,`
16006
+ `)}catch{s()}},l=a.runEvents?.subscribe(n,i),c=r.updatedAt,p=setInterval(()=>{if(o)return;let u=a.runs.get(n);u&&u.updatedAt!==c&&(c=u.updatedAt,i(u))},2e3);return!0}function qe(t,e,a){let n="";return t.setEncoding("utf8"),t.on("data",r=>{n+=r}),t.on("end",()=>{let r;try{r=n?JSON.parse(n):{}}catch(s){R(e,400,{error:"invalid JSON body",message:s.message});return}let o;try{o=a(r)}catch(s){try{R(e,500,{error:"handler threw (sync)",message:s?.message??String(s)})}catch{}return}Promise.resolve(o).catch(s=>{try{R(e,500,{error:"handler threw",message:s?.message??String(s)})}catch{}})}),t.on("error",r=>R(e,400,{error:"body read failed",message:r.message})),!0}function R(t,e,a){return t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a)),!0}import{readFileSync as mm}from"fs";import{createRequire as fm}from"module";var Ou=2048,Ks=/^[A-Za-z0-9_-]{8,256}$/;async function Js(t,e,a,n,r,o){if(a!=="/api/app/push"&&!a.startsWith("/api/app/push/")&&a!=="/api/app/alerts")return!1;let s=o.store(),i=s?o.publicKey():null,l=s?i?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":o.reason??"Notifications are not set up on this computer.";if(n==="GET"&&a==="/api/app/push")return Y(e,200,{available:!l,reason:l??null,publicKey:i,subscriptions:s&&i?s.list(r.id).filter(h=>h.publicKey===i).length:0,...s?s.prefs.all(r.id):Nu()});if(n==="GET"&&a==="/api/app/alerts")return Y(e,200,{items:s?s.recent(o.keepRecent,r.id):[]});if(n!=="POST"||a!=="/api/app/push/subscribe"&&a!=="/api/app/push/unsubscribe"&&a!=="/api/app/push/prefs")return Y(e,404,{error:"not found"});if(!s||l)return Y(e,503,{error:l});let c;try{c=await bt(t)}catch(h){return Y(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),k=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return Y(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return Y(e,400,{error:`${k} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[ce[g].field]),S[ce[g].field]=c[ce[g].field];return Y(e,200,{ok:!0,...S})}let p=Du(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return Y(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return Y(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,f=c.keys?.auth;return typeof u!="string"||!Ks.test(u)||typeof f!="string"||!Ks.test(f)?Y(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?Y(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:f,deviceId:r.id,deviceName:r.name,publicKey:i}),Y(e,200,{ok:!0}))}function Nu(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Du(t,e){if(typeof t!="string"||t.length>Ou)return null;try{let a=new URL(t);if(a.protocol!=="https:"||a.port||a.username||a.password)return null;let n=a.hostname.toLowerCase();return e.some(o=>{let s=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!s&&(n===s||n.endsWith("."+s))})?t:null}catch{return null}}function Y(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}cn();var Ys=50,Hu=280;async function Qs(t,e,a,n,r,o){if(a!=="/api/app/announcements")return!1;if(n==="GET"){let s=o.prefs(),i=[],l=null;try{i=Bu(await o.recent(Ys))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return Vs(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return Vs(e,404,{error:"not found"})}function Zs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||U(t.dashboard,e),n=t.channels.push;return{async recent(r){let o=await fetch(`${e}/events/recent?kind=announce&limit=${r}`,{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`the daemon answered ${o.status}`);return(await o.json()).events??[]},prefs:()=>{if(!n.enabled||n.relayTo)return null;let r=it();return r?new rr(r):null}}}function Bu(t){let e=[];for(let a of Array.isArray(t)?t:[]){let n=a;!n||n.kind!=="announce"||typeof n.id!="string"||typeof n.at!="string"||e.push({id:n.id.slice(0,64),text:Pa(typeof n.summary=="string"?n.summary:"",Hu),by:typeof n.agentId=="string"?Pa(n.agentId,100):null,node:Pa(typeof n.node=="string"?n.node:"",100),at:n.at.slice(0,40)})}return e.sort((a,n)=>(Date.parse(n.at)||0)-(Date.parse(a.at)||0)),e.slice(0,Ys)}function Pa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function Vs(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var zu="operator",qu=50,ei=4,ti=500;function Fu(t){let e={channel:"app",chatId:t.chatId,sender:zu,...t.spoken?{via:"voice"}:{}};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function ai(t,e,a,n){let{path:r,body:o}=Fu(e),s="",i=!1,l=[],c=new Map,p=(u,f,h)=>{let k=u!=="done",_=i?{text:pt(f,k),artifacts:[]}:dt(f,le.perMessage,k),{cleanText:S,ui:g}=u==="done"?mt(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ja(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{},...t.operatorKey?{"X-AgentX-Operator":t.operatorKey}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let f=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,f||`AgentX answered HTTP ${u.status}.`)}for await(let f of Wu(u.body)){n(f.event,f.data);let h=f.data??{};if(f.event==="start")i=h.rich===!1;else if(f.event==="text"&&typeof h.text=="string")s+=h.text;else if(f.event==="tool"&&h.status==="start"&&l.length<qu){let k={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(k),h.id&&c.set(String(h.id),k)}else if(f.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(f.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(f.event==="error")return p("error",s,Uu(h.error))}}return a.aborted?p("stopped",s):p("error",s,"The connection to the agent closed before it answered.")}catch(u){return a.aborted?p("stopped",s):p("error",s,`Could not reach AgentX: ${u?.message||u}`)}}function Uu(t){let e=String(t||"The agent could not answer.");return vn(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ja(t){if(!t)return;let e=s=>/^https?:\/\//i.test(s)&&s.length<=2048,a={},n=(t.buttons??[]).filter(s=>e(s.url)).slice(0,8).map(s=>({label:s.label.slice(0,80),url:s.url}));n.length&&(a.buttons=n),t.poll&&(a.poll={question:t.poll.question.slice(0,300),options:t.poll.options.slice(0,10).map(s=>s.slice(0,100)),multiple:t.poll.multiple===!0}),t.media&&e(t.media.url)&&(a.media={type:t.media.type,url:t.media.url,...t.media.caption?{caption:t.media.caption.slice(0,300)}:{}});let r=(t.quickReplies??[]).slice(0,ei).map(s=>s.slice(0,ti));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,ei).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,ti)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Wu(t){let e=t.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:r,value:o}=await e.read();if(r)break;n+=a.decode(o,{stream:!0}).replace(/\r\n/g,`
15973
16007
  `);let s;for(;(s=n.indexOf(`
15974
16008
 
15975
16009
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
@@ -15979,12 +16013,12 @@ data: ${JSON.stringify(s)}
15979
16013
 
15980
16014
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15981
16015
 
15982
- `)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function ti(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=Uu(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:Oa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Oa(t,e=120){for(let a of t.split(`
15983
- `)){let n=ai(a);if(n)return Na(n,e)}return""}function Uu(t,e=120){let a=t.split(`
15984
- `).map(ai).filter(Boolean);return a.length?Na(a[a.length-1],e):""}function ai(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Na(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Ut=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Wt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var ei=140;function Gt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Oa(r||"",ei-18)||"something went wrong."}`:Oa(n,ei)||"Answered.";return{deviceId:t,title:Na(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var ri=8e3,Gu=/^[A-Za-z0-9_.:-]{1,64}$/,Re=new Map,Da=new Map,za=new Ut;function oi(){return za}async function si(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??za;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await ii(o)});let i=o.store();if(!i)return H(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),H(e,200,{conversations:ti(r.id,Ju(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Re.get(p.id);return H(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Re.get(p.id);if(!p||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),li(e);let{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g}=p;return e.write(Ha("conversation",{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g})),e.write(Ha("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await bt(t,64*1024)}catch(p){return H(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return H(e,404,{error:"no such conversation"});let u=Re.get(p.id);return u?(u.ac.abort(),Ba(p,o,r.name),H(e,200,{stopped:!0})):await Ba(p,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await Ku(e,c,r,i,o),!0}function Xu(t,e,a){let n=Fe(e.url),r=new Set,o=[];for(let s of t){let i=Fe(s.url),l=a.find(u=>Fe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function ii(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Xu(e.nodes,t.daemon,a)}async function Ku(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>ri){H(t,400,{error:`message must be 1\u2013${ri} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!Gu.test(_)){H(t,400,{error:"pick an agent"});return}let S=(await ii(r)).find(d=>d.target===k);if(!S){H(t,400,{error:`unknown node "${k}"`});return}if(!S.online){H(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){H(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Re.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Ft(r.orphanLimitMs??18e5);Re.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Da.set(l,{id:l,deviceId:a.id,title:c,agent:f,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),li(t),t.write(Ha("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let k=e.spoken===!0,_=await Zs(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(m,x)=>i.broadcast(m,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ba(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:_.text,status:_.status,at:Date.now(),..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},..._.tools.length?{tools:_.tools}:{}},_.files)??[];i.broadcast("final",{status:_.status,content:_.text,..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:_.status,attached:g,appOpen:(r.presence??za).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Wt(d)&&r.notifyFinish(Gt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Re.delete(l),Da.delete(l),i.finish()}}function Ju(){let t=[];for(let[e,a]of Da){let n=Re.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function li(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Ha(t,e){return`event: ${t}
16016
+ `)},15e3);r.unref?.(),this.listeners.set(n,e),this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=null),e.on("close",()=>{clearInterval(r),this.listeners.delete(n),!this.done&&!this.listeners.size&&!this.ac.signal.aborted&&!this.orphanTimer&&(this.orphanTimer=setTimeout(()=>{this.orphaned=!0,this.ac.abort()},this.orphanLimitMs),this.orphanTimer.unref?.())})}finish(){this.done=!0,this.orphanTimer&&clearTimeout(this.orphanTimer);for(let e of this.listeners.values())e.writableEnded||e.end();this.listeners.clear()}};function ri(t,e,a,n=12){let r=[],o=new Set,s=e.filter(i=>i.deviceId===t).sort((i,l)=>i.startedAt-l.startedAt);for(let i of s){if(r.length>=n)break;o.add(i.id);let l=Gu(i.text);r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:l?"answering":"thinking",preview:l||i.title.slice(0,120),updatedAt:i.startedAt})}for(let i of a){if(r.length>=n)break;o.has(i.id)||(o.add(i.id),r.push({id:i.id,title:i.title,agent:i.agent,agentName:i.agentName||i.agent,...i.color?{color:i.color}:{},state:"done",status:i.status,preview:Oa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function Oa(t,e=120){for(let a of t.split(`
16017
+ `)){let n=oi(a);if(n)return Na(n,e)}return""}function Gu(t,e=120){let a=t.split(`
16018
+ `).map(oi).filter(Boolean);return a.length?Na(a[a.length-1],e):""}function oi(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function Na(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var Ut=class{constructor(e=15e3){this.windowMs=e}seen=new Map;poll(e,a=Date.now()){this.seen.set(e,a)}away(e){this.seen.delete(e)}open(e,a=Date.now()){let n=this.seen.get(e);return n!==void 0&&a-n<=this.windowMs}};function Wt(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var ni=140;function Gt(t,e,a,n,r){let o=a==="error"?`Could not answer: ${Oa(r||"",ni-18)||"something went wrong."}`:Oa(n,ni)||"Answered.";return{deviceId:t,title:Na(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var ii=8e3,Ku=/^[A-Za-z0-9_.:-]{1,64}$/,Re=new Map,Da=new Map,za=new Ut;function li(){return za}async function ci(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??za;if(n==="GET"&&a==="/api/app/agents")return H(e,200,{nodes:await di(o)});let i=o.store();if(!i)return H(e,503,{error:"The database on this computer is unavailable, so chats can't be saved."});if(n==="GET"&&a==="/api/app/chat/active")return s.poll(r.id),H(e,200,{conversations:ri(r.id,Yu(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),H(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return H(e,200,{conversations:i.list(r.id)});let l=n==="GET"?/^\/api\/app\/conversations\/([^/]+)$/.exec(a):null;if(l){let p=i.get(r.id,decodeURIComponent(l[1]));if(!p)return H(e,404,{error:"no such conversation"});new URL(t.url||a,"http://x").searchParams.get("peek")!=="1"&&i.markRead(r.id,p.id);let u=Re.get(p.id);return H(e,200,{...p,running:!!u,...u?{partial:{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}}}:{}})}if(n==="GET"&&a==="/api/app/chat/attach"){let p=i.get(r.id,new URL(t.url||a,"http://x").searchParams.get("conversationId")||""),u=p&&Re.get(p.id);if(!p||!u)return H(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),pi(e);let{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g}=p;return e.write(Ha("conversation",{id:f,title:h,node:k,nodeName:_,agent:S,agentName:g})),e.write(Ha("resume",{text:u.text,tools:u.tools,...u.plain?{plain:!0}:{}})),u.attach(e),!0}if(n!=="POST"||a!=="/api/app/chat"&&a!=="/api/app/chat/stop")return H(e,404,{error:"not found"});let c;try{c=await bt(t,64*1024)}catch(p){return H(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return H(e,404,{error:"no such conversation"});let u=Re.get(p.id);return u?(u.ac.abort(),Ba(p,o,r.name),H(e,200,{stopped:!0})):await Ba(p,o,r.name)?H(e,200,{stopped:!0}):H(e,404,{error:"nothing is running in this conversation"})}return await Vu(e,c,r,i,o),!0}function Ju(t,e,a){let n=Fe(e.url),r=new Set,o=[];for(let s of t){let i=Fe(s.url),l=a.find(u=>Fe(u.peerUrl)===i);l&&r.add(l.peer);let c=i===n,p=s.agents.length?s.agents:l?.skills??[];o.push({target:c?"local":l?l.peer:null,name:s.reachable?s.name:(c?e.name:l?.peer)||s.name,online:c?s.reachable:l?l.healthy:!1,agents:p.map(u=>{let f=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:f>0||(u.active??0)>0,running:f,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function di(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Ju(e.nodes,t.daemon,a)}async function Vu(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>ii){H(t,400,{error:`message must be 1\u2013${ii} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){H(t,404,{error:"no such conversation"});return}}else{let k=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!Ku.test(_)){H(t,400,{error:"pick an agent"});return}let S=(await di(r)).find(d=>d.target===k);if(!S){H(t,400,{error:`unknown node "${k}"`});return}if(!S.online){H(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){H(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:k,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Re.has(s.id)){H(t,409,{error:"The agent is still answering in this conversation."});return}let i=new Ft(r.orphanLimitMs??18e5);Re.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h}=s;Da.set(l,{id:l,deviceId:a.id,title:c,agent:f,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),pi(t),t.write(Ha("conversation",{id:l,title:c,node:p,nodeName:u,agent:f,agentName:h})),i.attach(t);try{let k=e.spoken===!0,_=await ai(r.daemon,{node:p,agent:f,message:o,chatId:`app:${l}`,spoken:k},i.ac.signal,(m,x)=>i.broadcast(m,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,Ba(s,r,a.name));let S=n.appendWithFiles(a.id,l,{role:"assistant",content:_.text,status:_.status,at:Date.now(),..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},..._.tools.length?{tools:_.tools}:{}},_.files)??[];i.broadcast("final",{status:_.status,content:_.text,..._.error?{error:_.error}:{},..._.ui?{ui:_.ui}:{},...S.length?{files:S}:{}});let g=i.watched();g&&n.markRead(a.id,l);let d={status:_.status,attached:g,appOpen:(r.presence??za).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&Wt(d)&&r.notifyFinish(Gt(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Re.delete(l),Da.delete(l),i.finish()}}function Yu(){let t=[];for(let[e,a]of Da){let n=Re.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function pi(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function Ha(t,e){return`event: ${t}
15985
16019
  data: ${JSON.stringify(e)}
15986
16020
 
15987
- `}async function Ba(t,e,a){try{let n=Fe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Fe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Fe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Fe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Vu}from"stream";var Yu=/^\/api\/app\/files\/([^/]+)$/,Qu=15e3;async function di(t,e,a,n,r,o){let s=Yu.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let p=await Zu(c.node,o);if(!p)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let f=setTimeout(()=>u.abort(),Qu),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Bn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...zn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Vu.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function Zu(t,e){if(t==="local")return{url:ci(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ci(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ci(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var ui=8e3;async function mi(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Vn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Jn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Ne(t,Kn.bytes);if(!_)return Q(e,413,{error:Yn()});if(!_.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return pi(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,ui):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!tm(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return pi(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function pi(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(em(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function em(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function tm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===ui&&a.content.startsWith(e)))}var am=new Set(["ring","offer","answer","ice","hangup"]),Xt=/^[A-Za-z0-9_-]{4,64}$/,nm=128*1024;async function fi(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==p),f=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:f,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,nm);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=rm(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=hi(p.to);if(u&&p.kind==="ring"){let f=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Xt.test(l)?om(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!Xt.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Qe(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Qe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Xt.test(l))return P(e,400,{error:"callId is required"});let c=await Qe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function hi(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Qe(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function rm(t,e){let a=String(t?.kind??"");if(!am.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Xt.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!hi(r))return"to must be bot:<agent id> for an agent";if(Xe(r)===Xe(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function om(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var gi=`
16021
+ `}async function Ba(t,e,a){try{let n=Fe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Fe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Fe(l.url)===n)?.agents.find(l=>l.id===t.agent)?.runningTasks?.filter(l=>l.chatId===`app:${t.id}`)??[],i=0;for(let l of s)(await e.nodePost(n,`/api/tasks/${encodeURIComponent(l.id)}/cancel`,{reason:`cancelled by operator (phone: ${a})`})).status<300&&i++;return i}catch{return 0}}function Fe(t){return t.replace(/\/+$/,"")}function H(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Qu}from"stream";var Zu=/^\/api\/app\/files\/([^/]+)$/,em=15e3;async function mi(t,e,a,n,r,o){let s=Zu.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return $e(e,405,{error:"GET only"});let i=o.store();if(!i)return $e(e,503,{error:"The database on this computer is unavailable."});let l="";try{l=decodeURIComponent(s[1])}catch{}let c=i.getFile(r.id,l);if(!c)return $e(e,404,{error:"no such file"});let p=await tm(c.node,o);if(!p)return $e(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let f=setTimeout(()=>u.abort(),em),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Bn}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return $e(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(f)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),m=[403,404,413,415,416].includes(h.status)?h.status:502;return $e(e,m,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let k=Number(h.headers.get("content-length")||0);if(k>le.bytes)return u.abort(),$e(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...zn(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(k)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Qu.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>le.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function tm(t,e){if(t==="local")return{url:ui(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=ui(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function ui(t){return t.replace(/\/+$/,"")}function $e(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),t.end(JSON.stringify(a)),!0}var hi=8e3;async function gi(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return Q(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!Vn(h))return Q(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let k=Jn(t.headers["x-audio-duration-ms"]);if(k)return t.resume(),Q(e,k.status,{error:k.error});let _=await Ne(t,Kn.bytes);if(!_)return Q(e,413,{error:Yn()});if(!_.length)return Q(e,400,{error:"The recording is empty."});let S={"Content-Type":h,"X-Audio-Duration-Ms":String(t.headers["x-audio-duration-ms"]).trim()};return fi(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await Ne(t,64*1024);if(!i)return Q(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return Q(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return Q(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return Q(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,hi):"";if(!p.trim())return Q(e,400,{error:"text is required"});if(!nm(c.messages,p))return Q(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,f={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return fi(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(f)),{"Content-Type":"application/json"},9e4)}async function fi(t,e,a,n,r,o){try{let s=await fetch(e.url.replace(/\/+$/,"")+a,{method:"POST",headers:{...r,...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:new Uint8Array(n),signal:AbortSignal.timeout(o)}),i=s.headers.get("content-type")||"",l=Buffer.from(await s.arrayBuffer());return s.ok&&i.startsWith("audio/")?(t.writeHead(200,{"Content-Type":i,"Content-Length":l.length,"Cache-Control":"no-store"}),t.end(l),!0):s.status===404&&Array.isArray(am(l)?.endpoints)?Q(t,503,{error:"AgentX on this computer is too old for voice. Update it."}):(t.writeHead(s.status,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(i.includes("json")?l:JSON.stringify({error:`AgentX answered HTTP ${s.status}.`})),!0)}catch(s){return Q(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function Q(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function am(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function nm(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===hi&&a.content.startsWith(e)))}var rm=new Set(["ring","offer","answer","ice","hangup"]),Xt=/^[A-Za-z0-9_-]{4,64}$/,om=128*1024;async function xi(t,e,a,n,r){if(!a.startsWith("/api/app/camera/"))return!1;let o=r.daemon.url.replace(/\/+$/,""),s=r.daemon.token?{Authorization:`Bearer ${r.daemon.token}`}:{};if(a==="/api/app/camera/config"){if(n!=="GET")return P(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return P(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return P(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=Xe(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>Xe(String(h?.name??""))!==p),f=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return P(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:f,camera:c.camera??null})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,om);if(!l)return P(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=sm(c,r.nodeName);if(typeof p=="string")return P(e,400,{error:p});let u=vi(p.to);if(u&&p.kind==="ring"){let f=await Qe(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return P(e,f.status,f.status<300?{ok:!0,watch:f.body.watch}:{error:f.body.error})}try{let f=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await f.json().catch(()=>({}));return P(e,f.ok?200:502,f.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${f.status}.`})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return Xt.test(l)?im(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):P(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Ne(t,4096);if(!l)return P(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return P(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!Xt.test(p))return P(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",f=await Qe(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return P(e,f.status,f.status<300?{reply:f.body.reply,frame:f.body.frame}:{error:f.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return P(e,405,{error:"GET"});let l=await Qe(o,s,"GET","/calls/asking");if(l.status>=300)return P(e,l.status,{error:l.body.error});let c=(Array.isArray(l.body.calls)?l.body.calls:[]).map(p=>({id:p.id,agentId:p.agentId,reason:p.reason,createdAt:p.createdAt}));return P(e,200,{asks:c,ringSeconds:l.body.ringSeconds??null})}let i=/^\/api\/app\/camera\/asks\/([A-Za-z0-9_-]{4,64})\/(answer|decline)$/.exec(a);if(i){if(n!=="POST")return P(e,405,{error:"POST"});let l=await Qe(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return P(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return P(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!Xt.test(l))return P(e,400,{error:"callId is required"});let c=await Qe(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return P(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return P(e,404,{error:"not found"})}function vi(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Qe(t,e,a,n,r,o=15e3){try{let s=await fetch(`${t}${n}`,{method:a,headers:{"Content-Type":"application/json",...e},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(o)}),i=await s.json().catch(()=>({}));return s.status===404&&typeof i?.error=="string"&&/channels\.webrtc\.enabled/.test(i.error)?{status:503,body:i}:{status:s.ok?s.status:s.status>=500?502:s.status,body:s.ok?i:{error:i?.error||`AgentX answered HTTP ${s.status}.`}}}catch{return{status:502,body:{error:"Could not reach AgentX on this computer."}}}}function sm(t,e){let a=String(t?.kind??"");if(!rm.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!Xt.test(n))return"callId must be 4 to 64 letters, digits, - or _";let r=typeof t?.to=="string"?t.to.trim():"";if(!r||r.length>100)return"to must name a machine or an agent";if(r.startsWith("bot:")&&!vi(r))return"to must be bot:<agent id> for an agent";if(Xe(r)===Xe(e))return"pick another machine; this phone signals from this one";let o={kind:a,callId:n,from:e,to:r};if(a==="offer"||a==="answer"){if(typeof t.sdp!="string"||!t.sdp)return"sdp is required";o.sdp=t.sdp}if(a==="ice"){let s=t.candidate;if(!s||typeof s.candidate!="string")return"candidate is required";o.candidate={candidate:s.candidate,sdpMid:typeof s.sdpMid=="string"?s.sdpMid:null,sdpMLineIndex:typeof s.sdpMLineIndex=="number"?s.sdpMLineIndex:null,usernameFragment:typeof s.usernameFragment=="string"?s.usernameFragment:null}}return a==="ring"&&(o.reason="camera"),o}async function im(t,e,a,n){let r=new AbortController;t.on("close",()=>r.abort());let o;try{o=await fetch(a,{headers:{Accept:"text/event-stream",...n},signal:r.signal})}catch{return P(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?P(e,503,{error:"Calls are off on this computer."}):P(e,502,{error:`AgentX answered HTTP ${o.status}.`});e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"});let s=o.body.getReader();try{for(;;){let{done:i,value:l}=await s.read();if(i)break;e.write(l)}}catch{}finally{r.abort(),e.end()}return!0}function P(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var bi=`
15988
16022
  (function () {
15989
16023
  var fleetPanel = document.getElementById('panel-fleet');
15990
16024
  var activityPanel = document.getElementById('panel-activity');
@@ -16228,7 +16262,7 @@ data: ${JSON.stringify(e)}
16228
16262
  setInterval(refresh, 15000);
16229
16263
  refresh();
16230
16264
  })();
16231
- `;var xi=`
16265
+ `;var yi=`
16232
16266
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
16233
16267
  .fx-head h2 { margin: 4px 0 0; }
16234
16268
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -16285,7 +16319,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16285
16319
  }
16286
16320
  .fx-error:empty { display: none; }
16287
16321
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
16288
- `;var vi=`
16322
+ `;var wi=`
16289
16323
  (function () {
16290
16324
  var panel = document.getElementById('panel-alerts');
16291
16325
  if (!panel) return;
@@ -16466,7 +16500,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16466
16500
  refresh();
16467
16501
  loadRecent();
16468
16502
  })();
16469
- `;var bi=`
16503
+ `;var ki=`
16470
16504
  (function () {
16471
16505
  var panel = document.getElementById('panel-alerts');
16472
16506
  if (!panel) return;
@@ -16579,7 +16613,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16579
16613
  }
16580
16614
  load();
16581
16615
  })();
16582
- `;var yi=`
16616
+ `;var _i=`
16583
16617
  (function () {
16584
16618
  var panel = document.getElementById('panel-chat');
16585
16619
  var V = window.AXChatView;
@@ -16851,7 +16885,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16851
16885
  var last = recall('ax-chat-conv');
16852
16886
  if (!fromHash() && last) openConversation(last);
16853
16887
  })();
16854
- `;var wi=`
16888
+ `;var Si=`
16855
16889
  window.AXChatView = (function () {
16856
16890
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
16857
16891
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -17132,7 +17166,7 @@ window.AXChatView = (function () {
17132
17166
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
17133
17167
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
17134
17168
  })();
17135
- `;var ki=`
17169
+ `;var Ei=`
17136
17170
  window.AXChatSheets = function (o) {
17137
17171
  var V = o.V, picker = o.picker, hist = o.hist;
17138
17172
  function loadPicker() {
@@ -17178,7 +17212,7 @@ window.AXChatSheets = function (o) {
17178
17212
  });
17179
17213
  return { loadPicker: loadPicker, loadHistory: loadHistory };
17180
17214
  };
17181
- `;var _i=`
17215
+ `;var Ti=`
17182
17216
  window.AXChatLog = function (o) {
17183
17217
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
17184
17218
  function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
@@ -17241,7 +17275,7 @@ window.AXChatLog = function (o) {
17241
17275
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
17242
17276
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
17243
17277
  };
17244
- `;var Si=`
17278
+ `;var Ai=`
17245
17279
  (function () {
17246
17280
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
17247
17281
  var top = panel && panel.querySelector('.cx-top');
@@ -17391,7 +17425,7 @@ window.AXChatLog = function (o) {
17391
17425
  window.AXStrip = { poll: poll, update: update, banner: banner };
17392
17426
  poll();
17393
17427
  })();
17394
- `;var Ei=`
17428
+ `;var Ci=`
17395
17429
  .cs { margin: 0 -2px; }
17396
17430
  .cs[hidden] { display: none; }
17397
17431
  .cs-list {
@@ -17447,7 +17481,7 @@ window.AXChatLog = function (o) {
17447
17481
  @media (prefers-reduced-motion: reduce) {
17448
17482
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
17449
17483
  }
17450
- `;function Ti(t,e,a=5){if(t.some(o=>o.key===e.key))return{queue:t.slice(),dropped:[]};let n=t.concat([e]),r=Math.max(0,n.length-Math.max(1,a));return{queue:n.slice(r),dropped:n.slice(0,r)}}function Ai(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Ci=`
17484
+ `;function Ii(t,e,a=5){if(t.some(o=>o.key===e.key))return{queue:t.slice(),dropped:[]};let n=t.concat([e]),r=Math.max(0,n.length-Math.max(1,a));return{queue:n.slice(r),dropped:n.slice(0,r)}}function Mi(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var Li=`
17451
17485
  body { height: 100dvh; }
17452
17486
  main { min-height: 0; }
17453
17487
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -17557,7 +17591,7 @@ main { min-height: 0; }
17557
17591
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
17558
17592
  }
17559
17593
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
17560
- `;var Ii=`
17594
+ `;var Ri=`
17561
17595
  window.AXOrb = (function () {
17562
17596
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
17563
17597
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -17688,7 +17722,7 @@ window.AXOrb = (function () {
17688
17722
  }
17689
17723
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
17690
17724
  })();
17691
- `;var Mi=`
17725
+ `;var $i=`
17692
17726
  window.AXVoiceIO = (function () {
17693
17727
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
17694
17728
  var ac = null, playing = null;
@@ -17806,7 +17840,7 @@ window.AXVoiceIO = (function () {
17806
17840
 
17807
17841
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
17808
17842
  })();
17809
- `;var Li=`
17843
+ `;var Pi=`
17810
17844
  (function () {
17811
17845
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
17812
17846
  if (!panel || !C || !IO || !O) return;
@@ -18014,7 +18048,7 @@ window.AXVoiceIO = (function () {
18014
18048
  idle();
18015
18049
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
18016
18050
  })();
18017
- `;var Ri=`
18051
+ `;var ji=`
18018
18052
  .vx {
18019
18053
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
18020
18054
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -18050,7 +18084,7 @@ window.AXVoiceIO = (function () {
18050
18084
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
18051
18085
  .cx-typing-on .vx-row { gap: 16px; }
18052
18086
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
18053
- `;var $i=`
18087
+ `;var Oi=`
18054
18088
  <main class="card">
18055
18089
  <h1>This phone isn't paired</h1>
18056
18090
  <p>On the computer running AgentX, open a terminal in the folder that holds <code>agentx.json</code> and run <code>agentx app pair</code>. Scan the QR code it shows, or type the code under it.</p>
@@ -18064,7 +18098,7 @@ window.AXVoiceIO = (function () {
18064
18098
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
18065
18099
  </form>
18066
18100
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
18067
- </main>`,Pi=`
18101
+ </main>`,Ni=`
18068
18102
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
18069
18103
  .pair-form label { font-weight: 600; }
18070
18104
  .pair-form input {
@@ -18086,7 +18120,7 @@ window.AXVoiceIO = (function () {
18086
18120
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
18087
18121
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
18088
18122
  }
18089
- `,ji=`
18123
+ `,Di=`
18090
18124
  (function () {
18091
18125
  var form = document.getElementById('pair-form');
18092
18126
  var input = document.getElementById('pair-code');
@@ -18178,7 +18212,7 @@ window.AXVoiceIO = (function () {
18178
18212
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
18179
18213
  }
18180
18214
  })();
18181
- `;var Oi=`
18215
+ `;var Hi=`
18182
18216
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
18183
18217
  <video id="scan-video" playsinline muted autoplay></video>
18184
18218
  <div class="scan-frame" aria-hidden="true"></div>
@@ -18187,7 +18221,7 @@ window.AXVoiceIO = (function () {
18187
18221
  <button type="button" id="scan-close" class="scan-close">Close</button>
18188
18222
  </div>
18189
18223
  <p id="scan-msg" class="scan-msg" role="status" aria-live="polite">Point the camera at the QR code shown by agentx app pair.</p>
18190
- </div>`,Ni=`
18224
+ </div>`,Bi=`
18191
18225
  .pair-form .scan-btn {
18192
18226
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
18193
18227
  }
@@ -18216,7 +18250,7 @@ window.AXVoiceIO = (function () {
18216
18250
  }
18217
18251
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
18218
18252
  body.scanning { overflow: hidden; }
18219
- `,Di=`
18253
+ `,zi=`
18220
18254
  (function () {
18221
18255
  var openBtn = document.getElementById('scan-btn');
18222
18256
  var box = document.getElementById('scan');
@@ -18424,7 +18458,7 @@ body.scanning { overflow: hidden; }
18424
18458
  border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
18425
18459
  }
18426
18460
  .cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
18427
- `;var Hi='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Bi=`
18461
+ `;var qi='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Fi=`
18428
18462
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
18429
18463
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
18430
18464
  <span class="cam-dot" aria-hidden="true"></span>
@@ -18449,7 +18483,7 @@ body.scanning { overflow: hidden; }
18449
18483
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
18450
18484
  </div>
18451
18485
  </div>
18452
- </div>`,zi=`
18486
+ </div>`,Ui=`
18453
18487
  (function () {
18454
18488
  var btn = document.getElementById('cam-btn');
18455
18489
  var sheet = document.getElementById('cam');
@@ -18718,7 +18752,7 @@ body.scanning { overflow: hidden; }
18718
18752
  });
18719
18753
  window.addEventListener('pagehide', function () { stop(); });
18720
18754
  })();
18721
- `;var qi=`
18755
+ `;var Wi=`
18722
18756
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
18723
18757
  <div class="cam-askbar-text">
18724
18758
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -18728,7 +18762,7 @@ body.scanning { overflow: hidden; }
18728
18762
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
18729
18763
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
18730
18764
  </div>
18731
- </div>`,Fi=`
18765
+ </div>`,Gi=`
18732
18766
  .cam-askbar[hidden] { display: none; }
18733
18767
  .cam-askbar {
18734
18768
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -18743,7 +18777,7 @@ body.scanning { overflow: hidden; }
18743
18777
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
18744
18778
  }
18745
18779
  .cam-askbar-no { background: transparent; color: #fff; }
18746
- `,Ui=`
18780
+ `,Xi=`
18747
18781
  (function () {
18748
18782
  var bar = document.getElementById('cam-ask-bar');
18749
18783
  if (!bar) return;
@@ -18813,7 +18847,7 @@ body.scanning { overflow: hidden; }
18813
18847
  setInterval(poll, 5000);
18814
18848
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
18815
18849
  })();
18816
- `;function Wi(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function Gi(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var Xi=`
18850
+ `;function Ki(t,e){let a={width:1280,height:720,frameRate:15},n=t||a;return{audio:!1,video:{facingMode:{ideal:e==="user"?"user":"environment"},width:{ideal:n.width||a.width},height:{ideal:n.height||a.height},frameRate:{ideal:n.frameRate||a.frameRate}}}}function Ji(t){let e=Math.max(0,Math.ceil(t/1e3)),a=Math.floor(e/60),n=e%60;return a+":"+(n<10?"0":"")+n}var Vi=`
18817
18851
  (function () {
18818
18852
  var main = document.querySelector('main');
18819
18853
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
@@ -18922,7 +18956,7 @@ body.scanning { overflow: hidden; }
18922
18956
  main.addEventListener('touchend', function () { end(false); });
18923
18957
  main.addEventListener('touchcancel', function () { end(true); });
18924
18958
  })();
18925
- `,Ki=`
18959
+ `,Yi=`
18926
18960
  main { position: relative; }
18927
18961
  main.sw-on { overflow: hidden; }
18928
18962
  .sw-on > [role=tabpanel] { will-change: transform; }
@@ -18933,7 +18967,7 @@ main > .sw-peek {
18933
18967
  }
18934
18968
  main > #panel-chat.sw-peek { display: flex; flex-direction: column; }
18935
18969
  @media (prefers-reduced-motion: reduce) { .sw-slide > [role=tabpanel] { transition: none; } }
18936
- `;function Ji(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function Vi(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function Yi(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function Qi(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var Fa=`
18970
+ `;function Qi(t){let e=["INPUT","TEXTAREA","SELECT","DIALOG"];return!t.some(a=>a.scrollsX||a.editable||a.touchAction==="none"||a.touchAction==="pan-x"||e.indexOf(a.tag)>=0)}function Zi(t,e){let a=Math.abs(t),n=Math.abs(e);return a<10&&n<10?"":a>n*1.5?"x":"y"}function el(t,e,a){return a>0&&t===0||a<0&&t===e-1?a/4:a}function tl(t,e,a,n,r){if(!(Math.abs(r)>.5?r*a>0&&Math.abs(a)>30:Math.abs(a)>n/3))return t;let i=t+(a<0?1:-1);return i<0||i>=e?t:i}var Fa=`
18937
18971
  ${z({afterUnauthorized:Hr})}
18938
18972
  var CACHE = 'agentx-app-v3';
18939
18973
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
@@ -19025,7 +19059,7 @@ self.addEventListener('notificationclick', function (e) {
19025
19059
  return self.clients.openWindow(target);
19026
19060
  }));
19027
19061
  });
19028
- `;var sm="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})();</script>";function Ua(t){return`<meta charset="utf-8">
19062
+ `;var lm="<script>(function(){var t;try{t=localStorage.getItem('ax-theme')}catch(e){}if(t!=='light'&&t!=='dark'){t=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)})();</script>";function Ua(t){return`<meta charset="utf-8">
19029
19063
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
19030
19064
  <meta name="theme-color" content="#2979FF">
19031
19065
  <meta name="referrer" content="no-referrer">
@@ -19036,38 +19070,38 @@ self.addEventListener('notificationclick', function (e) {
19036
19070
  <link rel="icon" type="image/png" href="/app/icon-192.png">
19037
19071
  <link rel="apple-touch-icon" href="/app/icon-192.png">
19038
19072
  <title>${t}</title>
19039
- ${sm}
19040
- <style>${Tt}${cm}</style>`}var Zi=[{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 el(){let t=Zi.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=Zi.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
19073
+ ${lm}
19074
+ <style>${Tt}${pm}</style>`}var al=[{id:"chat",label:"Chat",soon:"Loading your conversations\u2026"},{id:"fleet",label:"Fleet",soon:"Loading your machines\u2026"},{id:"activity",label:"Activity",soon:"Loading what your agents are doing\u2026"},{id:"alerts",label:"Alerts",soon:"Loading notifications\u2026"}];function nl(){let t=al.map((a,n)=>`<button type="button" role="tab" id="tab-${a.id}" aria-controls="panel-${a.id}" aria-selected="${n===0}" tabindex="${n===0?0:-1}" data-tab="${a.id}">${a.label}</button>`).join(""),e=al.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
19041
19075
  <h2>${a.label}</h2>
19042
19076
  <p class="soon">${a.soon}</p>
19043
19077
  </section>`).join("");return`<!doctype html>
19044
19078
  <html lang="en">
19045
- <head>${Ua("AgentX")}<style>${dm}${xi}${Ci}${Ei}${Ri}${qa}${Fi}${Ki}</style></head>
19079
+ <head>${Ua("AgentX")}<style>${um}${yi}${Li}${Ci}${ji}${qa}${Gi}${Yi}</style></head>
19046
19080
  <body>
19047
19081
  <header class="bar">
19048
19082
  <div>
19049
19083
  <h1>AgentX</h1>
19050
19084
  <p id="who" class="who">Connecting\u2026</p>
19051
19085
  </div>
19052
- <div class="bar-btns">${Hi}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
19086
+ <div class="bar-btns">${qi}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
19053
19087
  </header>
19054
19088
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
19055
- ${qi}
19089
+ ${Wi}
19056
19090
  <main>${e}</main>
19057
19091
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
19058
- ${Bi}
19059
- <script>${im}</script>
19060
- <script>${z({swipeMayStart:Ji,swipeAxis:Vi,swipeOffset:Yi,swipeLanding:Qi})}${Xi}</script>
19061
- <script>${gi}</script>
19062
- <script>${vi}</script>
19092
+ ${Fi}
19093
+ <script>${cm}</script>
19094
+ <script>${z({swipeMayStart:Qi,swipeAxis:Zi,swipeOffset:el,swipeLanding:tl})}${Vi}</script>
19063
19095
  <script>${bi}</script>
19064
- <script>${z({markdownToHtml:Nn})}${wi}${_i}${ki}${yi}</script>
19065
- <script>${z({queueSpeech:Ti,nextSpeech:Ai})}${Ii}${Mi}${Li}</script>
19066
- <script>${Si}</script>
19067
- <script>${z({cameraConstraints:Wi,shareClock:Gi})}${zi}</script>
19068
- <script>${Ui}</script>
19096
+ <script>${wi}</script>
19097
+ <script>${ki}</script>
19098
+ <script>${z({markdownToHtml:Nn})}${Si}${Ti}${Ei}${_i}</script>
19099
+ <script>${z({queueSpeech:Ii,nextSpeech:Mi})}${Ri}${$i}${Pi}</script>
19100
+ <script>${Ai}</script>
19101
+ <script>${z({cameraConstraints:Ki,shareClock:Ji})}${Ui}</script>
19102
+ <script>${Xi}</script>
19069
19103
  </body>
19070
- </html>`}function tl(){return`<!doctype html>
19104
+ </html>`}function rl(){return`<!doctype html>
19071
19105
  <html lang="en">
19072
19106
  <head>${Ua("Pair \xB7 AgentX")}</head>
19073
19107
  <body>
@@ -19075,17 +19109,17 @@ ${Bi}
19075
19109
  <h1>Pairing this phone\u2026</h1>
19076
19110
  <p id="msg" role="status">One moment.</p>
19077
19111
  </main>
19078
- <script>${lm}</script>
19112
+ <script>${dm}</script>
19079
19113
  </body>
19080
- </html>`}function al(){return`<!doctype html>
19114
+ </html>`}function ol(){return`<!doctype html>
19081
19115
  <html lang="en">
19082
- <head>${Ua("Not paired \xB7 AgentX")}<style>${Pi}${Ni}</style></head>
19083
- <body>${$i}${Oi}
19116
+ <head>${Ua("Not paired \xB7 AgentX")}<style>${Ni}${Bi}</style></head>
19117
+ <body>${Oi}${Hi}
19084
19118
  <script>${z({mayBounce:Br,formatPairInput:Pt,parsePairScan:zr})}</script>
19085
- <script>${ji}</script>
19086
19119
  <script>${Di}</script>
19120
+ <script>${zi}</script>
19087
19121
  </body>
19088
- </html>`}function nl(){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 im=`
19122
+ </html>`}function sl(){return JSON.stringify({id:"/app",name:"AgentX",short_name:"AgentX",description:"Talk to your agents and watch your fleet.",start_url:"/app",scope:"/app",display:"standalone",background_color:"#2979FF",theme_color:"#2979FF",icons:[{src:"/app/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/app/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}]})}var cm=`
19089
19123
  (function () {
19090
19124
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
19091
19125
  function select(tab, focus, keepHash) {
@@ -19155,7 +19189,7 @@ ${Bi}
19155
19189
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
19156
19190
  }
19157
19191
  })();
19158
- `,lm=`
19192
+ `,dm=`
19159
19193
  (function () {
19160
19194
  var msg = document.getElementById('msg');
19161
19195
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -19172,7 +19206,7 @@ ${Bi}
19172
19206
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
19173
19207
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
19174
19208
  })();
19175
- `,cm=`
19209
+ `,pm=`
19176
19210
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
19177
19211
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
19178
19212
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -19184,7 +19218,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
19184
19218
  .card h1 { font-size: 22px; margin: 0 0 12px; }
19185
19219
  .muted { color: var(--ax-text-2); }
19186
19220
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
19187
- `,dm=`
19221
+ `,um=`
19188
19222
  body { display: flex; flex-direction: column; }
19189
19223
  .bar {
19190
19224
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -19222,8 +19256,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
19222
19256
  }
19223
19257
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
19224
19258
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
19225
- `;var Kt="agentx_app",mm=400*86400,fm=new yt,hm=new Ee;async function rl(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new F;if(n==="GET"){if(a==="/app/manifest.webmanifest")return xe(e,200,"application/manifest+json",nl());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),xe(e,200,"text/javascript; charset=utf-8",Fa);if(a==="/app/icon-192.png")return xe(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/app/icon-512.png")return xe(e,200,"image/png",Be(512),"public, max-age=86400");if(a==="/app/pair")return xe(e,200,"text/html; charset=utf-8",tl());if(a==="/app/qr.js"){let i=gm();return i?xe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Pe(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Wa(et(t),o);return i?(e.setHeader("Set-Cookie",Ga(et(t))),Pe(e,200,{device:i.name})):Pe(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await On(t,{codes:r.pairCodes??new ft,limiter:r.pairLimiter??fm,verify:l=>Wa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ga(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Pe(e,i.status,i.body)}let s=Wa(xm(t),o);if(!s){let i=et(t);return(r.rejectLog??hm).record(a.slice(0,120),$t(t,He(Xa(t,Kt),o),i?He(i,o):null)),a==="/app"?xe(e,401,"text/html; charset=utf-8",al()):Pe(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Xa(t,Kt);return i&&!et(t)&&e.setHeader("Set-Cookie",Ga(i)),xe(e,200,"text/html; charset=utf-8",el())}return n==="GET"&&a==="/api/app/me"?Pe(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await jn(t,e,a,n,s.name,r.fleet)||r.push&&await Gs(t,e,a,n,s,r.push)||r.announce&&await Js(t,e,a,n,s,r.announce)||r.chat&&await si(t,e,a,n,s,r.chat)||r.chat&&await di(t,e,a,n,s,r.chat)||r.voice&&await mi(t,e,a,n,s,r.voice)||r.camera&&await fi(t,e,a,n,r.camera)?!0:Pe(e,404,{error:"not found"})}var Ze;function gm(){if(Ze!==void 0)return Ze;try{let t=um(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
19226
- `;Ze=Buffer.concat([Buffer.from(a),pm(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ze=null}return Ze}function Wa(t,e){if(!t)return null;let a=e.verify(t);return a&&ke(a,"app")?a:null}function Ga(t){return`${Kt}=${t}; Path=/; Max-Age=${mm}; HttpOnly; Secure; SameSite=Lax`}function xm(t){return et(t)??Xa(t,Kt)}function et(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Xa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Pe(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as ol}from"crypto";var je={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},vm=/^[a-f0-9]{32}$/,bm=/^c[a-z0-9]{8,32}$/,ym=/^#[0-9a-fA-F]{6}$/;function Ka(t){return bm.test(t)}var tt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
19259
+ `;var Kt="agentx_app",hm=400*86400,gm=new yt,xm=new Ee;async function il(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new F;if(n==="GET"){if(a==="/app/manifest.webmanifest")return xe(e,200,"application/manifest+json",sl());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),xe(e,200,"text/javascript; charset=utf-8",Fa);if(a==="/app/icon-192.png")return xe(e,200,"image/png",Be(192),"public, max-age=86400");if(a==="/app/icon-512.png")return xe(e,200,"image/png",Be(512),"public, max-age=86400");if(a==="/app/pair")return xe(e,200,"text/html; charset=utf-8",rl());if(a==="/app/qr.js"){let i=vm();return i?xe(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Pe(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=Wa(et(t),o);return i?(e.setHeader("Set-Cookie",Ga(et(t))),Pe(e,200,{device:i.name})):Pe(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await On(t,{codes:r.pairCodes??new ft,limiter:r.pairLimiter??gm,verify:l=>Wa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",Ga(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Pe(e,i.status,i.body)}let s=Wa(bm(t),o);if(!s){let i=et(t);return(r.rejectLog??xm).record(a.slice(0,120),$t(t,He(Xa(t,Kt),o),i?He(i,o):null)),a==="/app"?xe(e,401,"text/html; charset=utf-8",ol()):Pe(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=Xa(t,Kt);return i&&!et(t)&&e.setHeader("Set-Cookie",Ga(i)),xe(e,200,"text/html; charset=utf-8",nl())}return n==="GET"&&a==="/api/app/me"?Pe(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await jn(t,e,a,n,s.name,r.fleet)||r.push&&await Js(t,e,a,n,s,r.push)||r.announce&&await Qs(t,e,a,n,s,r.announce)||r.chat&&await ci(t,e,a,n,s,r.chat)||r.chat&&await mi(t,e,a,n,s,r.chat)||r.voice&&await gi(t,e,a,n,s,r.voice)||r.camera&&await xi(t,e,a,n,r.camera)?!0:Pe(e,404,{error:"not found"})}var Ze;function vm(){if(Ze!==void 0)return Ze;try{let t=fm(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
19260
+ `;Ze=Buffer.concat([Buffer.from(a),mm(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),Ze=null}return Ze}function Wa(t,e){if(!t)return null;let a=e.verify(t);return a&&ke(a,"app")?a:null}function Ga(t){return`${Kt}=${t}; Path=/; Max-Age=${hm}; HttpOnly; Secure; SameSite=Lax`}function bm(t){return et(t)??Xa(t,Kt)}function et(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function Xa(t,e){for(let a of(t.headers.cookie||"").split(";")){let n=a.indexOf("=");if(n>0&&a.slice(0,n).trim()===e)return a.slice(n+1).trim()||null}return null}function xe(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Pe(t,e,a){return xe(t,e,"application/json",JSON.stringify(a))}import{randomBytes as ll}from"crypto";var je={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},ym=/^[a-f0-9]{32}$/,wm=/^c[a-z0-9]{8,32}$/,km=/^#[0-9a-fA-F]{6}$/;function Ka(t){return wm.test(t)}var tt=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
19227
19261
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
19228
19262
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
19229
19263
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -19236,39 +19270,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
19236
19270
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
19237
19271
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
19238
19272
  CREATE INDEX IF NOT EXISTS app_chat_files_conversation ON app_chat_files(conversation_id);`),e.prepare("PRAGMA table_info(app_chat_messages)").all().some(r=>r.name==="files")||e.exec("ALTER TABLE app_chat_messages ADD COLUMN files TEXT");let n=e.prepare("PRAGMA table_info(app_chat_conversations)").all();n.some(r=>r.name==="read_at")||e.transaction(()=>{e.prepare("PRAGMA table_info(app_chat_conversations)").all().some(o=>o.name==="read_at")||(e.exec("ALTER TABLE app_chat_conversations ADD COLUMN read_at INTEGER"),e.exec("UPDATE app_chat_conversations SET read_at = updated_at"))}).immediate(),n.some(r=>r.name==="color")||e.exec("ALTER TABLE app_chat_conversations ADD COLUMN color TEXT"),e.exec(`CREATE TABLE IF NOT EXISTS app_chat_delivered (
19239
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ka(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${ol(4).toString("hex")}`,{color:s,...i}=a,l=s&&ym.test(s)?s:void 0,c={id:o,title:km(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
19240
- (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Ka(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(wm);return{...sl(n),messages:r}}list(e,a=je.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
19273
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ka(e)?this.db.prepare("SELECT device_id FROM app_chat_conversations WHERE id = ?").get(e)?.device_id??null:null}appendOnce(e,a,n,r,o=[],s=Date.now()){return!n||n.length>200?null:this.db.transaction(()=>!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e)||this.db.prepare("INSERT OR IGNORE INTO app_chat_delivered (key, conversation_id, at) VALUES (?, ?, ?)").run(n,a,s).changes===0?null:(this.db.prepare("DELETE FROM app_chat_delivered WHERE at < ?").run(s-30*24*60*6e4),this.appendWithFiles(e,a,r,o))).immediate()}create(e,a,n,r=Date.now()){let o=`c${r.toString(36)}${ll(4).toString("hex")}`,{color:s,...i}=a,l=s&&km.test(s)?s:void 0,c={id:o,title:Sm(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
19274
+ (id, device_id, title, node, node_name, agent, agent_name, color, created_at, updated_at, read_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,e,c.title,c.node,c.nodeName,c.agent,c.agentName??null,l??null,r,r,r),this.pruneDevice(e),c}get(e,a){if(!Ka(a))return null;let n=this.db.prepare("SELECT * FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e);if(!n)return null;let r=this.db.prepare("SELECT * FROM app_chat_messages WHERE conversation_id = ? ORDER BY id").all(a).map(_m);return{...cl(n),messages:r}}list(e,a=je.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
19241
19275
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
19242
19276
  (SELECT substr(m.content, 1, 240) FROM app_chat_messages m WHERE m.conversation_id = c.id ORDER BY m.id DESC LIMIT 1) AS last
19243
- FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...sl(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Ka(a)&&this.db.prepare("UPDATE app_chat_conversations SET read_at = MAX(COALESCE(read_at, 0), ?) WHERE id = ? AND device_id = ?").run(n,a,e)}unread(e,a){return this.db.prepare(`SELECT c.id, c.title, c.agent, c.agent_name, c.color,
19277
+ FROM app_chat_conversations c WHERE c.device_id = ? ORDER BY c.updated_at DESC, c.rowid DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>{let o=typeof r.last=="string"?r.last.replace(/\s+/g," ").trim().slice(0,120):"";return{...cl(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Ka(a)&&this.db.prepare("UPDATE app_chat_conversations SET read_at = MAX(COALESCE(read_at, 0), ?) WHERE id = ? AND device_id = ?").run(n,a,e)}unread(e,a){return this.db.prepare(`SELECT c.id, c.title, c.agent, c.agent_name, c.color,
19244
19278
  substr(m.content, 1, 240) AS answer, m.status, m.at
19245
19279
  FROM app_chat_conversations c
19246
19280
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
19247
19281
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
19248
19282
  ORDER BY m.at DESC, m.id DESC LIMIT ?`).all(e,Math.max(0,a)).map(r=>({id:r.id,title:r.title,agent:r.agent,...r.agent_name?{agentName:r.agent_name}:{},...r.color?{color:r.color}:{},answer:String(r.answer??"").trim(),status:r.status==="error"||r.status==="stopped"?r.status:"done",at:r.at}))}append(e,a,n){return this.appendWithFiles(e,a,n)!==null}appendWithFiles(e,a,n,r=[]){if(!this.db.prepare("SELECT 1 FROM app_chat_conversations WHERE id = ? AND device_id = ?").get(a,e))return null;let s=n.content.length>je.content?n.content.slice(0,je.content)+`
19249
19283
 
19250
- [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let f of r){if(l.length>=je.filesPerMessage)break;let h=f.filename.trim(),k=_n(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:ol(16).toString("hex"),name:_,mime:k.mime,kind:k.kind,path:h})}let c=l.map(f=>({id:f.id,name:f.name,mime:f.mime,kind:f.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
19284
+ [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,je.toolsPerMessage),l=[];for(let f of r){if(l.length>=je.filesPerMessage)break;let h=f.filename.trim(),k=_n(h);if(!k||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:ll(16).toString("hex"),name:_,mime:k.mime,kind:k.kind,path:h})}let c=l.map(f=>({id:f.id,name:f.name,mime:f.mime,kind:f.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
19251
19285
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,n.role,s,n.status??null,n.error?.slice(0,500)??null,n.ui?JSON.stringify(n.ui):null,i?.length?JSON.stringify(i):null,c.length?JSON.stringify(c):null,n.at),u=this.db.prepare(`INSERT INTO app_chat_files (id, conversation_id, message_id, path, name, mime, kind, created_at)
19252
19286
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let f of l)u.run(f.id,a,Number(p.lastInsertRowid),f.path,f.name,f.mime,f.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
19253
19287
  (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,je.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
19254
- (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!vm.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
19288
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ?)`).run(a,a),this.db.prepare("UPDATE app_chat_conversations SET updated_at = ? WHERE id = ?").run(n.at,a),c}getFile(e,a){if(!ym.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
19255
19289
  JOIN app_chat_conversations c ON c.id = f.conversation_id WHERE f.id = ? AND c.device_id = ?`).get(a,e);return n?{id:n.id,name:n.name,mime:n.mime,kind:n.kind,path:n.path,conversationId:n.conversation_id,node:n.node,agent:n.agent}:null}pruneDevice(e){let a=this.db.prepare(`SELECT id FROM app_chat_conversations WHERE device_id = ?
19256
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function sl(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 wm(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 km(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var _m=4e3,Ja=100,Sm=15,il=t=>t.replace(/\/+$/,""),Jt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=_m){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,Ja);e=Array.isArray(o)?o:o.events,a=!Array.isArray(o)&&o.gap===!0}catch{return 0}this.warnIfSkipped(e.length,a),e.length&&(this.cursor=e[e.length-1].id);let n=[...this.retry.values()].map(o=>o.event);for(let o of e)o.kind==="delegation"&&o.type==="reply"&&typeof o.ref=="string"&&o.ref&&!this.retry.has(o.id)&&n.push(o);let r=0;for(let o of n){let s=await this.file(o).catch(()=>"retry");if(s==="retry"){let i=(this.retry.get(o.id)?.left??Sm)-1;i>0?this.retry.set(o.id,{event:o,left:i}):(this.retry.delete(o.id),this.deps.log?.(`[app] callback reply ${o.ref} from ${o.node} could not be read; it stays in the agent's session`))}else this.retry.delete(o.id),s==="filed"&&r++}return r}finally{this.running=!1}}warnIfSkipped(e,a){let n=this.deps.warn??this.deps.log,r=this.cursor?`after event ${this.cursor}`:"on the first read";a&&n?.(`[app] warning: callback event cursor ${this.cursor} is no longer in the daemon's event ring; replies published before the oldest kept event were skipped`),e>=Ja&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ja}); older replies ${r} may have been skipped`)}async file(e){let a=this.deps.store();if(!a)return"retry";let n=await this.deps.nodeUrl(e.node);if(!n)return"retry";let r=await this.deps.fetchReply(n,e.ref);if(!r||r.taskId!==e.ref||r.channel!=="app"||!r.chatId.startsWith("app:"))return"skip";let o=r.chatId.slice(4),s=a.ownerOf(o);if(!s)return"skip";let i=a.get(s,o);if(!i)return"skip";let l=await this.deps.conversationUrl(i);if(!l||il(l)!==il(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=Em(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,f=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:f};return this.deps.notifyFinish&&Wt(h)&&this.deps.notifyFinish(Gt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Em(t,e){let a=t.plain?{text:pt(t.text,!1),artifacts:[]}:dt(t.text,le.perMessage,!1),{cleanText:n,ui:r}=mt(a.text),o=t.plain?void 0:ja(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Tm(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Tm(t){return t.replace(/\s+/g," ").trim().slice(0,300)}cn();function Ue(){let t=it();return t&&ye(t,"dashboard"),t}function Wy(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,Dm(h,t))}catch(k){console.error(` Board "${h.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?at(process.cwd(),t.workflows.dir):void 0,c=new bn(l?{baseDir:l}:void 0),p=new yn(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new wn(l?{baseDir:l}:void 0);ps(t),Ue(),Un({business:t.business?.enabled===!0});let f=Am(async(h,k)=>{try{await Pm(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){b(k,500,{error:_.message||"internal error"})}});tf(t).start(),f.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
19290
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,je.conversationsPerDevice);for(let{id:n}of a)this.db.prepare("DELETE FROM app_chat_files WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_messages WHERE conversation_id = ?").run(n),this.db.prepare("DELETE FROM app_chat_conversations WHERE id = ?").run(n)}};function cl(t){return{id:t.id,title:t.title,node:t.node,nodeName:t.node_name,agent:t.agent,...t.agent_name?{agentName:t.agent_name}:{},...t.color?{color:t.color}:{},createdAt:t.created_at,updatedAt:t.updated_at}}function _m(t){let e=o=>{if(o)try{return JSON.parse(o)}catch{return}},a=e(t.ui),n=e(t.tools),r=e(t.files);return{role:t.role,content:t.content,at:t.at,...t.status?{status:t.status}:{},...t.error?{error:t.error}:{},...a?{ui:a}:{},...n?{tools:n}:{},...r?{files:r}:{}}}function Sm(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Em=4e3,Ja=100,Tm=15,dl=t=>t.replace(/\/+$/,""),Jt=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Em){this.timer||(this.timer=setInterval(()=>{this.tick()},e),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async tick(){if(this.running)return 0;this.running=!0;try{let e,a=!1;try{let o=await this.deps.recent(this.cursor,Ja);e=Array.isArray(o)?o:o.events,a=!Array.isArray(o)&&o.gap===!0}catch{return 0}this.warnIfSkipped(e.length,a),e.length&&(this.cursor=e[e.length-1].id);let n=[...this.retry.values()].map(o=>o.event);for(let o of e)o.kind==="delegation"&&o.type==="reply"&&typeof o.ref=="string"&&o.ref&&!this.retry.has(o.id)&&n.push(o);let r=0;for(let o of n){let s=await this.file(o).catch(()=>"retry");if(s==="retry"){let i=(this.retry.get(o.id)?.left??Tm)-1;i>0?this.retry.set(o.id,{event:o,left:i}):(this.retry.delete(o.id),this.deps.log?.(`[app] callback reply ${o.ref} from ${o.node} could not be read; it stays in the agent's session`))}else this.retry.delete(o.id),s==="filed"&&r++}return r}finally{this.running=!1}}warnIfSkipped(e,a){let n=this.deps.warn??this.deps.log,r=this.cursor?`after event ${this.cursor}`:"on the first read";a&&n?.(`[app] warning: callback event cursor ${this.cursor} is no longer in the daemon's event ring; replies published before the oldest kept event were skipped`),e>=Ja&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ja}); older replies ${r} may have been skipped`)}async file(e){let a=this.deps.store();if(!a)return"retry";let n=await this.deps.nodeUrl(e.node);if(!n)return"retry";let r=await this.deps.fetchReply(n,e.ref);if(!r||r.taskId!==e.ref||r.channel!=="app"||!r.chatId.startsWith("app:"))return"skip";let o=r.chatId.slice(4),s=a.ownerOf(o);if(!s)return"skip";let i=a.get(s,o);if(!i)return"skip";let l=await this.deps.conversationUrl(i);if(!l||dl(l)!==dl(n)||i.agent!==r.agent)return this.deps.log?.(`[app] callback reply ${r.taskId} from ${e.node} does not match conversation ${o}; ignored`),"skip";let c=Am(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,f=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:f};return this.deps.notifyFinish&&Wt(h)&&this.deps.notifyFinish(Gt(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Am(t,e){let a=t.plain?{text:pt(t.text,!1),artifacts:[]}:dt(t.text,le.perMessage,!1),{cleanText:n,ui:r}=mt(a.text),o=t.plain?void 0:ja(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Cm(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Cm(t){return t.replace(/\s+/g," ").trim().slice(0,300)}cn();function Ue(){let t=it();return t&&ye(t,"dashboard"),t}function Yy(t){let e=t.dashboard,a=t.boards,n=e.port,r=e.bind,o=e.token,s=new Map;for(let h of a)try{s.set(h.id,Bm(h,t))}catch(k){console.error(` Board "${h.id}" failed to initialize: ${k.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?at(process.cwd(),t.workflows.dir):void 0,c=new bn(l?{baseDir:l}:void 0),p=new yn(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new wn(l?{baseDir:l}:void 0);fs(t),Ue(),Un({business:t.business?.enabled===!0});let f=Im(async(h,k)=>{try{await Om(h,k,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){b(k,500,{error:_.message||"internal error"})}});nf(t).start(),f.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
19257
19291
  Live dashboard: http://${h}:${n}
19258
19292
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
19259
19293
  Kanban dashboard: http://${h}:${n}
19260
- `),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var $m=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Pm(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(qn(t.headers)==="foreign"&&Fn(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Yr(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:ll(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(d,m)=>Nr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await rl(t,e,r,o,{nodeName:a.config.node?.name,fleet:fl(a.config),push:ml(a.config),announce:Vs(a.config),chat:hl(a.config),voice:af(a.config),camera:nf(a.config)}))return;if(o==="GET"&&$m.has(r)&&Sr("page",r),o==="GET"&&r==="/"){let d=dr();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ns({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await we(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await we(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ue(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await we(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ir({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=En(await we(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await Sn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Rs({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($s({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await ue(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ds({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hs({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zs({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qs({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){pr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ur(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await mr(t,e);return}if(o==="GET"&&r==="/admin"){lo(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){To(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){go(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Oo(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await df(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await La(t,e,r,x=>xl(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await dl(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=nt(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await dl(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await No(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await pf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-W6OQ7JI2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zo({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Bo(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qo({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fo({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await zm(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){e.writeHead(302,{Location:"/activity?view=map"}),e.end();return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await us(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await La(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await fs(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){xs(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await co(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,Xn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Ao(t,e,r,n);return}if(await Io(t,e,r,{people:()=>Ke(a.config.people),members:ll(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await xo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await vs(t,e,r);return}if(r.startsWith("/api/admin/")){await po(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(Qr);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=lf("web/"+d);try{let x=await cf(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await We(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await we(a.config);b(e,200,await Ps(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await we(a.config);b(e,200,await Os(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await js(e,await we(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Km(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await Jm(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await Qm(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await Zm(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ue(t);try{let m=await of(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Vm(t,e,[`agent:${d}`]))return;await Ym(t,e,a.config,d);return}if(o==="GET"&&r==="/api/node/build"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:d,signal:AbortSignal.timeout(3e3)});if(!m.ok)throw new Error(`HTTP ${m.status}`);b(e,200,Gn(await m.json()))}catch(d){b(e,502,{error:d.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await qm(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
19294
+ `),console.log(` Boards: ${a.map(k=>k.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var jm=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/people","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Om(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(qn(t.headers)==="foreign"&&Fn(o)){b(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await eo(t,e,r,o,{nodeName:a.config.node?.name,root:process.cwd(),people:()=>Ke(a.config.people),members:pl(a.config.members.logRetentionDays),db:()=>Ue(),linkFor:(d,m)=>Nr(d,m,{gitlab:a.config.channels.gitlab?.host})})||await il(t,e,r,o,{nodeName:a.config.node?.name,fleet:xl(a.config),push:gl(a.config),announce:Zs(a.config),chat:vl(a.config),voice:rf(a.config),camera:of(a.config)}))return;if(o==="GET"&&jm.has(r)&&Sr("page",r),o==="GET"&&r==="/"){let d=dr();if(!d.configExists||d.agentCount===0){e.writeHead(302,{Location:"/setup"}),e.end();return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bs({peers:D(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($a({peers:D(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await we(a.config);if(!d){b(e,503,{error:"no node available"});return}let m=await new Promise(v=>{let w="";t.on("data",T=>w+=T),t.on("end",()=>v(w)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:m||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){b(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await we(a.config),m=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await ue(t):void 0,v=x?.node??m,w=v?d.find(I=>I.url===v):d[0];if(!w){b(e,400,{error:"unknown node"});return}let T=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",y=await fetch(w.url+r+T,{method:o,headers:{"Content-Type":"application/json",...w.token?{Authorization:`Bearer ${w.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});b(e,y.status,await y.json().catch(()=>({error:`HTTP ${y.status}`})))}catch(d){b(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await ue(t),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await we(a.config);if(!d){b(e,200,{configured:!1,workflows:[]});return}let m=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});b(e,m.status,await m.json().catch(()=>({configured:!1,workflows:[]})))}catch{b(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Pr({peers:D(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end($r({peers:D(a.config),view:n.searchParams.get("view")}));return}if(o==="GET"&&r==="/monitor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ir({peers:D(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,m=setTimeout(()=>d.abort(),8e3);try{let x=En(await we(a.config,d.signal),a.config.mesh.peers);if(o==="GET"&&r==="/api/monitor"){let I=await Promise.all(x.map(async C=>{try{let E=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!E.ok)throw new Error(`HTTP ${E.status}`);return{name:C.name,url:C.url,ok:!0,data:await E.json()}}catch(E){return{name:C.name,url:C.url,ok:!1,error:E.message}}}));b(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){b(e,400,{error:"Select a known node"});return}let w=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(w)||o==="POST"&&["register","ended","action","retry","clear"].includes(w))){b(e,405,{error:"Unknown monitor operation"});return}let T=o==="POST"?JSON.stringify(await Sn(t)):void 0,y=await fetch(v.url+"/monitor/"+w+(w==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):w==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:T,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});b(e,y.status,await y.json())}catch(x){b(e,502,{error:x.message})}finally{clearTimeout(m)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(js({peers:D(a.config)}));return}if(o==="GET"&&r==="/guests"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Os({peers:D(a.config)}));return}if(o==="GET"&&r==="/api/guests"||o==="POST"&&/^\/api\/guests\/[^/]+\/(pause|resume|end|update)$/.test(r)){try{let d={"Content-Type":"application/json"};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=o==="POST"?await ue(t).catch(()=>({})):void 0,v=await fetch(`${m}${r.replace(/^\/api\/guests/,"/mesh/guests")}`,{method:o,headers:d,...x!==void 0?{body:JSON.stringify(x??{})}:{}});b(e,v.status,await v.json().catch(()=>({error:`HTTP ${v.status}`})))}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zs({peers:D(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(qs({peers:D(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fs({peers:D(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(cr({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",m=n.searchParams.get("node")||a.config.dashboard.daemonUrl;if(!d){e.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),e.end("<p>Missing <code>?agent=</code>. Open this task from the Live page.</p>");return}e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Us({taskId:decodeURIComponent(i[1]),agentId:d,agentName:n.searchParams.get("name")||void 0,channel:n.searchParams.get("channel")||void 0,archived:n.searchParams.get("archived")==="1",ask:n.searchParams.get("ask")||void 0,askAt:n.searchParams.get("at")||void 0,nodeUrl:m,peers:D(a.config)}));return}let l=o==="GET"&&r.match(/^\/agents\/([^/]+)\/history$/);if(l){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Ws({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:D(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){pr(t,e);return}if(o==="POST"&&r==="/api/setup"){await ur(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await mr(t,e);return}if(o==="GET"&&r==="/admin"){uo(t,e,D(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){Io(e,D(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){bo(t,e,D(a.config),a.token);return}if(o==="GET"&&(r==="/admin/health"||r==="/admin/observability")){if(r==="/admin/observability"){e.writeHead(302,{Location:"/admin/health"}),e.end();return}Ho(t,e,D(a.config));return}if(r.startsWith("/api/admin/")||r.startsWith("/api/workflows")||r.startsWith("/api/agents")){let d=n.searchParams.get("peer")==="fleet"?"fleet":String(t.headers["x-agentx-peer"]||"").trim()||n.searchParams.get("peer")||"";if(d==="fleet"){if(r==="/api/admin/activity-graph"){await uf(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await La(t,e,r,x=>yl(x,a.config));return}let m=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(m){let x=decodeURIComponent(m[1]),v=x.indexOf("::");if(v>0){let w=x.slice(0,v),T=x.slice(v+2),y=a.config.node?.id||a.config.node?.name||"local";if(w===y)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===w);if(I){let C=nt(I.url.replace(/\/+$/,""),a.config);if(C){await ml(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(T)}`);return}}b(e,404,{error:`unknown node "${w}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let m=nt(d,a.config);if(!m){b(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,w=>w.startsWith("?")?"?":"");await ml(t,e,m,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await Bo(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await mf(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-W6OQ7JI2.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});b(e,200,v)}catch(d){b(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Uo({peers:D(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await Fo(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wo({peers:D(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Go({peers:D(a.config)}));return}if(o==="GET"&&(r==="/admin/wiki"||r.startsWith("/admin/wiki/"))){if(r==="/admin/wiki"){e.writeHead(302,{Location:"/admin/wiki/"}),e.end();return}await Fm(a)(t,e);return}if(o==="GET"&&r==="/admin/activity-graph"){e.writeHead(302,{Location:"/activity?view=map"}),e.end();return}if(o==="GET"&&r==="/api/admin/activity-graph"&&await hs(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await La(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await xs(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){ys(t,e,c[1],D(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await mo(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){b(e,200,Xn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await Mo(t,e,r,n);return}if(await Ro(t,e,r,{people:()=>Ke(a.config.people),members:pl(a.config.members.logRetentionDays),root:process.cwd(),db:()=>Ue(),peers:D(a.config),localToken:a.token}))return;if(r.startsWith("/api/admin/graph/")){await yo(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await ws(t,e,r);return}if(r.startsWith("/api/admin/")){await fo(t,e,r);return}if(o==="GET"&&r==="/sortable.min.js"){e.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Cache-Control":"public, max-age=86400"}),e.end(to);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){b(e,400,{error:"invalid asset name"});return}let m=df("web/"+d);try{let x=await pf(m),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",w=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":w?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{b(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await We(a.config);b(e,200,d)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),m=n.searchParams.get("timezone")||"UTC",x=await We(a.config,{date:d,timezone:m});b(e,200,x)}catch(d){b(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(m,x,v,w)=>{let T=parseInt(n.searchParams.get(m)||"",10);return Number.isFinite(T)?Math.max(v,Math.min(w,T)):x};try{let m=await we(a.config);b(e,200,await Ns(m,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(m){b(e,502,{error:m.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){b(e,400,{error:"day=YYYY-MM-DD query param required"});return}let m=(x,v,w,T)=>{let y=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(y)?Math.max(w,Math.min(T,y)):v};try{let x=await we(a.config);b(e,200,await Hs(x,{day:d,tzOffsetMinutes:m("tzOffset",0,-840,840),limit:m("limit",40,1,200)}))}catch(x){b(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}let m=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,w]=[m.get("kind"),m.get("key")];if(!v||!w){b(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(w)}&limit=${encodeURIComponent(m.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,w,T]=[m.get("agent"),m.get("channel"),m.get("chat")];if(!v||!w||!T){b(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(w)}&chat=${encodeURIComponent(T)}&tzOffset=${encodeURIComponent(m.get("tzOffset")||"0")}`}else{let v=m.get("task");if(!v){b(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await Ds(e,await we(a.config),d,x)}catch(v){b(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){Vm(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!m||!x||!v){b(e,400,{error:"node, agent, task query params required"});return}await Ym(t,e,a,m,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),w=d.searchParams.get("limit")||"50";if(!m||!x){b(e,400,{error:"node and agent query params required"});return}await ef(e,a,m,x,v,w);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),m=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!m||!x||v!=="cancel"&&v!=="followup"){b(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await tf(t,e,a,m,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,"/voice/stop");return}if(o==="GET"&&r==="/api/agents"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!m.ok)throw new Error(`HTTP ${m.status}`);let x=await m.json();b(e,200,x)}catch(d){b(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!m.ok){b(e,m.status,{error:`HTTP ${m.status}`});return}b(e,200,await m.json())}catch(d){b(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await ue(t);try{let m=await lf(a.config,d);b(e,200,m)}catch(m){b(e,502,{error:m.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!Qm(t,e,[`agent:${d}`]))return;await Zm(t,e,a.config,d);return}if(o==="GET"&&r==="/api/node/build"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/health",{headers:d,signal:AbortSignal.timeout(3e3)});if(!m.ok)throw new Error(`HTTP ${m.status}`);b(e,200,Gn(await m.json()))}catch(d){b(e,502,{error:d.message||"daemon not reachable"})}return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",m=d.startsWith("Bearer ")?d.slice(7):"";if(m!==a.token){let x=new F,v=m?x.verify(m):null;if(!v||!ke(v,"dashboard:write")){b(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Um(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){b(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){b(e,400,{error:"node query param required"});return}await en(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let m=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(y=>({name:y.name,url:y.url,token:y.token}))],v={flag:!1},w=[];t.on("close",()=>{v.flag=!0;for(let y of w)try{y.abort()}catch{}});let T=setInterval(()=>{if(!v.flag)try{e.write(`: ping
19261
19295
 
19262
19296
  `)}catch{}},15e3);t.on("close",()=>clearInterval(T));for(let y of x)(async()=>{let I={Accept:"text/event-stream"};y.token&&(I.Authorization=`Bearer ${y.token}`);let C=new AbortController;w.push(C);try{let E=await fetch(`${y.url.replace(/\/+$/,"")}/events${m?`?${m}`:""}`,{headers:I,signal:C.signal});if(!E.ok||!E.body)return;let $=E.body.getReader(),L=new TextDecoder,j="";for(;!v.flag;){let{done:W,value:q}=await $.read();if(W)break;j+=L.decode(q,{stream:!0});let G;for(;(G=j.indexOf(`
19263
19297
 
19264
19298
  `))>=0;){let ie=j.slice(0,G);if(j=j.slice(G+2),v.flag)break;try{e.write(ie+`
19265
19299
 
19266
- `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(y.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of w)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,m),$=v?E.map(L=>Nm(L)):E;b(e,200,{runs:$})}catch(d){b(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){b(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let w={};v.token&&(w.Authorization=`Bearer ${v.token}`);let T=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:w});if(T.ok){b(e,200,await T.json());return}}catch{}b(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,v)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Us(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let w=ia(m);if(!w)return!0;let T=new F().verify(w);if(!T)return b(x,401,{error:"invalid or revoked token"}),!1;for(let y of v)if(!ke(T,y))return b(x,403,{error:`token missing scope: ${y}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,m]=S,x=decodeURIComponent(m),v=a.boards.find(C=>C.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}let T=await ue(t),y=v.columns.find(C=>C.id===T.to),I=v.columns.find(C=>C.id===T.from);if(!y){b(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await Om(w,x,I,y),Va({actor:Ya(t),action:"move",boardId:d,itemId:x,payload:{from:T.from,to:T.to}}),b(e,200,{ok:!0})}catch(C){b(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(T=>T.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:y}=await jm(v,w,n.searchParams);b(e,200,{columns:T,totals:y});return}if(o==="GET"&&x){try{let T=typeof w.getItem=="function"?await w.getItem(x):null;if(!T){b(e,404,{error:"not found"});return}b(e,200,T)}catch(T){b(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await ue(t);try{let y=typeof w.updateItem=="function"?await w.updateItem(x,T):null;if(!y){b(e,501,{error:"update unsupported"});return}Va({actor:Ya(t),action:"update",boardId:d,itemId:x,payload:T}),b(e,200,y)}catch(y){b(e,502,{error:y.message})}return}if(o==="POST"&&!x){let T=await ue(t);if(!T.title){b(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){b(e,400,{error:`source ${w.type} does not support create`});return}try{let y=await w.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});Va({actor:Ya(t),action:"create",boardId:d,itemId:y.id,payload:{title:T.title}}),b(e,201,y)}catch(y){b(e,502,{error:y.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}b(e,404,{error:"not found",path:r})}async function jm(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let d of t.columns)k[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&k[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=nn(d,S);if(!m)continue;let x=k[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(k))k[d]=k[d].filter(m=>m.assignee===i);for(let d of Object.keys(k))k[d].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([d,m])=>[d,m.length]));return{columns:k,totals:g}}async function Om(t,e,a,n){let r=rn(a,n),o=t;r.closeIssue&&typeof o.setState=="function"?await o.setState(e,"close"):r.reopen&&typeof o.setState=="function"&&await o.setState(e,"reopen"),(r.addLabels?.length||r.removeLabels?.length)&&typeof o.transitionMany=="function"?await o.transitionMany(e,r.addLabels||[],r.removeLabels||[]):r.addLabels?.length&&t.transition&&await t.transition(e,r.addLabels[0],r.removeLabels?.[0])}function Nm(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 Dm(t,e){if(t.source.type==="gitlab"){let a=e.channels.gitlab;if(!a?.token)throw new Error("channels.gitlab.token is required for gitlab boards");let n={};for(let r of a.agentMappings)r.gitlabUsernames.length&&(n[r.agentId]=r.gitlabUsernames);return new Qn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Va(t){try{let e=at(process.cwd(),".agentx");pl(e)||Im(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
19267
- `;Cm(at(e,"board-audit.jsonl"),a)}catch{}}function Ya(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Hm=2e3;async function Bm(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(),Hm),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let w=v.ok?await v.json().catch(()=>{}):void 0;return{ok:w!==void 0,json:async()=>w}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,k,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let g=await f.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(k&&k.ok){let g=await k.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Cn.routines))}if(h&&h.ok){let g=await h.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Xm(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Vt=null;function zm(t){if(Vt)return Vt;let e=at(process.cwd(),".agentx/wiki");return Vt=Ar({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Vt}async function Qt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function qm(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function we(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await Qt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var Fm=3e3,Um=6e3,Wm=5*6e4,Za=new Map,Yt=new Map;function We(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Yt.get(a);if(n)return n;let r=(async()=>{let o=await we(t,AbortSignal.timeout(Fm)),s=await Promise.all(o.map(async i=>{let l=await Bm(i.url,i.token,AbortSignal.timeout(Um),e);return e?l:Gm(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Yt.delete(a));return Yt.set(a,r),r}function Gm(t,e,a=Date.now()){if(e.reachable&&!e.error)return Za.set(t,{node:e,at:a}),e;let n=Za.get(t);return!n||a-n.at>Wm?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Gy(){Za.clear(),Yt.clear()}function Xm(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 Km(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}
19300
+ `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),m=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",w=a.workflowRuns.list({limit:m,workflowId:x}),T=`?limit=${m}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,y=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(L=>({url:L.url,token:L.token}))],I=await Promise.all(y.map(async L=>{let j={};L.token&&(j.Authorization=`Bearer ${L.token}`);try{let W=new AbortController,q=setTimeout(()=>W.abort(),5e3);try{let G=await fetch(`${L.url.replace(/\/+$/,"")}/api/workflows/runs${T}`,{headers:j,signal:W.signal});if(!G.ok)return[];let ie=await G.json();return Array.isArray(ie.runs)?ie.runs:[]}finally{clearTimeout(q)}}catch{return[]}})),C=new Map;for(let L of w)C.set(L.id,L);for(let L of I)for(let j of L)C.set(j.id,j);let E=Array.from(C.values()).sort((L,j)=>L.updatedAt<j.updatedAt?1:-1).slice(0,m),$=v?E.map(L=>Hm(L)):E;b(e,200,{runs:$})}catch(d){b(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let f=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(f){let d=decodeURIComponent(f[1]),m=a.workflowRuns.get(d);if(m){b(e,200,{run:m});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let w={};v.token&&(w.Authorization=`Bearer ${v.token}`);let T=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:w});if(T.ok){b(e,200,await T.json());return}}catch{}b(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let m=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${m}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));b(e,x.status,v)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await ue(t).catch(()=>({})),m={"Content-Type":"application/json"};a.config.dashboard.token&&(m.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:m,body:JSON.stringify(d??{})}),w=await v.json().catch(()=>({error:`HTTP ${v.status}`}));b(e,v.status,w)}catch(d){b(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&Xs(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(m,x,v)=>{if(a.token)return!0;let w=ia(m);if(!w)return!0;let T=new F().verify(w);if(!T)return b(x,401,{error:"invalid or revoked token"}),!1;for(let y of v)if(!ke(T,y))return b(x,403,{error:`token missing scope: ${y}`,scopes:T.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){b(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let k=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(k&&o==="GET"){let d=a.sources.get(k[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMembers=="function"?await d.listMembers():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){b(e,404,{error:"unknown board"});return}try{let m=typeof d.listMilestones=="function"?await d.listMilestones():[];b(e,200,m)}catch(m){b(e,502,{error:m.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,m]=S,x=decodeURIComponent(m),v=a.boards.find(C=>C.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}let T=await ue(t),y=v.columns.find(C=>C.id===T.to),I=v.columns.find(C=>C.id===T.from);if(!y){b(e,400,{error:`unknown 'to' column: ${T.to}`});return}try{await Dm(w,x,I,y),Va({actor:Ya(t),action:"move",boardId:d,itemId:x,payload:{from:T.from,to:T.to}}),b(e,200,{ok:!0})}catch(C){b(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,m]=g,x=m?decodeURIComponent(m):void 0,v=a.boards.find(T=>T.id===d);if(!v){b(e,404,{error:`unknown board: ${d}`});return}let w=a.sources.get(d);if(!w){b(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:T,totals:y}=await Nm(v,w,n.searchParams);b(e,200,{columns:T,totals:y});return}if(o==="GET"&&x){try{let T=typeof w.getItem=="function"?await w.getItem(x):null;if(!T){b(e,404,{error:"not found"});return}b(e,200,T)}catch(T){b(e,502,{error:T.message})}return}if(o==="PATCH"&&x){let T=await ue(t);try{let y=typeof w.updateItem=="function"?await w.updateItem(x,T):null;if(!y){b(e,501,{error:"update unsupported"});return}Va({actor:Ya(t),action:"update",boardId:d,itemId:x,payload:T}),b(e,200,y)}catch(y){b(e,502,{error:y.message})}return}if(o==="POST"&&!x){let T=await ue(t);if(!T.title){b(e,400,{error:"title required"});return}if(!w.capabilities.create||!w.create){b(e,400,{error:`source ${w.type} does not support create`});return}try{let y=await w.create({title:T.title,description:T.description,labels:T.labels,assigneeUsernames:T.assigneeUsernames,milestoneTitle:T.milestoneTitle,projectHint:T.projectHint});Va({actor:Ya(t),action:"create",boardId:d,itemId:y.id,payload:{title:T.title}}),b(e,201,y)}catch(y){b(e,502,{error:y.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}b(e,404,{error:"not found",path:r})}async function Nm(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let m of t.columns)d[m.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(m=>[m.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),f=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],k={};for(let d of t.columns)k[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&k[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of f){let m=nn(d,S);if(!m)continue;let x=k[m];x&&x.push({...d,stage:m})}if(i)for(let d of Object.keys(k))k[d]=k[d].filter(m=>m.assignee===i);for(let d of Object.keys(k))k[d].sort((m,x)=>{let v=(m.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(m.updatedAt||"")});let g=Object.fromEntries(Object.entries(k).map(([d,m])=>[d,m.length]));return{columns:k,totals:g}}async function Dm(t,e,a,n){let r=rn(a,n),o=t;r.closeIssue&&typeof o.setState=="function"?await o.setState(e,"close"):r.reopen&&typeof o.setState=="function"&&await o.setState(e,"reopen"),(r.addLabels?.length||r.removeLabels?.length)&&typeof o.transitionMany=="function"?await o.transitionMany(e,r.addLabels||[],r.removeLabels||[]):r.addLabels?.length&&t.transition&&await t.transition(e,r.addLabels[0],r.removeLabels?.[0])}function Hm(t){return{id:t.id,workflowId:t.workflowId,workflowVersion:t.workflowVersion,homeNode:t.homeNode,status:t.status,pending:t.pending,entityRef:t.entityRef,history:(t.history||[]).slice(-5),parentRunId:t.parentRunId,parentNodeId:t.parentNodeId,rootRunId:t.rootRunId,depth:t.depth,createdAt:t.createdAt,updatedAt:t.updatedAt}}function Bm(t,e){if(t.source.type==="gitlab"){let a=e.channels.gitlab;if(!a?.token)throw new Error("channels.gitlab.token is required for gitlab boards");let n={};for(let r of a.agentMappings)r.gitlabUsernames.length&&(n[r.agentId]=r.gitlabUsernames);return new Qn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Va(t){try{let e=at(process.cwd(),".agentx");fl(e)||Lm(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
19301
+ `;Mm(at(e,"board-audit.jsonl"),a)}catch{}}function Ya(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var zm=2e3;async function qm(t,e,a,n){let r={};e&&(r.Authorization=`Bearer ${e}`);let o={id:t,name:t,url:t,reachable:!1,agents:[]};try{let s=n?`?date=${encodeURIComponent(n.date)}&timezone=${encodeURIComponent(n.timezone)}`:"",i=g=>{let d=new AbortController,m=setTimeout(()=>d.abort(),zm),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let w=v.ok?await v.json().catch(()=>{}):void 0;return{ok:w!==void 0,json:async()=>w}}).catch(()=>null).finally(()=>{clearTimeout(m),a?.removeEventListener("abort",x)})},[l,c,p,u,f,h,k,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(f&&f.ok){let g=await f.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(k&&k.ok){let g=await k.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Cn.routines))}if(h&&h.ok){let g=await h.json().catch(()=>null);g?.active&&g.kind==="lesson"&&(o.lesson={agentId:g.agentId??null,mode:String(g.mode||"teach"),goal:String(g.goal||""),step:Number(g.step)||0,saying:String(g.saying||""),startedAt:String(g.startedAt||"")})}if(_&&_.ok){let g=await _.json().catch(()=>null);g&&Array.isArray(g.sessions)&&Jm(o,g.sessions,g.saved??{})}o.reachable=!0,o._peers=Array.isArray(p?.ok?await p.json():null)?o._peers:void 0}catch(s){o.error=s.message||String(s)}return o}var Vt=null;function Fm(t){if(Vt)return Vt;let e=at(process.cwd(),".agentx/wiki");return Vt=Ar({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Vt}async function Qt(t,e,a){try{let n={};e&&(n.Authorization=`Bearer ${e}`);let r=await fetch(t+"/mesh",{headers:n,signal:a});return r.ok?(await r.json()).filter(s=>s&&s.peerUrl).map(s=>({url:String(s.peerUrl).replace(/\/+$/,""),name:s.peer||s.peerUrl})):[]}catch{return[]}}async function Um(t,e,a){let n=Math.max(1,Math.min(200,Number(a.get("limit"))||50)),r=e.dashboard.daemonUrl.replace(/\/+$/,""),o=process.env.MESH_TOKEN||U(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){b(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();b(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){b(t,502,{error:s.message||"daemon unreachable"})}}async function we(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=U(a,n),o=new Map;o.set(n,{name:"primary",url:n,token:r});for(let i of a.daemons){let l=i.url.replace(/\/+$/,"");o.has(l)||o.set(l,{name:i.name,url:l,token:U(a,l)})}let s=await Qt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:U(a,i.url)});return[...o.values()]}var Wm=3e3,Gm=6e3,Xm=5*6e4,Za=new Map,Yt=new Map;function We(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Yt.get(a);if(n)return n;let r=(async()=>{let o=await we(t,AbortSignal.timeout(Wm)),s=await Promise.all(o.map(async i=>{let l=await qm(i.url,i.token,AbortSignal.timeout(Gm),e);return e?l:Km(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Yt.delete(a));return Yt.set(a,r),r}function Km(t,e,a=Date.now()){if(e.reachable&&!e.error)return Za.set(t,{node:e,at:a}),e;let n=Za.get(t);return!n||a-n.at>Xm?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Qy(){Za.clear(),Yt.clear()}function Jm(t,e,a){let n=s=>s?s.replace(/\/+$/,"").split("/").pop()||s:"",r=e.map(s=>({session:String(s.sessionId).slice(0,8),project:n(s.cwd),agentIds:Array.isArray(s.agentIds)?s.agentIds:[],mode:String(s.mode||"notify"),lastSeenAt:Number(s.lastSeenAt)||0,pending:Number(s.pending)||0})),o=new Set(e.map(s=>s.sessionId));for(let[s,i]of Object.entries(a))o.has(s)||!Array.isArray(i.agentIds)||i.agentIds.length===0||r.push({session:s.slice(0,8),project:n(i.cwd),agentIds:i.agentIds,mode:String(i.mode||"notify"),lastSeenAt:Number(i.savedAt)||0,pending:0,waiting:!0});t.attachSessions=r;for(let s of t.agents){let i=r.find(l=>l.agentIds.includes(s.id)&&!l.waiting)??r.find(l=>l.agentIds.includes(s.id));i&&(s.attached={session:i.session,project:i.project,mode:i.mode,lastSeenAt:i.lastSeenAt,waiting:i.waiting})}}function Vm(t,e,a){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let n=!1,r=(l,c)=>{n||e.write(`event: ${l}
19268
19302
  data: ${JSON.stringify(c)}
19269
19303
 
19270
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await We(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function Jm(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await Qt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of k)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){b(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:_}=await f.read();if(_)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Vm(t,e,a){let n=ia(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ke(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Ym(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){b(e,502,{error:c.message||"upstream call failed"})}}async function Qm(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await Qt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function Zm(t,e,a,n,r,o){await en(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function en(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await ul(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function ul(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await Qt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function ml(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=Rn(e.keysFile);return{store:()=>{let r=Ue();return r?new or(r):null},publicKey:()=>$n(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function fl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>We(t,n),async nodePost(n,r,o){let s=await ul(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=xt({root:process.cwd()}).items.map(cl)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=nt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(cl)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=_e(),p=await vt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=nt(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}var Qa=null;function ll(t){return Qa?.days!==t&&(Qa={days:t,store:new ct(process.cwd(),Date.now,t)}),Qa.store}function hl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=fl(t);return{store:()=>{let r=Ue();return r?new tt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:dn(process.cwd())??void 0},snapshot:()=>We(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s),tokenFor:r=>U(t.dashboard,r.replace(/\/+$/,"")),...ef(t,e,a)}}function ef(t,e,a){let n=ml(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}
19271
- ${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function tf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=hl(t);return new Jt({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await We(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:oi(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function af(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ue();return a?new tt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function nf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function cl(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var rf=`
19304
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await We(a);r("snapshot",l)}catch(l){r("error",{message:l.message})}finally{o=!1}}};s();let i=setInterval(s,2e3);t.on("close",()=>{n=!0,clearInterval(i),e.end()})}async function Ym(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let k of a.config.dashboard.daemons)i.add(k.url.replace(/\/+$/,""));try{let k=await Qt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of k)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(k){b(e,502,{error:k.message||"upstream connect failed"});return}if(!u.ok||!u.body){b(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let f=u.body.getReader();(async()=>{try{for(;;){let{value:k,done:_}=await f.read();if(_)break;k&&e.write(k)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function Qm(t,e,a){let n=ia(t);if(!n)return b(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new F().verify(n);if(!r)return b(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ke(r,o))return b(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function Zm(t,e,a,n){let r=a.agents?.[n];if(!r){b(e,404,{error:"unknown agent"});return}if(r.access!=="public"){b(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await ue(t)}catch{b(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){b(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){b(e,502,{error:c.message||"upstream call failed"})}}async function ef(t,e,a,n,r,o){let s=a.replace(/\/+$/,""),i=new Set;i.add(e.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let u of e.config.dashboard.daemons)i.add(u.url.replace(/\/+$/,""));try{let u=await Qt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let f of u)i.add(f.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){b(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=U(e.config.dashboard,s),c={Accept:"application/json"};l&&(c.Authorization=`Bearer ${l}`);let p=r?`/agents/${encodeURIComponent(n)}/tasks/${encodeURIComponent(r)}`:`/agents/${encodeURIComponent(n)}/tasks?limit=${encodeURIComponent(o)}`;try{let u=await fetch(`${s}${p}`,{headers:c}),f=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(f)}catch(u){b(t,502,{error:u.message||"upstream fetch failed"})}}async function tf(t,e,a,n,r,o){await en(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function en(t,e,a,n,r){let o={};try{o=await ue(t)??{}}catch{}let s=await hl(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function hl(t,e,a,n){let r=(c,p)=>({status:c,text:JSON.stringify(p),contentType:"application/json"}),o=e.replace(/\/+$/,""),s=new Set;s.add(t.dashboard.daemonUrl.replace(/\/+$/,""));for(let c of t.dashboard.daemons)s.add(c.url.replace(/\/+$/,""));try{let c=await Qt(t.dashboard.daemonUrl.replace(/\/+$/,""),t.dashboard.token);for(let p of c)s.add(p.url.replace(/\/+$/,""))}catch{}if(!s.has(o))return r(403,{error:"node not in dashboard allowlist",target:o});let i=U(t.dashboard,o),l={"Content-Type":"application/json",Accept:"application/json"};i&&(l.Authorization=`Bearer ${i}`);try{let c=await fetch(`${o}${a}`,{method:"POST",headers:l,body:JSON.stringify(n??{})});return{status:c.status,text:await c.text(),contentType:c.headers.get("content-type")||"application/json; charset=utf-8"}}catch(c){return r(502,{error:c.message||"upstream fetch failed"})}}function gl(t){let e=t.channels.push,a=r=>({store:()=>null,publicKey:()=>null,keepRecent:0,allowedHosts:[],reason:r});if(!e.enabled)return a("Notifications are off. On the computer, run: agentx notifications push --enable");if(e.relayTo)return a(`Notifications are set up on ${e.relayTo}. Pair this phone with that computer instead.`);let n=Rn(e.keysFile);return{store:()=>{let r=Ue();return r?new or(r):null},publicKey:()=>$n(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function xl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>We(t,n),async nodePost(n,r,o){let s=await hl(t,n,r,o);return{status:s.status,body:a(s.text)}},async approvals(){let n={node:e,nodeName:t.node?.name||"this computer",items:[]};try{n.items=xt({root:process.cwd()}).items.map(ul)}catch(o){n.error=o.message}let r=await Promise.all(t.dashboard.daemons.map(async o=>{let s={node:o.url.replace(/\/+$/,""),nodeName:o.name,items:[]},i=nt(o.url,t);if(!i)return s;try{let l=await fetch(`${i.url}/api/admin/approvals`,{headers:{"X-Agentx-Peer":"primary",...i.token?{Authorization:`Bearer ${i.token}`}:{}},signal:AbortSignal.timeout(4e3)});if(!l.ok)return s.error=`HTTP ${l.status}`,s;let c=await l.json();s.items=(c.items??[]).map(ul)}catch(l){s.error=l.message||"unreachable"}return s}));return[n,...r]},async decide(n,r,o,s){let i=n.replace(/\/+$/,"");if(i===e){let c=_e(),p=await vt({root:process.cwd()},r,o,{laterHours:c.laterHours,by:s});return p.ok?{status:200,body:{ok:!0,message:p.message}}:{status:409,body:{error:p.error}}}let l=nt(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}var Qa=null;function pl(t){return Qa?.days!==t&&(Qa={days:t,store:new ct(process.cwd(),Date.now,t)}),Qa.store}function vl(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=U(t.dashboard,e),n=xl(t);return{store:()=>{let r=Ue();return r?new tt(r):null},daemon:{url:e,token:a,name:t.node?.name,operatorKey:dn(process.cwd())??void 0},snapshot:()=>We(t),meshPeers:async()=>{let r=await fetch(e+"/mesh",{headers:a?{Authorization:`Bearer ${a}`}:{},signal:AbortSignal.timeout(3e3)});return r.ok?await r.json():[]},nodePost:(r,o,s)=>n.nodePost(r,o,s),tokenFor:r=>U(t.dashboard,r.replace(/\/+$/,"")),...af(t,e,a)}}function af(t,e,a){let n=gl(t);return{finishAlerts:r=>{let o=n.store();return!!o&&o.chatFinishOn(r)&&o.list(r).length>0},notifyFinish:async r=>{try{let o=await fetch(e+"/channel/send",{method:"POST",headers:{"Content-Type":"application/json",...a?{Authorization:`Bearer ${a}`}:{}},body:JSON.stringify({channel:"push",chatId:r.deviceId,text:`${r.title}
19305
+ ${r.body}`,buttons:[{label:"Open",url:r.url}]}),signal:AbortSignal.timeout(1e4)});o.ok||console.error(`[app] finish notification not sent: HTTP ${o.status} ${(await o.text()).slice(0,160)}`)}catch(o){console.error(`[app] finish notification not sent: ${o?.message||o}`)}}}}function nf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>U(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=vl(t);return new Jt({recent:async(o,s)=>{let i=new URLSearchParams({kind:"delegation",limit:String(s)});o&&i.set("since",o);let l=await fetch(`${e}/events/recent?${i}`,{headers:n(e),signal:AbortSignal.timeout(5e3)});if(!l.ok)throw new Error(`the daemon answered ${l.status}`);let c=await l.json();return{events:Array.isArray(c.events)?c.events:[],gap:c.gap===!0}},nodeUrl:async o=>{let i=(await We(t)).nodes.find(l=>l.name===o||l.id===o);return i?.url?i.url.replace(/\/+$/,""):null},conversationUrl:async o=>{if(o.node==="local")return e;let s=(await r.meshPeers().catch(()=>[])).find(i=>i.peer===o.node);return s?s.peerUrl.replace(/\/+$/,""):null},fetchReply:async(o,s)=>{let i=await fetch(`${o}/a2a/delegations/${encodeURIComponent(s)}/reply`,{headers:n(o),signal:AbortSignal.timeout(5e3)});if(i.status===404)return null;if(!i.ok)throw new Error(`the node answered ${i.status}`);return await i.json()},store:r.store,presence:li(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function rf(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ue();return a?new tt(a):null},daemon:{url:e,token:U(t.dashboard,e)}}}function of(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:U(t.dashboard,e)},nodeName:t.node.name}}function ul(t){return{key:t.key,title:t.title,ask:t.ask,recommend:t.recommend,yes:t.yes,no:t.no,raisedBy:t.raised_by,expires:t.expires}}var sf=`
19272
19306
  You are helping draft a new GitLab issue. Follow these conventions strictly.
19273
19307
 
19274
19308
  Title pattern:
@@ -19300,10 +19334,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
19300
19334
  Shape:
19301
19335
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
19302
19336
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
19303
- `;async function of(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):
19337
+ `;async function lf(t,e){let a=(e?.rough||"").toString().trim();if(!a)throw new Error("rough description required");let n=e?.agent||t.dashboard.draftAgent;if(!n)throw new Error("no draft agent configured (set dashboard.draftAgent or pass agent in body)");let r=e?.context||{},o=["Rough description from the user:",'"""',a,'"""',"",`Board: ${r.boardName||"(unspecified)"}`,r.primaryLabel?`Primary board label (include in labels): ${r.primaryLabel}`:"",r.columnLabel?`Target column label (include in labels): ${r.columnLabel}`:"",r.project?`GitLab project: ${r.project}`:"",r.knownLabels?.length?`Known labels in this project (prefer picking from these when they fit):
19304
19338
  - ${r.knownLabels.slice(0,60).join(`
19305
19339
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
19306
- `),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:rf}})});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=sf(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 sf(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 lf(t){let e=Rm(Lm(import.meta.url));return at(e,t)}async function cf(t){return Mm(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function gl(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:gl(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 df(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await zt(await xl(r,a.config)))}async function xl(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ma(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=nt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return cs(n)}async function pf(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=f.find(k=>pl(k));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:f}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
19340
+ `),s=t.dashboard.daemonUrl.replace(/\/+$/,"")+"/task",i={"Content-Type":"application/json"};t.dashboard.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);let l=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({agent:n,message:o,context:{channel:"a2a",sender:"board-dashboard",systemPrompt:sf}})});if(!l.ok)throw new Error(`daemon /task HTTP ${l.status}: ${await l.text().catch(()=>"")}`);let c=await l.json();if(c.error)throw new Error(String(c.error));let p=(c.content||"").toString(),u=cf(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let f=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!f.includes(r.primaryLabel)&&f.unshift(r.primaryLabel),r.columnLabel&&!f.includes(r.columnLabel)&&f.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:f,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function cf(t){if(!t)return null;try{return JSON.parse(t)}catch{}let e=t.match(/```(?:json)?\s*([\s\S]*?)```/);if(e)try{return JSON.parse(e[1])}catch{}let a=t.indexOf("{");if(a===-1)return null;let n=0;for(let r=a;r<t.length;r++){let o=t[r];if(o==="{")n++;else if(o==="}"&&(n--,n===0))try{return JSON.parse(t.slice(a,r+1))}catch{return null}}return null}function df(t){let e=Pm($m(import.meta.url));return at(e,t)}async function pf(t){return Rm(t)}function b(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function ue(t){return new Promise((e,a)=>{let n=[];t.on("data",r=>n.push(r)),t.on("end",()=>{try{let r=Buffer.concat(n).toString("utf-8");e(r?JSON.parse(r):{})}catch(r){a(r)}}),t.on("error",a)})}function bl(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function D(t,e){let a=e||t,n={id:"primary",name:a.node?.name||"this daemon",dashboardUrl:"",primary:!0},r=(a.dashboard?.daemons||[]).map(s=>({id:s.url.replace(/\/+$/,""),name:s.name,dashboardUrl:bl(s),tokenScope:s.dashboardToken||s.token?"proxy-ready":void 0})),o=r.length>0?[{id:"fleet",name:"Fleet (all peers)",dashboardUrl:"",tokenScope:"merged across nodes"}]:[];return[n,...r,...o]}async function uf(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;b(e,200,await zt(await yl(r,a.config)))}async function yl(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=Ma(t);r&&n.push({nodeId:a,snap:r});let o=(e.dashboard?.daemons||[]).filter(i=>i.url),s=await Promise.all(o.map(async i=>{let l=nt(i.url.replace(/\/+$/,""),e);if(!l)return null;try{let c=new AbortController,p=setTimeout(()=>c.abort(),8e3);try{let u=await fetch(`${l.url}/api/admin/activity-graph?hours=${t}`,{headers:{Accept:"application/json","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},signal:c.signal});return u.ok?{nodeId:i.name||i.url,snap:await u.json()}:null}finally{clearTimeout(p)}}catch{return null}}));for(let i of s)i&&n.push(i);return us(n)}async function mf(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",f=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=f.find(k=>fl(k));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:f}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
19307
19341
 
19308
19342
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let f;for(;(f=i.indexOf(`
19309
19343
  `))>=0;){let h=i.slice(0,f).replace(/\r$/,"");i=i.slice(f+1);try{e.write(`event: line
@@ -19311,5 +19345,5 @@ data: ${h.replace(/\n/g," ")}
19311
19345
 
19312
19346
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
19313
19347
 
19314
- `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function dl(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function nt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:gl(n),token:n.dashboardToken||n.token}:null}export{Xm as applyAttachSessions,Bm as fetchDaemonAgents,Pm as handleBoardRequest,Gy as resetLiveCaches,we as resolveNodeTargets,Wy as startBoardDashboard,Gm as withLastGood};
19315
- //# sourceMappingURL=board-dashboard-PVRIWBSD.js.map
19348
+ `)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function ml(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){b(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function nt(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:bl(n),token:n.dashboardToken||n.token}:null}export{Jm as applyAttachSessions,qm as fetchDaemonAgents,Om as handleBoardRequest,Qy as resetLiveCaches,we as resolveNodeTargets,Yy as startBoardDashboard,Km as withLastGood};
19349
+ //# sourceMappingURL=board-dashboard-MHMYOBKA.js.map