agentix-cli 0.79.2 → 0.79.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 gn}from"./chunk-2NYP4OQU.js";import{a as kn}from"./chunk-CPXZWVKN.js";import{a as le,b as hn}from"./chunk-JWDJMFU6.js";import{a as A,b as _n,c as En,d as Sn,e as Tn,h as An,i as Re,j as Cn,k as In,l as Ln,m as Rn,n as $n}from"./chunk-LPDQ2KK4.js";import{a as Mn}from"./chunk-Z3IP66SL.js";import{a as xn,b as U,c as vn,d as L,i as lt,j as ct,k as ne,l as W,m as dt,n as bn,o as yn,p as wn}from"./chunk-O5U5NVLR.js";import{$a as st,Ca as an,Ea as nn,Fa as rn,Ga as on,M as tt,N as at,O as Va,Oa as sn,P as Ya,Qa as Me,Va as cn,W as z,X as Qa,Xa as Le,Y as Za,Ya as nt,Za as rt,_a as ot,a as Fa,ab as dn,bb as pn,c as Ze,cb as un,d as Dt,db as it,e as qa,fb as mn,i as et,ib as fn,l as He,n as Ua,p as ae,q as ye,r as Xa,s as Ht}from"./chunk-H7SL56KH.js";import{g as Ba,h as za}from"./chunk-R7WZUUYO.js";import{p as Wa,t as Ga}from"./chunk-S2GAEH2F.js";import{c as ln}from"./chunk-7XB2CVC3.js";import{a as O,b as en,c as tn}from"./chunk-CL53UVOF.js";import"./chunk-2ZQ42Q4L.js";import"./chunk-AQASR6KR.js";import{b as Ka,c as Ja}from"./chunk-2D3RYIDU.js";import{a as Pa,f as ja,g as Ot,h as Nt,l as Oa,m as Na,n as Da,u as Ye,v as Qe,w as ie,x as Ha}from"./chunk-2ACZWM7F.js";import"./chunk-WP6KLXTP.js";import{a as Ie}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-WVYOXM45.js";import"./chunk-2AXFYDWF.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-6SJTBTDG.js";import"./chunk-HTKSZZXK.js";import"./chunk-M4XUZA3O.js";import"./chunk-RD5EKHGZ.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 $a}from"./chunk-WNI2P7S6.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-7QRCAHPX.js";import"./chunk-FX3D7YON.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{E as te,H as jt,a as La,b as Ra,c as Qs,v as Ve,w as Zs}from"./chunk-YKPISR5J.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Bt(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 Pn(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Bt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var re={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},we=(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>",pt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+we(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function jn(t={}){return L({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
1
+ import{a as vn}from"./chunk-2NYP4OQU.js";import{a as En}from"./chunk-CPXZWVKN.js";import{a as ce,b as xn}from"./chunk-JWDJMFU6.js";import{a as A,b as Sn,c as Tn,d as An,e as Cn,h as In,i as we,j as Mn,k as Ln,l as $n,m as Pn,n as jn}from"./chunk-LPDQ2KK4.js";import{a as Rn}from"./chunk-Z3IP66SL.js";import{a as bn,b as U,c as yn,d as L,i as lt,j as ct,k as ne,l as W,m as dt,n as wn,o as kn,p as _n}from"./chunk-O5U5NVLR.js";import{$ as tn,$a as nt,Fa as rn,Ha as on,Ia as sn,Ja as ln,M as tt,N as at,Q as Ya,R as Qa,Ra as cn,S as Za,Ta as Le,Ya as pn,Z as z,_ as en,_a as Re,ab as rt,bb as ot,c as qa,cb as st,db as un,e as Ze,eb as mn,f as Dt,fb as fn,g as Ua,gb as it,ib as hn,k as et,lb as gn,n as He,p as Wa,r as ae,s as ye,t as Ka,u as Ht}from"./chunk-5RRORS5S.js";import{g as za,h as Fa}from"./chunk-R7WZUUYO.js";import{p as Ga,t as Xa}from"./chunk-S2GAEH2F.js";import{c as dn}from"./chunk-7XB2CVC3.js";import{a as O,b as an,c as nn}from"./chunk-CL53UVOF.js";import"./chunk-2ZQ42Q4L.js";import"./chunk-AQASR6KR.js";import{b as Ja,c as Va}from"./chunk-2D3RYIDU.js";import{a as ja,f as Oa,g as Ot,h as Nt,l as Na,m as Da,n as Ha,u as Ye,v as Qe,w as le,x as Ba}from"./chunk-2ACZWM7F.js";import"./chunk-WP6KLXTP.js";import{a as Me}from"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-WVYOXM45.js";import"./chunk-2AXFYDWF.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-6SJTBTDG.js";import"./chunk-HTKSZZXK.js";import"./chunk-M4XUZA3O.js";import"./chunk-RD5EKHGZ.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 Pa}from"./chunk-WNI2P7S6.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-7QRCAHPX.js";import"./chunk-FX3D7YON.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{E as te,H as jt,a as Ra,b as $a,c as Zs,v as Ve,w as ei}from"./chunk-YKPISR5J.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Bt(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 On(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Bt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var re={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},ke=(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>",pt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+ke(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function Nn(t={}){return L({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
2
2
 
3
3
  <div class="bf-head">
4
4
  <div>
@@ -7,8 +7,8 @@ import{a as gn}from"./chunk-2NYP4OQU.js";import{a as kn}from"./chunk-CPXZWVKN.js
7
7
  </div>
8
8
  <div class="bf-sync">
9
9
  <span class="bf-sync__t" id="synced">Gathering&hellip;</span>
10
- <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${we(re.pulse,13)} Activity</a>
11
- <button class="ax-btn" id="refresh" title="Refresh now">${we(re.refresh)} Refresh</button>
10
+ <a class="ax-btn ax-btn--sm" href="/activity" title="What ran, and when">${ke(re.pulse,13)} Activity</a>
11
+ <button class="ax-btn" id="refresh" title="Refresh now">${ke(re.refresh)} Refresh</button>
12
12
  </div>
13
13
  </div>
14
14
 
@@ -38,7 +38,7 @@ import{a as gn}from"./chunk-2NYP4OQU.js";import{a as kn}from"./chunk-CPXZWVKN.js
38
38
 
39
39
  ${pt(re.file,"Session briefings","brief-count")}
40
40
  <div class="bf-toolbar">
41
- <div class="bf-search">${we(re.search)}
41
+ <div class="bf-search">${ke(re.search)}
42
42
  <input id="search" type="search" placeholder="Search sessions&hellip;" aria-label="Search sessions">
43
43
  </div>
44
44
  <div class="bf-filters" id="filters" role="group" aria-label="Filter briefings"></div>
@@ -46,15 +46,15 @@ ${pt(re.file,"Session briefings","brief-count")}
46
46
  <div id="reviews" class="bf-col"></div>
47
47
 
48
48
  <section class="ax-panel bf-connect">
49
- <div class="bf-connect__head">${we(re.plug,17)}<h2>Connect a CLI session</h2>
49
+ <div class="bf-connect__head">${ke(re.plug,17)}<h2>Connect a CLI session</h2>
50
50
  <span class="bf-connect__note">Daemon-owned processes only</span></div>
51
51
  <div class="bf-discover">
52
52
  <div class="ax-field"><label for="node">Node</label><select id="node"></select></div>
53
- <button class="ax-btn" id="discover">${we(re.search)} Discover CLIs</button>
53
+ <button class="ax-btn" id="discover">${ke(re.search)} Discover CLIs</button>
54
54
  </div>
55
55
  <div class="bf-cli" id="discovered"></div>
56
56
  <details class="bf-manual">
57
- <summary>${we(re.chev,12)} Register manually</summary>
57
+ <summary>${ke(re.chev,12)} Register manually</summary>
58
58
  <div class="bf-forms">
59
59
  <form id="register" class="bf-form">
60
60
  <div class="ax-sec-label"><h3>Register a session</h3></div>
@@ -85,7 +85,7 @@ ${pt(re.file,"Session briefings","brief-count")}
85
85
  </div>
86
86
  </details>
87
87
  </section>
88
- </div>`,css:ei,scripts:`<script>${U({decayOf:Bt,rankByDecay:Pn})}const ICON = ${JSON.stringify(re)};${ti}</script>`})}var ei=`
88
+ </div>`,css:ti,scripts:`<script>${U({decayOf:Bt,rankByDecay:On})}const ICON = ${JSON.stringify(re)};${ai}</script>`})}var ti=`
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
- }`,ti=String.raw`
364
+ }`,ai=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,22 +776,22 @@ 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 zt(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 Ft(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 On(t,e=[],a){let{bands:n,gaps:r}=zt(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,m=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>Ft(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 ai}from"crypto";import{readFileSync as ni,statSync as ri}from"fs";import{resolve as oi,dirname as si}from"path";import{fileURLToPath as ii}from"url";var Nn=new Map;function ut(t){let e=Nn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=si(ii(import.meta.url)),r=oi(n,"web",t),o=ri(r),s=o.size<8e6?ai("sha1").update(ni(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Nn.set(t,a),a}var ce={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"/>'},mt=(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>",li=[["agent","Agent",ce.bot],["client","Client",ce.user],["project","Project",ce.folder],["channel","Channel",ce.route],["node","Node",ce.mesh]],Dn={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 Hn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return L({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
779
+ })();`;function zt(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 Ft(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 Dn(t,e=[],a){let{bands:n,gaps:r}=zt(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,m=(l.startedAt-p.from)/u*100,h=Math.min(Math.max((l.durationMs||0)/u*100,1.2),100-m),w=s.get(l.laneKey)??{key:l.laneKey,label:l.laneLabel,sub:l.laneSub,tracks:1,runs:[]};w.runs.push({...l,band:c,track:0,left:m,width:h,marks:o.get(l.id)??[]}),s.set(l.laneKey,w)}let i=[...s.values()];for(let l of i)l.tracks=Math.max(...n.map((c,p)=>Ft(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 ni}from"crypto";import{readFileSync as ri,statSync as oi}from"fs";import{resolve as si,dirname as ii}from"path";import{fileURLToPath as li}from"url";var Hn=new Map;function ut(t){let e=Hn.get(t);if(e)return e;let a=`/assets/${t}`;try{let n=ii(li(import.meta.url)),r=si(n,"web",t),o=oi(r),s=o.size<8e6?ni("sha1").update(ri(r)).digest("hex").slice(0,10):`${o.size}-${Math.floor(o.mtimeMs)}`;a=`/assets/${t}?v=${s}`}catch{}return Hn.set(t,a),a}var de={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"/>'},mt=(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>",ci=[["agent","Agent",de.bot],["client","Client",de.user],["project","Project",de.folder],["channel","Channel",de.route],["node","Node",de.mesh]],Bn={timeline:"Every run on the mesh, from task traces. The axis breaks over silence &mdash; quiet stretches are labelled, not drawn.",map:"The fleet as a transit map: projects are lines, agents are stations, work in flight is a train. Live."};function zn(t={}){let e=t.view==="map"?"map":"timeline",a=e==="map";return L({title:"AgentX \xB7 Activity",activeTab:"activity",subtitle:"Activity",peers:t.peers,body:`<div class="ac">
780
780
 
781
781
  <div class="ac-head">
782
782
  <div>
783
783
  <div class="ac-kicker">Operations</div>
784
784
  <h1>What ran, where, and what it decided</h1>
785
- <p class="ac-sub" id="sub">${Dn[e]}</p>
785
+ <p class="ac-sub" id="sub">${Bn[e]}</p>
786
786
  </div>
787
787
  <div class="ac-tools">
788
788
  <div class="ac-seg" id="view" role="radiogroup" aria-label="View">
789
- ${[["timeline","Timeline",ce.timeline],["map","Map",ce.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${mt(o,13)}${r}</button>`).join("")}
789
+ ${[["timeline","Timeline",de.timeline],["map","Map",de.map]].map(([n,r,o])=>`<button type="button" role="radio" data-value="${n}" aria-checked="${n===e}"${n===e?' class="is-on"':""}>${mt(o,13)}${r}</button>`).join("")}
790
790
  </div>
791
791
  <div class="ac-seg" id="hours" role="radiogroup" aria-label="Window">
792
792
  ${[["6","6h"],["24","24h"],["72","3d"],["168","7d"]].map(([n,r],o)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${o===1}"${o===1?' class="is-on"':""}>${r}</button>`).join("")}
793
793
  </div>
794
- <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${mt(ce.refresh,13)} Refresh</button>
794
+ <button class="ax-btn ax-btn--sm" id="refresh"${a?" hidden":""}>${mt(de.refresh,13)} Refresh</button>
795
795
  </div>
796
796
  </div>
797
797
 
@@ -799,14 +799,14 @@ 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
- ${li.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${mt(o,13)}${r}</button>`).join("")}
802
+ ${ci.map(([n,r,o],s)=>`<button type="button" role="radio" data-value="${n}" aria-checked="${s===0}"${s===0?' class="is-on"':""}>${mt(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>
806
806
  <span class="ac-k"><i class="ac-d ac-d--warning"></i>warning</span>
807
807
  <span class="ac-k"><i class="ac-d ac-d--recommendation"></i>friction</span>
808
808
  <span class="ac-k"><i class="ac-d ac-d--later"></i>do later</span>
809
- <span class="ac-k">${mt(ce.x,11)}canceled</span>
809
+ <span class="ac-k">${mt(de.x,11)}canceled</span>
810
810
  </div>
811
811
  </div>
812
812
 
@@ -819,7 +819,7 @@ refresh();
819
819
  <div id="ax-fleet-root" data-hours="24" data-src="${ut("activity-graph.global.js")}"></div>
820
820
  </div>
821
821
 
822
- </div>`,css:ci,scripts:`<script>${U({computeBands:zt,packTracks:Ft,buildTimeline:On})}const ICON = ${JSON.stringify(ce)};const SUB = ${JSON.stringify(Dn)};${di}</script>`})}var ci=`
822
+ </div>`,css:di,scripts:`<script>${U({computeBands:zt,packTracks:Ft,buildTimeline:Dn})}const ICON = ${JSON.stringify(de)};const SUB = ${JSON.stringify(Bn)};${pi}</script>`})}var di=`
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
- `,di=String.raw`
908
+ `,pi=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>';
@@ -1022,7 +1022,7 @@ history.replaceState(null,'',u);
1022
1022
  if(v==='map')ensureMap();else if(!loaded){loaded=true;load();}}
1023
1023
  $('view').addEventListener('click',e=>{const b=e.target.closest('button[data-value]');if(!b||b.dataset.value===view)return;show(b.dataset.value);});
1024
1024
  show(view);
1025
- `;function Bn(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return L({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:pi,scripts:`<script src="${ut("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var pi=`
1025
+ `;function Fn(t={}){let e='<div id="wfe-root" style="height:100%"></div>';return L({title:"AgentX \xB7 Workflow editor",activeTab:"workflows",subtitle:"Workflow editor",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ui,scripts:`<script src="${ut("workflow-editor.global.js")}" defer></script>`,noMain:!0})}var ui=`
1026
1026
  /* Preload the fonts the redesign's CSS references. Placed in the shell so
1027
1027
  * they start fetching while the React bundle is still parsing. */
1028
1028
  @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");
@@ -1043,10 +1043,10 @@ body { margin: 0; overflow: hidden; }
1043
1043
  font: 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
1044
1044
  text-align: center;
1045
1045
  }
1046
- `;import{createServer as $p}from"http";import{appendFileSync as Pp,existsSync as qs,mkdirSync as jp}from"fs";import{readFile as Op}from"fs/promises";import{fileURLToPath as Np}from"url";import{dirname as Dp,resolve as Ke}from"path";Qs();var zn='/*! 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 ht,readFileSync as Jn,writeFileSync as Vn,rmSync as Uu,mkdirSync as xi,copyFileSync as vi,readdirSync as bi}from"fs";import{resolve as $e}from"path";Zs();function qn(t){let e=Ve.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ve.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 ft(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=Ve.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 Fn=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Un(t){return ft(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 Wn(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return ft((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:Fn(t?.chats),senders:Fn(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 Gn(t){let e=String(t?.id??"");return ft(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 Xn(t){let e=String(t?.id??"");return ft(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}"`})}jt();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 Kn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=lt({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+ct([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return L({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+mi()+bn,css:hi,scripts:`${e}<script>${yn}
1047
- ${wn}
1048
- ${ui}
1049
- ${gi}</script>`})}var ui=`
1046
+ `;import{createServer as Pp}from"http";import{appendFileSync as jp,existsSync as Us,mkdirSync as Op}from"fs";import{readFile as Np}from"fs/promises";import{fileURLToPath as Dp}from"url";import{dirname as Hp,resolve as Ke}from"path";Zs();var qn='/*! 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 ht,readFileSync as Yn,writeFileSync as Qn,rmSync as Wu,mkdirSync as vi,copyFileSync as bi,readdirSync as yi}from"fs";import{resolve as $e}from"path";ei();function Wn(t){let e=Ve.safeParse(t?.whatsappTriage??{}),a=e.success?e.data:Ve.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 ft(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=Ve.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 Un=t=>(Array.isArray(t)?t:String(t??"").split(/[,\n]/)).map(e=>String(e).trim()).filter(Boolean);function Gn(t){return ft(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 Xn(t){let e=String(t?.id??"").trim(),a=String(t?.agent??"").trim();return ft((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:Un(t?.chats),senders:Un(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 Kn(t){let e=String(t?.id??"");return ft(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 Jn(t){let e=String(t?.id??"");return ft(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}"`})}jt();var pe={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 Vn(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=lt({kicker:"Settings",title:"Your team's control room",lead:`Manage the agents, the places they answer from, and who's allowed to reach them. Everything here writes to <span class="mono muted">agentx.json</span> on your machine \u2014 nothing leaves.`})+ct([{kind:"off",num:"\u2014",label:"Agents online"},{kind:"off",num:"\u2014",label:"Channels connected"},{kind:"off",num:"0",label:"Needs attention"},{kind:"off",num:"\u2014",label:"Active tokens"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="ax-health">')+'<div class="ax-wit" id="ax-voice-missing" style="display:none"><span class="ax-wit__icon">!</span><div></div></div>';return L({title:"AgentX \xB7 Settings",activeTab:"admin",subtitle:"Settings",peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a+fi()+wn,css:gi,scripts:`${e}<script>${kn}
1047
+ ${_n}
1048
+ ${mi}
1049
+ ${xi}</script>`})}var mi=`
1050
1050
  (function(){
1051
1051
  function fmt(n) { return n == null ? '\u2014' : String(n); }
1052
1052
  async function voiceMissing() {
@@ -1140,8 +1140,8 @@ ${gi}</script>`})}var ui=`
1140
1140
  refresh();
1141
1141
  // Refresh again after the main admin script has had a chance to mutate config.
1142
1142
  document.addEventListener('ax-config-saved', refresh);
1143
- })();`;function mi(){let t=tn().business?`<button data-tab="business">Business</button>
1144
- `:"";return fi.replace("__BUSINESS_TABS__",t)}var fi=`
1143
+ })();`;function fi(){let t=nn().business?`<button data-tab="business">Business</button>
1144
+ `:"";return hi.replace("__BUSINESS_TABS__",t)}var hi=`
1145
1145
  <div id="peer-banner" class="peer-banner">
1146
1146
  <span class="label">Managing</span>
1147
1147
  <span class="name" id="peer-banner-name">\u2014</span>
@@ -1284,7 +1284,7 @@ ${gi}</script>`})}var ui=`
1284
1284
  <div id="global-msg" class="msg"></div>
1285
1285
 
1286
1286
  <section id="tab-agents" class="tab active">
1287
- ${W({icon:de.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1287
+ ${W({icon:pe.agents,title:"Your agents",lead:"Each agent is a role with its own trigger words and workspace. Delete removes the config only \u2014 the folder on disk stays."})}
1288
1288
  ${ne({persistKey:"agents",bodyHtml:`<b>What's an agent, exactly?</b> Think of it as a specialised teammate. A sales agent handles pricing questions, a support agent answers tickets, a reports agent sends a weekly summary. You decide what they do and what to say to wake them up (their "trigger words", like <code>@support</code>).`})}
1289
1289
  <div id="agent-list" class="ax-stack"></div>
1290
1290
  <div class="add-form">
@@ -1307,7 +1307,7 @@ ${gi}</script>`})}var ui=`
1307
1307
  </section>
1308
1308
 
1309
1309
  <section id="tab-channels" class="tab">
1310
- ${W({icon:de.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1310
+ ${W({icon:pe.channels,title:"Where your agents show up",lead:"Connect a chat app, and your agents can answer from there. Set up once \u2014 they'll keep working in the background."})}
1311
1311
  ${ne({persistKey:"channels",bodyHtml:"<b>How does this work?</b> Connect Telegram with a bot token or pair WhatsApp with a QR code. For webhook sources (GitHub, GitLab), use the URL shown in setup. Slack and Discord adapters are not supported in this build."})}
1312
1312
 
1313
1313
  <details class="add-form" style="margin-top:14px;margin-bottom:18px" id="notif-section">
@@ -1414,7 +1414,7 @@ ${gi}</script>`})}var ui=`
1414
1414
  </section>
1415
1415
 
1416
1416
  <section id="tab-crons" class="tab">
1417
- ${W({icon:de.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1417
+ ${W({icon:pe.schedules,title:"Schedules",lead:"Make an agent do something on a timer \u2014 no one has to ask. Daily summaries, weekly reports, hourly health checks."})}
1418
1418
  ${ne({persistKey:"crons",bodyHtml:"<b>What's a good schedule?</b> Anything recurring. A <i>Reports agent</i> sending Monday-morning numbers, a <i>Health agent</i> pinging you at 3am if a server's down, a <i>Standup agent</i> reminding the team. Pick a time below."})}
1419
1419
  <div id="cron-list" class="ax-stack" style="margin-bottom:22px"></div>
1420
1420
 
@@ -1512,7 +1512,7 @@ ${gi}</script>`})}var ui=`
1512
1512
  </section>
1513
1513
 
1514
1514
  <section id="tab-webhooks" class="tab">
1515
- ${W({icon:de.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1515
+ ${W({icon:pe.webhooks,title:"Webhooks",lead:"A URL you give to another service. When something happens there \u2014 a PR is merged, an error fires \u2014 they POST to that URL, and we forward it to your agent as a readable message."})}
1516
1516
  ${ne({persistKey:"webhooks",bodyHtml:`<b>Not sure you need this?</b> If a service you use has a "webhooks" setting (GitHub, Stripe, Sentry, Typeform\u2026), you probably do. It's how those services tell AgentX when something's worth looking at.`})}
1517
1517
  <div id="webhook-list" class="ax-stack"></div>
1518
1518
  <div class="add-form">
@@ -1554,7 +1554,7 @@ ${gi}</script>`})}var ui=`
1554
1554
  </section>
1555
1555
 
1556
1556
  <section id="tab-mesh" class="tab">
1557
- ${W({icon:de.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1557
+ ${W({icon:pe.mesh,title:"Mesh",lead:"Link this AgentX to other machines so they share work. Good for teams running AgentX on multiple laptops or a mix of laptop + server."})}
1558
1558
  <div id="mesh-hero" class="ax-mesh-hero"></div>
1559
1559
  ${ne({persistKey:"mesh",bodyHtml:"<b>Do I need mesh?</b> Only if you're running AgentX in more than one place. Solo users on one laptop can skip this entirely."})}
1560
1560
  ${dt({label:"Connected peers"})}
@@ -1584,7 +1584,7 @@ ${gi}</script>`})}var ui=`
1584
1584
  </section>
1585
1585
 
1586
1586
  <section id="tab-business" class="tab">
1587
- ${W({icon:de.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1587
+ ${W({icon:pe.tokens,title:"Business layer",lead:"Org chart, projects, and contact map \u2014 the data that drives PM gating and activity-graph attribution. Same as agentx business in the terminal."})}
1588
1588
  ${ne({persistKey:"business",bodyHtml:'<b>Three concepts.</b> The <b>org chart</b> is who reports to whom (<code>reportsTo</code>). <b>Projects</b> map an id to a PM and client (drives the PM gate and lets the activity graph attribute work to the right client). The <b>contact map</b> tells the activity graph which client a Telegram/WhatsApp chat belongs to \u2014 without it, free-text channels fall into the catch-all "internal" bucket. Editing here writes to <code>agentx.json</code>; restart the daemon (or POST /reload) for the change to take effect.'})}
1589
1589
 
1590
1590
  <div class="ax-stack" style="margin-top:14px">
@@ -1672,7 +1672,7 @@ ${gi}</script>`})}var ui=`
1672
1672
  </section>
1673
1673
 
1674
1674
  <section id="tab-boards-cfg" class="tab">
1675
- ${W({icon:de.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1675
+ ${W({icon:pe.tokens,title:"Kanban boards",lead:"Configure the boards rendered on the home page. Same as agentx board add, edit, remove and column in the terminal. Source is GitLab today; backlog/wiki sources land when the schema unlocks them."})}
1676
1676
  ${ne({persistKey:"boards-cfg",bodyHtml:'<b>Two layers.</b> A board points to one or more GitLab projects (<code>source.projects</code>) and optionally filters by a primary tool label. Inside each board, <b>columns</b> map drag-drop actions to scoped-labels (e.g. dropping a card on "Doing" adds <code>Status::Doing</code>). The default flow is Open \u2192 To Do \u2192 Doing \u2192 On Hold \u2192 Review \u2192 Closed; override per-board with the column controls below.'})}
1677
1677
 
1678
1678
  <div class="ax-stack" style="margin-top:14px">
@@ -1697,7 +1697,7 @@ ${gi}</script>`})}var ui=`
1697
1697
  </section>
1698
1698
 
1699
1699
  <section id="tab-actions" class="tab">
1700
- ${W({icon:de.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1700
+ ${W({icon:pe.actions,title:"Action registry",lead:"Reusable shell commands and HTTP calls. Workflows invoke them by id; the dashboard runs them on demand for smoke-tests. Same as agentx actions in the terminal."})}
1701
1701
  ${ne({persistKey:"actions",bodyHtml:"<b>Two flavors.</b> <code>shell</code> runs a templated command on the daemon host (cwd + extra env vars supported). <code>http</code> calls a URL with templated method/headers/body. Inputs are typed (string / number / boolean) and fill <code>{{name}}</code> markers; <code>$VAR</code> resolves against the daemon's process env. Output capped at 32KB."})}
1702
1702
 
1703
1703
  <div class="ax-stack" style="margin-top:14px">
@@ -1753,7 +1753,7 @@ ${gi}</script>`})}var ui=`
1753
1753
  </section>
1754
1754
 
1755
1755
  <section id="tab-tokens" class="tab">
1756
- ${W({icon:de.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1756
+ ${W({icon:pe.tokens,title:"Access tokens",lead:"Passwords, but for software. Anything that wants to talk to AgentX from outside (a Slack bridge, another AgentX machine, a script) uses one."})}
1757
1757
  ${ne({persistKey:"tokens",bodyHtml:"<b>Tokens get scopes.</b> A scope is what the token is allowed to do. Give the narrowest one that works \u2014 a Slack bridge only needs to send messages, it doesn't need to edit settings. You can't recover a token after you close this page, so copy it immediately."})}
1758
1758
  <div id="token-list" class="ax-stack"></div>
1759
1759
  <div class="add-form">
@@ -1773,7 +1773,7 @@ ${gi}</script>`})}var ui=`
1773
1773
  </section>
1774
1774
 
1775
1775
  <section id="tab-advanced" class="tab">
1776
- ${W({icon:de.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1776
+ ${W({icon:pe.advanced,title:"Raw configuration",lead:"Everything on the other tabs writes to this file. Edit here for bulk changes, diffs, or fields we haven't put in the UI yet. Saving creates a timestamped backup."})}
1777
1777
  ${ne({persistKey:"advanced",bodyHtml:`<b>Safe to look, careful editing.</b> We've pretty-printed and annotated each section so you can read it. Click any <span class="mono" style="color:var(--ax-muted)">\u25B8</span> to fold. Switch to <b>Edit</b> to change values \u2014 invalid JSON is refused before saving.`})}
1778
1778
 
1779
1779
  <div class="ax-jv-toolbar">
@@ -1800,7 +1800,7 @@ ${gi}</script>`})}var ui=`
1800
1800
  <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>
1801
1801
  </section>
1802
1802
  </main>
1803
- `,hi=`
1803
+ `,gi=`
1804
1804
 
1805
1805
  /* --- Inner tabs (Agents / Channels / Schedules / \u2026) --- */
1806
1806
  nav.tabs{display:flex;gap:4px;padding:14px 24px 0;background:var(--ax-bg-elev);
@@ -2008,7 +2008,7 @@ textarea.raw{min-height:480px;font-family:var(--ax-mono);font-size:12px;line-hei
2008
2008
  .peer-banner button{background:transparent;border:1px solid currentColor;color:var(--ax-accent);
2009
2009
  padding:4px 10px;border-radius:4px;font:inherit;font-size:11px;cursor:pointer}
2010
2010
  .peer-banner button:hover{background:color-mix(in oklch,var(--ax-accent) 12%,transparent)}
2011
- `,gi=`
2011
+ `,xi=`
2012
2012
  const $ = (id) => document.getElementById(id);
2013
2013
  let state = null;
2014
2014
 
@@ -4875,11 +4875,11 @@ for (const btn of document.querySelectorAll('nav.tabs button')) {
4875
4875
  })();
4876
4876
 
4877
4877
  refresh();
4878
- `;function Yn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Kn({peers:a,localToken:n}))}async function Qn(t,e){let a=Wt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function Zn(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await $i(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await yi(t),r={"GET /api/admin/state":()=>ki(),"POST /api/admin/agents":()=>Ci(n),"PATCH /api/admin/agents":()=>Ii(n),"DELETE /api/admin/agents":()=>Mi(n),"POST /api/admin/agents/access":()=>_i(n),"POST /api/admin/channels/telegram":()=>Li(n),"DELETE /api/admin/channels/telegram":()=>tl(n),"POST /api/admin/channels/telegram/toggle":()=>al(n),"POST /api/admin/crons":()=>nl(n),"DELETE /api/admin/crons":()=>rl(n),"POST /api/admin/config/raw":()=>ol(n),"GET /api/admin/tokens":()=>Ei(),"POST /api/admin/tokens":()=>Si(n),"DELETE /api/admin/tokens":()=>Ti(n),"POST /api/admin/agents/test":()=>Ai(n),"POST /api/admin/agents/integrations":()=>Hi(n),"DELETE /api/admin/agents/integrations":()=>Bi(n),"PATCH /api/admin/agents/integrations":()=>zi(n),"PATCH /api/admin/channels/telegram":()=>Ri(n),"POST /api/admin/channels/slack":()=>Ki(n),"POST /api/admin/channels/slack/toggle":()=>Ji(n),"POST /api/admin/channels/discord":()=>Vi(n),"POST /api/admin/channels/discord/toggle":()=>Yi(n),"POST /api/admin/channels/gitlab":()=>Qi(n),"POST /api/admin/channels/gitlab/toggle":()=>Zi(n),"GET /api/admin/channels/whatsapp/state":()=>Be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Be("/webrtc/history"),"POST /api/admin/actions":()=>vl(n),"DELETE /api/admin/actions":()=>bl(n),"POST /api/admin/actions/run":()=>yl(n),"GET /api/admin/channels/whatsapp/chats":()=>Be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>ue("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>el(n),"POST /api/admin/webhooks":()=>Fi(n),"PATCH /api/admin/webhooks":()=>qi(n),"DELETE /api/admin/webhooks":()=>Xi(n),"POST /api/admin/whatsapp-triage":()=>Un(n),"POST /api/admin/whatsapp-triage/rules":()=>Wn(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Gn(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Xn(n),"POST /api/admin/mesh/peers":()=>Ui(n),"DELETE /api/admin/mesh/peers":()=>Wi(n),"POST /api/admin/mesh/toggle":()=>Gi(n),"GET /api/admin/files":()=>Pi(t),"GET /api/admin/files/read":()=>ji(t),"PUT /api/admin/files":()=>Oi(n),"POST /api/admin/files/skill":()=>Ni(n),"DELETE /api/admin/files/skill":()=>Di(n),"POST /api/admin/business/orgchart":()=>sl(n),"DELETE /api/admin/business/orgchart":()=>il(n),"POST /api/admin/business/project":()=>ll(n),"DELETE /api/admin/business/project":()=>pl(n),"POST /api/admin/business/client":()=>cl(n),"DELETE /api/admin/business/client":()=>dl(n),"POST /api/admin/business/contact":()=>ul(n),"DELETE /api/admin/business/contact":()=>ml(n),"POST /api/admin/boards":()=>fl(n),"DELETE /api/admin/boards":()=>hl(n),"POST /api/admin/boards/columns":()=>gl(n),"DELETE /api/admin/boards/columns":()=>xl(n),"POST /api/admin/notifications":()=>kl(n),"POST /api/admin/screen":()=>_l(n),"POST /api/admin/webhooks/triggers":()=>El(n),"POST /api/admin/mesh/health":()=>wl(n),"GET /api/admin/projects":()=>Be("/api/admin/projects"),"POST /api/admin/projects/workflows/link":()=>ue("/api/admin/projects/workflows/link",n),"POST /api/admin/projects/workflows/unlink":()=>ue("/api/admin/projects/workflows/unlink",n),"POST /api/admin/projects/header":()=>ue("/api/admin/projects/header",n),"POST /api/admin/projects/clauses":()=>ue("/api/admin/projects/clauses",n),"POST /api/admin/projects/contacts/link":()=>ue("/api/admin/projects/contacts/link",n),"POST /api/admin/projects/contacts/unlink":()=>ue("/api/admin/projects/contacts/unlink",n),"POST /api/admin/projects/create":()=>ue("/api/admin/projects/create",n),"POST /api/admin/projects/delete":()=>ue("/api/admin/projects/delete",n)},o=`${t.method} ${a}`,s=r[o];if(!s){qt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();qt(e,200,i)}catch(n){qt(e,400,{error:n.message||"admin op failed"})}}function qt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function yi(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 wi(t){let e=$e(process.cwd(),t);if(!ht(e))return[];let a=[];for(let n of bi(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Jn($e(e,n.name),"utf-8")))}catch{}return a}function Wt(){let t=$e(process.cwd(),"agentx.json");return ht(t)?JSON.parse(Jn(t,"utf-8")):null}function ki(){let t=Wt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let v=x.credentials||{},k={};for(let[b,E]of Object.entries(v))typeof E=="string"&&/^[A-Z][A-Z0-9_]*$/.test(E)?k[b]=process.env[E]?"set":"unset":typeof E=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.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",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Wa(w.local),ntfy:Ln(t.channels?.ntfy)},S=[];try{S=wi(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(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,whatsappTriage:qn(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:mn(t.screen),actions:S}}function _i(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 Ei(){return new ae().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function Si(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Ti(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ai(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=te();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Ci(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=tr(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=$e(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=$e(i,"CLAUDE.md");if(!ht(c))try{xi(i,{recursive:!0}),Vn(c,`# ${a}
4878
+ `;function Zn(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Vn({peers:a,localToken:n}))}async function er(t,e){let a=Wt();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(a))}async function tr(t,e,a){try{if(t.method==="GET"&&a==="/api/admin/channels/whatsapp/qr.svg"){await Pi(e,"/whatsapp/qr.svg");return}let n=t.method==="GET"?void 0:await wi(t),r={"GET /api/admin/state":()=>_i(),"POST /api/admin/agents":()=>Ii(n),"PATCH /api/admin/agents":()=>Mi(n),"DELETE /api/admin/agents":()=>Li(n),"POST /api/admin/agents/access":()=>Ei(n),"POST /api/admin/channels/telegram":()=>Ri(n),"DELETE /api/admin/channels/telegram":()=>al(n),"POST /api/admin/channels/telegram/toggle":()=>nl(n),"POST /api/admin/crons":()=>rl(n),"DELETE /api/admin/crons":()=>ol(n),"POST /api/admin/config/raw":()=>sl(n),"GET /api/admin/tokens":()=>Si(),"POST /api/admin/tokens":()=>Ti(n),"DELETE /api/admin/tokens":()=>Ai(n),"POST /api/admin/agents/test":()=>Ci(n),"POST /api/admin/agents/integrations":()=>Bi(n),"DELETE /api/admin/agents/integrations":()=>zi(n),"PATCH /api/admin/agents/integrations":()=>Fi(n),"PATCH /api/admin/channels/telegram":()=>$i(n),"POST /api/admin/channels/slack":()=>Ji(n),"POST /api/admin/channels/slack/toggle":()=>Vi(n),"POST /api/admin/channels/discord":()=>Yi(n),"POST /api/admin/channels/discord/toggle":()=>Qi(n),"POST /api/admin/channels/gitlab":()=>Zi(n),"POST /api/admin/channels/gitlab/toggle":()=>el(n),"GET /api/admin/channels/whatsapp/state":()=>Be("/whatsapp/state"),"GET /api/admin/channels/webrtc/history":()=>Be("/webrtc/history"),"POST /api/admin/actions":()=>bl(n),"DELETE /api/admin/actions":()=>yl(n),"POST /api/admin/actions/run":()=>wl(n),"GET /api/admin/channels/whatsapp/chats":()=>Be("/whatsapp/chats"),"GET /api/admin/channels/whatsapp/contacts":()=>Be("/whatsapp/contacts"),"POST /api/admin/channels/whatsapp/ingest":()=>me("/whatsapp/ingest",n),"POST /api/admin/crons/preview":()=>tl(n),"POST /api/admin/webhooks":()=>qi(n),"PATCH /api/admin/webhooks":()=>Ui(n),"DELETE /api/admin/webhooks":()=>Ki(n),"POST /api/admin/whatsapp-triage":()=>Gn(n),"POST /api/admin/whatsapp-triage/rules":()=>Xn(n),"PATCH /api/admin/whatsapp-triage/rules":()=>Kn(n),"DELETE /api/admin/whatsapp-triage/rules":()=>Jn(n),"POST /api/admin/mesh/peers":()=>Wi(n),"DELETE /api/admin/mesh/peers":()=>Gi(n),"POST /api/admin/mesh/toggle":()=>Xi(n),"GET /api/admin/files":()=>ji(t),"GET /api/admin/files/read":()=>Oi(t),"PUT /api/admin/files":()=>Ni(n),"POST /api/admin/files/skill":()=>Di(n),"DELETE /api/admin/files/skill":()=>Hi(n),"POST /api/admin/business/orgchart":()=>il(n),"DELETE /api/admin/business/orgchart":()=>ll(n),"POST /api/admin/business/project":()=>cl(n),"DELETE /api/admin/business/project":()=>ul(n),"POST /api/admin/business/client":()=>dl(n),"DELETE /api/admin/business/client":()=>pl(n),"POST /api/admin/business/contact":()=>ml(n),"DELETE /api/admin/business/contact":()=>fl(n),"POST /api/admin/boards":()=>hl(n),"DELETE /api/admin/boards":()=>gl(n),"POST /api/admin/boards/columns":()=>xl(n),"DELETE /api/admin/boards/columns":()=>vl(n),"POST /api/admin/notifications":()=>_l(n),"POST /api/admin/screen":()=>El(n),"POST /api/admin/webhooks/triggers":()=>Sl(n),"POST /api/admin/mesh/health":()=>kl(n),"GET /api/admin/projects":()=>Be("/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){qt(e,404,{error:`unknown admin endpoint: ${o}`});return}let i=await s();qt(e,200,i)}catch(n){qt(e,400,{error:n.message||"admin op failed"})}}function qt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function wi(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 ki(t){let e=$e(process.cwd(),t);if(!ht(e))return[];let a=[];for(let n of yi(e,{withFileTypes:!0}))if(!(!n.isFile()||!n.name.endsWith(".json")))try{a.push(JSON.parse(Yn($e(e,n.name),"utf-8")))}catch{}return a}function Wt(){let t=$e(process.cwd(),"agentx.json");return ht(t)?JSON.parse(Yn(t,"utf-8")):null}function _i(){let t=Wt();if(!t)return{exists:!1};let e=Object.entries(t.agents||{}).map(([d,f])=>({id:d,name:f.name,tier:f.tier,model:f.model,mentions:f.mentions||[],workspace:f.workspace,access:f.access||"private",systemPrompt:f.systemPrompt||"",maxConcurrent:f.maxConcurrent??1,maxExecutionMinutes:f.maxExecutionMinutes??20,permissionMode:f.permissionMode||"default",integrations:(Array.isArray(f.integrations)?f.integrations:[]).map(x=>{let v=x.credentials||{},k={};for(let[b,E]of Object.entries(v))typeof E=="string"&&/^[A-Z][A-Z0-9_]*$/.test(E)?k[b]=process.env[E]?"set":"unset":typeof E=="string"&&(k[b]="literal");return{kind:x.kind,label:x.label,enabled:x.enabled!==!1,credentials:v,credStatus:k,metadata:x.metadata||{}}})})),a=t.channels?.telegram?.accounts||{},n={enabled:!!t.channels?.telegram?.enabled,accounts:Object.entries(a).map(([d,f])=>({id:d,botUsername:f.botUsername||"",agentBinding:f.agentBinding||"",botTokenRef:f.token||""}))},r={enabled:!!t.channels?.slack?.enabled,botTokenRef:t.channels?.slack?.botToken||"",appTokenRef:t.channels?.slack?.appToken||"",agentBinding:t.channels?.slack?.agentBinding||""},o={enabled:!!t.channels?.discord?.enabled,tokenRef:t.channels?.discord?.token||"",agentBinding:t.channels?.discord?.agentBinding||""},s={enabled:!!t.channels?.gitlab?.enabled,host:t.channels?.gitlab?.host||"",webhookPort:t.channels?.gitlab?.webhookPort||18810,tokenRef:t.channels?.gitlab?.token||"",routeCount:Array.isArray(t.channels?.gitlab?.routes)?t.channels.gitlab.routes.length:0,agentMappingCount:Array.isArray(t.channels?.gitlab?.agentMappings)?t.channels.gitlab.agentMappings.length:0},i={enabled:!!t.channels?.whatsapp?.enabled,sessionDir:t.channels?.whatsapp?.sessionDir||".agentx/whatsapp-sessions",routeCount:Array.isArray(t.channels?.whatsapp?.routes)?t.channels.whatsapp.routes.length:0},l=Object.entries(t.crons||{}).map(([d,f])=>({id:d,schedule:f.schedule,agent:f.agent,prompt:(f.prompt||"").slice(0,200),enabled:f.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",m=t.business||{},h={enabled:!!m.enabled,timezone:m.timezone||"UTC",orgChart:m.orgChart||{},projects:Array.isArray(m.projects)?m.projects:[],contactMap:Array.isArray(m.contactMap)?m.contactMap:[],clients:m.clients&&typeof m.clients=="object"?m.clients:{}},w=t.notifications||{},_={longTaskThreshold:w.longTaskThreshold??30,destination:w.destination||null,on:{taskComplete:w.on?.taskComplete!==!1,taskError:w.on?.taskError!==!1,taskQueued:!!w.on?.taskQueued},local:Ga(w.local),ntfy:$n(t.channels?.ntfy)},S=[];try{S=ki(".agentx/actions").filter(f=>f&&typeof f=="object"&&f.id).map(f=>({id:f.id,title:f.title,kind:f.kind,description:f.description||"",inputs:Array.isArray(f.inputs)?f.inputs:[],timeoutMs:f.timeoutMs??3e4,command:f.kind==="shell"?f.command:void 0,url:f.kind==="http"?f.url:void 0,method:f.kind==="http"?f.method:void 0})).sort((f,x)=>f.id.localeCompare(x.id))}catch{}let g=(Array.isArray(t.boards)?t.boards:[]).map(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,whatsappTriage:Wn(t),crons:l,webhooks:c,mesh:p,daemonUrl:u,nodeName:t.node?.name,business:h,boards:g,notifications:_,screen:hn(t.screen),actions:S}}function Ei(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 Si(){return new ae().list().map(t=>({id:t.id,name:t.name,prefix:t.prefix,scopes:t.scopes,createdAt:t.createdAt,expiresAt:t.expiresAt,revokedAt:t.revokedAt,lastUsedAt:t.lastUsedAt}))}function Ti(t){let e=String(t?.name||"").trim(),a=Array.isArray(t?.scopes)?t.scopes.map(String):[],n=t?.expiresInDays?Number(t.expiresInDays):void 0,{token:r,record:o}=new ae().create({name:e,scopes:a,expiresInDays:n});return{summary:`created token "${e}"`,token:r,record:o}}function Ai(t){let e=String(t?.id||"").trim();if(!e)throw new Error("Token id is required.");let a=new ae().revoke(e);if(!a)throw new Error(`Token "${e}" not found.`);return{summary:`revoked token ${e} (${a.name})`}}async function Ci(t){let e=String(t?.agent||t?.id||"").trim(),a=String(t?.message||"").trim(),n=String(t?.chatId||"").trim()||`admin-${Date.now()}`;if(!e)throw new Error("Agent id is required.");if(!a)throw new Error("Message is required.");let r="http://127.0.0.1:18800",o;try{let p=te();r=p.dashboard.daemonUrl.replace(/\/+$/,"")||r,o=p.dashboard.token}catch{}let s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let i=await fetch(`${r}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"test-drive",sender:"admin",chatId:n}})}),l=await i.text(),c;try{c=JSON.parse(l)}catch{c={content:l}}if(!i.ok)throw new Error(c?.error||`daemon HTTP ${i.status}`);return{chatId:n,response:c}}function Ii(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=nr(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=$e(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=$e(i,"CLAUDE.md");if(!ht(c))try{vi(i,{recursive:!0}),Qn(c,`# ${a}
4879
4879
 
4880
4880
  ${s||"You are "+a+"."}
4881
- `)}catch{}return{summary:l}}function Ii(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=tr(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 Mi(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 Li(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 Ri(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 Be(t){let{url:e,headers:a}=Gt(),n=await fetch(e+t,{headers:a}),r=await n.text();if(!n.ok)throw new Error(`daemon ${n.status}: ${r.slice(0,200)}`);try{return JSON.parse(r)}catch{return{raw:r}}}async function ue(t,e){let{url:a,headers:n}=Gt(),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 $i(t,e){try{let{url:a,headers:n}=Gt(),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 Gt(){let t="http://127.0.0.1:18800",e={};try{let a=te();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ze(t){let a=Wt()?.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 Ut(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function Pi(t){let e=Ut(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Le(ze(e));return{agentId:e,...a}}function ji(t){let e=Ut(t,"agent").trim(),a=Ut(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return nt(ze(e),a)}function Oi(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=rt(ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Ni(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=ot(ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Di(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(ze(e),a);return{summary:`removed skill "${a}"`,...n}}function Hi(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 Bi(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 zi(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 er=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function Fi(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(!er.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 qi(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"&&er.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 Ui(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 Wi(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 Gi(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 Xi(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 Ki(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 Ji(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 Vi(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 Yi(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 Qi(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 Zi(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 el(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-YW6JFH3Z.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 tl(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 al(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 nl(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 rl(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 ol(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=$e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(ht(n))try{vi(n,r)}catch{}Vn(n,JSON.stringify(a,null,2)+`
4882
- `,"utf-8");try{let s=te().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 tr(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function sl(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 il(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 ll(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 cl(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 dl(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 pl(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 ul(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 ml(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 fl(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 hl(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 gl(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 xl(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 vl(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 bl(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 yl(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 wl(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 kl(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=Ga(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=Rn(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 _l(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=fn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function El(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}}jt();import{resolve as Al}from"path";function ar(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4881
+ `)}catch{}return{summary:l}}function Mi(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=nr(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 Li(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 Ri(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 $i(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 Be(t){let{url:e,headers:a}=Gt(),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}=Gt(),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 Pi(t,e){try{let{url:a,headers:n}=Gt(),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 Gt(){let t="http://127.0.0.1:18800",e={};try{let a=te();t=a.dashboard.daemonUrl?.replace(/\/+$/,"")||t,a.dashboard.token&&(e.Authorization=`Bearer ${a.dashboard.token}`)}catch{}return{url:t,headers:e}}function ze(t){let a=Wt()?.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 Ut(t,e){try{return new URL(t.url||"/","http://localhost").searchParams.get(e)||""}catch{return""}}function ji(t){let e=Ut(t,"agent").trim();if(!e)throw new Error("agent= query param is required.");let a=Re(ze(e));return{agentId:e,...a}}function Oi(t){let e=Ut(t,"agent").trim(),a=Ut(t,"path").trim();if(!e||!a)throw new Error("agent= and path= query params are required.");return nt(ze(e),a)}function Ni(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=rt(ze(e),a,n);return{summary:`saved ${a} (${r.bytes} bytes)`,...r}}function Di(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=ot(ze(e),a,{title:n,content:r});return{summary:`added skill "${a}"`,...o}}function Hi(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(ze(e),a);return{summary:`removed skill "${a}"`,...n}}function Bi(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 zi(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 Fi(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 ar=["gitlab","github","sentry","stripe","vercel","odoo","hubspot","discord","slack","custom"];function qi(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(!ar.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 Ui(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"&&ar.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 Wi(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 Gi(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 Xi(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 Ki(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 Ji(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 Vi(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 Yi(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 Qi(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 Zi(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 el(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 tl(t){let e=String(t?.schedule||"").trim();if(!e)throw new Error("schedule is required");let{getNextCronDate:a}=await import("./scheduler-YW6JFH3Z.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 al(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 nl(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 rl(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 ol(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 sl(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=$e(process.cwd(),"agentx.json"),r=`${n}.bak.${Date.now()}`;if(ht(n))try{bi(n,r)}catch{}Qn(n,JSON.stringify(a,null,2)+`
4882
+ `,"utf-8");try{let s=te().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 nr(t){return String(t||"").split(/[,\s]+/).map(e=>e.trim()).filter(Boolean).filter((e,a,n)=>n.indexOf(e)===a)}async function il(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 ll(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 cl(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 dl(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 pl(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 ul(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 ml(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 fl(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 hl(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 gl(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 xl(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 vl(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 bl(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 yl(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 wl(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 kl(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 _l(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=Xa(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=Pn(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 El(t){if(!t||typeof t!="object")throw new Error("nothing to update");let{summary:e}=A(a=>(a.screen=gn(a.screen,t),`screen updated (buffer ${a.screen.buffer?.enabled?"on":"off"})`));return{summary:e}}async function Sl(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}}jt();import{resolve as Cl}from"path";function rr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div id="msg" class="msg"></div>
4883
4883
 
4884
4884
  <div id="disabled-banner" class="banner warn" style="display:none">
4885
4885
  <b>Graph is disabled.</b> Set <code class="mono">graph.enabled: true</code>
@@ -4934,7 +4934,7 @@ ${s||"You are "+a+"."}
4934
4934
  <h2>Recent classifications</h2>
4935
4935
  <p class="muted">Last 25 log rows, newest first \u2014 approved / pending / rejected.</p>
4936
4936
  <div id="recent"></div>
4937
- </section>`;return L({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Sl,scripts:`${e}<script>${Tl}</script>`})}var Sl=`
4937
+ </section>`;return L({title:"AgentX \xB7 Intent Graph",activeTab:"graph",subtitle:"Intent Graph",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Tl,scripts:`${e}<script>${Al}</script>`})}var Tl=`
4938
4938
  main { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; }
4939
4939
  h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
4940
4940
  .grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@@ -5038,7 +5038,7 @@ details {
5038
5038
  border-radius: 4px; padding: 8px 12px; margin-top: 8px;
5039
5039
  }
5040
5040
  details summary { cursor: pointer; font-size: 11px; color: var(--ax-muted); user-select: none; }
5041
- details[open] summary { margin-bottom: 8px; }`,Tl=`
5041
+ details[open] summary { margin-bottom: 8px; }`,Al=`
5042
5042
  const $ = (id) => document.getElementById(id);
5043
5043
  const state = { schema: null, nodes: [], pending: [], recent: [] };
5044
5044
 
@@ -5258,7 +5258,7 @@ $('btn-save-schema').addEventListener('click', async () => {
5258
5258
  $('btn-reload-schema').addEventListener('click', refresh);
5259
5259
 
5260
5260
  refresh();
5261
- `;function rr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ar({peers:a,localToken:n}))}async function or(t,e,a){try{let n=t.method==="GET"?void 0:await Ol(t),r=Cl(),o={"GET /api/admin/graph/state":()=>Il(r),"POST /api/admin/graph/classifications/approve":()=>Ml(r,n),"POST /api/admin/graph/classifications/reject":()=>Ll(r,n),"POST /api/admin/graph/nodes":()=>Rl(r,n),"PATCH /api/admin/graph/nodes":()=>$l(r,n),"DELETE /api/admin/graph/nodes":()=>Pl(r,n),"PUT /api/admin/graph/schema":()=>jl(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Xt(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Xt(e,200,l)}catch(n){Xt(e,400,{error:n?.message||"graph op failed"})}}function Cl(){let t=te(),e=Al(process.cwd(),t.graph.baseDir);return new $a({baseDir:e})}function Il(t){let e=te(),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 Ml(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=sr(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=Kt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Ll(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=sr(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function sr(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 Rl(t,e){let a=nr(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?nr(String(e.parentId)):null,o=Kt({[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 $l(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Kt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function Pl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function jl(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 Kt(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 nr(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Xt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Ol(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 ir(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5261
+ `;function sr(t,e,a=[],n){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(rr({peers:a,localToken:n}))}async function ir(t,e,a){try{let n=t.method==="GET"?void 0:await Nl(t),r=Il(),o={"GET /api/admin/graph/state":()=>Ml(r),"POST /api/admin/graph/classifications/approve":()=>Ll(r,n),"POST /api/admin/graph/classifications/reject":()=>Rl(r,n),"POST /api/admin/graph/nodes":()=>$l(r,n),"PATCH /api/admin/graph/nodes":()=>Pl(r,n),"DELETE /api/admin/graph/nodes":()=>jl(r,n),"PUT /api/admin/graph/schema":()=>Ol(r,n)},s=`${t.method} ${a}`,i=o[s];if(!i){Xt(e,404,{error:`unknown graph endpoint: ${s}`});return}let l=await i();Xt(e,200,l)}catch(n){Xt(e,400,{error:n?.message||"graph op failed"})}}function Il(){let t=te(),e=Cl(process.cwd(),t.graph.baseDir);return new Pa({baseDir:e})}function Ml(t){let e=te(),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 Ll(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=lr(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=Kt(e.proposedAxes)),t.approveClassification(n),{summary:`Approved ${n.msgHash}`}}function Rl(t,e){let a=String(e?.msgHash||"").trim();if(!a)throw new Error("msgHash is required");let n=lr(t,a);return t.rejectClassification(n),{summary:`Rejected ${n.msgHash}`}}function lr(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 $l(t,e){let a=or(String(e?.id||"")),n=String(e?.level||"").trim(),r=e?.parentId?or(String(e.parentId)):null,o=Kt({[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 Pl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");let n=Kt({[a]:e?.axes||{}})[a]||{};return{node:t.updateNodeAxes(a,n)}}function jl(t,e){let a=String(e?.id||"").trim();if(!a)throw new Error("id is required");return t.deleteNode(a),{summary:`Deleted ${a}`}}function Ol(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 Kt(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 or(t){return t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function Xt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function Nl(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 cr(t={}){let e=t.localToken?`<script>window.AX_LOCAL_TOKEN = ${JSON.stringify(t.localToken)};</script>`:"",a=`<div class="apv">
5262
5262
  <header class="apv__head">
5263
5263
  <div>
5264
5264
  <h1>Approvals</h1>
@@ -5292,7 +5292,7 @@ refresh();
5292
5292
  <div><button type="submit" class="ax-btn ax-btn--primary">Save settings</button></div>
5293
5293
  </form>
5294
5294
  </details>
5295
- </div>`;return L({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Nl,scripts:`${e}<script>${Dl}</script>`})}var Nl=`
5295
+ </div>`;return L({title:"AgentX \xB7 Approvals",activeTab:"approvals",subtitle:"Approvals",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:Dl,scripts:`${e}<script>${Hl}</script>`})}var Dl=`
5296
5296
  .apv { max-width: 860px; margin: 0 auto; padding: 20px 16px 64px; color: var(--ax-text); }
5297
5297
  .apv__head { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: flex-end; margin-bottom: 14px; }
5298
5298
  .apv__head h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
@@ -5341,9 +5341,9 @@ refresh();
5341
5341
  @media (max-width: 560px) {
5342
5342
  .apv__acts .ax-btn { flex: 1 1 0; }
5343
5343
  }
5344
- `,Dl=`
5344
+ `,Hl=`
5345
5345
  (function(){
5346
- var state = { items: [], snoozed: 0, kind: '', showAll: false };
5346
+ var state = { items: [], snoozed: 0, kind: '', showAll: false, popup: false };
5347
5347
  var LABEL = { card: 'Card', schedule: 'Schedule', memory: 'Memory fact', wiki: 'Wiki lesson', whatsapp: 'WhatsApp reply' };
5348
5348
  function $(id){ return document.getElementById(id); }
5349
5349
  function esc(s){ return String(s == null ? '' : s).replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c]; }); }
@@ -5370,6 +5370,7 @@ async function load(){
5370
5370
  var d = await r.json();
5371
5371
  if (!r.ok) throw new Error(d.error || ('HTTP ' + r.status));
5372
5372
  state.items = d.items || []; state.snoozed = d.snoozed || 0;
5373
+ state.popup = !!(d.settings && d.settings.popup && d.settings.popup.enabled);
5373
5374
  $('apv-errors').innerHTML = (d.errors || []).map(function(e){ return '<p class="apv__err">Couldn&#39;t read ' + esc(e.kind) + ': ' + esc(e.error) + '. The list may be incomplete.</p>'; }).join('');
5374
5375
  render();
5375
5376
  if (d.settings) fillSettings(d.settings);
@@ -5420,6 +5421,7 @@ function item(i){
5420
5421
  + '<button type="button" class="ax-btn ax-btn--primary" data-act="yes">Yes</button>'
5421
5422
  + '<button type="button" class="ax-btn ax-btn--danger" data-act="no">No</button>'
5422
5423
  + '<button type="button" class="ax-btn ax-btn--ghost" data-act="later">Later</button>'
5424
+ + (i.kind === 'card' && state.popup ? '<button type="button" class="ax-btn ax-btn--ghost" data-pop title="Show this card on the Mac again">Show on Mac</button>' : '')
5423
5425
  + '</div></li>';
5424
5426
  }
5425
5427
 
@@ -5443,6 +5445,17 @@ async function act(li, action){
5443
5445
  }
5444
5446
  }
5445
5447
 
5448
+ async function pop(li, b){
5449
+ b.disabled = true;
5450
+ try {
5451
+ var r = await fetch('/api/admin/approvals/popup', { method: 'POST', headers: headers(true), body: JSON.stringify({ key: li.getAttribute('data-key') }) });
5452
+ var d = await r.json();
5453
+ if (!r.ok) throw new Error(d.error || ('HTTP ' + r.status));
5454
+ say(d.message, 'ok');
5455
+ } catch (e) { say(e.message, 'err'); }
5456
+ b.disabled = false;
5457
+ }
5458
+
5446
5459
  function fillSettings(s){
5447
5460
  var f = $('apv-form');
5448
5461
  f.defaultExpiryDays.value = s.defaultExpiryDays;
@@ -5459,6 +5472,8 @@ document.addEventListener('click', function(ev){
5459
5472
  var t = ev.target;
5460
5473
  var b = t.closest && t.closest('button[data-act]');
5461
5474
  if (b) { act(b.closest('.apv__item'), b.getAttribute('data-act')); return; }
5475
+ var p = t.closest && t.closest('button[data-pop]');
5476
+ if (p) { pop(p.closest('.apv__item'), p); return; }
5462
5477
  var f = t.closest && t.closest('.apv__f');
5463
5478
  if (f) {
5464
5479
  state.kind = f.getAttribute('data-kind');
@@ -5493,7 +5508,7 @@ $('apv-form').addEventListener('submit', async function(ev){
5493
5508
  load();
5494
5509
  setInterval(function(){ if (document.visibilityState === 'visible' && !document.querySelector('.apv__item:focus-within')) load(); }, 60000);
5495
5510
  })();
5496
- `;var Hl=["yes","no","later"];function me(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function lr(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 cr(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(ir({peers:e,localToken:a}))}async function dr(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 me(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=tt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return me(e,200,{...i,settings:Re(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await lr(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Hl.includes(c))return me(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=Re(s.configPath),u=await at(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?(me(e,200,{ok:!0,message:u.message}),!0):(me(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await lr(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let m=Cn(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await In(l,{configPath:s.configPath,reload:s.reload});return p.success?(me(e,200,{ok:!0,settings:Re(s.configPath)}),!0):(me(e,400,{error:p.error}),!0)}}catch(i){return me(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return me(e,404,{error:"Not found"}),!0}import{resolve as Fl}from"path";import{existsSync as ql}from"fs";import Ul from"better-sqlite3";function pr(t={}){let e=`<div class="ax-obs">
5511
+ `;var Bl=["yes","no","later"];function oe(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}async function Jt(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 dr(t,e,a){t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(cr({peers:e,localToken:a}))}async function pr(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 oe(e,400,{error:"missing X-Requested-With: agentx-board"}),!0;try{if(o==="GET"&&a==="/api/admin/approvals"){let i=tt(s,{includeSnoozed:n.searchParams.get("all")==="1"});return oe(e,200,{...i,settings:we(s.configPath)}),!0}if(o==="POST"&&a==="/api/admin/approvals/decide"){let i=await Jt(t),l=typeof i.key=="string"?i.key:"",c=i.action;if(!l||!Bl.includes(c))return oe(e,400,{error:"send { key, action: yes | no | later }"}),!0;let p=we(s.configPath),u=await at(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?(oe(e,200,{ok:!0,message:u.message}),!0):(oe(e,409,{error:u.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/popup"){let i=await Jt(t),l=Ya(s,typeof i.key=="string"?i.key:"",!!we(s.configPath).popup?.enabled);return l.ok?(oe(e,200,{ok:!0,message:l.message}),!0):(oe(e,409,{error:l.error}),!0)}if(o==="POST"&&a==="/api/admin/approvals/settings"){let i=await Jt(t),l={},c=u=>{let m=i[u];if(m!==void 0){if(typeof m!="number"||!(m>0))throw new Error(`${u} must be a positive number`);return m}};if(l.defaultExpiryDays=c("defaultExpiryDays"),l.maxExpiryDays=c("maxExpiryDays"),l.laterHours=c("laterHours"),typeof i.notifyAgent=="boolean"&&(l.notifyAgent=i.notifyAgent),typeof i.digestEnabled=="boolean"&&(l.digestEnabled=i.digestEnabled),typeof i.digestTime=="string"&&(l.digestTime=i.digestTime),typeof i.destination=="string"){let u=i.destination.trim();if(!u)l.destination=null;else{let m=Mn(u);if(!m)throw new Error("digest destination takes channel:chat id, for example telegram:123456");l.destination=m}}let p=await Ln(l,{configPath:s.configPath,reload:s.reload});return p.success?(oe(e,200,{ok:!0,settings:we(s.configPath)}),!0):(oe(e,400,{error:p.error}),!0)}}catch(i){return oe(e,400,{error:String(i?.message??i).slice(0,300)}),!0}return oe(e,404,{error:"Not found"}),!0}import{resolve as ql}from"path";import{existsSync as Ul}from"fs";import Wl from"better-sqlite3";function ur(t={}){let e=`<div class="ax-obs">
5497
5512
  <header class="ax-obs__head">
5498
5513
  <h1>Health</h1>
5499
5514
  <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>
@@ -5615,7 +5630,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5615
5630
  </div>
5616
5631
  <div id="obs-doctor-body" class="ax-obs__doctor-body"></div>
5617
5632
  </section>
5618
- </div>`;return L({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:Bl,scripts:`<script>${zl}</script>`})}var Bl=`
5633
+ </div>`;return L({title:"AgentX \xB7 Health",activeTab:"health",subtitle:"Health",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:zl,scripts:`<script>${Fl}</script>`})}var zl=`
5619
5634
  .ax-obs { padding: 16px 24px; }
5620
5635
  .ax-obs__head { margin-bottom: 16px; }
5621
5636
  .ax-obs__head h1 { margin: 0 0 4px; font-size: 18px; }
@@ -5732,7 +5747,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
5732
5747
  .ax-obs__doctor-title { font-size: 12px; font-weight: 500; }
5733
5748
  .ax-obs__doctor-detail { font-size: 11px; color: var(--ax-muted); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; word-break: break-word; }
5734
5749
  .ax-obs__doctor-fix { font-size: 11px; color: var(--ax-accent, #3a7bd5); margin-top: 2px; }
5735
- `,zl=`
5750
+ `,Fl=`
5736
5751
  (function(){
5737
5752
  var panes = document.querySelectorAll('.ax-obs__pane');
5738
5753
  var tabs = document.querySelectorAll('.ax-obs__tab');
@@ -6116,7 +6131,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6116
6131
 
6117
6132
  load(current);
6118
6133
  })();
6119
- `;var fr={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 hr(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Jt(t){let e=fr[hr(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 Wl(){let t=Fl(process.cwd(),".agentx/db.sqlite");if(!ql(t))return null;try{let e=new Ul(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function gr(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(pr({peers:a}))}function Gl(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 xr(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Wl();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Gl(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6134
+ `;var hr={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 gr(t){let e=(t||"").toLowerCase();return e.includes("opus")?"opus":e.includes("haiku")?"haiku":e.includes("sonnet")||e.includes("claude")?"sonnet":"external"}function Vt(t){let e=hr[gr(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 Gl(){let t=ql(process.cwd(),".agentx/db.sqlite");if(!Ul(t))return null;try{let e=new Wl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch{return null}}function xr(t,e,a=[]){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ur({peers:a}))}function Xl(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 vr(t,e,a){if(!a.startsWith("/api/admin/observability/"))return!1;let n=a.replace(/^\/api\/admin\/observability\//,"").split("?")[0],r=Gl();if(!r)return fe(e,503,{error:"operational SQLite not available",rows:[]}),!0;try{let{limit:o,agent:s}=Xl(t);if(n==="routing"){let i=[],l={limit:o};s&&(i.push("agent_id = @agent"),l.agent=s);let c=`
6120
6135
  SELECT at, channel, chat_id, account_id, kind, deciding_stage, agent_id, reason
6121
6136
  FROM route_traces
6122
6137
  ${i.length?"WHERE "+i.join(" AND "):""}
@@ -6131,8 +6146,8 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6131
6146
  FROM task_history
6132
6147
  WHERE ${i.join(" AND ")}
6133
6148
  ORDER BY started_at DESC LIMIT @limit
6134
- `,u=r.db.prepare(c).all(l).map(m=>({...m,plain:vr(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,Xl(r.db)),!0;if(n==="activity")return fe(e,200,Kl(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=ur(i.searchParams.get("range"));return fe(e,200,mr(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=ur(i.searchParams.get("range")),c=mr(r.db,l),p=Jl(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 vr(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(`
6135
- `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Xl(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=E=>p.length?p[Math.min(p.length-1,Math.floor(p.length*E))].duration_ms:0,m=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((E,I)=>E+Jt(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((E,I)=>E+Jt(I),0),g=t.prepare(`
6149
+ `,u=r.db.prepare(c).all(l).map(m=>({...m,plain:br(m.error)}));return fe(e,200,{rows:u}),!0}if(n==="summary"||n==="overview")return fe(e,200,Kl(r.db)),!0;if(n==="activity")return fe(e,200,Jl(r.db,{agent:s})),!0;if(n==="cost"){let i=new URL(t.url||"/","http://_"),l=mr(i.searchParams.get("range"));return fe(e,200,fr(r.db,l)),!0}if(n==="cost.csv"){let i=new URL(t.url||"/","http://_"),l=mr(i.searchParams.get("range")),c=fr(r.db,l),p=Vl(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 br(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(`
6150
+ `)[0].slice(0,80)+(e.length>80?"\u2026":""):"unknown failure"}function Kl(t){let e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()).toISOString(),n=new Date(e.getTime()-864e5),r=new Date(n.getFullYear(),n.getMonth(),n.getDate()).toISOString(),o=new Date(e.getTime()-864e5).toISOString(),s=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ?").get(a).n,i=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE started_at >= ? AND started_at < ?").get(r,a).n,l=t.prepare("SELECT COUNT(*) AS n FROM task_history WHERE status='error' AND started_at >= ?").get(a).n,c=t.prepare("SELECT AVG(duration_ms) AS d FROM task_history WHERE status='ok' AND started_at >= ?").get(a).d??0,p=t.prepare("SELECT duration_ms FROM task_history WHERE status='ok' AND started_at >= ? AND duration_ms IS NOT NULL ORDER BY duration_ms ASC").all(a),u=E=>p.length?p[Math.min(p.length-1,Math.floor(p.length*E))].duration_ms:0,m=u(.5),h=u(.95),_=t.prepare("SELECT * FROM usage_daily WHERE day = date('now')").all().reduce((E,I)=>E+Vt(I),0),S=t.prepare("SELECT * FROM usage_daily WHERE day = date('now', '-1 day')").all().reduce((E,I)=>E+Vt(I),0),g=t.prepare(`
6136
6151
  SELECT agent_id,
6137
6152
  COUNT(*) AS tasks,
6138
6153
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors,
@@ -6155,7 +6170,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6155
6170
  FROM task_history
6156
6171
  WHERE status='error' AND started_at >= ?
6157
6172
  ORDER BY started_at DESC LIMIT 5
6158
- `).all(o).map(E=>({...E,plain:vr(E.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:b}}function Kl(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(`
6173
+ `).all(o).map(E=>({...E,plain:br(E.error)}));return{kpis:{tasksToday:s,tasksDelta:s-i,errorsToday:l,errorRate:s>0?l/s:0,avgDurationMs:Math.round(c),p50DurationMs:m,p95DurationMs:h,spendToday:_,spendDelta:_-S,idleAgentCount:v.length},perAgent:g,perChannel:d,idleAgents:v,recentErrors:b}}function Jl(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(`
6159
6174
  SELECT strftime('%Y-%m-%dT%H:00', started_at) AS hour,
6160
6175
  COUNT(*) AS tasks,
6161
6176
  SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) AS errors
@@ -6182,7 +6197,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6182
6197
  WHERE started_at >= @since
6183
6198
  GROUP BY agent_id
6184
6199
  ORDER BY tasks_24h DESC, tasks_7d DESC
6185
- `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function ur(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 mr(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6200
+ `).all({since:n,last24:a});return{hourly:s,daily:i,perAgent:l}}function mr(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 fr(t,e){let a=e>0?`WHERE day >= date('now', '-${e} day')`:"",n=t.prepare(`
6186
6201
  SELECT day, agent_id, model,
6187
6202
  input_tokens, output_tokens, cache_read_tokens, cache_create_tokens,
6188
6203
  tier2_input_tokens, tier2_output_tokens, tier2_cache_read_tokens, tier2_cache_create_tokens,
@@ -6190,20 +6205,20 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6190
6205
  FROM usage_daily
6191
6206
  ${a}
6192
6207
  ORDER BY day
6193
- `).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,m=0,h=0,w=0,_=0,S=0,g={},d={};for(let T of n){let M=Jt(T),P=hr(T.model),j=fr[P],B=(T.tier2_input_tokens||0)/1e6*j.input*.5+(T.tier2_output_tokens||0)/1e6*j.output*.5+(T.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,oe=(T.input_tokens||0)+(T.tier2_input_tokens||0),F=(T.output_tokens||0)+(T.tier2_output_tokens||0),ee=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),V=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);u+=M,T.day>=s&&(p+=M,w+=T.tasks||0),T.day>=i&&T.day<s&&(S+=M,_+=T.tasks||0),T.day===r&&(l+=M),T.day===o&&(c+=M),T.day===r&&(m+=B),T.day>=s&&(h+=B);let N=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});N.tasks+=T.tasks||0,N.input+=oe,N.output+=F,N.cacheRead+=ee,N.cacheCreate+=V,N.cost+=M,N.tier2+=B;let se=N.agents[T.agent_id]||(N.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});se.tasks+=T.tasks||0,se.cost+=M,se.tier2+=B,se.input+=oe,se.output+=F,se.cacheRead+=ee,se.cacheCreate+=V,T.model&&(se.model=T.model);let q=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});q.tasks+=T.tasks||0,q.cost+=M,q.tier2+=B,q.input+=oe,q.output+=F,q.cacheRead+=ee,q.cacheCreate+=V,T.model&&(q.model=T.model)}let f=Object.values(g).sort((T,M)=>T.date<M.date?-1:1),x=0,v=0,k=0,b=0,E=0,I=0;for(let T of f)x+=T.tasks,v+=T.input,k+=T.output,b+=T.cacheRead,E+=T.cacheCreate,I+=T.cost;let C=Object.entries(d).map(([T,M])=>({agent_id:T,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((T,M)=>M.cost-T.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:v+k+b+E,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(w-_)/_:0},days:f,perAgent:C}}function Jl(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+`
6208
+ `).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,m=0,h=0,w=0,_=0,S=0,g={},d={};for(let T of n){let M=Vt(T),P=gr(T.model),j=hr[P],B=(T.tier2_input_tokens||0)/1e6*j.input*.5+(T.tier2_output_tokens||0)/1e6*j.output*.5+(T.tier2_cache_read_tokens||0)/1e6*j.cacheRead*.5+(T.tier2_cache_create_tokens||0)/1e6*j.cacheCreate*.5,se=(T.input_tokens||0)+(T.tier2_input_tokens||0),F=(T.output_tokens||0)+(T.tier2_output_tokens||0),ee=(T.cache_read_tokens||0)+(T.tier2_cache_read_tokens||0),V=(T.cache_create_tokens||0)+(T.tier2_cache_create_tokens||0);u+=M,T.day>=s&&(p+=M,w+=T.tasks||0),T.day>=i&&T.day<s&&(S+=M,_+=T.tasks||0),T.day===r&&(l+=M),T.day===o&&(c+=M),T.day===r&&(m+=B),T.day>=s&&(h+=B);let N=g[T.day]||(g[T.day]={date:T.day,tasks:0,input:0,output:0,cacheRead:0,cacheCreate:0,cost:0,tier2:0,agents:{}});N.tasks+=T.tasks||0,N.input+=se,N.output+=F,N.cacheRead+=ee,N.cacheCreate+=V,N.cost+=M,N.tier2+=B;let ie=N.agents[T.agent_id]||(N.agents[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});ie.tasks+=T.tasks||0,ie.cost+=M,ie.tier2+=B,ie.input+=se,ie.output+=F,ie.cacheRead+=ee,ie.cacheCreate+=V,T.model&&(ie.model=T.model);let q=d[T.agent_id]||(d[T.agent_id]={tasks:0,cost:0,input:0,output:0,cacheRead:0,cacheCreate:0,tier2:0,model:T.model});q.tasks+=T.tasks||0,q.cost+=M,q.tier2+=B,q.input+=se,q.output+=F,q.cacheRead+=ee,q.cacheCreate+=V,T.model&&(q.model=T.model)}let f=Object.values(g).sort((T,M)=>T.date<M.date?-1:1),x=0,v=0,k=0,b=0,E=0,I=0;for(let T of f)x+=T.tasks,v+=T.input,k+=T.output,b+=T.cacheRead,E+=T.cacheCreate,I+=T.cost;let C=Object.entries(d).map(([T,M])=>({agent_id:T,...M,tokens:M.input+M.output+M.cacheRead+M.cacheCreate})).sort((T,M)=>M.cost-T.cost);return{range:e,generatedAt:new Date().toISOString(),kpis:{spendToday:l,spendYesterday:c,spend7d:p,spend30d:u,tier2Today:m,tier2_7d:h,tier2PctToday:l>0?m/l:0,spendRange:I,avgDailyRange:f.length?I/f.length:0,tasksRange:x,tokensRange:v+k+b+E,cacheHitRange:b+v>0?b/(b+v):0,costPerTaskRange:x>0?I/x:0,spendDeltaWoW:S>0?(p-S)/S:0,tasksDeltaWoW:_>0?(w-_)/_:0},days:f,perAgent:C}}function Vl(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+`
6194
6209
  `+a.join(`
6195
6210
  `)+`
6196
- `}import{resolve as Vl}from"path";import{existsSync as Yl}from"fs";import Ql from"better-sqlite3";function Zl(){let t=Vl(process.cwd(),".agentx/intent/ledger.sqlite");if(!Yl(t))return null;try{let e=new Ql(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-br>6e4&&(br=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var br=0;function ke(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ec(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 yr(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=Zl();if(!r)return ke(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=ec(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":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6211
+ `}import{resolve as Yl}from"path";import{existsSync as Ql}from"fs";import Zl from"better-sqlite3";function ec(){let t=Yl(process.cwd(),".agentx/intent/ledger.sqlite");if(!Ql(t))return null;try{let e=new Zl(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-yr>6e4&&(yr=a,console.error(`[ledger-panel] openReadOnly failed: ${e?.message??e}`)),null}}var yr=0;function _e(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function tc(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 wr(t,e,a){if(!a.startsWith("/api/admin/ledger/"))return!1;let n=a.replace(/^\/api\/admin\/ledger\//,"").split("?")[0],r=ec();if(!r)return _e(e,503,{error:"intent ledger not available",rows:[]}),!0;try{let o=new URL(t.url||"/","http://_"),s=tc(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":"",m=s!==void 0?"WHERE decided_at >= @since":"",h=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_events ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),w=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_decisions ${m}`).get({since:s}).n,_=r.db.prepare(`SELECT outcome, COUNT(*) AS n FROM intent_decisions ${m} GROUP BY outcome ORDER BY n DESC`).all({since:s}),S=r.db.prepare(`SELECT COUNT(*) AS n FROM intent_divergences ${u}`).get({since:s}).n,g=r.db.prepare(`SELECT source, COUNT(*) AS n FROM intent_divergences ${u} GROUP BY source ORDER BY n DESC`).all({since:s}),d=r.db.prepare(`
6197
6212
  SELECT COUNT(*) AS n FROM intent_decisions d
6198
6213
  LEFT JOIN intent_resolutions r
6199
6214
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6200
6215
  WHERE d.outcome = 'dispatched' AND r.decision_event_id IS NULL
6201
- `).get().n;return ke(e,200,{since:s??null,eventsBySource:h,totalDecisions:w,decisionsByOutcome:_,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i),l&&(u.push("project = @project"),m.project=l);let h=`
6216
+ `).get().n;return _e(e,200,{since:s??null,eventsBySource:h,totalDecisions:w,decisionsByOutcome:_,totalDivergences:S,divergencesBySource:g,inFlight:d}),!0}if(n==="events"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i),l&&(u.push("project = @project"),m.project=l);let h=`
6202
6217
  SELECT id, ts, source, source_event_id, project, subject, intent
6203
6218
  FROM intent_events
6204
6219
  ${u.length?"WHERE "+u.join(" AND "):""}
6205
6220
  ORDER BY ts DESC LIMIT @limit
6206
- `;return ke(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="divergences"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i);let h=`
6221
+ `;return _e(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="divergences"){let u=[],m={limit:p};s!==void 0&&(u.push("ts >= @since"),m.since=s),i&&(u.push("source = @source"),m.source=i);let h=`
6207
6222
  SELECT ts, source, decided_by,
6208
6223
  legacy_agent_id, legacy_outcome, legacy_reason,
6209
6224
  ledger_agent_id, ledger_outcome, ledger_reason,
@@ -6211,7 +6226,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6211
6226
  FROM intent_divergences
6212
6227
  ${u.length?"WHERE "+u.join(" AND "):""}
6213
6228
  ORDER BY ts DESC LIMIT @limit
6214
- `;return ke(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(u.push("e.source = @source"),m.source=i);let h=`
6229
+ `;return _e(e,200,{rows:r.db.prepare(h).all(m)}),!0}if(n==="active"){let u=["d.outcome = 'dispatched'","r.decision_event_id IS NULL"],m={limit:p};i&&(u.push("e.source = @source"),m.source=i);let h=`
6215
6230
  SELECT e.id AS event_id, e.ts, e.source, e.project, e.subject, e.intent,
6216
6231
  d.decided_by, d.decided_at, d.agent_id, d.reason
6217
6232
  FROM intent_decisions d
@@ -6220,7 +6235,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6220
6235
  ON r.decision_event_id = d.event_id AND r.decision_decided_by = d.decided_by
6221
6236
  WHERE ${u.join(" AND ")}
6222
6237
  ORDER BY d.decided_at DESC LIMIT @limit
6223
- `;return ke(e,200,{rows:r.db.prepare(h).all(m)}),!0}return ke(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return ke(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function wr(t={}){return L({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6238
+ `;return _e(e,200,{rows:r.db.prepare(h).all(m)}),!0}return _e(e,404,{error:"unknown ledger slice",rows:[]}),!0}catch(o){return _e(e,500,{error:o?.message??String(o),rows:[]}),!0}finally{r.close()}}function kr(t={}){return L({title:"AgentX \xB7 Ledger",activeTab:"graph",subtitle:"Ledger",body:`<div class="ax-led">
6224
6239
  <header class="ax-led__head">
6225
6240
  <h1>Intent ledger</h1>
6226
6241
  <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>
@@ -6425,7 +6440,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6425
6440
  }
6426
6441
  load();
6427
6442
  })();
6428
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function kr(t={}){return L({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6443
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function _r(t={}){return L({title:"AgentX \xB7 Cost",activeTab:"cost",subtitle:"Cost",body:`<div class="ax-cost">
6429
6444
  <header class="ax-cost__head">
6430
6445
  <div>
6431
6446
  <h1>Cost</h1>
@@ -6998,7 +7013,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
6998
7013
  load();
6999
7014
  setInterval(load, 30000);
7000
7015
  })();
7001
- </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function _r(t={}){let e=`<div class="ax-pj__root">
7016
+ </script>`,peers:t.peers,currentPeerId:t.currentPeerId})}function Er(t={}){let e=`<div class="ax-pj__root">
7002
7017
  <aside class="ax-pj__list">
7003
7018
  <header>
7004
7019
  <h2>Projects</h2>
@@ -7025,7 +7040,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7025
7040
  </header>
7026
7041
  <div id="pj-detail-body" class="ax-pj__detail-body"></div>
7027
7042
  </section>
7028
- </div>`;return L({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:tc,scripts:`<script>${ac}</script>`})}var tc=`
7043
+ </div>`;return L({title:"AgentX \xB7 Projects",activeTab:"projects",subtitle:"Projects",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:ac,scripts:`<script>${nc}</script>`})}var ac=`
7029
7044
  .ax-pj__root {
7030
7045
  display: grid;
7031
7046
  grid-template-columns: 360px 1fr;
@@ -7212,7 +7227,7 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7212
7227
  }
7213
7228
  .ax-pj__warn { color: var(--ax-warn, #facc15); border-top: 1px solid var(--ax-border); }
7214
7229
  .ax-pj__hint { font-size: 11px; color: var(--ax-fg-muted, var(--ax-text)); margin-top: 4px; }
7215
- `,ac=`
7230
+ `,nc=`
7216
7231
  (function(){
7217
7232
  const $ = (sel) => document.querySelector(sel);
7218
7233
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\\"":"&quot;"}[c]));
@@ -7862,9 +7877,9 @@ setInterval(function(){ if (document.visibilityState === 'visible' && !document.
7862
7877
  load();
7863
7878
  });
7864
7879
  })();
7865
- `;import{resolve as Zt,join as gc}from"path";import{existsSync as ea,readdirSync as xc,readFileSync as vc}from"fs";import bc from"better-sqlite3";var Sr=String.raw`[\w.-]+(?:/[\w.-]+)+`,nc=new RegExp(`^(?:chat:)?(${Sr}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),rc=new RegExp(`^\\[(?:GitLab|GitHub) (${Sr}) `);function Er(t){if(!t)return null;let e=t.match(nc);return e?e[1]:null}function Vt(t){if(!t)return null;let e=t.trimStart().match(rc);return e?e[1]:null}function gt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Er(typeof n?.chatId=="string"?n.chatId:null)??Er(e)??Vt(a)}function oc(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function xt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var sc=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,ic=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,lc=t=>/^issue/i.test(t)?"issue":"mr";function cc(t){let e=t.subject.match(sc)??t.inputPreview.trimStart().match(ic);return e?{kind:lc(e[1]),n:Number(e[2])}:null}function dc(t,e=8){let a=[],n=new Set;for(let r of t.matchAll(/(?:^|[\s(,])!(\d{1,6})\b/g)){let o=Number(r[1]);if(!n.has(o)&&(n.add(o),a.push({kind:"mr",n:o}),a.length>=e))break}return a}function Tr(t){if(!oc(t.projectId))return[];let e=cc(t);return e?[e]:dc(t.inputPreview)}var pc=6e4,uc=5*6e4,mc=40,Ar=6,Cr=new Map;function Ir(t){let e=new Map,a=[...t].sort((n,r)=>r.startedAt-n.startedAt);for(let n of a){let r=n.channelId==="github"||/\bpull:\d+/.test(n.subject);for(let o of Tr(n)){let s=xt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=mc)return[...e.values()]}}return[...e.values()]}async function Mr(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=xt(s.project,s.ref),l=Cr.get(i);l&&n-l.at<(s.github?uc:pc)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Ar)await Promise.all(o.slice(s,s+Ar).map(async i=>{let l=xt(i.project,i.ref),c=null;try{c=i.github?await hc(i,e,a):await fc(i,e,a)}catch{}Cr.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Lr(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 fc(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 Lr(`${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 hc(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 Lr(`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}var Yt=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function Rr(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=ln(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=Yt(o.from,80);if(s){a.callback={from:s,status:Yt(o.status,20)??"done"};let i=Yt(o.peer,80);i&&(a.callback.peer=i)}}return a}function ta(){let t=Zt(process.cwd(),".agentx/intent/ledger.sqlite");if(!ea(t))return null;try{let e=new bc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-$r>6e4&&($r=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var $r=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={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 yc(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)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 Pe)return s}return"workflow"}return t}function Or(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 wc(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 Nr(t,e,a){return qa(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 kc(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:G(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&&!Qt(l))return{id:l,name:l,avatar:G(l),kind:"a2a"}}let i=o||r||s;if(i&&!Qt(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:G(i),kind:Ec(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&&!Qt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=Pr(p);return{id:c,name:l||i||c,avatar:G(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:G(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:G(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:G(i),kind:Pr(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:G(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:G(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:G(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:G(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:G(o),kind:"whatsapp"}}}return null}var _c={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Ec(t,e){let a=_c[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function Pr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Qt(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 G(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 Dr(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}
7880
+ `;import{resolve as ea,join as xc}from"path";import{existsSync as ta,readdirSync as vc,readFileSync as bc}from"fs";import yc from"better-sqlite3";var Tr=String.raw`[\w.-]+(?:/[\w.-]+)+`,rc=new RegExp(`^(?:chat:)?(${Tr}):(?:issue|issues|merge_request|mr|pull|pr)s?:\\d+`),oc=new RegExp(`^\\[(?:GitLab|GitHub) (${Tr}) `);function Sr(t){if(!t)return null;let e=t.match(rc);return e?e[1]:null}function Yt(t){if(!t)return null;let e=t.trimStart().match(oc);return e?e[1]:null}function gt(t,e,a){let n=t&&typeof t=="object"?t.context:null;return n&&typeof n.project=="string"&&n.project.trim()?n.project.trim():Sr(typeof n?.chatId=="string"?n.chatId:null)??Sr(e)??Yt(a)}function sc(t){let[e,...a]=t.split("/");return!a.length||e==="unmapped"||a[0].startsWith("_")?null:t}function xt(t,e){return`${t}${e.kind==="mr"?"!":"#"}${e.n}`}var ic=/\b(issue|merge_request|pull|MR|Issue)s?[:\s]+[#!]?(\d+)/,lc=/^\[(?:GitLab|GitHub) \S+ (issue|merge_request|pull|MR|Issue)s? [#!]?(\d+)/i,cc=t=>/^issue/i.test(t)?"issue":"mr";function dc(t){let e=t.subject.match(ic)??t.inputPreview.trimStart().match(lc);return e?{kind:cc(e[1]),n:Number(e[2])}:null}function pc(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 Ar(t){if(!sc(t.projectId))return[];let e=dc(t);return e?[e]:pc(t.inputPreview)}var uc=6e4,mc=5*6e4,fc=40,Cr=6,Ir=new Map;function Mr(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 Ar(n)){let s=xt(n.projectId,o);if(e.has(s)||e.set(s,{project:n.projectId,ref:o,github:r}),e.size>=fc)return[...e.values()]}}return[...e.values()]}async function Lr(t,e,a=fetch,n=Date.now()){let r={},o=[];for(let s of t){let i=xt(s.project,s.ref),l=Ir.get(i);l&&n-l.at<(s.github?mc:uc)?l.item&&(r[i]=l.item):o.push(s)}for(let s=0;s<o.length;s+=Cr)await Promise.all(o.slice(s,s+Cr).map(async i=>{let l=xt(i.project,i.ref),c=null;try{c=i.github?await gc(i,e,a):await hc(i,e,a)}catch{}Ir.set(l,{at:n,item:c}),c&&(r[l]=c)}));return r}async function Rr(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 hc(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 Rr(`${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 gc(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 Rr(`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}var Qt=(t,e)=>typeof t=="string"&&t.trim()?t.trim().slice(0,e):void 0;function $r(t){let e=t&&typeof t=="object"?t.context:void 0;if(!e||typeof e!="object")return{};let a={},n=dn(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=Qt(o.from,80);if(s){a.callback={from:s,status:Qt(o.status,20)??"done"};let i=Qt(o.peer,80);i&&(a.callback.peer=i)}}return a}function aa(){let t=ea(process.cwd(),".agentx/intent/ledger.sqlite");if(!ta(t))return null;try{let e=new yc(t,{readonly:!0,fileMustExist:!0});return{db:e,close:()=>e.close()}}catch(e){let a=Date.now();return a-Pr>6e4&&(Pr=a,console.error(`[activity-graph] openLedger failed: ${e?.message??e}`)),null}}var Pr=0;function he(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}var Pe={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 wc(t,e,a){if(t==="mesh"){let n=a?.context?.channel;if(typeof n=="string"&&n in Pe)return n;if(e.startsWith("mesh.")){let r=e.slice(5);if(r==="a2a")return"a2a";if(r in Pe)return r}return"mesh"}if(t==="workflow"){let n=a?.event?.payload,r=typeof n?.channel=="string"?n.channel:"";if(r&&r in Pe)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 Pe)return s}return"workflow"}return t}function Nr(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 kc(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 Dr(t,e,a){return Ua(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 _c(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:G(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&&!Zt(l))return{id:l,name:l,avatar:G(l),kind:"a2a"}}let i=o||r||s;if(i&&!Zt(r||o||"")){let l=r||o||s;return{id:l,name:o||r||l,avatar:G(i),kind:Sc(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&&!Zt(i||l||"")){let p=typeof n.channel=="string"?n.channel:"",u=jr(p);return{id:c,name:l||i||c,avatar:G(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:G(c),kind:"gitlab"}}let i=o.sender;if(i?.login)return{id:i.login,name:i.login,avatar:G(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:G(i),kind:jr(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:G(o),kind:"gitlab"}}}if(t==="github"){let n=a.sender||a.payload?.sender;if(n?.login)return{id:n.login,name:n.login,avatar:G(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:G(r),kind:"telegram"}}if(n?.id)return{id:String(n.id),name:n.first_name||`tg:${n.id}`,avatar:G(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:G(o),kind:"whatsapp"}}}return null}var Ec={github:"github",gitlab:"gitlab",a2a:"a2a",voice:"voice",desktop:"desktop",app:"app"};function Sc(t,e){let a=Ec[t.startsWith("mesh.")?t.slice(5):""]??"mesh";return a!=="a2a"&&e.via==="voice"?"voice":a}function jr(t){return t==="telegram"||t==="whatsapp"||t==="slack"||t==="discord"?t:"system"}function Zt(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 G(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 Hr(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}
7866
7881
  ${r}`:n)}e.comment?.body&&a.push(e.comment.body),e.issue?.title&&a.push(e.issue.title+(e.issue.body?`
7867
- ${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 Sc(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 Hr(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7882
+ ${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 Tc(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 Br(t,e,a){let n=Date.now(),r=n-a*3600*1e3,o=t.prepare(`
7868
7883
  SELECT id, ts, source, project, subject, intent, raw_json
7869
7884
  FROM intent_events WHERE ts >= ? ORDER BY ts ASC
7870
7885
  `).all(r),s=new Map,i=new Map;if(o.length>0){let b=o.map(M=>M.id),E=b.map((M,P)=>`@id${P}`).join(","),I=Object.fromEntries(b.map((M,P)=>[`id${P}`,M])),C=t.prepare(`
@@ -7873,9 +7888,9 @@ ${e.issue.body}`:"")),e.pull_request?.title&&a.push(e.pull_request.title),typeof
7873
7888
  `).all(I);for(let M of C)s.has(M.event_id)||s.set(M.event_id,[]),s.get(M.event_id).push(M);let T=t.prepare(`
7874
7889
  SELECT decision_event_id, decision_decided_by, resolved_at, status, duration_ms, result_summary
7875
7890
  FROM intent_resolutions WHERE decision_event_id IN (${E})
7876
- `).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,p=new Map,u=new Map,m=[],h=e?.business?.projects??[],w=e?.business?.contactMap??[],_=Dt(e?.business??{});for(let b of o){let E=null;try{E=JSON.parse(b.raw_json)}catch{}let I=Nr(b.source,E,w),C=Dr(b.source,E),T=Rr(E),M=b.project??gt(E,b.subject,C),P=null,j=null;I?(P=I.client,j=I.project||`${I.client}/_chat`):M&&(P=Ze(M,h),j=M);let B=yc(b.source,b.intent||"",E),oe=Pe[B]||{label:B,color:"#6b7280"};p.has(B)||p.set(B,{id:B,label:oe.label,color:oe.color});let F="__system",ee,V=kc(b.source,b.intent||"",E);if(V){F=V.id,ee=V.kind;let N=I?.displayName||V.name;(!u.has(V.id)||I?.displayName)&&u.set(V.id,{id:V.id,name:N,avatar:G(N),kind:V.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let se=`${b.id}|${N.decided_by}`,q=i.get(se),Ia=N.decided_at,Ma=q?.resolved_at??null,$t=Ma===null,Vs=q?.duration_ms??($t?n-Ia:0),Ys=$t?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",Y,De;if(P)Y=P,De=j;else{let Pt=_.get(N.agent_id);Pt?(Y=Pt,De=`${Pt}/_${b.source}`):(Y="unmapped",De=`unmapped/_${b.source}`)}l.has(Y)||l.set(Y,{id:Y,name:Y,color:Or(Y),projects:[]}),c.has(Y)||c.set(Y,new Set),c.get(Y).add(De),m.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:Y,projectId:De,channelId:B,initiatorId:F,initiatorKind:ee,subject:Sc(b.subject),intent:b.intent||"",startedAt:Ia,resolvedAt:Ma,duration:Vs,active:$t,outcome:Ys,tokens:0,inputPreview:C,system:wc(N.agent_id,e),...T})}}let S=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,E)=>b.id.localeCompare(E.id)),g=[],d=new Set;if(e){let b=e.business??{},E=I=>{let C=b.orgChart?.[I]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[I,C]of Object.entries(e.agents||{})){let T={id:I,name:C.name||I,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:E(I)};g.push(T),d.add(I)}}for(let b of m)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,E)=>b.id.localeCompare(E.id));let f=[],x=new Set;for(let[b,E]of Object.entries(Pe))f.push({id:b,label:E.label,color:E.color}),x.add(b);for(let b of p.values())x.has(b.id)||f.push(b);let v=[...u.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:S,agents:g,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function aa(t){let e=ta();if(!e)return null;try{return Hr(e.db,ve,t)}finally{e.close()}}function Br(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 m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}for(let u of 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 m=Tc(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Or(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,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 Tc(t){if(t.clientId!=="unmapped")return t;let e=Vt(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:Ze(e,a)}}async function vt(t){let e=ve?.channels?.gitlab,a=await Mr(Ir(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 ve=null;function zr(t){ve=t}async function Fr(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=ta();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=qr(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await vt(Hr(n.db,ve,o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Ac=5e3;async function na(t,e,a,n=aa){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
7891
+ `).all(I);for(let M of T)i.set(`${M.decision_event_id}|${M.decision_decided_by}`,M)}let l=new Map,c=new Map,p=new Map,u=new Map,m=[],h=e?.business?.projects??[],w=e?.business?.contactMap??[],_=Dt(e?.business??{});for(let b of o){let E=null;try{E=JSON.parse(b.raw_json)}catch{}let I=Dr(b.source,E,w),C=Hr(b.source,E),T=$r(E),M=b.project??gt(E,b.subject,C),P=null,j=null;I?(P=I.client,j=I.project||`${I.client}/_chat`):M&&(P=Ze(M,h),j=M);let B=wc(b.source,b.intent||"",E),se=Pe[B]||{label:B,color:"#6b7280"};p.has(B)||p.set(B,{id:B,label:se.label,color:se.color});let F="__system",ee,V=_c(b.source,b.intent||"",E);if(V){F=V.id,ee=V.kind;let N=I?.displayName||V.name;(!u.has(V.id)||I?.displayName)&&u.set(V.id,{id:V.id,name:N,avatar:G(N),kind:V.kind})}else u.has("__system")||u.set("__system",{id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});for(let N of s.get(b.id)??[]){if(N.outcome!=="dispatched"||!N.agent_id)continue;let ie=`${b.id}|${N.decided_by}`,q=i.get(ie),Ma=N.decided_at,La=q?.resolved_at??null,$t=La===null,Ys=q?.duration_ms??($t?n-Ma:0),Qs=$t?"active":q?.status==="error"||q?.status==="fail"?"error":"completed",Y,De;if(P)Y=P,De=j;else{let Pt=_.get(N.agent_id);Pt?(Y=Pt,De=`${Pt}/_${b.source}`):(Y="unmapped",De=`unmapped/_${b.source}`)}l.has(Y)||l.set(Y,{id:Y,name:Y,color:Nr(Y),projects:[]}),c.has(Y)||c.set(Y,new Set),c.get(Y).add(De),m.push({id:`${b.id}|${N.decided_by}`,agentId:N.agent_id,clientId:Y,projectId:De,channelId:B,initiatorId:F,initiatorKind:ee,subject:Tc(b.subject),intent:b.intent||"",startedAt:Ma,resolvedAt:La,duration:Ys,active:$t,outcome:Qs,tokens:0,inputPreview:C,system:kc(N.agent_id,e),...T})}}let S=[...l.values()].map(b=>({...b,projects:[...c.get(b.id)||[]].sort()})).sort((b,E)=>b.id.localeCompare(E.id)),g=[],d=new Set;if(e){let b=e.business??{},E=I=>{let C=b.orgChart?.[I]?.role,T=C?b.roles?.[C]?.title:void 0;return typeof T=="string"&&T.trim()?T.trim():void 0};for(let[I,C]of Object.entries(e.agents||{})){let T={id:I,name:C.name||I,tier:C.tier==="claude-code"?"lead":"worker",model:C.model||"",role:C.systemPrompt?C.systemPrompt.split(/[.\n]/)[0].slice(0,60):C.tier||"",title:E(I)};g.push(T),d.add(I)}}for(let b of m)d.has(b.agentId)||(g.push({id:b.agentId,name:b.agentId,tier:"worker",model:"",role:""}),d.add(b.agentId));g.sort((b,E)=>b.id.localeCompare(E.id));let f=[],x=new Set;for(let[b,E]of Object.entries(Pe))f.push({id:b,label:E.label,color:E.color}),x.add(b);for(let b of p.values())x.has(b.id)||f.push(b);let v=[...u.values()];v.find(b=>b.id==="__system")||v.push({id:"__system",name:"Schedule",avatar:"\u23F1",kind:"system"});let k=e?.channels?.gitlab?.host;return{now:n,windowH:a,clients:S,agents:g,channels:f,initiators:v,dispatches:m,forges:{gitlab:typeof k=="string"?k:void 0,github:"https://github.com"}}}function na(t){let e=aa();if(!e)return null;try{return Br(e.db,ve,t)}finally{e.close()}}function zr(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 m=e.get(u.id);if(!m)e.set(u.id,{...u,projects:[...u.projects]});else{let h=Array.from(new Set([...m.projects,...u.projects])).sort();e.set(u.id,{...m,projects:h})}}for(let u of 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 m=Ac(u);if(m.clientId!==u.clientId&&!e.has(m.clientId)&&e.set(m.clientId,{id:m.clientId,name:m.clientId,color:Nr(m.clientId),projects:[]}),m.projectId!==u.projectId){let h=e.get(m.clientId);h.projects.includes(m.projectId)||e.set(m.clientId,{...h,projects:[...h.projects,m.projectId].sort()})}o.push({...m,nodeId:c,id:`${c}::${m.id}`})}}return{now:s||Date.now(),windowH:i||6,localNodeId:t[0]?.nodeId,forges:l,clients:[...e.values()].sort((c,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 Ac(t){if(t.clientId!=="unmapped")return t;let e=Yt(t.inputPreview);if(!e)return t;let a=ve?.business?.projects??[];return{...t,projectId:e,clientId:Ze(e,a)}}async function vt(t){let e=ve?.channels?.gitlab,a=await Lr(Mr(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 ve=null;function Fr(t){ve=t}async function qr(t,e,a){if(a!=="/api/admin/activity-graph"&&!a.startsWith("/api/admin/activity-graph?"))return!1;let n=aa();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=Ur(parseInt(r.searchParams.get("hours")||"6",10));he(e,200,await vt(Br(n.db,ve,o)))}catch(r){he(e,500,{error:r?.message??String(r)})}finally{n.close()}return!0}var Cc=5e3;async function ra(t,e,a,n=na){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
7877
7892
 
7878
- `);let r=new URL(t.url||"/","http://_"),o=qr(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
7893
+ `);let r=new URL(t.url||"/","http://_"),o=Ur(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
7879
7894
 
7880
7895
  `)}catch{i()}},25e3);try{for(;!s;){try{let p=await n(o),u=p&&await vt(p);if(s)break;u?(e.write(`event: snapshot
7881
7896
  `),e.write(`data: ${JSON.stringify(u)}
@@ -7886,7 +7901,7 @@ data: ${JSON.stringify({error:"ledger not available"})}
7886
7901
  `)}catch(p){e.write(`event: error
7887
7902
  data: ${JSON.stringify({error:p?.message??String(p)})}
7888
7903
 
7889
- `)}let c=Date.now();for(;!s&&Date.now()-c<Ac;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function qr(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Cc(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=Zt(process.cwd(),".agentx/task-history",t,n);if(!ea(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=Zt(process.cwd(),".agentx/task-history",t,o);return ea(s)?jr(s,e,a):null}return jr(r,e,a)}function jr(t,e,a){let n=null,r=1/0;for(let o of xc(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(vc(gc(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 Ur(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=ta();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),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Dr(c.source,m),w=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let k=Cc(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(_=k.responseText);let b=k.transcript;Array.isArray(b)&&(S=b.length)}}let g=ve?.business?.projects??[],d=ve?.business?.contactMap??[],f=Dt(ve?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Nr(c.source,m,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||gt(m,c.subject,h)){let k=c.project||gt(m,c.subject,h);x={client:Ze(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=f.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}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:w,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 Rc,readFileSync as $c}from"fs";import{resolve as Gr}from"path";jt();function Wr(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=Ic.replace(/__AGENT_ID__/g,O(e));return L({title:`AgentX \xB7 ${O(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${O(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Mc,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>${Lc}</script>`})}var Ic=`
7904
+ `)}let c=Date.now();for(;!s&&Date.now()-c<Cc;)await new Promise(p=>setTimeout(p,200))}}finally{clearInterval(l);try{e.end()}catch{}}return!0}function Ur(t){return!Number.isFinite(t)||t<1?6:Math.min(720,Math.max(1,t))}function Ic(t,e,a=5e3){let n=new Date(e).toISOString().slice(0,10),r=ea(process.cwd(),".agentx/task-history",t,n);if(!ta(r)){let o=new Date(e-864e5).toISOString().slice(0,10),s=ea(process.cwd(),".agentx/task-history",t,o);return ta(s)?Or(s,e,a):null}return Or(r,e,a)}function Or(t,e,a){let n=null,r=1/0;for(let o of vc(t)){if(!o.endsWith(".json"))continue;let s;try{s=JSON.parse(bc(xc(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 Wr(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=aa();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),m=null;try{m=JSON.parse(c.raw_json)}catch{}let h=Hr(c.source,m),w=m&&typeof m=="object"&&(m.text||m.message?.text||m.message?.caption||m.object_attributes?.note||m.object_attributes?.description||m.comment?.body||m.issue?.body||(typeof m.message=="string"?m.message:null)||(typeof m.prompt=="string"?m.prompt:null)||null)||h,_=null,S=null;if(p.agent_id){let k=Ic(p.agent_id,p.decided_at);if(k){typeof k.responseText=="string"&&(_=k.responseText);let b=k.transcript;Array.isArray(b)&&(S=b.length)}}let g=ve?.business?.projects??[],d=ve?.business?.contactMap??[],f=Dt(ve?.business??{}),x={client:"unmapped",project:`unmapped/_${c.source}`,via:"fallback"},v=Dr(c.source,m,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||gt(m,c.subject,h)){let k=c.project||gt(m,c.subject,h);x={client:Ze(k,g),project:k,via:c.project?`project namespace prefix (${k})`:`forge path in chat id / message (${k})`}}else if(p.agent_id){let k=f.get(p.agent_id);k&&(x={client:k,project:`${k}/_${c.source}`,via:`orgChart fallback (agent ${p.agent_id} reports up to a PM whose project belongs to ${k})`})}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:w,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 $c,readFileSync as Pc}from"fs";import{resolve as Xr}from"path";jt();function Gr(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=Mc.replace(/__AGENT_ID__/g,O(e));return L({title:`AgentX \xB7 ${O(e)}`,activeTab:"admin",subtitle:`Agent \xB7 ${O(e)}`,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:r,css:Lc,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>${Rc}</script>`})}var Mc=`
7890
7905
  <!-- Breadcrumb -->
7891
7906
  <div class="ax-crumb">
7892
7907
  <a href="/admin">Settings</a>
@@ -8475,7 +8490,7 @@ data: ${JSON.stringify({error:p?.message??String(p)})}
8475
8490
  </div>
8476
8491
  </div>
8477
8492
  </div>
8478
- `,Mc=`
8493
+ `,Lc=`
8479
8494
  /* Agent-specific layout + legacy styles for bits the migration left in
8480
8495
  * place (EasyMDE theming, skills tree, plain-editor). Shared chrome + tab
8481
8496
  * primitives live in components.css.ts. */
@@ -8594,7 +8609,7 @@ textarea.inp.mono { font-family: var(--ax-mono); }
8594
8609
 
8595
8610
  /* Agent-specific button variant used in rail context (no ax-btn wrapper) */
8596
8611
  .ax-btn.lg { padding: 9px 16px; font-size: 13px; }
8597
- `,Lc=`
8612
+ `,Rc=`
8598
8613
  const $ = (id) => document.getElementById(id);
8599
8614
  const state = { agent: null, activeSkill: null, activeSkillFile: null, identityPath: null };
8600
8615
 
@@ -9450,15 +9465,15 @@ document.addEventListener('keydown', (e) => {
9450
9465
  /* ===== Boot ===== */
9451
9466
  initOptsToggles();
9452
9467
  loadAgent();
9453
- `;function Xr(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Wr({agentId:a,peers:n,localToken:r}))}async function Kr(t,e,a){try{let n=t.method==="GET"?void 0:await td(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){bt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Fe(i),"PATCH ":()=>Pc(i,n),"PATCH capability":()=>Nc(i,n),"POST mcp":()=>jc(i,n),"DELETE mcp":()=>Oc(i,n),"GET identity":()=>Dc(i),"GET identity/file":()=>Hc(i,String(o.path||"")),"PUT identity/file":()=>Bc(i,n),"GET skills":()=>zc(i),"POST skills":()=>Fc(i,n),"DELETE skills":()=>qc(i,n),"GET skills/tree":()=>Uc(i,String(o.slug||"")),"GET skills/file":()=>Wc(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Gc(i,n),"GET skills/deps":()=>Xc(i,String(o.slug||"")),"POST skills/install":()=>Kc(i,n,t),"POST skills/deps":()=>Jc(i,n,t),"GET channels":()=>Vc(i),"GET activity":()=>Yc(i,t),"GET handovers":()=>Qc(i),"POST handovers":()=>Zc(i,n),"DELETE handovers":()=>ed(n)}[c];if(!u){bt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();bt(e,200,m)}catch(n){bt(e,400,{error:n?.message||"agent op failed"})}}function Jr(){let t=Gr(process.cwd(),"agentx.json");return Rc(t)?JSON.parse($c(t,"utf-8")):null}function X(t){let e=Jr();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 Fe(t){let{def:e,cfg:a}=X(t),n=e.workspace?Le(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 Pc(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:Fe(t)}}function jc(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:Fe(t)}}function Oc(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:Fe(t)}}function Nc(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:Fe(t)}}function Dc(t){let{def:e}=X(t);return Le(e.workspace)}function Hc(t,e){if(!e)throw new Error("path query param required");let{def:a}=X(t);return nt(a.workspace,e)}function Bc(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=X(t);return rt(n.workspace,a,String(e?.content??""))}function zc(t){let{def:e}=X(t),a=Le(e.workspace);return{skills:a.skills,workspace:a.workspace}}function Fc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return ot(n.workspace,a,{title:e?.title,content:e?.content})}function qc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return st(n.workspace,a)}function Uc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t),n=dn(a.workspace,e),r=it(a.workspace,e);return{slug:e,tree:n,deps:r}}function Wc(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=X(t);return pn(n.workspace,e,a)}function Gc(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=X(t);return un(r.workspace,a,n,String(e?.content??""))}function Xc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t);return it(a.workspace,e)}async function Kc(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=Vr(e?.worker),{def:o}=X(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(`
9454
- `);return Yr(a,r,s,`install-${n}:${Date.now()}`)}async function Jc(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Vr(e?.worker),{def:o}=X(t),s=it(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=Gr(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(`
9455
- `);return Yr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Vr(t){if(t&&typeof t=="string")return t;let e=te();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Yr(t,e,a,n){let r=te(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Vc(t){let e=Jr(),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 Yc(t,e){try{let n=(te().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function ra(){return new Pa}function Qc(t){let e=ra(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function Zc(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 ed(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 bt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function td(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 _e={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 Qr=[{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 oa(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(_e)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9468
+ `;function Kr(t,e,a,n=[],r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Gr({agentId:a,peers:n,localToken:r}))}async function Jr(t,e,a){try{let n=t.method==="GET"?void 0:await ad(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){bt(e,404,{error:`unknown agent endpoint: ${a}`});return}let i=s[1],l=s[2]||"",c=`${t.method} ${l}`,u={"GET ":()=>Fe(i),"PATCH ":()=>jc(i,n),"PATCH capability":()=>Dc(i,n),"POST mcp":()=>Oc(i,n),"DELETE mcp":()=>Nc(i,n),"GET identity":()=>Hc(i),"GET identity/file":()=>Bc(i,String(o.path||"")),"PUT identity/file":()=>zc(i,n),"GET skills":()=>Fc(i),"POST skills":()=>qc(i,n),"DELETE skills":()=>Uc(i,n),"GET skills/tree":()=>Wc(i,String(o.slug||"")),"GET skills/file":()=>Gc(i,String(o.slug||""),String(o.path||"")),"PUT skills/file":()=>Xc(i,n),"GET skills/deps":()=>Kc(i,String(o.slug||"")),"POST skills/install":()=>Jc(i,n,t),"POST skills/deps":()=>Vc(i,n,t),"GET channels":()=>Yc(i),"GET activity":()=>Qc(i,t),"GET handovers":()=>Zc(i),"POST handovers":()=>ed(i,n),"DELETE handovers":()=>td(n)}[c];if(!u){bt(e,404,{error:`unknown agent sub-endpoint: ${c}`});return}let m=await u();bt(e,200,m)}catch(n){bt(e,400,{error:n?.message||"agent op failed"})}}function Vr(){let t=Xr(process.cwd(),"agentx.json");return $c(t)?JSON.parse(Pc(t,"utf-8")):null}function X(t){let e=Vr();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 Fe(t){let{def:e,cfg:a}=X(t),n=e.workspace?Re(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 jc(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:Fe(t)}}function Oc(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:Fe(t)}}function Nc(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:Fe(t)}}function Dc(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:Fe(t)}}function Hc(t){let{def:e}=X(t);return Re(e.workspace)}function Bc(t,e){if(!e)throw new Error("path query param required");let{def:a}=X(t);return nt(a.workspace,e)}function zc(t,e){let a=String(e?.path||"");if(!a)throw new Error("path required");let{def:n}=X(t);return rt(n.workspace,a,String(e?.content??""))}function Fc(t){let{def:e}=X(t),a=Re(e.workspace);return{skills:a.skills,workspace:a.workspace}}function qc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return ot(n.workspace,a,{title:e?.title,content:e?.content})}function Uc(t,e){let a=String(e?.slug||"").trim();if(!a)throw new Error("slug required");let{def:n}=X(t);return st(n.workspace,a)}function Wc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t),n=un(a.workspace,e),r=it(a.workspace,e);return{slug:e,tree:n,deps:r}}function Gc(t,e,a){if(!e||!a)throw new Error("slug and path query params required");let{def:n}=X(t);return mn(n.workspace,e,a)}function Xc(t,e){let a=String(e?.slug||""),n=String(e?.path||"");if(!a||!n)throw new Error("slug and path required");let{def:r}=X(t);return fn(r.workspace,a,n,String(e?.content??""))}function Kc(t,e){if(!e)throw new Error("slug query param required");let{def:a}=X(t);return it(a.workspace,e)}async function Jc(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=Yr(e?.worker),{def:o}=X(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(`
9469
+ `);return Qr(a,r,s,`install-${n}:${Date.now()}`)}async function Vc(t,e,a){let n=String(e?.slug||"").trim();if(!n)throw new Error("slug required");let r=Yr(e?.worker),{def:o}=X(t),s=it(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=Xr(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(`
9470
+ `);return Qr(a,r,l,`deps-${t}-${n}:${Date.now()}`)}function Yr(t){if(t&&typeof t=="string")return t;let e=te();return e.dashboard?.draftAgent||e.node?.defaultAgent||Object.keys(e.agents).find(a=>a.includes("devops"))||Object.keys(e.agents)[0]}async function Qr(t,e,a,n){let r=te(),o=(r.dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),s={"Content-Type":"application/json"},i=t.headers.authorization;i?s.Authorization=String(i):r.dashboard.token&&(s.Authorization=`Bearer ${r.dashboard.token}`);let l=await fetch(`${o}/task`,{method:"POST",headers:s,body:JSON.stringify({agent:e,message:a,context:{channel:"admin",sender:"admin-ui",chatId:n}})}),c=await l.text(),p;try{p=JSON.parse(c)}catch{p={content:c}}if(!l.ok)throw new Error(p?.error||`daemon /task HTTP ${l.status}`);return{worker:e,taskId:p?.taskId,content:p?.content,duration:p?.duration,error:p?.error}}function Yc(t){let e=Vr(),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 Qc(t,e){try{let n=(te().dashboard.daemonUrl||"http://localhost:18800").replace(/\/+$/,""),r=await fetch(`${n}/agents`);if(!r.ok)throw new Error(`daemon HTTP ${r.status}`);let s=(await r.json()).find(i=>i.id===t);return{activeTasks:s?.activeTasks??0,totalTasks:s?.totalTasks??0,errors:s?.errors??0,lastActive:s?.lastActive??null,runningTasks:s?.runningTasks??[],lastSummary:s?.lastSummary??null}}catch(a){return{error:a?.message,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]}}}function oa(){return new ja}function Zc(t){let e=oa(),{incoming:a,outgoing:n}=e.listByAgent(t);return{incoming:a,outgoing:n}}function ed(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=oa().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 td(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:oa().remove(e,a,n)?"Released":"No active handover for that chat"}}function bt(t,e,a){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(a))}function ad(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 Ee={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 Zr=[{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 sa(t={}){let e=`<script>window.UI_LABELS = ${JSON.stringify(Ee)};</script>`,a=`<span id="ts" class="ax-mono" title="Last update">\u2014</span>
9456
9471
  <span id="conn-dot" class="ax-dot ax-dot--ok ax-dot--pulse" title="connected"></span>
9457
9472
  <span id="conn-label">live</span>`,n=`<div class="ax-app-live">
9458
9473
  <section id="statstrip" class="ax-statstrip"></section>
9459
9474
  <main id="grid" class="ax-live__body"></main>
9460
9475
  </div>
9461
- `;return L({title:`${_e.brand} \xB7 ${_e.subtitle}`,activeTab:"live",subtitle:_e.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:ad,scripts:e+`<script>${nd}</script>`,headExtras:`<script>
9476
+ `;return L({title:`${Ee.brand} \xB7 ${Ee.subtitle}`,activeTab:"live",subtitle:Ee.subtitle,peers:t.peers,currentPeerId:t.currentPeerId,customHeader:void 0,noMain:!0,body:n,css:nd,scripts:e+`<script>${rd}</script>`,headExtras:`<script>
9462
9477
  // rightExtras for the topbar are injected at runtime \u2014 they reference
9463
9478
  // IDs (#ts, #conn-dot) that the script below addresses directly.
9464
9479
  document.addEventListener('DOMContentLoaded', () => {
@@ -9469,7 +9484,7 @@ loadAgent();
9469
9484
  extras.innerHTML = ${JSON.stringify(a)};
9470
9485
  right.insertBefore(extras, right.firstChild);
9471
9486
  });
9472
- </script>`})}var ad=`
9487
+ </script>`})}var nd=`
9473
9488
  /* --- Page frame --- */
9474
9489
  .ax-app-live { min-height: 100vh; display: flex; flex-direction: column; }
9475
9490
 
@@ -9676,7 +9691,7 @@ loadAgent();
9676
9691
  border-top-color: var(--ax-accent); border-radius: 50%;
9677
9692
  animation: ax-spin 800ms linear infinite; display: inline-block;
9678
9693
  }
9679
- @keyframes ax-spin { to { transform: rotate(360deg); } }`,nd=`
9694
+ @keyframes ax-spin { to { transform: rotate(360deg); } }`,rd=`
9680
9695
  'use strict';
9681
9696
 
9682
9697
  const ui = { nodes: new Map(), summary: { nodes: 0, agents: 0, busy: 0, errors: 0 } };
@@ -10247,7 +10262,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10247
10262
  });
10248
10263
  }
10249
10264
 
10250
- `;var Zr=`
10265
+ `;var eo=`
10251
10266
  .mx-content{max-width:1180px;margin:0 auto;padding:0 24px 56px}
10252
10267
  .mx-updated{margin:0;color:var(--ax-muted);font-size:11px;font-family:var(--ax-mono)}
10253
10268
  .mx-section{margin-bottom:28px}.mx-section .ax-section-head{margin-bottom:14px}
@@ -10421,7 +10436,7 @@ function taskAction(nodeUrl, taskId, kind, body, hooks) {
10421
10436
  .mx-summary{max-width:56vw}
10422
10437
  }
10423
10438
  @media(prefers-reduced-motion:reduce){.mx-drawer{transition:none}}
10424
- `;var eo=`<script>
10439
+ `;var to=`<script>
10425
10440
  window.MX=(function(){
10426
10441
  var ENT={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
10427
10442
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return ENT[c]})}
@@ -10530,7 +10545,7 @@ window.MX=(function(){
10530
10545
  verdict:verdict,verdictChip:verdictChip,mark:mark,causeLabel:causeLabel,
10531
10546
  setHealth:setHealth,get:get};
10532
10547
  })();
10533
- </script>`;var to=`<script>
10548
+ </script>`;var ao=`<script>
10534
10549
  window.MXD=(function(){
10535
10550
  function el(id){return document.getElementById(id)}
10536
10551
  function tz(){return -new Date().getTimezoneOffset()}
@@ -10744,7 +10759,7 @@ window.MXD=(function(){
10744
10759
 
10745
10760
  return {openDay:openDay,openJob:openJob,openConversation:openConversation};
10746
10761
  })();
10747
- </script>`;var ao=`<script>
10762
+ </script>`;var no=`<script>
10748
10763
  (function(){
10749
10764
  var LANES=[
10750
10765
  {id:'cron',name:'Scheduled',hint:'cron jobs'},
@@ -11060,7 +11075,7 @@ window.MXD=(function(){
11060
11075
  window.addEventListener('scroll',hideTip,{passive:true});
11061
11076
  load();
11062
11077
  })();
11063
- </script>`;var no=`<script>
11078
+ </script>`;var ro=`<script>
11064
11079
  (function(){
11065
11080
  var showAll=document.getElementById('mx-show-all'),expanded=false;
11066
11081
  var esc=MX.esc;
@@ -11238,7 +11253,7 @@ window.MXD=(function(){
11238
11253
  }
11239
11254
  load();setInterval(load,5000);
11240
11255
  })();
11241
- </script>`;var ro=`
11256
+ </script>`;var oo=`
11242
11257
  .mx-rt-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px}
11243
11258
  .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}
11244
11259
  .mx-rt-wrap > .mx-empty{border:0}
@@ -11279,7 +11294,7 @@ window.MXD=(function(){
11279
11294
  .mx-rt-msg td{display:block}.mx-rt-msg td::before{content:none}
11280
11295
  .mx-rt-name{max-width:100%}
11281
11296
  }
11282
- `,oo=`<script>
11297
+ `,so=`<script>
11283
11298
  (function(){
11284
11299
  var root=document.getElementById('mx-routines');
11285
11300
  var bar=document.getElementById('mx-rt-filter');
@@ -11406,7 +11421,7 @@ window.MXD=(function(){
11406
11421
  syncBar();
11407
11422
  document.addEventListener('mx:snapshot',function(e){render(e.detail||{})});
11408
11423
  })();
11409
- </script>`;var so=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],io=`<script>
11424
+ </script>`;var io=[{id:"all",label:"All"},{id:"peers",label:"Other machines"},{id:"announce",label:"Announcements"},{id:"problems",label:"Problems"}],lo=`<script>
11410
11425
  (function(){
11411
11426
  var root=document.getElementById('mx-feed');
11412
11427
  if(!root)return;
@@ -11481,12 +11496,12 @@ window.MXD=(function(){
11481
11496
  }
11482
11497
  load();setInterval(load,5000);
11483
11498
  })();
11484
- </script>`;var Q={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 Z(t,e,a,n,r=""){return W({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var rd=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],od=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],sd=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function lo(t){let e=lt({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+ct([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
11499
+ </script>`;var Q={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 Z(t,e,a,n,r=""){return W({icon:t,title:e,lead:a,actionHtml:r}).replace("<h2>",`<h2 id="${n}">`)}var od=[{id:"all",label:"All"},{id:"attention",label:"Flagged"},{id:"schedule",label:"Schedules"},{id:"event",label:"Events"}],sd=[{id:"activity",label:"Activity"},{id:"lifetime",label:"Lifetime"},{id:"ops",label:"Operations"}],id=[{days:0,label:"Today"},{days:7,label:"7d"},{days:30,label:"30d"},{days:90,label:"90d"}];function co(t){let e=lt({kicker:"Operations",title:"Mesh operations",lead:"What the fleet actually did, how long it lived, and which of it was worth running."})+ct([{kind:"off",num:"-",label:"Nodes online"},{kind:"off",num:"-",label:"Tasks running"},{kind:"off",num:"-",label:"Failed today"},{kind:"off",num:"-",label:"Jobs needing review"}]).replace('<div class="ax-health-strip">','<div class="ax-health-strip" id="mx-health">'),a=`<div class="mx-toolbar">
11485
11500
  <div class="mx-tabs" role="tablist" aria-label="Mesh views">
11486
- ${od.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("")}
11501
+ ${sd.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("")}
11487
11502
  </div>
11488
11503
  <div class="mx-range" id="mx-range" role="group" aria-label="History window">
11489
- ${sd.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11504
+ ${id.map(i=>`<button type="button" data-days="${i.days}" aria-pressed="${i.days===30}">${i.label}</button>`).join("")}
11490
11505
  </div>
11491
11506
  </div>
11492
11507
  <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">
@@ -11539,7 +11554,7 @@ window.MXD=(function(){
11539
11554
  <section class="mx-section" aria-labelledby="mx-routines-title">
11540
11555
  ${Z(Q.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>')}
11541
11556
  <div class="mx-rt-bar" id="mx-rt-filter" role="group" aria-label="Filter routines">
11542
- ${rd.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11557
+ ${od.map(i=>`<button class="mx-chip" type="button" data-rt-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11543
11558
  </div>
11544
11559
  <div class="mx-rt-wrap" id="mx-routines"><div class="mx-empty">Loading routines...</div></div>
11545
11560
  </section>
@@ -11547,7 +11562,7 @@ window.MXD=(function(){
11547
11562
  <section class="mx-section" aria-labelledby="mx-feed-title">
11548
11563
  ${Z(Q.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>')}
11549
11564
  <div class="mx-rt-bar" role="group" aria-label="Filter the mesh feed">
11550
- ${so.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11565
+ ${io.map(i=>`<button class="mx-chip" type="button" data-feed-filter="${i.id}" aria-pressed="${i.id==="all"}">${i.label}</button>`).join("")}
11551
11566
  </div>
11552
11567
  <div class="ax-stack" id="mx-feed" aria-live="polite"><div class="mx-empty">Loading the mesh feed...</div></div>
11553
11568
  </section>
@@ -11580,7 +11595,7 @@ window.MXD=(function(){
11580
11595
  <button class="ax-btn ax-btn--ghost" id="mx-close" type="button" aria-label="Close details">Close</button>
11581
11596
  </header>
11582
11597
  <div class="mx-drawer__body" id="mx-drawer-body"></div>
11583
- </aside>`;return L({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:Zr+ro,scripts:eo+id+to+ao+oo+no+io})}var id=`<script>
11598
+ </aside>`;return L({title:"AgentX \xB7 Mesh Operations",activeTab:"mesh",subtitle:"Operations",peers:t.peers,noMain:!0,body:s,css:eo+oo,scripts:to+ld+ao+no+so+ro+lo})}var ld=`<script>
11584
11599
  (function(){
11585
11600
  var tabs=Array.prototype.slice.call(document.querySelectorAll('.mx-tab'));
11586
11601
  var range=document.getElementById('mx-range');
@@ -11608,7 +11623,7 @@ window.MXD=(function(){
11608
11623
  var saved=null;try{saved=localStorage.getItem('mx-view')}catch(e){}
11609
11624
  select(tabs.some(function(t){return t.dataset.view===saved})?saved:'activity');
11610
11625
  })();
11611
- </script>`;async function co(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 ld(s,e.days)}function ld(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,m=0,h=0,w=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let f=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=d[x]?.[0]||0,f[x][1]+=d[x]?.[1]||0;n.set(d.day,f)}for(let d of g.origins){let f=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};f.runs+=d.runs,f.errors+=d.errors,f.hours+=d.hours,r.set(d.channel,f)}for(let d of g.causes){let f=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};f.count+=d.count;for(let x of d.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=d.example),o.set(d.cause,f)}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,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,w+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:w}}}async function po(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 uo(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 cd(s,e.day)}function cd(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 mo(t={}){let e=`
11626
+ </script>`;async function po(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 cd(s,e.days)}function cd(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,m=0,h=0,w=0;for(let{node:S,data:g}of t)if(g){a.runs+=g.totals.runs,a.errors+=g.totals.errors,a.hours+=g.totals.hours,a.agents+=g.totals.agents,a.threads+=g.totals.threads;for(let d of g.days){let f=n.get(d.day)||{day:d.day,cron:[0,0],workflow:[0,0],direct:[0,0]};for(let x of["cron","workflow","direct"])f[x][0]+=d[x]?.[0]||0,f[x][1]+=d[x]?.[1]||0;n.set(d.day,f)}for(let d of g.origins){let f=r.get(d.channel)||{channel:d.channel,runs:0,errors:0,hours:0};f.runs+=d.runs,f.errors+=d.errors,f.hours+=d.hours,r.set(d.channel,f)}for(let d of g.causes){let f=o.get(d.cause)||{cause:d.cause,count:0,agents:[],example:""};f.count+=d.count;for(let x of d.agents)f.agents.includes(x)||f.agents.push(x);f.example||(f.example=d.example),o.set(d.cause,f)}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,m=Math.max(m,g.rotations.maxTokens),h+=g.retention.traces,w+=g.retention.tracesWithSteps;for(let d of g.jobs)i.push({...d,node:S.name,nodeUrl:S.url});for(let d of g.threads)l.push({...d,node:S.name,nodeUrl:S.url})}let _=t.filter(S=>S.data).map(S=>S.data.since).filter(S=>Number.isFinite(S));return{generatedAt:Date.now(),windowDays:e,since:_.length?Math.min(..._):Date.now()-e*864e5,nodes:t.map(S=>({name:S.node.name,url:S.node.url,ok:!!S.data,error:S.error,runs:S.data?.totals.runs||0})),totals:{...a,hours:Math.round(a.hours*100)/100},days:[...n.values()].sort((S,g)=>S.day.localeCompare(g.day)),origins:[...r.values()].map(S=>({...S,hours:Math.round(S.hours*100)/100})).sort((S,g)=>g.runs-S.runs),causes:[...o.values()].sort((S,g)=>g.count-S.count),jobs:i.sort((S,g)=>g.hours-S.hours),threads:l.sort((S,g)=>g.lastAt-g.firstAt-(S.lastAt-S.firstAt)||g.runs-S.runs),rotations:{total:c,byReason:[...s.entries()].map(([S,g])=>({reason:S,count:g})).sort((S,g)=>g.count-S.count),tokenSum:p,tokenSamples:u,maxTokens:m},retention:{traces:h,tracesWithSteps:w}}}async function uo(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 mo(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 dd(s,e.day)}function dd(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 fo(t={}){let e=`
11612
11627
  <select id="boardPicker" title="Switch board"></select>
11613
11628
  <div class="search">
11614
11629
  <span class="icon">\u2315</span>
@@ -11709,7 +11724,7 @@ window.MXD=(function(){
11709
11724
  </footer>
11710
11725
  </div>
11711
11726
  </div>
11712
- <script src="/sortable.min.js"></script>`;return L({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:dd,scripts:`<script>${pd}</script>`,headExtras:`<script>
11727
+ <script src="/sortable.min.js"></script>`;return L({title:"AgentX \xB7 Boards",activeTab:"boards",subtitle:"Boards",subheader:e,peers:t.peers,currentPeerId:t.currentPeerId,noMain:!0,body:a,css:pd,scripts:`<script>${ud}</script>`,headExtras:`<script>
11713
11728
  // The boards page has its own connection dot + wants body height:100%
11714
11729
  // for the full-viewport kanban layout. Inject the dot into the topbar
11715
11730
  // and override body height at runtime so the shared shell doesn't
@@ -11725,7 +11740,7 @@ window.MXD=(function(){
11725
11740
  right.insertBefore(dot, right.firstChild);
11726
11741
  }
11727
11742
  });
11728
- </script>`})}var dd=`
11743
+ </script>`})}var pd=`
11729
11744
  /* Kanban subheader \u2014 replaces the legacy toolbar that used to live in <header>. */
11730
11745
  .ax-subheader select, .ax-subheader input, .ax-subheader button {
11731
11746
  background: var(--col); color: var(--text); border: 1px solid var(--border);
@@ -11978,7 +11993,7 @@ header a.link:hover { color: var(--accent); border-color: var(--accent); }
11978
11993
  .draft-box .draft-row .hint { color: var(--muted); font-size: 12px; flex: 1; }
11979
11994
  .draft-box .draft-row .hint.err { color: var(--red); }
11980
11995
  .draft-box .draft-row .hint.ok { color: var(--green); }
11981
- `,pd=`
11996
+ `,ud=`
11982
11997
  'use strict';
11983
11998
  const state = {
11984
11999
  boards: [], current: null, items: {},
@@ -13031,9 +13046,9 @@ function appendEvents(events) {
13031
13046
  }
13032
13047
 
13033
13048
  loadBoards().catch(e => toast('Init failed: ' + e.message));
13034
- `;function fo(t={}){let a=`<h1>Plain-English glossary</h1>
13049
+ `;function ho(t={}){let a=`<h1>Plain-English glossary</h1>
13035
13050
  <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>
13036
- ${Qr.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${O(n.alias)}</span>`:"";return`<article class="term"><h3>${O(n.term)}${r}</h3><p>${O(n.definition)}</p></article>`}).join("")}`;return L({title:`${_e.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:ud})}var ud=`
13051
+ ${Zr.map(n=>{let r=n.alias?`<span class="alias" title="Schema key">${O(n.alias)}</span>`:"";return`<article class="term"><h3>${O(n.term)}${r}</h3><p>${O(n.definition)}</p></article>`}).join("")}`;return L({title:`${Ee.brand} \xB7 Glossary`,activeTab:"glossary",subtitle:"Glossary",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:md})}var md=`
13037
13052
  main { max-width: 760px; margin: 0 auto; padding: 32px 24px 80px; }
13038
13053
  h1 { font-size: 22px; margin: 0 0 6px; font-weight: 600; letter-spacing: -0.01em; }
13039
13054
  .lead {
@@ -13063,7 +13078,7 @@ article.term .alias {
13063
13078
  }
13064
13079
  article.term p {
13065
13080
  margin: 0; color: var(--ax-text-2); font-size: 13px; line-height: 1.6;
13066
- }`;function ho(t={}){let e=`<div class="ax-wf__root">
13081
+ }`;function go(t={}){let e=`<div class="ax-wf__root">
13067
13082
  <aside class="ax-wf__list">
13068
13083
  <header>
13069
13084
  <h2>Workflows</h2>
@@ -13140,7 +13155,7 @@ article.term p {
13140
13155
  </aside>
13141
13156
  </div>
13142
13157
 
13143
- <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return L({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:md,scripts:`<script>${U({workflowHealth:Fa})}${fd}</script>`})}var md=`
13158
+ <div id="wf-toast" class="ax-wf__toast" hidden></div>`;return L({title:"AgentX \xB7 Workflows",activeTab:"workflows",subtitle:"Workflows",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:fd,scripts:`<script>${U({workflowHealth:qa})}${hd}</script>`})}var fd=`
13144
13159
  .ax-wf__root {
13145
13160
  display: grid;
13146
13161
  grid-template-columns: 340px 1fr;
@@ -13524,7 +13539,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
13524
13539
  font-size: 12px; z-index: 50;
13525
13540
  }
13526
13541
  .hint { color: var(--ax-muted); font-size: 11px; }
13527
- `,fd=`
13542
+ `,hd=`
13528
13543
  (() => {
13529
13544
  const $ = (sel) => document.querySelector(sel)
13530
13545
  const $$ = (sel) => Array.from(document.querySelectorAll(sel))
@@ -14313,7 +14328,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14313
14328
  setInterval(refresh, 15000)
14314
14329
  })
14315
14330
  })();
14316
- `;function go(t={}){let e=`<div class="ax-proc__root">
14331
+ `;function xo(t={}){let e=`<div class="ax-proc__root">
14317
14332
  <header class="ax-proc__header">
14318
14333
  <h1>Procedures</h1>
14319
14334
  <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>
@@ -14357,7 +14372,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14357
14372
  <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>
14358
14373
  <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>
14359
14374
  </section>
14360
- </div>`;return L({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:hd,scripts:`<script>${gd}</script>`})}var hd=`
14375
+ </div>`;return L({title:"AgentX \xB7 Procedures",activeTab:"procedures",subtitle:"Procedures",peers:t.peers,currentPeerId:t.currentPeerId,body:e,css:gd,scripts:`<script>${xd}</script>`})}var gd=`
14361
14376
  .ax-proc__root { padding: 18px 24px 40px; max-width: 1100px; margin: 0 auto; color: var(--ax-text); }
14362
14377
  .ax-proc__header h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
14363
14378
  .ax-proc__header .hint { color: var(--ax-muted); font-size: 12px; margin: 0 0 18px; }
@@ -14383,7 +14398,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14383
14398
  .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); }
14384
14399
  .ax-proc__link { color: var(--ax-accent, #6366f1); text-decoration: none; font-size: 11px; }
14385
14400
  .ax-proc__link:hover { text-decoration: underline; }
14386
- `,gd=`
14401
+ `,xd=`
14387
14402
  (function(){
14388
14403
  function $(sel){ return document.querySelector(sel) }
14389
14404
  function esc(s){ return String(s||"").replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c] }) }
@@ -14483,7 +14498,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14483
14498
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootAll)
14484
14499
  else bootAll()
14485
14500
  })();
14486
- `;function xo(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14501
+ `;function vo(t){let e=t.agentName||t.agentId,a=`<div class="ax-task-page"
14487
14502
  data-task-id="${O(t.taskId)}"
14488
14503
  data-agent-id="${O(t.agentId)}"
14489
14504
  data-node-url="${O(t.nodeUrl)}"
@@ -14526,7 +14541,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14526
14541
  <button type="button" id="task-send" class="ax-btn ax-btn--primary">send \u2192</button>
14527
14542
  </div>
14528
14543
  </footer>
14529
- </div>`;return L({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:xd,scripts:`<script>${vd}</script>`})}var xd=`
14544
+ </div>`;return L({title:`AgentX \xB7 ${e}`,activeTab:"live",subtitle:"Task",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:vd,scripts:`<script>${bd}</script>`})}var vd=`
14530
14545
  /* The shell gives <main> no padding, so page content butted straight against
14531
14546
  the sticky topbar. Breathe. */
14532
14547
  .ax-task-page {
@@ -14668,7 +14683,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
14668
14683
  line-height: 1.55; text-wrap: pretty; white-space: pre-wrap; word-break: break-word;
14669
14684
  }
14670
14685
 
14671
- `,vd=`
14686
+ `,bd=`
14672
14687
  (function () {
14673
14688
  var root = document.querySelector('.ax-task-page');
14674
14689
  if (!root) return;
@@ -15053,7 +15068,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15053
15068
  });
15054
15069
 
15055
15070
  })();
15056
- `;function vo(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15071
+ `;function bo(t){let e=t.agentName||t.agentId,a=`<div class="ax-history"
15057
15072
  data-agent-id="${O(t.agentId)}"
15058
15073
  data-agent-name="${O(e)}"
15059
15074
  data-node-url="${O(t.nodeUrl)}">
@@ -15082,7 +15097,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15082
15097
  <div class="ax-history__list" id="hist-list">
15083
15098
  <div class="ax-history__empty">loading\u2026</div>
15084
15099
  </div>
15085
- </div>`;return L({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:bd,scripts:`<script>${yd}</script>`})}var bd=`
15100
+ </div>`;return L({title:`AgentX \xB7 ${e} history`,activeTab:"live",subtitle:"History",peers:t.peers,currentPeerId:t.currentPeerId,body:a,css:yd,scripts:`<script>${wd}</script>`})}var yd=`
15086
15101
  /* <main> carries no padding in the shell \u2014 without this the breadcrumb sits
15087
15102
  flush against the sticky topbar. */
15088
15103
  .ax-history {
@@ -15134,7 +15149,7 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15134
15149
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
15135
15150
  }
15136
15151
  .ax-history__foot { margin-top: 6px; font-size: var(--ax-fs-xs); color: var(--ax-muted); font-family: var(--ax-mono); }
15137
- `,yd=`
15152
+ `,wd=`
15138
15153
  (function () {
15139
15154
  var root = document.querySelector('.ax-history');
15140
15155
  if (!root) return;
@@ -15234,11 +15249,11 @@ details.ax-wf__panel pre { margin: 0; padding: 10px 14px; }
15234
15249
  listEl.innerHTML = '<div class="ax-history__empty" style="color:var(--ax-err)">' + esc(e.message) + '</div>';
15235
15250
  });
15236
15251
  })();
15237
- `;function yo(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 je(t,e,l=>bo(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:kd(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?je(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"])?je(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"])?je(t,e,l=>{let c=Ot.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=Nt(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 je(t,e,p=>bo(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 wd=["mesh"];function bo(t,e,a,n){let r=Ot.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=Nt(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 wd)!(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 kd(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 m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return je(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 _d(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 _d(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)}
15252
+ `;function wo(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 je(t,e,l=>yo(e,a,l,{mode:"create",convertFromYaml:i}))}}if(n.startsWith("/api/workflows/runs"))return r==="GET"&&!a.requireScope(t,e,["dashboard:read"])?!0:_d(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?je(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"])?je(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"])?je(t,e,l=>{let c=Ot.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=Nt(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 je(t,e,p=>yo(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 kd=["mesh"];function yo(t,e,a,n){let r=Ot.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=Nt(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 kd)!(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 _d(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 m=u.map(h=>({id:h.id,workflowId:h.workflowId,workflowVersion:h.workflowVersion,homeNode:h.homeNode,status:h.status,pending:h.pending,entityRef:h.entityRef,history:(h.history||[]).slice(-5),parentRunId:h.parentRunId,parentNodeId:h.parentNodeId,rootRunId:h.rootRunId,depth:h.depth,createdAt:h.createdAt,updatedAt:h.updatedAt}));return R(e,200,{runs:m})}let s=o.match(/^\/([^\/?]+)\/status$/);if(s){if((t.method||"GET").toUpperCase()!=="POST")return R(e,405,{error:"method not allowed"});if(!a.requireScope(t,e,["dashboard:write"]))return!0;let l=decodeURIComponent(s[1]);return je(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 Ed(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 Ed(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)}
15238
15253
 
15239
15254
  `);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)}
15240
15255
 
15241
- `)}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 je(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 xp}from"fs";import{createRequire as vp}from"module";import{deflateSync as Ed}from"zlib";var Sd=[41,121,255],Td=[255,255,255],wo=new Map;function ia(t){let e=wo.get(t);return e||(e=Cd(t,Ad(t)),wo.set(t,e)),e}function Ad(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?Td:Sd;a.set(c,o*e+1+s*3)}return a}function Cd(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]),sa("IHDR",a),sa("IDAT",Ed(e)),sa("IEND",Buffer.alloc(0))])}function sa(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(Md(n)),Buffer.concat([a,n,r])}var Id=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 Md(t){let e=4294967295;for(let a of t)e=Id[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function yt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Ld(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:yt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:yt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:yt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function Rd(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:yt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var $d=/^\/api\/app\/tasks\/(cancel|followup)$/;async function ko(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let h=Pd(s.searchParams.get("timezone")),w=await o.snapshot({date:jd(h),timezone:h});return a==="/api/app/activity"?pe(e,200,{ts:w.ts,tasks:Rd(w.nodes)}):pe(e,200,{ts:w.ts,nodes:w.nodes.map(Ld)})}if(n==="GET"&&a==="/api/app/approvals")return pe(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match($d);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await Ee(t)}catch(h){return pe(e,400,{error:h.message})}let p=qe(c.node);if(!p)return pe(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,m;if(i){let h=qe(c.taskId);if(!h)return pe(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")m=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=qe(c.message);if(!_)return pe(e,400,{error:"message is required"});m=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")m=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")m=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=qe(c.cronId);if(!h||typeof c.enabled!="boolean")return pe(e,400,{error:"cronId and enabled (true or false) are required"});m=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=qe(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return pe(e,400,{error:"key and action (yes, no or later) are required"});m=await o.decide(p,h,w,u)}return pe(e,m.status,m.body)}function qe(t){return typeof t=="string"?t.trim():""}function Pd(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function jd(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function Ee(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function pe(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Od=2048,_o=/^[A-Za-z0-9_-]{8,256}$/;async function Eo(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 K(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):Nd()});if(n==="GET"&&a==="/api/app/alerts")return K(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 K(e,404,{error:"not found"});if(!s||l)return K(e,503,{error:l});let c;try{c=await Ee(t)}catch(h){return K(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(le).filter(g=>c[le[g].field]!==void 0),w=h.map(g=>le[g].field).join(", "),_=Object.values(le).map(g=>g.field).join(" or ");if(h.length===0)return K(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[le[g].field]!="boolean"))return K(e,400,{error:`${w} must be true or false`});let S={};for(let g of h)s.prefs.set(r.id,g,c[le[g].field]),S[le[g].field]=c[le[g].field];return K(e,200,{ok:!0,...S})}let p=Dd(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return K(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return K(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!_o.test(u)||typeof m!="string"||!_o.test(m)?K(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?K(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),K(e,200,{ok:!0}))}function Nd(){let t={};for(let e of Object.values(le))t[e.field]=e.default;return t}function Dd(t,e){if(typeof t!="string"||t.length>Od)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 K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var To=50,Hd=280;async function Ao(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=Bd(await o.recent(To))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return So(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return So(e,404,{error:"not found"})}function Co(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||z(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=Ie();return r?new hn(r):null}}}function Bd(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:la(typeof n.summary=="string"?n.summary:"",Hd),by:typeof n.agentId=="string"?la(n.agentId,100):null,node:la(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,To)}function la(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function So(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var zd="operator",Fd=50,Io=4,Mo=500;function qd(t){let e={channel:"app",chatId:t.chatId,sender:zd,...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 Lo(t,e,a,n){let{path:r,body:o}=qd(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let w=u!=="done",_=i?{text:Qe(m,w),artifacts:[]}:Ye(m,ie.perMessage,w),{cleanText:S,ui:g}=u==="done"?et(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:ca(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of Wd(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<Fd){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,Ud(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 Ud(t){let e=String(t||"The agent could not answer.");return ja(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function ca(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,Io).map(s=>s.slice(0,Mo));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Io).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Mo)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Wd(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,`
15256
+ `)}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 je(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 vp}from"fs";import{createRequire as bp}from"module";import{deflateSync as Sd}from"zlib";var Td=[41,121,255],Ad=[255,255,255],ko=new Map;function la(t){let e=ko.get(t);return e||(e=Id(t,Cd(t)),ko.set(t,e)),e}function Cd(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?Ad:Td;a.set(c,o*e+1+s*3)}return a}function Id(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]),ia("IHDR",a),ia("IDAT",Sd(e)),ia("IEND",Buffer.alloc(0))])}function ia(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(Ld(n)),Buffer.concat([a,n,r])}var Md=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 Ld(t){let e=4294967295;for(let a of t)e=Md[(e^a)&255]^e>>>8;return(e^4294967295)>>>0}function yt(t,e=160){if(!t)return t;let a=t.replace(/\s+/g," ").trim();return a.length>e?a.slice(0,e-1)+"\u2026":a}function Rd(t){let e=new Map;for(let n of t.cronRuns??[]){let r=e.get(n.jobId);(!r||r.startedAt<n.startedAt)&&e.set(n.jobId,n)}let a={success:0,failed:0};for(let n of t.cronRuns??[])n.status==="success"?a.success++:a.failed++;return{id:t.id,name:t.name,url:t.url,reachable:t.reachable,error:yt(t.error),uptimeSec:t.uptimeSec,inflight:t.inflight,restart:t.restart?.state&&t.restart.state!=="none"?t.restart:void 0,agents:t.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:yt(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:a,items:(t.crons??[]).map(n=>{let r=e.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:r?{status:r.status,at:r.startedAt,text:yt(r.status==="success"?r.responseSummary:r.errorSummary)}:void 0}})}}}function $d(t){let e=[];for(let a of t)for(let n of a.agents)for(let r of n.runningTasks??[])e.push({node:a.url,nodeName:a.name,agentId:n.id,agentName:n.name,taskId:r.id,preview:yt(r.messagePreview),channel:r.channel,startedAt:r.startedAt});return e.sort((a,n)=>a.startedAt<n.startedAt?1:-1)}var Pd=/^\/api\/app\/tasks\/(cancel|followup)$/;async function _o(t,e,a,n,r,o){let s=new URL(t.url||a,"http://localhost");if(n==="GET"&&(a==="/api/app/fleet"||a==="/api/app/activity")){let h=jd(s.searchParams.get("timezone")),w=await o.snapshot({date:Od(h),timezone:h});return a==="/api/app/activity"?ue(e,200,{ts:w.ts,tasks:$d(w.nodes)}):ue(e,200,{ts:w.ts,nodes:w.nodes.map(Rd)})}if(n==="GET"&&a==="/api/app/approvals")return ue(e,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let i=a.match(Pd);if(!(i||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(a)))return!1;let c;try{c=await Se(t)}catch(h){return ue(e,400,{error:h.message})}let p=qe(c.node);if(!p)return ue(e,400,{error:"node is required"});let u=`operator (phone: ${r})`,m;if(i){let h=qe(c.taskId);if(!h)return ue(e,400,{error:"taskId is required"});let w=`/api/tasks/${encodeURIComponent(h)}/${i[1]}`;if(i[1]==="cancel")m=await o.nodePost(p,w,{reason:`cancelled by ${u}`});else{let _=qe(c.message);if(!_)return ue(e,400,{error:"message is required"});m=await o.nodePost(p,w,{message:_,sender:u})}}else if(a==="/api/app/nodes/restart")m=await o.nodePost(p,c.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(a==="/api/app/nodes/reload")m=await o.nodePost(p,"/reload",{});else if(a==="/api/app/crons/toggle"){let h=qe(c.cronId);if(!h||typeof c.enabled!="boolean")return ue(e,400,{error:"cronId and enabled (true or false) are required"});m=await o.nodePost(p,`/crons/${encodeURIComponent(h)}/enabled`,{enabled:c.enabled})}else{let h=qe(c.key),w=c.action;if(!h||w!=="yes"&&w!=="no"&&w!=="later")return ue(e,400,{error:"key and action (yes, no or later) are required"});m=await o.decide(p,h,w,u)}return ue(e,m.status,m.body)}function qe(t){return typeof t=="string"?t.trim():""}function jd(t){if(!t)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:t}),t}catch{return"UTC"}}function Od(t,e=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(e)}async function Se(t,e=16*1024){let a=0,n=[];for await(let s of t){if(a+=s.length,a>e)throw new Error("body too large");n.push(s)}let r=Buffer.concat(n).toString("utf-8").trim();if(!r)return{};let o=JSON.parse(r);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function ue(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Nd=2048,Eo=/^[A-Za-z0-9_-]{8,256}$/;async function So(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 K(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):Dd()});if(n==="GET"&&a==="/api/app/alerts")return K(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 K(e,404,{error:"not found"});if(!s||l)return K(e,503,{error:l});let c;try{c=await Se(t)}catch(h){return K(e,400,{error:h.message})}if(a==="/api/app/push/prefs"){let h=Object.keys(ce).filter(g=>c[ce[g].field]!==void 0),w=h.map(g=>ce[g].field).join(", "),_=Object.values(ce).map(g=>g.field).join(" or ");if(h.length===0)return K(e,400,{error:`send ${_}, true or false`});if(h.some(g=>typeof c[ce[g].field]!="boolean"))return K(e,400,{error:`${w} 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 K(e,200,{ok:!0,...S})}let p=Hd(c.endpoint,o.allowedHosts);if(!p){let h="";try{h=new URL(String(c.endpoint)).hostname}catch{}return K(e,400,{error:`not a known push service${h?`: ${h}`:""} (see channels.push.allowedHosts)`})}if(a==="/api/app/push/unsubscribe")return K(e,200,{ok:!0,removed:s.unsubscribe(p,r.id)});let u=c.keys?.p256dh,m=c.keys?.auth;return typeof u!="string"||!Eo.test(u)||typeof m!="string"||!Eo.test(m)?K(e,400,{error:"keys.p256dh and keys.auth are required"}):c.publicKey!==void 0&&c.publicKey!==i?K(e,409,{error:"this computer's push keys changed; turn notifications on again"}):(s.subscribe({endpoint:p,p256dh:u,auth:m,deviceId:r.id,deviceName:r.name,publicKey:i}),K(e,200,{ok:!0}))}function Dd(){let t={};for(let e of Object.values(ce))t[e.field]=e.default;return t}function Hd(t,e){if(typeof t!="string"||t.length>Nd)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 K(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Ao=50,Bd=280;async function Co(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=zd(await o.recent(Ao))}catch(c){l=String(c?.message||"unreachable").slice(0,200)}return To(e,200,{items:i,error:l,notify:s?s.on(r.id,"announce"):!1,notifyAvailable:!!s})}return To(e,404,{error:"not found"})}function Io(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=process.env.MESH_TOKEN||z(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=Me();return r?new xn(r):null}}}function zd(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:ca(typeof n.summary=="string"?n.summary:"",Bd),by:typeof n.agentId=="string"?ca(n.agentId,100):null,node:ca(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,Ao)}function ca(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}function To(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var Fd="operator",qd=50,Mo=4,Lo=500;function Ud(t){let e={channel:"app",chatId:t.chatId,sender:Fd,...t.spoken?{via:"voice"}:{}};return t.node==="local"?{path:"/task",body:{agent:t.agent,message:t.message,stream:!0,context:e}}:{path:"/mesh/task",body:{peer:t.node,agent:t.agent,message:t.message,stream:!0,context:e}}}async function Ro(t,e,a,n){let{path:r,body:o}=Ud(e),s="",i=!1,l=[],c=new Map,p=(u,m,h)=>{let w=u!=="done",_=i?{text:Qe(m,w),artifacts:[]}:Ye(m,le.perMessage,w),{cleanText:S,ui:g}=u==="done"?et(_.text):{cleanText:_.text,ui:void 0},d=i?void 0:da(g);return{status:u,text:S,tools:l,files:_.artifacts,...d?{ui:d}:{},...h?{error:h}:{}}};try{let u=await fetch(t.url.replace(/\/+$/,"")+r,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify(o),signal:a});if(!u.ok||!u.body){let m=await u.json().then(h=>h?.error).catch(()=>"");return p("error",s,m||`AgentX answered HTTP ${u.status}.`)}for await(let m of Gd(u.body)){n(m.event,m.data);let h=m.data??{};if(m.event==="start")i=h.rich===!1;else if(m.event==="text"&&typeof h.text=="string")s+=h.text;else if(m.event==="tool"&&h.status==="start"&&l.length<qd){let w={name:String(h.name||"tool").slice(0,80),...h.arg?{arg:String(h.arg).slice(0,80)}:{}};l.push(w),h.id&&c.set(String(h.id),w)}else if(m.event==="tool"&&h.status==="result"&&h.error===!0&&c.has(String(h.id)))c.get(String(h.id)).error=!0;else{if(m.event==="done")return p("done",typeof h.content=="string"&&h.content?h.content:s);if(m.event==="error")return p("error",s,Wd(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 Wd(t){let e=String(t||"The agent could not answer.");return Oa(e)?"The agent is busy with other work. Send the message again when it is free.":e.slice(0,500)}function da(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,Mo).map(s=>s.slice(0,Lo));r.length&&(a.quickReplies=r);let o=(t.replies??[]).slice(0,Mo).map(s=>({label:s.label.slice(0,80),reply:s.reply.slice(0,Lo)}));return o.length&&(a.replies=o),Object.keys(a).length?a:void 0}async function*Gd(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,`
15242
15257
  `);let s;for(;(s=n.indexOf(`
15243
15258
 
15244
15259
  `))!==-1;){let i=n.slice(0,s);n=n.slice(s+2);let l="message",c=[];for(let p of i.split(`
@@ -15248,12 +15263,12 @@ data: ${JSON.stringify(s)}
15248
15263
 
15249
15264
  `)},r=setInterval(()=>{a()&&e.write(`: ping
15250
15265
 
15251
- `)},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 $o(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=Gd(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:da(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function da(t,e=120){for(let a of t.split(`
15252
- `)){let n=Po(a);if(n)return pa(n,e)}return""}function Gd(t,e=120){let a=t.split(`
15253
- `).map(Po).filter(Boolean);return a.length?pa(a[a.length-1],e):""}function Po(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function pa(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var kt=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 _t(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var Ro=140;function Et(t,e,a,n,r){let o=a==="error"?`Could not answer: ${da(r||"",Ro-18)||"something went wrong."}`:da(n,Ro)||"Answered.";return{deviceId:t,title:pa(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var Oo=8e3,Kd=/^[A-Za-z0-9_.:-]{1,64}$/,Se=new Map,ua=new Map,ha=new kt;function No(){return ha}async function Do(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??ha;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Ho(o)});let i=o.store();if(!i)return D(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),D(e,200,{conversations:$o(r.id,Yd(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),D(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return D(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 D(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=Se.get(p.id);return D(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&&Se.get(p.id);if(!p||!u)return D(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),Bo(e);let{id:m,title:h,node:w,nodeName:_,agent:S,agentName:g}=p;return e.write(ma("conversation",{id:m,title:h,node:w,nodeName:_,agent:S,agentName:g})),e.write(ma("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 D(e,404,{error:"not found"});let c;try{c=await Ee(t,64*1024)}catch(p){return D(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return D(e,404,{error:"no such conversation"});let u=Se.get(p.id);return u?(u.ac.abort(),fa(p,o,r.name),D(e,200,{stopped:!0})):await fa(p,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await Vd(e,c,r,i,o),!0}function Jd(t,e,a){let n=Oe(e.url),r=new Set,o=[];for(let s of t){let i=Oe(s.url),l=a.find(u=>Oe(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 m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Ho(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Jd(e.nodes,t.daemon,a)}async function Vd(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>Oo){D(t,400,{error:`message must be 1\u2013${Oo} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!Kd.test(_)){D(t,400,{error:"pick an agent"});return}let S=(await Ho(r)).find(d=>d.target===w);if(!S){D(t,400,{error:`unknown node "${w}"`});return}if(!S.online){D(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){D(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:w,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Se.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new wt(r.orphanLimitMs??18e5);Se.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h}=s;ua.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),Bo(t),t.write(ma("conversation",{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let w=e.spoken===!0,_=await Lo(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:w},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,fa(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??ha).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&_t(d)&&r.notifyFinish(Et(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Se.delete(l),ua.delete(l),i.finish()}}function Yd(){let t=[];for(let[e,a]of ua){let n=Se.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function Bo(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function ma(t,e){return`event: ${t}
15266
+ `)},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 Po(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=Xd(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:pa(i.answer)||(i.status==="done"?"Answered.":i.status==="stopped"?"Stopped.":"The agent could not answer."),updatedAt:i.at}))}return r}function pa(t,e=120){for(let a of t.split(`
15267
+ `)){let n=jo(a);if(n)return ua(n,e)}return""}function Xd(t,e=120){let a=t.split(`
15268
+ `).map(jo).filter(Boolean);return a.length?ua(a[a.length-1],e):""}function jo(t){return t.replace(/^\s*(?:[#>]+|[-*+]\s|\d+\.\s)\s*/,"").replace(/[*_`]+/g,"").replace(/\s+/g," ").trim()}function ua(t,e){let a=[...t];return a.length>e?a.slice(0,e-1).join("")+"\u2026":t}var kt=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 _t(t){return t.enabled&&!t.attached&&!t.appOpen&&t.status!=="stopped"}var $o=140;function Et(t,e,a,n,r){let o=a==="error"?`Could not answer: ${pa(r||"",$o-18)||"something went wrong."}`:pa(n,$o)||"Answered.";return{deviceId:t,title:ua(e.agentName||e.agent,80),body:o,url:`/app#chat=${e.id}`}}var No=8e3,Jd=/^[A-Za-z0-9_.:-]{1,64}$/,Te=new Map,ma=new Map,ga=new kt;function Do(){return ga}async function Ho(t,e,a,n,r,o){if(a!=="/api/app/agents"&&a!=="/api/app/chat"&&a!=="/api/app/chat/stop"&&a!=="/api/app/chat/attach"&&a!=="/api/app/chat/active"&&a!=="/api/app/chat/away"&&a!=="/api/app/conversations"&&!a.startsWith("/api/app/conversations/"))return!1;let s=o.presence??ga;if(n==="GET"&&a==="/api/app/agents")return D(e,200,{nodes:await Bo(o)});let i=o.store();if(!i)return D(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),D(e,200,{conversations:Po(r.id,Qd(),i.unread(r.id,12))});if(n==="POST"&&a==="/api/app/chat/away")return s.away(r.id),D(e,200,{ok:!0});if(n==="GET"&&a==="/api/app/conversations")return D(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 D(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=Te.get(p.id);return D(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&&Te.get(p.id);if(!p||!u)return D(e,404,{error:"nothing is running in this conversation"});i.markRead(r.id,p.id),zo(e);let{id:m,title:h,node:w,nodeName:_,agent:S,agentName:g}=p;return e.write(fa("conversation",{id:m,title:h,node:w,nodeName:_,agent:S,agentName:g})),e.write(fa("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 D(e,404,{error:"not found"});let c;try{c=await Se(t,64*1024)}catch(p){return D(e,400,{error:p.message})}if(a==="/api/app/chat/stop"){let p=i.get(r.id,String(c.conversationId??""));if(!p)return D(e,404,{error:"no such conversation"});let u=Te.get(p.id);return u?(u.ac.abort(),ha(p,o,r.name),D(e,200,{stopped:!0})):await ha(p,o,r.name)?D(e,200,{stopped:!0}):D(e,404,{error:"nothing is running in this conversation"})}return await Yd(e,c,r,i,o),!0}function Vd(t,e,a){let n=Oe(e.url),r=new Set,o=[];for(let s of t){let i=Oe(s.url),l=a.find(u=>Oe(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 m=Array.isArray(u.runningTasks)?u.runningTasks.length:0;return{id:u.id,name:u.name||u.id,busy:m>0||(u.active??0)>0,running:m,...u.color?{color:u.color}:{}}})})}for(let s of a)r.has(s.peer)||o.push({target:s.peer,name:s.peer,online:s.healthy,agents:(s.skills??[]).map(i=>({id:i.id,name:i.name||i.id,busy:!1,running:0}))});return o}async function Bo(t){let[e,a]=await Promise.all([t.snapshot().catch(()=>({nodes:[]})),t.meshPeers().catch(()=>[])]);return Vd(e.nodes,t.daemon,a)}async function Yd(t,e,a,n,r){let o=typeof e.message=="string"?e.message.trim():"";if(!o||o.length>No){D(t,400,{error:`message must be 1\u2013${No} characters`});return}let s;if(e.conversationId!=null){if(s=n.get(a.id,String(e.conversationId)),!s){D(t,404,{error:"no such conversation"});return}}else{let w=typeof e.node=="string"?e.node:"",_=typeof e.agent=="string"?e.agent:"";if(!Jd.test(_)){D(t,400,{error:"pick an agent"});return}let S=(await Bo(r)).find(d=>d.target===w);if(!S){D(t,400,{error:`unknown node "${w}"`});return}if(!S.online){D(t,409,{error:`${S.name} is offline`});return}let g=S.agents.find(d=>d.id===_);if(!g){D(t,400,{error:`no agent "${_}" on ${S.name}`});return}s=n.create(a.id,{node:w,nodeName:S.name,agent:_,agentName:g.name,...g.color?{color:g.color}:{}},o)}if(Te.has(s.id)){D(t,409,{error:"The agent is still answering in this conversation."});return}let i=new wt(r.orphanLimitMs??18e5);Te.set(s.id,i);let{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h}=s;ma.set(l,{id:l,deviceId:a.id,title:c,agent:m,...h?{agentName:h}:{},...s.color?{color:s.color}:{}}),n.append(a.id,s.id,{role:"user",content:o,at:Date.now()}),zo(t),t.write(fa("conversation",{id:l,title:c,node:p,nodeName:u,agent:m,agentName:h})),i.attach(t);try{let w=e.spoken===!0,_=await Ro(r.daemon,{node:p,agent:m,message:o,chatId:`app:${l}`,spoken:w},i.ac.signal,(f,x)=>i.broadcast(f,x));i.orphaned&&(_.error=`Stopped: the phone was away for more than ${Math.round((r.orphanLimitMs??18e5)/6e4)} minutes.`,ha(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??ga).open(a.id),enabled:!!r.finishAlerts?.(a.id)};r.notifyFinish&&_t(d)&&r.notifyFinish(Et(a.id,s,_.status,_.text,_.error)).catch(()=>{})}finally{Te.delete(l),ma.delete(l),i.finish()}}function Qd(){let t=[];for(let[e,a]of ma){let n=Te.get(e);n&&t.push({...a,text:n.text,startedAt:n.startedAt})}return t}function zo(t){t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-store","X-Accel-Buffering":"no"})}function fa(t,e){return`event: ${t}
15254
15269
  data: ${JSON.stringify(e)}
15255
15270
 
15256
- `}async function fa(t,e,a){try{let n=Oe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Oe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Oe(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 Oe(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Qd}from"stream";var Zd=/^\/api\/app\/files\/([^/]+)$/,ep=15e3;async function Fo(t,e,a,n,r,o){let s=Zd.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Te(e,405,{error:"GET only"});let i=o.store();if(!i)return Te(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 Te(e,404,{error:"no such file"});let p=await tp(c.node,o);if(!p)return Te(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),ep),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Va}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Te(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return Te(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>ie.bytes)return u.abort(),Te(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...Ya(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Qd.fromWeb(h.body);return g.on("data",d=>{S+=d.length,S>ie.bytes&&(g.destroy(),e.destroy())}),g.on("error",()=>e.destroy()),g.pipe(e),!0}async function tp(t,e){if(t==="local")return{url:zo(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=zo(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function zo(t){return t.replace(/\/+$/,"")}function Te(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 Uo=8e3;async function Wo(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!on(h))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=rn(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),J(e,w.status,{error:w.error});let _=await Me(t,nn.bytes);if(!_)return J(e,413,{error:sn()});if(!_.length)return J(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 qo(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await Me(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Uo):"";if(!p.trim())return J(e,400,{error:"text is required"});if(!np(c.messages,p))return J(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return qo(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function qo(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(ap(l)?.endpoints)?J(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 J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function ap(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function np(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Uo&&a.content.startsWith(e)))}var rp=new Set(["ring","offer","answer","ice","hangup"]),St=/^[A-Za-z0-9_-]{4,64}$/,op=128*1024;async function Go(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 $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=He(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>He(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Me(t,op);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=sp(c,r.nodeName);if(typeof p=="string")return $(e,400,{error:p});let u=Xo(p.to);if(u&&p.kind==="ring"){let m=await Ue(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return $(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return $(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return St.test(l)?ip(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Me(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!St.test(p))return $(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await Ue(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return $(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await Ue(o,s,"GET","/calls/asking");if(l.status>=300)return $(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 $(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 $(e,405,{error:"POST"});let l=await Ue(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!St.test(l))return $(e,400,{error:"callId is required"});let c=await Ue(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function Xo(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Ue(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 sp(t,e){let a=String(t?.kind??"");if(!rp.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!St.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:")&&!Xo(r))return"to must be bot:<agent id> for an agent";if(He(r)===He(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 ip(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 $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(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 $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var lp={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},Tt=class{constructor(e=lp,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},cp="That code didn't work. Check it, or run agentx app pair for a new one.",dp=400;async function Ko(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await Ee(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await pp(a,e.minMs??dp),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:cp}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function pp(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function ga(t,e){if(!t)return"absent";let a=Xa(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var At=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 Vo(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Jo(t.headers["sec-fetch-mode"]),n.site=Jo(t.headers["sec-fetch-site"]),n}function Jo(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var Yo=`
15271
+ `}async function ha(t,e,a){try{let n=Oe(e.daemon.url);if(t.node!=="local"){let l=(await e.meshPeers()).find(c=>c.peer===t.node);if(!l)return 0;n=Oe(l.peerUrl)}let s=(await e.snapshot()).nodes.find(l=>Oe(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 Oe(t){return t.replace(/\/+$/,"")}function D(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}import{Readable as Zd}from"stream";var ep=/^\/api\/app\/files\/([^/]+)$/,tp=15e3;async function qo(t,e,a,n,r,o){let s=ep.exec(a);if(!s)return!1;if(n!=="GET"&&n!=="HEAD")return Ae(e,405,{error:"GET only"});let i=o.store();if(!i)return Ae(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 Ae(e,404,{error:"no such file"});let p=await ap(c.node,o);if(!p)return Ae(e,502,{error:`${c.node} is not linked to this computer's mesh any more.`});let u=new AbortController;e.on("close",()=>u.abort());let m=setTimeout(()=>u.abort(),tp),h;try{let d=new URLSearchParams({agent:c.agent,file:c.path});h=await fetch(`${p.url}${Qa}?${d}`,{method:n,headers:{...p.token?{Authorization:`Bearer ${p.token}`}:{},...typeof t.headers.range=="string"?{Range:t.headers.range}:{}},signal:u.signal})}catch{return Ae(e,502,{error:"The computer that made this file did not answer."})}finally{clearTimeout(m)}if(h.status!==200&&h.status!==206){let d=await h.json().then(x=>x?.error).catch(()=>""),f=[403,404,413,415,416].includes(h.status)?h.status:502;return Ae(e,f,{error:d||`The computer that made this file answered HTTP ${h.status}.`})}let w=Number(h.headers.get("content-length")||0);if(w>le.bytes)return u.abort(),Ae(e,413,{error:"the file is too large"});let _=h.headers.get("content-range");if(e.writeHead(h.status,{...Za(c.mime,c.name,c.kind),...h.headers.get("content-length")?{"Content-Length":String(w)}:{},...h.status===206&&_?{"Content-Range":_}:{}}),n==="HEAD"||!h.body)return e.end(),!0;let S=0,g=Zd.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 ap(t,e){if(t==="local")return{url:Fo(e.daemon.url),token:e.daemon.token};let a=(await e.meshPeers().catch(()=>[])).find(r=>r.peer===t);if(!a)return null;let n=Fo(a.peerUrl);return{url:n,token:e.tokenFor?.(n)}}function Fo(t){return t.replace(/\/+$/,"")}function Ae(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 Wo=8e3;async function Go(t,e,a,n,r,o){if(a!=="/api/app/voice/transcribe"&&a!=="/api/app/voice/speak")return!1;if(n!=="POST")return J(e,405,{error:"POST"});if(a==="/api/app/voice/transcribe"){let h=String(t.headers["content-type"]||"");if(!ln(h))return J(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let w=sn(t.headers["x-audio-duration-ms"]);if(w)return t.resume(),J(e,w.status,{error:w.error});let _=await Le(t,on.bytes);if(!_)return J(e,413,{error:cn()});if(!_.length)return J(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 Uo(e,o.daemon,"/voice/transcribe",_,S,18e4)}let s,i=await Le(t,64*1024);if(!i)return J(e,413,{error:"request too large"});try{s=JSON.parse(i.toString("utf8")||"{}")}catch{return J(e,400,{error:"expected JSON"})}let l=o.store();if(!l)return J(e,503,{error:"The database on this computer is unavailable."});let c=l.get(r.id,String(s?.conversationId??""));if(!c)return J(e,404,{error:"no such conversation"});let p=typeof s?.text=="string"?s.text.slice(0,Wo):"";if(!p.trim())return J(e,400,{error:"text is required"});if(!rp(c.messages,p))return J(e,404,{error:"no such answer in this conversation"});let u=s?.announce===!0?`${c.agentName||c.agent}: ${p}`:p,m={agent:c.agent,text:u,...c.node!=="local"?{peer:c.node}:{}};return Uo(e,o.daemon,"/voice/speak",Buffer.from(JSON.stringify(m)),{"Content-Type":"application/json"},9e4)}async function Uo(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(np(l)?.endpoints)?J(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 J(t,502,{error:s?.name==="TimeoutError"?"AgentX took too long to answer.":"Could not reach AgentX on this computer."})}}function J(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}function np(t){try{return JSON.parse(t.toString("utf8"))}catch{return null}}function rp(t,e){return t.some(a=>a.role==="assistant"&&(a.content===e||e.length===Wo&&a.content.startsWith(e)))}var op=new Set(["ring","offer","answer","ice","hangup"]),St=/^[A-Za-z0-9_-]{4,64}$/,sp=128*1024;async function Xo(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 $(e,405,{error:"GET"});try{let l=await fetch(`${o}/webrtc/config`,{headers:s,signal:AbortSignal.timeout(1e4)});if(l.status===404)return $(e,503,{error:"Calls are off on this computer. Set channels.webrtc.enabled to true in agentx.json."});if(!l.ok)return $(e,502,{error:`AgentX answered HTTP ${l.status}.`});let c=await l.json(),p=He(r.nodeName),u=(Array.isArray(c.peers)?c.peers:[]).filter(h=>He(String(h?.name??""))!==p),m=(Array.isArray(c.agents)?c.agents:[]).filter(h=>h&&typeof h.id=="string").map(h=>({id:h.id,name:typeof h.name=="string"&&h.name?h.name:h.id}));return $(e,200,{node:r.nodeName,iceServers:c.iceServers??[],peers:u,agents:m,camera:c.camera??null})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/signal"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Le(t,sp);if(!l)return $(e,413,{error:"signal too large"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=ip(c,r.nodeName);if(typeof p=="string")return $(e,400,{error:p});let u=Ko(p.to);if(u&&p.kind==="ring"){let m=await Ue(o,s,"POST","/webrtc/camera/watch",{callId:p.callId,agentId:u});return $(e,m.status,m.status<300?{ok:!0,watch:m.body.watch}:{error:m.body.error})}try{let m=await fetch(`${o}/webrtc/signal/out`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(p),signal:AbortSignal.timeout(15e3)}),h=await m.json().catch(()=>({}));return $(e,m.ok?200:502,m.ok?{ok:!0}:{error:h?.error||`AgentX answered HTTP ${m.status}.`})}catch{return $(e,502,{error:"Could not reach AgentX on this computer."})}}if(a==="/api/app/camera/events"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";return St.test(l)?lp(t,e,`${o}/webrtc/events?callId=${encodeURIComponent(l)}&as=${encodeURIComponent(r.nodeName)}`,s):$(e,400,{error:"callId is required"})}if(a==="/api/app/camera/look"){if(n!=="POST")return $(e,405,{error:"POST"});let l=await Le(t,4096);if(!l)return $(e,413,{error:"note too long"});let c;try{c=JSON.parse(l.toString("utf8")||"{}")}catch{return $(e,400,{error:"expected JSON"})}let p=String(c?.callId??"");if(!St.test(p))return $(e,400,{error:"callId is required"});let u=typeof c?.note=="string"?c.note:"",m=await Ue(o,s,"POST",`/webrtc/camera/watch/${encodeURIComponent(p)}/look`,{note:u},18e4);return $(e,m.status,m.status<300?{reply:m.body.reply,frame:m.body.frame}:{error:m.body.error})}if(a==="/api/app/camera/asks"){if(n!=="GET")return $(e,405,{error:"GET"});let l=await Ue(o,s,"GET","/calls/asking");if(l.status>=300)return $(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 $(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 $(e,405,{error:"POST"});let l=await Ue(o,s,"POST",`/calls/${i[1]}/${i[2]}`,{});return $(e,l.status,l.status<300?{call:l.body.call}:{error:l.body.error})}if(a==="/api/app/camera/watch"){if(n!=="GET")return $(e,405,{error:"GET"});let l=new URL(t.url||"/","http://x").searchParams.get("callId")||"";if(!St.test(l))return $(e,400,{error:"callId is required"});let c=await Ue(o,s,"GET",`/webrtc/camera/watch/${encodeURIComponent(l)}`);return $(e,c.status,c.status<300?{watch:c.body.watch}:{error:c.body.error})}return $(e,404,{error:"not found"})}function Ko(t){let e=/^bot:([A-Za-z0-9_.-]{1,80})$/.exec(t);return e?e[1]:null}async function Ue(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 ip(t,e){let a=String(t?.kind??"");if(!op.has(a))return"kind must be ring, offer, answer, ice or hangup";let n=String(t?.callId??"");if(!St.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:")&&!Ko(r))return"to must be bot:<agent id> for an agent";if(He(r)===He(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 lp(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 $(e,502,{error:"Could not reach AgentX on this computer."})}if(!o.ok||!o.body)return o.status===404?$(e,503,{error:"Calls are off on this computer."}):$(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 $(t,e,a){return t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(a)),!0}var cp={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},Tt=class{constructor(e=cp,a=Date.now){this.opts=e;this.now=a}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let a=this.now(),n=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return n>a?Math.ceil((n-a)/1e3):0}fail(e){let a=this.clients.get(e);a||this.clients.set(e,a={failures:[],lockedUntil:0}),this.bump(a,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,a){let n=this.now();e.failures=e.failures.filter(r=>n-r<this.opts.windowMs),e.failures.push(n),e.failures.length>=a&&(e.lockedUntil=n+this.opts.lockoutMs)}},dp="That code didn't work. Check it, or run agentx app pair for a new one.",pp=400;async function Jo(t,e){let a=Date.now(),n=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",o=e.limiter.retryAfter(r);if(o>0)return n(`[app] pair-code refused from ${r}: locked out for ${o}s more`),{status:429,body:{error:"too many attempts",retryAfter:o},retryAfter:o};let s=null;try{s=(await Se(t,1024)).code}catch{}let i=e.codes.redeem(s),l=i?e.verify(i.token):null;return await up(a,e.minMs??pp),!i||!l?(e.limiter.fail(r),n(`[app] pair-code failed from ${r}`),{status:401,body:{error:dp}}):(e.limiter.succeed(r),n(`[app] pair-code paired ${i.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:i.token})}async function up(t,e){let a=t+e-Date.now();a>0&&await new Promise(n=>setTimeout(n,a))}function xa(t,e){if(!t)return"absent";let a=Ka(t),n=e.list().find(r=>r.hash===a);return n&&(n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())?"revoked":"invalid"}var At=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 Yo(t,e,a){let n={cookie:e};return a&&(n.bearer=a),n.mode=Vo(t.headers["sec-fetch-mode"]),n.site=Vo(t.headers["sec-fetch-site"]),n}function Vo(t){let e=Array.isArray(t)?t[0]:t;return e&&/^[a-z-]{1,20}$/.test(e)?e:"-"}var Qo=`
15257
15272
  (function () {
15258
15273
  var fleetPanel = document.getElementById('panel-fleet');
15259
15274
  var activityPanel = document.getElementById('panel-activity');
@@ -15497,7 +15512,7 @@ data: ${JSON.stringify(e)}
15497
15512
  setInterval(refresh, 15000);
15498
15513
  refresh();
15499
15514
  })();
15500
- `;var Qo=`
15515
+ `;var Zo=`
15501
15516
  .fx-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
15502
15517
  .fx-head h2 { margin: 4px 0 0; }
15503
15518
  .fx-sub { font-size: 15px; margin: 18px 0 8px; color: var(--ax-text-2); }
@@ -15554,7 +15569,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15554
15569
  }
15555
15570
  .fx-error:empty { display: none; }
15556
15571
  .fx-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
15557
- `;var Zo=`
15572
+ `;var es=`
15558
15573
  (function () {
15559
15574
  var panel = document.getElementById('panel-alerts');
15560
15575
  if (!panel) return;
@@ -15735,7 +15750,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15735
15750
  refresh();
15736
15751
  loadRecent();
15737
15752
  })();
15738
- `;var es=`
15753
+ `;var ts=`
15739
15754
  (function () {
15740
15755
  var panel = document.getElementById('panel-alerts');
15741
15756
  if (!panel) return;
@@ -15848,7 +15863,7 @@ details[open] > summary::before { transform: rotate(90deg); }
15848
15863
  }
15849
15864
  load();
15850
15865
  })();
15851
- `;var ts=`
15866
+ `;var as=`
15852
15867
  (function () {
15853
15868
  var panel = document.getElementById('panel-chat');
15854
15869
  var V = window.AXChatView;
@@ -16120,7 +16135,7 @@ details[open] > summary::before { transform: rotate(90deg); }
16120
16135
  var last = recall('ax-chat-conv');
16121
16136
  if (!fromHash() && last) openConversation(last);
16122
16137
  })();
16123
- `;var as=`
16138
+ `;var ns=`
16124
16139
  window.AXChatView = (function () {
16125
16140
  var NL = String.fromCharCode(10), TAB = String.fromCharCode(9), FENCE = String.fromCharCode(96, 96, 96);
16126
16141
  // Cut a half-written agentx:ui block from a streaming reply so its raw
@@ -16401,7 +16416,7 @@ window.AXChatView = (function () {
16401
16416
  openViewer: openViewer, closeViewer: closeViewer, readStream: readStream,
16402
16417
  cachePut: cachePut, cacheGet: cacheGet, cacheAll: cacheAll, cacheDrop: cacheDrop };
16403
16418
  })();
16404
- `;var ns=`
16419
+ `;var rs=`
16405
16420
  window.AXChatSheets = function (o) {
16406
16421
  var V = o.V, picker = o.picker, hist = o.hist;
16407
16422
  function loadPicker() {
@@ -16447,7 +16462,7 @@ window.AXChatSheets = function (o) {
16447
16462
  });
16448
16463
  return { loadPicker: loadPicker, loadHistory: loadHistory };
16449
16464
  };
16450
- `;var rs=`
16465
+ `;var os=`
16451
16466
  window.AXChatLog = function (o) {
16452
16467
  var V = o.V, log = o.log, empty = o.empty, NOTES = o.notes;
16453
16468
  function scrollDown() { var m = document.querySelector('main'); if (m) m.scrollTop = m.scrollHeight; }
@@ -16510,7 +16525,7 @@ window.AXChatLog = function (o) {
16510
16525
  return { scrollDown: scrollDown, clear: clear, userMsg: userMsg, queuedMsg: queuedMsg, agentMsg: agentMsg, setBody: setBody,
16511
16526
  setNote: setNote, renderUi: renderUi, renderFiles: renderFiles, renderConversation: renderConversation, flash: flash };
16512
16527
  };
16513
- `;var os=`
16528
+ `;var ss=`
16514
16529
  (function () {
16515
16530
  var panel = document.getElementById('panel-chat'), C = window.AXChat, V = window.AXChatView, O = window.AXOrb;
16516
16531
  var top = panel && panel.querySelector('.cx-top');
@@ -16660,7 +16675,7 @@ window.AXChatLog = function (o) {
16660
16675
  window.AXStrip = { poll: poll, update: update, banner: banner };
16661
16676
  poll();
16662
16677
  })();
16663
- `;var ss=`
16678
+ `;var is=`
16664
16679
  .cs { margin: 0 -2px; }
16665
16680
  .cs[hidden] { display: none; }
16666
16681
  .cs-list {
@@ -16716,7 +16731,7 @@ window.AXChatLog = function (o) {
16716
16731
  @media (prefers-reduced-motion: reduce) {
16717
16732
  .cs-thinking .cs-dot, .cs-answering .cs-dot, .cs-banner { animation: none; }
16718
16733
  }
16719
- `;function is(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 ls(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var cs=`
16734
+ `;function ls(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 cs(t,e){return e||!t.length?{item:null,queue:t.slice()}:{item:t[0],queue:t.slice(1)}}var ds=`
16720
16735
  body { height: 100dvh; }
16721
16736
  main { min-height: 0; }
16722
16737
  #panel-chat:not([hidden]) { display: flex; flex-direction: column; min-height: 100%; }
@@ -16826,7 +16841,7 @@ main { min-height: 0; }
16826
16841
  background: color-mix(in oklch, var(--ax-accent) 15%, var(--ax-surface)); color: var(--ax-accent);
16827
16842
  }
16828
16843
  .cx-composer .fx-btn { border-radius: var(--ax-radius); }
16829
- `;var ds=`
16844
+ `;var ps=`
16830
16845
  window.AXOrb = (function () {
16831
16846
  // Same list, order and hash as presenceLook (src/voice/presence.ts) and
16832
16847
  // OrbMath.colorHex, for an agent whose colour did not come with it.
@@ -16957,7 +16972,7 @@ window.AXOrb = (function () {
16957
16972
  }
16958
16973
  return { create: create, colorFor: colorFor, levelFromRms: levelFromRms, speakingEnvelope: speakingEnvelope };
16959
16974
  })();
16960
- `;var ps=`
16975
+ `;var us=`
16961
16976
  window.AXVoiceIO = (function () {
16962
16977
  var TYPES = ['audio/webm;codecs=opus', 'audio/mp4', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/aac'];
16963
16978
  var ac = null, playing = null;
@@ -17075,7 +17090,7 @@ window.AXVoiceIO = (function () {
17075
17090
 
17076
17091
  return { canRecord: canRecord, mimeType: mimeType, unlock: unlock, record: record, playAudio: playAudio, speakText: speakText, stop: stopPlaying };
17077
17092
  })();
17078
- `;var us=`
17093
+ `;var ms=`
17079
17094
  (function () {
17080
17095
  var panel = document.getElementById('panel-chat'), C = window.AXChat, IO = window.AXVoiceIO, O = window.AXOrb;
17081
17096
  if (!panel || !C || !IO || !O) return;
@@ -17283,7 +17298,7 @@ window.AXVoiceIO = (function () {
17283
17298
  idle();
17284
17299
  window.AXVoice = { show: show, orb: orb, state: function () { return v.state; }, queued: function () { return speech.length; } };
17285
17300
  })();
17286
- `;var ms=`
17301
+ `;var fs=`
17287
17302
  .vx {
17288
17303
  position: sticky; bottom: -16px; z-index: 1; display: grid; justify-items: center; gap: 4px;
17289
17304
  margin: 0 0 -16px; padding: 8px 0 12px; background: var(--ax-bg);
@@ -17319,7 +17334,7 @@ window.AXVoiceIO = (function () {
17319
17334
  .cx-typing-on .vx-orb { width: 88px; height: 88px; }
17320
17335
  .cx-typing-on .vx-row { gap: 16px; }
17321
17336
  @media (prefers-reduced-motion: reduce) { .vx-orb { transition: none; } }
17322
- `;var fs=`
17337
+ `;var hs=`
17323
17338
  <main class="card">
17324
17339
  <h1>This phone isn't paired</h1>
17325
17340
  <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>
@@ -17333,7 +17348,7 @@ window.AXVoiceIO = (function () {
17333
17348
  <p id="pair-msg" class="pair-msg" role="status" aria-live="polite"></p>
17334
17349
  </form>
17335
17350
  <p class="muted">If this phone was paired before, it may have been removed with <code>agentx app revoke</code>.</p>
17336
- </main>`,hs=`
17351
+ </main>`,gs=`
17337
17352
  .pair-form { display: grid; gap: 10px; margin: 20px 0 24px; }
17338
17353
  .pair-form label { font-weight: 600; }
17339
17354
  .pair-form input {
@@ -17355,7 +17370,7 @@ window.AXVoiceIO = (function () {
17355
17370
  margin: 0; padding: 8px 12px; border-radius: var(--ax-radius-sm); font-size: var(--ax-fs-sm);
17356
17371
  background: var(--ax-amber-t); color: var(--ax-amber-ink); border: 1px solid var(--ax-amber-e);
17357
17372
  }
17358
- `,gs=`
17373
+ `,xs=`
17359
17374
  (function () {
17360
17375
  var form = document.getElementById('pair-form');
17361
17376
  var input = document.getElementById('pair-code');
@@ -17447,7 +17462,7 @@ window.AXVoiceIO = (function () {
17447
17462
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
17448
17463
  }
17449
17464
  })();
17450
- `;function xs(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function vs(t,e){return!t||e-t>=3e4||t>e}function bs(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 ys(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 ws=`
17465
+ `;function vs(t){return t>=200&&t<300?"retry":t===401?"lock":"keep"}function bs(t,e){return!t||e-t>=3e4||t>e}function ys(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 ws(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 ks=`
17451
17466
  <div id="scan" class="scan" role="dialog" aria-modal="true" aria-labelledby="scan-title" hidden>
17452
17467
  <video id="scan-video" playsinline muted autoplay></video>
17453
17468
  <div class="scan-frame" aria-hidden="true"></div>
@@ -17456,7 +17471,7 @@ window.AXVoiceIO = (function () {
17456
17471
  <button type="button" id="scan-close" class="scan-close">Close</button>
17457
17472
  </div>
17458
17473
  <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>
17459
- </div>`,ks=`
17474
+ </div>`,_s=`
17460
17475
  .pair-form .scan-btn {
17461
17476
  color: var(--ax-accent-2, var(--ax-accent)); background: transparent; border: 2px solid var(--ax-accent);
17462
17477
  }
@@ -17485,7 +17500,7 @@ window.AXVoiceIO = (function () {
17485
17500
  }
17486
17501
  .scan-msg.bad { color: #ffd0cc; font-weight: 600; }
17487
17502
  body.scanning { overflow: hidden; }
17488
- `,_s=`
17503
+ `,Es=`
17489
17504
  (function () {
17490
17505
  var openBtn = document.getElementById('scan-btn');
17491
17506
  var box = document.getElementById('scan');
@@ -17651,7 +17666,7 @@ body.scanning { overflow: hidden; }
17651
17666
  document.addEventListener('visibilitychange', function () { if (document.hidden) close(); });
17652
17667
  window.addEventListener('pagehide', close);
17653
17668
  })();
17654
- `;var xa=`
17669
+ `;var va=`
17655
17670
  .cam { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; background: var(--ax-bg); }
17656
17671
  .cam[hidden] { display: none; }
17657
17672
  .cam-live {
@@ -17693,7 +17708,7 @@ body.scanning { overflow: hidden; }
17693
17708
  border: var(--ax-border-w) solid var(--ax-border); line-height: 1.5; max-height: 30vh; overflow: auto;
17694
17709
  }
17695
17710
  .cam-reply strong { display: block; font-size: 13px; color: var(--ax-text-2); margin-bottom: 4px; }
17696
- `;var Es='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Ss=`
17711
+ `;var Ss='<button type="button" id="cam-btn" class="icon-btn" aria-label="Share camera" aria-haspopup="dialog">\u{1F4F7}</button>',Ts=`
17697
17712
  <div id="cam" class="cam" role="dialog" aria-modal="true" aria-labelledby="cam-title" hidden>
17698
17713
  <div class="cam-live" id="cam-live" role="status" aria-live="polite" hidden>
17699
17714
  <span class="cam-dot" aria-hidden="true"></span>
@@ -17718,7 +17733,7 @@ body.scanning { overflow: hidden; }
17718
17733
  <button type="button" id="cam-close" class="cam-secondary">Close</button>
17719
17734
  </div>
17720
17735
  </div>
17721
- </div>`,Ts=`
17736
+ </div>`,As=`
17722
17737
  (function () {
17723
17738
  var btn = document.getElementById('cam-btn');
17724
17739
  var sheet = document.getElementById('cam');
@@ -17987,7 +18002,7 @@ body.scanning { overflow: hidden; }
17987
18002
  });
17988
18003
  window.addEventListener('pagehide', function () { stop(); });
17989
18004
  })();
17990
- `;var As=`
18005
+ `;var Cs=`
17991
18006
  <div id="cam-ask-bar" class="cam-askbar" role="alert" hidden>
17992
18007
  <div class="cam-askbar-text">
17993
18008
  <strong id="cam-ask-who">An agent</strong> wants to see through your camera
@@ -17997,7 +18012,7 @@ body.scanning { overflow: hidden; }
17997
18012
  <button type="button" id="cam-ask-show" class="cam-askbar-show">Show</button>
17998
18013
  <button type="button" id="cam-ask-no" class="cam-askbar-no">Decline</button>
17999
18014
  </div>
18000
- </div>`,Cs=`
18015
+ </div>`,Is=`
18001
18016
  .cam-askbar[hidden] { display: none; }
18002
18017
  .cam-askbar {
18003
18018
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
@@ -18012,7 +18027,7 @@ body.scanning { overflow: hidden; }
18012
18027
  border: 2px solid #fff; background: #fff; color: var(--ax-accent);
18013
18028
  }
18014
18029
  .cam-askbar-no { background: transparent; color: #fff; }
18015
- `,Is=`
18030
+ `,Ms=`
18016
18031
  (function () {
18017
18032
  var bar = document.getElementById('cam-ask-bar');
18018
18033
  if (!bar) return;
@@ -18082,8 +18097,8 @@ body.scanning { overflow: hidden; }
18082
18097
  setInterval(poll, 5000);
18083
18098
  document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') poll(); });
18084
18099
  })();
18085
- `;function Ms(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 Ls(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 va=`
18086
- ${U({afterUnauthorized:xs})}
18100
+ `;function Ls(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 Rs(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 ba=`
18101
+ ${U({afterUnauthorized:vs})}
18087
18102
  var CACHE = 'agentx-app-v3';
18088
18103
  var STATIC = ['/app/manifest.webmanifest', '/app/icon-192.png', '/app/icon-512.png'];
18089
18104
  self.addEventListener('install', function (e) {
@@ -18174,7 +18189,7 @@ self.addEventListener('notificationclick', function (e) {
18174
18189
  return self.clients.openWindow(target);
18175
18190
  }));
18176
18191
  });
18177
- `;var up="<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 ba(t){return`<meta charset="utf-8">
18192
+ `;var mp="<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 ya(t){return`<meta charset="utf-8">
18178
18193
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
18179
18194
  <meta name="theme-color" content="#2979FF">
18180
18195
  <meta name="referrer" content="no-referrer">
@@ -18185,55 +18200,55 @@ self.addEventListener('notificationclick', function (e) {
18185
18200
  <link rel="icon" type="image/png" href="/app/icon-192.png">
18186
18201
  <link rel="apple-touch-icon" href="/app/icon-192.png">
18187
18202
  <title>${t}</title>
18188
- ${up}
18189
- <style>${xn}${hp}</style>`}var Rs=[{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 $s(){let t=Rs.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=Rs.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
18203
+ ${mp}
18204
+ <style>${bn}${gp}</style>`}var $s=[{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 Ps(){let t=$s.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=$s.map((a,n)=>`<section role="tabpanel" id="panel-${a.id}" aria-labelledby="tab-${a.id}" tabindex="0"${n===0?"":" hidden"}>
18190
18205
  <h2>${a.label}</h2>
18191
18206
  <p class="soon">${a.soon}</p>
18192
18207
  </section>`).join("");return`<!doctype html>
18193
18208
  <html lang="en">
18194
- <head>${ba("AgentX")}<style>${gp}${Qo}${cs}${ss}${ms}${xa}${Cs}</style></head>
18209
+ <head>${ya("AgentX")}<style>${xp}${Zo}${ds}${is}${fs}${va}${Is}</style></head>
18195
18210
  <body>
18196
18211
  <header class="bar">
18197
18212
  <div>
18198
18213
  <h1>AgentX</h1>
18199
18214
  <p id="who" class="who">Connecting\u2026</p>
18200
18215
  </div>
18201
- <div class="bar-btns">${Es}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
18216
+ <div class="bar-btns">${Ss}<button type="button" id="theme" class="icon-btn" aria-label="Switch to light theme">\u25D0</button></div>
18202
18217
  </header>
18203
18218
  <p id="offline" class="offline" role="status" hidden>Offline. Showing the saved app; live data needs a connection.</p>
18204
- ${As}
18219
+ ${Cs}
18205
18220
  <main>${e}</main>
18206
18221
  <nav class="tabs" role="tablist" aria-label="Sections">${t}</nav>
18207
- ${Ss}
18208
- <script>${mp}</script>
18209
- <script>${Yo}</script>
18210
- <script>${Zo}</script>
18222
+ ${Ts}
18223
+ <script>${fp}</script>
18224
+ <script>${Qo}</script>
18211
18225
  <script>${es}</script>
18212
- <script>${U({markdownToHtml:vn})}${as}${rs}${ns}${ts}</script>
18213
- <script>${U({queueSpeech:is,nextSpeech:ls})}${ds}${ps}${us}</script>
18214
- <script>${os}</script>
18215
- <script>${U({cameraConstraints:Ms,shareClock:Ls})}${Ts}</script>
18216
- <script>${Is}</script>
18226
+ <script>${ts}</script>
18227
+ <script>${U({markdownToHtml:yn})}${ns}${os}${rs}${as}</script>
18228
+ <script>${U({queueSpeech:ls,nextSpeech:cs})}${ps}${us}${ms}</script>
18229
+ <script>${ss}</script>
18230
+ <script>${U({cameraConstraints:Ls,shareClock:Rs})}${As}</script>
18231
+ <script>${Ms}</script>
18217
18232
  </body>
18218
- </html>`}function Ps(){return`<!doctype html>
18233
+ </html>`}function js(){return`<!doctype html>
18219
18234
  <html lang="en">
18220
- <head>${ba("Pair \xB7 AgentX")}</head>
18235
+ <head>${ya("Pair \xB7 AgentX")}</head>
18221
18236
  <body>
18222
18237
  <main class="card">
18223
18238
  <h1>Pairing this phone\u2026</h1>
18224
18239
  <p id="msg" role="status">One moment.</p>
18225
18240
  </main>
18226
- <script>${fp}</script>
18241
+ <script>${hp}</script>
18227
18242
  </body>
18228
- </html>`}function js(){return`<!doctype html>
18243
+ </html>`}function Os(){return`<!doctype html>
18229
18244
  <html lang="en">
18230
- <head>${ba("Not paired \xB7 AgentX")}<style>${hs}${ks}</style></head>
18231
- <body>${fs}${ws}
18232
- <script>${U({mayBounce:vs,formatPairInput:bs,parsePairScan:ys})}</script>
18233
- <script>${gs}</script>
18234
- <script>${_s}</script>
18245
+ <head>${ya("Not paired \xB7 AgentX")}<style>${gs}${_s}</style></head>
18246
+ <body>${hs}${ks}
18247
+ <script>${U({mayBounce:bs,formatPairInput:ys,parsePairScan:ws})}</script>
18248
+ <script>${xs}</script>
18249
+ <script>${Es}</script>
18235
18250
  </body>
18236
- </html>`}function Os(){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 mp=`
18251
+ </html>`}function Ns(){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 fp=`
18237
18252
  (function () {
18238
18253
  var tabs = Array.prototype.slice.call(document.querySelectorAll('[role=tab]'));
18239
18254
  function select(tab, focus, keepHash) {
@@ -18303,7 +18318,7 @@ ${Ss}
18303
18318
  navigator.serviceWorker.register('/app/sw.js', { scope: '/app' }).catch(function () {});
18304
18319
  }
18305
18320
  })();
18306
- `,fp=`
18321
+ `,hp=`
18307
18322
  (function () {
18308
18323
  var msg = document.getElementById('msg');
18309
18324
  var m = /(?:^#|&)token=([^&]+)/.exec(location.hash);
@@ -18320,7 +18335,7 @@ ${Ss}
18320
18335
  : 'Pairing failed (HTTP ' + r.status + '). Try again.';
18321
18336
  }).catch(function () { msg.textContent = 'Could not reach AgentX. Check this phone is on your tailnet, then try again.'; });
18322
18337
  })();
18323
- `,hp=`
18338
+ `,gp=`
18324
18339
  html, body { margin: 0; background: var(--ax-bg); color: var(--ax-text); font-family: var(--ax-font); }
18325
18340
  body { min-height: 100dvh; -webkit-text-size-adjust: 100%; }
18326
18341
  code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surface-3); padding: 1px 6px; border-radius: 6px; }
@@ -18332,7 +18347,7 @@ code { font-family: var(--ax-mono); font-size: 0.92em; background: var(--ax-surf
18332
18347
  .card h1 { font-size: 22px; margin: 0 0 12px; }
18333
18348
  .muted { color: var(--ax-text-2); }
18334
18349
  :focus-visible { outline: 3px solid var(--ax-accent); outline-offset: 2px; }
18335
- `,gp=`
18350
+ `,xp=`
18336
18351
  body { display: flex; flex-direction: column; }
18337
18352
  .bar {
18338
18353
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
@@ -18370,8 +18385,8 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
18370
18385
  }
18371
18386
  .tabs [role=tab][aria-selected=true] { background: var(--ax-accent-t); color: var(--ax-accent-2); }
18372
18387
  [data-theme="dark"] .tabs [role=tab][aria-selected=true] { color: var(--ax-text); }
18373
- `;var Ct="agentx_app",bp=400*86400,yp=new Tt,wp=new At;async function Ns(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ae;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ge(e,200,"application/manifest+json",Os());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ge(e,200,"text/javascript; charset=utf-8",va);if(a==="/app/icon-192.png")return ge(e,200,"image/png",ia(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ge(e,200,"image/png",ia(512),"public, max-age=86400");if(a==="/app/pair")return ge(e,200,"text/html; charset=utf-8",Ps());if(a==="/app/qr.js"){let i=kp();return i?ge(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ae(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=ya(Ge(t),o);return i?(e.setHeader("Set-Cookie",wa(Ge(t))),Ae(e,200,{device:i.name})):Ae(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Ko(t,{codes:r.pairCodes??new An,limiter:r.pairLimiter??yp,verify:l=>ya(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",wa(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ae(e,i.status,i.body)}let s=ya(_p(t),o);if(!s){let i=Ge(t);return(r.rejectLog??wp).record(a.slice(0,120),Vo(t,ga(ka(t,Ct),o),i?ga(i,o):null)),a==="/app"?ge(e,401,"text/html; charset=utf-8",js()):Ae(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=ka(t,Ct);return i&&!Ge(t)&&e.setHeader("Set-Cookie",wa(i)),ge(e,200,"text/html; charset=utf-8",$s())}return n==="GET"&&a==="/api/app/me"?Ae(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await ko(t,e,a,n,s.name,r.fleet)||r.push&&await Eo(t,e,a,n,s,r.push)||r.announce&&await Ao(t,e,a,n,s,r.announce)||r.chat&&await Do(t,e,a,n,s,r.chat)||r.chat&&await Fo(t,e,a,n,s,r.chat)||r.voice&&await Wo(t,e,a,n,s,r.voice)||r.camera&&await Go(t,e,a,n,r.camera)?!0:Ae(e,404,{error:"not found"})}var We;function kp(){if(We!==void 0)return We;try{let t=vp(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
18374
- `;We=Buffer.concat([Buffer.from(a),xp(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),We=null}return We}function ya(t,e){if(!t)return null;let a=e.verify(t);return a&&ye(a,"app")?a:null}function wa(t){return`${Ct}=${t}; Path=/; Max-Age=${bp}; HttpOnly; Secure; SameSite=Lax`}function _p(t){return Ge(t)??ka(t,Ct)}function Ge(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function ka(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 ge(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ae(t,e,a){return ge(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Ds}from"crypto";var Ce={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:ie.perMessage},Ep=/^[a-f0-9]{32}$/,Sp=/^c[a-z0-9]{8,32}$/,Tp=/^#[0-9a-fA-F]{6}$/;function _a(t){return Sp.test(t)}var Xe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
18388
+ `;var Ct="agentx_app",yp=400*86400,wp=new Tt,kp=new At;async function Ds(t,e,a,n,r={}){if(a!=="/app"&&!a.startsWith("/app/")&&!a.startsWith("/api/app/"))return!1;let o=r.tokens??new ae;if(n==="GET"){if(a==="/app/manifest.webmanifest")return ge(e,200,"application/manifest+json",Ns());if(a==="/app/sw.js")return e.setHeader("Service-Worker-Allowed","/app"),ge(e,200,"text/javascript; charset=utf-8",ba);if(a==="/app/icon-192.png")return ge(e,200,"image/png",la(192),"public, max-age=86400");if(a==="/app/icon-512.png")return ge(e,200,"image/png",la(512),"public, max-age=86400");if(a==="/app/pair")return ge(e,200,"text/html; charset=utf-8",js());if(a==="/app/qr.js"){let i=_p();return i?ge(e,200,"text/javascript; charset=utf-8",i,"public, max-age=2592000"):Ce(e,404,{error:"not found"})}}if(n==="POST"&&a==="/api/app/session"){let i=wa(Ge(t),o);return i?(e.setHeader("Set-Cookie",ka(Ge(t))),Ce(e,200,{device:i.name})):Ce(e,401,{error:"invalid or revoked device token"})}if(n==="POST"&&a==="/api/app/pair-code"){let i=await Jo(t,{codes:r.pairCodes??new In,limiter:r.pairLimiter??wp,verify:l=>wa(l,o)?.name??null,minMs:r.pairMinMs});return i.status===200&&e.setHeader("Set-Cookie",ka(i.token)),i.status===429&&e.setHeader("Retry-After",String(i.retryAfter)),Ce(e,i.status,i.body)}let s=wa(Ep(t),o);if(!s){let i=Ge(t);return(r.rejectLog??kp).record(a.slice(0,120),Yo(t,xa(_a(t,Ct),o),i?xa(i,o):null)),a==="/app"?ge(e,401,"text/html; charset=utf-8",Os()):Ce(e,401,{error:"this device is not paired",hint:"run: agentx app pair"})}if(n==="GET"&&a==="/app"){let i=_a(t,Ct);return i&&!Ge(t)&&e.setHeader("Set-Cookie",ka(i)),ge(e,200,"text/html; charset=utf-8",Ps())}return n==="GET"&&a==="/api/app/me"?Ce(e,200,{id:s.id,device:s.name,node:r.nodeName??null}):r.fleet&&await _o(t,e,a,n,s.name,r.fleet)||r.push&&await So(t,e,a,n,s,r.push)||r.announce&&await Co(t,e,a,n,s,r.announce)||r.chat&&await Ho(t,e,a,n,s,r.chat)||r.chat&&await qo(t,e,a,n,s,r.chat)||r.voice&&await Go(t,e,a,n,s,r.voice)||r.camera&&await Xo(t,e,a,n,r.camera)?!0:Ce(e,404,{error:"not found"})}var We;function _p(){if(We!==void 0)return We;try{let t=bp(import.meta.url),{version:e}=t("jsqr/package.json"),a=`/*! jsQR ${e} | Apache-2.0 | https://github.com/cozmo/jsQR */
18389
+ `;We=Buffer.concat([Buffer.from(a),vp(t.resolve("jsqr"))])}catch(t){console.error(`[app] QR decoder unavailable (install the jsqr package): ${t.message}`),We=null}return We}function wa(t,e){if(!t)return null;let a=e.verify(t);return a&&ye(a,"app")?a:null}function ka(t){return`${Ct}=${t}; Path=/; Max-Age=${yp}; HttpOnly; Secure; SameSite=Lax`}function Ep(t){return Ge(t)??_a(t,Ct)}function Ge(t){let e=t.headers.authorization||"";return e.toLowerCase().startsWith("bearer ")&&e.slice(7).trim()||null}function _a(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 ge(t,e,a,n,r="no-store"){return t.writeHead(e,{"Content-Type":a,"Cache-Control":r}),t.end(n),!0}function Ce(t,e,a){return ge(t,e,"application/json",JSON.stringify(a))}import{randomBytes as Hs}from"crypto";var Ie={content:32e3,messagesPerConversation:200,conversationsPerDevice:100,toolsPerMessage:50,filesPerMessage:le.perMessage},Sp=/^[a-f0-9]{32}$/,Tp=/^c[a-z0-9]{8,32}$/,Ap=/^#[0-9a-fA-F]{6}$/;function Ea(t){return Tp.test(t)}var Xe=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS app_chat_conversations (
18375
18390
  id TEXT PRIMARY KEY, device_id TEXT NOT NULL, title TEXT NOT NULL,
18376
18391
  node TEXT NOT NULL, node_name TEXT NOT NULL, agent TEXT NOT NULL, agent_name TEXT,
18377
18392
  created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);
@@ -18384,39 +18399,39 @@ main h2 { font-size: 20px; margin: 4px 0 8px; }
18384
18399
  id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, message_id INTEGER NOT NULL,
18385
18400
  path TEXT NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, kind TEXT NOT NULL, created_at INTEGER NOT NULL);
18386
18401
  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 (
18387
- key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return _a(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)}${Ds(4).toString("hex")}`,{color:s,...i}=a,l=s&&Tp.test(s)?s:void 0,c={id:o,title:Cp(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
18388
- (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(!_a(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(Ap);return{...Hs(n),messages:r}}list(e,a=Ce.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
18402
+ key TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, at INTEGER NOT NULL)`)}ownerOf(e){return Ea(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)}${Hs(4).toString("hex")}`,{color:s,...i}=a,l=s&&Ap.test(s)?s:void 0,c={id:o,title:Ip(n),...i,...l?{color:l}:{},createdAt:r,updatedAt:r,messages:[]};return this.db.prepare(`INSERT INTO app_chat_conversations
18403
+ (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(!Ea(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(Cp);return{...Bs(n),messages:r}}list(e,a=Ie.conversationsPerDevice){return this.db.prepare(`SELECT c.*,
18389
18404
  (SELECT COUNT(*) FROM app_chat_messages m WHERE m.conversation_id = c.id) AS n,
18390
18405
  (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
18391
- 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{...Hs(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){_a(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,
18406
+ 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{...Bs(r),messages:r.n,...o?{last:o}:{}}})}markRead(e,a,n=Date.now()){Ea(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,
18392
18407
  substr(m.content, 1, 240) AS answer, m.status, m.at
18393
18408
  FROM app_chat_conversations c
18394
18409
  JOIN app_chat_messages m ON m.id = (SELECT MAX(id) FROM app_chat_messages WHERE conversation_id = c.id)
18395
18410
  WHERE c.device_id = ? AND m.role = 'assistant' AND m.at > COALESCE(c.read_at, 0)
18396
- 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>Ce.content?n.content.slice(0,Ce.content)+`
18411
+ 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>Ie.content?n.content.slice(0,Ie.content)+`
18397
18412
 
18398
- [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ce.toolsPerMessage),l=[];for(let m of r){if(l.length>=Ce.filesPerMessage)break;let h=m.filename.trim(),w=Ha(h);if(!w||!h||h.length>ie.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Ds(16).toString("hex"),name:_,mime:w.mime,kind:w.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
18413
+ [Cut here: the full answer is in the agent's task history.]`:n.content,i=n.tools?.slice(0,Ie.toolsPerMessage),l=[];for(let m of r){if(l.length>=Ie.filesPerMessage)break;let h=m.filename.trim(),w=Ba(h);if(!w||!h||h.length>le.pathChars||h.includes("\0"))continue;let _=(h.split(/[\\/]/).pop()||h).slice(0,120);l.push({id:Hs(16).toString("hex"),name:_,mime:w.mime,kind:w.kind,path:h})}let c=l.map(m=>({id:m.id,name:m.name,mime:m.mime,kind:m.kind})),p=this.db.prepare(`INSERT INTO app_chat_messages (conversation_id, role, content, status, error, ui, tools, files, at)
18399
18414
  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)
18400
18415
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let m of l)u.run(m.id,a,Number(p.lastInsertRowid),m.path,m.name,m.mime,m.kind,n.at);return this.db.prepare(`DELETE FROM app_chat_messages WHERE conversation_id = ? AND id NOT IN
18401
- (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ce.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
18402
- (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(!Ep.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
18416
+ (SELECT id FROM app_chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?)`).run(a,a,Ie.messagesPerConversation),this.db.prepare(`DELETE FROM app_chat_files WHERE conversation_id = ? AND message_id NOT IN
18417
+ (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(!Sp.test(a))return null;let n=this.db.prepare(`SELECT f.*, c.node, c.agent FROM app_chat_files f
18403
18418
  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 = ?
18404
- ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ce.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 Hs(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 Ap(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 Cp(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Ip=4e3,Ea=100,Mp=15,Bs=t=>t.replace(/\/+$/,""),It=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Ip){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,Ea);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??Mp)-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>=Ea&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Ea}); 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||Bs(l)!==Bs(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=Lp(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&_t(h)&&this.deps.notifyFinish(Et(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Lp(t,e){let a=t.plain?{text:Qe(t.text,!1),artifacts:[]}:Ye(t.text,ie.perMessage,!1),{cleanText:n,ui:r}=et(a.text),o=t.plain?void 0:ca(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:Rp(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function Rp(t){return t.replace(/\s+/g," ").trim().slice(0,300)}function Jx(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,Up(h,t))}catch(w){console.error(` Board "${h.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Ke(process.cwd(),t.workflows.dir):void 0,c=new Oa(l?{baseDir:l}:void 0),p=new Na(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new Da(l?{baseDir:l}:void 0);zr(t),en({business:t.business?.enabled===!0});let m=$p(async(h,w)=>{try{await Bp(h,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){y(w,500,{error:_.message||"internal error"})}});iu(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
18419
+ ORDER BY updated_at DESC, rowid DESC LIMIT -1 OFFSET ?`).all(e,Ie.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 Bs(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 Cp(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 Ip(t){let e=t.replace(/\s+/g," ").trim();return(e.length>60?e.slice(0,59)+"\u2026":e)||"Untitled"}var Mp=4e3,Sa=100,Lp=15,zs=t=>t.replace(/\/+$/,""),It=class{constructor(e){this.deps=e}cursor;retry=new Map;timer;running=!1;start(e=Mp){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,Sa);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??Lp)-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>=Sa&&n?.(`[app] warning: one poll returned ${e} delegation events, the most it reads (${Sa}); 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||zs(l)!==zs(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=Rp(r,this.deps.now?.()??Date.now());if(a.appendOnce(s,o,`dlg:${e.node}:${r.taskId}`,c.row,c.declared)===null)return"skip";let u=c.row.status,m=!!this.deps.finishAlerts?.(s),h={status:u,attached:!1,appOpen:this.deps.presence.open(s),enabled:m};return this.deps.notifyFinish&&_t(h)&&this.deps.notifyFinish(Et(s,i,u,c.row.content,c.row.error)).catch(()=>{}),"filed"}};function Rp(t,e){let a=t.plain?{text:Qe(t.text,!1),artifacts:[]}:Ye(t.text,le.perMessage,!1),{cleanText:n,ui:r}=et(a.text),o=t.plain?void 0:da(r),s=t.status==="error"?"error":"done";return{row:{role:"assistant",content:n,status:s,...s==="error"?{error:$p(n)}:{},...o?{ui:o}:{},at:e},declared:a.artifacts}}function $p(t){return t.replace(/\s+/g," ").trim().slice(0,300)}function Yx(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,Wp(h,t))}catch(w){console.error(` Board "${h.id}" failed to initialize: ${w.message}`)}let i=t.node?.id||"local",l=t.workflows?.dir?Ke(process.cwd(),t.workflows.dir):void 0,c=new Na(l?{baseDir:l}:void 0),p=new Da(l?{baseDir:l,nodeId:i}:{nodeId:i}),u=new Ha(l?{baseDir:l}:void 0);Fr(t),an({business:t.business?.enabled===!0});let m=Pp(async(h,w)=>{try{await zp(h,w,{boards:a,sources:s,token:o,config:t,workflowStore:c,workflowRuns:p,workflowLayouts:u})}catch(_){y(w,500,{error:_.message||"internal error"})}});lu(t).start(),m.listen(n,r,()=>{let h=r==="0.0.0.0"?"localhost":r;a.length===0?(console.log(`
18405
18420
  Live dashboard: http://${h}:${n}
18406
18421
  `),console.log(" (no boards configured \u2014 '/' serves the live view; add a board with 'agentx board add')")):(console.log(`
18407
18422
  Kanban dashboard: http://${h}:${n}
18408
- `),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Hp=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function Bp(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(Qa(t.headers)==="foreign"&&Za(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Ns(t,e,r,o,{nodeName:a.config.node?.name,fleet:Gs(a.config),push:Ws(a.config),announce:Co(a.config),chat:Xs(a.config),voice:lu(a.config),camera:cu(a.config)}))return;if(o==="GET"&&Hp.has(r)&&Mn("page",r),o==="GET"&&r==="/"){let d=_n();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(oa({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(mo({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(oa({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await xe(t):void 0,v=x?.node??f,k=v?d.find(I=>I.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",E=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,E.status,await E.json().catch(()=>({error:`HTTP ${E.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await xe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Bn({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Hn({peers:H(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(jn({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=za(await be(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 T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await Ba(t)):void 0,E=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,E.status,await E.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(lo({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fo({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ho({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(go({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kn({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",f=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(xo({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:f,peers:H(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(vo({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){En(t,e);return}if(o==="POST"&&r==="/api/setup"){await Sn(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Tn(t,e);return}if(o==="GET"&&r==="/admin"){Yn(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){cr(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){rr(t,e,H(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}gr(t,e,H(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 hu(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await na(t,e,r,x=>Js(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),v=x.indexOf("::");if(v>0){let k=x.slice(0,v),b=x.slice(v+2),E=a.config.node?.id||a.config.node?.name||"local";if(k===E)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=Je(I.url.replace(/\/+$/,""),a.config);if(C){await Fs(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=Je(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await Fs(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await xr(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await gu(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-DST4SVW4.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(wr({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await yr(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_r({peers:H(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 Xp(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 Fr(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await na(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Ur(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Xr(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ae,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await Qn(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,an()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await dr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await or(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Kr(t,e,r);return}if(r.startsWith("/api/admin/")){await Zn(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(zn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=mu("web/"+d);try{let x=await fu(f),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ne(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Ne(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,v,k)=>{let b=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let f=await be(a.config);y(e,200,await co(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,v,k,b)=>{let E=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(E)?Math.max(k,Math.min(b,E)):v};try{let x=await be(a.config);y(e,200,await uo(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[f.get("kind"),f.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await po(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){eu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!f||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await tu(t,e,a,f,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await ru(e,a,f,x,v,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!f||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await ou(t,e,a,f,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await Ca(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await xe(t);try{let f=await pu(a.config,d);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!au(t,e,[`agent:${d}`]))return;await nu(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ae,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Kp(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await Ca(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(E=>({name:E.name,url:E.url,token:E.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let E of k)try{E.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
18423
+ `),console.log(` Boards: ${a.map(w=>w.id).join(", ")}`)),r==="127.0.0.1"&&!o?console.log(" (bound to localhost; no auth token \u2014 safe default)"):r!=="127.0.0.1"&&!o&&console.log(" \u26A0 bound to a non-loopback address without a token \u2014 writes are UNAUTHENTICATED")})}var Bp=new Set(["/","/live","/mesh","/monitor","/activity","/boards","/glossary","/workflows","/workflows/editor","/procedures","/processes","/graph","/setup","/admin","/admin/graph","/approvals","/admin/health","/admin/observability","/admin/ledger","/admin/cost","/admin/projects","/admin/wiki"]);async function zp(t,e,a){let n=new URL(t.url||"/","http://localhost"),r=n.pathname,o=(t.method||"GET").toUpperCase();if(en(t.headers)==="foreign"&&tn(o)){y(e,403,{error:"Forbidden: request from a page on another origin"});return}if(o==="OPTIONS"){e.writeHead(204),e.end();return}if(await Ds(t,e,r,o,{nodeName:a.config.node?.name,fleet:Xs(a.config),push:Gs(a.config),announce:Io(a.config),chat:Ks(a.config),voice:cu(a.config),camera:du(a.config)}))return;if(o==="GET"&&Bp.has(r)&&Rn("page",r),o==="GET"&&r==="/"){let d=Sn();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(sa({peers:H(a.config)}));return}if(o==="GET"&&r==="/boards"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(fo({peers:H(a.config)}));return}if(o==="GET"&&r==="/live"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(sa({peers:H(a.config)}));return}if(o==="POST"&&r.match(/^\/webhook\/n8n\/[A-Za-z0-9._:-]{1,64}$/)){try{let[d]=await be(a.config);if(!d){y(e,503,{error:"no node available"});return}let f=await new Promise(v=>{let k="";t.on("data",b=>k+=b),t.on("end",()=>v(k)),t.on("error",()=>v(""))}),x=await fetch(d.url+r,{method:"POST",headers:{"Content-Type":"application/json",...d.token?{Authorization:`Bearer ${d.token}`}:{}},body:f||"{}"});e.writeHead(x.status,{"Content-Type":"application/json"}),e.end(await x.text())}catch(d){y(e,502,{error:"could not reach the node",message:String(d?.message||d)})}return}if(r==="/api/assistant"||r.startsWith("/api/assistant/")){try{let d=await be(a.config),f=o==="POST"?void 0:n.searchParams.get("node"),x=o==="POST"?await xe(t):void 0,v=x?.node??f,k=v?d.find(I=>I.url===v):d[0];if(!k){y(e,400,{error:"unknown node"});return}let b=n.search?n.search.replace(/([?&])node=[^&]*/,"$1").replace(/[?&]$/,""):"",E=await fetch(k.url+r+b,{method:o,headers:{"Content-Type":"application/json",...k.token?{Authorization:`Bearer ${k.token}`}:{}},...o==="POST"?{body:JSON.stringify({...x,node:void 0})}:{}});y(e,E.status,await E.json().catch(()=>({error:`HTTP ${E.status}`})))}catch(d){y(e,502,{error:"could not reach the node",message:d?.message||String(d)})}return}if(o==="POST"&&r==="/api/workflows/editor/chat"){try{let d=await xe(t),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/api/workflows/editor/chat`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(o==="GET"&&r==="/api/n8n/workflows"){try{let[d]=await be(a.config);if(!d){y(e,200,{configured:!1,workflows:[]});return}let f=await fetch(d.url+"/api/n8n/workflows",{headers:d.token?{Authorization:`Bearer ${d.token}`}:{}});y(e,f.status,await f.json().catch(()=>({configured:!1,workflows:[]})))}catch{y(e,200,{configured:!1,workflows:[]})}return}if(o==="GET"&&r==="/workflows/editor"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Fn({peers:H(a.config)}));return}if(o==="GET"&&r==="/activity"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(zn({peers:H(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(Nn({peers:H(a.config)}));return}if(r==="/api/monitor"||r.startsWith("/api/monitor/")){let d=new AbortController,f=setTimeout(()=>d.abort(),8e3);try{let x=Fa(await be(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 T=await fetch(C.url+"/monitor",{headers:C.token?{Authorization:`Bearer ${C.token}`}:{},signal:d.signal});if(!T.ok)throw new Error(`HTTP ${T.status}`);return{name:C.name,url:C.url,ok:!0,data:await T.json()}}catch(T){return{name:C.name,url:C.url,ok:!1,error:T.message}}}));y(e,200,{nodes:I});return}let v=x.find(I=>I.url===n.searchParams.get("node"));if(!v){y(e,400,{error:"Select a known node"});return}let k=r.slice(13);if(!(o==="GET"&&["discover","actions","activity"].includes(k)||o==="POST"&&["register","ended","action","retry","clear"].includes(k))){y(e,405,{error:"Unknown monitor operation"});return}let b=o==="POST"?JSON.stringify(await za(t)):void 0,E=await fetch(v.url+"/monitor/"+k+(k==="actions"?"?offset="+encodeURIComponent(n.searchParams.get("offset")||"0"):k==="activity"?"?hours="+encodeURIComponent(n.searchParams.get("hours")||"24"):""),{method:o,body:b,signal:d.signal,headers:{"Content-Type":"application/json",...v.token?{Authorization:`Bearer ${v.token}`}:{}}});y(e,E.status,await E.json())}catch(x){y(e,502,{error:x.message})}finally{clearTimeout(f)}return}if(o==="GET"&&r==="/mesh"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(co({peers:H(a.config)}));return}if(o==="GET"&&r==="/glossary"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(ho({peers:H(a.config)}));return}if(o==="GET"&&r==="/workflows"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(go({peers:H(a.config)}));return}if(o==="GET"&&r==="/procedures"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(xo({peers:H(a.config)}));return}if(o==="GET"&&r==="/processes"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(En({}));return}let i=o==="GET"&&r.match(/^\/tasks\/([^/]+)$/);if(i){let d=n.searchParams.get("agent")||"",f=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(vo({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:f,peers:H(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(bo({agentId:decodeURIComponent(l[1]),agentName:n.searchParams.get("name")||void 0,nodeUrl:n.searchParams.get("node")||a.config.dashboard.daemonUrl,peers:H(a.config)}));return}if(o==="GET"&&r==="/graph"){e.writeHead(302,{Location:"/admin/graph"}),e.end();return}if(o==="GET"&&r==="/setup"){Tn(t,e);return}if(o==="POST"&&r==="/api/setup"){await An(t,e);return}if(o==="POST"&&r==="/api/setup/start-daemon"){await Cn(t,e);return}if(o==="GET"&&r==="/admin"){Zn(t,e,H(a.config),a.token);return}if(o==="GET"&&r==="/approvals"){dr(e,H(a.config),a.token);return}if(o==="GET"&&r==="/admin/graph"){sr(t,e,H(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}xr(t,e,H(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 gu(t,e,a);return}if(r==="/api/admin/activity-graph/stream"){await ra(t,e,r,x=>Vs(x,a.config));return}let f=r.match(/^\/api\/admin\/activity-graph\/dispatch\/(.+)$/);if(f){let x=decodeURIComponent(f[1]),v=x.indexOf("::");if(v>0){let k=x.slice(0,v),b=x.slice(v+2),E=a.config.node?.id||a.config.node?.name||"local";if(k===E)t.url=`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`;else{let I=(a.config.dashboard?.daemons||[]).find(C=>(C.name||C.url)===k);if(I){let C=Je(I.url.replace(/\/+$/,""),a.config);if(C){await qs(t,e,C,`/api/admin/activity-graph/dispatch/${encodeURIComponent(b)}`);return}}y(e,404,{error:`unknown node "${k}" in fleet dispatch id`});return}}}}else if(d&&d!=="primary"){let f=Je(d,a.config);if(!f){y(e,404,{error:`unknown peer: ${d}`});return}let x=(n.search||"").replace(/[?&]peer=[^&]*/g,k=>k.startsWith("?")?"?":"");await qs(t,e,f,r+(x==="?"?"":x));return}}if(o==="GET"&&r.startsWith("/api/admin/observability/")&&await vr(t,e,r))return;if(o==="GET"&&r==="/api/admin/logs/stream"){await xu(t,e);return}if(o==="GET"&&r==="/api/admin/doctor"){try{let{runDoctorChecks:d}=await import("./doctor-DST4SVW4.js"),x=new URL(t.url||"/","http://_").searchParams.get("running")!=="false",v=await d({running:x});y(e,200,v)}catch(d){y(e,500,{error:d?.message||String(d)})}return}if(o==="GET"&&r==="/admin/ledger"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(kr({peers:H(a.config)}));return}if(o==="GET"&&r.startsWith("/api/admin/ledger/")&&await wr(t,e,r))return;if(o==="GET"&&r==="/admin/cost"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(_r({peers:H(a.config)}));return}if(o==="GET"&&r==="/admin/projects"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(Er({peers:H(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 Kp(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 qr(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/stream")&&await ra(t,e,r)||o==="GET"&&r.startsWith("/api/admin/activity-graph/dispatch/")&&await Wr(t,e,r))return;let c=o==="GET"&&r.match(/^\/admin\/agents\/([a-z0-9][a-z0-9_-]*)$/);if(c){Kr(t,e,c[1],H(a.config),a.token);return}if(r.startsWith("/api/admin/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ae,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/admin/config"){await er(t,e);return}if(o==="GET"&&r==="/api/admin/voice-health"){y(e,200,rn()??{checkedAt:null,missing:[]});return}if(r.startsWith("/api/admin/approvals")){await pr(t,e,r,n);return}if(r.startsWith("/api/admin/graph/")){await ir(t,e,r);return}if(r.startsWith("/api/admin/agent/")){await Jr(t,e,r);return}if(r.startsWith("/api/admin/")){await tr(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(qn);return}if(o==="GET"&&r.startsWith("/assets/")){let d=r.slice(8);if(!/^[a-zA-Z0-9._-]+\.(js|map|css)$/.test(d)){y(e,400,{error:"invalid asset name"});return}let f=fu("web/"+d);try{let x=await hu(f),v=d.endsWith(".map")?"application/json; charset=utf-8":d.endsWith(".css")?"text/css; charset=utf-8":"application/javascript; charset=utf-8",k=n.searchParams.has("v");e.writeHead(200,{"Content-Type":v,"Cache-Control":k?"public, max-age=31536000, immutable":"public, max-age=60"}),e.end(x)}catch{y(e,404,{error:"asset not found",hint:"run: npm run build:web"})}return}if(o==="GET"&&r==="/api/live"){try{let d=await Ne(a.config);y(e,200,d)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh"){try{let d=n.searchParams.get("date")||new Date().toISOString().slice(0,10),f=n.searchParams.get("timezone")||"UTC",x=await Ne(a.config,{date:d,timezone:f});y(e,200,x)}catch(d){y(e,502,{error:d.message})}return}if(o==="GET"&&r==="/api/mesh/analytics"){let d=(f,x,v,k)=>{let b=parseInt(n.searchParams.get(f)||"",10);return Number.isFinite(b)?Math.max(v,Math.min(k,b)):x};try{let f=await be(a.config);y(e,200,await po(f,{days:d("days",30,0,180),tzOffsetMinutes:d("tzOffset",0,-840,840),limit:d("limit",60,1,200)}))}catch(f){y(e,502,{error:f.message})}return}if(o==="GET"&&r==="/api/mesh/day"){let d=n.searchParams.get("day")||"";if(!/^\d{4}-\d{2}-\d{2}$/.test(d)){y(e,400,{error:"day=YYYY-MM-DD query param required"});return}let f=(x,v,k,b)=>{let E=parseInt(n.searchParams.get(x)||"",10);return Number.isFinite(E)?Math.max(k,Math.min(b,E)):v};try{let x=await be(a.config);y(e,200,await mo(x,{day:d,tzOffsetMinutes:f("tzOffset",0,-840,840),limit:f("limit",40,1,200)}))}catch(x){y(e,502,{error:x.message})}return}if(o==="GET"&&(r==="/api/mesh/thread"||r==="/api/mesh/job"||r==="/api/mesh/run"||r==="/api/mesh/conversation")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}let f=n.searchParams,x;if(r==="/api/mesh/thread"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/thread?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/job"){let[v,k]=[f.get("kind"),f.get("key")];if(!v||!k){y(e,400,{error:"kind and key required"});return}x=`/analytics/job?kind=${encodeURIComponent(v)}&key=${encodeURIComponent(k)}&limit=${encodeURIComponent(f.get("limit")||"120")}`}else if(r==="/api/mesh/conversation"){let[v,k,b]=[f.get("agent"),f.get("channel"),f.get("chat")];if(!v||!k||!b){y(e,400,{error:"agent, channel, chat required"});return}x=`/analytics/conversation?agent=${encodeURIComponent(v)}&channel=${encodeURIComponent(k)}&chat=${encodeURIComponent(b)}&tzOffset=${encodeURIComponent(f.get("tzOffset")||"0")}`}else{let v=f.get("task");if(!v){y(e,400,{error:"task required"});return}x=`/analytics/run/${encodeURIComponent(v)}`}try{await uo(e,await be(a.config),d,x)}catch(v){y(e,502,{error:v.message})}return}if(o==="GET"&&r==="/api/live/stream"){tu(t,e,a.config);return}if(o==="GET"&&r==="/api/task/stream"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task");if(!f||!x||!v){y(e,400,{error:"node, agent, task query params required"});return}await au(t,e,a,f,x,v);return}if(o==="GET"&&r==="/api/task/history"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("agent"),v=d.searchParams.get("task"),k=d.searchParams.get("limit")||"50";if(!f||!x){y(e,400,{error:"node and agent query params required"});return}await ou(e,a,f,x,v,k);return}if(o==="POST"&&r==="/api/task/action"){let d=new URL(t.url||"/","http://localhost"),f=d.searchParams.get("node"),x=d.searchParams.get("task"),v=d.searchParams.get("kind");if(!f||!x||v!=="cancel"&&v!=="followup"){y(e,400,{error:"node, task, kind=cancel|followup query params required"});return}await su(t,e,a,f,x,v);return}if(o==="POST"&&r==="/api/voice/stop"){let d=new URL(t.url||"/","http://localhost").searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await Ia(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 f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/agents",{headers:d});if(!f.ok)throw new Error(`HTTP ${f.status}`);let x=await f.json();y(e,200,x)}catch(d){y(e,502,{error:d.message||"agents fetch failed"})}return}if(o==="GET"&&r==="/api/business/status"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=await fetch(a.config.dashboard.daemonUrl.replace(/\/+$/,"")+"/business/status",{headers:d});if(!f.ok){y(e,f.status,{error:`HTTP ${f.status}`});return}y(e,200,await f.json())}catch(d){y(e,502,{error:d.message||"business status fetch failed"})}return}if(o==="POST"&&r==="/api/draft"){let d=await xe(t);try{let f=await uu(a.config,d);y(e,200,f)}catch(f){y(e,502,{error:f.message||"draft failed"})}return}let p=r.match(/^\/api\/public\/agents\/([^/]+)\/messages$/);if(p&&o==="POST"){let d=p[1];if(!nu(t,e,[`agent:${d}`]))return;await ru(t,e,a.config,d);return}if(r.startsWith("/api/")&&a.token){let d=t.headers.authorization||"",f=d.startsWith("Bearer ")?d.slice(7):"";if(f!==a.token){let x=new ae,v=f?x.verify(f):null;if(!v||!ye(v,"dashboard:write")){y(e,401,{error:"unauthorized"});return}}}if(o==="GET"&&r==="/api/mesh/feed"){await Jp(e,a.config,n.searchParams);return}if((o==="POST"||o==="PATCH"||o==="DELETE"||o==="PUT")&&r.startsWith("/api/")&&t.headers["x-requested-with"]!=="agentx-board"){y(e,400,{error:"missing X-Requested-With: agentx-board"});return}if(o==="POST"&&(r==="/api/node/restart"||r==="/api/node/restart/cancel")){let d=n.searchParams.get("node");if(!d){y(e,400,{error:"node query param required"});return}await Ia(t,e,a,d,r==="/api/node/restart"?"/daemon/restart":"/daemon/restart/cancel");return}if(o==="GET"&&r==="/events"){let f=new URL(t.url||"/","http://localhost").searchParams.toString();e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let x=[{name:a.config.node.name||"local",url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(E=>({name:E.name,url:E.url,token:E.token}))],v={flag:!1},k=[];t.on("close",()=>{v.flag=!0;for(let E of k)try{E.abort()}catch{}});let b=setInterval(()=>{if(!v.flag)try{e.write(`: ping
18409
18424
 
18410
- `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let E of x)(async()=>{let I={Accept:"text/event-stream"};E.token&&(I.Authorization=`Bearer ${E.token}`);let C=new AbortController;k.push(C);try{let T=await fetch(`${E.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:I,signal:C.signal});if(!T.ok||!T.body)return;let M=T.body.getReader(),P=new TextDecoder,j="";for(;!v.flag;){let{done:B,value:oe}=await M.read();if(B)break;j+=P.decode(oe,{stream:!0});let F;for(;(F=j.indexOf(`
18425
+ `)}catch{}},15e3);t.on("close",()=>clearInterval(b));for(let E of x)(async()=>{let I={Accept:"text/event-stream"};E.token&&(I.Authorization=`Bearer ${E.token}`);let C=new AbortController;k.push(C);try{let T=await fetch(`${E.url.replace(/\/+$/,"")}/events${f?`?${f}`:""}`,{headers:I,signal:C.signal});if(!T.ok||!T.body)return;let M=T.body.getReader(),P=new TextDecoder,j="";for(;!v.flag;){let{done:B,value:se}=await M.read();if(B)break;j+=P.decode(se,{stream:!0});let F;for(;(F=j.indexOf(`
18411
18426
 
18412
18427
  `))>=0;){let ee=j.slice(0,F);if(j=j.slice(F+2),v.flag)break;try{e.write(ee+`
18413
18428
 
18414
- `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:f,workflowId:x}),b=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,E=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(P=>({url:P.url,token:P.token}))],I=await Promise.all(E.map(async P=>{let j={};P.token&&(j.Authorization=`Bearer ${P.token}`);try{let B=new AbortController,oe=setTimeout(()=>B.abort(),5e3);try{let F=await fetch(`${P.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:j,signal:B.signal});if(!F.ok)return[];let ee=await F.json();return Array.isArray(ee.runs)?ee.runs:[]}finally{clearTimeout(oe)}}catch{return[]}})),C=new Map;for(let P of k)C.set(P.id,P);for(let P of I)for(let j of P)C.set(j.id,j);let T=Array.from(C.values()).sort((P,j)=>P.updatedAt<j.updatedAt?1:-1).slice(0,f),M=v?T.map(P=>qp(P)):T;y(e,200,{runs:M})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let d=decodeURIComponent(m[1]),f=a.workflowRuns.get(d);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let k={};v.token&&(k.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,v)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await xe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&yo(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,v)=>{if(a.token)return!0;let k=Ht(f);if(!k)return!0;let b=new ae().verify(k);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let E of v)if(!ye(b,E))return y(x,403,{error:`token missing scope: ${E}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,f]=S,x=decodeURIComponent(f),v=a.boards.find(C=>C.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await xe(t),E=v.columns.find(C=>C.id===b.to),I=v.columns.find(C=>C.id===b.from);if(!E){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await Fp(k,x,I,E),Sa({actor:Ta(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,f]=g,x=f?decodeURIComponent(f):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:E}=await zp(v,k,n.searchParams);y(e,200,{columns:b,totals:E});return}if(o==="GET"&&x){try{let b=typeof k.getItem=="function"?await k.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await xe(t);try{let E=typeof k.updateItem=="function"?await k.updateItem(x,b):null;if(!E){y(e,501,{error:"update unsupported"});return}Sa({actor:Ta(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,E)}catch(E){y(e,502,{error:E.message})}return}if(o==="POST"&&!x){let b=await xe(t);if(!b.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let E=await k.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Sa({actor:Ta(t),action:"create",boardId:d,itemId:E.id,payload:{title:b.title}}),y(e,201,E)}catch(E){y(e,502,{error:E.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function zp(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let f of t.columns)d[f.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(f=>[f.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let d of t.columns)w[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&w[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of m){let f=La(d,S);if(!f)continue;let x=w[f];x&&x.push({...d,stage:f})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(f=>f.assignee===i);for(let d of Object.keys(w))w[d].sort((f,x)=>{let v=(f.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(w).map(([d,f])=>[d,f.length]));return{columns:w,totals:g}}async function Fp(t,e,a,n){let r=Ra(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 qp(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 Up(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 cn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Sa(t){try{let e=Ke(process.cwd(),".agentx");qs(e)||jp(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
18415
- `;Pp(Ke(e,"board-audit.jsonl"),a)}catch{}}function Ta(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Wp=2e3;async function Gp(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,f=setTimeout(()=>d.abort(),Wp),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let k=v.ok?await v.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,p,u,m,h,w,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Ua.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)&&Zp(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 Mt=null;function Xp(t){if(Mt)return Mt;let e=Ke(process.cwd(),".agentx/wiki");return Mt=$n({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Mt}async function Rt(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 Kp(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||z(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function be(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=z(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:z(a,l)})}let s=await Rt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:z(a,i.url)});return[...o.values()]}var Jp=3e3,Vp=6e3,Yp=5*6e4,Aa=new Map,Lt=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Lt.get(a);if(n)return n;let r=(async()=>{let o=await be(t,AbortSignal.timeout(Jp)),s=await Promise.all(o.map(async i=>{let l=await Gp(i.url,i.token,AbortSignal.timeout(Vp),e);return e?l:Qp(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Lt.delete(a));return Lt.set(a,r),r}function Qp(t,e,a=Date.now()){if(e.reachable&&!e.error)return Aa.set(t,{node:e,at:a}),e;let n=Aa.get(t);return!n||a-n.at>Yp?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Vx(){Aa.clear(),Lt.clear()}function Zp(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 eu(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}
18429
+ `)}catch{v.flag=!0}}}}catch{}})();return}if(o==="GET"&&r==="/api/workflows/runs"){try{let d=new URL(t.url||"/","http://localhost"),f=Math.max(1,Math.min(500,Number(d.searchParams.get("limit")||50))),x=d.searchParams.get("workflowId")||void 0,v=d.searchParams.get("summary")==="1"||d.searchParams.get("summary")==="true",k=a.workflowRuns.list({limit:f,workflowId:x}),b=`?limit=${f}${x?`&workflowId=${encodeURIComponent(x)}`:""}${v?"&summary=1":""}`,E=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(P=>({url:P.url,token:P.token}))],I=await Promise.all(E.map(async P=>{let j={};P.token&&(j.Authorization=`Bearer ${P.token}`);try{let B=new AbortController,se=setTimeout(()=>B.abort(),5e3);try{let F=await fetch(`${P.url.replace(/\/+$/,"")}/api/workflows/runs${b}`,{headers:j,signal:B.signal});if(!F.ok)return[];let ee=await F.json();return Array.isArray(ee.runs)?ee.runs:[]}finally{clearTimeout(se)}}catch{return[]}})),C=new Map;for(let P of k)C.set(P.id,P);for(let P of I)for(let j of P)C.set(j.id,j);let T=Array.from(C.values()).sort((P,j)=>P.updatedAt<j.updatedAt?1:-1).slice(0,f),M=v?T.map(P=>Up(P)):T;y(e,200,{runs:M})}catch(d){y(e,502,{error:"runs fetch failed",message:d.message||String(d)})}return}let m=o==="GET"&&r.match(/^\/api\/workflows\/runs\/([^\/]+)$/);if(m){let d=decodeURIComponent(m[1]),f=a.workflowRuns.get(d);if(f){y(e,200,{run:f});return}let x=[{url:a.config.dashboard.daemonUrl,token:a.config.dashboard.token},...(a.config.dashboard.daemons||[]).map(v=>({url:v.url,token:v.token}))];for(let v of x)try{let k={};v.token&&(k.Authorization=`Bearer ${v.token}`);let b=await fetch(`${v.url.replace(/\/+$/,"")}/api/workflows/runs/${encodeURIComponent(d)}`,{headers:k});if(b.ok){y(e,200,await b.json());return}}catch{}y(e,404,{error:"run not found on any configured peer"});return}if(o==="GET"&&r==="/api/actions/builtin"){try{let d={};a.config.dashboard.token&&(d.Authorization=`Bearer ${a.config.dashboard.token}`);let f=a.config.dashboard.daemonUrl.replace(/\/+$/,""),x=await fetch(`${f}/api/actions/builtin`,{headers:d}),v=await x.json().catch(()=>({error:`HTTP ${x.status}`}));y(e,x.status,v)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}let h=o==="POST"&&r.match(/^\/workflows\/([^/]+)\/run$/);if(h){try{let d=await xe(t).catch(()=>({})),f={"Content-Type":"application/json"};a.config.dashboard.token&&(f.Authorization=`Bearer ${a.config.dashboard.token}`);let x=a.config.dashboard.daemonUrl.replace(/\/+$/,""),v=await fetch(`${x}/workflows/${encodeURIComponent(h[1])}/run`,{method:"POST",headers:f,body:JSON.stringify(d??{})}),k=await v.json().catch(()=>({error:`HTTP ${v.status}`}));y(e,v.status,k)}catch(d){y(e,502,{error:"daemon unreachable",message:d.message||String(d)})}return}if(r.startsWith("/api/workflows")&&wo(t,e,{store:a.workflowStore,runs:a.workflowRuns,layouts:a.workflowLayouts,requireScope:(f,x,v)=>{if(a.token)return!0;let k=Ht(f);if(!k)return!0;let b=new ae().verify(k);if(!b)return y(x,401,{error:"invalid or revoked token"}),!1;for(let E of v)if(!ye(b,E))return y(x,403,{error:`token missing scope: ${E}`,scopes:b.scopes}),!1;return!0}}))return;if(o==="GET"&&r==="/api/boards"){y(e,200,a.boards.map(d=>({id:d.id,name:d.name,source:d.source,primaryToolLabel:d.primaryToolLabel,labels:d.labels,columns:d.columns,timeRangeDays:d.timeRangeDays})));return}let w=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/members$/);if(w&&o==="GET"){let d=a.sources.get(w[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMembers=="function"?await d.listMembers():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let _=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/milestones$/);if(_&&o==="GET"){let d=a.sources.get(_[1]);if(!d){y(e,404,{error:"unknown board"});return}try{let f=typeof d.listMilestones=="function"?await d.listMilestones():[];y(e,200,f)}catch(f){y(e,502,{error:f.message})}return}let S=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items\/(.+?)\/move$/),g=r.match(/^\/api\/boards\/([a-z0-9_-]+)\/items(?:\/(.+))?$/);if(S&&o==="PATCH"){let[,d,f]=S,x=decodeURIComponent(f),v=a.boards.find(C=>C.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}let b=await xe(t),E=v.columns.find(C=>C.id===b.to),I=v.columns.find(C=>C.id===b.from);if(!E){y(e,400,{error:`unknown 'to' column: ${b.to}`});return}try{await qp(k,x,I,E),Ta({actor:Aa(t),action:"move",boardId:d,itemId:x,payload:{from:b.from,to:b.to}}),y(e,200,{ok:!0})}catch(C){y(e,502,{error:C.message||"transition failed"})}return}if(g){let[,d,f]=g,x=f?decodeURIComponent(f):void 0,v=a.boards.find(b=>b.id===d);if(!v){y(e,404,{error:`unknown board: ${d}`});return}let k=a.sources.get(d);if(!k){y(e,503,{error:`board "${d}" source unavailable`});return}if(o==="GET"&&!x){let{columns:b,totals:E}=await Fp(v,k,n.searchParams);y(e,200,{columns:b,totals:E});return}if(o==="GET"&&x){try{let b=typeof k.getItem=="function"?await k.getItem(x):null;if(!b){y(e,404,{error:"not found"});return}y(e,200,b)}catch(b){y(e,502,{error:b.message})}return}if(o==="PATCH"&&x){let b=await xe(t);try{let E=typeof k.updateItem=="function"?await k.updateItem(x,b):null;if(!E){y(e,501,{error:"update unsupported"});return}Ta({actor:Aa(t),action:"update",boardId:d,itemId:x,payload:b}),y(e,200,E)}catch(E){y(e,502,{error:E.message})}return}if(o==="POST"&&!x){let b=await xe(t);if(!b.title){y(e,400,{error:"title required"});return}if(!k.capabilities.create||!k.create){y(e,400,{error:`source ${k.type} does not support create`});return}try{let E=await k.create({title:b.title,description:b.description,labels:b.labels,assigneeUsernames:b.assigneeUsernames,milestoneTitle:b.milestoneTitle,projectHint:b.projectHint});Ta({actor:Aa(t),action:"create",boardId:d,itemId:E.id,payload:{title:b.title}}),y(e,201,E)}catch(E){y(e,502,{error:E.message})}return}}if(o==="GET"&&/^\/[a-z][a-z-]*\/?$/.test(r)){let d=r.replace(/^\/+|\/+$/g,""),x={health:"/admin/health",ledger:"/admin/ledger",cost:"/admin/cost",projects:"/admin/projects",graph:"/admin/graph",wiki:"/admin/wiki/",observability:"/admin/health"}[d];if(x){e.writeHead(302,{Location:x}),e.end();return}}y(e,404,{error:"not found",path:r})}async function Fp(t,e,a){if(!e.capabilities.listAll||!e.listAll){let d={};for(let f of t.columns)d[f.id]=[];return{columns:d,totals:Object.fromEntries(t.columns.map(f=>[f.id,0]))}}let n=[];t.primaryToolLabel&&n.push(t.primaryToolLabel);let r=a.get("label")||void 0;r&&n.push(r);let o=a.get("q")||void 0,s=a.get("milestone")||void 0,i=a.get("assignee")||void 0,l=parseInt(a.get("days")||String(t.timeRangeDays),10),c=parseInt(a.get("closedDays")||String(t.closedWindowDays??30),10),p=t.columns.some(d=>d.kind!=="closed"),u=t.columns.some(d=>d.kind==="closed"),m=p?await e.listAll({sinceDays:l,labels:n.length?n:void 0,search:o,milestone:s,state:"opened"}):[],h=u?await e.listAll({sinceDays:c,labels:n.length?n:void 0,search:o,milestone:s,state:"closed"}):[],w={};for(let d of t.columns)w[d.id]=[];let _=t.columns.find(d=>d.kind==="closed");for(let d of h)_&&w[_.id].push({...d,stage:_.id});let S=t.columns.filter(d=>d.kind!=="closed");for(let d of m){let f=Ra(d,S);if(!f)continue;let x=w[f];x&&x.push({...d,stage:f})}if(i)for(let d of Object.keys(w))w[d]=w[d].filter(f=>f.assignee===i);for(let d of Object.keys(w))w[d].sort((f,x)=>{let v=(f.priority??99)-(x.priority??99);return v!==0?v:(x.updatedAt||"").localeCompare(f.updatedAt||"")});let g=Object.fromEntries(Object.entries(w).map(([d,f])=>[d,f.length]));return{columns:w,totals:g}}async function qp(t,e,a,n){let r=$a(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 Up(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 Wp(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 pn(a.host,a.token,t.source.projects,n,(...r)=>console.log("[board]",...r))}throw new Error(`unsupported board source: ${t.source.type}`)}function Ta(t){try{let e=Ke(process.cwd(),".agentx");Us(e)||Op(e,{recursive:!0});let a=JSON.stringify({ts:new Date().toISOString(),...t})+`
18430
+ `;jp(Ke(e,"board-audit.jsonl"),a)}catch{}}function Aa(t){let e=t.headers["x-forwarded-for"];return(Array.isArray(e)?e[0]:e?.split(",")[0])||t.socket.remoteAddress||"unknown"}var Gp=2e3;async function Xp(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,f=setTimeout(()=>d.abort(),Gp),x=()=>d.abort();return a?.addEventListener("abort",x,{once:!0}),fetch(t+g,{headers:r,signal:d.signal}).then(async v=>{let k=v.ok?await v.json().catch(()=>{}):void 0;return{ok:k!==void 0,json:async()=>k}}).catch(()=>null).finally(()=>{clearTimeout(f),a?.removeEventListener("abort",x)})},[l,c,p,u,m,h,w,_]=await Promise.all([i("/health"),fetch(t+"/agents",{headers:r,signal:a}).catch(()=>null),i("/mesh"),i("/crons"),i("/crons/runs"+s),i("/talk"),i("/routines"),i("/attach/sessions")]);if(!c||!c.ok)return o.error=c?`HTTP ${c.status}`:"unreachable",o;let S=await c.json();if(o.agents=S.map(g=>({id:g.id,name:g.name,tier:g.tier,model:g.model,...typeof g.color=="string"&&/^#[0-9a-fA-F]{6}$/.test(g.color)?{color:g.color}:{},skillCount:Number.isFinite(g.skillCount)?g.skillCount:void 0,active:g.active||0,total:g.total||0,errors:g.errors||0,lastActive:g.lastActive,lastSummary:g.lastSummary,hourlyTasks:Array.isArray(g.hourlyTasks)?g.hourlyTasks:void 0,runningTasks:Array.isArray(g.runningTasks)?g.runningTasks:[]})),l&&l.ok){let g=await l.json().catch(()=>({}));o.uptimeSec=g.uptime,typeof g.inflight?.total=="number"&&(o.inflight=g.inflight.total),g.restart&&typeof g.restart.state=="string"&&(o.restart=g.restart),o.name=g.node?.name||g.node?.id||t,o.id=g.node?.id||t,g.usage&&(o.usage=g.usage)}if(u&&u.ok){let g=await u.json().then(d=>Array.isArray(d)?d:[],()=>[]);o.crons=g.map(d=>({id:d.id,enabled:d.enabled===!0,schedule:String(d.schedule||""),timezone:d.timezone,agent:String(d.agent||""),kind:typeof d.command=="string"&&d.command.trim()?"command":"agent",model:d.model,nextRun:d.nextRun,retryPending:d.retryPending===!0,consecutiveErrors:Number(d.consecutiveErrors)||0}))}if(m&&m.ok){let g=await m.json().catch(()=>({}));o.cronRuns=Array.isArray(g.runs)?g.runs:[]}if(w&&w.ok){let g=await w.json().catch(()=>null);g&&Array.isArray(g.routines)&&(o.routines=g.routines.slice(0,Wa.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)&&eu(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 Mt=null;function Kp(t){if(Mt)return Mt;let e=Ke(process.cwd(),".agentx/wiki");return Mt=jn({wikiDir:e,pathPrefix:"/admin/wiki",mode:"graph"}),Mt}async function Rt(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 Jp(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||z(e.dashboard,r);try{let s=await fetch(`${r}/events/recent?skip=task:step&limit=${n}`,{headers:o?{Authorization:`Bearer ${o}`}:{},signal:AbortSignal.timeout(5e3)});if(!s.ok){y(t,502,{error:`daemon answered ${s.status}`});return}let i=await s.json();y(t,200,{node:e.node.name||e.node.id,events:i.events??[]})}catch(s){y(t,502,{error:s.message||"daemon unreachable"})}}async function be(t,e){let a=t.dashboard,n=a.daemonUrl.replace(/\/+$/,""),r=z(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:z(a,l)})}let s=await Rt(n,r,e);for(let i of s)o.has(i.url)||o.set(i.url,{...i,token:z(a,i.url)});return[...o.values()]}var Vp=3e3,Yp=6e3,Qp=5*6e4,Ca=new Map,Lt=new Map;function Ne(t,e){let a=e?`${e.date}|${e.timezone}`:"live",n=Lt.get(a);if(n)return n;let r=(async()=>{let o=await be(t,AbortSignal.timeout(Vp)),s=await Promise.all(o.map(async i=>{let l=await Xp(i.url,i.token,AbortSignal.timeout(Yp),e);return e?l:Zp(i.url,l)}));return{ts:new Date().toISOString(),nodes:s}})().finally(()=>Lt.delete(a));return Lt.set(a,r),r}function Zp(t,e,a=Date.now()){if(e.reachable&&!e.error)return Ca.set(t,{node:e,at:a}),e;let n=Ca.get(t);return!n||a-n.at>Qp?e:{...n.node,stale:!0,staleSince:new Date(n.at).toISOString(),error:e.error}}function Qx(){Ca.clear(),Lt.clear()}function eu(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 tu(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}
18416
18431
  data: ${JSON.stringify(c)}
18417
18432
 
18418
- `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ne(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 tu(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await Rt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of w)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:_}=await m.read();if(_)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function au(t,e,a){let n=Ht(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ae().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ye(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function nu(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await xe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function ru(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 Rt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(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}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function ou(t,e,a,n,r,o){await Ca(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Ca(t,e,a,n,r){let o={};try{o=await xe(t)??{}}catch{}let s=await Us(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Us(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 Rt(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=z(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 Ws(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=Ka(e.keysFile);return{store:()=>{let r=Ie();return r?new gn(r):null},publicKey:()=>Ja(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Gs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ne(t,n),async nodePost(n,r,o){let s=await Us(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=tt({root:process.cwd()}).items.map(zs)}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=Je(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(zs)}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=Re(),p=await at({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=Je(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function Xs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=z(t.dashboard,e),n=Gs(t);return{store:()=>{let r=Ie();return r?new Xe(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ne(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=>z(t.dashboard,r.replace(/\/+$/,"")),...su(t,e,a)}}function su(t,e,a){let n=Ws(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}
18419
- ${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 iu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>z(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Xs(t);return new It({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 Ne(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:No(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function lu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Ie();return a?new Xe(a):null},daemon:{url:e,token:z(t.dashboard,e)}}}function cu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:z(t.dashboard,e)},nodeName:t.node.name}}function zs(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 du=`
18433
+ `)},o=!1,s=async()=>{if(!o){o=!0;try{let l=await Ne(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 au(t,e,a,n,r,o){let s=n.replace(/\/+$/,""),i=new Set;i.add(a.config.dashboard.daemonUrl.replace(/\/+$/,""));for(let w of a.config.dashboard.daemons)i.add(w.url.replace(/\/+$/,""));try{let w=await Rt(a.config.dashboard.daemonUrl.replace(/\/+$/,""),a.config.dashboard.token);for(let _ of w)i.add(_.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(e,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(a.config.dashboard,s),c={Accept:"text/event-stream"};l&&(c.Authorization=`Bearer ${l}`);let p=new AbortController,u;try{u=await fetch(`${s}/agents/${encodeURIComponent(r)}/tasks/${encodeURIComponent(o)}/stream`,{headers:c,signal:p.signal})}catch(w){y(e,502,{error:w.message||"upstream connect failed"});return}if(!u.ok||!u.body){y(e,u.status||502,{error:`upstream HTTP ${u.status}`});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let m=u.body.getReader();(async()=>{try{for(;;){let{value:w,done:_}=await m.read();if(_)break;w&&e.write(w)}}catch{}finally{try{e.end()}catch{}}})(),t.on("close",()=>{p.abort();try{e.end()}catch{}})}function nu(t,e,a){let n=Ht(t);if(!n)return y(e,401,{error:"missing token",hint:"pass Authorization: Bearer <token> (agentx token create)"}),null;let r=new ae().verify(n);if(!r)return y(e,401,{error:"invalid or revoked token"}),null;for(let o of a)if(!ye(r,o))return y(e,403,{error:`token missing scope: ${o}`,scopes:r.scopes}),null;return r}async function ru(t,e,a,n){let r=a.agents?.[n];if(!r){y(e,404,{error:"unknown agent"});return}if(r.access!=="public"){y(e,403,{error:"agent is private",hint:`set agents.${n}.access = "public" to expose it`});return}let o;try{o=await xe(t)}catch{y(e,400,{error:"invalid JSON body"});return}let s=o?.message;if(!s||typeof s!="string"){y(e,400,{error:"required: { message: string, context?: {...} }"});return}let i=a.dashboard.daemonUrl.replace(/\/+$/,""),l={"Content-Type":"application/json"};a.dashboard.token&&(l.Authorization=`Bearer ${a.dashboard.token}`);try{let c=await fetch(`${i}/task`,{method:"POST",headers:l,body:JSON.stringify({agent:n,message:s,context:{channel:"public-api",sender:o.context?.sender||"api",...o.context||{}}})}),p=await c.text();e.writeHead(c.status,{"Content-Type":c.headers.get("content-type")||"application/json; charset=utf-8"}),e.end(p)}catch(c){y(e,502,{error:c.message||"upstream call failed"})}}async function ou(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 Rt(e.config.dashboard.daemonUrl.replace(/\/+$/,""),e.config.dashboard.token);for(let m of u)i.add(m.url.replace(/\/+$/,""))}catch{}if(!i.has(s)){y(t,403,{error:"node not in dashboard allowlist",target:s});return}let l=z(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}),m=await u.text();t.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json; charset=utf-8"}),t.end(m)}catch(u){y(t,502,{error:u.message||"upstream fetch failed"})}}async function su(t,e,a,n,r,o){await Ia(t,e,a,n,`/api/tasks/${encodeURIComponent(r)}/${o}`)}async function Ia(t,e,a,n,r){let o={};try{o=await xe(t)??{}}catch{}let s=await Ws(a.config,n,r,o);e.writeHead(s.status,{"Content-Type":s.contentType}),e.end(s.text)}async function Ws(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 Rt(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=z(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 Gs(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=Ja(e.keysFile);return{store:()=>{let r=Me();return r?new vn(r):null},publicKey:()=>Va(n)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts,reason:"The database on this computer is unavailable, so notifications can't be saved."}}function Xs(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=n=>{try{return JSON.parse(n)}catch{return{error:n.slice(0,200)}}};return{snapshot:n=>Ne(t,n),async nodePost(n,r,o){let s=await Ws(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=tt({root:process.cwd()}).items.map(Fs)}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=Je(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(Fs)}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=we(),p=await at({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=Je(i,t);if(!l)return{status:403,body:{error:"node not in dashboard allowlist",target:i}};try{let c=await fetch(`${l.url}/api/admin/approvals/decide`,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"agentx-board","X-Agentx-Peer":"primary",...l.token?{Authorization:`Bearer ${l.token}`}:{}},body:JSON.stringify({key:r,action:o}),signal:AbortSignal.timeout(1e4)});return{status:c.status,body:a(await c.text())}}catch(c){return{status:502,body:{error:c.message||"peer dashboard unreachable"}}}}}}function Ks(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=z(t.dashboard,e),n=Xs(t);return{store:()=>{let r=Me();return r?new Xe(r):null},daemon:{url:e,token:a,name:t.node?.name},snapshot:()=>Ne(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=>z(t.dashboard,r.replace(/\/+$/,"")),...iu(t,e,a)}}function iu(t,e,a){let n=Gs(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}
18434
+ ${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 lu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,""),a=o=>z(t.dashboard,o.replace(/\/+$/,"")),n=o=>{let s=a(o);return s?{Authorization:`Bearer ${s}`}:{}},r=Ks(t);return new It({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 Ne(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:Do(),finishAlerts:r.finishAlerts,notifyFinish:r.notifyFinish,log:o=>console.log(o),warn:o=>console.warn(o)})}function cu(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{store:()=>{let a=Me();return a?new Xe(a):null},daemon:{url:e,token:z(t.dashboard,e)}}}function du(t){let e=t.dashboard.daemonUrl.replace(/\/+$/,"");return{daemon:{url:e,token:z(t.dashboard,e)},nodeName:t.node.name}}function Fs(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 pu=`
18420
18435
  You are helping draft a new GitLab issue. Follow these conventions strictly.
18421
18436
 
18422
18437
  Title pattern:
@@ -18448,10 +18463,10 @@ Return ONLY a single JSON object on one line \u2014 no prose, no code fences, no
18448
18463
  Shape:
18449
18464
  { "title": string, "description": string, "labels": string[], "assigneeUsername": string | null, "kind": string }
18450
18465
  If you don't have enough information to pick a label confidently, omit it rather than guessing.
18451
- `;async function pu(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):
18466
+ `;async function uu(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):
18452
18467
  - ${r.knownLabels.slice(0,60).join(`
18453
18468
  - `)}`:"",r.members?.length?`Possible assignees (GitLab usernames): ${r.members.slice(0,20).join(", ")}`:"","","Produce the JSON draft now."].filter(Boolean).join(`
18454
- `),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:du}})});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=uu(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function uu(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 mu(t){let e=Dp(Np(import.meta.url));return Ke(e,t)}async function fu(t){return Op(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function xe(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 Ks(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:Ks(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 hu(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await vt(await Js(r,a.config)))}async function Js(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=aa(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=Je(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 Br(n)}async function gu(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(w=>qs(w));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
18469
+ `),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:pu}})});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=mu(p);if(!u||typeof u.title!="string")throw new Error("agent did not return a valid JSON draft. Raw: "+p.slice(0,400));let m=Array.isArray(u.labels)?u.labels.filter(h=>typeof h=="string"):[];return r.primaryLabel&&!m.includes(r.primaryLabel)&&m.unshift(r.primaryLabel),r.columnLabel&&!m.includes(r.columnLabel)&&m.unshift(r.columnLabel),{title:u.title.trim(),description:(u.description||"").toString(),labels:m,assigneeUsername:typeof u.assigneeUsername=="string"?u.assigneeUsername:void 0,kind:typeof u.kind=="string"?u.kind:void 0,raw:p}}function mu(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 fu(t){let e=Hp(Dp(import.meta.url));return Ke(e,t)}async function hu(t){return Np(t)}function y(t,e,a){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a))}async function xe(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 Js(t){return t.dashboardUrl?t.dashboardUrl.replace(/\/+$/,""):t.url.replace(/\/+$/,"").replace(/:(?:1[89][89]00|18810)$/,":4202")}function H(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:Js(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 gu(t,e,a){let n=new URL(t.url||"/","http://_"),r=parseInt(n.searchParams.get("hours")||"6",10)||6;y(e,200,await vt(await Vs(r,a.config)))}async function Vs(t,e){let a=e.node?.id||e.node?.name||"local",n=[],r=na(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=Je(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 zr(n)}async function xu(t,e){let{spawn:a,execSync:n}=await import("child_process"),r,o;try{n("which journalctl",{stdio:"pipe"}),r="journalctl",o=["-u","agentx","--no-pager","-n","200","-f","-o","cat"]}catch{let u=process.env.HOME||"",m=[u&&`${u}/.agentx/logs/daemon-stdout.log`,"/tmp/agentx-daemon.log"].filter(Boolean),h=m.find(w=>Us(w));if(!h){e.writeHead(503,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no log source \u2014 install journalctl, run the daemon under launchd, or run it foreground writing to /tmp/agentx-daemon.log",searched:m}));return}r="tail",o=["-F","-n","200",h]}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),e.write(`: source=${r}
18455
18470
 
18456
18471
  `);let s=a(r,o,{stdio:["ignore","pipe","pipe"]}),i="",l=u=>{i+=u.toString("utf8");let m;for(;(m=i.indexOf(`
18457
18472
  `))>=0;){let h=i.slice(0,m).replace(/\r$/,"");i=i.slice(m+1);try{e.write(`event: line
@@ -18459,5 +18474,5 @@ data: ${h.replace(/\n/g," ")}
18459
18474
 
18460
18475
  `)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
18461
18476
 
18462
- `)}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 Fs(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",w=>h.push(w)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let 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}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Je(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Ks(n),token:n.dashboardToken||n.token}:null}export{Zp as applyAttachSessions,Gp as fetchDaemonAgents,Bp as handleBoardRequest,Vx as resetLiveCaches,be as resolveNodeTargets,Jx as startBoardDashboard,Qp as withLastGood};
18463
- //# sourceMappingURL=board-dashboard-PCRI2TGB.js.map
18477
+ `)}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 qs(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,m)=>{let h=[];t.on("data",w=>h.push(w)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",m)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let 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}),m=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(m)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Je(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:Js(n),token:n.dashboardToken||n.token}:null}export{eu as applyAttachSessions,Xp as fetchDaemonAgents,zp as handleBoardRequest,Qx as resetLiveCaches,be as resolveNodeTargets,Yx as startBoardDashboard,Zp as withLastGood};
18478
+ //# sourceMappingURL=board-dashboard-OJSOA4OL.js.map